@t2000/sdk 1.5.0 → 1.7.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/dist/index.d.ts CHANGED
@@ -1,13 +1,13 @@
1
1
  import { EventEmitter } from 'eventemitter3';
2
2
  import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
3
3
  import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
4
- import { V as TxMetadata, q as SafeguardConfig, T as T2000Error, R as TransactionSigner, a1 as ZkLoginProof, x as SupportedAsset } from './types-BhiUiiNs.js';
5
- export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, aB as CETUS_USDC_SUI_POOL, C as CLOCK_ID, b as COIN_REGISTRY, c as ClassifyBalanceChange, d as ClassifyResult, e as CoinMeta, D as DEFAULT_NETWORK, f as DEFAULT_SAFEGUARD_CONFIG, E as ETH_TYPE, g as ExtractedTransfer, F as FeeOperation, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, aC as OPERATION_ASSETS, O as OUTBOUND_OPS, k as OVERLAY_FEE_RATE, aD as Operation, l as OverlayFeeConfig, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, m as STABLE_ASSETS, n as SUI_DECIMALS, o as SUI_TYPE, p as SUPPORTED_ASSETS, r as SafeguardError, s as SafeguardErrorDetails, t as SafeguardRule, u as SimulationResult, v as StableAsset, w as SuiRpcTxBlock, y as SwapRouteResult, z as T2000ErrorCode, H as T2000ErrorData, J as T2000_OVERLAY_FEE_WALLET, Q as TOKEN_MAP, U as TxDirection, W as USDC_DECIMALS, X as USDC_TYPE, Y as USDE_TYPE, Z as USDSUI_TYPE, _ as USDT_TYPE, $ as WAL_TYPE, a0 as WBTC_TYPE, a2 as ZkLoginSigner, a3 as addFeeTransfer, aE as assertAllowedAsset, a4 as buildSwapTx, a5 as calculateFee, a6 as classifyAction, a7 as classifyLabel, a8 as classifyTransaction, a9 as extractTransferDetails, aa as extractTxCommands, ab as extractTxSender, ac as fallbackLabel, ad as findSwapRoute, ae as formatAssetAmount, af as formatSui, ag as formatUsd, aF as getCoinMeta, ah as getDecimals, ai as getDecimalsForCoinType, aj as getTier, aG as isAllowedAsset, aH as isInRegistry, ak as isSupported, al as isTier1, am as isTier2, an as mapMoveAbortCode, ao as mapWalletError, ap as mistToSui, aI as normalizeCoinType, aq as parseSuiRpcTx, aJ as queryHistory, aK as queryTransaction, ar as rawToStable, as as rawToUsdc, at as refineLendingLabel, au as resolveSymbol, av as resolveTokenType, aL as simulateTransaction, aw as stableToRaw, ax as suiToMist, aM as throwIfSimulationFailed, ay as truncateAddress, az as usdcToRaw, aA as validateAddress } from './types-BhiUiiNs.js';
4
+ import { V as TxMetadata, q as SafeguardConfig, T as T2000Error, R as TransactionSigner, a1 as ZkLoginProof, x as SupportedAsset, l as OverlayFeeConfig, y as SwapRouteResult } from './types-B0VlW8Ov.js';
5
+ export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, aB as CETUS_USDC_SUI_POOL, C as CLOCK_ID, b as COIN_REGISTRY, c as ClassifyBalanceChange, d as ClassifyResult, e as CoinMeta, D as DEFAULT_NETWORK, f as DEFAULT_SAFEGUARD_CONFIG, E as ETH_TYPE, g as ExtractedTransfer, F as FeeOperation, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, aC as OPERATION_ASSETS, O as OUTBOUND_OPS, k as OVERLAY_FEE_RATE, aD as Operation, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, m as STABLE_ASSETS, n as SUI_DECIMALS, o as SUI_TYPE, p as SUPPORTED_ASSETS, r as SafeguardError, s as SafeguardErrorDetails, t as SafeguardRule, u as SimulationResult, v as StableAsset, w as SuiRpcTxBlock, z as T2000ErrorCode, H as T2000ErrorData, J as T2000_OVERLAY_FEE_WALLET, Q as TOKEN_MAP, U as TxDirection, W as USDC_DECIMALS, X as USDC_TYPE, Y as USDE_TYPE, Z as USDSUI_TYPE, _ as USDT_TYPE, $ as WAL_TYPE, a0 as WBTC_TYPE, a2 as ZkLoginSigner, a3 as addFeeTransfer, aE as addSwapToTx, aF as assertAllowedAsset, a4 as buildSwapTx, a5 as calculateFee, a6 as classifyAction, a7 as classifyLabel, a8 as classifyTransaction, a9 as extractTransferDetails, aa as extractTxCommands, ab as extractTxSender, ac as fallbackLabel, ad as findSwapRoute, ae as formatAssetAmount, af as formatSui, ag as formatUsd, aG as getCoinMeta, ah as getDecimals, ai as getDecimalsForCoinType, aj as getTier, aH as isAllowedAsset, aI as isInRegistry, ak as isSupported, al as isTier1, am as isTier2, an as mapMoveAbortCode, ao as mapWalletError, ap as mistToSui, aJ as normalizeCoinType, aq as parseSuiRpcTx, aK as queryHistory, aL as queryTransaction, ar as rawToStable, as as rawToUsdc, at as refineLendingLabel, au as resolveSymbol, av as resolveTokenType, aM as simulateTransaction, aw as stableToRaw, ax as suiToMist, aN as throwIfSimulationFailed, ay as truncateAddress, az as usdcToRaw, aA as validateAddress } from './types-B0VlW8Ov.js';
6
6
  import { L as LendingAdapter, a as LendingRates, P as PendingReward$1 } from './descriptors-BnbL3xN8.js';
7
7
  export { A as AdapterCapability, b as AdapterPositions, c as AdapterTxResult, H as HealthInfo, d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from './descriptors-BnbL3xN8.js';
8
8
  import { i as T2000Options, P as PayOptions, c as PayResult, j as StakeVSuiResult, U as UnstakeVSuiResult, k as SwapResult, l as SwapQuoteResult, h as SendResult, B as BalanceResponse, T as TransactionRecord, D as DepositInfo, m as PaymentRequest, S as SaveResult, W as WithdrawResult, b as MaxWithdrawResult, a as BorrowResult, g as RepayResult, M as MaxBorrowResult, H as HealthFactorResult, d as PendingReward, C as ClaimRewardsResult, n as CompoundRewardsResult, f as PositionsResult, R as RatesResult, E as EarningsResult, F as FundStatusResult, o as FinancialSummary } from './types-jAD-e7Pq.js';
9
9
  export { A as AssetRates, G as GasReserve, p as HFAlertLevel, e as PositionEntry } from './types-jAD-e7Pq.js';
10
- import { Transaction } from '@mysten/sui/transactions';
10
+ import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
11
11
  export { NaviAdapter, ProtocolRegistry } from './adapters/index.js';
12
12
  import '@cetusprotocol/aggregator-sdk';
13
13
 
@@ -233,6 +233,490 @@ declare function walletExists(keyPath?: string): Promise<boolean>;
233
233
  declare function exportPrivateKey(keypair: Ed25519Keypair): string;
234
234
  declare function getAddress(keypair: Ed25519Keypair): string;
235
235
 
236
+ declare function buildSendTx({ client, address, to, amount, asset, }: {
237
+ client: SuiJsonRpcClient;
238
+ address: string;
239
+ to: string;
240
+ amount: number;
241
+ asset?: SupportedAsset;
242
+ }): Promise<Transaction>;
243
+ /**
244
+ * Fragment-appender for the chain-mode send leg of SPEC 7 multi-write
245
+ * PTBs. Consumes a coin reference produced by a previous appender (e.g.
246
+ * `addWithdrawToTx`, `addSwapToTx`) and transfers it to `recipient`
247
+ * within the same PTB — no intermediate wallet materialization.
248
+ *
249
+ * Codifies the hand-built send leg from
250
+ * `scripts/smoke-spec7-withdraw-then-send.ts` (P2.1) into a typed
251
+ * appender. SPEC 7 § "Layer 1" — P2.2b will register this in the
252
+ * `WRITE_APPENDER_REGISTRY` under `send_transfer` for chain-mode
253
+ * dispatch; the registry adapter will handle the wallet-fetch fallback
254
+ * by delegating to `buildSendTx` when no upstream coin is available.
255
+ *
256
+ * For single-step send_transfer flows (no chained predecessor), use
257
+ * `buildSendTx` directly — it builds a complete tx including the
258
+ * wallet-coin selection / merge / split prelude.
259
+ *
260
+ * @returns void — the coin is consumed by `tx.transferObjects`. Callers
261
+ * that need the post-transfer "effective amount" should rely on the
262
+ * upstream appender's `effectiveAmount` (e.g. `addWithdrawToTx`'s
263
+ * return), not on this appender.
264
+ */
265
+ declare function addSendToTx(tx: Transaction, coin: TransactionObjectArgument, recipient: string): void;
266
+
267
+ /**
268
+ * Wallet-side coin selection helpers — shared paginated coin lookup +
269
+ * merge + split prelude used by every wallet-mode appender that needs
270
+ * a `TransactionObjectArgument` reference to a specific amount of a
271
+ * given coin type.
272
+ *
273
+ * Replaces three earlier inline implementations:
274
+ * - `cetus-swap.ts:fetchAllCoinsForSwap` (kept for backwards-compat,
275
+ * delegates here)
276
+ * - `volo.ts:fetchCoinsByType` (kept for backwards-compat, delegates
277
+ * here)
278
+ * - audric host's `transactions/prepare/route.ts:fetchCoinsForSwap`
279
+ * (P2.2c retires this when migrating to `composeTx`)
280
+ *
281
+ * Single source of truth for the "fetch coins of type X owned by
282
+ * address Y, paginated" pattern. P2.2b extracts this so `composeTx`'s
283
+ * registry adapters can build a wallet-mode `TransactionObjectArgument`
284
+ * uniformly across save / send / repay / etc.
285
+ */
286
+
287
+ interface CoinPage {
288
+ ids: string[];
289
+ totalBalance: bigint;
290
+ }
291
+ /**
292
+ * Paginated coin lookup. Fetches every coin object of `coinType` owned
293
+ * by `owner` (walks the cursor until `hasNextPage === false`). Returns
294
+ * the list of object IDs + summed balance.
295
+ *
296
+ * Replaces inline `client.getCoins` calls that miss coins on the second
297
+ * page when wallets accumulate many small coin objects (the bug class
298
+ * that bit `buildSendTx` pre-P2.2 — captured for SPEC 12).
299
+ */
300
+ declare function fetchAllCoins(client: SuiJsonRpcClient, owner: string, coinType: string): Promise<CoinPage>;
301
+ interface SelectAndSplitResult {
302
+ /** TransactionObjectArgument for a coin holding `effectiveAmount` raw units. */
303
+ coin: TransactionObjectArgument;
304
+ /** Actual raw amount the returned coin holds. May be < requested if `swapAll` is true. */
305
+ effectiveAmount: bigint;
306
+ /** True iff the request consumed the entire wallet balance (no split needed). */
307
+ swapAll: boolean;
308
+ }
309
+ /**
310
+ * Wallet-mode coin selection prelude. Fetches every coin of `coinType`
311
+ * owned by `owner`, merges them into a primary, and splits off the
312
+ * requested `amount` (or returns the merged primary directly if the
313
+ * request meets/exceeds the total balance — `swapAll` semantics).
314
+ *
315
+ * Throws `T2000Error` (`INSUFFICIENT_BALANCE`) when:
316
+ * - No coins of `coinType` exist for `owner`
317
+ * - `amount` is bigger than the total balance AND the caller did NOT
318
+ * opt into `swapAll: true` clipping
319
+ *
320
+ * Used by:
321
+ * - `composeTx` registry adapters (save_deposit, send_transfer,
322
+ * repay_debt — non-SUI assets) for the wallet-mode prelude
323
+ * - Layer 1 dual-mode appenders (`addSwapToTx`, `addStakeVSuiToTx`,
324
+ * `addUnstakeVSuiToTx`) when `inputCoin` is omitted
325
+ *
326
+ * @param tx — PTB to append `mergeCoins` + `splitCoins` commands to.
327
+ * @param client — Sui RPC client for the paginated `getCoins` lookup.
328
+ * @param owner — wallet address whose coins to fetch.
329
+ * @param coinType — fully-qualified Sui coin type
330
+ * (`"0x...::usdc::USDC"`).
331
+ * @param amount — raw amount to split out (in MIST / smallest unit).
332
+ * Pass `'all'` to consume the entire merged primary directly.
333
+ * @param options.allowSwapAll — if true (default), `amount` >=
334
+ * totalBalance auto-clips to total (matches audric host's swap
335
+ * branch). If false, throws `INSUFFICIENT_BALANCE` when over.
336
+ *
337
+ * @returns
338
+ * - `coin` — `TransactionObjectArgument` ready for downstream
339
+ * consumption (e.g. `addSaveToTx`, `tx.transferObjects`).
340
+ * - `effectiveAmount` — the raw amount the returned coin actually
341
+ * holds (handles swapAll clipping).
342
+ * - `swapAll` — true iff the entire merged primary was consumed.
343
+ */
344
+ declare function selectAndSplitCoin(tx: Transaction, client: SuiJsonRpcClient, owner: string, coinType: string, amount: bigint | 'all', options?: {
345
+ allowSwapAll?: boolean;
346
+ }): Promise<SelectAndSplitResult>;
347
+ /**
348
+ * SUI-specific coin selection. Branches on sponsorship context:
349
+ *
350
+ * - **Sponsored (`sponsoredContext: true`)** — fetches SUI coins via
351
+ * `getCoins` and merges/splits, because `tx.gas` belongs to the
352
+ * Enoki sponsor (NOT the user) under sponsored flows. Same shape as
353
+ * `selectAndSplitCoin` for any other coin type.
354
+ *
355
+ * - **Self-funded (`sponsoredContext: false`)** — splits from `tx.gas`
356
+ * directly (the user's gas coin IS their SUI). More efficient — no
357
+ * getCoins RTT.
358
+ *
359
+ * Captures the SUI-vs-other-asset divergence that lives inline in
360
+ * `buildSendTx` today (`tx.splitCoins(tx.gas, ...)` vs paginated
361
+ * lookup). composeTx's `send_transfer` adapter routes through this
362
+ * helper to handle both.
363
+ */
364
+ declare function selectSuiCoin(tx: Transaction, client: SuiJsonRpcClient, owner: string, amountMist: bigint, sponsoredContext: boolean): Promise<SelectAndSplitResult>;
365
+
366
+ /**
367
+ * SPEC 7 v0.4 § Layer 0 — Canonical Write Architecture.
368
+ *
369
+ * `composeTx({ steps })` is the single canonical entry-point for every
370
+ * Audric Enoki-sponsored write. The fragment-appender pattern (Layer 1)
371
+ * is the implementation; this primitive dispatches each step to its
372
+ * registered appender from the typed `WRITE_APPENDER_REGISTRY`.
373
+ *
374
+ * Single-write and multi-write go through the same code path. A 1-step
375
+ * `composeTx([{ toolName: 'send_transfer', input: {...} }])` produces
376
+ * the same shape of result as a 3-step bundle.
377
+ *
378
+ * **Why this exists**
379
+ *
380
+ * Pre-Layer-0, four parallel write stacks lived across the audric host:
381
+ * `transactions/prepare` (fat ~600-line route), `services/prepare`
382
+ * (hand-rolled), `debug-swap` (diagnostic), and PayButton (dapp-kit).
383
+ * Each one re-implemented merge/split/transfer + hand-maintained the
384
+ * `allowedAddresses` array Enoki requires. Two production bugs in the
385
+ * past 60 days came from drift between them — PR-H1 (claim-rewards
386
+ * self-transfer missing from allowedAddresses) and PR-H4 (borrow/
387
+ * withdraw self-transfer same bug).
388
+ *
389
+ * Layer 0 collapses 3 of those stacks into one canonical primitive.
390
+ * PayButton stays out by design (different signer, different trust
391
+ * model — see `audric-canonical-write.mdc` for the rationale and the
392
+ * `// CANONICAL-BYPASS:` escape-hatch contract).
393
+ *
394
+ * **What composeTx owns**
395
+ *
396
+ * - PTB assembly via per-tool wallet-mode appenders (the
397
+ * `WRITE_APPENDER_REGISTRY`).
398
+ * - Pre-built `txKindBytes` (`tx.build({ onlyTransactionKind: true })`)
399
+ * ready for Enoki's `createSponsoredTransaction`.
400
+ * - Auto-derived `derivedAllowedAddresses` from the assembled PTB's
401
+ * top-level `transferObjects` calls — eliminates the PR-H1/H4 bug
402
+ * class permanently. Hand-maintained arrays are now unreachable.
403
+ * - S.38 Pyth flag plumbing — `sponsoredContext: true` automatically
404
+ * applies `skipPythUpdate` (borrow/withdraw) and `skipOracle` (repay)
405
+ * to NAVI appenders so Enoki doesn't reject `tx.gas`-as-argument.
406
+ *
407
+ * **What composeTx does NOT own**
408
+ *
409
+ * - **Fees** — Audric concern, not @t2000/sdk concern (CLAUDE.md
410
+ * rule #9). The SDK is fee-free by design as of @t2000/sdk@1.1.0
411
+ * (B5 v2). Audric host wraps composeTx with fee insertion in P2.2c.
412
+ * - **Sponsorship** — caller's job. composeTx returns `txKindBytes`
413
+ * pre-built for Enoki; the caller calls `createSponsoredTransaction`
414
+ * with their JWT.
415
+ * - **Chain-mode coin handoff between steps** — Layer 2 (engine
416
+ * bundling) ships this. P2.2b is wallet-mode-only: each step fetches
417
+ * coins independently. Layer 2 will extend by introducing
418
+ * `inputCoinFromStep: number` to thread upstream output coins.
419
+ *
420
+ * **Cross-references**
421
+ *
422
+ * - Spec → `spec/SPEC_7_MULTI_WRITE_PTB.md` § "Layer 0: Canonical
423
+ * Write Architecture"
424
+ * - Read-side companion → `t2000/.cursor/rules/single-source-of-truth.mdc`
425
+ * + `audric/.cursor/rules/audric-canonical-portfolio.mdc`
426
+ * - Write-side rule → `audric/.cursor/rules/audric-canonical-write.mdc`
427
+ */
428
+
429
+ /**
430
+ * Canonical write tools. The 9 tools that can be composed into a PTB.
431
+ *
432
+ * Excluded by design:
433
+ * - `pay_api` — recipient/amount unknown at compose time; the on-chain
434
+ * leg uses `send_transfer` after the gateway 402 challenge resolves.
435
+ * - `save_contact` — no on-chain leg (Prisma-only).
436
+ */
437
+ type WriteToolName = 'save_deposit' | 'withdraw' | 'borrow' | 'repay_debt' | 'send_transfer' | 'swap_execute' | 'claim_rewards' | 'volo_stake' | 'volo_unstake';
438
+ interface SaveDepositInput {
439
+ amount: number;
440
+ asset?: 'USDC' | 'USDsui';
441
+ }
442
+ interface WithdrawInput {
443
+ amount: number;
444
+ asset?: 'USDC' | 'USDsui';
445
+ }
446
+ interface BorrowInput {
447
+ amount: number;
448
+ asset?: 'USDC' | 'USDsui';
449
+ }
450
+ interface RepayDebtInput {
451
+ amount: number;
452
+ asset?: 'USDC' | 'USDsui';
453
+ }
454
+ interface SendTransferInput {
455
+ to: string;
456
+ amount: number;
457
+ asset?: SupportedAsset;
458
+ }
459
+ interface SwapExecuteInput {
460
+ from: string;
461
+ to: string;
462
+ amount: number;
463
+ slippage?: number;
464
+ byAmountIn?: boolean;
465
+ /** Cetus provider allow-list. Sponsored callers MUST pass an exclusion list
466
+ * to remove Pyth-dependent providers — see addSwapToTx JSDoc. composeTx
467
+ * derives this automatically from `sponsoredContext` if omitted. */
468
+ providers?: string[];
469
+ }
470
+ type ClaimRewardsInput = Record<string, never>;
471
+ interface VoloStakeInput {
472
+ amountSui: number;
473
+ }
474
+ interface VoloUnstakeInput {
475
+ amountVSui: number | 'all';
476
+ }
477
+ /**
478
+ * Discriminated union mapping `toolName` → `input`. Used to type
479
+ * `WriteStep` so consumers get autocomplete + compile-time validation
480
+ * that the input matches the tool.
481
+ */
482
+ type WriteStep = {
483
+ toolName: 'save_deposit';
484
+ input: SaveDepositInput;
485
+ } | {
486
+ toolName: 'withdraw';
487
+ input: WithdrawInput;
488
+ } | {
489
+ toolName: 'borrow';
490
+ input: BorrowInput;
491
+ } | {
492
+ toolName: 'repay_debt';
493
+ input: RepayDebtInput;
494
+ } | {
495
+ toolName: 'send_transfer';
496
+ input: SendTransferInput;
497
+ } | {
498
+ toolName: 'swap_execute';
499
+ input: SwapExecuteInput;
500
+ } | {
501
+ toolName: 'claim_rewards';
502
+ input: ClaimRewardsInput;
503
+ } | {
504
+ toolName: 'volo_stake';
505
+ input: VoloStakeInput;
506
+ } | {
507
+ toolName: 'volo_unstake';
508
+ input: VoloUnstakeInput;
509
+ };
510
+ interface ComposeTxOptions {
511
+ sender: string;
512
+ steps: WriteStep[];
513
+ client: SuiJsonRpcClient;
514
+ /**
515
+ * S.38 Pyth flag (sponsorship-critical). When true:
516
+ * - NAVI borrow/withdraw appenders apply `skipPythUpdate: true`
517
+ * (preserves on-chain price-feed updates, skips the tx.gas-using
518
+ * Pyth fee payment that Enoki rejects).
519
+ * - NAVI repay appender applies `skipOracle: true` (debt reduction
520
+ * has no health-factor risk, full oracle bypass is safe).
521
+ * - Cetus swap appender applies `getProvidersExcluding([HAEDALPMM,
522
+ * METASTABLE, OBRIC, STEAMM_OMM, STEAMM_OMM_V2, SEVENK,
523
+ * HAEDALHMMV2])` — Pyth-dependent providers reference `tx.gas` for
524
+ * oracle fees, also rejected by Enoki.
525
+ * - SUI sends fetch coins via `getCoins` (tx.gas belongs to sponsor,
526
+ * not user) instead of splitting from `tx.gas`.
527
+ *
528
+ * Self-funded callers (CLI, MCP, server tasks) leave this `false` /
529
+ * omit — they pay all oracle/Pyth fees from their own SUI gas.
530
+ */
531
+ sponsoredContext?: boolean;
532
+ /**
533
+ * Per-call overlay fee config for Cetus swaps. Audric host passes
534
+ * `{ rate: 0.001, receiver: T2000_OVERLAY_FEE_WALLET }` to charge the
535
+ * 0.1% swap overlay. CLI / direct SDK callers omit. Forwarded to
536
+ * `addSwapToTx`'s `input.overlayFee`.
537
+ */
538
+ overlayFee?: OverlayFeeConfig;
539
+ /**
540
+ * Optional fee-injection hooks for save_deposit + borrow. Fires inside
541
+ * the appender at the exact moment the user's coin is in hand and BEFORE
542
+ * the protocol step consumes (save) or the canonical transferObjects
543
+ * finalizes (borrow). Audric host uses this to inline `addFeeTransfer`
544
+ * for USDC SAVE_FEE_BPS / BORROW_FEE_BPS without ever leaving the
545
+ * canonical write contract — keeps the SDK fee-free per CLAUDE.md
546
+ * rule #9 while letting hosts charge their own overlay fees.
547
+ *
548
+ * Hooks are fire-and-forget (no return value). They mutate `tx` directly
549
+ * (e.g., `addFeeTransfer(tx, coin, ...)` splits the fee chunk off and
550
+ * appends a top-level `transferObjects` to the host's fee wallet — that
551
+ * recipient automatically appears in `derivedAllowedAddresses`).
552
+ */
553
+ feeHooks?: ComposeTxFeeHooks;
554
+ }
555
+ /**
556
+ * Per-tool fee-injection callbacks. Each hook fires at a tool-specific
557
+ * moment in the appender flow (see field JSDoc). Currently scoped to
558
+ * the 2 fee-eligible tools — extend if/when new ones land.
559
+ */
560
+ interface ComposeTxFeeHooks {
561
+ /**
562
+ * Fires inside the `save_deposit` appender AFTER the user's USDC/USDsui
563
+ * coin is split into the deposit amount, BEFORE NAVI's `deposit` move
564
+ * call consumes the coin. Order matters: the `coin` reference passed in
565
+ * is the SAME `TransactionObjectArgument` that flows into the deposit,
566
+ * so any `splitCoins(coin, [feeAmount])` inside the hook reduces the
567
+ * deposit by exactly that fee.
568
+ */
569
+ save_deposit?: (ctx: ComposeTxFeeHookContext<SaveDepositInput>) => void | Promise<void>;
570
+ /**
571
+ * Fires inside the `borrow` appender AFTER NAVI returns the borrowed
572
+ * coin, BEFORE the canonical `transferObjects(coin, sender)` finalizes.
573
+ * The `coin` reference is the borrowed-and-not-yet-transferred output;
574
+ * splitting a fee here means the user receives the remainder.
575
+ */
576
+ borrow?: (ctx: ComposeTxFeeHookContext<BorrowInput>) => void | Promise<void>;
577
+ }
578
+ /**
579
+ * Context object passed to every fee hook. Carries the `tx` (mutate it),
580
+ * the in-flight `coin` (split fees off it), the resolved tool input
581
+ * (asset/amount for fee-policy decisions), and the sender (rarely needed
582
+ * but kept for symmetry with `AppenderContext`).
583
+ */
584
+ interface ComposeTxFeeHookContext<TInput> {
585
+ tx: Transaction;
586
+ coin: TransactionObjectArgument;
587
+ input: TInput;
588
+ sender: string;
589
+ }
590
+ /** Per-step preview returned by each registry appender. Tool-specific shape. */
591
+ type StepPreview = {
592
+ toolName: 'save_deposit';
593
+ effectiveAmount: number;
594
+ asset: 'USDC' | 'USDsui';
595
+ } | {
596
+ toolName: 'withdraw';
597
+ effectiveAmount: number;
598
+ asset: 'USDC' | 'USDsui';
599
+ } | {
600
+ toolName: 'borrow';
601
+ effectiveAmount: number;
602
+ asset: 'USDC' | 'USDsui';
603
+ } | {
604
+ toolName: 'repay_debt';
605
+ effectiveAmount: number;
606
+ asset: 'USDC' | 'USDsui';
607
+ } | {
608
+ toolName: 'send_transfer';
609
+ effectiveAmount: number;
610
+ recipient: string;
611
+ asset: SupportedAsset;
612
+ } | {
613
+ toolName: 'swap_execute';
614
+ effectiveAmountIn: number;
615
+ expectedAmountOut: number;
616
+ route: SwapRouteResult;
617
+ } | {
618
+ toolName: 'claim_rewards';
619
+ rewards: PendingReward$1[];
620
+ } | {
621
+ toolName: 'volo_stake';
622
+ effectiveAmountMist: bigint;
623
+ } | {
624
+ toolName: 'volo_unstake';
625
+ effectiveAmountMist: bigint | 'all';
626
+ };
627
+ interface ComposeTxResult {
628
+ tx: Transaction;
629
+ /**
630
+ * Pre-built bytes for Enoki's `createSponsoredTransaction`. Built
631
+ * with `onlyTransactionKind: true` so the gas coin can be supplied
632
+ * by the sponsor.
633
+ */
634
+ txKindBytes: Uint8Array;
635
+ /**
636
+ * Auto-derived from the assembled PTB's top-level `transferObjects`
637
+ * commands. Replaces hand-maintained `allowedAddresses` arrays in
638
+ * audric host's `transactions/prepare` + `services/prepare` —
639
+ * eliminates the PR-H1/H4 bug class permanently.
640
+ */
641
+ derivedAllowedAddresses: string[];
642
+ perStepPreviews: StepPreview[];
643
+ }
644
+ /**
645
+ * Per-appender context passed into every registry entry. Carries the
646
+ * RPC client, sender, sponsorship flag, and optional per-call overlay
647
+ * fee config (Cetus swaps).
648
+ */
649
+ interface AppenderContext {
650
+ client: SuiJsonRpcClient;
651
+ sender: string;
652
+ sponsoredContext: boolean;
653
+ overlayFee?: OverlayFeeConfig;
654
+ feeHooks?: ComposeTxFeeHooks;
655
+ }
656
+ type AppenderFn<TInput, TPreview extends StepPreview> = (tx: Transaction, input: TInput, ctx: AppenderContext) => Promise<TPreview>;
657
+ /**
658
+ * The typed registry. Each entry is a wallet-mode dispatcher that takes
659
+ * (tx, input, ctx) and returns a per-step preview. Compile-time check
660
+ * that all 9 `WriteToolName` values have an entry — TypeScript will
661
+ * fail the build if a tool is missing.
662
+ */
663
+ declare const WRITE_APPENDER_REGISTRY: {
664
+ save_deposit: AppenderFn<SaveDepositInput, Extract<StepPreview, {
665
+ toolName: 'save_deposit';
666
+ }>>;
667
+ withdraw: AppenderFn<WithdrawInput, Extract<StepPreview, {
668
+ toolName: 'withdraw';
669
+ }>>;
670
+ borrow: AppenderFn<BorrowInput, Extract<StepPreview, {
671
+ toolName: 'borrow';
672
+ }>>;
673
+ repay_debt: AppenderFn<RepayDebtInput, Extract<StepPreview, {
674
+ toolName: 'repay_debt';
675
+ }>>;
676
+ send_transfer: AppenderFn<SendTransferInput, Extract<StepPreview, {
677
+ toolName: 'send_transfer';
678
+ }>>;
679
+ swap_execute: AppenderFn<SwapExecuteInput, Extract<StepPreview, {
680
+ toolName: 'swap_execute';
681
+ }>>;
682
+ claim_rewards: AppenderFn<ClaimRewardsInput, Extract<StepPreview, {
683
+ toolName: 'claim_rewards';
684
+ }>>;
685
+ volo_stake: AppenderFn<VoloStakeInput, Extract<StepPreview, {
686
+ toolName: 'volo_stake';
687
+ }>>;
688
+ volo_unstake: AppenderFn<VoloUnstakeInput, Extract<StepPreview, {
689
+ toolName: 'volo_unstake';
690
+ }>>;
691
+ };
692
+ /**
693
+ * Walks the assembled PTB's command list and extracts every recipient
694
+ * address from top-level `TransferObjects` commands. Top-level only —
695
+ * recipients inside nested Move calls are NOT inspected (Enoki only
696
+ * cross-checks top-level commands).
697
+ *
698
+ * Replaces hand-maintained `allowedAddresses` arrays. Two production
699
+ * bugs in 60 days came from drift between the array and the actual
700
+ * PTB recipients (PR-H1 + PR-H4). Computing this from the PTB makes
701
+ * drift impossible by construction.
702
+ */
703
+ declare function deriveAllowedAddressesFromPtb(tx: Transaction): string[];
704
+ /**
705
+ * Compose a PTB from a list of canonical write steps. Each step
706
+ * dispatches to its registered fragment-appender; the assembled PTB is
707
+ * returned alongside pre-built `txKindBytes` ready for Enoki sponsorship
708
+ * + auto-derived `derivedAllowedAddresses`.
709
+ *
710
+ * Single-step: `composeTx({ steps: [{ toolName: 'send_transfer', input: {...} }], ... })`
711
+ * Multi-step (Layer 2): `composeTx({ steps: [{...}, {...}, {...}], ... })`
712
+ *
713
+ * Throws:
714
+ * - `T2000Error('NO_APPENDER')` — unknown `toolName`
715
+ * - Any error thrown by the per-step appender (insufficient balance,
716
+ * asset not supported, route not found, etc.) — propagates as-is.
717
+ */
718
+ declare function composeTx(opts: ComposeTxOptions): Promise<ComposeTxResult>;
719
+
236
720
  declare const HF_WARN_THRESHOLD = 1.8;
237
721
  declare const HF_CRITICAL_THRESHOLD = 1.3;
238
722
  type FinancialSummaryOptions = Record<string, never>;
@@ -248,6 +732,29 @@ declare function getFinancialSummary(client: SuiJsonRpcClient, walletAddress: st
248
732
 
249
733
  declare function getRates(client: SuiJsonRpcClient): Promise<RatesResult>;
250
734
  declare function getPendingRewards(client: SuiJsonRpcClient, address: string): Promise<PendingReward$1[]>;
735
+ /**
736
+ * Standalone builder for the `claim_rewards` tool. Wraps the existing
737
+ * `addClaimRewardsToTx` appender into a complete PTB so the SPEC 7
738
+ * `composeTx` registry adapter has a single-step builder it can dispatch
739
+ * to when `claim_rewards` is invoked alone (the chain-mode path uses
740
+ * `addClaimRewardsToTx` directly inside a multi-step PTB).
741
+ *
742
+ * Multi-protocol claim flows (e.g. NAVI + Suilend in a future world)
743
+ * still go through the `T2000` class's `claimRewards()` method, which
744
+ * iterates every registered lending adapter via the adapter registry —
745
+ * this standalone builder is intentionally NAVI-only to keep the shape
746
+ * symmetric with the rest of SPEC 7's Layer 1 builders.
747
+ *
748
+ * Returns `{ tx, rewards }`:
749
+ * - `tx` — built PTB with sender set; if no rewards are claimable, no
750
+ * move calls are appended (caller should skip executing).
751
+ * - `rewards` — what WILL be claimed by `tx`. Empty array means nothing
752
+ * to claim.
753
+ */
754
+ declare function buildClaimRewardsTx(client: SuiJsonRpcClient, address: string): Promise<{
755
+ tx: Transaction;
756
+ rewards: PendingReward$1[];
757
+ }>;
251
758
 
252
759
  declare function getSwapQuote(params: {
253
760
  walletAddress: string;
@@ -283,5 +790,68 @@ declare function buildStakeVSuiTx(_client: SuiJsonRpcClient, address: string, am
283
790
  * Build a PTB to unstake vSUI back to SUI.
284
791
  */
285
792
  declare function buildUnstakeVSuiTx(client: SuiJsonRpcClient, address: string, amountMist: bigint | 'all'): Promise<Transaction>;
793
+ /**
794
+ * SPEC 7 § "Layer 1" Volo stake appender. Two modes.
795
+ *
796
+ * Wallet mode (`inputCoin` omitted): fetches SUI coins from the
797
+ * sender's wallet (paginated), merges/splits to `amountMist`. Mirrors
798
+ * the audric host's `transactions/prepare/route.ts:524-545` volo-stake
799
+ * branch — sponsored-flow safe (does NOT consume `tx.gas`, which
800
+ * belongs to the Enoki sponsor in sponsored flows).
801
+ *
802
+ * For non-sponsored flows where the caller owns `tx.gas`, prefer
803
+ * `buildStakeVSuiTx` directly (it splits from gas, which is more
804
+ * efficient by avoiding the extra getCoins RTT).
805
+ *
806
+ * Chain mode (`inputCoin` provided): consumes the passed-in SUI coin
807
+ * ref entirely. Used for chained flows like "swap USDC → SUI → stake".
808
+ * The caller is responsible for splitting upstream if they only want
809
+ * part of the input coin staked.
810
+ *
811
+ * @returns
812
+ * - `coin`: vSUI output coin ref, ready for downstream consumption or
813
+ * wallet transfer (`tx.transferObjects`).
814
+ * - `effectiveAmountMist`: SUI mist consumed (echoes `input.amountMist`
815
+ * in both modes; chain-mode trusts the caller-supplied value since
816
+ * the actual coin balance is opaque).
817
+ */
818
+ declare function addStakeVSuiToTx(tx: Transaction, client: SuiJsonRpcClient, address: string, input: {
819
+ amountMist: bigint;
820
+ inputCoin?: TransactionObjectArgument;
821
+ }): Promise<{
822
+ coin: TransactionObjectArgument;
823
+ effectiveAmountMist: bigint;
824
+ }>;
825
+ /**
826
+ * SPEC 7 § "Layer 1" Volo unstake appender. Two modes.
827
+ *
828
+ * Wallet mode (`inputCoin` omitted): fetches vSUI coins from the
829
+ * sender's wallet (paginated), merges to a primary coin, splits to
830
+ * `amountMist` (or consumes the entire merged primary if `'all'`).
831
+ *
832
+ * Chain mode (`inputCoin` provided): consumes the passed-in vSUI coin
833
+ * ref. With `amountMist = 'all'`, the entire input coin is unstaked.
834
+ * With a bigint `amountMist`, the input coin is split internally and
835
+ * only that portion unstaked (the leftover stays accessible via the
836
+ * original ref). Used for chained flows where vSUI was just produced
837
+ * by a prior step.
838
+ *
839
+ * @returns
840
+ * - `coin`: SUI output coin ref, ready for downstream consumption
841
+ * (e.g. `addSendToTx`, `addStakeVSuiToTx` re-stake) or wallet
842
+ * transfer (`tx.transferObjects`).
843
+ * - `effectiveAmountMist`: input vSUI mist consumed; echoes
844
+ * `input.amountMist` (`'all'` is preserved as-is — the actual SUI
845
+ * received differs from input vSUI by the pool exchange rate, so
846
+ * callers needing the SUI amount must query `getVoloStats` or
847
+ * parse balance changes from the executed tx).
848
+ */
849
+ declare function addUnstakeVSuiToTx(tx: Transaction, client: SuiJsonRpcClient, address: string, input: {
850
+ amountMist: bigint | 'all';
851
+ inputCoin?: TransactionObjectArgument;
852
+ }): Promise<{
853
+ coin: TransactionObjectArgument;
854
+ effectiveAmountMist: bigint | 'all';
855
+ }>;
286
856
 
287
- export { BalanceResponse, BorrowResult, ClaimRewardsResult, CompoundRewardsResult, ContactManager, DepositInfo, EarningsResult, FinancialSummary, type FinancialSummaryOptions, FundStatusResult, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, HealthFactorResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, RepayResult, SafeguardConfig, SafeguardEnforcer, SaveResult, SendResult, StakeVSuiResult, SupportedAsset, SwapQuoteResult, SwapResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, TxMetadata, UnstakeVSuiResult, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, type VoloStats, WithdrawResult, ZkLoginProof, buildStakeVSuiTx, buildUnstakeVSuiTx, exportPrivateKey, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getRates, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, saveKey, walletExists };
857
+ export { type AppenderContext, BalanceResponse, type BorrowInput, BorrowResult, type ClaimRewardsInput, ClaimRewardsResult, type CoinPage, type ComposeTxFeeHookContext, type ComposeTxFeeHooks, type ComposeTxOptions, type ComposeTxResult, CompoundRewardsResult, ContactManager, DepositInfo, EarningsResult, FinancialSummary, type FinancialSummaryOptions, FundStatusResult, HF_CRITICAL_THRESHOLD, HF_WARN_THRESHOLD, HealthFactorResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, type RepayDebtInput, RepayResult, SafeguardConfig, SafeguardEnforcer, type SaveDepositInput, SaveResult, type SelectAndSplitResult, SendResult, type SendTransferInput, StakeVSuiResult, type StepPreview, SupportedAsset, type SwapExecuteInput, SwapQuoteResult, SwapResult, SwapRouteResult, T2000, T2000Error, T2000Options, TransactionRecord, TransactionSigner, TxMetadata, UnstakeVSuiResult, VOLO_METADATA, VOLO_PKG, VOLO_POOL, VSUI_TYPE, type VoloStakeInput, type VoloStats, type VoloUnstakeInput, WRITE_APPENDER_REGISTRY, type WithdrawInput, WithdrawResult, type WriteStep, type WriteToolName, ZkLoginProof, addSendToTx, addStakeVSuiToTx, addUnstakeVSuiToTx, buildClaimRewardsTx, buildSendTx, buildStakeVSuiTx, buildUnstakeVSuiTx, composeTx, deriveAllowedAddressesFromPtb, exportPrivateKey, fetchAllCoins, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getRates, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, saveKey, selectAndSplitCoin, selectSuiCoin, walletExists };