@@ -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,35 @@ 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
+ // ToModifyWire converts an OrderRequest to a ModifyOrderWire using the provided AssetInfo.
73
+ func (req * OrderRequest ) ToModifyWire (info AssetInfo ) ModifyOrderWire {
74
+ return ModifyOrderWire {
75
+ OrderID : * req .OrderID ,
76
+ Order : req .ToWire (info ),
77
+ }
78
+ }
79
+
80
+ // ToWire converts an OrderRequest to an OrderWire using the provided AssetInfo.
81
+ func (req * OrderRequest ) ToWire (info AssetInfo ) OrderWire {
82
+ var assetID = info .AssetID
83
+ var maxDecimals = PERP_MAX_DECIMALS
84
+ if req .isSpot () {
85
+ assetID = info .AssetID + 10000 // https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/asset-ids
52
86
maxDecimals = SPOT_MAX_DECIMALS
53
- } else {
54
- assetId = info .AssetId
55
- maxDecimals = PERP_MAX_DECIMALS
56
87
}
57
88
return OrderWire {
58
- Asset : assetId ,
89
+ Asset : assetID ,
59
90
IsBuy : req .IsBuy ,
60
91
LimitPx : PriceToWire (req .LimitPx , maxDecimals , info .SzDecimals ),
61
92
SizePx : SizeToWire (req .Sz , info .SzDecimals ),
@@ -65,30 +96,7 @@ func OrderRequestToWire(req OrderRequest, meta map[string]AssetInfo, isSpot bool
65
96
}
66
97
}
67
98
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
- }
91
-
99
+ // OrderTypeToWire converts an OrderType to an OrderTypeWire.
92
100
func OrderTypeToWire (orderType OrderType ) OrderTypeWire {
93
101
if orderType .Limit != nil {
94
102
return OrderTypeWire {
@@ -110,8 +118,26 @@ func OrderTypeToWire(orderType OrderType) OrderTypeWire {
110
118
return OrderTypeWire {}
111
119
}
112
120
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
121
+ /**
122
+ * FloatToWire converts a float64 to a string representation following Hyperliquid's decimal rules.
123
+ * FloatToWire converts a float64 to a string representation following Hyperliquid's decimal rules.
124
+ *
125
+ * The conversion adheres to market-specific decimal place constraints:
126
+ * - Perpetual markets: Maximum 6 decimal places
127
+ * - Spot markets: Maximum 8 decimal places
128
+ *
129
+ * The function dynamically adjusts decimal precision based on:
130
+ * 1. Integer part magnitude
131
+ * 2. Maximum allowed decimals (maxDecimals)
132
+ * 3. Size decimal precision (szDecimals)
133
+ *
134
+ * Output formatting:
135
+ * - Removes trailing zeros
136
+ * - Trims unnecessary decimal points
137
+ * - Maintains tick size precision requirements
138
+ *
139
+ * @see https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size
140
+ */
115
141
func FloatToWire (x float64 , maxDecimals int , szDecimals int ) string {
116
142
bigf := big .NewFloat (x )
117
143
var maxDecSz uint
@@ -228,3 +254,38 @@ func StructToMap(strct any) (res map[string]interface{}, err error) {
228
254
json .Unmarshal (a , & res )
229
255
return res , nil
230
256
}
257
+
258
+ // RoundOrderSize rounds the order size to the nearest tick size
259
+ func RoundOrderSize (x float64 , szDecimals int ) string {
260
+ newX := math .Round (x * math .Pow10 (szDecimals )) / math .Pow10 (szDecimals )
261
+ // TODO: add rounding
262
+ return big .NewFloat (newX ).Text ('f' , szDecimals )
263
+ }
264
+
265
+ // RoundOrderPrice rounds the order price to the nearest tick size
266
+ func RoundOrderPrice (x float64 , szDecimals int , maxDecimals int ) string {
267
+ maxSignFigures := 5
268
+ allowedDecimals := maxDecimals - szDecimals
269
+ numberOfDigitsInIntegerPart := len (strconv .Itoa (int (x )))
270
+ if numberOfDigitsInIntegerPart >= maxSignFigures {
271
+ return RoundOrderSize (x , 0 )
272
+ }
273
+ allowedSignFigures := maxSignFigures - numberOfDigitsInIntegerPart
274
+ if x >= 1 {
275
+ return RoundOrderSize (x , min (allowedSignFigures , allowedDecimals ))
276
+ }
277
+
278
+ text := RoundOrderSize (x , allowedDecimals )
279
+ startSignFigures := false
280
+ for i := 2 ; i < len (text ); i ++ {
281
+ if text [i ] == '0' && ! startSignFigures {
282
+ continue
283
+ }
284
+ startSignFigures = true
285
+ allowedSignFigures --
286
+ if allowedSignFigures == 0 {
287
+ return text [:i + 1 ]
288
+ }
289
+ }
290
+ return text
291
+ }
0 commit comments