import { EventEmitter } from 'eventemitter3';
import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
import { Q as TxMetadata, o as SafeguardConfig, T as T2000Error, H as TransactionSigner, _ as ZkLoginProof, v as SupportedAsset } from './types-CvBZ1IrA.js';
export { A as ALL_NAVI_ASSETS, B as BORROW_FEE_BPS, a as BPS_DENOMINATOR, ax 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, ay as OPERATION_ASSETS, O as OUTBOUND_OPS, az as Operation, P as ProtocolFeeInfo, S as SAVE_FEE_BPS, k as STABLE_ASSETS, l as SUI_DECIMALS, m as SUI_TYPE, n as SUPPORTED_ASSETS, p as SafeguardError, q as SafeguardErrorDetails, r as SafeguardRule, s as SimulationResult, t as StableAsset, u as SuiRpcTxBlock, w as T2000ErrorCode, x as T2000ErrorData, y as T2000_OVERLAY_FEE_WALLET, z as TOKEN_MAP, J as TxDirection, U as USDC_DECIMALS, R as USDC_TYPE, V as USDE_TYPE, W as USDSUI_TYPE, X as USDT_TYPE, Y as WAL_TYPE, Z as WBTC_TYPE, $ as ZkLoginSigner, a0 as addFeeTransfer, aA as assertAllowedAsset, a1 as calculateFee, a2 as classifyAction, a3 as classifyLabel, a4 as classifyTransaction, a5 as extractAllUserLegs, a6 as extractTransferDetails, a7 as extractTxCommands, a8 as extractTxSender, a9 as fallbackLabel, aa as formatAssetAmount, ab as formatSui, ac as formatUsd, aB as getCoinMeta, ad as getDecimals, ae as getDecimalsForCoinType, af as getTier, aC as isAllowedAsset, aD as isInRegistry, ag as isSupported, ah as isTier1, ai as isTier2, aj as mapMoveAbortCode, ak as mapWalletError, al as mistToSui, aE as normalizeAsset, aF as normalizeCoinType, am as parseSuiRpcTx, aG as queryHistory, aH as queryTransaction, an as rawToStable, ao as rawToUsdc, ap as refineLendingLabel, aq as resolveSymbol, ar as resolveTokenType, aI as simulateTransaction, as as stableToRaw, at as suiToMist, aJ as throwIfSimulationFailed, au as truncateAddress, av as usdcToRaw, aw as validateAddress } from './types-CvBZ1IrA.js';
import { L as LendingAdapter, a as LendingRates, P as PendingReward$1 } from './descriptors-BnbL3xN8.js';
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';
import { n as T2000Options, P as PayOptions, d as PayResult, o as StakeVSuiResult, U as UnstakeVSuiResult, p as SwapResult, q as SwapQuoteResult, i as SendResult, B as BalanceResponse, k as TransactionRecord, D as DepositInfo, r as PaymentRequest, S as SaveResult, W as WithdrawResult, b as MaxWithdrawResult, a as BorrowResult, h as RepayResult, M as MaxBorrowResult, H as HealthFactorResult, e as PendingReward, C as ClaimRewardsResult, s as CompoundRewardsResult, g as PositionsResult, R as RatesResult, E as EarningsResult, F as FundStatusResult, c as OverlayFeeConfig, j as SwapRouteResult, t as FinancialSummary } from './types-epj9U13o.js';
export { A as AssetRates, G as GasReserve, u as HFAlertLevel, O as OVERLAY_FEE_RATE, f as PositionEntry, v as SerializedCetusRoute, w as SerializedCetusRoutePath, x as SerializedRouterDataV3, T as TransactionLeg, y as addSwapToTx, l as buildSwapTx, z as deserializeCetusRoute, m as findSwapRoute, I as isCetusRouteFresh, J as serializeCetusRoute, K as verifyCetusRouteCoinMatch } from './types-epj9U13o.js';
import { Transaction, TransactionObjectArgument } from '@mysten/sui/transactions';
import { SuinsClient } from '@mysten/suins';
export { NaviAdapter, ProtocolRegistry } from './adapters/index.js';
import '@cetusprotocol/aggregator-sdk';

declare class SafeguardEnforcer {
    private config;
    private readonly configPath;
    constructor(configDir?: string);
    load(): void;
    assertNotLocked(): void;
    check(metadata: TxMetadata): void;
    recordUsage(amount: number): void;
    lock(): void;
    unlock(): void;
    set(key: string, value: unknown): void;
    getConfig(): SafeguardConfig;
    isConfigured(): boolean;
    private resetDailyIfNewDay;
    private save;
}

interface Contact {
    name: string;
    address: string;
}
declare class ContactManager {
    private contacts;
    private readonly filePath;
    private readonly dir;
    constructor(configDir?: string);
    private load;
    private save;
    add(name: string, address: string): {
        action: 'added' | 'updated';
    };
    remove(name: string): boolean;
    get(name: string): Contact | undefined;
    list(): Contact[];
    resolve(nameOrAddress: string): {
        address: string;
        contactName?: string;
    };
    private validateName;
}

interface T2000Events {
    balanceChange: (event: {
        asset: string;
        previous: number;
        current: number;
        cause: string;
        tx?: string;
    }) => void;
    healthWarning: (event: {
        healthFactor: number;
        threshold: number;
        severity: 'warning';
    }) => void;
    healthCritical: (event: {
        healthFactor: number;
        threshold: number;
        severity: 'critical';
    }) => void;
    yield: (event: {
        earned: number;
        total: number;
        apy: number;
        timestamp: number;
    }) => void;
    error: (error: T2000Error) => void;
}
declare class T2000 extends EventEmitter<T2000Events> {
    private readonly _signer;
    private readonly _keypair?;
    private readonly client;
    private readonly _address;
    private readonly registry;
    readonly enforcer: SafeguardEnforcer;
    readonly contacts: ContactManager;
    private constructor();
    private constructor();
    private static createDefaultRegistry;
    static create(options?: T2000Options): Promise<T2000>;
    static fromPrivateKey(privateKey: string, options?: {
        network?: 'mainnet' | 'testnet';
        rpcUrl?: string;
    }): T2000;
    static init(options: {
        pin: string;
        passphrase?: string;
        keyPath?: string;
        name?: string;
    }): Promise<{
        agent: T2000;
        address: string;
    }>;
    /** SuiJsonRpcClient used by this agent — exposed for integrations. */
    get suiClient(): SuiJsonRpcClient;
    /** Ed25519Keypair used by this agent — exposed for CLI/MCP integrations. */
    get keypair(): Ed25519Keypair;
    /** Transaction signer (works for both keypair and zkLogin). */
    get signer(): TransactionSigner;
    pay(options: PayOptions): Promise<PayResult>;
    stakeVSui(params: {
        amount: number;
    }): Promise<StakeVSuiResult>;
    unstakeVSui(params: {
        amount: number | 'all';
    }): Promise<UnstakeVSuiResult>;
    swap(params: {
        from: string;
        to: string;
        amount: number;
        byAmountIn?: boolean;
        slippage?: number;
    }): Promise<SwapResult>;
    swapQuote(params: {
        from: string;
        to: string;
        amount: number;
        byAmountIn?: boolean;
    }): Promise<SwapQuoteResult>;
    address(): string;
    send(params: {
        to: string;
        amount: number;
        asset?: string;
    }): Promise<SendResult>;
    balance(): Promise<BalanceResponse>;
    history(params?: {
        limit?: number;
    }): Promise<TransactionRecord[]>;
    transactionDetail(digest: string): Promise<TransactionRecord | null>;
    deposit(): Promise<DepositInfo>;
    receive(params?: {
        amount?: number;
        currency?: string;
        memo?: string;
        label?: string;
    }): PaymentRequest;
    exportKey(): string;
    static fromZkLogin(opts: {
        ephemeralKeypair: Ed25519Keypair;
        zkProof: ZkLoginProof;
        userAddress: string;
        maxEpoch: number;
        rpcUrl?: string;
    }): T2000;
    registerAdapter(adapter: LendingAdapter): Promise<void>;
    save(params: {
        amount: number | 'all';
        asset?: SupportedAsset;
        protocol?: string;
    }): Promise<SaveResult>;
    withdraw(params: {
        amount: number | 'all';
        asset?: string;
        protocol?: string;
    }): Promise<WithdrawResult>;
    private withdrawAllProtocols;
    /**
     * [v0.51.0] Per-asset wallet balance lookup.
     *
     * `queryBalance.available` rolls up only `STABLE_ASSETS` (USDC), so it cannot
     * answer "do they have enough USDsui to save 10?". This helper hits
     * `getBalance` for the specific coin type — same mechanism `queryBalance`
     * uses internally — and converts to a human-readable amount using the asset's
     * decimals. Returns 0 (not a throw) when the address holds none of the asset,
     * matching the caller's existing "insufficient balance" error path.
     */
    private _queryAssetBalance;
    private _fetchCoins;
    private _mergeCoinsInTx;
    private _lastFundDigest;
    private _autoFundFromSavings;
    maxWithdraw(): Promise<MaxWithdrawResult>;
    borrow(params: {
        amount: number;
        asset?: SupportedAsset;
        protocol?: string;
    }): Promise<BorrowResult>;
    repay(params: {
        amount: number | 'all';
        asset?: SupportedAsset;
        protocol?: string;
    }): Promise<RepayResult>;
    private _repayAllBorrows;
    maxBorrow(): Promise<MaxBorrowResult>;
    healthFactor(): Promise<HealthFactorResult>;
    getPendingRewards(): Promise<PendingReward[]>;
    claimRewards(): Promise<ClaimRewardsResult>;
    /**
     * Claim pending rewards, swap non-USDC tokens to USDC via Cetus, and deposit into NAVI.
     * Multi-step: claim (transfers to wallet) -> swap each reward token to USDC -> deposit USDC.
     * Minimum threshold: skips if total rewards < $0.10 (gas not worth it).
     */
    compoundRewards(options?: {
        minValueUsd?: number;
    }): Promise<CompoundRewardsResult>;
    positions(): Promise<PositionsResult>;
    rates(): Promise<RatesResult>;
    allRates(asset?: string): Promise<{
        protocol: string;
        protocolId: string;
        rates: LendingRates;
    }[]>;
    allRatesAcrossAssets(): Promise<{
        protocol: string;
        protocolId: string;
        asset: string;
        rates: LendingRates;
    }[]>;
    earnings(): Promise<EarningsResult>;
    fundStatus(): Promise<FundStatusResult>;
    private resolveLending;
    private emitBalanceChange;
}

declare function generateKeypair(): Ed25519Keypair;
declare function keypairFromPrivateKey(privateKey: string): Ed25519Keypair;
declare function saveKey(keypair: Ed25519Keypair, passphrase: string, keyPath?: string): Promise<string>;
declare function loadKey(passphrase: string, keyPath?: string): Promise<Ed25519Keypair>;
declare function walletExists(keyPath?: string): Promise<boolean>;
declare function exportPrivateKey(keypair: Ed25519Keypair): string;
declare function getAddress(keypair: Ed25519Keypair): string;

declare function buildSendTx({ client, address, to, amount, asset, }: {
    client: SuiJsonRpcClient;
    address: string;
    to: string;
    amount: number;
    asset?: SupportedAsset;
}): Promise<Transaction>;
/**
 * Fragment-appender for the chain-mode send leg of SPEC 7 multi-write
 * Payment Intents. Consumes a coin reference produced by a previous
 * appender (e.g. `addWithdrawToTx`, `addSwapToTx`) and transfers it to
 * `recipient` within the same Payment Intent — no intermediate wallet
 * materialization.
 *
 * Codifies the hand-built send leg from
 * `scripts/smoke-spec7-withdraw-then-send.ts` (P2.1) into a typed
 * appender. SPEC 7 § "Layer 1" — P2.2b will register this in the
 * `WRITE_APPENDER_REGISTRY` under `send_transfer` for chain-mode
 * dispatch; the registry adapter will handle the wallet-fetch fallback
 * by delegating to `buildSendTx` when no upstream coin is available.
 *
 * For single-step send_transfer flows (no chained predecessor), use
 * `buildSendTx` directly — it builds a complete tx including the
 * wallet-coin selection / merge / split prelude.
 *
 * @returns void — the coin is consumed by `tx.transferObjects`. Callers
 *   that need the post-transfer "effective amount" should rely on the
 *   upstream appender's `effectiveAmount` (e.g. `addWithdrawToTx`'s
 *   return), not on this appender.
 */
declare function addSendToTx(tx: Transaction, coin: TransactionObjectArgument, recipient: string): void;

/**
 * Wallet-side coin selection helpers — shared paginated coin lookup +
 * merge + split prelude used by every wallet-mode appender that needs
 * a `TransactionObjectArgument` reference to a specific amount of a
 * given coin type.
 *
 * Replaces three earlier inline implementations:
 * - `cetus-swap.ts:fetchAllCoinsForSwap` (deleted 2026-05-02 — addSwapToTx
 *   now calls `selectAndSplitCoin` directly so the merge cache is shared
 *   across every appender in a multi-write bundle)
 * - `volo.ts:fetchCoinsByType` (kept for backwards-compat, delegates
 *   here)
 * - audric host's `transactions/prepare/route.ts:fetchCoinsForSwap`
 *   (P2.2c retires this when migrating to `composeTx`)
 *
 * Single source of truth for the "fetch coins of type X owned by
 * address Y, paginated" pattern. P2.2b extracts this so `composeTx`'s
 * registry adapters can build a wallet-mode `TransactionObjectArgument`
 * uniformly across save / send / repay / etc. The 2026-05-02 P2.7 fix
 * adds a per-PTB merge cache so multi-write bundles that touch the same
 * coin type twice (swap+save, save+send, etc.) only emit `mergeCoins`
 * once — see `ptbMergeCache` JSDoc below.
 */

interface CoinPage {
    ids: string[];
    totalBalance: bigint;
}
/**
 * Paginated coin lookup. Fetches every coin object of `coinType` owned
 * by `owner` (walks the cursor until `hasNextPage === false`). Returns
 * the list of object IDs + summed balance.
 *
 * Replaces inline `client.getCoins` calls that miss coins on the second
 * page when wallets accumulate many small coin objects (the bug class
 * that bit `buildSendTx` pre-P2.2 — captured for SPEC 12).
 */
declare function fetchAllCoins(client: SuiJsonRpcClient, owner: string, coinType: string): Promise<CoinPage>;
interface SelectAndSplitResult {
    /** TransactionObjectArgument for a coin holding `effectiveAmount` raw units. */
    coin: TransactionObjectArgument;
    /** Actual raw amount the returned coin holds. May be < requested if `swapAll` is true. */
    effectiveAmount: bigint;
    /** True iff the request consumed the entire wallet balance (no split needed). */
    swapAll: boolean;
}
/**
 * Wallet-mode coin selection prelude. Fetches every coin of `coinType`
 * owned by `owner`, merges them into a primary, and splits off the
 * requested `amount` (or returns the merged primary directly if the
 * request meets/exceeds the total balance — `swapAll` semantics).
 *
 * Throws `T2000Error` (`INSUFFICIENT_BALANCE`) when:
 * - No coins of `coinType` exist for `owner`
 * - `amount` is bigger than the total balance AND the caller did NOT
 *   opt into `swapAll: true` clipping
 *
 * Used by:
 * - `composeTx` registry adapters (save_deposit, send_transfer,
 *   repay_debt — non-SUI assets) for the wallet-mode prelude
 * - Layer 1 dual-mode appenders (`addSwapToTx`, `addStakeVSuiToTx`,
 *   `addUnstakeVSuiToTx`) when `inputCoin` is omitted
 *
 * @param tx — PTB to append `mergeCoins` + `splitCoins` commands to.
 * @param client — Sui RPC client for the paginated `getCoins` lookup.
 * @param owner — wallet address whose coins to fetch.
 * @param coinType — fully-qualified Sui coin type
 *   (`"0x...::usdc::USDC"`).
 * @param amount — raw amount to split out (in MIST / smallest unit).
 *   Pass `'all'` to consume the entire merged primary directly.
 * @param options.allowSwapAll — if true (default), `amount` >=
 *   totalBalance auto-clips to total (matches audric host's swap
 *   branch). If false, throws `INSUFFICIENT_BALANCE` when over.
 *
 * @returns
 *   - `coin` — `TransactionObjectArgument` ready for downstream
 *     consumption (e.g. `addSaveToTx`, `tx.transferObjects`).
 *   - `effectiveAmount` — the raw amount the returned coin actually
 *     holds (handles swapAll clipping).
 *   - `swapAll` — true iff the entire merged primary was consumed.
 */
declare function selectAndSplitCoin(tx: Transaction, client: SuiJsonRpcClient, owner: string, coinType: string, amount: bigint | 'all', options?: {
    allowSwapAll?: boolean;
}): Promise<SelectAndSplitResult>;
/**
 * SUI-specific coin selection. Branches on sponsorship context:
 *
 * - **Sponsored (`sponsoredContext: true`)** — fetches SUI coins via
 *   `getCoins` and merges/splits, because `tx.gas` belongs to the
 *   Enoki sponsor (NOT the user) under sponsored flows. Same shape as
 *   `selectAndSplitCoin` for any other coin type.
 *
 * - **Self-funded (`sponsoredContext: false`)** — splits from `tx.gas`
 *   directly (the user's gas coin IS their SUI). More efficient — no
 *   getCoins RTT.
 *
 * Captures the SUI-vs-other-asset divergence that lives inline in
 * `buildSendTx` today (`tx.splitCoins(tx.gas, ...)` vs paginated
 * lookup). composeTx's `send_transfer` adapter routes through this
 * helper to handle both.
 */
declare function selectSuiCoin(tx: Transaction, client: SuiJsonRpcClient, owner: string, amountMist: bigint, sponsoredContext: boolean): Promise<SelectAndSplitResult>;

/**
 * SPEC 7 v0.4 § Layer 0 — Canonical Write Architecture.
 *
 * `composeTx({ steps })` is the single canonical entry-point for every
 * Audric Enoki-sponsored write. The fragment-appender pattern (Layer 1)
 * is the implementation; this primitive dispatches each step to its
 * registered appender from the typed `WRITE_APPENDER_REGISTRY`.
 *
 * Single-write and multi-write go through the same code path. A 1-step
 * `composeTx([{ toolName: 'send_transfer', input: {...} }])` produces
 * the same shape of result as a 3-step bundle.
 *
 * **Why this exists**
 *
 * Pre-Layer-0, four parallel write stacks lived across the audric host:
 * `transactions/prepare` (fat ~600-line route), `services/prepare`
 * (hand-rolled), `debug-swap` (diagnostic), and PayButton (dapp-kit).
 * Each one re-implemented merge/split/transfer + hand-maintained the
 * `allowedAddresses` array Enoki requires. Two production bugs in the
 * past 60 days came from drift between them — PR-H1 (claim-rewards
 * self-transfer missing from allowedAddresses) and PR-H4 (borrow/
 * withdraw self-transfer same bug).
 *
 * Layer 0 collapses 3 of those stacks into one canonical primitive.
 * PayButton stays out by design (different signer, different trust
 * model — see `audric-canonical-write.mdc` for the rationale and the
 * `// CANONICAL-BYPASS:` escape-hatch contract).
 *
 * **What composeTx owns**
 *
 * - PTB assembly via per-tool wallet-mode appenders (the
 *   `WRITE_APPENDER_REGISTRY`).
 * - Pre-built `txKindBytes` (`tx.build({ onlyTransactionKind: true })`)
 *   ready for Enoki's `createSponsoredTransaction`.
 * - Auto-derived `derivedAllowedAddresses` from the assembled PTB's
 *   top-level `transferObjects` calls — eliminates the PR-H1/H4 bug
 *   class permanently. Hand-maintained arrays are now unreachable.
 * - S.38 Pyth flag plumbing — `sponsoredContext: true` automatically
 *   applies `skipPythUpdate` (borrow/withdraw) and `skipOracle` (repay)
 *   to NAVI appenders so Enoki doesn't reject `tx.gas`-as-argument.
 *
 * **What composeTx does NOT own**
 *
 * - **Fees** — Audric concern, not @t2000/sdk concern (CLAUDE.md
 *   rule #9). The SDK is fee-free by design as of @t2000/sdk@1.1.0
 *   (B5 v2). Audric host wraps composeTx with fee insertion in P2.2c.
 * - **Sponsorship** — caller's job. composeTx returns `txKindBytes`
 *   pre-built for Enoki; the caller calls `createSponsoredTransaction`
 *   with their JWT.
 * - **Chain-mode coin handoff between steps** — Layer 2 (engine
 *   bundling) ships this. P2.2b is wallet-mode-only: each step fetches
 *   coins independently. Layer 2 will extend by introducing
 *   `inputCoinFromStep: number` to thread upstream output coins.
 *
 * **Cross-references**
 *
 * - Spec → `spec/SPEC_7_MULTI_WRITE_PTB.md` § "Layer 0: Canonical
 *   Write Architecture"
 * - Read-side companion → `t2000/.cursor/rules/single-source-of-truth.mdc`
 *   + `audric/.cursor/rules/audric-canonical-portfolio.mdc`
 * - Write-side rule → `audric/.cursor/rules/audric-canonical-write.mdc`
 */

/**
 * Canonical write tools. The 10 tools that can be composed into a PTB
 * (Track B 2026-05-08 added `harvest_rewards`).
 *
 * Excluded by design:
 * - `pay_api` — recipient/amount unknown at compose time; the on-chain
 *   leg uses `send_transfer` after the gateway 402 challenge resolves.
 * - `save_contact` — no on-chain leg (Prisma-only).
 */
type WriteToolName = 'save_deposit' | 'withdraw' | 'borrow' | 'repay_debt' | 'send_transfer' | 'swap_execute' | 'claim_rewards' | 'harvest_rewards' | 'volo_stake' | 'volo_unstake';
interface SaveDepositInput {
    amount: number;
    asset?: 'USDC' | 'USDsui';
}
interface WithdrawInput {
    amount: number;
    asset?: 'USDC' | 'USDsui';
}
interface BorrowInput {
    amount: number;
    asset?: 'USDC' | 'USDsui';
}
interface RepayDebtInput {
    amount: number;
    asset?: 'USDC' | 'USDsui';
}
interface SendTransferInput {
    to: string;
    amount: number;
    asset?: SupportedAsset;
}
interface SwapExecuteInput {
    from: string;
    to: string;
    amount: number;
    slippage?: number;
    byAmountIn?: boolean;
    /** Cetus provider allow-list. Sponsored callers MUST pass an exclusion list
     *  to remove Pyth-dependent providers — see addSwapToTx JSDoc. composeTx
     *  derives this automatically from `sponsoredContext` if omitted. */
    providers?: string[];
    /**
     * [SPEC 20.2 / D-1 (a)] Optional precomputed Cetus route discovered at
     * `swap_quote` time. Bypasses `findSwapRoute()` (-400-500ms) inside
     * `addSwapToTx`. Caller (audric prepare-route) is responsible for
     * coin-type verification (D-2) + freshness check (D-3) before passing.
     * `addSwapToTx` performs an additional sanity check on `amountIn` +
     * `byAmountIn` and falls back to fresh discovery on mismatch.
     */
    precomputedRoute?: SwapRouteResult;
}
type ClaimRewardsInput = Record<string, never>;
/**
 * [Track B] `harvest_rewards` accepts only optional tunables — no required
 * inputs, since the user's choice is binary ("harvest now" or not). Default
 * slippage 1%, default dust floor $0.01. The audric host's HARVEST chip
 * passes literal `{}` and gets sensible defaults.
 */
interface HarvestRewardsInput {
    /** Per-swap slippage tolerance (0.001–0.05). Default 0.01 (1%). */
    slippage?: number;
    /** USD floor for "is this worth swapping?" — dust below transfers to wallet. Default $0.01. */
    minRewardUsd?: number;
}
interface VoloStakeInput {
    amountSui: number;
}
interface VoloUnstakeInput {
    amountVSui: number | 'all';
}
/**
 * Discriminated union mapping `toolName` → `input`. Used to type
 * `WriteStep` so consumers get autocomplete + compile-time validation
 * that the input matches the tool.
 *
 * **[SPEC 13 Phase 1] `inputCoinFromStep`** — consumer steps may
 * reference an earlier step's output coin handle by index. When set,
 * `composeTx`'s orchestration loop threads the producer's
 * `outputCoin` into this step's appender as the `inputCoin` arg,
 * bypassing the wallet pre-fetch path. The producer's terminal
 * `tx.transferObjects([coin], sender)` is suppressed automatically so
 * the same handle isn't double-consumed.
 *
 * Producer-only tools (`withdraw`, `borrow`, `claim_rewards`) don't
 * accept the field — they have no input coin slot. Consumer +
 * dual-mode tools all accept it.
 */
type WriteStep = {
    toolName: 'save_deposit';
    input: SaveDepositInput;
    inputCoinFromStep?: number;
} | {
    toolName: 'withdraw';
    input: WithdrawInput;
} | {
    toolName: 'borrow';
    input: BorrowInput;
} | {
    toolName: 'repay_debt';
    input: RepayDebtInput;
    inputCoinFromStep?: number;
} | {
    toolName: 'send_transfer';
    input: SendTransferInput;
    inputCoinFromStep?: number;
} | {
    toolName: 'swap_execute';
    input: SwapExecuteInput;
    inputCoinFromStep?: number;
} | {
    toolName: 'claim_rewards';
    input: ClaimRewardsInput;
} | {
    toolName: 'harvest_rewards';
    input: HarvestRewardsInput;
} | {
    toolName: 'volo_stake';
    input: VoloStakeInput;
    inputCoinFromStep?: number;
} | {
    toolName: 'volo_unstake';
    input: VoloUnstakeInput;
    inputCoinFromStep?: number;
};
interface ComposeTxOptions {
    sender: string;
    steps: WriteStep[];
    client: SuiJsonRpcClient;
    /**
     * S.38 Pyth flag (sponsorship-critical). When true:
     * - NAVI borrow/withdraw appenders apply `skipPythUpdate: true`
     *   (preserves on-chain price-feed updates, skips the tx.gas-using
     *   Pyth fee payment that Enoki rejects).
     * - NAVI repay appender applies `skipOracle: true` (debt reduction
     *   has no health-factor risk, full oracle bypass is safe).
     * - Cetus swap appender applies `getProvidersExcluding([HAEDALPMM,
     *   METASTABLE, OBRIC, STEAMM_OMM, STEAMM_OMM_V2, SEVENK,
     *   HAEDALHMMV2])` — Pyth-dependent providers reference `tx.gas` for
     *   oracle fees, also rejected by Enoki.
     * - SUI sends fetch coins via `getCoins` (tx.gas belongs to sponsor,
     *   not user) instead of splitting from `tx.gas`.
     *
     * Self-funded callers (CLI, MCP, server tasks) leave this `false` /
     * omit — they pay all oracle/Pyth fees from their own SUI gas.
     */
    sponsoredContext?: boolean;
    /**
     * Per-call overlay fee config for Cetus swaps. Audric host passes
     * `{ rate: 0.001, receiver: T2000_OVERLAY_FEE_WALLET }` to charge the
     * 0.1% swap overlay. CLI / direct SDK callers omit. Forwarded to
     * `addSwapToTx`'s `input.overlayFee`.
     */
    overlayFee?: OverlayFeeConfig;
    /**
     * Optional fee-injection hooks for save_deposit + borrow. Fires inside
     * the appender at the exact moment the user's coin is in hand and BEFORE
     * the protocol step consumes (save) or the canonical transferObjects
     * finalizes (borrow). Audric host uses this to inline `addFeeTransfer`
     * for USDC SAVE_FEE_BPS / BORROW_FEE_BPS without ever leaving the
     * canonical write contract — keeps the SDK fee-free per CLAUDE.md
     * rule #9 while letting hosts charge their own overlay fees.
     *
     * Hooks are fire-and-forget (no return value). They mutate `tx` directly
     * (e.g., `addFeeTransfer(tx, coin, ...)` splits the fee chunk off and
     * appends a top-level `transferObjects` to the host's fee wallet — that
     * recipient automatically appears in `derivedAllowedAddresses`).
     */
    feeHooks?: ComposeTxFeeHooks;
}
/**
 * Per-tool fee-injection callbacks. Each hook fires at a tool-specific
 * moment in the appender flow (see field JSDoc). Currently scoped to
 * the 2 fee-eligible tools — extend if/when new ones land.
 */
interface ComposeTxFeeHooks {
    /**
     * Fires inside the `save_deposit` appender AFTER the user's USDC/USDsui
     * coin is split into the deposit amount, BEFORE NAVI's `deposit` move
     * call consumes the coin. Order matters: the `coin` reference passed in
     * is the SAME `TransactionObjectArgument` that flows into the deposit,
     * so any `splitCoins(coin, [feeAmount])` inside the hook reduces the
     * deposit by exactly that fee.
     */
    save_deposit?: (ctx: ComposeTxFeeHookContext<SaveDepositInput>) => void | Promise<void>;
    /**
     * Fires inside the `borrow` appender AFTER NAVI returns the borrowed
     * coin, BEFORE the canonical `transferObjects(coin, sender)` finalizes.
     * The `coin` reference is the borrowed-and-not-yet-transferred output;
     * splitting a fee here means the user receives the remainder.
     */
    borrow?: (ctx: ComposeTxFeeHookContext<BorrowInput>) => void | Promise<void>;
}
/**
 * Context object passed to every fee hook. Carries the `tx` (mutate it),
 * the in-flight `coin` (split fees off it), the resolved tool input
 * (asset/amount for fee-policy decisions), and the sender (rarely needed
 * but kept for symmetry with `AppenderContext`).
 */
interface ComposeTxFeeHookContext<TInput> {
    tx: Transaction;
    coin: TransactionObjectArgument;
    input: TInput;
    sender: string;
}
/** Per-step preview returned by each registry appender. Tool-specific shape. */
type StepPreview = {
    toolName: 'save_deposit';
    effectiveAmount: number;
    asset: 'USDC' | 'USDsui';
} | {
    toolName: 'withdraw';
    effectiveAmount: number;
    asset: 'USDC' | 'USDsui';
} | {
    toolName: 'borrow';
    effectiveAmount: number;
    asset: 'USDC' | 'USDsui';
} | {
    toolName: 'repay_debt';
    effectiveAmount: number;
    asset: 'USDC' | 'USDsui';
} | {
    toolName: 'send_transfer';
    effectiveAmount: number;
    recipient: string;
    asset: SupportedAsset;
} | {
    toolName: 'swap_execute';
    effectiveAmountIn: number;
    expectedAmountOut: number;
    route: SwapRouteResult;
} | {
    toolName: 'claim_rewards';
    rewards: PendingReward$1[];
} | {
    toolName: 'harvest_rewards';
    claimed: PendingReward$1[];
    swaps: Array<{
        fromSymbol: string;
        fromCoinType: string;
        toSymbol: 'USDC';
        inputAmount: number;
        expectedOutputUsdc: number;
    }>;
    skipped: Array<{
        symbol: string;
        coinType: string;
        amount: number;
        reason: 'untradeable' | 'dust' | 'no-route';
    }>;
    expectedUsdcDeposited: number;
} | {
    toolName: 'volo_stake';
    effectiveAmountMist: bigint;
} | {
    toolName: 'volo_unstake';
    effectiveAmountMist: bigint | 'all';
};
interface ComposeTxResult {
    tx: Transaction;
    /**
     * Pre-built bytes for Enoki's `createSponsoredTransaction`. Built
     * with `onlyTransactionKind: true` so the gas coin can be supplied
     * by the sponsor.
     */
    txKindBytes: Uint8Array;
    /**
     * Auto-derived from the assembled PTB's top-level `transferObjects`
     * commands. Replaces hand-maintained `allowedAddresses` arrays in
     * audric host's `transactions/prepare` + `services/prepare` —
     * eliminates the PR-H1/H4 bug class permanently.
     */
    derivedAllowedAddresses: string[];
    perStepPreviews: StepPreview[];
}
/**
 * Per-appender context passed into every registry entry. Carries the
 * RPC client, sender, sponsorship flag, optional per-call overlay
 * fee config (Cetus swaps), and SPEC 13 Phase 1 chain-mode fields.
 */
interface AppenderContext {
    client: SuiJsonRpcClient;
    sender: string;
    sponsoredContext: boolean;
    overlayFee?: OverlayFeeConfig;
    feeHooks?: ComposeTxFeeHooks;
    /**
     * [SPEC 13 Phase 1] When set, the consumer appender consumes this
     * coin handle directly instead of pre-fetching from the wallet via
     * `selectAndSplitCoin` / `selectSuiCoin`. Provided by the
     * orchestration loop when the step has `inputCoinFromStep` set; the
     * loop looks up `priorOutputs[step.inputCoinFromStep]` and threads
     * it through here.
     *
     * In chain mode, the consumer consumes the handle IN FULL — the
     * `input.amount` field is treated as informational (used for preview
     * math). This matches Cetus's `routerSwap`, NAVI's `deposit`/`repay`,
     * and the Sui `transferObjects` semantics: each takes a coin object
     * and consumes its entire balance.
     */
    chainedCoin?: TransactionObjectArgument;
    /**
     * [SPEC 13 Phase 1] True when this step's output coin will be
     * consumed by a downstream step (some later step has
     * `inputCoinFromStep === currentStepIndex`). Producer appenders MUST
     * skip their terminal `tx.transferObjects([coin], ctx.sender)` call
     * when this is true — otherwise the same `TransactionObjectArgument`
     * gets used twice (once by the consumer, once by the transfer) and
     * the PTB build fails or the on-chain leg reverts.
     */
    isOutputConsumed?: boolean;
}
/**
 * [SPEC 13 Phase 1] Appender return shape. Producers populate
 * `outputCoin` so the orchestration loop can thread it into a
 * downstream consumer's `chainedCoin`. Terminal consumers
 * (`save_deposit`, `repay_debt`, `send_transfer`) omit it.
 *
 * `swap_execute`, `volo_stake`, and `volo_unstake` are dual-mode —
 * they accept `chainedCoin` AND populate `outputCoin`.
 */
interface AppenderResult<TPreview extends StepPreview> {
    preview: TPreview;
    outputCoin?: TransactionObjectArgument;
}
type AppenderFn<TInput, TPreview extends StepPreview> = (tx: Transaction, input: TInput, ctx: AppenderContext) => Promise<AppenderResult<TPreview>>;
/**
 * Cetus provider exclusion list for sponsored flows. Mirrors the
 * audric host's `SPONSORED_TX_PROVIDERS` constant — these 7 providers
 * reference `tx.gas` for Pyth oracle fee payments, which Enoki rejects.
 *
 * NOTE: keeping this hardcoded means `findSwapRoute` doesn't need a
 * dependency on `@cetusprotocol/aggregator-sdk`'s `getProvidersExcluding`
 * helper — composeTx forwards the literal list to Cetus, Cetus does the
 * inverse lookup. Result is identical.
 */
declare const SPONSORED_PYTH_DEPENDENT_PROVIDERS: readonly ["HAEDALPMM", "METASTABLE", "OBRIC", "STEAMM_OMM", "STEAMM_OMM_V2", "SEVENK", "HAEDALHMMV2"];
/**
 * Get all eligible Cetus provider names except the Pyth-dependent ones,
 * for sponsored swap context. Computed from the Cetus SDK's
 * `getAllProviders()` minus the exclusion list.
 *
 * [Bug A fix / 2026-05-10] Exported so the engine's `swap_quote` tool can
 * call this when discovering routes for sponsored hosts. Previously the
 * engine only exclude these providers at COMPOSE time; now it excludes
 * at QUOTE time too, so the precomputed route stashed on
 * `pending_action.cetusRoute` is always sponsor-safe.
 */
declare function getSponsoredSwapProviders(): Promise<string[]>;
/**
 * The typed registry. Each entry is a wallet-mode dispatcher that takes
 * (tx, input, ctx) and returns a per-step preview. Compile-time check
 * that all 10 `WriteToolName` values have an entry — TypeScript will
 * fail the build if a tool is missing.
 */
declare const WRITE_APPENDER_REGISTRY: {
    save_deposit: AppenderFn<SaveDepositInput, Extract<StepPreview, {
        toolName: 'save_deposit';
    }>>;
    withdraw: AppenderFn<WithdrawInput, Extract<StepPreview, {
        toolName: 'withdraw';
    }>>;
    borrow: AppenderFn<BorrowInput, Extract<StepPreview, {
        toolName: 'borrow';
    }>>;
    repay_debt: AppenderFn<RepayDebtInput, Extract<StepPreview, {
        toolName: 'repay_debt';
    }>>;
    send_transfer: AppenderFn<SendTransferInput, Extract<StepPreview, {
        toolName: 'send_transfer';
    }>>;
    swap_execute: AppenderFn<SwapExecuteInput, Extract<StepPreview, {
        toolName: 'swap_execute';
    }>>;
    claim_rewards: AppenderFn<ClaimRewardsInput, Extract<StepPreview, {
        toolName: 'claim_rewards';
    }>>;
    harvest_rewards: AppenderFn<HarvestRewardsInput, Extract<StepPreview, {
        toolName: 'harvest_rewards';
    }>>;
    volo_stake: AppenderFn<VoloStakeInput, Extract<StepPreview, {
        toolName: 'volo_stake';
    }>>;
    volo_unstake: AppenderFn<VoloUnstakeInput, Extract<StepPreview, {
        toolName: 'volo_unstake';
    }>>;
};
/**
 * Walks the assembled PTB's command list and extracts every recipient
 * address from top-level `TransferObjects` commands. Top-level only —
 * recipients inside nested Move calls are NOT inspected (Enoki only
 * cross-checks top-level commands).
 *
 * Replaces hand-maintained `allowedAddresses` arrays. Two production
 * bugs in 60 days came from drift between the array and the actual
 * PTB recipients (PR-H1 + PR-H4). Computing this from the PTB makes
 * drift impossible by construction.
 */
declare function deriveAllowedAddressesFromPtb(tx: Transaction): string[];
/**
 * Compose a PTB from a list of canonical write steps. Each step
 * dispatches to its registered fragment-appender; the assembled PTB is
 * returned alongside pre-built `txKindBytes` ready for Enoki sponsorship
 * + auto-derived `derivedAllowedAddresses`.
 *
 * Single-step: `composeTx({ steps: [{ toolName: 'send_transfer', input: {...} }], ... })`
 * Multi-step (Layer 2): `composeTx({ steps: [{...}, {...}, {...}], ... })`
 *
 * Throws:
 * - `T2000Error('NO_APPENDER')` — unknown `toolName`
 * - Any error thrown by the per-step appender (insufficient balance,
 *   asset not supported, route not found, etc.) — propagates as-is.
 */
declare function composeTx(opts: ComposeTxOptions): Promise<ComposeTxResult>;

declare const HF_WARN_THRESHOLD = 1.8;
declare const HF_CRITICAL_THRESHOLD = 1.3;
type FinancialSummaryOptions = Record<string, never>;
/**
 * Fetch a complete financial snapshot for one wallet in parallel.
 * Designed for the indexer HF hook + chain-memory cron.
 *
 * Every sub-call has a fallback so a single RPC failure doesn't
 * crash the entire batch. Callers can check individual zero values
 * to detect degraded data.
 */
declare function getFinancialSummary(client: SuiJsonRpcClient, walletAddress: string, _options?: FinancialSummaryOptions): Promise<FinancialSummary>;

declare function getRates(client: SuiJsonRpcClient): Promise<RatesResult>;
/**
 * [Track B follow-up / 2026-05-08] Stateless wrapper around `getPendingRewards`
 * that creates its own `SuiJsonRpcClient`. Used by the engine's
 * `pending_rewards` tool — engine doesn't import `@mysten/sui` directly
 * (would expand its dep surface), so this helper accepts just `(address,
 * suiRpcUrl?)` and instantiates the client internally.
 *
 * **Why this exists.** Pre-fix the engine tool went through
 * `requireAgent(context).getPendingRewards()`, which threw
 * "Tool requires a T2000 agent instance — pass `agent` in EngineConfig"
 * in audric prod (audric uses sponsored-tx flow, never instantiates a
 * T2000 agent). Live mainnet smoke on funkii's wallet 2026-05-08 caught
 * this immediately when the LLM correctly called pending_rewards before
 * harvest_rewards. This helper makes the audric/CLI paths symmetric
 * (both work, neither requires an agent).
 *
 * Defaults `suiRpcUrl` to mainnet fullnode for CLI / standalone callers
 * that don't pass one. Errors propagate with the same `T2000Error`
 * shape as the underlying `getPendingRewards` (PROTOCOL_UNAVAILABLE on
 * NAVI degradation, etc.) so the engine tool's catch path is unchanged.
 */
declare function getPendingRewardsByAddress(address: string, suiRpcUrl?: string): Promise<PendingReward$1[]>;
declare function getPendingRewards(client: SuiJsonRpcClient, address: string): Promise<PendingReward$1[]>;
declare function addClaimRewardsToTx(tx: Transaction, client: SuiJsonRpcClient, address: string): Promise<PendingReward$1[]>;
/**
 * Standalone builder for the `claim_rewards` tool. Wraps the existing
 * `addClaimRewardsToTx` appender into a complete PTB so the SPEC 7
 * `composeTx` registry adapter has a single-step builder it can dispatch
 * to when `claim_rewards` is invoked alone (the chain-mode path uses
 * `addClaimRewardsToTx` directly inside a multi-step PTB).
 *
 * Multi-protocol claim flows (e.g. NAVI + Suilend in a future world)
 * still go through the `T2000` class's `claimRewards()` method, which
 * iterates every registered lending adapter via the adapter registry —
 * this standalone builder is intentionally NAVI-only to keep the shape
 * symmetric with the rest of SPEC 7's Layer 1 builders.
 *
 * Returns `{ tx, rewards }`:
 * - `tx` — built PTB with sender set; if no rewards are claimable, no
 *   move calls are appended (caller should skip executing).
 * - `rewards` — what WILL be claimed by `tx`. Empty array means nothing
 *   to claim.
 */
declare function buildClaimRewardsTx(client: SuiJsonRpcClient, address: string): Promise<{
    tx: Transaction;
    rewards: PendingReward$1[];
}>;
/**
 * Minimal shape we read off the NAVI SDK's `LendingReward` rows. Kept
 * structural rather than imported so the tests don't have to reproduce
 * the full upstream type and the function works for any future caller
 * that has the same fields.
 */
interface ClaimableRewardLike {
    userClaimableReward: number | string;
    rewardCoinType: string;
    assetId?: number | string;
}
/**
 * Aggregate raw NAVI `claimable` rows into the `PendingReward[]` shape
 * the engine surfaces to the LLM and the UI. Aggregates by reward coin
 * type so a user with rewards from multiple pools (e.g. USDC pool + SUI
 * pool both rewarding vSUI) sees a single "0.0165 vSUI" line rather
 * than three separate dust entries. Filters out non-finite / non-positive
 * amounts so dust noise can't sneak in as "$0.00 REWARD" rows.
 */
declare function aggregateClaimableRewards(claimable: ClaimableRewardLike[]): PendingReward$1[];

/**
 * NAVI rewards harvest — single-PTB compound flow.
 *
 * **Goal.** Bundle the three-step "claim → swap → save" reward-cycling
 * routine into ONE atomic Programmable Transaction Block so the user
 * sees ONE confirm card instead of three sequential ones, and so the
 * legs settle together (or revert together — no half-claimed-but-
 * unsaved drift).
 *
 * **Flow.**
 *   1. Read pending rewards via NAVI's `getUserAvailableLendingRewards`
 *      (same source as `getPendingRewards` + `addClaimRewardsToTx`, so
 *      what the user sees in `pending_rewards` is exactly what gets
 *      harvested — no drift).
 *   2. Append `claimLendingRewardsPTB(... { customCoinReceive: { type: 'skip' }})`
 *      so the claimed coin handles are returned as `TransactionObjectArgument`
 *      handles instead of being transferred to the wallet — they stay
 *      consumable inside the same PTB.
 *   3. For each claimed handle:
 *        • If the reward IS USDC, hold the handle for the deposit step.
 *        • If the reward is in `COIN_REGISTRY` AND tradeable on Cetus
 *          (any tier-2 token effectively), append `addSwapToTx` in chain
 *          mode using the claimed coin as `inputCoin`. Collect the USDC
 *          output handle.
 *        • Else (untradeable / non-registry), transfer the claimed coin
 *          back to the user's wallet — preserves the reward but skips
 *          the auto-deposit (the user keeps it as a wallet asset).
 *   4. Merge all collected USDC handles via `tx.mergeCoins`, then deposit
 *      via `addSaveToTx`.
 *
 * **Atomicity.** Single PTB = single transaction = single sponsored-gas
 * envelope. Either ALL legs settle (claim + swap(s) + deposit) or none
 * do. No partial-state recovery code needed.
 *
 * **Sponsored-gas posture.** This builder appends ONLY chained move
 * calls — no `tx.gas` reads, no Pyth fee writes, no oracle Pyth updates.
 * Cetus chain-mode swaps with `slippage` ≤ 5% don't require Pyth either
 * (Cetus aggregator routes around Pyth-dependent providers when callers
 * pass `providers: getProvidersExcluding(...)`). Audric's host wires
 * the provider exclusion automatically for Enoki sponsorship — see
 * `cetus-swap.ts` JSDoc.
 *
 * **Dust filter.** Rewards with `amount * priceCache.get(symbol) <
 * minRewardUsd` are skipped from the swap leg AND from the deposit —
 * not worth the gas to swap dust. They get transferred back to the
 * wallet (preserving on-chain truth: the claim happened, the swap
 * didn't). Default minRewardUsd = $0.01.
 *
 * **Failure modes.**
 *   - PROTOCOL_UNAVAILABLE — NAVI rewards lookup or claim PTB build failed.
 *     Engine surfaces "NAVI is degraded right now."
 *   - SWAP_NO_ROUTE — a reward asset has no Cetus route. Logged + that
 *     leg is skipped (rewards transferred to wallet). Other legs proceed.
 *   - INVALID_AMOUNT — rewards array empty after dust filter (nothing
 *     worth harvesting). Throws so the engine narrates "nothing to
 *     harvest right now" instead of building a no-op PTB.
 *
 * **Why a separate file (not inside `navi.ts`).** This composition
 * crosses two protocols (NAVI + Cetus) — keeping it out of `navi.ts`
 * preserves the single-protocol-per-file invariant the rest of the SDK
 * follows. Mirrors how `cetus-swap.ts` already lives separately even
 * though it composes through `composeTx.ts`.
 */

interface HarvestSwapLeg {
    /** Reward symbol pre-swap (e.g. 'vSUI', 'NAVX'). */
    fromSymbol: string;
    /** Reward coinType pre-swap. */
    fromCoinType: string;
    /** Always 'USDC' — this builder only deposits to the USDC pool. */
    toSymbol: 'USDC';
    /** Display-units input amount (the entire claimed reward for that coin). */
    inputAmount: number;
    /** Display-units USDC the swap quote estimated. Actual on-chain may differ within slippage. */
    expectedOutputUsdc: number;
}
interface HarvestSkippedLeg {
    /** Reward symbol skipped (untradeable, dust, or no-route). */
    symbol: string;
    coinType: string;
    /** Display-units claimed amount (still credited to user's wallet — just not auto-deposited). */
    amount: number;
    /** 'untradeable' | 'dust' | 'no-route' */
    reason: 'untradeable' | 'dust' | 'no-route';
}
interface HarvestPlan {
    /** Every reward that WILL be claimed by this PTB. */
    claimed: PendingReward$1[];
    /** Each non-USDC reward that WILL be swapped to USDC inline. */
    swaps: HarvestSwapLeg[];
    /** Rewards claimed but transferred back to wallet (no auto-deposit). */
    skipped: HarvestSkippedLeg[];
    /** Display-units USDC that will be deposited to the NAVI USDC pool. */
    expectedUsdcDeposited: number;
}
/**
 * Callback invoked right before the harvest's internal `addSaveToTx`.
 * Mirrors the shape of `composeTx`'s `feeHooks.save_deposit` so audric's
 * existing hook can be threaded straight through without adapters. The
 * SDK never invents a fee — the host decides whether to skim from
 * `coin` and to where. See CLAUDE.md rule #9 (fees are a host concern).
 */
type HarvestSaveFeeHook = (ctx: {
    tx: Transaction;
    coin: TransactionObjectArgument;
    input: {
        asset: 'USDC';
        amount: number;
    };
    sender: string;
}) => void | Promise<void>;
interface BuildHarvestRewardsTxOptions {
    /** Per-swap slippage tolerance (0.001–0.05). Defaults to 0.01 (1%). */
    slippage?: number;
    /**
     * USD floor for "is this worth swapping?". Rewards below this threshold
     * get transferred back to the wallet instead of swapped. Default $0.01.
     * Pass 0 to disable the filter (always swap; useful for tests).
     */
    minRewardUsd?: number;
    /**
     * Symbol → USD price map. Sourced from the engine's `ToolContext.priceCache`
     * in production; tests can pass a literal Map. When undefined, the dust
     * filter degrades to "skip nothing" (every reward is swapped) so we don't
     * accidentally drop large rewards just because we couldn't price them.
     */
    priceCache?: Map<string, number>;
    /**
     * Cetus provider allow-list. Sponsored callers (Enoki) pass
     * `getProvidersExcluding(['pyth-dependent-list'])` to keep the PTB
     * Pyth-free. Non-sponsored callers omit this.
     */
    providers?: string[];
    /**
     * [v1.24.2 fee wiring] Overlay fee forwarded to EACH internal
     * `addSwapToTx` call. When set, every swap leg charges the rate to
     * the receiver (typically `T2000_OVERLAY_FEE_WALLET` for audric).
     * Omit for fee-free harvests (CLI / direct SDK callers).
     */
    overlayFee?: OverlayFeeConfig;
    /**
     * [v1.24.2 fee wiring] Fired immediately before the internal
     * `addSaveToTx` consumes the merged USDC deposit coin. The hook
     * receives the deposit handle so it can split a fee off via
     * `addFeeTransfer(...)` (host's call). Audric threads its
     * `feeHooks.save_deposit` straight through here so a harvest's
     * deposit leg pays the same `SAVE_FEE_BPS` as a single-op `save`.
     *
     * Order is load-bearing: this hook fires AFTER all USDC handles
     * are merged into one and BEFORE the NAVI deposit consumes it.
     * Fee receiver gets recorded as a top-level transferObjects, so
     * it's automatically picked up by `derivedAllowedAddresses`.
     */
    saveFeeHook?: HarvestSaveFeeHook;
}
/**
 * Standalone harvest builder — creates a fresh PTB, sets the sender,
 * appends the full harvest flow, and returns both the tx and the plan.
 * Used by CLI / direct SDK callers (smoke tests, scripts). The audric
 * host goes through `composeTx({ steps: [{ toolName: 'harvest_rewards' }] })`
 * which wires the appender + Enoki sponsorship.
 */
declare function buildHarvestRewardsTx(client: SuiJsonRpcClient, address: string, options?: BuildHarvestRewardsTxOptions): Promise<{
    tx: Transaction;
    plan: HarvestPlan;
}>;

declare function getSwapQuote(params: {
    walletAddress: string;
    from: string;
    to: string;
    amount: number;
    byAmountIn?: boolean;
    /**
     * [Bug A fix / 2026-05-10] Optional Cetus provider allow-list, forwarded to
     * `findSwapRoute`. Sponsored callers (Enoki) MUST pass
     * `getSponsoredSwapProviders()` to remove Pyth-dependent providers
     * (HAEDALPMM, METASTABLE, OBRIC, STEAMM_OMM/_V2, SEVENK, HAEDALHMMV2).
     * Those providers cause the Cetus aggregator's internal `routerSwap` to
     * insert a `tx.splitCoins(tx.gas, ...)` call for the Pyth update fee,
     * which Enoki rejects with HTTP 400 "Cannot use GasCoin as a transaction
     * argument" (3-step bundle smoke 2026-05-10).
     *
     * Pre-fix: `getSwapQuote` discovered routes against the FULL provider set,
     * stashed Pyth-dependent routes onto `pending_action.cetusRoute` (SPEC
     * 20.2 fast-path), and the audric `prepare` route's `swap_execute`
     * appender used the precomputed route AS-IS — bypassing the providers
     * filter that `composeTx` correctly applied. Result: every swap whose
     * best route happened to include a Pyth-dependent provider failed at
     * Enoki sponsorship.
     *
     * Non-sponsored callers (e.g. CLI direct swap) leave this undefined to
     * keep access to the full provider set including Pyth-dependent pools.
     */
    providers?: string[];
}): Promise<SwapQuoteResult>;

/**
 * VOLO vSUI liquid staking — thin transaction builders.
 * No SDK dependency. Two Move calls, immutable contract addresses.
 */

declare const VOLO_PKG = "0x68d22cf8bdbcd11ecba1e094922873e4080d4d11133e2443fddda0bfd11dae20";
declare const VOLO_POOL = "0x2d914e23d82fedef1b5f56a32d5c64bdcc3087ccfea2b4d6ea51a71f587840e5";
declare const VOLO_METADATA = "0x680cd26af32b2bde8d3361e804c53ec1d1cfe24c7f039eb7f549e8dfde389a60";
declare const VSUI_TYPE = "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT";
interface VoloStats {
    apy: number;
    exchangeRate: number;
    tvl: number;
}
/**
 * Fetch VOLO vSUI staking stats (APY, exchange rate, TVL).
 */
declare function getVoloStats(): Promise<VoloStats>;
/**
 * Build a PTB to stake SUI for vSUI.
 */
declare function buildStakeVSuiTx(_client: SuiJsonRpcClient, address: string, amountMist: bigint): Promise<Transaction>;
/**
 * Build a PTB to unstake vSUI back to SUI.
 */
declare function buildUnstakeVSuiTx(client: SuiJsonRpcClient, address: string, amountMist: bigint | 'all'): Promise<Transaction>;
/**
 * SPEC 7 § "Layer 1" Volo stake appender. Two modes.
 *
 * Wallet mode (`inputCoin` omitted): fetches SUI coins from the
 * sender's wallet (paginated), merges/splits to `amountMist`. Mirrors
 * the audric host's `transactions/prepare/route.ts:524-545` volo-stake
 * branch — sponsored-flow safe (does NOT consume `tx.gas`, which
 * belongs to the Enoki sponsor in sponsored flows).
 *
 * For non-sponsored flows where the caller owns `tx.gas`, prefer
 * `buildStakeVSuiTx` directly (it splits from gas, which is more
 * efficient by avoiding the extra getCoins RTT).
 *
 * Chain mode (`inputCoin` provided): consumes the passed-in SUI coin
 * ref entirely. Used for chained flows like "swap USDC → SUI → stake".
 * The caller is responsible for splitting upstream if they only want
 * part of the input coin staked.
 *
 * @returns
 *   - `coin`: vSUI output coin ref, ready for downstream consumption or
 *     wallet transfer (`tx.transferObjects`).
 *   - `effectiveAmountMist`: SUI mist consumed (echoes `input.amountMist`
 *     in both modes; chain-mode trusts the caller-supplied value since
 *     the actual coin balance is opaque).
 */
declare function addStakeVSuiToTx(tx: Transaction, client: SuiJsonRpcClient, address: string, input: {
    amountMist: bigint;
    inputCoin?: TransactionObjectArgument;
}): Promise<{
    coin: TransactionObjectArgument;
    effectiveAmountMist: bigint;
}>;
/**
 * SPEC 7 § "Layer 1" Volo unstake appender. Two modes.
 *
 * Wallet mode (`inputCoin` omitted): fetches vSUI coins from the
 * sender's wallet (paginated), merges to a primary coin, splits to
 * `amountMist` (or consumes the entire merged primary if `'all'`).
 *
 * Chain mode (`inputCoin` provided): consumes the passed-in vSUI coin
 * ref. With `amountMist = 'all'`, the entire input coin is unstaked.
 * With a bigint `amountMist`, the input coin is split internally and
 * only that portion unstaked (the leftover stays accessible via the
 * original ref). Used for chained flows where vSUI was just produced
 * by a prior step.
 *
 * @returns
 *   - `coin`: SUI output coin ref, ready for downstream consumption
 *     (e.g. `addSendToTx`, `addStakeVSuiToTx` re-stake) or wallet
 *     transfer (`tx.transferObjects`).
 *   - `effectiveAmountMist`: input vSUI mist consumed; echoes
 *     `input.amountMist` (`'all'` is preserved as-is — the actual SUI
 *     received differs from input vSUI by the pool exchange rate, so
 *     callers needing the SUI amount must query `getVoloStats` or
 *     parse balance changes from the executed tx).
 */
declare function addUnstakeVSuiToTx(tx: Transaction, client: SuiJsonRpcClient, address: string, input: {
    amountMist: bigint | 'all';
    inputCoin?: TransactionObjectArgument;
}): Promise<{
    coin: TransactionObjectArgument;
    effectiveAmountMist: bigint | 'all';
}>;

/**
 * SuiNS leaf-subname builders for the `audric.sui` parent NFT.
 *
 * Used by SPEC 10 v0.2.1 Phase A.1 — Audric Passport Identity. Lets the audric host
 * mint and revoke `username.audric.sui` leaves under the parent NFT held by the
 * dedicated custody address (`0xaca29165…23d11`).
 *
 * **Why a dedicated SDK module (not inline in the audric route):**
 *  - Consumers (audric/web's `/api/identity/{reserve,change,release}` routes) can import
 *    the canonical builder shape without re-discovering the `SuinsTransaction` API.
 *  - Single source of truth for the parent NFT ID + parent name.
 *  - Single source of truth for label validation (length / charset / hyphen rules).
 *
 * **Signer model — read this before wiring into a route:**
 *  These builders are signed by the **service account** (the parent NFT custody address),
 *  NOT by the user's zkLogin key. Per `audric/.cursor/rules/audric-canonical-write.mdc`,
 *  the SPEC 10 leaf-mint API routes are explicitly documented as a CANONICAL-BYPASS of
 *  the `composeTx` write contract — they are server-to-server, the user's key is never
 *  in the loop, and Enoki sponsors the gas. PTB atomicity requires single-signer, so
 *  leaf mints cannot be bundled with chat-agent writes via composeTx.
 *
 * **Reference:** `spec/runbooks/RUNBOOK_audric_sui_parent.md` §1 (parent NFT ID) +
 *  §3 (validated SDK reference shape) + §4 (mainnet smoke test 2026-05-01).
 */

/**
 * Parent name registered on SuiNS mainnet. Audric's identity namespace anchor.
 *
 * Every leaf created via `buildAddLeafTx` becomes `<label>.audric.sui` and resolves
 * via the standard SuiNS resolver (`suix_resolveNameServiceAddress`).
 */
declare const AUDRIC_PARENT_NAME = "audric.sui";
/**
 * On-chain object ID of the `audric.sui` parent NFT (a `SuinsRegistration`).
 *
 * Owned by the dedicated custody address `0xaca29165188f10136073788f648e1186dd25100100146186ebecedaf94b23d11`
 * (per `RUNBOOK_audric_sui_parent.md` §1). Every leaf mint / revoke MUST be signed
 * by the address that owns this NFT. Mainnet only.
 */
declare const AUDRIC_PARENT_NFT_ID = "0x070456e283ec988b6302bdd6cc5172bbdcb709998cf116586fb98d19b0870198";
interface BuildAddLeafParams {
    /** Bare label, e.g. `'alice'` — NOT the full `'alice.audric.sui'` path. */
    label: string;
    /** Sui address the leaf will resolve to (typically the user's zkLogin wallet). */
    targetAddress: string;
}
interface BuildRevokeLeafParams {
    /** Bare label of the leaf to revoke. */
    label: string;
}
type LabelValidationResult = {
    valid: true;
} | {
    valid: false;
    reason: string;
};
/**
 * Validate a leaf label against SuiNS protocol rules. Pure function; no I/O.
 *
 * Pre-call this before `buildAddLeafTx` / `buildRevokeLeafTx` if you want a
 * structured error (the builder functions throw on invalid labels). The audric
 * `/api/identity/check` endpoint uses this to drive the picker's real-time
 * availability indicator.
 *
 * Reserved-name policy (specific Audric handles like `support`, `admin`,
 * `official`) is NOT enforced here — that's a UI / route-level concern owned
 * by the audric host, not a protocol-level rule. See SPEC 10 D3.
 */
declare function validateLabel(label: unknown): LabelValidationResult;
/**
 * Build an unsigned PTB that creates a `<label>.audric.sui` leaf subname pointing
 * to `targetAddress`.
 *
 * The returned `Transaction` has neither sender nor gas configured — the caller
 * (audric's `/api/identity/reserve` route) sets the sender to the parent NFT
 * custody address and submits via Enoki sponsorship. See `audric-transaction-flow.mdc`
 * for the sponsored-tx wrapper pattern; note SPEC 10 leaf-mint is a documented
 * CANONICAL-BYPASS of `composeTx` because the signer is the service account, not
 * the user's zkLogin key.
 *
 * Throws synchronously if `label` violates protocol rules or `targetAddress` is
 * not a valid Sui address — fail-closed before bytes are built.
 */
declare function buildAddLeafTx(suinsClient: SuinsClient, { label, targetAddress }: BuildAddLeafParams): Transaction;
/**
 * Build an unsigned PTB that revokes a `<label>.audric.sui` leaf subname.
 *
 * Used by:
 *   1. The change-username flow (`/api/identity/change`): revoke old leaf inside
 *      the same PTB as the new leaf creation, atomically.
 *   2. The release-username flow (`/api/admin/identity/release`): admin recovery
 *      of squatted / impersonating handles.
 *   3. Account-deletion flow (future): revoke leaf when user deletes their account.
 *
 * The mainnet smoke test (2026-05-01) confirmed revocation gas cost is roughly
 * negative net (storage rebate exceeds computation) — see RUNBOOK §4.
 */
declare function buildRevokeLeafTx(suinsClient: SuinsClient, { label }: BuildRevokeLeafParams): Transaction;
/**
 * Convenience: turn a bare label into the full `<label>.audric.sui` path.
 *
 * **Use this for ON-CHAIN operations** — SuiNS leaf NFT `name` field, the
 * `createLeafSubName` / `removeLeafSubName` move calls, and any RPC call
 * that returns/expects the canonical name string. The `<label>.audric.sui`
 * form is what the SuiNS protocol writes into the NFT `name` field.
 *
 * **Do NOT use this for UI rendering** — that's `displayHandle()`'s job
 * (S.118 reversal of SPEC 10 D10, see audric-build-tracker). Pre-S.118
 * we surfaced the full `.sui` form everywhere; we now use the SuiNS V2
 * `@` form (`alice@audric`) for display because it's shorter, fits the
 * agent harness mono aesthetic, and matches SuiNS's own V2 standard.
 *
 * Both forms resolve to the same address via SuiNS RPC (verified
 * mainnet 2026-05-08 PF1) — `displayHandle()` is purely a render-layer
 * choice, not a backend storage change.
 */
declare function fullHandle(label: string): string;
/**
 * SuiNS V2 short-form display alias. `displayHandle('alice')` →
 * `'alice@audric'`. Use for chat narration, permission cards, receipts,
 * profile pages, share-to-X copy, OG metadata, and lookup_user output.
 *
 * **Why a separate function from `fullHandle`:**
 *  - `fullHandle('alice')` → `'alice.audric.sui'` is the **on-chain**
 *    NFT name field; SuiNS's `createLeafSubName` writes exactly this
 *    string and `suix_resolveNameServiceAddress` accepts it.
 *  - `displayHandle('alice')` → `'alice@audric'` is the **UI** form
 *    that users see and share. SuiNS RPC also accepts this form
 *    (verified mainnet 2026-05-08 PF1 — both forms return the same
 *    address), so we have one storage form (`<label>.audric.sui`) and
 *    two interchangeable input forms (the user can paste either).
 *
 * Reverses SPEC 10 D10 ("full handle ALWAYS"). See audric-build-tracker
 * S.118 for the rationale; see also `audric/apps/web/lib/identity/`
 * for canonicalization in the input parser (which is a no-op since
 * SuiNS RPC accepts both — kept available for future-proofing).
 */
declare function displayHandle(label: string): string;

export { AUDRIC_PARENT_NAME, AUDRIC_PARENT_NFT_ID, type AppenderContext, BalanceResponse, type BorrowInput, BorrowResult, type BuildAddLeafParams, type BuildHarvestRewardsTxOptions, type BuildRevokeLeafParams, 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, type HarvestPlan, type HarvestSkippedLeg, type HarvestSwapLeg, HealthFactorResult, type LabelValidationResult, LendingAdapter, LendingRates, MaxBorrowResult, MaxWithdrawResult, OverlayFeeConfig, PayOptions, PayResult, PaymentRequest, PendingReward, PositionsResult, RatesResult, type RepayDebtInput, RepayResult, SPONSORED_PYTH_DEPENDENT_PROVIDERS, 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, addClaimRewardsToTx, addSendToTx, addStakeVSuiToTx, addUnstakeVSuiToTx, aggregateClaimableRewards, buildAddLeafTx, buildClaimRewardsTx, buildHarvestRewardsTx, buildRevokeLeafTx, buildSendTx, buildStakeVSuiTx, buildUnstakeVSuiTx, composeTx, deriveAllowedAddressesFromPtb, displayHandle, exportPrivateKey, fetchAllCoins, fullHandle, generateKeypair, getAddress, getFinancialSummary, getPendingRewards, getPendingRewardsByAddress, getRates, getSponsoredSwapProviders, getSwapQuote, getVoloStats, keypairFromPrivateKey, loadKey, saveKey, selectAndSplitCoin, selectSuiCoin, validateLabel, walletExists };
