@vultisig/cli 6.0.0 → 6.3.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 +24 -0
- package/dist/index.js +198 -70
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 6.3.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#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.
|
|
8
|
+
|
|
9
|
+
- 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)]:
|
|
10
|
+
- @vultisig/core-chain@4.1.1
|
|
11
|
+
- @vultisig/sdk@6.3.0
|
|
12
|
+
|
|
13
|
+
## 6.2.0
|
|
14
|
+
|
|
15
|
+
### Minor Changes
|
|
16
|
+
|
|
17
|
+
- [#1389](https://github.com/vultisig/vultisig-sdk/pull/1389) [`e1e73cb`](https://github.com/vultisig/vultisig-sdk/commit/e1e73cb5a67de6c77731b2d58ed7b2cb547e1228) Thanks [@gomesalexandre](https://github.com/gomesalexandre)! - Export the RN-safe `prepareIbcTransfer` and `prepareSuiTokenTransferFromKeys` helpers from `@vultisig/sdk/react-native`, along with their public support types/constants so React Native consumers no longer need deep imports for IBC and Sui token transfer prep.
|
|
18
|
+
|
|
19
|
+
### Patch Changes
|
|
20
|
+
|
|
21
|
+
- [#2225](https://github.com/vultisig/vultisig-sdk/pull/2225) [`95edf12`](https://github.com/vultisig/vultisig-sdk/commit/95edf1264827d0a63baa9d0580817caf2dffdc9e) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Add a canonical raw EVM transaction-envelope keysign helper and use it in the CLI signing path.
|
|
22
|
+
|
|
23
|
+
- Updated dependencies [[`8a98b44`](https://github.com/vultisig/vultisig-sdk/commit/8a98b44e1f4438212e6deb7cca8491e23940118c), [`95edf12`](https://github.com/vultisig/vultisig-sdk/commit/95edf1264827d0a63baa9d0580817caf2dffdc9e), [`e1e73cb`](https://github.com/vultisig/vultisig-sdk/commit/e1e73cb5a67de6c77731b2d58ed7b2cb547e1228), [`3fff7cf`](https://github.com/vultisig/vultisig-sdk/commit/3fff7cfdfe23d2d5622f7caa87a6f1525329f07e), [`0697060`](https://github.com/vultisig/vultisig-sdk/commit/0697060107c7fe1c8ec818d3e0eae01557d9d96f)]:
|
|
24
|
+
- @vultisig/sdk@6.2.0
|
|
25
|
+
- @vultisig/core-chain@4.1.0
|
|
26
|
+
|
|
3
27
|
## 6.0.0
|
|
4
28
|
|
|
5
29
|
### Major Changes
|
package/dist/index.js
CHANGED
|
@@ -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) {
|
|
@@ -14493,13 +14467,177 @@ var ERC20_TRANSFER_ABI = parseAbi(["function transfer(address to, uint256 value)
|
|
|
14493
14467
|
function decodeErc20Transfer(calldata) {
|
|
14494
14468
|
if (calldata.slice(0, ERC20_TRANSFER_SELECTOR.length).toLowerCase() !== ERC20_TRANSFER_SELECTOR) return null;
|
|
14495
14469
|
try {
|
|
14496
|
-
const decoded = decodeFunctionData({
|
|
14470
|
+
const decoded = decodeFunctionData({
|
|
14471
|
+
abi: ERC20_TRANSFER_ABI,
|
|
14472
|
+
data: calldata
|
|
14473
|
+
});
|
|
14497
14474
|
const [recipient, amount] = decoded.args;
|
|
14498
14475
|
return { recipient, amount };
|
|
14499
14476
|
} catch {
|
|
14500
14477
|
throw new Error("Invalid ERC-20 transfer calldata \u2014 refusing to sign");
|
|
14501
14478
|
}
|
|
14502
14479
|
}
|
|
14480
|
+
var tokenLabel = (value) => typeof value === "string" ? value : "";
|
|
14481
|
+
var MAX_TOKEN_SYMBOL_LENGTH = 32;
|
|
14482
|
+
var MAX_TOKEN_LABEL_LENGTH = 512;
|
|
14483
|
+
function safeTokenSymbol(symbol) {
|
|
14484
|
+
const defaultDisplaySymbol = symbol.match(/^[\p{L}\p{N}][\p{L}\p{N}._+-]{0,31}/u)?.[0] ?? "token";
|
|
14485
|
+
if (symbol.length > MAX_TOKEN_SYMBOL_LENGTH) {
|
|
14486
|
+
return { displaySymbol: defaultDisplaySymbol, suspicious: true };
|
|
14487
|
+
}
|
|
14488
|
+
const suspiciousAt = symbol.search(/0x[0-9a-f]{40}|\([^)]*\bon\b[^)]*\)/iu);
|
|
14489
|
+
const candidate = (suspiciousAt < 0 ? symbol : symbol.slice(0, suspiciousAt)).trim();
|
|
14490
|
+
const displaySymbol = candidate.match(/^[\p{L}\p{N}][\p{L}\p{N}._+-]*/u)?.[0] ?? "token";
|
|
14491
|
+
if (suspiciousAt < 0 && candidate === displaySymbol) {
|
|
14492
|
+
return { displaySymbol, suspicious: false };
|
|
14493
|
+
}
|
|
14494
|
+
return { displaySymbol, suspicious: true };
|
|
14495
|
+
}
|
|
14496
|
+
function unresolvedTokenIdentity(label) {
|
|
14497
|
+
if (typeof label !== "string" || label.length > MAX_TOKEN_LABEL_LENGTH) {
|
|
14498
|
+
return { rawSymbol: "", displaySymbol: "", kind: "unresolved" };
|
|
14499
|
+
}
|
|
14500
|
+
const suffixAt = label.lastIndexOf(" (");
|
|
14501
|
+
const rawSymbol = (suffixAt > 0 ? label.slice(0, suffixAt) : label).trim();
|
|
14502
|
+
return {
|
|
14503
|
+
rawSymbol,
|
|
14504
|
+
displaySymbol: safeTokenSymbol(rawSymbol).displaySymbol,
|
|
14505
|
+
kind: "unresolved"
|
|
14506
|
+
};
|
|
14507
|
+
}
|
|
14508
|
+
function untrustedSymbolIdentity(symbol) {
|
|
14509
|
+
const rawSymbol = tokenLabel(symbol);
|
|
14510
|
+
return {
|
|
14511
|
+
rawSymbol,
|
|
14512
|
+
displaySymbol: safeTokenSymbol(rawSymbol).displaySymbol,
|
|
14513
|
+
kind: "unresolved"
|
|
14514
|
+
};
|
|
14515
|
+
}
|
|
14516
|
+
function resolvedTokenIdentity(label, expectedChain) {
|
|
14517
|
+
const unresolved = unresolvedTokenIdentity(label);
|
|
14518
|
+
if (typeof label !== "string" || label.length > MAX_TOKEN_LABEL_LENGTH) return unresolved;
|
|
14519
|
+
const match = label.match(/^([\s\S]*) \(([\s\S]*?) on ([^,]+), \d+ dec, source: [^)]+\)$/u);
|
|
14520
|
+
if (!match) return unresolved;
|
|
14521
|
+
const [, rawSymbol, rawAssetId, descriptorChain] = match;
|
|
14522
|
+
const { displaySymbol, suspicious } = safeTokenSymbol(rawSymbol);
|
|
14523
|
+
const parsedChain = resolveChainReference(descriptorChain);
|
|
14524
|
+
const routedChain = typeof expectedChain === "string" || typeof expectedChain === "number" ? resolveChainReference(expectedChain) : void 0;
|
|
14525
|
+
if (suspicious || !parsedChain || !routedChain || parsedChain !== routedChain) {
|
|
14526
|
+
return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14527
|
+
}
|
|
14528
|
+
const assetId = rawAssetId.trim();
|
|
14529
|
+
if (!assetId) return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14530
|
+
if (assetId.toLowerCase() === "native") return { rawSymbol, displaySymbol, kind: "native" };
|
|
14531
|
+
if (getChainKind4(routedChain) === "evm") {
|
|
14532
|
+
if (!/^0x[0-9a-f]{40}$/iu.test(assetId)) return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14533
|
+
} else if (!/^[\p{L}\p{N}:._/-]{1,128}$/u.test(assetId)) {
|
|
14534
|
+
return { rawSymbol, displaySymbol, kind: "unresolved" };
|
|
14535
|
+
}
|
|
14536
|
+
return { rawSymbol, displaySymbol, kind: "token", contract: assetId };
|
|
14537
|
+
}
|
|
14538
|
+
function replaceUnsafeSymbol(text, identity) {
|
|
14539
|
+
if (!identity.rawSymbol || identity.rawSymbol === identity.displaySymbol) return text;
|
|
14540
|
+
return text.split(identity.rawSymbol).join(identity.displaySymbol);
|
|
14541
|
+
}
|
|
14542
|
+
function anchorEnd(text, label) {
|
|
14543
|
+
if (!label) return -1;
|
|
14544
|
+
const tokenChar = /[\p{L}\p{N}._+-]/u;
|
|
14545
|
+
const trimmedLength = text.trimEnd().length;
|
|
14546
|
+
const index = trimmedLength - label.length;
|
|
14547
|
+
if (index < 0 || !text.startsWith(label, index)) return -1;
|
|
14548
|
+
const before = text[index - 1];
|
|
14549
|
+
if (before && tokenChar.test(before)) return -1;
|
|
14550
|
+
return trimmedLength;
|
|
14551
|
+
}
|
|
14552
|
+
function hasAnchor(text, anchors) {
|
|
14553
|
+
return anchors.some((anchor) => anchorEnd(text, anchor) >= 0);
|
|
14554
|
+
}
|
|
14555
|
+
function hasSingleSwapDelimiter(summary, labels) {
|
|
14556
|
+
const identities = [
|
|
14557
|
+
unresolvedTokenIdentity(labels.from_token),
|
|
14558
|
+
untrustedSymbolIdentity(labels.from_token_symbol),
|
|
14559
|
+
unresolvedTokenIdentity(labels.to_token),
|
|
14560
|
+
untrustedSymbolIdentity(labels.to_token_symbol)
|
|
14561
|
+
];
|
|
14562
|
+
const structuralSummary = identities.reduce((text, identity) => replaceUnsafeSymbol(text, identity), summary);
|
|
14563
|
+
const firstArrow = structuralSummary.indexOf("\u2192");
|
|
14564
|
+
return firstArrow >= 0 && structuralSummary.indexOf("\u2192", firstArrow + 1) < 0;
|
|
14565
|
+
}
|
|
14566
|
+
function splitSwapHead(head, sellAnchors, buyAnchors) {
|
|
14567
|
+
let best;
|
|
14568
|
+
let arrowAt = head.indexOf("\u2192");
|
|
14569
|
+
while (arrowAt >= 0) {
|
|
14570
|
+
const left = head.slice(0, arrowAt);
|
|
14571
|
+
const right = head.slice(arrowAt + 1);
|
|
14572
|
+
const viaAt = right.indexOf(" via ");
|
|
14573
|
+
const buy = viaAt >= 0 ? right.slice(0, viaAt) : right;
|
|
14574
|
+
const provider = viaAt >= 0 ? right.slice(viaAt) : "";
|
|
14575
|
+
const score = Number(hasAnchor(left, sellAnchors)) + Number(hasAnchor(buy, buyAnchors));
|
|
14576
|
+
if (!best || score > best.score) {
|
|
14577
|
+
best = { left, buy, provider, score };
|
|
14578
|
+
}
|
|
14579
|
+
arrowAt = head.indexOf("\u2192", arrowAt + 1);
|
|
14580
|
+
}
|
|
14581
|
+
return best;
|
|
14582
|
+
}
|
|
14583
|
+
function terminalAnchorSymbol(anchor) {
|
|
14584
|
+
return anchor.trim().match(/[\p{L}\p{N}][\p{L}\p{N}._+-]*$/u)?.[0] ?? "";
|
|
14585
|
+
}
|
|
14586
|
+
function discloseSwapSide(side, anchors, suffix, expectedSymbol) {
|
|
14587
|
+
if (!expectedSymbol) {
|
|
14588
|
+
return `${side.trimEnd()} (contract unavailable)${side.slice(side.trimEnd().length)}`;
|
|
14589
|
+
}
|
|
14590
|
+
for (const anchor of anchors) {
|
|
14591
|
+
const end = anchorEnd(side, anchor);
|
|
14592
|
+
if (end < 0) continue;
|
|
14593
|
+
const visibleSymbol = terminalAnchorSymbol(anchor);
|
|
14594
|
+
if (expectedSymbol && visibleSymbol && visibleSymbol !== expectedSymbol) break;
|
|
14595
|
+
if (!suffix) return side;
|
|
14596
|
+
return `${side.slice(0, end)}${suffix}${side.slice(end)}`;
|
|
14597
|
+
}
|
|
14598
|
+
return `${side.trimEnd()} (contract unavailable)${side.slice(side.trimEnd().length)}`;
|
|
14599
|
+
}
|
|
14600
|
+
function discloseSwapTokenContracts(head, labels, payload, sourceChain) {
|
|
14601
|
+
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;
|
|
14602
|
+
const fromToken = resolvedTokenIdentity(labels.from_token, sourceChain);
|
|
14603
|
+
const toToken = resolvedTokenIdentity(labels.to_token, destinationChain);
|
|
14604
|
+
const fromSymbol = untrustedSymbolIdentity(labels.from_token_symbol);
|
|
14605
|
+
const toSymbol = untrustedSymbolIdentity(labels.to_token_symbol);
|
|
14606
|
+
const approvalArgs = payload?.approvalTxArgs;
|
|
14607
|
+
const rawApprovalTarget = tokenLabel(
|
|
14608
|
+
approvalArgs && typeof approvalArgs === "object" ? approvalArgs.tx?.to : void 0
|
|
14609
|
+
);
|
|
14610
|
+
const approvalTarget = /^0x[0-9a-f]{40}$/iu.test(rawApprovalTarget) ? rawApprovalTarget : "";
|
|
14611
|
+
const symbolIdentities = [fromToken, fromSymbol, toToken, toSymbol];
|
|
14612
|
+
const sanitizeText = (value) => symbolIdentities.reduce((text, identity) => replaceUnsafeSymbol(text, identity), tokenLabel(value));
|
|
14613
|
+
const sanitizedHead = sanitizeText(head);
|
|
14614
|
+
const sellAnchors = [sanitizeText(labels.amount_in), fromSymbol.displaySymbol, fromToken.displaySymbol].filter(
|
|
14615
|
+
Boolean
|
|
14616
|
+
);
|
|
14617
|
+
const buyAnchors = [sanitizeText(labels.expected_output), toSymbol.displaySymbol, toToken.displaySymbol].filter(
|
|
14618
|
+
Boolean
|
|
14619
|
+
);
|
|
14620
|
+
const approvalMatchesResolvedSellToken = fromToken.kind === "token" && !!fromToken.contract && !!approvalTarget && fromToken.contract.toLowerCase() === approvalTarget.toLowerCase();
|
|
14621
|
+
const sellSuffix = payload?.approvalTxArgs ? approvalMatchesResolvedSellToken ? ` (${approvalTarget})` : " (contract unavailable)" : fromToken.kind === "native" ? "" : fromToken.kind === "token" && fromToken.contract ? ` (${fromToken.contract})` : " (contract unavailable)";
|
|
14622
|
+
const buySuffix = toToken.kind === "native" ? "" : toToken.kind === "token" && toToken.contract ? ` (${toToken.contract})` : " (contract unavailable)";
|
|
14623
|
+
const halves = splitSwapHead(sanitizedHead, sellAnchors, buyAnchors);
|
|
14624
|
+
if (!halves) return `${sanitizedHead} (contract unavailable)`;
|
|
14625
|
+
const sellResolved = fromToken.kind !== "unresolved";
|
|
14626
|
+
const buyResolved = toToken.kind !== "unresolved";
|
|
14627
|
+
const sell = discloseSwapSide(
|
|
14628
|
+
halves.left,
|
|
14629
|
+
sellAnchors,
|
|
14630
|
+
sellResolved ? sellSuffix : "",
|
|
14631
|
+
sellResolved ? fromToken.displaySymbol : void 0
|
|
14632
|
+
);
|
|
14633
|
+
const buy = discloseSwapSide(
|
|
14634
|
+
halves.buy,
|
|
14635
|
+
buyAnchors,
|
|
14636
|
+
buyResolved ? buySuffix : "",
|
|
14637
|
+
buyResolved ? toToken.displaySymbol : void 0
|
|
14638
|
+
);
|
|
14639
|
+
return `${sell}\u2192${buy}${halves.provider}`;
|
|
14640
|
+
}
|
|
14503
14641
|
var isEvmChain = (chain) => EVM_CHAINS.has(chain);
|
|
14504
14642
|
function stripEmbeddedPayloadContract(value, disclosedContract) {
|
|
14505
14643
|
if (!disclosedContract) return value;
|
|
@@ -14885,12 +15023,22 @@ var AgentExecutor = class {
|
|
|
14885
15023
|
}
|
|
14886
15024
|
const isSwap = !!(p?.approvalTxArgs || p?.swap_tx || labels.quote_summary || labels.to_token_symbol);
|
|
14887
15025
|
if (isSwap) {
|
|
14888
|
-
const
|
|
14889
|
-
const
|
|
15026
|
+
const rawQuoteSummary = tokenLabel(labels.quote_summary);
|
|
15027
|
+
const quoteSummary = hasSingleSwapDelimiter(rawQuoteSummary, labels) ? rawQuoteSummary : "";
|
|
15028
|
+
const usedQuoteSummary = !!quoteSummary;
|
|
15029
|
+
const amountIn = tokenLabel(labels.amount_in) || tokenLabel(p?.txArgs?.amount) || "?";
|
|
15030
|
+
const fromSymbol = tokenLabel(labels.from_token_symbol);
|
|
15031
|
+
const sellHead = fromSymbol && !amountIn.endsWith(` ${fromSymbol}`) ? `${amountIn} ${fromSymbol}` : amountIn;
|
|
15032
|
+
const head = discloseSwapTokenContracts(
|
|
15033
|
+
quoteSummary || `swap ${sellHead} \u2192 ${tokenLabel(labels.to_token_symbol) || "?"}`,
|
|
15034
|
+
labels,
|
|
15035
|
+
p,
|
|
15036
|
+
stored.chain
|
|
15037
|
+
);
|
|
14890
15038
|
const parts = [head, `on ${stored.chain}`];
|
|
14891
|
-
if (!usedQuoteSummary && labels.provider) parts.push(`via ${labels.provider}`);
|
|
15039
|
+
if (!usedQuoteSummary && tokenLabel(labels.provider)) parts.push(`via ${tokenLabel(labels.provider)}`);
|
|
14892
15040
|
if (p?.__multiLeg) parts.push("(+ token approval \u2014 2 transactions)");
|
|
14893
|
-
if (labels.estimated_fee) parts.push(`est. fee ${labels.estimated_fee}`);
|
|
15041
|
+
if (tokenLabel(labels.estimated_fee)) parts.push(`est. fee ${tokenLabel(labels.estimated_fee)}`);
|
|
14894
15042
|
return parts.join(" ");
|
|
14895
15043
|
}
|
|
14896
15044
|
const signedTx = extractNestedTx(p);
|
|
@@ -14914,18 +15062,18 @@ var AgentExecutor = class {
|
|
|
14914
15062
|
*/
|
|
14915
15063
|
renderLabelSendSummary(p, labels, chain, to, disclosedContract) {
|
|
14916
15064
|
const amount = stripEmbeddedPayloadContract(labels.resolved_amount ?? p?.txArgs?.amount ?? "?", disclosedContract);
|
|
14917
|
-
const
|
|
15065
|
+
const tokenLabel2 = stripEmbeddedPayloadContract(
|
|
14918
15066
|
(labels.token_resolved || labels.token_symbol || "").trim(),
|
|
14919
15067
|
disclosedContract
|
|
14920
15068
|
);
|
|
14921
|
-
const symbol =
|
|
15069
|
+
const symbol = tokenLabel2.split(/\s+/, 1)[0];
|
|
14922
15070
|
const escapedChain = String(chain).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14923
15071
|
const routedChainPattern = new RegExp(`(?:^|\\s)(?:not\\s+)?on ${escapedChain}(?=\\s|$)`);
|
|
14924
15072
|
const positiveRoutedChainPattern = new RegExp(`(?:^|\\s)(?<!\\bnot\\s+)on ${escapedChain}(?=\\s|$)`);
|
|
14925
|
-
const tokenContext =
|
|
15073
|
+
const tokenContext = tokenLabel2.slice(symbol.length);
|
|
14926
15074
|
const labelCarriesRoutedChain = positiveRoutedChainPattern.test(tokenContext);
|
|
14927
15075
|
const tokenDetail = tokenContext.replace(routedChainPattern, "").trim();
|
|
14928
|
-
const amountEmbedsTokenLabel =
|
|
15076
|
+
const amountEmbedsTokenLabel = tokenLabel2.length > 0 && amount.endsWith(` ${tokenLabel2}`);
|
|
14929
15077
|
const amountWithSymbol = symbol && !amount.endsWith(` ${symbol}`) && !amountEmbedsTokenLabel ? `${amount} ${symbol}` : amount;
|
|
14930
15078
|
const tokenDetailSuffix = amountEmbedsTokenLabel || !tokenDetail ? "" : ` ${tokenDetail}`;
|
|
14931
15079
|
const location = amountEmbedsTokenLabel && labelCarriesRoutedChain ? "" : `on ${chain}${tokenDetailSuffix}`;
|
|
@@ -15382,9 +15530,8 @@ var AgentExecutor = class {
|
|
|
15382
15530
|
}
|
|
15383
15531
|
/**
|
|
15384
15532
|
* Sign and broadcast a server-built EVM transaction (raw EVM tx from
|
|
15385
|
-
* tx_ready SSE).
|
|
15386
|
-
*
|
|
15387
|
-
* `signMultiLeg` depends on for back-to-back approve+main broadcasts.
|
|
15533
|
+
* tx_ready SSE). The SDK raw-envelope helper owns zero-value calldata,
|
|
15534
|
+
* gas-limit, and fee mapping; the CLI reconciles its nonce with local state.
|
|
15388
15535
|
*/
|
|
15389
15536
|
async signEvmServerTx(serverTxData, defaultChain, params) {
|
|
15390
15537
|
const swapTx = extractNestedTx(serverTxData);
|
|
@@ -15401,14 +15548,6 @@ var AgentExecutor = class {
|
|
|
15401
15548
|
}
|
|
15402
15549
|
await this.acquireEvmLockIfNeeded(chain);
|
|
15403
15550
|
try {
|
|
15404
|
-
const address = await this.vault.address(chain);
|
|
15405
|
-
const balance = await this.vault.balance(chain);
|
|
15406
|
-
const coin = {
|
|
15407
|
-
chain,
|
|
15408
|
-
address,
|
|
15409
|
-
decimals: balance.decimals || 18,
|
|
15410
|
-
ticker: balance.symbol || chain.toString()
|
|
15411
|
-
};
|
|
15412
15551
|
const amount = BigInt(swapTx.value || "0");
|
|
15413
15552
|
const hasCalldata = !!(swapTx.data && swapTx.data !== "0x");
|
|
15414
15553
|
if (this.verbose)
|
|
@@ -15421,30 +15560,19 @@ var AgentExecutor = class {
|
|
|
15421
15560
|
await this.vault.unlock?.(this.password);
|
|
15422
15561
|
}
|
|
15423
15562
|
}
|
|
15424
|
-
const
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
|
|
15429
|
-
|
|
15563
|
+
const keysignPayload = await this.vault.prepareRawEvmTx({
|
|
15564
|
+
chain,
|
|
15565
|
+
tx: {
|
|
15566
|
+
to: swapTx.to,
|
|
15567
|
+
value: swapTx.value ?? 0n,
|
|
15568
|
+
data: swapTx.data ?? "0x",
|
|
15569
|
+
gasLimit: swapTx.gasLimit ?? swapTx.gas_limit,
|
|
15570
|
+
maxFeePerGas: swapTx.maxFeePerGas ?? swapTx.max_fee_per_gas,
|
|
15571
|
+
maxPriorityFeePerGas: swapTx.maxPriorityFeePerGas ?? swapTx.max_priority_fee_per_gas,
|
|
15572
|
+
nonce: swapTx.nonce
|
|
15573
|
+
}
|
|
15430
15574
|
});
|
|
15431
|
-
if (amount === 0n && hasCalldata) {
|
|
15432
|
-
;
|
|
15433
|
-
keysignPayload.toAmount = "0";
|
|
15434
|
-
}
|
|
15435
15575
|
await this.patchEvmNonce(chain, keysignPayload);
|
|
15436
|
-
if (swapTx.gas_limit) {
|
|
15437
|
-
const bs = keysignPayload.blockchainSpecific;
|
|
15438
|
-
if (bs?.case === "ethereumSpecific" && bs.value?.gasLimit) {
|
|
15439
|
-
const serverGas = swapTx.gas_limit.toString();
|
|
15440
|
-
const currentGas = bs.value.gasLimit.toString();
|
|
15441
|
-
if (BigInt(serverGas) > BigInt(currentGas)) {
|
|
15442
|
-
bs.value.gasLimit = serverGas;
|
|
15443
|
-
if (this.verbose) process.stderr.write(`[gas] Using server gas_limit: ${serverGas} (was ${currentGas})
|
|
15444
|
-
`);
|
|
15445
|
-
}
|
|
15446
|
-
}
|
|
15447
|
-
}
|
|
15448
15576
|
await this.patchEvmGas(chain, keysignPayload);
|
|
15449
15577
|
const messageHashes = await this.vault.extractMessageHashes(keysignPayload);
|
|
15450
15578
|
const signature = await this.vault.sign(
|
|
@@ -19500,7 +19628,7 @@ var cachedVersion = null;
|
|
|
19500
19628
|
function getVersion() {
|
|
19501
19629
|
if (cachedVersion) return cachedVersion;
|
|
19502
19630
|
if (true) {
|
|
19503
|
-
cachedVersion = "6.
|
|
19631
|
+
cachedVersion = "6.3.0";
|
|
19504
19632
|
return cachedVersion;
|
|
19505
19633
|
}
|
|
19506
19634
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.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": {
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"@napi-rs/keyring": "^1.3.0",
|
|
75
75
|
"@noble/hashes": "^2.2.0",
|
|
76
76
|
"@vultisig/client-shared": "^0.3.5",
|
|
77
|
-
"@vultisig/core-chain": "^4.
|
|
77
|
+
"@vultisig/core-chain": "^4.1.1",
|
|
78
78
|
"@vultisig/rujira": "^70.0.0",
|
|
79
|
-
"@vultisig/sdk": "^6.
|
|
79
|
+
"@vultisig/sdk": "^6.3.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": "^2.
|
|
97
|
+
"@vultisig/core-mpc": "^2.1.1",
|
|
98
98
|
"esbuild": "^0.28.1",
|
|
99
99
|
"ethers": "^6.17.0",
|
|
100
100
|
"node-pty": "^1.1.0",
|