@@ -2,8 +2,8 @@ use anyhow::{bail, Context, Result};
22use colored:: Colorize ;
33use serde_json:: json;
44
5- use crate :: commands:: quote:: commodity_to_spot_token ;
6- use crate :: { binance, config, signing} ;
5+ use crate :: commands:: quote:: resolve_hip3_asset ;
6+ use crate :: { binance, config, hip3 , signing} ;
77
88/// Resolve which exchange to use
99fn resolve_exchange ( exchange : & str ) -> Result < String > {
@@ -69,9 +69,9 @@ pub async fn buy(
6969 let amount_f: f64 = amount_usdc. parse ( ) . context ( "Invalid amount" ) ?;
7070 let size = amount_f / price_f;
7171
72- // Check if this is a commodity → route to spot order
73- if let Some ( spot_token ) = commodity_to_spot_token ( & symbol) {
74- return commodity_spot_buy ( spot_token , & symbol, price_f, size, & cfg, json_output) . await ;
72+ // Check if this is a HIP-3 asset (commodities, stocks)
73+ if let Some ( ( dex , asset_name ) ) = resolve_hip3_asset ( & symbol) {
74+ return hip3_perp_buy ( & dex , & asset_name , & symbol, price_f, size, amount_usdc , & cfg, json_output) . await ;
7575 }
7676
7777 if !json_output {
@@ -156,9 +156,9 @@ pub async fn sell(
156156 let size: f64 = amount. parse ( ) . context ( "Invalid amount" ) ?;
157157 let price_f: f64 = price. parse ( ) . context ( "Invalid price" ) ?;
158158
159- // Check if this is a commodity → route to spot order
160- if let Some ( spot_token ) = commodity_to_spot_token ( & symbol) {
161- return commodity_spot_sell ( spot_token , & symbol, price_f, size, & cfg, json_output) . await ;
159+ // Check if this is a HIP-3 asset (commodities, stocks)
160+ if let Some ( ( dex , asset_name ) ) = resolve_hip3_asset ( & symbol) {
161+ return hip3_perp_sell ( & dex , & asset_name , & symbol, price_f, size, & cfg, json_output) . await ;
162162 }
163163
164164 if !json_output {
@@ -203,71 +203,74 @@ pub async fn sell(
203203 Ok ( ( ) )
204204}
205205
206- // ── Commodity spot order helpers ─────────────────────────────────────
206+ // ── HIP-3 perp order helpers ──── ─────────────────────────────────────
207207
208- /// Route a commodity "perp buy" to a spot buy on HL
209- async fn commodity_spot_buy (
210- spot_token : & str ,
208+ /// Place a HIP-3 perp buy order (e.g. cash:SILVER)
209+ #[ allow( clippy:: too_many_arguments) ]
210+ async fn hip3_perp_buy (
211+ dex : & str ,
212+ asset_name : & str ,
211213 original_symbol : & str ,
212214 price : f64 ,
213215 size : f64 ,
216+ amount_usdc : & str ,
214217 cfg : & config:: HlConfig ,
215218 json_output : bool ,
216219) -> Result < ( ) > {
217220 if !json_output {
218221 println ! ( ) ;
219222 println ! (
220- " 📝 {} trades as {}/USDC spot on Hyperliquid " ,
221- original_symbol ,
222- spot_token
223+ " 📝 Placing HIP-3 perp limit BUY ({} on {} dex) " ,
224+ asset_name . cyan ( ) ,
225+ dex
223226 ) ;
224- println ! ( " Placing spot limit BUY" ) ;
225- println ! ( " Token : {}" , spot_token . cyan ( ) ) ;
227+ println ! ( " Symbol: {}" , original_symbol . cyan ( ) ) ;
228+ println ! ( " Asset : {}" , asset_name ) ;
226229 println ! ( " Size: {:.6}" , size) ;
227230 println ! ( " Price: ${:.2}" , price) ;
228- println ! ( " Total: ${:.2 }" , price * size ) ;
231+ println ! ( " Total: ${}" , amount_usdc ) ;
229232 println ! (
230233 " Network: {}" ,
231234 if cfg. testnet { "Testnet" } else { "Mainnet" }
232235 ) ;
233236 println ! ( ) ;
234237 }
235238
236- let result = signing :: place_spot_order ( spot_token , true , price, size) . await ?;
239+ let result = hip3 :: place_order ( dex , asset_name , true , price, size) . await ?;
237240
238241 let response = json ! ( {
239- "action" : "commodity_spot_buy " ,
242+ "action" : "hip3_perp_buy " ,
240243 "symbol" : original_symbol,
241- "spotToken" : spot_token,
244+ "hip3Asset" : asset_name,
245+ "dex" : dex,
242246 "size" : format!( "{:.6}" , size) ,
243247 "price" : format!( "{:.2}" , price) ,
244- "total_usdc" : format! ( "{:.2}" , price * size ) ,
248+ "total_usdc" : amount_usdc ,
245249 "network" : if cfg. testnet { "testnet" } else { "mainnet" } ,
246- "note" : format!( "{} trades as {}/USDC spot pair (no perp available)" , original_symbol, spot_token) ,
247- "result" : format!( "{:?}" , result) ,
250+ "result" : result,
248251 } ) ;
249252
250253 if json_output {
251254 println ! ( "{}" , serde_json:: to_string_pretty( & response) ?) ;
252255 } else {
253- match result {
254- hyperliquid_rust_sdk:: ExchangeResponseStatus :: Ok ( data) => {
255- println ! ( " ✅ Spot order placed!" ) ;
256- println ! ( " Response: {:?}" , data) ;
257- }
258- hyperliquid_rust_sdk:: ExchangeResponseStatus :: Err ( e) => {
259- println ! ( " ❌ Order failed: {}" , e) ;
256+ if let Some ( status) = result. get ( "status" ) . and_then ( |s| s. as_str ( ) ) {
257+ if status == "ok" {
258+ println ! ( " ✅ HIP-3 perp order placed!" ) ;
259+ } else {
260+ println ! ( " ❌ Order failed: {}" , status) ;
260261 }
261262 }
263+ println ! ( " Response: {}" , serde_json:: to_string_pretty( & result) ?) ;
262264 println ! ( ) ;
263265 }
264266
265267 Ok ( ( ) )
266268}
267269
268- /// Route a commodity "perp sell" to a spot sell on HL
269- async fn commodity_spot_sell (
270- spot_token : & str ,
270+ /// Place a HIP-3 perp sell order
271+ async fn hip3_perp_sell (
272+ dex : & str ,
273+ asset_name : & str ,
271274 original_symbol : & str ,
272275 price : f64 ,
273276 size : f64 ,
@@ -277,12 +280,12 @@ async fn commodity_spot_sell(
277280 if !json_output {
278281 println ! ( ) ;
279282 println ! (
280- " 📝 {} trades as {}/USDC spot on Hyperliquid " ,
281- original_symbol ,
282- spot_token
283+ " 📝 Placing HIP-3 perp limit SELL ({} on {} dex) " ,
284+ asset_name . cyan ( ) ,
285+ dex
283286 ) ;
284- println ! ( " Placing spot limit SELL" ) ;
285- println ! ( " Token : {}" , spot_token . cyan ( ) ) ;
287+ println ! ( " Symbol: {}" , original_symbol . cyan ( ) ) ;
288+ println ! ( " Asset : {}" , asset_name ) ;
286289 println ! ( " Size: {:.6}" , size) ;
287290 println ! ( " Price: ${:.2}" , price) ;
288291 println ! (
@@ -292,31 +295,30 @@ async fn commodity_spot_sell(
292295 println ! ( ) ;
293296 }
294297
295- let result = signing :: place_spot_order ( spot_token , false , price, size) . await ?;
298+ let result = hip3 :: place_order ( dex , asset_name , false , price, size) . await ?;
296299
297300 let response = json ! ( {
298- "action" : "commodity_spot_sell " ,
301+ "action" : "hip3_perp_sell " ,
299302 "symbol" : original_symbol,
300- "spotToken" : spot_token,
303+ "hip3Asset" : asset_name,
304+ "dex" : dex,
301305 "size" : format!( "{:.6}" , size) ,
302306 "price" : format!( "{:.2}" , price) ,
303307 "network" : if cfg. testnet { "testnet" } else { "mainnet" } ,
304- "note" : format!( "{} trades as {}/USDC spot pair (no perp available)" , original_symbol, spot_token) ,
305- "result" : format!( "{:?}" , result) ,
308+ "result" : result,
306309 } ) ;
307310
308311 if json_output {
309312 println ! ( "{}" , serde_json:: to_string_pretty( & response) ?) ;
310313 } else {
311- match result {
312- hyperliquid_rust_sdk:: ExchangeResponseStatus :: Ok ( data) => {
313- println ! ( " ✅ Spot order placed!" ) ;
314- println ! ( " Response: {:?}" , data) ;
315- }
316- hyperliquid_rust_sdk:: ExchangeResponseStatus :: Err ( e) => {
317- println ! ( " ❌ Order failed: {}" , e) ;
314+ if let Some ( status) = result. get ( "status" ) . and_then ( |s| s. as_str ( ) ) {
315+ if status == "ok" {
316+ println ! ( " ✅ HIP-3 perp order placed!" ) ;
317+ } else {
318+ println ! ( " ❌ Order failed: {}" , status) ;
318319 }
319320 }
321+ println ! ( " Response: {}" , serde_json:: to_string_pretty( & result) ?) ;
320322 println ! ( ) ;
321323 }
322324
0 commit comments