@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.
Files changed (3) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/index.js +198 -70
  3. 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({ abi: ERC20_TRANSFER_ABI, data: calldata });
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 usedQuoteSummary = !!labels.quote_summary;
14889
- const head = labels.quote_summary || `swap ${labels.amount_in ?? p?.txArgs?.amount ?? "?"} ${labels.from_token_symbol ?? ""} \u2192 ${labels.to_token_symbol ?? ""}`.trim();
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 tokenLabel = stripEmbeddedPayloadContract(
15065
+ const tokenLabel2 = stripEmbeddedPayloadContract(
14918
15066
  (labels.token_resolved || labels.token_symbol || "").trim(),
14919
15067
  disclosedContract
14920
15068
  );
14921
- const symbol = tokenLabel.split(/\s+/, 1)[0];
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 = tokenLabel.slice(symbol.length);
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 = tokenLabel.length > 0 && amount.endsWith(` ${tokenLabel}`);
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). Uses vault.prepareSendTx with memo field to carry the
15386
- * calldata, plus EVM-specific nonce/lock plumbing that Phase B's
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 buildAmount = amount === 0n && hasCalldata ? 1n : amount;
15425
- const keysignPayload = await this.vault.prepareSendTx({
15426
- coin,
15427
- receiver: swapTx.to,
15428
- amount: buildAmount,
15429
- memo: swapTx.data
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.0.0";
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.0.0",
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.0.0",
77
+ "@vultisig/core-chain": "^4.1.1",
78
78
  "@vultisig/rujira": "^70.0.0",
79
- "@vultisig/sdk": "^6.0.0",
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.0.0",
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",