nansen-cli 1.38.0 → 1.40.0
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/CHANGELOG.md +35 -0
- package/README.md +56 -1
- package/package.json +1 -1
- package/skills/nansen-wallet-batch/SKILL.md +1 -1
- package/skills/nansen-wallet-profiler/SKILL.md +1 -1
- package/src/api.js +4 -3
- package/src/cli.js +8 -3
- package/src/limit-order.js +30 -7
- package/src/response-meta.js +2 -2
- package/src/rpc-urls.js +67 -0
- package/src/schema.json +20 -3
- package/src/swap-simulation.js +477 -0
- package/src/trade-validation.js +237 -6
- package/src/trading.js +566 -70
- package/src/transfer.js +25 -3
- package/src/walletconnect-trading.js +4 -2
package/src/transfer.js
CHANGED
|
@@ -120,9 +120,31 @@ async function buildEvmTransaction({ to, amount, token, privateKey, chain, max =
|
|
|
120
120
|
const privBuf = Buffer.from(privateKey, 'hex');
|
|
121
121
|
const from = deriveEvmAddress(privateKey);
|
|
122
122
|
|
|
123
|
-
//
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
// Fetch both pending and latest nonce counts. 'pending' is used so mempool-
|
|
124
|
+
// queued transactions are counted — 'latest' alone would assign the same
|
|
125
|
+
// nonce to back-to-back sends, causing one to fail or silently replace the
|
|
126
|
+
// other. The gap check mirrors trading.js's getEvmNonce: if more than 2
|
|
127
|
+
// transactions are already queued, signing another would silently stack
|
|
128
|
+
// behind them and sit unexecutable until they clear or get replaced.
|
|
129
|
+
const MAX_PENDING_NONCE_GAP = 2;
|
|
130
|
+
const [pendingHex, latestHex] = await Promise.all([
|
|
131
|
+
rpcCall(rpcUrl, 'eth_getTransactionCount', [from, 'pending']),
|
|
132
|
+
rpcCall(rpcUrl, 'eth_getTransactionCount', [from, 'latest']),
|
|
133
|
+
]);
|
|
134
|
+
const nonce = BigInt(pendingHex);
|
|
135
|
+
const latestNonce = BigInt(latestHex);
|
|
136
|
+
const gap = Number(nonce - latestNonce);
|
|
137
|
+
if (gap > MAX_PENDING_NONCE_GAP) {
|
|
138
|
+
// wallet send has no --nonce/--priority-fee, so don't tell the user to
|
|
139
|
+
// replace via this CLI. Also note the two-RPC race on load-balanced
|
|
140
|
+
// endpoints (same caveat as trading.js getEvmNonce).
|
|
141
|
+
throw new Error(
|
|
142
|
+
`${from} has ${gap} unmined transactions queued on ${chain} (next mined nonce ${latestNonce}, next pending ${nonce}). ` +
|
|
143
|
+
`Signing another would queue behind them and stay unexecutable until they clear. ` +
|
|
144
|
+
`Wait for them to clear (or replace them with a higher fee from where they were sent) before retrying. ` +
|
|
145
|
+
`Note that a load-balanced public RPC may report a transaction it isn't actually holding, so don't diagnose from a single endpoint.`,
|
|
146
|
+
);
|
|
147
|
+
}
|
|
126
148
|
|
|
127
149
|
// Fees — dynamic priority fee
|
|
128
150
|
const feeHistory = await rpcCall(rpcUrl, 'eth_feeHistory', [4, 'latest', [50]]);
|
|
@@ -114,13 +114,15 @@ export async function sendTransactionViaWalletConnect(txData, timeoutMs = 120000
|
|
|
114
114
|
* @param {number} chainId - EIP-155 chain ID
|
|
115
115
|
* @param {bigint|string|number} amount - Allowance to grant, in base units
|
|
116
116
|
* @param {bigint|string|number} [maxAllowance] - Hard cap from persisted request intent
|
|
117
|
+
* @param {object} [opts]
|
|
118
|
+
* @param {boolean} [opts.allowZero=false] - Allow a zero-amount revoke approval
|
|
117
119
|
* @returns {{ txHash?: string, signedTransaction?: string }}
|
|
118
120
|
*/
|
|
119
|
-
export async function sendApprovalViaWalletConnect(tokenAddress, spenderAddress, chainId, amount, maxAllowance) {
|
|
121
|
+
export async function sendApprovalViaWalletConnect(tokenAddress, spenderAddress, chainId, amount, maxAllowance, { allowZero = false } = {}) {
|
|
120
122
|
// encodeApproveCalldata enforces a valid 20-byte spender, a bounded (< MAX)
|
|
121
123
|
// amount within the request cap, and exactly-68-byte calldata — so a
|
|
122
124
|
// malformed or tampered spender/amount can't reshape the ABI word layout.
|
|
123
|
-
const data = encodeApproveCalldata(spenderAddress, amount, { maxAllowance });
|
|
125
|
+
const data = encodeApproveCalldata(spenderAddress, amount, { maxAllowance, allowZero });
|
|
124
126
|
|
|
125
127
|
return sendTransactionViaWalletConnect({
|
|
126
128
|
to: tokenAddress,
|