nansen-cli 1.10.1 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/trading.js CHANGED
@@ -756,7 +756,7 @@ export function formatQuote(quote, index) {
756
756
  * Build trading command handlers for CLI integration.
757
757
  */
758
758
  export function buildTradingCommands(deps = {}) {
759
- const { errorOutput = console.error, exit = process.exit } = deps;
759
+ const { log = console.log, exit = process.exit } = deps;
760
760
 
761
761
  return {
762
762
  'quote': async (args, apiInstance, flags, options) => {
@@ -773,7 +773,7 @@ export function buildTradingCommands(deps = {}) {
773
773
  const swapMode = options['swap-mode'] || 'exactIn';
774
774
 
775
775
  if (!chain || !from || !to || !amount) {
776
- errorOutput(`
776
+ log(`
777
777
  Usage: nansen trade quote --chain <chain> --from <token> --to <token> --amount <baseUnits>
778
778
 
779
779
  PREREQUISITE:
@@ -803,7 +803,7 @@ EXAMPLES:
803
803
 
804
804
  const amountError = validateBaseUnitAmount(amount);
805
805
  if (amountError) {
806
- errorOutput(`Error: ${amountError}`);
806
+ log(`Error: ${amountError}`);
807
807
  exit(1);
808
808
  return;
809
809
  }
@@ -817,13 +817,13 @@ EXAMPLES:
817
817
  let walletAddress;
818
818
  if (isWalletConnect) {
819
819
  if (chainType !== 'evm') {
820
- errorOutput('WalletConnect is only supported for EVM chains');
820
+ log('WalletConnect is only supported for EVM chains');
821
821
  exit(1);
822
822
  return;
823
823
  }
824
824
  walletAddress = await getWalletConnectAddress();
825
825
  if (!walletAddress) {
826
- errorOutput('No WalletConnect session active. Run: walletconnect connect');
826
+ log('No WalletConnect session active. Run: walletconnect connect');
827
827
  exit(1);
828
828
  return;
829
829
  }
@@ -839,16 +839,16 @@ EXAMPLES:
839
839
  }
840
840
 
841
841
  if (!walletAddress) {
842
- errorOutput('No wallet found. A wallet address is required for quotes because the trading API builds a transaction specific to the sender.\nCreate one with: nansen wallet create');
842
+ log('No wallet found. A wallet address is required for quotes because the trading API builds a transaction specific to the sender.\nCreate one with: nansen wallet create');
843
843
  exit(1);
844
844
  return;
845
845
  }
846
846
 
847
- errorOutput(`\nFetching quote on ${chainConfig.name}...`);
848
- errorOutput(` Wallet: ${walletAddress}`);
847
+ log(`\nFetching quote on ${chainConfig.name}...`);
848
+ log(` Wallet: ${walletAddress}`);
849
849
 
850
850
  const fromWarning = getWrappedNativeFromWarning(from, chain);
851
- if (fromWarning) errorOutput(` ${fromWarning}`);
851
+ if (fromWarning) log(` ${fromWarning}`);
852
852
 
853
853
  const params = {
854
854
  chainIndex: chainConfig.index,
@@ -865,30 +865,30 @@ EXAMPLES:
865
865
  const response = await getQuote(params);
866
866
 
867
867
  if (!response.success || !response.quotes?.length) {
868
- errorOutput('No quotes available');
868
+ log('No quotes available');
869
869
  if (response.warnings?.length) {
870
- response.warnings.forEach(w => errorOutput(` Warning: ${w}`));
870
+ response.warnings.forEach(w => log(` Warning: ${w}`));
871
871
  }
872
872
  exit(1);
873
873
  return;
874
874
  }
875
875
 
876
- errorOutput('');
877
- response.quotes.forEach((q, i) => errorOutput(formatQuote(q, i)));
876
+ log('');
877
+ response.quotes.forEach((q, i) => log(formatQuote(q, i)));
878
878
 
879
879
  const quoteId = saveQuote(response, chain, isWalletConnect ? 'walletconnect' : 'local');
880
- errorOutput(`\n Quote ID: ${quoteId}`);
881
- errorOutput(` Execute: nansen trade execute --quote ${quoteId}`);
880
+ log(`\n Quote ID: ${quoteId}`);
881
+ log(` Execute: nansen trade execute --quote ${quoteId}`);
882
882
  if (response.quotes.length > 1) {
883
- errorOutput(` Pin #1: nansen trade execute --quote ${quoteId} --quote-index 0`);
883
+ log(` Pin #1: nansen trade execute --quote ${quoteId} --quote-index 0`);
884
884
  }
885
885
 
886
886
  if (response.quotes[0]?.approvalAddress && !isNativeToken(response.quotes[0]?.inputMint)) {
887
- errorOutput(`\n Warning: This token swap requires an ERC-20 approval step.`);
888
- errorOutput(` The execute command will handle this automatically.`);
887
+ log(`\n Warning: This token swap requires an ERC-20 approval step.`);
888
+ log(` The execute command will handle this automatically.`);
889
889
  }
890
890
 
891
- errorOutput('');
891
+ log('');
892
892
  return undefined; // Output already printed above
893
893
 
894
894
  } catch (err) {
@@ -896,8 +896,8 @@ EXAMPLES:
896
896
  if (err.code === 'INVALID_AMOUNT' || /amount/i.test(err.message)) {
897
897
  message += '. Amounts must be in base units (e.g., 1000000000 lamports for 1 SOL, 1000000000000000000 wei for 1 ETH)';
898
898
  }
899
- errorOutput(`Error: ${message}`);
900
- if (err.details) errorOutput(` Details: ${JSON.stringify(err.details)}`);
899
+ log(`Error: ${message}`);
900
+ if (err.details) log(` Details: ${JSON.stringify(err.details)}`);
901
901
  exit(1);
902
902
  }
903
903
  },
@@ -908,7 +908,7 @@ EXAMPLES:
908
908
  const noSimulate = flags['no-simulate'] || flags.noSimulate;
909
909
 
910
910
  if (!quoteId) {
911
- errorOutput(`
911
+ log(`
912
912
  Usage: nansen trade execute --quote <quoteId> [options]
913
913
 
914
914
  OPTIONS:
@@ -931,7 +931,7 @@ EXAMPLES:
931
931
 
932
932
  const allQuotes = quoteData.response.quotes || [];
933
933
  if (!allQuotes.length) {
934
- errorOutput('❌ No quote data found');
934
+ log('❌ No quote data found');
935
935
  exit(1);
936
936
  return;
937
937
  }
@@ -944,8 +944,8 @@ EXAMPLES:
944
944
  // Check if any quote in range has transaction data before prompting for password
945
945
  const hasAnyTransaction = allQuotes.slice(startIndex, endIndex).some(q => q?.transaction);
946
946
  if (!hasAnyTransaction) {
947
- errorOutput('❌ No quotes contain transaction data.');
948
- errorOutput(' Ensure userWalletAddress was provided when fetching the quote.');
947
+ log('❌ No quotes contain transaction data.');
948
+ log(' Ensure userWalletAddress was provided when fetching the quote.');
949
949
  exit(1);
950
950
  return;
951
951
  }
@@ -965,7 +965,7 @@ EXAMPLES:
965
965
  effectiveWalletName = list.defaultWallet;
966
966
  }
967
967
  if (!effectiveWalletName) {
968
- errorOutput('No wallet found. Create one with: nansen wallet create');
968
+ log('No wallet found. Create one with: nansen wallet create');
969
969
  exit(1);
970
970
  return;
971
971
  }
@@ -974,13 +974,13 @@ EXAMPLES:
974
974
  } else {
975
975
  // Verify WalletConnect session is still active and address matches quote
976
976
  if (chainType !== 'evm') {
977
- errorOutput('WalletConnect is only supported for EVM chains');
977
+ log('WalletConnect is only supported for EVM chains');
978
978
  exit(1);
979
979
  return;
980
980
  }
981
981
  const wcAddress = await getWalletConnectAddress();
982
982
  if (!wcAddress) {
983
- errorOutput('No WalletConnect session active. Run: walletconnect connect');
983
+ log('No WalletConnect session active. Run: walletconnect connect');
984
984
  exit(1);
985
985
  return;
986
986
  }
@@ -988,7 +988,7 @@ EXAMPLES:
988
988
  const quoteWallet = quoteData.response?.quotes?.[0]?.transaction?.from
989
989
  || quoteData.response?.metadata?.userWalletAddress;
990
990
  if (quoteWallet && wcAddress.toLowerCase() !== quoteWallet.toLowerCase()) {
991
- errorOutput(`Connected wallet (${wcAddress}) doesn't match quote. Get a new quote with --wallet walletconnect`);
991
+ log(`Connected wallet (${wcAddress}) doesn't match quote. Get a new quote with --wallet walletconnect`);
992
992
  exit(1);
993
993
  return;
994
994
  }
@@ -1004,17 +1004,17 @@ EXAMPLES:
1004
1004
 
1005
1005
  // Verify transaction data exists
1006
1006
  if (!currentQuote.transaction) {
1007
- errorOutput(` ⚠ Quote ${quoteName}: no transaction data, skipping...`);
1007
+ log(` ⚠ Quote ${quoteName}: no transaction data, skipping...`);
1008
1008
  lastQuoteError = `Quote ${quoteName} has no transaction data`;
1009
1009
  continue;
1010
1010
  }
1011
1011
 
1012
- errorOutput(`\nExecuting trade on ${chainConfig.name}...`);
1012
+ log(`\nExecuting trade on ${chainConfig.name}...`);
1013
1013
  if (endIndex - startIndex > 1) {
1014
- errorOutput(` Trying quote ${qi + 1}/${allQuotes.length} (${quoteName})...`);
1014
+ log(` Trying quote ${qi + 1}/${allQuotes.length} (${quoteName})...`);
1015
1015
  }
1016
- errorOutput(formatQuote(currentQuote));
1017
- errorOutput('');
1016
+ log(formatQuote(currentQuote));
1017
+ log('');
1018
1018
 
1019
1019
  try {
1020
1020
  let signedTransaction;
@@ -1027,7 +1027,7 @@ EXAMPLES:
1027
1027
  if (typeof txBase64 === 'object' && txBase64.data) {
1028
1028
  txBase64 = base58Decode(txBase64.data).toString('base64');
1029
1029
  }
1030
- errorOutput(' Signing Solana transaction...');
1030
+ log(' Signing Solana transaction...');
1031
1031
  signedTransaction = signSolanaTransaction(txBase64, exported.solana.privateKey);
1032
1032
  requestId = currentQuote.metadata?.requestId;
1033
1033
 
@@ -1041,15 +1041,15 @@ EXAMPLES:
1041
1041
  if (isNative) {
1042
1042
  const expectedValue = BigInt(currentQuote.inAmount || currentQuote.inputAmount || '0');
1043
1043
  if (txValue !== expectedValue) {
1044
- errorOutput(` ❌ Transaction value mismatch for ${quoteName}: tx.value=${txValue}, expected=${expectedValue}`);
1045
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1044
+ log(` ❌ Transaction value mismatch for ${quoteName}: tx.value=${txValue}, expected=${expectedValue}`);
1045
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1046
1046
  lastQuoteError = `${quoteName} transaction value mismatch`;
1047
1047
  continue;
1048
1048
  }
1049
1049
  } else {
1050
1050
  if (txValue > 0n) {
1051
- errorOutput(` ❌ ERC-20 swap has non-zero tx.value (${txValue}) for ${quoteName} — aborting`);
1052
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1051
+ log(` ❌ ERC-20 swap has non-zero tx.value (${txValue}) for ${quoteName} — aborting`);
1052
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1053
1053
  lastQuoteError = `${quoteName} unexpected tx.value`;
1054
1054
  continue;
1055
1055
  }
@@ -1063,10 +1063,10 @@ EXAMPLES:
1063
1063
  );
1064
1064
 
1065
1065
  if (existingAllowance >= inputAmount && existingAllowance > 0n) {
1066
- errorOutput(` ✓ Sufficient allowance exists for ${quoteName}, skipping approval`);
1066
+ log(` ✓ Sufficient allowance exists for ${quoteName}, skipping approval`);
1067
1067
  } else {
1068
- errorOutput(` ⚠ Approval required → ${currentQuote.approvalAddress}`);
1069
- errorOutput(` Sending approval via WalletConnect...`);
1068
+ log(` ⚠ Approval required → ${currentQuote.approvalAddress}`);
1069
+ log(` Sending approval via WalletConnect...`);
1070
1070
  try {
1071
1071
  const approvalResult = await sendApprovalViaWalletConnect(
1072
1072
  currentQuote.inputMint,
@@ -1076,7 +1076,7 @@ EXAMPLES:
1076
1076
  let approvalTxHash = approvalResult.txHash;
1077
1077
  if (!approvalTxHash && approvalResult.signedTransaction) {
1078
1078
  // Wallet returned a signed tx instead of broadcasting — broadcast via Trading API
1079
- errorOutput(` Broadcasting approval via Trading API...`);
1079
+ log(` Broadcasting approval via Trading API...`);
1080
1080
  const broadcastResult = await executeTransaction({
1081
1081
  signedTransaction: approvalResult.signedTransaction,
1082
1082
  chain,
@@ -1088,18 +1088,18 @@ EXAMPLES:
1088
1088
  approvalTxHash = broadcastResult.txHash;
1089
1089
  }
1090
1090
  if (approvalTxHash) {
1091
- errorOutput(` Waiting for approval confirmation...`);
1091
+ log(` Waiting for approval confirmation...`);
1092
1092
  const receipt = await waitForReceipt(chain, approvalTxHash);
1093
- errorOutput(` ✓ Approval confirmed in block ${parseInt(receipt.blockNumber, 16)}: ${approvalTxHash}`);
1093
+ log(` ✓ Approval confirmed in block ${parseInt(receipt.blockNumber, 16)}: ${approvalTxHash}`);
1094
1094
  }
1095
1095
  } catch (approvalErr) {
1096
- errorOutput(` ❌ Approval failed for ${quoteName}: ${approvalErr.message}`);
1097
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1096
+ log(` ❌ Approval failed for ${quoteName}: ${approvalErr.message}`);
1097
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1098
1098
  lastQuoteError = `${quoteName} approval failed`;
1099
1099
  continue;
1100
1100
  }
1101
1101
  await new Promise(r => setTimeout(r, 2000));
1102
- errorOutput('');
1102
+ log('');
1103
1103
  }
1104
1104
  }
1105
1105
 
@@ -1113,8 +1113,8 @@ EXAMPLES:
1113
1113
  value: txData.value ? '0x' + BigInt(txData.value).toString(16) : '0x0',
1114
1114
  });
1115
1115
  if (!sim.success) {
1116
- errorOutput(` ⚠ Simulation failed for ${quoteName}: ${sim.reason}`);
1117
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1116
+ log(` ⚠ Simulation failed for ${quoteName}: ${sim.reason}`);
1117
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1118
1118
  lastQuoteError = `${quoteName} simulation failed: ${sim.reason}`;
1119
1119
  continue;
1120
1120
  }
@@ -1127,7 +1127,7 @@ EXAMPLES:
1127
1127
  const finalGas = apiGas > 0 ? apiGas : txGas;
1128
1128
 
1129
1129
  // Send transaction via WalletConnect
1130
- errorOutput(' Sending transaction via WalletConnect...');
1130
+ log(' Sending transaction via WalletConnect...');
1131
1131
  let wcResult;
1132
1132
  try {
1133
1133
  wcResult = await sendTransactionViaWalletConnect({
@@ -1138,24 +1138,24 @@ EXAMPLES:
1138
1138
  chainId: chainConfig.chainId,
1139
1139
  });
1140
1140
  } catch (wcErr) {
1141
- errorOutput(` ❌ WalletConnect transaction failed for ${quoteName}: ${wcErr.message}`);
1142
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1141
+ log(` ❌ WalletConnect transaction failed for ${quoteName}: ${wcErr.message}`);
1142
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1143
1143
  lastQuoteError = `${quoteName}: ${wcErr.message}`;
1144
1144
  continue;
1145
1145
  }
1146
1146
 
1147
1147
  if (wcResult.txHash) {
1148
1148
  // Wallet broadcast — verify on-chain
1149
- errorOutput(' Verifying on-chain status...');
1149
+ log(' Verifying on-chain status...');
1150
1150
  try {
1151
1151
  await waitForReceipt(chain, wcResult.txHash);
1152
1152
  } catch (receiptErr) {
1153
- errorOutput(`\n ⚠ Transaction was broadcast but REVERTED on-chain!`);
1154
- errorOutput(` Tx Hash: ${wcResult.txHash}`);
1155
- errorOutput(` Explorer: ${chainConfig.explorer}${wcResult.txHash}`);
1156
- errorOutput(` Error: ${receiptErr.message}`);
1153
+ log(`\n ⚠ Transaction was broadcast but REVERTED on-chain!`);
1154
+ log(` Tx Hash: ${wcResult.txHash}`);
1155
+ log(` Explorer: ${chainConfig.explorer}${wcResult.txHash}`);
1156
+ log(` Error: ${receiptErr.message}`);
1157
1157
  if (qi + 1 < endIndex) {
1158
- errorOutput(` Trying next quote...`);
1158
+ log(` Trying next quote...`);
1159
1159
  lastQuoteError = `${quoteName} reverted on-chain`;
1160
1160
  continue;
1161
1161
  }
@@ -1163,11 +1163,11 @@ EXAMPLES:
1163
1163
  return;
1164
1164
  }
1165
1165
 
1166
- errorOutput(`\n ✓ Transaction successful!`);
1167
- errorOutput(` Tx Hash: ${wcResult.txHash}`);
1168
- errorOutput(` Chain: ${chainConfig.name}`);
1169
- errorOutput(` Explorer: ${chainConfig.explorer}${wcResult.txHash}`);
1170
- errorOutput('');
1166
+ log(`\n ✓ Transaction successful!`);
1167
+ log(` Tx Hash: ${wcResult.txHash}`);
1168
+ log(` Chain: ${chainConfig.name}`);
1169
+ log(` Explorer: ${chainConfig.explorer}${wcResult.txHash}`);
1170
+ log('');
1171
1171
  return undefined; // Success
1172
1172
  }
1173
1173
 
@@ -1191,15 +1191,15 @@ EXAMPLES:
1191
1191
  if (isNative) {
1192
1192
  const expectedValue = BigInt(currentQuote.inAmount || currentQuote.inputAmount || '0');
1193
1193
  if (txValue !== expectedValue) {
1194
- errorOutput(` ❌ Transaction value mismatch for ${quoteName}: tx.value=${txValue}, expected=${expectedValue}`);
1195
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1194
+ log(` ❌ Transaction value mismatch for ${quoteName}: tx.value=${txValue}, expected=${expectedValue}`);
1195
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1196
1196
  lastQuoteError = `${quoteName} transaction value mismatch`;
1197
1197
  continue;
1198
1198
  }
1199
1199
  } else {
1200
1200
  if (txValue > 0n) {
1201
- errorOutput(` ❌ ERC-20 swap has non-zero tx.value (${txValue}) for ${quoteName} — aborting`);
1202
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1201
+ log(` ❌ ERC-20 swap has non-zero tx.value (${txValue}) for ${quoteName} — aborting`);
1202
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1203
1203
  lastQuoteError = `${quoteName} unexpected tx.value`;
1204
1204
  continue;
1205
1205
  }
@@ -1213,10 +1213,10 @@ EXAMPLES:
1213
1213
  );
1214
1214
 
1215
1215
  if (existingAllowance >= inputAmount && existingAllowance > 0n) {
1216
- errorOutput(` ✓ Sufficient allowance exists for ${quoteName}, skipping approval`);
1216
+ log(` ✓ Sufficient allowance exists for ${quoteName}, skipping approval`);
1217
1217
  } else {
1218
- errorOutput(` ⚠ Approval required → ${currentQuote.approvalAddress}`);
1219
- errorOutput(` Sending approval tx...`);
1218
+ log(` ⚠ Approval required → ${currentQuote.approvalAddress}`);
1219
+ log(` Sending approval tx...`);
1220
1220
  const approvalNonce = await getEvmNonce(chain, walletAddress);
1221
1221
 
1222
1222
  const approvalGasPrice = currentQuote.transaction?.gasPrice || currentQuote.transaction?.maxFeePerGas || '1000000';
@@ -1236,25 +1236,25 @@ EXAMPLES:
1236
1236
  });
1237
1237
 
1238
1238
  if (approvalResult.status !== 'Success') {
1239
- errorOutput(` ❌ Approval failed for ${quoteName}: ${approvalResult.error || 'unknown error'}`);
1240
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1239
+ log(` ❌ Approval failed for ${quoteName}: ${approvalResult.error || 'unknown error'}`);
1240
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1241
1241
  lastQuoteError = `${quoteName} approval failed`;
1242
1242
  continue;
1243
1243
  }
1244
1244
 
1245
- errorOutput(` Waiting for approval confirmation...`);
1245
+ log(` Waiting for approval confirmation...`);
1246
1246
  try {
1247
1247
  const receipt = await waitForReceipt(chain, approvalResult.txHash);
1248
- errorOutput(` ✓ Approval confirmed in block ${parseInt(receipt.blockNumber, 16)}: ${approvalResult.txHash}`);
1248
+ log(` ✓ Approval confirmed in block ${parseInt(receipt.blockNumber, 16)}: ${approvalResult.txHash}`);
1249
1249
  } catch (receiptErr) {
1250
- errorOutput(` ❌ Approval may not have confirmed: ${receiptErr.message}`);
1251
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1250
+ log(` ❌ Approval may not have confirmed: ${receiptErr.message}`);
1251
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1252
1252
  lastQuoteError = `${quoteName} approval unconfirmed`;
1253
1253
  continue;
1254
1254
  }
1255
1255
  // Wait for RPC state propagation after approval
1256
1256
  await new Promise(r => setTimeout(r, 2000));
1257
- errorOutput('');
1257
+ log('');
1258
1258
  }
1259
1259
  }
1260
1260
 
@@ -1270,8 +1270,8 @@ EXAMPLES:
1270
1270
  value: txData.value ? '0x' + BigInt(txData.value).toString(16) : '0x0',
1271
1271
  });
1272
1272
  if (!sim.success) {
1273
- errorOutput(` ⚠ Simulation failed for ${quoteName}: ${sim.reason}`);
1274
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1273
+ log(` ⚠ Simulation failed for ${quoteName}: ${sim.reason}`);
1274
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1275
1275
  lastQuoteError = `${quoteName} simulation failed: ${sim.reason}`;
1276
1276
  continue;
1277
1277
  }
@@ -1285,17 +1285,17 @@ EXAMPLES:
1285
1285
  const txGas = parseInt(txData.gas || txData.gasLimit || "0");
1286
1286
  const finalGas = apiGas > 0 ? apiGas : txGas;
1287
1287
  if (finalGas !== txGas) {
1288
- errorOutput(` ℹ Using API gas ${finalGas} (tx.gas was ${txGas})`);
1288
+ log(` ℹ Using API gas ${finalGas} (tx.gas was ${txGas})`);
1289
1289
  }
1290
1290
  if (txData.gasLimit) txData.gasLimit = String(finalGas);
1291
1291
  else txData.gas = String(finalGas);
1292
1292
 
1293
- errorOutput(' Fetching nonce...');
1293
+ log(' Fetching nonce...');
1294
1294
  await new Promise(r => setTimeout(r, 1000));
1295
1295
  const nonce = await getEvmNonce(chain, walletAddress);
1296
- errorOutput(` Nonce: ${nonce}`);
1296
+ log(` Nonce: ${nonce}`);
1297
1297
 
1298
- errorOutput(' Signing EVM transaction...');
1298
+ log(' Signing EVM transaction...');
1299
1299
  signedTransaction = signEvmTransaction(
1300
1300
  currentQuote.transaction,
1301
1301
  exported.evm.privateKey,
@@ -1304,7 +1304,7 @@ EXAMPLES:
1304
1304
  );
1305
1305
  }
1306
1306
 
1307
- errorOutput(' Broadcasting...');
1307
+ log(' Broadcasting...');
1308
1308
  const execParams = {
1309
1309
  signedTransaction,
1310
1310
  chain,
@@ -1320,64 +1320,64 @@ EXAMPLES:
1320
1320
 
1321
1321
  // For EVM: verify the tx actually succeeded on-chain
1322
1322
  if (chainType === 'evm' && result.txHash) {
1323
- errorOutput(' Verifying on-chain status...');
1323
+ log(' Verifying on-chain status...');
1324
1324
  try {
1325
1325
  await waitForReceipt(chain, result.txHash);
1326
1326
  } catch (receiptErr) {
1327
- errorOutput(`\n ⚠ Transaction was broadcast but REVERTED on-chain!`);
1328
- errorOutput(` Tx Hash: ${result.txHash}`);
1329
- errorOutput(` Explorer: ${explorerUrl}`);
1330
- errorOutput(` Error: ${receiptErr.message}`);
1327
+ log(`\n ⚠ Transaction was broadcast but REVERTED on-chain!`);
1328
+ log(` Tx Hash: ${result.txHash}`);
1329
+ log(` Explorer: ${explorerUrl}`);
1330
+ log(` Error: ${receiptErr.message}`);
1331
1331
  if (qi + 1 < endIndex) {
1332
- errorOutput(` Trying next quote...`);
1332
+ log(` Trying next quote...`);
1333
1333
  lastQuoteError = `${quoteName} reverted on-chain`;
1334
1334
  continue;
1335
1335
  }
1336
- errorOutput(`\n The trading API reported success, but the contract execution failed.`);
1337
- errorOutput(` This can happen due to: stale quotes, insufficient gas, or liquidity changes.`);
1336
+ log(`\n The trading API reported success, but the contract execution failed.`);
1337
+ log(` This can happen due to: stale quotes, insufficient gas, or liquidity changes.`);
1338
1338
  exit(1);
1339
1339
  return;
1340
1340
  }
1341
1341
  }
1342
1342
 
1343
- errorOutput(`\n ✓ Transaction successful!`);
1344
- errorOutput(` Status: ${result.status}`);
1345
- errorOutput(` ${result.signature ? 'Signature' : 'Tx Hash'}: ${txId}`);
1346
- errorOutput(` Chain: ${chainConfig.name} (${result.chainType})`);
1347
- errorOutput(` Broadcaster: ${result.broadcaster}`);
1348
- errorOutput(` Explorer: ${explorerUrl}`);
1343
+ log(`\n ✓ Transaction successful!`);
1344
+ log(` Status: ${result.status}`);
1345
+ log(` ${result.signature ? 'Signature' : 'Tx Hash'}: ${txId}`);
1346
+ log(` Chain: ${chainConfig.name} (${result.chainType})`);
1347
+ log(` Broadcaster: ${result.broadcaster}`);
1348
+ log(` Explorer: ${explorerUrl}`);
1349
1349
 
1350
1350
  if (result.swapEvents?.length) {
1351
- errorOutput(` Swaps:`);
1351
+ log(` Swaps:`);
1352
1352
  result.swapEvents.forEach(e => {
1353
- errorOutput(` ${e.inputAmount} ${e.inputMint?.slice(0, 8)}... → ${e.outputAmount} ${e.outputMint?.slice(0, 8)}...`);
1353
+ log(` ${e.inputAmount} ${e.inputMint?.slice(0, 8)}... → ${e.outputAmount} ${e.outputMint?.slice(0, 8)}...`);
1354
1354
  });
1355
1355
  }
1356
- errorOutput('');
1356
+ log('');
1357
1357
  return undefined; // Success — done
1358
1358
  } else {
1359
- errorOutput(`\n ✗ Quote ${quoteName} failed: ${result.status}`);
1360
- if (result.error) errorOutput(` Error: ${result.error}`);
1359
+ log(`\n ✗ Quote ${quoteName} failed: ${result.status}`);
1360
+ if (result.error) log(` Error: ${result.error}`);
1361
1361
  lastQuoteError = `${quoteName}: ${result.error || result.status}`;
1362
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1362
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1363
1363
  }
1364
1364
 
1365
1365
  } catch (quoteErr) {
1366
- errorOutput(` ❌ Quote ${quoteName} failed: ${quoteErr.message}`);
1366
+ log(` ❌ Quote ${quoteName} failed: ${quoteErr.message}`);
1367
1367
  lastQuoteError = `${quoteName}: ${quoteErr.message}`;
1368
- if (qi + 1 < endIndex) errorOutput(` Trying next quote...`);
1368
+ if (qi + 1 < endIndex) log(` Trying next quote...`);
1369
1369
  }
1370
1370
  }
1371
1371
 
1372
1372
  // All quotes exhausted
1373
- errorOutput(`\n❌ All quotes failed. Last error: ${lastQuoteError || 'unknown'}`);
1374
- errorOutput('');
1373
+ log(`\n❌ All quotes failed. Last error: ${lastQuoteError || 'unknown'}`);
1374
+ log('');
1375
1375
  exit(1);
1376
1376
  return undefined;
1377
1377
 
1378
1378
  } catch (err) {
1379
- errorOutput(`Error: ${err.message}`);
1380
- if (err.details) errorOutput(` Details: ${JSON.stringify(err.details)}`);
1379
+ log(`Error: ${err.message}`);
1380
+ if (err.details) log(` Details: ${JSON.stringify(err.details)}`);
1381
1381
  exit(1);
1382
1382
  }
1383
1383
  },