@@ -490,6 +490,12 @@ export function buildLimitOrderCommands(deps = {}) {
490490 const expiresStr = options . expires || '30d' ;
491491 const walletName = options . wallet ;
492492
493+ if ( slippageBps != null && ( isNaN ( slippageBps ) || slippageBps < 0 || slippageBps > 10000 ) ) {
494+ log ( 'Error: --slippage-bps must be between 0 and 10000 basis points.' ) ;
495+ exit ( 1 ) ;
496+ return ;
497+ }
498+
493499 if ( ! from || ! to || ! amount || triggerPrice == null || ! triggerMintRaw || ! triggerCondition ) {
494500 log ( `
495501Usage: nansen trade limit create --from <token> --to <token> --amount <amount> --trigger-mint <token> --trigger-condition <above|below> --trigger-price <usd>
@@ -584,12 +590,16 @@ EXAMPLES:
584590 return ;
585591 }
586592
593+ let authToken = null ;
594+ let walletPubkey = null ;
595+
587596 try {
588597 // 1. Resolve wallet
589598 const resolved = await resolveSolanaWallet ( walletName , deps ) ;
590599 if ( ! resolved ) return ;
591600
592601 let { pubkey, walletType, walletInfo } = resolved ;
602+ walletPubkey = pubkey ;
593603
594604 // For local wallets, load private key now
595605 if ( walletType === 'local' ) {
@@ -604,25 +614,25 @@ EXAMPLES:
604614 log ( ` Trigger: $${ price } (${ triggerCondition } )` ) ;
605615
606616 // 2. Authenticate
607- const token = await authenticate ( pubkey , walletType , walletInfo , log ) ;
617+ authToken = await authenticate ( pubkey , walletType , walletInfo , log ) ;
608618
609619 // 3. Check vault, auto-register if needed
610620 // Backend returns { vaultPubkey: "..." } when vault exists, or throws/returns empty when not
611621 let hasVault = false ;
612622 try {
613- const vaultInfo = await getVault ( token , pubkey ) ;
623+ const vaultInfo = await getVault ( authToken , pubkey ) ;
614624 hasVault = ! ! vaultInfo ?. vaultPubkey ;
615625 } catch {
616626 // No vault found
617627 }
618628 if ( ! hasVault ) {
619629 log ( ' Registering vault for first-time use...' ) ;
620- await registerVault ( token ) ;
630+ await registerVault ( authToken ) ;
621631 }
622632
623633 // 4. Craft deposit transaction
624634 log ( ' Crafting deposit transaction...' ) ;
625- const deposit = await craftDeposit ( token , {
635+ const deposit = await craftDeposit ( authToken , {
626636 inputMint : from ,
627637 outputMint : to ,
628638 userAddress : pubkey ,
@@ -650,7 +660,7 @@ EXAMPLES:
650660 ...( expiresAt != null ? { expiresAt } : { } ) ,
651661 } ;
652662
653- const result = await createOrder ( token , orderParams ) ;
663+ const result = await createOrder ( authToken , orderParams ) ;
654664
655665 log ( `\n ✓ Limit order created` ) ;
656666 log ( ` Order ID: ${ result . id } ` ) ;
@@ -659,6 +669,21 @@ EXAMPLES:
659669 log ( '' ) ;
660670
661671 } catch ( err ) {
672+ // 5xx errors may indicate the order was created despite the error (e.g. gateway timeout).
673+ // Check recent orders to warn the user before they retry and create duplicates.
674+ if ( err . status >= 500 && authToken && walletPubkey ) {
675+ log ( `Warning: Order submission returned a server error, but may have succeeded.` ) ;
676+ log ( ` Checking order status...` ) ;
677+ try {
678+ const check = await listOrders ( authToken , walletPubkey , { limit : 1 } ) ;
679+ const recent = check . orders ?. [ 0 ] ;
680+ if ( recent && recent . inputMint === from && recent . outputMint === to ) {
681+ log ( ` Found recent matching order ${ recent . id } (status: ${ recent . status } ).` ) ;
682+ log ( ` Run: nansen trade limit list` ) ;
683+ return ;
684+ }
685+ } catch { /* list check failed, fall through to error */ }
686+ }
662687 log ( `Error: ${ err . message } ` ) ;
663688 if ( err . details ) log ( ` Details: ${ JSON . stringify ( err . details ) } ` ) ;
664689 if ( err . cause ) log ( ` Cause: ${ err . cause . message || err . cause } ` ) ;
0 commit comments