@@ -34,6 +34,21 @@ func HexToBytes(addr string) []byte {
34
34
return b
35
35
}
36
36
}
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
+ }
37
52
38
53
func OrderWiresToOrderAction (orders []OrderWire , grouping Grouping ) PlaceOrderAction {
39
54
return PlaceOrderAction {
@@ -43,19 +58,33 @@ func OrderWiresToOrderAction(orders []OrderWire, grouping Grouping) PlaceOrderAc
43
58
}
44
59
}
45
60
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 {
47
68
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
52
84
maxDecimals = SPOT_MAX_DECIMALS
53
- } else {
54
- assetId = info .AssetId
55
- maxDecimals = PERP_MAX_DECIMALS
56
85
}
57
86
return OrderWire {
58
- Asset : assetId ,
87
+ Asset : assetID ,
59
88
IsBuy : req .IsBuy ,
60
89
LimitPx : PriceToWire (req .LimitPx , maxDecimals , info .SzDecimals ),
61
90
SizePx : SizeToWire (req .Sz , info .SzDecimals ),
@@ -65,29 +94,7 @@ func OrderRequestToWire(req OrderRequest, meta map[string]AssetInfo, isSpot bool
65
94
}
66
95
}
67
96
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.
91
98
92
99
func OrderTypeToWire (orderType OrderType ) OrderTypeWire {
93
100
if orderType .Limit != nil {
@@ -110,8 +117,26 @@ func OrderTypeToWire(orderType OrderType) OrderTypeWire {
110
117
return OrderTypeWire {}
111
118
}
112
119
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
+ */
115
140
func FloatToWire (x float64 , maxDecimals int , szDecimals int ) string {
116
141
bigf := big .NewFloat (x )
117
142
var maxDecSz uint
@@ -228,3 +253,38 @@ func StructToMap(strct any) (res map[string]interface{}, err error) {
228
253
json .Unmarshal (a , & res )
229
254
return res , nil
230
255
}
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