@vultisig/cli 6.3.0 → 7.2.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 +30 -0
- package/dist/index.js +318 -73
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 7.2.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#2321](https://github.com/vultisig/vultisig-sdk/pull/2321) [`f45627f`](https://github.com/vultisig/vultisig-sdk/commit/f45627f7a986a3491c4586363acbfbdaa5f6b9c3) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Decode modern and legacy Cosmos governance votes into a lossless action-specific shared envelope.
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`f45627f`](https://github.com/vultisig/vultisig-sdk/commit/f45627f7a986a3491c4586363acbfbdaa5f6b9c3), [`fd7507a`](https://github.com/vultisig/vultisig-sdk/commit/fd7507af5d9dc14938da80372bc3c1a8ec02a459), [`a5def09`](https://github.com/vultisig/vultisig-sdk/commit/a5def098e06cf7269174eb6840dc516d78ec55f9), [`bcca32c`](https://github.com/vultisig/vultisig-sdk/commit/bcca32c885066e2bf224aa37d6666c68a3684956), [`052f2e3`](https://github.com/vultisig/vultisig-sdk/commit/052f2e3b56509c1ddc2bcc14f21d0d1a5ee5d674), [`231070e`](https://github.com/vultisig/vultisig-sdk/commit/231070ea811a79a84b43a98fadd80c2811071c94)]:
|
|
10
|
+
- @vultisig/sdk@7.2.0
|
|
11
|
+
- @vultisig/core-chain@5.2.0
|
|
12
|
+
|
|
13
|
+
## 7.0.0
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#2295](https://github.com/vultisig/vultisig-sdk/pull/2295) [`27dfd44`](https://github.com/vultisig/vultisig-sdk/commit/27dfd44fe6002d84c6f1e57ed0729ec22303a749) Thanks [@neavra](https://github.com/neavra)! - Refresh EIP-1559 priority fees immediately before CLI signing so zero-tip transactions use the live RPC suggestion, respect canonical per-chain minimums, and never exceed `maxFeePerGas`. Broadcast rejection messages now retain the actionable RPC reason without exposing the signed raw transaction.
|
|
18
|
+
|
|
19
|
+
- [#1996](https://github.com/vultisig/vultisig-sdk/pull/1996) [`a56c7cb`](https://github.com/vultisig/vultisig-sdk/commit/a56c7cb2b1bcfa74edcee0ae7e5552f830804734) Thanks [@gomesalexandre](https://github.com/gomesalexandre)! - Export the `ChainDiscoveryAggregate` type from the public SDK seedphrase and root entrypoints so consumers can import the aggregate result returned by seedphrase discovery without restating the contract locally.
|
|
20
|
+
|
|
21
|
+
- [#2307](https://github.com/vultisig/vultisig-sdk/pull/2307) [`42fd134`](https://github.com/vultisig/vultisig-sdk/commit/42fd1349b52fec44a5a0f47a898ad1537ac6ff60) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Refresh stale raw EVM server nonces from pending RPC state immediately before signing.
|
|
22
|
+
|
|
23
|
+
- [#2294](https://github.com/vultisig/vultisig-sdk/pull/2294) [`a3e1415`](https://github.com/vultisig/vultisig-sdk/commit/a3e1415758077867343de920af5bec36f2f89b11) Thanks [@neavra](https://github.com/neavra)! - Route pipe-mode confirmation and password replies around the serialized message queue so signable agent turns can complete.
|
|
24
|
+
|
|
25
|
+
- [#2318](https://github.com/vultisig/vultisig-sdk/pull/2318) [`26a83ed`](https://github.com/vultisig/vultisig-sdk/commit/26a83ed417c9543f9c92d28cbb1bd35f0f914817) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Fix TRON transaction lifecycle safety across fee preparation, status polling, and broadcast. Native TRX bandwidth estimates now measure the WalletCore-serialized signed transaction including memo bytes, default transaction times use the fetched block timestamp, expired raw transactions terminate polling, and successful broadcasts must return the deterministic local transaction hash.
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`27dfd44`](https://github.com/vultisig/vultisig-sdk/commit/27dfd44fe6002d84c6f1e57ed0729ec22303a749), [`1b3fb49`](https://github.com/vultisig/vultisig-sdk/commit/1b3fb498ad3f78b84b92b9f09b41fe8956fc5e9a), [`a56c7cb`](https://github.com/vultisig/vultisig-sdk/commit/a56c7cb2b1bcfa74edcee0ae7e5552f830804734), [`bd15294`](https://github.com/vultisig/vultisig-sdk/commit/bd15294a739c7977b26704b7b6df38e83e6bda23), [`7d4c116`](https://github.com/vultisig/vultisig-sdk/commit/7d4c116cc7a940e96abf075790c4a387edd03987), [`7b65284`](https://github.com/vultisig/vultisig-sdk/commit/7b65284f7fe73f538283a201a416efdbbda0830c), [`1716a79`](https://github.com/vultisig/vultisig-sdk/commit/1716a7946bf617ff16f8bb15f33b279efbb4a87d), [`a711b6c`](https://github.com/vultisig/vultisig-sdk/commit/a711b6ca8a8a7ae39d0efbb1c919b23b6538a1b8), [`ef6a8bb`](https://github.com/vultisig/vultisig-sdk/commit/ef6a8bb0007c6576179e5a8cb10aa47820075b57), [`26a83ed`](https://github.com/vultisig/vultisig-sdk/commit/26a83ed417c9543f9c92d28cbb1bd35f0f914817), [`4978c02`](https://github.com/vultisig/vultisig-sdk/commit/4978c02f08521600fc70fa6b4753bae5a589371b), [`8a2c126`](https://github.com/vultisig/vultisig-sdk/commit/8a2c126333bb1010cf859eef6a4876e7a20da18f), [`b19c5d5`](https://github.com/vultisig/vultisig-sdk/commit/b19c5d56f4d00d92493f8da74ff80d92b1d87c68)]:
|
|
28
|
+
- @vultisig/sdk@7.0.0
|
|
29
|
+
- @vultisig/core-chain@5.0.0
|
|
30
|
+
- @vultisig/rujira@71.0.0
|
|
31
|
+
- @vultisig/client-shared@0.3.6
|
|
32
|
+
|
|
3
33
|
## 6.3.0
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -8130,7 +8130,7 @@ var require_dist = __commonJS({
|
|
|
8130
8130
|
import "dotenv/config";
|
|
8131
8131
|
import { promises as fs4 } from "node:fs";
|
|
8132
8132
|
import { descriptions } from "@vultisig/client-shared";
|
|
8133
|
-
import { Chain as
|
|
8133
|
+
import { Chain as Chain15, parseKeygenQR, Vultisig as Vultisig6 } from "@vultisig/sdk";
|
|
8134
8134
|
import chalk16 from "chalk";
|
|
8135
8135
|
import { InvalidArgumentError, program as program2 } from "commander";
|
|
8136
8136
|
|
|
@@ -11487,7 +11487,7 @@ function resolveTxStatusParams(params) {
|
|
|
11487
11487
|
}
|
|
11488
11488
|
var POLL_INTERVAL_MS = 5e3;
|
|
11489
11489
|
var DEFAULT_TIMEOUT_SEC = 120;
|
|
11490
|
-
var isTerminal = (status) => status === "success" || status === "error";
|
|
11490
|
+
var isTerminal = (status) => status === "success" || status === "error" || status === "expired";
|
|
11491
11491
|
function resolveTimeoutMs(timeoutSec) {
|
|
11492
11492
|
if (typeof timeoutSec !== "number" || !Number.isFinite(timeoutSec)) {
|
|
11493
11493
|
return DEFAULT_TIMEOUT_SEC * 1e3;
|
|
@@ -11527,7 +11527,7 @@ async function executeTxStatus(ctx2, params, opts = {}) {
|
|
|
11527
11527
|
}
|
|
11528
11528
|
if (result.status === "success") {
|
|
11529
11529
|
recordResolution(params.txHash, "confirmed");
|
|
11530
|
-
} else if (result.status === "error") {
|
|
11530
|
+
} else if (result.status === "error" || result.status === "expired") {
|
|
11531
11531
|
recordResolution(params.txHash, "failed");
|
|
11532
11532
|
}
|
|
11533
11533
|
spinner.succeed(`Transaction status: ${toCliStatus(result.status)}`);
|
|
@@ -14046,9 +14046,104 @@ import { randomUUID } from "node:crypto";
|
|
|
14046
14046
|
// src/agent/toolOutputSigning.ts
|
|
14047
14047
|
import { getChainKind as getChainKind5 } from "@vultisig/sdk";
|
|
14048
14048
|
|
|
14049
|
+
// ../../packages/core/chain/dist/Chain.js
|
|
14050
|
+
var EthereumL2Chain = {
|
|
14051
|
+
Arbitrum: "Arbitrum",
|
|
14052
|
+
Base: "Base",
|
|
14053
|
+
Blast: "Blast",
|
|
14054
|
+
Optimism: "Optimism",
|
|
14055
|
+
Zksync: "Zksync",
|
|
14056
|
+
Mantle: "Mantle",
|
|
14057
|
+
Robinhood: "Robinhood"
|
|
14058
|
+
};
|
|
14059
|
+
var EvmChain = {
|
|
14060
|
+
...EthereumL2Chain,
|
|
14061
|
+
Avalanche: "Avalanche",
|
|
14062
|
+
CronosChain: "CronosChain",
|
|
14063
|
+
BSC: "BSC",
|
|
14064
|
+
Ethereum: "Ethereum",
|
|
14065
|
+
Polygon: "Polygon",
|
|
14066
|
+
Hyperliquid: "Hyperliquid",
|
|
14067
|
+
Sei: "Sei"
|
|
14068
|
+
};
|
|
14069
|
+
var UtxoChain;
|
|
14070
|
+
(function(UtxoChain2) {
|
|
14071
|
+
UtxoChain2["Bitcoin"] = "Bitcoin";
|
|
14072
|
+
UtxoChain2["BitcoinCash"] = "Bitcoin-Cash";
|
|
14073
|
+
UtxoChain2["Litecoin"] = "Litecoin";
|
|
14074
|
+
UtxoChain2["Dogecoin"] = "Dogecoin";
|
|
14075
|
+
UtxoChain2["Dash"] = "Dash";
|
|
14076
|
+
UtxoChain2["Zcash"] = "Zcash";
|
|
14077
|
+
})(UtxoChain || (UtxoChain = {}));
|
|
14078
|
+
var cosmosChainsByKind = {
|
|
14079
|
+
ibcEnabled: {
|
|
14080
|
+
Cosmos: "Cosmos",
|
|
14081
|
+
Osmosis: "Osmosis",
|
|
14082
|
+
Dydx: "Dydx",
|
|
14083
|
+
Terra: "Terra",
|
|
14084
|
+
TerraClassic: "TerraClassic",
|
|
14085
|
+
Noble: "Noble",
|
|
14086
|
+
Akash: "Akash"
|
|
14087
|
+
},
|
|
14088
|
+
vaultBased: {
|
|
14089
|
+
THORChain: "THORChain",
|
|
14090
|
+
MayaChain: "MayaChain"
|
|
14091
|
+
}
|
|
14092
|
+
};
|
|
14093
|
+
var IbcEnabledCosmosChain = cosmosChainsByKind.ibcEnabled;
|
|
14094
|
+
var VaultBasedCosmosChain = cosmosChainsByKind.vaultBased;
|
|
14095
|
+
var CosmosChain = {
|
|
14096
|
+
...IbcEnabledCosmosChain,
|
|
14097
|
+
...VaultBasedCosmosChain
|
|
14098
|
+
};
|
|
14099
|
+
var OtherChain;
|
|
14100
|
+
(function(OtherChain2) {
|
|
14101
|
+
OtherChain2["Sui"] = "Sui";
|
|
14102
|
+
OtherChain2["Solana"] = "Solana";
|
|
14103
|
+
OtherChain2["Polkadot"] = "Polkadot";
|
|
14104
|
+
OtherChain2["Bittensor"] = "Bittensor";
|
|
14105
|
+
OtherChain2["Ton"] = "Ton";
|
|
14106
|
+
OtherChain2["Ripple"] = "Ripple";
|
|
14107
|
+
OtherChain2["Tron"] = "Tron";
|
|
14108
|
+
OtherChain2["Cardano"] = "Cardano";
|
|
14109
|
+
OtherChain2["QBTC"] = "QBTC";
|
|
14110
|
+
})(OtherChain || (OtherChain = {}));
|
|
14111
|
+
var Chain10 = {
|
|
14112
|
+
...EvmChain,
|
|
14113
|
+
...UtxoChain,
|
|
14114
|
+
...CosmosChain,
|
|
14115
|
+
...OtherChain
|
|
14116
|
+
};
|
|
14117
|
+
var UtxoBasedChain = [...Object.values(UtxoChain), OtherChain.Cardano];
|
|
14118
|
+
var defaultChains = [Chain10.Bitcoin, Chain10.Ethereum, Chain10.THORChain, Chain10.Solana, Chain10.BSC];
|
|
14119
|
+
|
|
14120
|
+
// ../../packages/core/chain/dist/chains/evm/tx/fee/index.js
|
|
14121
|
+
var evmChainTxFeeFormat = {
|
|
14122
|
+
[EvmChain.Arbitrum]: "enveloped",
|
|
14123
|
+
[EvmChain.Base]: "enveloped",
|
|
14124
|
+
[EvmChain.Blast]: "enveloped",
|
|
14125
|
+
[EvmChain.Optimism]: "enveloped",
|
|
14126
|
+
[EvmChain.Zksync]: "enveloped",
|
|
14127
|
+
[EvmChain.Avalanche]: "enveloped",
|
|
14128
|
+
[EvmChain.CronosChain]: "enveloped",
|
|
14129
|
+
[EvmChain.BSC]: "legacy",
|
|
14130
|
+
[EvmChain.Ethereum]: "enveloped",
|
|
14131
|
+
[EvmChain.Polygon]: "enveloped",
|
|
14132
|
+
[EvmChain.Mantle]: "enveloped",
|
|
14133
|
+
[EvmChain.Hyperliquid]: "enveloped",
|
|
14134
|
+
// Sei must stay 'enveloped': iOS (EVMHelper.setGasParameters) and Android
|
|
14135
|
+
// (EthereumGasHelper.setGasParameters) sign every EVM chain except BSC as
|
|
14136
|
+
// EIP-1559. A different tx mode changes the pre-signing hash and therefore
|
|
14137
|
+
// the relay message_id, so extension<->mobile Sei co-signing deadlocks
|
|
14138
|
+
// (vultisig-windows#4369).
|
|
14139
|
+
[EvmChain.Sei]: "enveloped",
|
|
14140
|
+
[EvmChain.Robinhood]: "enveloped"
|
|
14141
|
+
};
|
|
14142
|
+
|
|
14049
14143
|
// src/agent/executor.ts
|
|
14050
14144
|
import {
|
|
14051
|
-
Chain as
|
|
14145
|
+
Chain as Chain12,
|
|
14146
|
+
clampEvmPriorityFee,
|
|
14052
14147
|
computeEip712Hash,
|
|
14053
14148
|
getChainKind as getChainKind4,
|
|
14054
14149
|
getEvmRpcUrl,
|
|
@@ -14220,7 +14315,7 @@ function sleep2(ms) {
|
|
|
14220
14315
|
|
|
14221
14316
|
// src/agent/hlOrder.ts
|
|
14222
14317
|
var import_msgpack = __toESM(require_dist(), 1);
|
|
14223
|
-
import { Chain as
|
|
14318
|
+
import { Chain as Chain11 } from "@vultisig/sdk";
|
|
14224
14319
|
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
14225
14320
|
var HL_AGENT_TYPES = {
|
|
14226
14321
|
Agent: [
|
|
@@ -14371,7 +14466,7 @@ async function validateRequestBinding(payload, expected, vault, now) {
|
|
|
14371
14466
|
if (typeof payload.owner_public_key !== "string") throw new Error("HL_INVALID_OWNER_PUBLIC_KEY");
|
|
14372
14467
|
if (payload.owner_public_key.toLowerCase() !== expected.publicKey.toLowerCase()) throw new Error("HL_OWNER_MISMATCH");
|
|
14373
14468
|
if (typeof payload.vault_address !== "string") throw new Error("HL_INVALID_VAULT_ADDRESS");
|
|
14374
|
-
const localAddress = await vault.address(
|
|
14469
|
+
const localAddress = await vault.address(Chain11.Ethereum);
|
|
14375
14470
|
if (payload.vault_address.toLowerCase() !== localAddress.toLowerCase()) throw new Error("HL_VAULT_ADDRESS_MISMATCH");
|
|
14376
14471
|
if (typeof payload.expires_at !== "string") throw new Error("HL_INVALID_EXPIRY");
|
|
14377
14472
|
const expiry = Date.parse(payload.expires_at);
|
|
@@ -14464,6 +14559,11 @@ var EVM_CHAINS = /* @__PURE__ */ new Set([
|
|
|
14464
14559
|
]);
|
|
14465
14560
|
var ERC20_TRANSFER_SELECTOR = "0xa9059cbb";
|
|
14466
14561
|
var ERC20_TRANSFER_ABI = parseAbi(["function transfer(address to, uint256 value)"]);
|
|
14562
|
+
var changedByMoreThanHalf = (before, after) => {
|
|
14563
|
+
if (before === after) return false;
|
|
14564
|
+
const difference = before > after ? before - after : after - before;
|
|
14565
|
+
return difference * 2n > before;
|
|
14566
|
+
};
|
|
14467
14567
|
function decodeErc20Transfer(calldata) {
|
|
14468
14568
|
if (calldata.slice(0, ERC20_TRANSFER_SELECTOR.length).toLowerCase() !== ERC20_TRANSFER_SELECTOR) return null;
|
|
14469
14569
|
try {
|
|
@@ -14709,12 +14809,12 @@ var AgentExecutor = class {
|
|
|
14709
14809
|
if (this.vault.isEncrypted && !this.vault.isUnlocked?.() && this.password) {
|
|
14710
14810
|
await this.vault.unlock?.(this.password);
|
|
14711
14811
|
}
|
|
14712
|
-
const expectedAddress = await this.vault.address(
|
|
14812
|
+
const expectedAddress = await this.vault.address(Chain12.Ethereum);
|
|
14713
14813
|
const signatures = [];
|
|
14714
14814
|
for (const step of payload.steps) {
|
|
14715
14815
|
const signed = await this.vault.signBytes({
|
|
14716
14816
|
data: step.digest,
|
|
14717
|
-
chain:
|
|
14817
|
+
chain: Chain12.Ethereum
|
|
14718
14818
|
});
|
|
14719
14819
|
const canonical = toCanonicalEvmSignature(signed.signature, signed.recovery ?? 0);
|
|
14720
14820
|
const v = canonical.recovery + 27;
|
|
@@ -14889,7 +14989,7 @@ var AgentExecutor = class {
|
|
|
14889
14989
|
if (!nestedTx && txReadyData && typeof txReadyData === "object") {
|
|
14890
14990
|
const txArgs = txReadyData.txArgs;
|
|
14891
14991
|
if (txArgs && typeof txArgs === "object" && typeof txArgs.to === "string" && typeof txArgs.amount === "string") {
|
|
14892
|
-
const chain2 = resolveChainFromTxReady(txReadyData) ||
|
|
14992
|
+
const chain2 = resolveChainFromTxReady(txReadyData) || Chain12.Ethereum;
|
|
14893
14993
|
if (getChainKind4(chain2) !== "evm") {
|
|
14894
14994
|
this.pendingPayloads.clear();
|
|
14895
14995
|
this.pendingLegs = [];
|
|
@@ -14914,7 +15014,7 @@ var AgentExecutor = class {
|
|
|
14914
15014
|
`);
|
|
14915
15015
|
return false;
|
|
14916
15016
|
}
|
|
14917
|
-
const chain = resolveChainFromTxReady(txReadyData) ||
|
|
15017
|
+
const chain = resolveChainFromTxReady(txReadyData) || Chain12.Ethereum;
|
|
14918
15018
|
this.pendingPayloads.clear();
|
|
14919
15019
|
this.pendingLegs = [];
|
|
14920
15020
|
this.pendingPayloads.set("latest", {
|
|
@@ -15572,8 +15672,9 @@ var AgentExecutor = class {
|
|
|
15572
15672
|
nonce: swapTx.nonce
|
|
15573
15673
|
}
|
|
15574
15674
|
});
|
|
15575
|
-
|
|
15675
|
+
const nonceGraceAge = Date.now() - (this.evmLastBroadcast.get(chain.toString()) ?? 0);
|
|
15576
15676
|
await this.patchEvmGas(chain, keysignPayload);
|
|
15677
|
+
await this.patchEvmNonce(chain, keysignPayload, nonceGraceAge);
|
|
15577
15678
|
const messageHashes = await this.vault.extractMessageHashes(keysignPayload);
|
|
15578
15679
|
const signature = await this.vault.sign(
|
|
15579
15680
|
{
|
|
@@ -15825,33 +15926,45 @@ var AgentExecutor = class {
|
|
|
15825
15926
|
}
|
|
15826
15927
|
}
|
|
15827
15928
|
/**
|
|
15828
|
-
*
|
|
15829
|
-
*
|
|
15830
|
-
*
|
|
15929
|
+
* Refresh the EVM nonce from pending RPC state, then patch it if our local state
|
|
15930
|
+
* is further ahead. Raw server envelopes may carry a nonce that became stale
|
|
15931
|
+
* before signing, so the RPC refresh must not depend on local state existing.
|
|
15831
15932
|
*
|
|
15832
15933
|
* Also detects evicted txs: if local state claims a higher nonce but there are
|
|
15833
15934
|
* no pending txs in the mempool (pending == latest), the intermediate txs were
|
|
15834
15935
|
* dropped and local state is stale.
|
|
15835
15936
|
*/
|
|
15836
|
-
async patchEvmNonce(chain, payload) {
|
|
15837
|
-
if (!
|
|
15937
|
+
async patchEvmNonce(chain, payload, capturedBroadcastAge) {
|
|
15938
|
+
if (!isEvmChain(chain)) return;
|
|
15838
15939
|
const bs = payload.blockchainSpecific;
|
|
15839
15940
|
if (!bs || bs.case !== "ethereumSpecific") return;
|
|
15840
|
-
const
|
|
15941
|
+
const recentBroadcastAge = capturedBroadcastAge ?? Date.now() - (this.evmLastBroadcast.get(chain.toString()) ?? 0);
|
|
15942
|
+
const hasRecentBroadcast = recentBroadcastAge < 3e4;
|
|
15943
|
+
const payloadNonce = bs.value.nonce;
|
|
15944
|
+
const latestNonce = this.stateStore && !hasRecentBroadcast ? await this.fetchEvmLatestNonce(chain) : null;
|
|
15945
|
+
const pendingNonce = await this.fetchEvmPendingNonce(chain);
|
|
15946
|
+
const rpcNonce = [payloadNonce, latestNonce, pendingNonce].reduce(
|
|
15947
|
+
(highest, nonce) => nonce !== null && nonce > highest ? nonce : highest,
|
|
15948
|
+
payloadNonce
|
|
15949
|
+
);
|
|
15950
|
+
if (rpcNonce !== payloadNonce) {
|
|
15951
|
+
bs.value.nonce = rpcNonce;
|
|
15952
|
+
if (this.verbose) process.stderr.write(`[nonce] Refreshed ${chain} nonce: ${payloadNonce} \u2192 ${rpcNonce}
|
|
15953
|
+
`);
|
|
15954
|
+
}
|
|
15955
|
+
if (!this.stateStore) return;
|
|
15841
15956
|
const nextNonce = this.stateStore.getNextEvmNonce(chain, rpcNonce);
|
|
15842
15957
|
if (nextNonce !== rpcNonce) {
|
|
15843
|
-
|
|
15844
|
-
if (Date.now() - lastBroadcast < 3e4) {
|
|
15958
|
+
if (hasRecentBroadcast) {
|
|
15845
15959
|
if (this.verbose)
|
|
15846
15960
|
process.stderr.write(
|
|
15847
|
-
`[nonce] Keeping local nonce ${nextNonce} for ${chain} (broadcast ${
|
|
15961
|
+
`[nonce] Keeping local nonce ${nextNonce} for ${chain} (broadcast ${recentBroadcastAge}ms ago)
|
|
15848
15962
|
`
|
|
15849
15963
|
);
|
|
15850
15964
|
bs.value.nonce = nextNonce;
|
|
15851
15965
|
return;
|
|
15852
15966
|
}
|
|
15853
|
-
|
|
15854
|
-
if (pendingNonce !== null && pendingNonce === rpcNonce) {
|
|
15967
|
+
if (latestNonce !== null && pendingNonce === latestNonce) {
|
|
15855
15968
|
if (this.verbose)
|
|
15856
15969
|
process.stderr.write(
|
|
15857
15970
|
`[nonce] Stale local state for ${chain}: local=${nextNonce}, on-chain=${rpcNonce}, no pending txs \u2014 using on-chain nonce
|
|
@@ -15861,7 +15974,8 @@ var AgentExecutor = class {
|
|
|
15861
15974
|
return;
|
|
15862
15975
|
}
|
|
15863
15976
|
const nonceGap = nextNonce - rpcNonce;
|
|
15864
|
-
|
|
15977
|
+
const pendingStateVerified = pendingNonce !== null && latestNonce !== null && pendingNonce >= latestNonce;
|
|
15978
|
+
if (!pendingStateVerified && nonceGap > 3n) {
|
|
15865
15979
|
process.stderr.write(
|
|
15866
15980
|
`[nonce] Warning: pending nonce was not verified for ${chain}; signing will continue with on-chain nonce ${rpcNonce} because the local gap is ${nonceGap}
|
|
15867
15981
|
`
|
|
@@ -15870,7 +15984,7 @@ var AgentExecutor = class {
|
|
|
15870
15984
|
return;
|
|
15871
15985
|
}
|
|
15872
15986
|
bs.value.nonce = nextNonce;
|
|
15873
|
-
if (
|
|
15987
|
+
if (!pendingStateVerified) {
|
|
15874
15988
|
process.stderr.write(
|
|
15875
15989
|
`[nonce] Warning: pending nonce was not verified for ${chain}; signing will continue with local nonce ${nextNonce}
|
|
15876
15990
|
`
|
|
@@ -15889,7 +16003,51 @@ var AgentExecutor = class {
|
|
|
15889
16003
|
if (!isEvmChain(chain)) return;
|
|
15890
16004
|
const bs = payload.blockchainSpecific;
|
|
15891
16005
|
if (!bs || bs.case !== "ethereumSpecific") return;
|
|
16006
|
+
const isEip1559 = evmChainTxFeeFormat[chain] === "enveloped";
|
|
16007
|
+
if (!isEip1559) return;
|
|
15892
16008
|
const rpcUrl = getEvmRpcUrl(chain);
|
|
16009
|
+
const currentPriorityFee = BigInt(bs.value.priorityFee || "0");
|
|
16010
|
+
const currentMaxFee = BigInt(bs.value.maxFeePerGasWei || "0");
|
|
16011
|
+
const baseFee = await this.fetchEvmBaseFee(chain, rpcUrl);
|
|
16012
|
+
let priorityFee = currentPriorityFee;
|
|
16013
|
+
if (currentPriorityFee > 0n) {
|
|
16014
|
+
priorityFee = clampEvmPriorityFee(chain, currentPriorityFee);
|
|
16015
|
+
if (priorityFee < currentPriorityFee) {
|
|
16016
|
+
process.stderr.write(
|
|
16017
|
+
`[gas] Warning: ${chain} maxPriorityFeePerGas ${currentPriorityFee} exceeded the safety ceiling; clamped to ${priorityFee}
|
|
16018
|
+
`
|
|
16019
|
+
);
|
|
16020
|
+
}
|
|
16021
|
+
} else {
|
|
16022
|
+
const rpcPriorityFee = await this.fetchEvmPriorityFee(rpcUrl);
|
|
16023
|
+
const baseFeeFallback = baseFee === null ? 0n : baseFee / 10n;
|
|
16024
|
+
const fallbackPriorityFee = baseFeeFallback < 2000000000n ? baseFeeFallback : 2000000000n;
|
|
16025
|
+
priorityFee = clampEvmPriorityFee(chain, rpcPriorityFee > 0n ? rpcPriorityFee : fallbackPriorityFee);
|
|
16026
|
+
}
|
|
16027
|
+
const minMaxFee = baseFee === null ? priorityFee : baseFee * 25n / 10n + priorityFee;
|
|
16028
|
+
const patchedMaxFee = currentMaxFee < minMaxFee ? minMaxFee : currentMaxFee;
|
|
16029
|
+
if (priorityFee !== currentPriorityFee) {
|
|
16030
|
+
bs.value.priorityFee = priorityFee.toString();
|
|
16031
|
+
if (this.verbose)
|
|
16032
|
+
process.stderr.write(`[gas] Patched ${chain} maxPriorityFeePerGas: ${currentPriorityFee} \u2192 ${priorityFee}
|
|
16033
|
+
`);
|
|
16034
|
+
}
|
|
16035
|
+
if (currentMaxFee < patchedMaxFee) {
|
|
16036
|
+
bs.value.maxFeePerGasWei = patchedMaxFee.toString();
|
|
16037
|
+
if (this.verbose)
|
|
16038
|
+
process.stderr.write(
|
|
16039
|
+
`[gas] Bumped ${chain} maxFeePerGas: ${currentMaxFee} \u2192 ${patchedMaxFee} (baseFee=${baseFee ?? "unavailable"})
|
|
16040
|
+
`
|
|
16041
|
+
);
|
|
16042
|
+
}
|
|
16043
|
+
if (changedByMoreThanHalf(currentPriorityFee, priorityFee) || changedByMoreThanHalf(currentMaxFee, patchedMaxFee)) {
|
|
16044
|
+
process.stderr.write(
|
|
16045
|
+
`[gas] Notice: ${chain} fees adjusted after confirmation: maxPriorityFeePerGas ${currentPriorityFee} \u2192 ${priorityFee}, maxFeePerGas ${currentMaxFee} \u2192 ${patchedMaxFee}
|
|
16046
|
+
`
|
|
16047
|
+
);
|
|
16048
|
+
}
|
|
16049
|
+
}
|
|
16050
|
+
async fetchEvmBaseFee(chain, rpcUrl) {
|
|
15893
16051
|
try {
|
|
15894
16052
|
const res = await fetch(rpcUrl, {
|
|
15895
16053
|
method: "POST",
|
|
@@ -15906,24 +16064,33 @@ var AgentExecutor = class {
|
|
|
15906
16064
|
if (!res.ok || data?.error || data?.result?.baseFeePerGas === void 0 || data?.result?.baseFeePerGas === null) {
|
|
15907
16065
|
throw new Error(`Failed to fetch current base fee for ${chain}`);
|
|
15908
16066
|
}
|
|
15909
|
-
|
|
15910
|
-
if (baseFee === 0n) return;
|
|
15911
|
-
const currentPriorityFee = BigInt(bs.value.priorityFee || "0");
|
|
15912
|
-
const currentMaxFee = BigInt(bs.value.maxFeePerGasWei || "0");
|
|
15913
|
-
const minMaxFee = baseFee * 25n / 10n + currentPriorityFee;
|
|
15914
|
-
if (currentMaxFee < minMaxFee) {
|
|
15915
|
-
bs.value.maxFeePerGasWei = minMaxFee.toString();
|
|
15916
|
-
if (this.verbose)
|
|
15917
|
-
process.stderr.write(
|
|
15918
|
-
`[gas] Bumped ${chain} maxFeePerGas: ${currentMaxFee} \u2192 ${minMaxFee} (baseFee=${baseFee})
|
|
15919
|
-
`
|
|
15920
|
-
);
|
|
15921
|
-
}
|
|
16067
|
+
return BigInt(data.result.baseFeePerGas);
|
|
15922
16068
|
} catch {
|
|
15923
16069
|
process.stderr.write(
|
|
15924
16070
|
`[gas] Warning: gas estimate was not refreshed for ${chain}; signing will continue with the original estimate
|
|
15925
16071
|
`
|
|
15926
16072
|
);
|
|
16073
|
+
return null;
|
|
16074
|
+
}
|
|
16075
|
+
}
|
|
16076
|
+
async fetchEvmPriorityFee(rpcUrl) {
|
|
16077
|
+
try {
|
|
16078
|
+
const res = await fetch(rpcUrl, {
|
|
16079
|
+
method: "POST",
|
|
16080
|
+
headers: { "Content-Type": "application/json" },
|
|
16081
|
+
body: JSON.stringify({
|
|
16082
|
+
jsonrpc: "2.0",
|
|
16083
|
+
method: "eth_maxPriorityFeePerGas",
|
|
16084
|
+
params: [],
|
|
16085
|
+
id: 2
|
|
16086
|
+
}),
|
|
16087
|
+
signal: AbortSignal.timeout(5e3)
|
|
16088
|
+
});
|
|
16089
|
+
const data = await res.json();
|
|
16090
|
+
if (!res.ok || data?.error || data?.result === void 0) return 0n;
|
|
16091
|
+
return BigInt(data.result);
|
|
16092
|
+
} catch {
|
|
16093
|
+
return 0n;
|
|
15927
16094
|
}
|
|
15928
16095
|
}
|
|
15929
16096
|
/**
|
|
@@ -15931,6 +16098,16 @@ var AgentExecutor = class {
|
|
|
15931
16098
|
* Returns null if the RPC call fails (non-fatal).
|
|
15932
16099
|
*/
|
|
15933
16100
|
async fetchEvmPendingNonce(chain) {
|
|
16101
|
+
return this.fetchEvmNonce(chain, "pending");
|
|
16102
|
+
}
|
|
16103
|
+
/**
|
|
16104
|
+
* Fetch the confirmed nonce from RPC (eth_getTransactionCount with "latest" tag).
|
|
16105
|
+
* Returns null if the RPC call fails (non-fatal).
|
|
16106
|
+
*/
|
|
16107
|
+
async fetchEvmLatestNonce(chain) {
|
|
16108
|
+
return this.fetchEvmNonce(chain, "latest");
|
|
16109
|
+
}
|
|
16110
|
+
async fetchEvmNonce(chain, blockTag) {
|
|
15934
16111
|
if (!isEvmChain(chain)) return null;
|
|
15935
16112
|
const rpcUrl = getEvmRpcUrl(chain);
|
|
15936
16113
|
try {
|
|
@@ -15941,7 +16118,7 @@ var AgentExecutor = class {
|
|
|
15941
16118
|
body: JSON.stringify({
|
|
15942
16119
|
jsonrpc: "2.0",
|
|
15943
16120
|
method: "eth_getTransactionCount",
|
|
15944
|
-
params: [address,
|
|
16121
|
+
params: [address, blockTag],
|
|
15945
16122
|
id: 1
|
|
15946
16123
|
}),
|
|
15947
16124
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -16041,11 +16218,11 @@ var AgentExecutor = class {
|
|
|
16041
16218
|
`);
|
|
16042
16219
|
const chainName = params.chain;
|
|
16043
16220
|
const chainId = domain.chainId;
|
|
16044
|
-
let chain =
|
|
16221
|
+
let chain = Chain12.Ethereum;
|
|
16045
16222
|
if (chainName) {
|
|
16046
|
-
chain = resolveChain(chainName) ||
|
|
16223
|
+
chain = resolveChain(chainName) || Chain12.Ethereum;
|
|
16047
16224
|
} else if (chainId) {
|
|
16048
|
-
chain = resolveChainId(chainId) ||
|
|
16225
|
+
chain = resolveChainId(chainId) || Chain12.Ethereum;
|
|
16049
16226
|
}
|
|
16050
16227
|
const sigResult = await this.vault.signBytes({
|
|
16051
16228
|
data: eip712Hash,
|
|
@@ -17379,7 +17556,9 @@ var PipeInterface = class {
|
|
|
17379
17556
|
session;
|
|
17380
17557
|
rl = null;
|
|
17381
17558
|
stopped = false;
|
|
17559
|
+
inputClosed = false;
|
|
17382
17560
|
pendingPasswordResolve = null;
|
|
17561
|
+
pendingPasswordReject = null;
|
|
17383
17562
|
pendingConfirmResolve = null;
|
|
17384
17563
|
constructor(session) {
|
|
17385
17564
|
this.session = session;
|
|
@@ -17411,38 +17590,45 @@ var PipeInterface = class {
|
|
|
17411
17590
|
}))
|
|
17412
17591
|
});
|
|
17413
17592
|
}
|
|
17414
|
-
const
|
|
17593
|
+
const commands = [];
|
|
17415
17594
|
let inputDone = false;
|
|
17416
17595
|
let processing = false;
|
|
17417
17596
|
this.rl.on("line", async (line) => {
|
|
17418
17597
|
const trimmed = line.trim();
|
|
17419
17598
|
if (!trimmed) return;
|
|
17420
|
-
|
|
17599
|
+
let cmd;
|
|
17600
|
+
try {
|
|
17601
|
+
cmd = JSON.parse(trimmed);
|
|
17602
|
+
} catch {
|
|
17603
|
+
this.emitInvalidInput("Malformed JSON input");
|
|
17604
|
+
return;
|
|
17605
|
+
}
|
|
17606
|
+
if (cmd?.type === "confirm" || cmd?.type === "password") {
|
|
17607
|
+
this.handleControlCommand(cmd);
|
|
17608
|
+
return;
|
|
17609
|
+
}
|
|
17610
|
+
commands.push(cmd);
|
|
17421
17611
|
if (!processing) {
|
|
17422
17612
|
processing = true;
|
|
17423
|
-
while (
|
|
17424
|
-
const
|
|
17613
|
+
while (commands.length > 0) {
|
|
17614
|
+
const nextCommand = commands.shift();
|
|
17425
17615
|
try {
|
|
17426
|
-
|
|
17427
|
-
await this.handleCommand(cmd);
|
|
17616
|
+
await this.handleCommand(nextCommand);
|
|
17428
17617
|
} catch (err) {
|
|
17429
|
-
|
|
17430
|
-
this.emit({
|
|
17431
|
-
type: "error",
|
|
17432
|
-
message: `Invalid input: ${message}`,
|
|
17433
|
-
code: code === "UNKNOWN_ERROR" /* UNKNOWN_ERROR */ ? "INVALID_INPUT" /* INVALID_INPUT */ : code
|
|
17434
|
-
});
|
|
17618
|
+
this.emitInvalidInput(err);
|
|
17435
17619
|
}
|
|
17436
17620
|
}
|
|
17437
17621
|
processing = false;
|
|
17438
|
-
if (inputDone &&
|
|
17622
|
+
if (inputDone && commands.length === 0) {
|
|
17439
17623
|
this.stop();
|
|
17440
17624
|
}
|
|
17441
17625
|
}
|
|
17442
17626
|
});
|
|
17443
17627
|
this.rl.on("close", () => {
|
|
17628
|
+
this.inputClosed = true;
|
|
17444
17629
|
inputDone = true;
|
|
17445
|
-
|
|
17630
|
+
this.settlePendingPrompts("Password input closed before a reply was received");
|
|
17631
|
+
if (!processing && commands.length === 0) {
|
|
17446
17632
|
this.stop();
|
|
17447
17633
|
}
|
|
17448
17634
|
});
|
|
@@ -17522,17 +17708,30 @@ var PipeInterface = class {
|
|
|
17522
17708
|
onDone: () => {
|
|
17523
17709
|
this.emit({ type: "done" });
|
|
17524
17710
|
},
|
|
17525
|
-
requestPassword:
|
|
17526
|
-
|
|
17711
|
+
requestPassword: () => {
|
|
17712
|
+
if (this.inputClosed) {
|
|
17713
|
+
const password2 = Promise.reject(
|
|
17714
|
+
Object.assign(new Error("Password input closed before a reply was received"), {
|
|
17715
|
+
code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */
|
|
17716
|
+
})
|
|
17717
|
+
);
|
|
17718
|
+
void password2.catch(() => void 0);
|
|
17719
|
+
return password2;
|
|
17720
|
+
}
|
|
17721
|
+
const password = new Promise((resolve, reject) => {
|
|
17527
17722
|
this.pendingPasswordResolve = resolve;
|
|
17723
|
+
this.pendingPasswordReject = reject;
|
|
17528
17724
|
this.emit({
|
|
17529
17725
|
type: "error",
|
|
17530
17726
|
message: "PASSWORD_REQUIRED",
|
|
17531
17727
|
code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */
|
|
17532
17728
|
});
|
|
17533
17729
|
});
|
|
17730
|
+
void password.catch(() => void 0);
|
|
17731
|
+
return password;
|
|
17534
17732
|
},
|
|
17535
17733
|
requestConfirmation: async (message) => {
|
|
17734
|
+
if (this.inputClosed) return false;
|
|
17536
17735
|
return new Promise((resolve) => {
|
|
17537
17736
|
this.pendingConfirmResolve = resolve;
|
|
17538
17737
|
this.emit({
|
|
@@ -17554,21 +17753,14 @@ var PipeInterface = class {
|
|
|
17554
17753
|
const { message, code } = normalizeAgentError(err);
|
|
17555
17754
|
this.emit({ type: "error", message, code });
|
|
17556
17755
|
this.emit({ type: "done" });
|
|
17756
|
+
} finally {
|
|
17757
|
+
this.settlePendingPrompts("Password request cancelled because the turn ended");
|
|
17557
17758
|
}
|
|
17558
17759
|
break;
|
|
17559
17760
|
}
|
|
17560
|
-
case "password":
|
|
17561
|
-
if (this.pendingPasswordResolve) {
|
|
17562
|
-
this.pendingPasswordResolve(cmd.password);
|
|
17563
|
-
this.pendingPasswordResolve = null;
|
|
17564
|
-
}
|
|
17565
|
-
break;
|
|
17566
|
-
}
|
|
17761
|
+
case "password":
|
|
17567
17762
|
case "confirm": {
|
|
17568
|
-
|
|
17569
|
-
this.pendingConfirmResolve(cmd.confirmed);
|
|
17570
|
-
this.pendingConfirmResolve = null;
|
|
17571
|
-
}
|
|
17763
|
+
this.handleControlCommand(cmd);
|
|
17572
17764
|
break;
|
|
17573
17765
|
}
|
|
17574
17766
|
default:
|
|
@@ -17579,6 +17771,54 @@ var PipeInterface = class {
|
|
|
17579
17771
|
});
|
|
17580
17772
|
}
|
|
17581
17773
|
}
|
|
17774
|
+
handleControlCommand(cmd) {
|
|
17775
|
+
if (cmd.type === "password") {
|
|
17776
|
+
if (!this.pendingPasswordResolve) {
|
|
17777
|
+
this.emitInvalidInput("No pending password request for this reply");
|
|
17778
|
+
return;
|
|
17779
|
+
}
|
|
17780
|
+
if (typeof cmd.password !== "string") {
|
|
17781
|
+
this.emitInvalidInput("Password reply must contain a string password");
|
|
17782
|
+
return;
|
|
17783
|
+
}
|
|
17784
|
+
const resolve2 = this.pendingPasswordResolve;
|
|
17785
|
+
this.pendingPasswordResolve = null;
|
|
17786
|
+
this.pendingPasswordReject = null;
|
|
17787
|
+
resolve2(cmd.password);
|
|
17788
|
+
return;
|
|
17789
|
+
}
|
|
17790
|
+
if (!this.pendingConfirmResolve) {
|
|
17791
|
+
this.emitInvalidInput("No pending confirmation for this reply");
|
|
17792
|
+
return;
|
|
17793
|
+
}
|
|
17794
|
+
if (cmd.confirmed !== true && cmd.confirmed !== false) {
|
|
17795
|
+
this.emitInvalidInput("Confirmation reply must contain a boolean confirmed value");
|
|
17796
|
+
return;
|
|
17797
|
+
}
|
|
17798
|
+
const resolve = this.pendingConfirmResolve;
|
|
17799
|
+
this.pendingConfirmResolve = null;
|
|
17800
|
+
resolve(cmd.confirmed === true);
|
|
17801
|
+
}
|
|
17802
|
+
settlePendingPrompts(passwordMessage) {
|
|
17803
|
+
const confirmResolve = this.pendingConfirmResolve;
|
|
17804
|
+
this.pendingConfirmResolve = null;
|
|
17805
|
+
confirmResolve?.(false);
|
|
17806
|
+
const passwordReject = this.pendingPasswordReject;
|
|
17807
|
+
this.pendingPasswordResolve = null;
|
|
17808
|
+
this.pendingPasswordReject = null;
|
|
17809
|
+
if (passwordReject) {
|
|
17810
|
+
const error2 = Object.assign(new Error(passwordMessage), { code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */ });
|
|
17811
|
+
passwordReject(error2);
|
|
17812
|
+
}
|
|
17813
|
+
}
|
|
17814
|
+
emitInvalidInput(err) {
|
|
17815
|
+
const { message, code } = normalizeAgentError(err);
|
|
17816
|
+
this.emit({
|
|
17817
|
+
type: "error",
|
|
17818
|
+
message: `Invalid input: ${message}`,
|
|
17819
|
+
code: code === "UNKNOWN_ERROR" /* UNKNOWN_ERROR */ ? "INVALID_INPUT" /* INVALID_INPUT */ : code
|
|
17820
|
+
});
|
|
17821
|
+
}
|
|
17582
17822
|
emit(event) {
|
|
17583
17823
|
process.stdout.write(JSON.stringify(event) + "\n");
|
|
17584
17824
|
}
|
|
@@ -18492,6 +18732,11 @@ var AgentSession = class {
|
|
|
18492
18732
|
recordResolution(txHash, "failed");
|
|
18493
18733
|
return;
|
|
18494
18734
|
}
|
|
18735
|
+
if (result.status === "expired") {
|
|
18736
|
+
ui.onTxStatus(txHash, chainName ?? "", "failed", explorerUrl);
|
|
18737
|
+
recordResolution(txHash, "failed");
|
|
18738
|
+
return;
|
|
18739
|
+
}
|
|
18495
18740
|
} catch (err) {
|
|
18496
18741
|
if (this.config.verbose) {
|
|
18497
18742
|
process.stderr.write(`[session] tx confirm poll ${attempt + 1} failed: ${err?.message ?? err}
|
|
@@ -19628,7 +19873,7 @@ var cachedVersion = null;
|
|
|
19628
19873
|
function getVersion() {
|
|
19629
19874
|
if (cachedVersion) return cachedVersion;
|
|
19630
19875
|
if (true) {
|
|
19631
|
-
cachedVersion = "
|
|
19876
|
+
cachedVersion = "7.2.0";
|
|
19632
19877
|
return cachedVersion;
|
|
19633
19878
|
}
|
|
19634
19879
|
try {
|
|
@@ -20125,7 +20370,7 @@ var EventBuffer = class {
|
|
|
20125
20370
|
};
|
|
20126
20371
|
|
|
20127
20372
|
// src/interactive/session.ts
|
|
20128
|
-
import { Chain as
|
|
20373
|
+
import { Chain as Chain14, fiatCurrencies as fiatCurrencies3 } from "@vultisig/sdk";
|
|
20129
20374
|
import chalk14 from "chalk";
|
|
20130
20375
|
import ora3 from "ora";
|
|
20131
20376
|
import * as readline3 from "readline";
|
|
@@ -20976,7 +21221,7 @@ Error: ${error2.message}`));
|
|
|
20976
21221
|
} else if (rest[i] === "--destination-tag") {
|
|
20977
21222
|
const tag = rest[i + 1];
|
|
20978
21223
|
const parsedTag = Number(tag);
|
|
20979
|
-
if (chain !==
|
|
21224
|
+
if (chain !== Chain14.Ripple || !/^(0|[1-9]\d*)$/.test(tag ?? "") || !Number.isSafeInteger(parsedTag) || parsedTag > 4294967295) {
|
|
20980
21225
|
throw new Error("Invalid XRP DestinationTag: expected an integer from 0 to 4294967295");
|
|
20981
21226
|
}
|
|
20982
21227
|
destinationTag = parsedTag;
|
|
@@ -21824,7 +22069,7 @@ See also: balance, tx-status`
|
|
|
21824
22069
|
if (!amount && !options.max) throw new Error("Provide an amount or use --max");
|
|
21825
22070
|
if (amount && options.max) throw new Error("Cannot specify both amount and --max");
|
|
21826
22071
|
const chain = resolveChainOrThrow(chainStr);
|
|
21827
|
-
if (options.destinationTag !== void 0 && chain !==
|
|
22072
|
+
if (options.destinationTag !== void 0 && chain !== Chain15.Ripple) {
|
|
21828
22073
|
throw new Error("--destination-tag is only supported for XRP");
|
|
21829
22074
|
}
|
|
21830
22075
|
const destinationTag = options.destinationTag === void 0 ? void 0 : Number(options.destinationTag);
|
|
@@ -21952,7 +22197,7 @@ program2.command("broadcast").description("Broadcast a pre-signed raw transactio
|
|
|
21952
22197
|
program2.command("tx-status").description("Check transaction status (polls until terminal or timeout)").requiredOption("--chain <chain>", "Target blockchain").requiredOption("--tx-hash <hash>", "Transaction hash to check").option("--no-wait", "Return immediately without waiting for confirmation").option("--timeout <seconds>", "Max seconds to poll before giving up (default 120)").addHelpText(
|
|
21953
22198
|
"after",
|
|
21954
22199
|
`
|
|
21955
|
-
Statuses: pending, not_found, confirmed, failed
|
|
22200
|
+
Statuses: pending, not_found, expired, confirmed, failed
|
|
21956
22201
|
Malformed hashes fail with INVALID_HASH (exit 4).
|
|
21957
22202
|
|
|
21958
22203
|
Examples:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "The self-custody MPC wallet CLI for AI coding agents (Claude Code, Cursor, OpenCode). Natural-language agent mode, 36+ chains, DKLS23 threshold signatures. Seedless.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -73,10 +73,10 @@
|
|
|
73
73
|
"@msgpack/msgpack": "^3.1.2",
|
|
74
74
|
"@napi-rs/keyring": "^1.3.0",
|
|
75
75
|
"@noble/hashes": "^2.2.0",
|
|
76
|
-
"@vultisig/client-shared": "^0.3.
|
|
77
|
-
"@vultisig/core-chain": "^
|
|
78
|
-
"@vultisig/rujira": "^
|
|
79
|
-
"@vultisig/sdk": "^
|
|
76
|
+
"@vultisig/client-shared": "^0.3.6",
|
|
77
|
+
"@vultisig/core-chain": "^5.2.0",
|
|
78
|
+
"@vultisig/rujira": "^71.0.0",
|
|
79
|
+
"@vultisig/sdk": "^7.2.0",
|
|
80
80
|
"chalk": "^5.6.2",
|
|
81
81
|
"cli-table3": "^0.6.5",
|
|
82
82
|
"commander": "^15.0.0",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"@types/node": "^26.1.1",
|
|
95
95
|
"@types/tabtab": "^3.0.4",
|
|
96
96
|
"@types/ws": "^8.18.1",
|
|
97
|
-
"@vultisig/core-mpc": "^
|
|
97
|
+
"@vultisig/core-mpc": "^3.1.0",
|
|
98
98
|
"esbuild": "^0.28.1",
|
|
99
99
|
"ethers": "^6.17.0",
|
|
100
100
|
"node-pty": "^1.1.0",
|