@vultisig/cli 0.14.0 → 0.15.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 CHANGED
@@ -1,5 +1,41 @@
1
1
  # @vultisig/cli
2
2
 
3
+ ## 0.15.0
4
+
5
+ ### Patch Changes
6
+
7
+ - [#234](https://github.com/vultisig/vultisig-sdk/pull/234) [`9f71a0e`](https://github.com/vultisig/vultisig-sdk/commit/9f71a0e430aadcb96707448c5e5e077aa0b561e0) Thanks [@rcoderdev](https://github.com/rcoderdev)! - Add Vitest for the CLI package and run CLI tests from the root `yarn test` script. Unimplemented agent actions now return `success: false` with an error message instead of `success: true` with a `data.message` field.
8
+
9
+ - [#235](https://github.com/vultisig/vultisig-sdk/pull/235) [`aea1c28`](https://github.com/vultisig/vultisig-sdk/commit/aea1c28051345ddef9c952108b203caa8b7fa032) Thanks [@rcoderdev](https://github.com/rcoderdev)! - ### Swap amounts (backward compatible)
10
+ - `SwapQuoteParams.amount` and `SwapTxParams.amount` now accept **`string | number`**. Call sites that already pass a **number** require no code changes.
11
+ - Human-readable swap amounts can be passed as **decimal strings** end-to-end (compound `vault.swap()`, `getSwapQuote`, `prepareSwapTx`, CLI agent), avoiding precision loss from `Number()` / `parseFloat()` on extreme magnitudes or fractional digits.
12
+ - `toChainAmount` accepts **`string | number`**; whitespace-only / empty strings throw instead of being treated as zero.
13
+
14
+ ### Send preparation (stricter validation)
15
+ - `prepareSendTx` and `estimateSendFee` reject **zero or negative** `amount` in base units. This aligns with real transfers; payloads with `toAmount: "0"` are no longer built for native/token sends.
16
+ - **Zero-value EVM contract calls** are unchanged: use `prepareContractCallTx` (or `vault.contractCall()`), which still builds via the internal path that allows `value: 0n`.
17
+
18
+ ### Other
19
+ - Swap approval sizing uses `toChainAmount` instead of float scaling for required allowance.
20
+ - `@vultisig/rujira` (source): `VultisigSignature.format` includes **`MLDSA`** to match SDK `Signature` — type-only widening, no runtime change; Rujira will pick up a **patch** version via normal dependency releases when published next.
21
+ - CLI: direct **`viem`** dependency; Solana local swap human amount via `formatUnits`; agent SSE `Transaction` typing includes optional `swap_tx` / `send_tx` / `tx`.
22
+
23
+ **Semver:** **Minor** for `@vultisig/core-chain`, `@vultisig/core-mpc`, and `@vultisig/sdk` (additive types + intentional validation tightening). **`@vultisig/cli` is linked to the SDK** in Changesets config, so it receives the same minor bump. This is **not** a SemVer **major** for integration purposes: swap inputs are only widened; `prepareSendTx({ amount: 0n })` was never a valid broadcast path.
24
+
25
+ **Release tooling note:** `yarn changeset status` may still propose a **major** version for `@vultisig/rujira` when the SDK minors, even though the only Rujira change is adding `'MLDSA'` to a string-literal union (fully backward compatible). Review the Version Packages PR and **downgrade Rujira to patch** if your policy is to reserve majors for real breaking API changes.
26
+
27
+ **`@vultisig/sdk` is 0.x:** per [SemVer](https://semver.org/#spec-item-4), minor releases on `0.y.z` may include behavior changes; consumers pinning `^0.14.0` should still accept `0.15.0` but should read changelog for validation tightening.
28
+
29
+ - Updated dependencies [[`9f71a0e`](https://github.com/vultisig/vultisig-sdk/commit/9f71a0e430aadcb96707448c5e5e077aa0b561e0), [`aea1c28`](https://github.com/vultisig/vultisig-sdk/commit/aea1c28051345ddef9c952108b203caa8b7fa032)]:
30
+ - @vultisig/sdk@0.15.0
31
+ - @vultisig/rujira@10.0.0
32
+
33
+ ## 0.14.2
34
+
35
+ ### Patch Changes
36
+
37
+ - [#233](https://github.com/vultisig/vultisig-sdk/pull/233) [`a0387b4`](https://github.com/vultisig/vultisig-sdk/commit/a0387b42b816c26fedf71a089fb461257d331be7) Thanks [@rcoderdev](https://github.com/rcoderdev)! - CLI agent executor now surfaces unimplemented and stub actions as failures (`success: false`) instead of returning misleading success. Removed `get_market_price` and `thorchain_query` from the local auto-execute allowlist where there is no implementation.
38
+
3
39
  ## 0.14.0
4
40
 
5
41
  ### Patch Changes
package/dist/index.js CHANGED
@@ -1430,6 +1430,25 @@ var init_sha3 = __esm({
1430
1430
  }
1431
1431
  });
1432
1432
 
1433
+ // node_modules/viem/_esm/utils/unit/formatUnits.js
1434
+ function formatUnits(value, decimals) {
1435
+ let display = value.toString();
1436
+ const negative = display.startsWith("-");
1437
+ if (negative)
1438
+ display = display.slice(1);
1439
+ display = display.padStart(decimals, "0");
1440
+ let [integer, fraction] = [
1441
+ display.slice(0, display.length - decimals),
1442
+ display.slice(display.length - decimals)
1443
+ ];
1444
+ fraction = fraction.replace(/(0+)$/, "");
1445
+ return `${negative ? "-" : ""}${integer || "0"}${fraction ? `.${fraction}` : ""}`;
1446
+ }
1447
+ var init_formatUnits = __esm({
1448
+ "node_modules/viem/_esm/utils/unit/formatUnits.js"() {
1449
+ }
1450
+ });
1451
+
1433
1452
  // src/index.ts
1434
1453
  import "dotenv/config";
1435
1454
  import { promises as fs4 } from "node:fs";
@@ -4765,6 +4784,9 @@ function getNativeTokenDecimals(chain) {
4765
4784
  // src/agent/executor.ts
4766
4785
  import { Chain as Chain9, Vultisig as Vultisig6 } from "@vultisig/sdk";
4767
4786
 
4787
+ // node_modules/viem/_esm/index.js
4788
+ init_formatUnits();
4789
+
4768
4790
  // src/core/VaultStateStore.ts
4769
4791
  import * as fs2 from "node:fs";
4770
4792
  import * as os from "node:os";
@@ -4929,7 +4951,6 @@ var AUTO_EXECUTE_ACTIONS = /* @__PURE__ */ new Set([
4929
4951
  "address_book_add",
4930
4952
  "address_book_remove",
4931
4953
  "get_address_book",
4932
- "get_market_price",
4933
4954
  "get_balances",
4934
4955
  "get_portfolio",
4935
4956
  "search_token",
@@ -4941,8 +4962,7 @@ var AUTO_EXECUTE_ACTIONS = /* @__PURE__ */ new Set([
4941
4962
  "sign_tx",
4942
4963
  "sign_typed_data",
4943
4964
  "read_evm_contract",
4944
- "scan_tx",
4945
- "thorchain_query"
4965
+ "scan_tx"
4946
4966
  ]);
4947
4967
  var PASSWORD_REQUIRED_ACTIONS = /* @__PURE__ */ new Set(["sign_tx", "sign_typed_data", "build_custom_tx"]);
4948
4968
 
@@ -5103,7 +5123,9 @@ var AgentExecutor = class {
5103
5123
  case "read_evm_contract":
5104
5124
  return this.readEvmContract(params);
5105
5125
  default:
5106
- return { message: `Action type '${action.type}' not implemented locally` };
5126
+ throw new Error(
5127
+ `Action type '${action.type}' is not implemented locally. The backend may handle this action server-side.`
5128
+ );
5107
5129
  }
5108
5130
  }
5109
5131
  // ============================================================================
@@ -5289,12 +5311,12 @@ var AgentExecutor = class {
5289
5311
  const quote = await this.vault.getSwapQuote({
5290
5312
  fromCoin,
5291
5313
  toCoin,
5292
- amount: parseFloat(amountStr)
5314
+ amount: amountStr
5293
5315
  });
5294
5316
  const swapResult = await this.vault.prepareSwapTx({
5295
5317
  fromCoin,
5296
5318
  toCoin,
5297
- amount: parseFloat(amountStr),
5319
+ amount: amountStr,
5298
5320
  swapQuote: quote,
5299
5321
  autoApprove: true
5300
5322
  });
@@ -5595,6 +5617,11 @@ var AgentExecutor = class {
5595
5617
  * Uses swap params from the tx_ready event to call vault.getSwapQuote → prepareSwapTx.
5596
5618
  */
5597
5619
  async buildAndSignSolanaSwapLocally(serverTxData) {
5620
+ if (serverTxData._phase === "prepare") {
5621
+ throw Object.assign(new Error("tx_ready prepare phase: deferring to server sign path"), {
5622
+ _phase: "prepare"
5623
+ });
5624
+ }
5598
5625
  const fromChainName = serverTxData.from_chain || serverTxData.chain || "Solana";
5599
5626
  const toChainName = serverTxData.to_chain;
5600
5627
  const fromChain = resolveChain(fromChainName);
@@ -5615,10 +5642,17 @@ var AgentExecutor = class {
5615
5642
  });
5616
5643
  const fromCoin = { chain: fromChain, token: fromToken || void 0 };
5617
5644
  const toCoin = { chain: toChain, token: toToken || void 0 };
5618
- const humanAmount = Number(amountStr) / Math.pow(10, fromDecimals);
5645
+ let humanAmount;
5646
+ try {
5647
+ humanAmount = formatUnits(BigInt(amountStr), fromDecimals);
5648
+ } catch {
5649
+ throw Object.assign(new Error(`Invalid amount in tx_ready data for local Solana swap build: ${amountStr}`), {
5650
+ _phase: "prepare"
5651
+ });
5652
+ }
5619
5653
  if (this.verbose)
5620
5654
  process.stderr.write(
5621
- `[solana_local_swap] from=${fromChainName} to=${toChainName || fromChainName} amount=${amountStr}
5655
+ `[solana_local_swap] from=${fromChainName} to=${toChainName || fromChainName} amount=${amountStr} human=${humanAmount}
5622
5656
  `
5623
5657
  );
5624
5658
  if (this.vault.isEncrypted && !this.vault.isUnlocked?.()) {
@@ -5909,19 +5943,21 @@ var AgentExecutor = class {
5909
5943
  // Address Book
5910
5944
  // ============================================================================
5911
5945
  async getAddressBook() {
5912
- return { entries: [], message: "Address book retrieved" };
5946
+ throw new Error("get_address_book is not yet implemented locally. The backend may handle this action server-side.");
5913
5947
  }
5914
- async addAddressBookEntry(params) {
5915
- return { added: true, name: params.name, address: params.address, chain: params.chain };
5948
+ async addAddressBookEntry(_params) {
5949
+ throw new Error("address_book_add is not yet implemented locally. The backend may handle this action server-side.");
5916
5950
  }
5917
- async removeAddressBookEntry(params) {
5918
- return { removed: true, address: params.address };
5951
+ async removeAddressBookEntry(_params) {
5952
+ throw new Error(
5953
+ "address_book_remove is not yet implemented locally. The backend may handle this action server-side."
5954
+ );
5919
5955
  }
5920
5956
  // ============================================================================
5921
5957
  // Token Search & Other
5922
5958
  // ============================================================================
5923
- async searchToken(params) {
5924
- return { message: `Token search for '${params.query || params.symbol}' - delegated to backend` };
5959
+ async searchToken(_params) {
5960
+ throw new Error("search_token is not yet implemented locally. The backend may handle this action server-side.");
5925
5961
  }
5926
5962
  async listVaults() {
5927
5963
  return {
@@ -5935,11 +5971,11 @@ var AgentExecutor = class {
5935
5971
  ]
5936
5972
  };
5937
5973
  }
5938
- async scanTx(params) {
5939
- return { message: `Transaction scan for ${params.tx_hash || "unknown"} - delegated to backend` };
5974
+ async scanTx(_params) {
5975
+ throw new Error("scan_tx is not yet implemented locally. The backend may handle this action server-side.");
5940
5976
  }
5941
- async readEvmContract(params) {
5942
- return { message: `EVM contract read for ${params.contract || "unknown"} - delegated to backend` };
5977
+ async readEvmContract(_params) {
5978
+ throw new Error("read_evm_contract is not yet implemented locally. The backend may handle this action server-side.");
5943
5979
  }
5944
5980
  };
5945
5981
  async function encodeContractCall(functionName, params) {
@@ -8792,7 +8828,7 @@ var cachedVersion = null;
8792
8828
  function getVersion() {
8793
8829
  if (cachedVersion) return cachedVersion;
8794
8830
  if (true) {
8795
- cachedVersion = "0.14.0";
8831
+ cachedVersion = "0.15.0";
8796
8832
  return cachedVersion;
8797
8833
  }
8798
8834
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vultisig/cli",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "Command-line wallet for Vultisig - multi-chain MPC wallet management",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,6 +21,7 @@
21
21
  "cli:interactive": "npx tsx src/index.ts --interactive",
22
22
  "repl": "npx tsx src/index.ts --interactive",
23
23
  "typecheck": "tsc --noEmit",
24
+ "test": "vitest run",
24
25
  "prepublishOnly": "npm run build"
25
26
  },
26
27
  "keywords": [
@@ -53,8 +54,8 @@
53
54
  "@cosmjs/proto-signing": "^0.38.1",
54
55
  "@cosmjs/stargate": "^0.38.1",
55
56
  "@noble/hashes": "^2.0.1",
56
- "@vultisig/rujira": "^9.0.0",
57
- "@vultisig/sdk": "^0.14.1",
57
+ "@vultisig/rujira": "^10.0.0",
58
+ "@vultisig/sdk": "^0.15.1",
58
59
  "chalk": "^5.6.2",
59
60
  "cli-table3": "^0.6.5",
60
61
  "commander": "^14.0.3",
@@ -62,6 +63,7 @@
62
63
  "ora": "^9.3.0",
63
64
  "qrcode-terminal": "^0.12.0",
64
65
  "tabtab": "^3.0.2",
66
+ "viem": "^2.45.1",
65
67
  "ws": "^8.19.0"
66
68
  },
67
69
  "devDependencies": {
@@ -71,7 +73,8 @@
71
73
  "@types/ws": "^8.18.1",
72
74
  "esbuild": "^0.27.4",
73
75
  "tsx": "^4.21.0",
74
- "typescript": "^5.9.3"
76
+ "typescript": "^5.9.3",
77
+ "vitest": "^3.2.4"
75
78
  },
76
79
  "engines": {
77
80
  "node": ">=20.0.0"