@@ -34,6 +34,21 @@ func HexToBytes(addr string) []byte {
3434 return b
3535 }
3636}
37+ func HexToInt (hexString string ) (* big.Int , error ) {
38+ value := new (big.Int )
39+ if len (hexString ) > 1 && hexString [:2 ] == "0x" {
40+ hexString = hexString [2 :]
41+ }
42+ _ , success := value .SetString (hexString , 16 )
43+ if ! success {
44+ return nil , fmt .Errorf ("invalid hexadecimal string: %s" , hexString )
45+ }
46+ return value , nil
47+ }
48+
49+ func IntToHex (value * big.Int ) string {
50+ return "0x" + value .Text (16 )
51+ }
3752
3853func OrderWiresToOrderAction (orders []OrderWire , grouping Grouping ) PlaceOrderAction {
3954 return PlaceOrderAction {
@@ -43,19 +58,33 @@ func OrderWiresToOrderAction(orders []OrderWire, grouping Grouping) PlaceOrderAc
4358 }
4459}
4560
46- func OrderRequestToWire (req OrderRequest , meta map [string ]AssetInfo , isSpot bool ) OrderWire {
61+ func (req * OrderRequest ) isSpot () bool {
62+ return strings .ContainsAny (req .Coin , "@-" )
63+ }
64+
65+ // ToWire (OrderRequest) converts an OrderRequest to an OrderWire using the provided metadata.
66+ // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/asset-ids
67+ func (req * OrderRequest ) ToWireMeta (meta map [string ]AssetInfo ) OrderWire {
4768 info := meta [req .Coin ]
48- var assetId , maxDecimals int
49- if isSpot {
50- // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/asset-ids
51- assetId = info .AssetId + 10000
69+ return req .ToWire (info )
70+ }
71+
72+ func (req * OrderRequest ) ToModifyWire (info AssetInfo ) ModifyOrderWire {
73+ return ModifyOrderWire {
74+ OrderID : * req .OrderID ,
75+ Order : req .ToWire (info ),
76+ }
77+
78+ }
79+ func (req * OrderRequest ) ToWire (info AssetInfo ) OrderWire {
80+ var assetID = info .AssetID
81+ var maxDecimals = PERP_MAX_DECIMALS
82+ if req .isSpot () {
83+ assetID = info .AssetID + 10000 // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/asset-ids
5284 maxDecimals = SPOT_MAX_DECIMALS
53- } else {
54- assetId = info .AssetId
55- maxDecimals = PERP_MAX_DECIMALS
5685 }
5786 return OrderWire {
58- Asset : assetId ,
87+ Asset : assetID ,
5988 IsBuy : req .IsBuy ,
6089 LimitPx : PriceToWire (req .LimitPx , maxDecimals , info .SzDecimals ),
6190 SizePx : SizeToWire (req .Sz , info .SzDecimals ),
@@ -65,29 +94,7 @@ func OrderRequestToWire(req OrderRequest, meta map[string]AssetInfo, isSpot bool
6594 }
6695}
6796
68- func ModifyOrderRequestToWire (req ModifyOrderRequest , meta map [string ]AssetInfo , isSpot bool ) ModifyOrderWire {
69- info := meta [req .Coin ]
70- var assetId , maxDecimals int
71- if isSpot {
72- // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/asset-ids
73- assetId = info .AssetId + 10000
74- maxDecimals = SPOT_MAX_DECIMALS
75- } else {
76- assetId = info .AssetId
77- maxDecimals = PERP_MAX_DECIMALS
78- }
79- return ModifyOrderWire {
80- OrderId : req .OrderId ,
81- Order : OrderWire {
82- Asset : assetId ,
83- IsBuy : req .IsBuy ,
84- LimitPx : PriceToWire (req .LimitPx , maxDecimals , info .SzDecimals ),
85- SizePx : SizeToWire (req .Sz , info .SzDecimals ),
86- ReduceOnly : req .ReduceOnly ,
87- OrderType : OrderTypeToWire (req .OrderType ),
88- },
89- }
90- }
97+ // ToWire (ModifyOrderRequest) converts a ModifyOrderRequest to a ModifyOrderWire using the provided metadata.
9198
9299func OrderTypeToWire (orderType OrderType ) OrderTypeWire {
93100 if orderType .Limit != nil {
@@ -110,8 +117,26 @@ func OrderTypeToWire(orderType OrderType) OrderTypeWire {
110117 return OrderTypeWire {}
111118}
112119
113- // Format the float with custom decimal places, default is 6 (perp), 8 (spot).
114- // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size
120+ /**
121+ * FloatToWire converts a float64 to a string representation following Hyperliquid's decimal rules.
122+ * FloatToWire converts a float64 to a string representation following Hyperliquid's decimal rules.
123+ *
124+ * The conversion adheres to market-specific decimal place constraints:
125+ * - Perpetual markets: Maximum 6 decimal places
126+ * - Spot markets: Maximum 8 decimal places
127+ *
128+ * The function dynamically adjusts decimal precision based on:
129+ * 1. Integer part magnitude
130+ * 2. Maximum allowed decimals (maxDecimals)
131+ * 3. Size decimal precision (szDecimals)
132+ *
133+ * Output formatting:
134+ * - Removes trailing zeros
135+ * - Trims unnecessary decimal points
136+ * - Maintains tick size precision requirements
137+ *
138+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size
139+ */
115140func FloatToWire (x float64 , maxDecimals int , szDecimals int ) string {
116141 bigf := big .NewFloat (x )
117142 var maxDecSz uint
@@ -228,3 +253,38 @@ func StructToMap(strct any) (res map[string]interface{}, err error) {
228253 json .Unmarshal (a , & res )
229254 return res , nil
230255}
256+
257+ // RoundOrderSize rounds the order size to the nearest tick size
258+ func RoundOrderSize (x float64 , szDecimals int ) string {
259+ newX := math .Round (x * math .Pow10 (szDecimals )) / math .Pow10 (szDecimals )
260+ // TODO: add rounding
261+ return big .NewFloat (newX ).Text ('f' , szDecimals )
262+ }
263+
264+ // RoundOrderPrice rounds the order price to the nearest tick size
265+ func RoundOrderPrice (x float64 , szDecimals int , maxDecimals int ) string {
266+ maxSignFigures := 5
267+ allowedDecimals := maxDecimals - szDecimals
268+ numberOfDigitsInIntegerPart := len (strconv .Itoa (int (x )))
269+ if numberOfDigitsInIntegerPart >= maxSignFigures {
270+ return RoundOrderSize (x , 0 )
271+ }
272+ allowedSignFigures := maxSignFigures - numberOfDigitsInIntegerPart
273+ if x >= 1 {
274+ return RoundOrderSize (x , min (allowedSignFigures , allowedDecimals ))
275+ }
276+
277+ text := RoundOrderSize (x , allowedDecimals )
278+ startSignFigures := false
279+ for i := 2 ; i < len (text ); i ++ {
280+ if text [i ] == '0' && ! startSignFigures {
281+ continue
282+ }
283+ startSignFigures = true
284+ allowedSignFigures --
285+ if allowedSignFigures == 0 {
286+ return text [:i + 1 ]
287+ }
288+ }
289+ return text
290+ }
0 commit comments