@vultisig/cli 6.2.0 → 7.0.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 +502 -109
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 7.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#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.
|
|
8
|
+
|
|
9
|
+
- [#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.
|
|
10
|
+
|
|
11
|
+
- [#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.
|
|
12
|
+
|
|
13
|
+
- [#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.
|
|
14
|
+
|
|
15
|
+
- [#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.
|
|
16
|
+
|
|
17
|
+
- 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)]:
|
|
18
|
+
- @vultisig/sdk@7.0.0
|
|
19
|
+
- @vultisig/core-chain@5.0.0
|
|
20
|
+
- @vultisig/rujira@71.0.0
|
|
21
|
+
- @vultisig/client-shared@0.3.6
|
|
22
|
+
|
|
23
|
+
## 6.3.0
|
|
24
|
+
|
|
25
|
+
### Patch Changes
|
|
26
|
+
|
|
27
|
+
- [#2202](https://github.com/vultisig/vultisig-sdk/pull/2202) [`2d90f80`](https://github.com/vultisig/vultisig-sdk/commit/2d90f803055e7c1325ab1dc1966e17431740cb1f) Thanks [@neavra](https://github.com/neavra)! - Derive swap sell-token contracts from signed approval payloads and mark unresolved contract disclosures explicitly.
|
|
28
|
+
|
|
29
|
+
- Updated dependencies [[`c0eafeb`](https://github.com/vultisig/vultisig-sdk/commit/c0eafeb12df42cffa70ef6951c081a74383e5fa2), [`b2f63b7`](https://github.com/vultisig/vultisig-sdk/commit/b2f63b70c4dac0001f0f40521efa4412f1d9e1cb), [`536c320`](https://github.com/vultisig/vultisig-sdk/commit/536c32028bf1f66897bf018c19f36c298545841a), [`78be14e`](https://github.com/vultisig/vultisig-sdk/commit/78be14ea9f1f011ded932ce6a9be5c19cf5694d0), [`76be65f`](https://github.com/vultisig/vultisig-sdk/commit/76be65fc297a43de6313b9dce3b096e6f764831a), [`e23780f`](https://github.com/vultisig/vultisig-sdk/commit/e23780f0b292cd76e80c72c5ccdcdafebd73a735), [`30499f8`](https://github.com/vultisig/vultisig-sdk/commit/30499f83f9909d8eb9bc1d310b25fdadb5c240e7), [`534154b`](https://github.com/vultisig/vultisig-sdk/commit/534154b6e9daaffad5d2e4958af3ead5fa940f21), [`3d40017`](https://github.com/vultisig/vultisig-sdk/commit/3d400171facf1107472e827c4ef48d7dd99843f1), [`c0c08f0`](https://github.com/vultisig/vultisig-sdk/commit/c0c08f0bd2337147d6b92ca7f391115edd7db62b), [`2869ae6`](https://github.com/vultisig/vultisig-sdk/commit/2869ae60bc157e2020a541e31a50afabef4e9edc), [`ef252e4`](https://github.com/vultisig/vultisig-sdk/commit/ef252e40b590a6cad9f303f7aba743c617442f90), [`4e23e92`](https://github.com/vultisig/vultisig-sdk/commit/4e23e9205310e46564bc1782b57499b2a39d7a5f), [`4561c65`](https://github.com/vultisig/vultisig-sdk/commit/4561c6584f62fa78d17546bcc119e31b6ea665cb), [`fc876a7`](https://github.com/vultisig/vultisig-sdk/commit/fc876a7fb561041539cb257a814d078304de6857), [`d08babd`](https://github.com/vultisig/vultisig-sdk/commit/d08babd96c36b193f8788605ed59871da1483ff3), [`4292e31`](https://github.com/vultisig/vultisig-sdk/commit/4292e3127e56bc2c92f2ac7b0a2886fcb0445043), [`d267ff6`](https://github.com/vultisig/vultisig-sdk/commit/d267ff66b9cf6d0b5898d40ec1f37cda6decb707), [`5f7dd00`](https://github.com/vultisig/vultisig-sdk/commit/5f7dd007cb5026d7c3ebe414fa5952f3419df570), [`bfe0292`](https://github.com/vultisig/vultisig-sdk/commit/bfe0292e3876fb7acc7044bac1b544c27aba8919), [`acd0b2e`](https://github.com/vultisig/vultisig-sdk/commit/acd0b2eaa882669a399fb378e51244ed4199ee47), [`f86320b`](https://github.com/vultisig/vultisig-sdk/commit/f86320bcfbee02b2f27473ac41a042db307596f6)]:
|
|
30
|
+
- @vultisig/core-chain@4.1.1
|
|
31
|
+
- @vultisig/sdk@6.3.0
|
|
32
|
+
|
|
3
33
|
## 6.2.0
|
|
4
34
|
|
|
5
35
|
### Minor 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
|
|
|
@@ -10610,32 +10610,6 @@ Use --add <contractAddress> to add or --remove <tokenId> to remove`));
|
|
|
10610
10610
|
}
|
|
10611
10611
|
}
|
|
10612
10612
|
|
|
10613
|
-
// ../../packages/core/chain/dist/chains/ripple/address.js
|
|
10614
|
-
import { classicAddressToXAddress, isValidXAddress, xAddressToClassicAddress } from "ripple-address-codec";
|
|
10615
|
-
var assertSupportedTag = (tag) => {
|
|
10616
|
-
if (tag === false)
|
|
10617
|
-
return void 0;
|
|
10618
|
-
return tag;
|
|
10619
|
-
};
|
|
10620
|
-
var decodeRippleXAddress = (address) => {
|
|
10621
|
-
const value = address.trim();
|
|
10622
|
-
if (!isValidXAddress(value))
|
|
10623
|
-
throw new Error("Invalid XRP X-address");
|
|
10624
|
-
const decoded = xAddressToClassicAddress(value);
|
|
10625
|
-
if (decoded.test)
|
|
10626
|
-
throw new Error("XRP testnet X-addresses are not supported");
|
|
10627
|
-
return {
|
|
10628
|
-
address: decoded.classicAddress,
|
|
10629
|
-
destinationTag: assertSupportedTag(decoded.tag)
|
|
10630
|
-
};
|
|
10631
|
-
};
|
|
10632
|
-
var normalizeRippleDestination = (address) => {
|
|
10633
|
-
const value = address.trim();
|
|
10634
|
-
if (value.startsWith("X") || value.startsWith("T"))
|
|
10635
|
-
return decodeRippleXAddress(value);
|
|
10636
|
-
return { address: value };
|
|
10637
|
-
};
|
|
10638
|
-
|
|
10639
10613
|
// ../../packages/core/mpc/dist/keysign/error.js
|
|
10640
10614
|
var BuildKeysignPayloadError = class extends Error {
|
|
10641
10615
|
type;
|
|
@@ -10667,7 +10641,7 @@ var resolveDestinationTag = ({ destinationTag, memo }) => {
|
|
|
10667
10641
|
};
|
|
10668
10642
|
|
|
10669
10643
|
// src/commands/transaction.ts
|
|
10670
|
-
import { Chain as Chain3, Vultisig as Vultisig2 } from "@vultisig/sdk";
|
|
10644
|
+
import { Chain as Chain3, normalizeRippleDestination, Vultisig as Vultisig2 } from "@vultisig/sdk";
|
|
10671
10645
|
var getSendPreviewDetails = (chain, keysignPayload) => {
|
|
10672
10646
|
let memo = keysignPayload.memo || void 0;
|
|
10673
10647
|
if (chain !== Chain3.Ripple) {
|
|
@@ -11513,7 +11487,7 @@ function resolveTxStatusParams(params) {
|
|
|
11513
11487
|
}
|
|
11514
11488
|
var POLL_INTERVAL_MS = 5e3;
|
|
11515
11489
|
var DEFAULT_TIMEOUT_SEC = 120;
|
|
11516
|
-
var isTerminal = (status) => status === "success" || status === "error";
|
|
11490
|
+
var isTerminal = (status) => status === "success" || status === "error" || status === "expired";
|
|
11517
11491
|
function resolveTimeoutMs(timeoutSec) {
|
|
11518
11492
|
if (typeof timeoutSec !== "number" || !Number.isFinite(timeoutSec)) {
|
|
11519
11493
|
return DEFAULT_TIMEOUT_SEC * 1e3;
|
|
@@ -11553,7 +11527,7 @@ async function executeTxStatus(ctx2, params, opts = {}) {
|
|
|
11553
11527
|
}
|
|
11554
11528
|
if (result.status === "success") {
|
|
11555
11529
|
recordResolution(params.txHash, "confirmed");
|
|
11556
|
-
} else if (result.status === "error") {
|
|
11530
|
+
} else if (result.status === "error" || result.status === "expired") {
|
|
11557
11531
|
recordResolution(params.txHash, "failed");
|
|
11558
11532
|
}
|
|
11559
11533
|
spinner.succeed(`Transaction status: ${toCliStatus(result.status)}`);
|
|
@@ -14072,9 +14046,104 @@ import { randomUUID } from "node:crypto";
|
|
|
14072
14046
|
// src/agent/toolOutputSigning.ts
|
|
14073
14047
|
import { getChainKind as getChainKind5 } from "@vultisig/sdk";
|
|
14074
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
|
+
|
|
14075
14143
|
// src/agent/executor.ts
|
|
14076
14144
|
import {
|
|
14077
|
-
Chain as
|
|
14145
|
+
Chain as Chain12,
|
|
14146
|
+
clampEvmPriorityFee,
|
|
14078
14147
|
computeEip712Hash,
|
|
14079
14148
|
getChainKind as getChainKind4,
|
|
14080
14149
|
getEvmRpcUrl,
|
|
@@ -14246,7 +14315,7 @@ function sleep2(ms) {
|
|
|
14246
14315
|
|
|
14247
14316
|
// src/agent/hlOrder.ts
|
|
14248
14317
|
var import_msgpack = __toESM(require_dist(), 1);
|
|
14249
|
-
import { Chain as
|
|
14318
|
+
import { Chain as Chain11 } from "@vultisig/sdk";
|
|
14250
14319
|
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
14251
14320
|
var HL_AGENT_TYPES = {
|
|
14252
14321
|
Agent: [
|
|
@@ -14397,7 +14466,7 @@ async function validateRequestBinding(payload, expected, vault, now) {
|
|
|
14397
14466
|
if (typeof payload.owner_public_key !== "string") throw new Error("HL_INVALID_OWNER_PUBLIC_KEY");
|
|
14398
14467
|
if (payload.owner_public_key.toLowerCase() !== expected.publicKey.toLowerCase()) throw new Error("HL_OWNER_MISMATCH");
|
|
14399
14468
|
if (typeof payload.vault_address !== "string") throw new Error("HL_INVALID_VAULT_ADDRESS");
|
|
14400
|
-
const localAddress = await vault.address(
|
|
14469
|
+
const localAddress = await vault.address(Chain11.Ethereum);
|
|
14401
14470
|
if (payload.vault_address.toLowerCase() !== localAddress.toLowerCase()) throw new Error("HL_VAULT_ADDRESS_MISMATCH");
|
|
14402
14471
|
if (typeof payload.expires_at !== "string") throw new Error("HL_INVALID_EXPIRY");
|
|
14403
14472
|
const expiry = Date.parse(payload.expires_at);
|
|
@@ -14490,16 +14559,185 @@ var EVM_CHAINS = /* @__PURE__ */ new Set([
|
|
|
14490
14559
|
]);
|
|
14491
14560
|
var ERC20_TRANSFER_SELECTOR = "0xa9059cbb";
|
|
14492
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
|
+
};
|
|
14493
14567
|
function decodeErc20Transfer(calldata) {
|
|
14494
14568
|
if (calldata.slice(0, ERC20_TRANSFER_SELECTOR.length).toLowerCase() !== ERC20_TRANSFER_SELECTOR) return null;
|
|
14495
14569
|
try {
|
|
14496
|
-
const decoded = decodeFunctionData({
|
|
14570
|
+
const decoded = decodeFunctionData({
|
|
14571
|
+
abi: ERC20_TRANSFER_ABI,
|
|
14572
|
+
data: calldata
|
|
14573
|
+
});
|
|
14497
14574
|
const [recipient, amount] = decoded.args;
|
|
14498
14575
|
return { recipient, amount };
|
|
14499
14576
|
} catch {
|
|
14500
14577
|
throw new Error("Invalid ERC-20 transfer calldata \u2014 refusing to sign");
|
|
14501
14578
|
}
|
|
14502
14579
|
}
|
|
14580
|
+
var tokenLabel = (value) => typeof value === "string" ? value : "";
|
|
14581
|
+
var MAX_TOKEN_SYMBOL_LENGTH = 32;
|
|
14582
|
+
var MAX_TOKEN_LABEL_LENGTH = 512;
|
|
14583
|
+
function safeTokenSymbol(symbol) {
|
|
14584
|
+
const defaultDisplaySymbol = symbol.match(/^[\p{L}\p{N}][\p{L}\p{N}._+-]{0,31}/u)?.[0] ?? "token";
|
|
14585
|
+
if (symbol.length > MAX_TOKEN_SYMBOL_LENGTH) {
|
|
14586
|
+
return { displaySymbol: defaultDisplaySymbol, suspicious: true };
|
|
14587
|
+
}
|
|
14588
|
+
const suspiciousAt = symbol.search(/0x[0-9a-f]{40}|\([^)]*\bon\b[^)]*\)/iu);
|
|
14589
|
+
const candidate = (suspiciousAt < 0 ? symbol : symbol.slice(0, suspiciousAt)).trim();
|
|
14590
|
+
const displaySymbol = candidate.match(/^[\p{L}\p{N}][\p{L}\p{N}._+-]*/u)?.[0] ?? "token";
|
|
14591
|
+
if (suspiciousAt < 0 && candidate === displaySymbol) {
|
|
14592
|
+
return { displaySymbol, suspicious: false };
|
|
14593
|
+
}
|
|
14594
|
+
return { displaySymbol, suspicious: true };
|
|
14595
|
+
}
|
|
14596
|
+
function unresolvedTokenIdentity(label) {
|
|
14597
|
+
if (typeof label !== "string" || label.length > MAX_TOKEN_LABEL_LENGTH) {
|
|
14598
|
+
return { rawSymbol: "", displaySymbol: "", kind: "unresolved" };
|
|
14599
|
+
}
|
|
14600
|
+
const suffixAt = label.lastIndexOf(" (");
|
|
14601
|
+
const rawSymbol = (suffixAt > 0 ? label.slice(0, suffixAt) : label).trim();
|
|
14602
|
+
return {
|
|
14603
|
+
rawSymbol,
|
|
14604
|
+
displaySymbol: safeTokenSymbol(rawSymbol).displaySymbol,
|
|
14605
|
+
kind: "unresolved"
|
|
14606
|
+
};
|
|
14607
|
+
}
|
|
14608
|
+
function untrustedSymbolIdentity(symbol) {
|
|
14609
|
+
const rawSymbol = tokenLabel(symbol);
|
|
14610
|
+
return {
|
|
14611
|
+
rawSymbol,
|
|
14612
|
+
displaySymbol: safeTokenSymbol(rawSymbol).displaySymbol,
|
|
14613
|
+
kind: "unresolved"
|
|
14614
|
+
};
|
|
14615
|
+
}
|
|
14616
|
+
function resolvedTokenIdentity(label, expectedChain) {
|
|
14617
|
+
const unresolved = unresolvedTokenIdentity(label);
|
|
14618
|
+
if (typeof label !== "string" || label.length > MAX_TOKEN_LABEL_LENGTH) return unresolved;
|
|
14619
|
+
const match = label.match(/^([\s\S]*) \(([\s\S]*?) on ([^,]+), \d+ dec, source: [^)]+\)$/u);
|
|
14620
|
+
if (!match) return unresolved;
|
|
14621
|
+
const [, rawSymbol, rawAssetId, descriptorChain] = match;
|
|
14622
|
+
const { displaySymbol, suspicious } = safeTokenSymbol(rawSymbol);
|
|
14623
|
+
const parsedChain = resolveChainReference(descriptorChain);
|
|
14624
|
+
const routedChain = typeof expectedChain === "string" || typeof expectedChain === "number" ? resolveChainReference(expectedChain) : void 0;
|
|
14625
|
+
if (suspicious || !parsedChain || !routedChain || parsedChain !== routedChain) {
|
|
14626
|
+
return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14627
|
+
}
|
|
14628
|
+
const assetId = rawAssetId.trim();
|
|
14629
|
+
if (!assetId) return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14630
|
+
if (assetId.toLowerCase() === "native") return { rawSymbol, displaySymbol, kind: "native" };
|
|
14631
|
+
if (getChainKind4(routedChain) === "evm") {
|
|
14632
|
+
if (!/^0x[0-9a-f]{40}$/iu.test(assetId)) return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14633
|
+
} else if (!/^[\p{L}\p{N}:._/-]{1,128}$/u.test(assetId)) {
|
|
14634
|
+
return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14635
|
+
}
|
|
14636
|
+
return { rawSymbol, displaySymbol, kind: "token", contract: assetId };
|
|
14637
|
+
}
|
|
14638
|
+
function replaceUnsafeSymbol(text, identity) {
|
|
14639
|
+
if (!identity.rawSymbol || identity.rawSymbol === identity.displaySymbol) return text;
|
|
14640
|
+
return text.split(identity.rawSymbol).join(identity.displaySymbol);
|
|
14641
|
+
}
|
|
14642
|
+
function anchorEnd(text, label) {
|
|
14643
|
+
if (!label) return -1;
|
|
14644
|
+
const tokenChar = /[\p{L}\p{N}._+-]/u;
|
|
14645
|
+
const trimmedLength = text.trimEnd().length;
|
|
14646
|
+
const index = trimmedLength - label.length;
|
|
14647
|
+
if (index < 0 || !text.startsWith(label, index)) return -1;
|
|
14648
|
+
const before = text[index - 1];
|
|
14649
|
+
if (before && tokenChar.test(before)) return -1;
|
|
14650
|
+
return trimmedLength;
|
|
14651
|
+
}
|
|
14652
|
+
function hasAnchor(text, anchors) {
|
|
14653
|
+
return anchors.some((anchor) => anchorEnd(text, anchor) >= 0);
|
|
14654
|
+
}
|
|
14655
|
+
function hasSingleSwapDelimiter(summary, labels) {
|
|
14656
|
+
const identities = [
|
|
14657
|
+
unresolvedTokenIdentity(labels.from_token),
|
|
14658
|
+
untrustedSymbolIdentity(labels.from_token_symbol),
|
|
14659
|
+
unresolvedTokenIdentity(labels.to_token),
|
|
14660
|
+
untrustedSymbolIdentity(labels.to_token_symbol)
|
|
14661
|
+
];
|
|
14662
|
+
const structuralSummary = identities.reduce((text, identity) => replaceUnsafeSymbol(text, identity), summary);
|
|
14663
|
+
const firstArrow = structuralSummary.indexOf("\u2192");
|
|
14664
|
+
return firstArrow >= 0 && structuralSummary.indexOf("\u2192", firstArrow + 1) < 0;
|
|
14665
|
+
}
|
|
14666
|
+
function splitSwapHead(head, sellAnchors, buyAnchors) {
|
|
14667
|
+
let best;
|
|
14668
|
+
let arrowAt = head.indexOf("\u2192");
|
|
14669
|
+
while (arrowAt >= 0) {
|
|
14670
|
+
const left = head.slice(0, arrowAt);
|
|
14671
|
+
const right = head.slice(arrowAt + 1);
|
|
14672
|
+
const viaAt = right.indexOf(" via ");
|
|
14673
|
+
const buy = viaAt >= 0 ? right.slice(0, viaAt) : right;
|
|
14674
|
+
const provider = viaAt >= 0 ? right.slice(viaAt) : "";
|
|
14675
|
+
const score = Number(hasAnchor(left, sellAnchors)) + Number(hasAnchor(buy, buyAnchors));
|
|
14676
|
+
if (!best || score > best.score) {
|
|
14677
|
+
best = { left, buy, provider, score };
|
|
14678
|
+
}
|
|
14679
|
+
arrowAt = head.indexOf("\u2192", arrowAt + 1);
|
|
14680
|
+
}
|
|
14681
|
+
return best;
|
|
14682
|
+
}
|
|
14683
|
+
function terminalAnchorSymbol(anchor) {
|
|
14684
|
+
return anchor.trim().match(/[\p{L}\p{N}][\p{L}\p{N}._+-]*$/u)?.[0] ?? "";
|
|
14685
|
+
}
|
|
14686
|
+
function discloseSwapSide(side, anchors, suffix, expectedSymbol) {
|
|
14687
|
+
if (!expectedSymbol) {
|
|
14688
|
+
return `${side.trimEnd()} (contract unavailable)${side.slice(side.trimEnd().length)}`;
|
|
14689
|
+
}
|
|
14690
|
+
for (const anchor of anchors) {
|
|
14691
|
+
const end = anchorEnd(side, anchor);
|
|
14692
|
+
if (end < 0) continue;
|
|
14693
|
+
const visibleSymbol = terminalAnchorSymbol(anchor);
|
|
14694
|
+
if (expectedSymbol && visibleSymbol && visibleSymbol !== expectedSymbol) break;
|
|
14695
|
+
if (!suffix) return side;
|
|
14696
|
+
return `${side.slice(0, end)}${suffix}${side.slice(end)}`;
|
|
14697
|
+
}
|
|
14698
|
+
return `${side.trimEnd()} (contract unavailable)${side.slice(side.trimEnd().length)}`;
|
|
14699
|
+
}
|
|
14700
|
+
function discloseSwapTokenContracts(head, labels, payload, sourceChain) {
|
|
14701
|
+
const destinationChain = Object.hasOwn(labels, "to_chain") ? labels.to_chain ?? null : typeof payload?.to_chain === "string" || typeof payload?.to_chain === "number" ? payload.to_chain : void 0;
|
|
14702
|
+
const fromToken = resolvedTokenIdentity(labels.from_token, sourceChain);
|
|
14703
|
+
const toToken = resolvedTokenIdentity(labels.to_token, destinationChain);
|
|
14704
|
+
const fromSymbol = untrustedSymbolIdentity(labels.from_token_symbol);
|
|
14705
|
+
const toSymbol = untrustedSymbolIdentity(labels.to_token_symbol);
|
|
14706
|
+
const approvalArgs = payload?.approvalTxArgs;
|
|
14707
|
+
const rawApprovalTarget = tokenLabel(
|
|
14708
|
+
approvalArgs && typeof approvalArgs === "object" ? approvalArgs.tx?.to : void 0
|
|
14709
|
+
);
|
|
14710
|
+
const approvalTarget = /^0x[0-9a-f]{40}$/iu.test(rawApprovalTarget) ? rawApprovalTarget : "";
|
|
14711
|
+
const symbolIdentities = [fromToken, fromSymbol, toToken, toSymbol];
|
|
14712
|
+
const sanitizeText = (value) => symbolIdentities.reduce((text, identity) => replaceUnsafeSymbol(text, identity), tokenLabel(value));
|
|
14713
|
+
const sanitizedHead = sanitizeText(head);
|
|
14714
|
+
const sellAnchors = [sanitizeText(labels.amount_in), fromSymbol.displaySymbol, fromToken.displaySymbol].filter(
|
|
14715
|
+
Boolean
|
|
14716
|
+
);
|
|
14717
|
+
const buyAnchors = [sanitizeText(labels.expected_output), toSymbol.displaySymbol, toToken.displaySymbol].filter(
|
|
14718
|
+
Boolean
|
|
14719
|
+
);
|
|
14720
|
+
const approvalMatchesResolvedSellToken = fromToken.kind === "token" && !!fromToken.contract && !!approvalTarget && fromToken.contract.toLowerCase() === approvalTarget.toLowerCase();
|
|
14721
|
+
const sellSuffix = payload?.approvalTxArgs ? approvalMatchesResolvedSellToken ? ` (${approvalTarget})` : " (contract unavailable)" : fromToken.kind === "native" ? "" : fromToken.kind === "token" && fromToken.contract ? ` (${fromToken.contract})` : " (contract unavailable)";
|
|
14722
|
+
const buySuffix = toToken.kind === "native" ? "" : toToken.kind === "token" && toToken.contract ? ` (${toToken.contract})` : " (contract unavailable)";
|
|
14723
|
+
const halves = splitSwapHead(sanitizedHead, sellAnchors, buyAnchors);
|
|
14724
|
+
if (!halves) return `${sanitizedHead} (contract unavailable)`;
|
|
14725
|
+
const sellResolved = fromToken.kind !== "unresolved";
|
|
14726
|
+
const buyResolved = toToken.kind !== "unresolved";
|
|
14727
|
+
const sell = discloseSwapSide(
|
|
14728
|
+
halves.left,
|
|
14729
|
+
sellAnchors,
|
|
14730
|
+
sellResolved ? sellSuffix : "",
|
|
14731
|
+
sellResolved ? fromToken.displaySymbol : void 0
|
|
14732
|
+
);
|
|
14733
|
+
const buy = discloseSwapSide(
|
|
14734
|
+
halves.buy,
|
|
14735
|
+
buyAnchors,
|
|
14736
|
+
buyResolved ? buySuffix : "",
|
|
14737
|
+
buyResolved ? toToken.displaySymbol : void 0
|
|
14738
|
+
);
|
|
14739
|
+
return `${sell}\u2192${buy}${halves.provider}`;
|
|
14740
|
+
}
|
|
14503
14741
|
var isEvmChain = (chain) => EVM_CHAINS.has(chain);
|
|
14504
14742
|
function stripEmbeddedPayloadContract(value, disclosedContract) {
|
|
14505
14743
|
if (!disclosedContract) return value;
|
|
@@ -14571,12 +14809,12 @@ var AgentExecutor = class {
|
|
|
14571
14809
|
if (this.vault.isEncrypted && !this.vault.isUnlocked?.() && this.password) {
|
|
14572
14810
|
await this.vault.unlock?.(this.password);
|
|
14573
14811
|
}
|
|
14574
|
-
const expectedAddress = await this.vault.address(
|
|
14812
|
+
const expectedAddress = await this.vault.address(Chain12.Ethereum);
|
|
14575
14813
|
const signatures = [];
|
|
14576
14814
|
for (const step of payload.steps) {
|
|
14577
14815
|
const signed = await this.vault.signBytes({
|
|
14578
14816
|
data: step.digest,
|
|
14579
|
-
chain:
|
|
14817
|
+
chain: Chain12.Ethereum
|
|
14580
14818
|
});
|
|
14581
14819
|
const canonical = toCanonicalEvmSignature(signed.signature, signed.recovery ?? 0);
|
|
14582
14820
|
const v = canonical.recovery + 27;
|
|
@@ -14751,7 +14989,7 @@ var AgentExecutor = class {
|
|
|
14751
14989
|
if (!nestedTx && txReadyData && typeof txReadyData === "object") {
|
|
14752
14990
|
const txArgs = txReadyData.txArgs;
|
|
14753
14991
|
if (txArgs && typeof txArgs === "object" && typeof txArgs.to === "string" && typeof txArgs.amount === "string") {
|
|
14754
|
-
const chain2 = resolveChainFromTxReady(txReadyData) ||
|
|
14992
|
+
const chain2 = resolveChainFromTxReady(txReadyData) || Chain12.Ethereum;
|
|
14755
14993
|
if (getChainKind4(chain2) !== "evm") {
|
|
14756
14994
|
this.pendingPayloads.clear();
|
|
14757
14995
|
this.pendingLegs = [];
|
|
@@ -14776,7 +15014,7 @@ var AgentExecutor = class {
|
|
|
14776
15014
|
`);
|
|
14777
15015
|
return false;
|
|
14778
15016
|
}
|
|
14779
|
-
const chain = resolveChainFromTxReady(txReadyData) ||
|
|
15017
|
+
const chain = resolveChainFromTxReady(txReadyData) || Chain12.Ethereum;
|
|
14780
15018
|
this.pendingPayloads.clear();
|
|
14781
15019
|
this.pendingLegs = [];
|
|
14782
15020
|
this.pendingPayloads.set("latest", {
|
|
@@ -14885,12 +15123,22 @@ var AgentExecutor = class {
|
|
|
14885
15123
|
}
|
|
14886
15124
|
const isSwap = !!(p?.approvalTxArgs || p?.swap_tx || labels.quote_summary || labels.to_token_symbol);
|
|
14887
15125
|
if (isSwap) {
|
|
14888
|
-
const
|
|
14889
|
-
const
|
|
15126
|
+
const rawQuoteSummary = tokenLabel(labels.quote_summary);
|
|
15127
|
+
const quoteSummary = hasSingleSwapDelimiter(rawQuoteSummary, labels) ? rawQuoteSummary : "";
|
|
15128
|
+
const usedQuoteSummary = !!quoteSummary;
|
|
15129
|
+
const amountIn = tokenLabel(labels.amount_in) || tokenLabel(p?.txArgs?.amount) || "?";
|
|
15130
|
+
const fromSymbol = tokenLabel(labels.from_token_symbol);
|
|
15131
|
+
const sellHead = fromSymbol && !amountIn.endsWith(` ${fromSymbol}`) ? `${amountIn} ${fromSymbol}` : amountIn;
|
|
15132
|
+
const head = discloseSwapTokenContracts(
|
|
15133
|
+
quoteSummary || `swap ${sellHead} \u2192 ${tokenLabel(labels.to_token_symbol) || "?"}`,
|
|
15134
|
+
labels,
|
|
15135
|
+
p,
|
|
15136
|
+
stored.chain
|
|
15137
|
+
);
|
|
14890
15138
|
const parts = [head, `on ${stored.chain}`];
|
|
14891
|
-
if (!usedQuoteSummary && labels.provider) parts.push(`via ${labels.provider}`);
|
|
15139
|
+
if (!usedQuoteSummary && tokenLabel(labels.provider)) parts.push(`via ${tokenLabel(labels.provider)}`);
|
|
14892
15140
|
if (p?.__multiLeg) parts.push("(+ token approval \u2014 2 transactions)");
|
|
14893
|
-
if (labels.estimated_fee) parts.push(`est. fee ${labels.estimated_fee}`);
|
|
15141
|
+
if (tokenLabel(labels.estimated_fee)) parts.push(`est. fee ${tokenLabel(labels.estimated_fee)}`);
|
|
14894
15142
|
return parts.join(" ");
|
|
14895
15143
|
}
|
|
14896
15144
|
const signedTx = extractNestedTx(p);
|
|
@@ -14914,18 +15162,18 @@ var AgentExecutor = class {
|
|
|
14914
15162
|
*/
|
|
14915
15163
|
renderLabelSendSummary(p, labels, chain, to, disclosedContract) {
|
|
14916
15164
|
const amount = stripEmbeddedPayloadContract(labels.resolved_amount ?? p?.txArgs?.amount ?? "?", disclosedContract);
|
|
14917
|
-
const
|
|
15165
|
+
const tokenLabel2 = stripEmbeddedPayloadContract(
|
|
14918
15166
|
(labels.token_resolved || labels.token_symbol || "").trim(),
|
|
14919
15167
|
disclosedContract
|
|
14920
15168
|
);
|
|
14921
|
-
const symbol =
|
|
15169
|
+
const symbol = tokenLabel2.split(/\s+/, 1)[0];
|
|
14922
15170
|
const escapedChain = String(chain).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14923
15171
|
const routedChainPattern = new RegExp(`(?:^|\\s)(?:not\\s+)?on ${escapedChain}(?=\\s|$)`);
|
|
14924
15172
|
const positiveRoutedChainPattern = new RegExp(`(?:^|\\s)(?<!\\bnot\\s+)on ${escapedChain}(?=\\s|$)`);
|
|
14925
|
-
const tokenContext =
|
|
15173
|
+
const tokenContext = tokenLabel2.slice(symbol.length);
|
|
14926
15174
|
const labelCarriesRoutedChain = positiveRoutedChainPattern.test(tokenContext);
|
|
14927
15175
|
const tokenDetail = tokenContext.replace(routedChainPattern, "").trim();
|
|
14928
|
-
const amountEmbedsTokenLabel =
|
|
15176
|
+
const amountEmbedsTokenLabel = tokenLabel2.length > 0 && amount.endsWith(` ${tokenLabel2}`);
|
|
14929
15177
|
const amountWithSymbol = symbol && !amount.endsWith(` ${symbol}`) && !amountEmbedsTokenLabel ? `${amount} ${symbol}` : amount;
|
|
14930
15178
|
const tokenDetailSuffix = amountEmbedsTokenLabel || !tokenDetail ? "" : ` ${tokenDetail}`;
|
|
14931
15179
|
const location = amountEmbedsTokenLabel && labelCarriesRoutedChain ? "" : `on ${chain}${tokenDetailSuffix}`;
|
|
@@ -15424,8 +15672,9 @@ var AgentExecutor = class {
|
|
|
15424
15672
|
nonce: swapTx.nonce
|
|
15425
15673
|
}
|
|
15426
15674
|
});
|
|
15427
|
-
|
|
15675
|
+
const nonceGraceAge = Date.now() - (this.evmLastBroadcast.get(chain.toString()) ?? 0);
|
|
15428
15676
|
await this.patchEvmGas(chain, keysignPayload);
|
|
15677
|
+
await this.patchEvmNonce(chain, keysignPayload, nonceGraceAge);
|
|
15429
15678
|
const messageHashes = await this.vault.extractMessageHashes(keysignPayload);
|
|
15430
15679
|
const signature = await this.vault.sign(
|
|
15431
15680
|
{
|
|
@@ -15677,33 +15926,45 @@ var AgentExecutor = class {
|
|
|
15677
15926
|
}
|
|
15678
15927
|
}
|
|
15679
15928
|
/**
|
|
15680
|
-
*
|
|
15681
|
-
*
|
|
15682
|
-
*
|
|
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.
|
|
15683
15932
|
*
|
|
15684
15933
|
* Also detects evicted txs: if local state claims a higher nonce but there are
|
|
15685
15934
|
* no pending txs in the mempool (pending == latest), the intermediate txs were
|
|
15686
15935
|
* dropped and local state is stale.
|
|
15687
15936
|
*/
|
|
15688
|
-
async patchEvmNonce(chain, payload) {
|
|
15689
|
-
if (!
|
|
15937
|
+
async patchEvmNonce(chain, payload, capturedBroadcastAge) {
|
|
15938
|
+
if (!isEvmChain(chain)) return;
|
|
15690
15939
|
const bs = payload.blockchainSpecific;
|
|
15691
15940
|
if (!bs || bs.case !== "ethereumSpecific") return;
|
|
15692
|
-
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;
|
|
15693
15956
|
const nextNonce = this.stateStore.getNextEvmNonce(chain, rpcNonce);
|
|
15694
15957
|
if (nextNonce !== rpcNonce) {
|
|
15695
|
-
|
|
15696
|
-
if (Date.now() - lastBroadcast < 3e4) {
|
|
15958
|
+
if (hasRecentBroadcast) {
|
|
15697
15959
|
if (this.verbose)
|
|
15698
15960
|
process.stderr.write(
|
|
15699
|
-
`[nonce] Keeping local nonce ${nextNonce} for ${chain} (broadcast ${
|
|
15961
|
+
`[nonce] Keeping local nonce ${nextNonce} for ${chain} (broadcast ${recentBroadcastAge}ms ago)
|
|
15700
15962
|
`
|
|
15701
15963
|
);
|
|
15702
15964
|
bs.value.nonce = nextNonce;
|
|
15703
15965
|
return;
|
|
15704
15966
|
}
|
|
15705
|
-
|
|
15706
|
-
if (pendingNonce !== null && pendingNonce === rpcNonce) {
|
|
15967
|
+
if (latestNonce !== null && pendingNonce === latestNonce) {
|
|
15707
15968
|
if (this.verbose)
|
|
15708
15969
|
process.stderr.write(
|
|
15709
15970
|
`[nonce] Stale local state for ${chain}: local=${nextNonce}, on-chain=${rpcNonce}, no pending txs \u2014 using on-chain nonce
|
|
@@ -15713,7 +15974,8 @@ var AgentExecutor = class {
|
|
|
15713
15974
|
return;
|
|
15714
15975
|
}
|
|
15715
15976
|
const nonceGap = nextNonce - rpcNonce;
|
|
15716
|
-
|
|
15977
|
+
const pendingStateVerified = pendingNonce !== null && latestNonce !== null && pendingNonce >= latestNonce;
|
|
15978
|
+
if (!pendingStateVerified && nonceGap > 3n) {
|
|
15717
15979
|
process.stderr.write(
|
|
15718
15980
|
`[nonce] Warning: pending nonce was not verified for ${chain}; signing will continue with on-chain nonce ${rpcNonce} because the local gap is ${nonceGap}
|
|
15719
15981
|
`
|
|
@@ -15722,7 +15984,7 @@ var AgentExecutor = class {
|
|
|
15722
15984
|
return;
|
|
15723
15985
|
}
|
|
15724
15986
|
bs.value.nonce = nextNonce;
|
|
15725
|
-
if (
|
|
15987
|
+
if (!pendingStateVerified) {
|
|
15726
15988
|
process.stderr.write(
|
|
15727
15989
|
`[nonce] Warning: pending nonce was not verified for ${chain}; signing will continue with local nonce ${nextNonce}
|
|
15728
15990
|
`
|
|
@@ -15741,7 +16003,51 @@ var AgentExecutor = class {
|
|
|
15741
16003
|
if (!isEvmChain(chain)) return;
|
|
15742
16004
|
const bs = payload.blockchainSpecific;
|
|
15743
16005
|
if (!bs || bs.case !== "ethereumSpecific") return;
|
|
16006
|
+
const isEip1559 = evmChainTxFeeFormat[chain] === "enveloped";
|
|
16007
|
+
if (!isEip1559) return;
|
|
15744
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) {
|
|
15745
16051
|
try {
|
|
15746
16052
|
const res = await fetch(rpcUrl, {
|
|
15747
16053
|
method: "POST",
|
|
@@ -15758,24 +16064,33 @@ var AgentExecutor = class {
|
|
|
15758
16064
|
if (!res.ok || data?.error || data?.result?.baseFeePerGas === void 0 || data?.result?.baseFeePerGas === null) {
|
|
15759
16065
|
throw new Error(`Failed to fetch current base fee for ${chain}`);
|
|
15760
16066
|
}
|
|
15761
|
-
|
|
15762
|
-
if (baseFee === 0n) return;
|
|
15763
|
-
const currentPriorityFee = BigInt(bs.value.priorityFee || "0");
|
|
15764
|
-
const currentMaxFee = BigInt(bs.value.maxFeePerGasWei || "0");
|
|
15765
|
-
const minMaxFee = baseFee * 25n / 10n + currentPriorityFee;
|
|
15766
|
-
if (currentMaxFee < minMaxFee) {
|
|
15767
|
-
bs.value.maxFeePerGasWei = minMaxFee.toString();
|
|
15768
|
-
if (this.verbose)
|
|
15769
|
-
process.stderr.write(
|
|
15770
|
-
`[gas] Bumped ${chain} maxFeePerGas: ${currentMaxFee} \u2192 ${minMaxFee} (baseFee=${baseFee})
|
|
15771
|
-
`
|
|
15772
|
-
);
|
|
15773
|
-
}
|
|
16067
|
+
return BigInt(data.result.baseFeePerGas);
|
|
15774
16068
|
} catch {
|
|
15775
16069
|
process.stderr.write(
|
|
15776
16070
|
`[gas] Warning: gas estimate was not refreshed for ${chain}; signing will continue with the original estimate
|
|
15777
16071
|
`
|
|
15778
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;
|
|
15779
16094
|
}
|
|
15780
16095
|
}
|
|
15781
16096
|
/**
|
|
@@ -15783,6 +16098,16 @@ var AgentExecutor = class {
|
|
|
15783
16098
|
* Returns null if the RPC call fails (non-fatal).
|
|
15784
16099
|
*/
|
|
15785
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) {
|
|
15786
16111
|
if (!isEvmChain(chain)) return null;
|
|
15787
16112
|
const rpcUrl = getEvmRpcUrl(chain);
|
|
15788
16113
|
try {
|
|
@@ -15793,7 +16118,7 @@ var AgentExecutor = class {
|
|
|
15793
16118
|
body: JSON.stringify({
|
|
15794
16119
|
jsonrpc: "2.0",
|
|
15795
16120
|
method: "eth_getTransactionCount",
|
|
15796
|
-
params: [address,
|
|
16121
|
+
params: [address, blockTag],
|
|
15797
16122
|
id: 1
|
|
15798
16123
|
}),
|
|
15799
16124
|
signal: AbortSignal.timeout(5e3)
|
|
@@ -15893,11 +16218,11 @@ var AgentExecutor = class {
|
|
|
15893
16218
|
`);
|
|
15894
16219
|
const chainName = params.chain;
|
|
15895
16220
|
const chainId = domain.chainId;
|
|
15896
|
-
let chain =
|
|
16221
|
+
let chain = Chain12.Ethereum;
|
|
15897
16222
|
if (chainName) {
|
|
15898
|
-
chain = resolveChain(chainName) ||
|
|
16223
|
+
chain = resolveChain(chainName) || Chain12.Ethereum;
|
|
15899
16224
|
} else if (chainId) {
|
|
15900
|
-
chain = resolveChainId(chainId) ||
|
|
16225
|
+
chain = resolveChainId(chainId) || Chain12.Ethereum;
|
|
15901
16226
|
}
|
|
15902
16227
|
const sigResult = await this.vault.signBytes({
|
|
15903
16228
|
data: eip712Hash,
|
|
@@ -17231,7 +17556,9 @@ var PipeInterface = class {
|
|
|
17231
17556
|
session;
|
|
17232
17557
|
rl = null;
|
|
17233
17558
|
stopped = false;
|
|
17559
|
+
inputClosed = false;
|
|
17234
17560
|
pendingPasswordResolve = null;
|
|
17561
|
+
pendingPasswordReject = null;
|
|
17235
17562
|
pendingConfirmResolve = null;
|
|
17236
17563
|
constructor(session) {
|
|
17237
17564
|
this.session = session;
|
|
@@ -17263,38 +17590,45 @@ var PipeInterface = class {
|
|
|
17263
17590
|
}))
|
|
17264
17591
|
});
|
|
17265
17592
|
}
|
|
17266
|
-
const
|
|
17593
|
+
const commands = [];
|
|
17267
17594
|
let inputDone = false;
|
|
17268
17595
|
let processing = false;
|
|
17269
17596
|
this.rl.on("line", async (line) => {
|
|
17270
17597
|
const trimmed = line.trim();
|
|
17271
17598
|
if (!trimmed) return;
|
|
17272
|
-
|
|
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);
|
|
17273
17611
|
if (!processing) {
|
|
17274
17612
|
processing = true;
|
|
17275
|
-
while (
|
|
17276
|
-
const
|
|
17613
|
+
while (commands.length > 0) {
|
|
17614
|
+
const nextCommand = commands.shift();
|
|
17277
17615
|
try {
|
|
17278
|
-
|
|
17279
|
-
await this.handleCommand(cmd);
|
|
17616
|
+
await this.handleCommand(nextCommand);
|
|
17280
17617
|
} catch (err) {
|
|
17281
|
-
|
|
17282
|
-
this.emit({
|
|
17283
|
-
type: "error",
|
|
17284
|
-
message: `Invalid input: ${message}`,
|
|
17285
|
-
code: code === "UNKNOWN_ERROR" /* UNKNOWN_ERROR */ ? "INVALID_INPUT" /* INVALID_INPUT */ : code
|
|
17286
|
-
});
|
|
17618
|
+
this.emitInvalidInput(err);
|
|
17287
17619
|
}
|
|
17288
17620
|
}
|
|
17289
17621
|
processing = false;
|
|
17290
|
-
if (inputDone &&
|
|
17622
|
+
if (inputDone && commands.length === 0) {
|
|
17291
17623
|
this.stop();
|
|
17292
17624
|
}
|
|
17293
17625
|
}
|
|
17294
17626
|
});
|
|
17295
17627
|
this.rl.on("close", () => {
|
|
17628
|
+
this.inputClosed = true;
|
|
17296
17629
|
inputDone = true;
|
|
17297
|
-
|
|
17630
|
+
this.settlePendingPrompts("Password input closed before a reply was received");
|
|
17631
|
+
if (!processing && commands.length === 0) {
|
|
17298
17632
|
this.stop();
|
|
17299
17633
|
}
|
|
17300
17634
|
});
|
|
@@ -17374,17 +17708,30 @@ var PipeInterface = class {
|
|
|
17374
17708
|
onDone: () => {
|
|
17375
17709
|
this.emit({ type: "done" });
|
|
17376
17710
|
},
|
|
17377
|
-
requestPassword:
|
|
17378
|
-
|
|
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) => {
|
|
17379
17722
|
this.pendingPasswordResolve = resolve;
|
|
17723
|
+
this.pendingPasswordReject = reject;
|
|
17380
17724
|
this.emit({
|
|
17381
17725
|
type: "error",
|
|
17382
17726
|
message: "PASSWORD_REQUIRED",
|
|
17383
17727
|
code: "PASSWORD_REQUIRED" /* PASSWORD_REQUIRED */
|
|
17384
17728
|
});
|
|
17385
17729
|
});
|
|
17730
|
+
void password.catch(() => void 0);
|
|
17731
|
+
return password;
|
|
17386
17732
|
},
|
|
17387
17733
|
requestConfirmation: async (message) => {
|
|
17734
|
+
if (this.inputClosed) return false;
|
|
17388
17735
|
return new Promise((resolve) => {
|
|
17389
17736
|
this.pendingConfirmResolve = resolve;
|
|
17390
17737
|
this.emit({
|
|
@@ -17406,21 +17753,14 @@ var PipeInterface = class {
|
|
|
17406
17753
|
const { message, code } = normalizeAgentError(err);
|
|
17407
17754
|
this.emit({ type: "error", message, code });
|
|
17408
17755
|
this.emit({ type: "done" });
|
|
17756
|
+
} finally {
|
|
17757
|
+
this.settlePendingPrompts("Password request cancelled because the turn ended");
|
|
17409
17758
|
}
|
|
17410
17759
|
break;
|
|
17411
17760
|
}
|
|
17412
|
-
case "password":
|
|
17413
|
-
if (this.pendingPasswordResolve) {
|
|
17414
|
-
this.pendingPasswordResolve(cmd.password);
|
|
17415
|
-
this.pendingPasswordResolve = null;
|
|
17416
|
-
}
|
|
17417
|
-
break;
|
|
17418
|
-
}
|
|
17761
|
+
case "password":
|
|
17419
17762
|
case "confirm": {
|
|
17420
|
-
|
|
17421
|
-
this.pendingConfirmResolve(cmd.confirmed);
|
|
17422
|
-
this.pendingConfirmResolve = null;
|
|
17423
|
-
}
|
|
17763
|
+
this.handleControlCommand(cmd);
|
|
17424
17764
|
break;
|
|
17425
17765
|
}
|
|
17426
17766
|
default:
|
|
@@ -17431,6 +17771,54 @@ var PipeInterface = class {
|
|
|
17431
17771
|
});
|
|
17432
17772
|
}
|
|
17433
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
|
+
}
|
|
17434
17822
|
emit(event) {
|
|
17435
17823
|
process.stdout.write(JSON.stringify(event) + "\n");
|
|
17436
17824
|
}
|
|
@@ -18344,6 +18732,11 @@ var AgentSession = class {
|
|
|
18344
18732
|
recordResolution(txHash, "failed");
|
|
18345
18733
|
return;
|
|
18346
18734
|
}
|
|
18735
|
+
if (result.status === "expired") {
|
|
18736
|
+
ui.onTxStatus(txHash, chainName ?? "", "failed", explorerUrl);
|
|
18737
|
+
recordResolution(txHash, "failed");
|
|
18738
|
+
return;
|
|
18739
|
+
}
|
|
18347
18740
|
} catch (err) {
|
|
18348
18741
|
if (this.config.verbose) {
|
|
18349
18742
|
process.stderr.write(`[session] tx confirm poll ${attempt + 1} failed: ${err?.message ?? err}
|
|
@@ -19480,7 +19873,7 @@ var cachedVersion = null;
|
|
|
19480
19873
|
function getVersion() {
|
|
19481
19874
|
if (cachedVersion) return cachedVersion;
|
|
19482
19875
|
if (true) {
|
|
19483
|
-
cachedVersion = "
|
|
19876
|
+
cachedVersion = "7.0.0";
|
|
19484
19877
|
return cachedVersion;
|
|
19485
19878
|
}
|
|
19486
19879
|
try {
|
|
@@ -19977,7 +20370,7 @@ var EventBuffer = class {
|
|
|
19977
20370
|
};
|
|
19978
20371
|
|
|
19979
20372
|
// src/interactive/session.ts
|
|
19980
|
-
import { Chain as
|
|
20373
|
+
import { Chain as Chain14, fiatCurrencies as fiatCurrencies3 } from "@vultisig/sdk";
|
|
19981
20374
|
import chalk14 from "chalk";
|
|
19982
20375
|
import ora3 from "ora";
|
|
19983
20376
|
import * as readline3 from "readline";
|
|
@@ -20828,7 +21221,7 @@ Error: ${error2.message}`));
|
|
|
20828
21221
|
} else if (rest[i] === "--destination-tag") {
|
|
20829
21222
|
const tag = rest[i + 1];
|
|
20830
21223
|
const parsedTag = Number(tag);
|
|
20831
|
-
if (chain !==
|
|
21224
|
+
if (chain !== Chain14.Ripple || !/^(0|[1-9]\d*)$/.test(tag ?? "") || !Number.isSafeInteger(parsedTag) || parsedTag > 4294967295) {
|
|
20832
21225
|
throw new Error("Invalid XRP DestinationTag: expected an integer from 0 to 4294967295");
|
|
20833
21226
|
}
|
|
20834
21227
|
destinationTag = parsedTag;
|
|
@@ -21676,7 +22069,7 @@ See also: balance, tx-status`
|
|
|
21676
22069
|
if (!amount && !options.max) throw new Error("Provide an amount or use --max");
|
|
21677
22070
|
if (amount && options.max) throw new Error("Cannot specify both amount and --max");
|
|
21678
22071
|
const chain = resolveChainOrThrow(chainStr);
|
|
21679
|
-
if (options.destinationTag !== void 0 && chain !==
|
|
22072
|
+
if (options.destinationTag !== void 0 && chain !== Chain15.Ripple) {
|
|
21680
22073
|
throw new Error("--destination-tag is only supported for XRP");
|
|
21681
22074
|
}
|
|
21682
22075
|
const destinationTag = options.destinationTag === void 0 ? void 0 : Number(options.destinationTag);
|
|
@@ -21804,7 +22197,7 @@ program2.command("broadcast").description("Broadcast a pre-signed raw transactio
|
|
|
21804
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(
|
|
21805
22198
|
"after",
|
|
21806
22199
|
`
|
|
21807
|
-
Statuses: pending, not_found, confirmed, failed
|
|
22200
|
+
Statuses: pending, not_found, expired, confirmed, failed
|
|
21808
22201
|
Malformed hashes fail with INVALID_HASH (exit 4).
|
|
21809
22202
|
|
|
21810
22203
|
Examples:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.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.0.0",
|
|
78
|
+
"@vultisig/rujira": "^71.0.0",
|
|
79
|
+
"@vultisig/sdk": "^7.0.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.0.0",
|
|
98
98
|
"esbuild": "^0.28.1",
|
|
99
99
|
"ethers": "^6.17.0",
|
|
100
100
|
"node-pty": "^1.1.0",
|