@t2000/cli 3.1.1 → 3.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @t2000/cli
2
2
 
3
- A bank account for AI agents on Sui. Guided setup, MCP integration for Claude Desktop / Cursor / Windsurf, send USDC, earn yield, borrow, and pay for APIs. USDC in, USDC out.
3
+ The Agentic Wallet for AI agents on Sui. Guided setup, MCP integration for Claude Desktop / Cursor / Windsurf, send USDC, earn yield, borrow, and pay for APIs. USDC in, USDC out.
4
4
 
5
5
  [![npm](https://img.shields.io/npm/v/@t2000/cli)](https://www.npmjs.com/package/@t2000/cli)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](https://opensource.org/licenses/MIT)
@@ -23,7 +23,7 @@ t2000 init
23
23
 
24
24
  ┌─────────────────────────────────────────┐
25
25
  │ Welcome to t2000 │
26
- A bank account for AI agents │
26
+ Agentic Wallet for AI agents │
27
27
  └─────────────────────────────────────────┘
28
28
 
29
29
  Step 1 of 3 — Create wallet
@@ -33,7 +33,7 @@ t2000 init
33
33
  ✓ Network Sui mainnet
34
34
  ✓ Checking ✓ Savings ✓ Credit
35
35
 
36
- 🎉 Bank account created
36
+ 🎉 Agentic Wallet created
37
37
  Address: 0x8b3e...d412
38
38
 
39
39
  ℹ Fund your wallet with SUI for gas + USDC to transact.
@@ -136,8 +136,8 @@ See the [MCP setup guide](../../docs/mcp-setup.md) for manual configuration.
136
136
  | `t2000 balance` | Show available USDC + savings + gas reserve |
137
137
  | `t2000 balance --show-limits` | Include maxWithdraw, maxBorrow, and health factor |
138
138
  | `t2000 address` | Show wallet address |
139
- | `t2000 deposit` | Show funding instructions |
140
- | `t2000 import` | Import an existing bank account from private key |
139
+ | `t2000 fund` | Show how to fund your Agentic Wallet (receive address + supported networks) |
140
+ | `t2000 import` | Import an existing wallet from private key |
141
141
  | `t2000 export` | Export private key (bech32 `suiprivkey1...` format) |
142
142
  | `t2000 history` | Transaction history |
143
143
 
@@ -256,7 +256,7 @@ Config is stored at `~/.t2000/config.json`.
256
256
 
257
257
  | Variable | Description |
258
258
  |----------|-------------|
259
- | `T2000_PIN` | Bank account PIN (skip interactive prompt) |
259
+ | `T2000_PIN` | Agentic Wallet PIN (skip interactive prompt) |
260
260
  | `T2000_PRIVATE_KEY` | Private key for `t2000 import` (skip interactive prompt) |
261
261
 
262
262
  ## Gas
@@ -281,12 +281,17 @@ Audric (the consumer product on top of the SDK) charges a small overlay fee on s
281
281
  ## Examples
282
282
 
283
283
  ```bash
284
- # Full DeFi cycle
284
+ # Full DeFi cycle (USDC)
285
285
  t2000 save all # Deposit all available USDC
286
286
  t2000 borrow 40 # Borrow against it
287
287
  t2000 repay 40 # Pay it back
288
288
  t2000 withdraw all # Get everything out (USDC by default; pass --asset USDsui for USDsui)
289
289
 
290
+ # Save / borrow / repay in USDsui (strategic stable, v0.51.0+)
291
+ t2000 save 50 --asset USDsui # Deposit USDsui to NAVI
292
+ t2000 borrow 20 --asset USDsui # Borrow USDsui against collateral
293
+ t2000 repay all --asset USDsui # Repay all USDsui debts (must match borrow asset)
294
+
290
295
  # Automation-friendly (no prompts, JSON output)
291
296
  t2000 balance --json
292
297
  t2000 save 10 --yes --json
@@ -16442,159 +16442,6 @@ var require_lodash = __commonJS2({
16442
16442
  module.exports = camelCase;
16443
16443
  }
16444
16444
  });
16445
- var volo_exports = {};
16446
- __export(volo_exports, {
16447
- MIN_STAKE_MIST: () => MIN_STAKE_MIST,
16448
- SUI_SYSTEM_STATE: () => SUI_SYSTEM_STATE,
16449
- VOLO_METADATA: () => VOLO_METADATA,
16450
- VOLO_PKG: () => VOLO_PKG,
16451
- VOLO_POOL: () => VOLO_POOL,
16452
- VSUI_TYPE: () => VSUI_TYPE,
16453
- addStakeVSuiToTx: () => addStakeVSuiToTx,
16454
- addUnstakeVSuiToTx: () => addUnstakeVSuiToTx,
16455
- buildStakeVSuiTx: () => buildStakeVSuiTx,
16456
- buildUnstakeVSuiTx: () => buildUnstakeVSuiTx,
16457
- getVoloStats: () => getVoloStats
16458
- });
16459
- async function getVoloStats() {
16460
- const res = await fetch(VOLO_STATS_URL, {
16461
- signal: AbortSignal.timeout(8e3)
16462
- });
16463
- if (!res.ok) {
16464
- throw new Error(`VOLO stats API error: HTTP ${res.status}`);
16465
- }
16466
- const data = await res.json();
16467
- const d = data.data ?? data;
16468
- return {
16469
- apy: d.apy ?? 0,
16470
- exchangeRate: d.exchange_rate ?? d.exchangeRate ?? 1,
16471
- tvl: d.tvl ?? 0
16472
- };
16473
- }
16474
- async function buildStakeVSuiTx(_client, address, amountMist) {
16475
- if (amountMist < MIN_STAKE_MIST) {
16476
- throw new Error(`Minimum stake is 1 SUI (${MIN_STAKE_MIST} MIST). Got: ${amountMist}`);
16477
- }
16478
- const tx = new Transaction();
16479
- tx.setSender(address);
16480
- const [suiCoin] = tx.splitCoins(tx.gas, [amountMist]);
16481
- const [vSuiCoin] = tx.moveCall({
16482
- target: `${VOLO_PKG}::stake_pool::stake`,
16483
- arguments: [
16484
- tx.object(VOLO_POOL),
16485
- tx.object(VOLO_METADATA),
16486
- tx.object(SUI_SYSTEM_STATE),
16487
- suiCoin
16488
- ]
16489
- });
16490
- tx.transferObjects([vSuiCoin], address);
16491
- return tx;
16492
- }
16493
- async function buildUnstakeVSuiTx(client, address, amountMist) {
16494
- const balResp = await client.getBalance({ owner: address, coinType: VSUI_TYPE });
16495
- const totalBalance = BigInt(balResp.totalBalance);
16496
- if (totalBalance === 0n) {
16497
- throw new Error("No vSUI found in wallet.");
16498
- }
16499
- const tx = new Transaction();
16500
- tx.setSender(address);
16501
- const requested = amountMist === "all" ? totalBalance : amountMist;
16502
- if (requested > totalBalance) {
16503
- throw new Error(`Insufficient vSUI: need ${requested} MIST, have ${totalBalance}`);
16504
- }
16505
- const vSuiCoin = coinWithBalance({ type: VSUI_TYPE, balance: requested })(tx);
16506
- const [suiCoin] = tx.moveCall({
16507
- target: `${VOLO_PKG}::stake_pool::unstake`,
16508
- arguments: [
16509
- tx.object(VOLO_POOL),
16510
- tx.object(VOLO_METADATA),
16511
- tx.object(SUI_SYSTEM_STATE),
16512
- vSuiCoin
16513
- ]
16514
- });
16515
- tx.transferObjects([suiCoin], address);
16516
- return tx;
16517
- }
16518
- async function addStakeVSuiToTx(tx, client, address, input) {
16519
- if (input.amountMist < MIN_STAKE_MIST) {
16520
- throw new Error(`Minimum stake is 1 SUI (${MIN_STAKE_MIST} MIST). Got: ${input.amountMist}`);
16521
- }
16522
- let suiCoin;
16523
- if (input.inputCoin) {
16524
- suiCoin = input.inputCoin;
16525
- } else {
16526
- const balResp = await client.getBalance({ owner: address, coinType: SUI_TYPE });
16527
- const totalBalance = BigInt(balResp.totalBalance);
16528
- if (totalBalance < input.amountMist) {
16529
- throw new Error(`Insufficient SUI: need ${input.amountMist} MIST, have ${totalBalance}`);
16530
- }
16531
- suiCoin = coinWithBalance({
16532
- type: SUI_TYPE,
16533
- balance: input.amountMist,
16534
- useGasCoin: false
16535
- })(tx);
16536
- }
16537
- const [vSuiCoin] = tx.moveCall({
16538
- target: `${VOLO_PKG}::stake_pool::stake`,
16539
- arguments: [
16540
- tx.object(VOLO_POOL),
16541
- tx.object(VOLO_METADATA),
16542
- tx.object(SUI_SYSTEM_STATE),
16543
- suiCoin
16544
- ]
16545
- });
16546
- return { coin: vSuiCoin, effectiveAmountMist: input.amountMist };
16547
- }
16548
- async function addUnstakeVSuiToTx(tx, client, address, input) {
16549
- let vSuiCoin;
16550
- if (input.inputCoin) {
16551
- if (input.amountMist === "all") {
16552
- vSuiCoin = input.inputCoin;
16553
- } else {
16554
- [vSuiCoin] = tx.splitCoins(input.inputCoin, [input.amountMist]);
16555
- }
16556
- } else {
16557
- const balResp = await client.getBalance({ owner: address, coinType: VSUI_TYPE });
16558
- const totalBalance = BigInt(balResp.totalBalance);
16559
- if (totalBalance === 0n) {
16560
- throw new Error("No vSUI found in wallet.");
16561
- }
16562
- const requested = input.amountMist === "all" ? totalBalance : input.amountMist;
16563
- if (requested > totalBalance) {
16564
- throw new Error(`Insufficient vSUI: need ${requested} MIST, have ${totalBalance}`);
16565
- }
16566
- vSuiCoin = coinWithBalance({ type: VSUI_TYPE, balance: requested })(tx);
16567
- }
16568
- const [suiCoin] = tx.moveCall({
16569
- target: `${VOLO_PKG}::stake_pool::unstake`,
16570
- arguments: [
16571
- tx.object(VOLO_POOL),
16572
- tx.object(VOLO_METADATA),
16573
- tx.object(SUI_SYSTEM_STATE),
16574
- vSuiCoin
16575
- ]
16576
- });
16577
- return { coin: suiCoin, effectiveAmountMist: input.amountMist };
16578
- }
16579
- var VOLO_PKG;
16580
- var VOLO_POOL;
16581
- var VOLO_METADATA;
16582
- var VSUI_TYPE;
16583
- var SUI_SYSTEM_STATE;
16584
- var MIN_STAKE_MIST;
16585
- var VOLO_STATS_URL;
16586
- var init_volo = __esm({
16587
- "src/protocols/volo.ts"() {
16588
- init_token_registry();
16589
- VOLO_PKG = "0x68d22cf8bdbcd11ecba1e094922873e4080d4d11133e2443fddda0bfd11dae20";
16590
- VOLO_POOL = "0x2d914e23d82fedef1b5f56a32d5c64bdcc3087ccfea2b4d6ea51a71f587840e5";
16591
- VOLO_METADATA = "0x680cd26af32b2bde8d3361e804c53ec1d1cfe24c7f039eb7f549e8dfde389a60";
16592
- VSUI_TYPE = "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT";
16593
- SUI_SYSTEM_STATE = "0x05";
16594
- MIN_STAKE_MIST = 1000000000n;
16595
- VOLO_STATS_URL = "https://open-api.naviprotocol.io/api/volo/stats";
16596
- }
16597
- });
16598
16445
  var coinSelection_exports = {};
16599
16446
  __export(coinSelection_exports, {
16600
16447
  fetchAllCoins: () => fetchAllCoins,
@@ -16937,6 +16784,63 @@ var init_cetus_swap = __esm({
16937
16784
  clientCache = /* @__PURE__ */ new Map();
16938
16785
  }
16939
16786
  });
16787
+ var swap_quote_exports = {};
16788
+ __export(swap_quote_exports, {
16789
+ getSwapQuote: () => getSwapQuote
16790
+ });
16791
+ async function getSwapQuote(params) {
16792
+ const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
16793
+ const fromType = resolveTokenType2(params.from);
16794
+ const toType = resolveTokenType2(params.to);
16795
+ if (!fromType) {
16796
+ throw new T2000Error(
16797
+ "ASSET_NOT_SUPPORTED",
16798
+ `Unknown token: ${params.from}. Provide the symbol (USDC, SUI, ...) or full coin type.`
16799
+ );
16800
+ }
16801
+ if (!toType) {
16802
+ throw new T2000Error(
16803
+ "ASSET_NOT_SUPPORTED",
16804
+ `Unknown token: ${params.to}. Provide the symbol (USDC, SUI, ...) or full coin type.`
16805
+ );
16806
+ }
16807
+ const byAmountIn = params.byAmountIn ?? true;
16808
+ const fromDecimals = getDecimalsForCoinType(fromType);
16809
+ const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
16810
+ const route = await findSwapRoute2({
16811
+ walletAddress: params.walletAddress,
16812
+ from: fromType,
16813
+ to: toType,
16814
+ amount: rawAmount,
16815
+ byAmountIn,
16816
+ providers: params.providers
16817
+ });
16818
+ if (!route) throw new T2000Error("SWAP_FAILED", `No swap route found for ${params.from} -> ${params.to}.`);
16819
+ if (route.insufficientLiquidity) {
16820
+ throw new T2000Error("SWAP_FAILED", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
16821
+ }
16822
+ const toDecimals = getDecimalsForCoinType(toType);
16823
+ const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
16824
+ const toAmount = Number(route.amountOut) / 10 ** toDecimals;
16825
+ const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
16826
+ const { serializeCetusRoute: serializeCetusRoute2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
16827
+ const serializedRoute = serializeCetusRoute2(route, { fromCoinType: fromType, toCoinType: toType });
16828
+ return {
16829
+ fromToken: params.from,
16830
+ toToken: params.to,
16831
+ fromAmount,
16832
+ toAmount,
16833
+ priceImpact: route.priceImpact,
16834
+ route: routeDesc,
16835
+ serializedRoute
16836
+ };
16837
+ }
16838
+ var init_swap_quote = __esm({
16839
+ "src/swap-quote.ts"() {
16840
+ init_errors();
16841
+ init_token_registry();
16842
+ }
16843
+ });
16940
16844
  init_errors();
16941
16845
  var MIST_PER_SUI = 1000000000n;
16942
16846
  var SUI_DECIMALS = 9;
@@ -17001,7 +16905,8 @@ var SUPPORTED_ASSETS = {
17001
16905
  displayName: "XAUM"
17002
16906
  }
17003
16907
  };
17004
- var STABLE_ASSETS = ["USDC"];
16908
+ var STABLE_ASSETS = ["USDC", "USDsui"];
16909
+ var SAVEABLE_ASSETS = ["USDC", "USDsui"];
17005
16910
  var ALL_NAVI_ASSETS = Object.keys(SUPPORTED_ASSETS);
17006
16911
  var OPERATION_ASSETS = {
17007
16912
  save: ["USDC", "USDsui"],
@@ -21754,7 +21659,7 @@ var ProtocolRegistry = class {
21754
21659
  }
21755
21660
  async bestSaveRateAcrossAssets() {
21756
21661
  const candidates = [];
21757
- for (const asset of STABLE_ASSETS) {
21662
+ for (const asset of SAVEABLE_ASSETS) {
21758
21663
  for (const adapter of this.lending.values()) {
21759
21664
  if (!adapter.supportedAssets.includes(asset)) continue;
21760
21665
  if (!adapter.capabilities.includes("save")) continue;
@@ -21774,7 +21679,7 @@ var ProtocolRegistry = class {
21774
21679
  async allRatesAcrossAssets() {
21775
21680
  const results = [];
21776
21681
  const seen = /* @__PURE__ */ new Set();
21777
- for (const asset of STABLE_ASSETS) {
21682
+ for (const asset of SAVEABLE_ASSETS) {
21778
21683
  if (seen.has(asset)) continue;
21779
21684
  seen.add(asset);
21780
21685
  for (const adapter of this.lending.values()) {
@@ -22370,51 +22275,14 @@ var T2000 = class _T2000 extends import_index.default {
22370
22275
  receipt: paymentDigest ? { reference: paymentDigest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : void 0
22371
22276
  };
22372
22277
  }
22373
- // -- VOLO vSUI Staking --
22374
- async stakeVSui(params) {
22375
- this.enforcer.assertNotLocked();
22376
- const { buildStakeVSuiTx: buildStakeVSuiTx2, getVoloStats: getVoloStats2 } = await Promise.resolve().then(() => (init_volo(), volo_exports));
22377
- const amountMist = BigInt(Math.floor(params.amount * Number(MIST_PER_SUI)));
22378
- const stats = await getVoloStats2();
22379
- const gasResult = await executeTx(this.client, this._signer, async () => {
22380
- return buildStakeVSuiTx2(this.client, this._address, amountMist);
22381
- });
22382
- const vSuiReceived = params.amount / stats.exchangeRate;
22383
- return {
22384
- success: true,
22385
- tx: gasResult.digest,
22386
- amountSui: params.amount,
22387
- vSuiReceived,
22388
- apy: stats.apy,
22389
- gasCost: gasResult.gasCostSui
22390
- };
22391
- }
22392
- async unstakeVSui(params) {
22393
- this.enforcer.assertNotLocked();
22394
- const { buildUnstakeVSuiTx: buildUnstakeVSuiTx2, getVoloStats: getVoloStats2, VSUI_TYPE: VSUI_TYPE2 } = await Promise.resolve().then(() => (init_volo(), volo_exports));
22395
- let amountMist;
22396
- let vSuiAmount;
22397
- if (params.amount === "all") {
22398
- amountMist = "all";
22399
- const bal = await this.client.getBalance({ owner: this._address, coinType: VSUI_TYPE2 });
22400
- vSuiAmount = Number(bal.totalBalance) / 1e9;
22401
- } else {
22402
- amountMist = BigInt(Math.floor(params.amount * 1e9));
22403
- vSuiAmount = params.amount;
22404
- }
22405
- const stats = await getVoloStats2();
22406
- const gasResult = await executeTx(this.client, this._signer, async () => {
22407
- return buildUnstakeVSuiTx2(this.client, this._address, amountMist);
22408
- });
22409
- const suiReceived = vSuiAmount * stats.exchangeRate;
22410
- return {
22411
- success: true,
22412
- tx: gasResult.digest,
22413
- vSuiAmount,
22414
- suiReceived,
22415
- gasCost: gasResult.gasCostSui
22416
- };
22417
- }
22278
+ // [S.323 / 2026-05-25] VOLO vSUI staking surfaces removed (full cut).
22279
+ // Engine cut Volo in S.277; SDK + CLI + MCP followed in S.323 because the
22280
+ // product surface (five products: Passport / Intelligence / Finance / Pay
22281
+ // / Store) doesn't include a staking primitive. vSUI still appears in the
22282
+ // codebase as a passive token (NAVI reward rewards, Cetus swap routing),
22283
+ // but there is no longer any way to MINT or REDEEM vSUI through t2000.
22284
+ // History: see spec/archive/v07e/AUDIT_V07E_EARNS_ITS_KEEP_2026-05-23.md
22285
+ // and the S.323 build-tracker entry.
22418
22286
  // -- Swap --
22419
22287
  async swap(params) {
22420
22288
  this.enforcer.assertNotLocked();
@@ -22522,36 +22390,24 @@ var T2000 = class _T2000 extends import_index.default {
22522
22390
  gasCost: gasResult.gasCostSui
22523
22391
  };
22524
22392
  }
22393
+ /**
22394
+ * [SPEC_AGENTIC_STACK P1 / SDK F2 — 2026-05-25]
22395
+ * Thin wrapper around the standalone `getSwapQuote()`. Pre-Phase 1 this method
22396
+ * was ~50 LoC duplicating `swap-quote.ts` — missing `serializedRoute` (SPEC 20.2
22397
+ * fast-path) and the `providers` allow-list (Bug A fix / Pyth-dependent
22398
+ * provider filter for sponsored callers). Routing both API surfaces through
22399
+ * one implementation ensures fixes land for both.
22400
+ */
22525
22401
  async swapQuote(params) {
22526
- const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
22527
- const fromType = resolveTokenType2(params.from);
22528
- const toType = resolveTokenType2(params.to);
22529
- if (!fromType) throw new T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.from}. Provide the full coin type.`);
22530
- if (!toType) throw new T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.to}. Provide the full coin type.`);
22531
- const byAmountIn = params.byAmountIn ?? true;
22532
- const fromDecimals = getDecimalsForCoinType(fromType);
22533
- const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
22534
- const route = await findSwapRoute2({
22402
+ const { getSwapQuote: getSwapQuote2 } = await Promise.resolve().then(() => (init_swap_quote(), swap_quote_exports));
22403
+ return getSwapQuote2({
22535
22404
  walletAddress: this._address,
22536
- from: fromType,
22537
- to: toType,
22538
- amount: rawAmount,
22539
- byAmountIn
22405
+ from: params.from,
22406
+ to: params.to,
22407
+ amount: params.amount,
22408
+ byAmountIn: params.byAmountIn,
22409
+ providers: params.providers
22540
22410
  });
22541
- if (!route) throw new T2000Error("SWAP_NO_ROUTE", `No swap route found for ${params.from} -> ${params.to}.`);
22542
- if (route.insufficientLiquidity) throw new T2000Error("SWAP_NO_ROUTE", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
22543
- const toDecimals = getDecimalsForCoinType(toType);
22544
- const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
22545
- const toAmount = Number(route.amountOut) / 10 ** toDecimals;
22546
- const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
22547
- return {
22548
- fromToken: params.from,
22549
- toToken: params.to,
22550
- fromAmount,
22551
- toAmount,
22552
- priceImpact: route.priceImpact,
22553
- route: routeDesc
22554
- };
22555
22411
  }
22556
22412
  // -- Wallet --
22557
22413
  address() {
@@ -22682,6 +22538,16 @@ var T2000 = class _T2000 extends import_index.default {
22682
22538
  ].join("\n")
22683
22539
  };
22684
22540
  }
22541
+ /**
22542
+ * [SPEC_AGENTIC_STACK P1 / SDK F2 (CLI rename support) — 2026-05-25]
22543
+ * Preferred alias of `deposit()`. The CLI surface is `t2000 fund` post-Phase 1
22544
+ * (more intuitive than "deposit" which sounds like a NAVI lending action).
22545
+ * `deposit()` stays as the canonical method name for back-compat; it is NOT
22546
+ * deprecated. This wrapper exists so SDK consumers can mirror CLI naming.
22547
+ */
22548
+ async fund() {
22549
+ return this.deposit();
22550
+ }
22685
22551
  receive(params) {
22686
22552
  const amount = params?.amount ?? null;
22687
22553
  const currency = params?.currency ?? "USDC";
@@ -23396,7 +23262,7 @@ var T2000 = class _T2000 extends import_index.default {
23396
23262
  this.emit("yield", {
23397
23263
  earned: result.dailyEarning,
23398
23264
  total: result.totalYieldEarned,
23399
- apy: result.currentApy / 100,
23265
+ apy: result.currentApy,
23400
23266
  timestamp: Date.now()
23401
23267
  });
23402
23268
  }
@@ -23639,7 +23505,6 @@ async function buildHarvestRewardsTx(client, address, options = {}) {
23639
23505
  return { tx, plan };
23640
23506
  }
23641
23507
  init_cetus_swap();
23642
- init_volo();
23643
23508
  init_coinSelection();
23644
23509
  init_token_registry();
23645
23510
  init_errors();
@@ -23863,41 +23728,8 @@ var WRITE_APPENDER_REGISTRY = {
23863
23728
  expectedUsdcDeposited: plan.expectedUsdcDeposited
23864
23729
  }
23865
23730
  };
23866
- },
23867
- volo_stake: async (tx, input, ctx) => {
23868
- if (input.amountSui <= 0) {
23869
- throw new T2000Error("INVALID_AMOUNT", "Stake amount must be greater than zero");
23870
- }
23871
- const amountMist = BigInt(Math.floor(input.amountSui * 1e9));
23872
- const result = await addStakeVSuiToTx(tx, ctx.client, ctx.sender, {
23873
- amountMist,
23874
- inputCoin: ctx.chainedCoin
23875
- });
23876
- if (!ctx.isOutputConsumed) {
23877
- tx.transferObjects([result.coin], ctx.sender);
23878
- }
23879
- return {
23880
- preview: { toolName: "volo_stake", effectiveAmountMist: result.effectiveAmountMist },
23881
- outputCoin: result.coin
23882
- };
23883
- },
23884
- volo_unstake: async (tx, input, ctx) => {
23885
- const amountMist = input.amountVSui === "all" ? "all" : BigInt(Math.floor(input.amountVSui * 1e9));
23886
- if (amountMist !== "all" && amountMist <= 0n) {
23887
- throw new T2000Error("INVALID_AMOUNT", "Unstake amount must be greater than zero");
23888
- }
23889
- const result = await addUnstakeVSuiToTx(tx, ctx.client, ctx.sender, {
23890
- amountMist,
23891
- inputCoin: ctx.chainedCoin
23892
- });
23893
- if (!ctx.isOutputConsumed) {
23894
- tx.transferObjects([result.coin], ctx.sender);
23895
- }
23896
- return {
23897
- preview: { toolName: "volo_unstake", effectiveAmountMist: result.effectiveAmountMist },
23898
- outputCoin: result.coin
23899
- };
23900
23731
  }
23732
+ // [S.323 / 2026-05-25] volo_stake / volo_unstake appenders removed.
23901
23733
  };
23902
23734
  function deriveAllowedAddressesFromPtb(tx) {
23903
23735
  const addresses = /* @__PURE__ */ new Set();
@@ -23958,7 +23790,7 @@ async function composeTx(opts) {
23958
23790
  if (producer.toolName === "save_deposit" || producer.toolName === "repay_debt" || producer.toolName === "send_transfer" || producer.toolName === "claim_rewards") {
23959
23791
  throw new T2000Error(
23960
23792
  "CHAIN_MODE_INVALID",
23961
- `Step ${i} (${step.toolName}) references step ${idx} (${producer.toolName}) as producer, but '${producer.toolName}' is a terminal consumer that does not produce a chainable coin handle. Allowed producers: withdraw, borrow, swap_execute, volo_stake, volo_unstake.`
23793
+ `Step ${i} (${step.toolName}) references step ${idx} (${producer.toolName}) as producer, but '${producer.toolName}' is a terminal consumer that does not produce a chainable coin handle. Allowed producers: withdraw, borrow, swap_execute.`
23962
23794
  );
23963
23795
  }
23964
23796
  consumedSteps.add(idx);
@@ -24167,58 +23999,9 @@ function parseMoveAbort(errorStr) {
24167
23999
  }
24168
24000
  return { reason: errorStr };
24169
24001
  }
24170
- init_errors();
24171
- init_token_registry();
24172
- async function getSwapQuote(params) {
24173
- const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
24174
- const fromType = resolveTokenType2(params.from);
24175
- const toType = resolveTokenType2(params.to);
24176
- if (!fromType) {
24177
- throw new T2000Error(
24178
- "ASSET_NOT_SUPPORTED",
24179
- `Unknown token: ${params.from}. Provide the symbol (USDC, SUI, ...) or full coin type.`
24180
- );
24181
- }
24182
- if (!toType) {
24183
- throw new T2000Error(
24184
- "ASSET_NOT_SUPPORTED",
24185
- `Unknown token: ${params.to}. Provide the symbol (USDC, SUI, ...) or full coin type.`
24186
- );
24187
- }
24188
- const byAmountIn = params.byAmountIn ?? true;
24189
- const fromDecimals = getDecimalsForCoinType(fromType);
24190
- const rawAmount = BigInt(Math.floor(params.amount * 10 ** fromDecimals));
24191
- const route = await findSwapRoute2({
24192
- walletAddress: params.walletAddress,
24193
- from: fromType,
24194
- to: toType,
24195
- amount: rawAmount,
24196
- byAmountIn,
24197
- providers: params.providers
24198
- });
24199
- if (!route) throw new T2000Error("SWAP_FAILED", `No swap route found for ${params.from} -> ${params.to}.`);
24200
- if (route.insufficientLiquidity) {
24201
- throw new T2000Error("SWAP_FAILED", `Insufficient liquidity for ${params.from} -> ${params.to}.`);
24202
- }
24203
- const toDecimals = getDecimalsForCoinType(toType);
24204
- const fromAmount = Number(route.amountIn) / 10 ** fromDecimals;
24205
- const toAmount = Number(route.amountOut) / 10 ** toDecimals;
24206
- const routeDesc = route.routerData.paths?.map((p) => p.provider).filter(Boolean).slice(0, 3).join(" + ") ?? "Cetus Aggregator";
24207
- const { serializeCetusRoute: serializeCetusRoute2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
24208
- const serializedRoute = serializeCetusRoute2(route, { fromCoinType: fromType, toCoinType: toType });
24209
- return {
24210
- fromToken: params.from,
24211
- toToken: params.to,
24212
- fromAmount,
24213
- toAmount,
24214
- priceImpact: route.priceImpact,
24215
- route: routeDesc,
24216
- serializedRoute
24217
- };
24218
- }
24002
+ init_swap_quote();
24219
24003
  init_cetus_swap();
24220
24004
  init_token_registry();
24221
- init_volo();
24222
24005
  var AUDRIC_PARENT_NAME = "audric.sui";
24223
24006
  var AUDRIC_PARENT_NFT_ID = "0x070456e283ec988b6302bdd6cc5172bbdcb709998cf116586fb98d19b0870198";
24224
24007
  var LABEL_PATTERN = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
@@ -24308,15 +24091,6 @@ export {
24308
24091
  IKA_TYPE,
24309
24092
  LOFI_TYPE,
24310
24093
  MANIFEST_TYPE,
24311
- getVoloStats,
24312
- buildStakeVSuiTx,
24313
- buildUnstakeVSuiTx,
24314
- addStakeVSuiToTx,
24315
- addUnstakeVSuiToTx,
24316
- VOLO_PKG,
24317
- VOLO_POOL,
24318
- VOLO_METADATA,
24319
- VSUI_TYPE,
24320
24094
  fetchAllCoins,
24321
24095
  selectAndSplitCoin,
24322
24096
  selectSuiCoin,
@@ -24328,6 +24102,7 @@ export {
24328
24102
  buildSwapTx,
24329
24103
  addSwapToTx,
24330
24104
  OVERLAY_FEE_RATE,
24105
+ getSwapQuote,
24331
24106
  MIST_PER_SUI,
24332
24107
  SUI_DECIMALS,
24333
24108
  USDC_DECIMALS,
@@ -24337,6 +24112,7 @@ export {
24337
24112
  CLOCK_ID,
24338
24113
  SUPPORTED_ASSETS,
24339
24114
  STABLE_ASSETS,
24115
+ SAVEABLE_ASSETS,
24340
24116
  ALL_NAVI_ASSETS,
24341
24117
  OPERATION_ASSETS,
24342
24118
  isAllowedAsset,
@@ -24423,7 +24199,6 @@ export {
24423
24199
  getFinancialSummary,
24424
24200
  simulateTransaction,
24425
24201
  throwIfSimulationFailed,
24426
- getSwapQuote,
24427
24202
  AUDRIC_PARENT_NAME,
24428
24203
  AUDRIC_PARENT_NFT_ID,
24429
24204
  validateLabel,
@@ -24455,4 +24230,4 @@ axios/dist/node/axios.cjs:
24455
24230
  @scure/bip39/index.js:
24456
24231
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
24457
24232
  */
24458
- //# sourceMappingURL=chunk-R7KXQRHQ.js.map
24233
+ //# sourceMappingURL=chunk-YSV3YXTK.js.map