@t2000/sdk 4.3.1 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/browser.cjs +42 -112
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +4 -4
- package/dist/browser.d.ts +4 -4
- package/dist/browser.js +43 -102
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +670 -6651
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -541
- package/dist/index.d.ts +29 -541
- package/dist/index.js +673 -6626
- package/dist/index.js.map +1 -1
- package/dist/types-CgZWnHhs.d.cts +1214 -0
- package/dist/types-CgZWnHhs.d.ts +1214 -0
- package/package.json +1 -13
- package/dist/adapters/descriptors.cjs +0 -48
- package/dist/adapters/descriptors.cjs.map +0 -1
- package/dist/adapters/descriptors.d.cts +0 -3
- package/dist/adapters/descriptors.d.ts +0 -3
- package/dist/adapters/descriptors.js +0 -45
- package/dist/adapters/descriptors.js.map +0 -1
- package/dist/adapters/index.cjs +0 -4815
- package/dist/adapters/index.cjs.map +0 -1
- package/dist/adapters/index.d.cts +0 -91
- package/dist/adapters/index.d.ts +0 -91
- package/dist/adapters/index.js +0 -4810
- package/dist/adapters/index.js.map +0 -1
- package/dist/descriptors-DqIb4AnV.d.cts +0 -134
- package/dist/descriptors-DqIb4AnV.d.ts +0 -134
- package/dist/types-CFV4VcJJ.d.cts +0 -667
- package/dist/types-Ch0zVUpC.d.cts +0 -727
- package/dist/types-Ch0zVUpC.d.ts +0 -727
- package/dist/types-DqRLGfOC.d.ts +0 -667
|
@@ -1,727 +0,0 @@
|
|
|
1
|
-
import { RouterDataV3 } from '@cetusprotocol/aggregator-sdk';
|
|
2
|
-
import { TransactionObjectArgument, Transaction } from '@mysten/sui/transactions';
|
|
3
|
-
import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Wallet-side coin selection helpers — single source of truth for the
|
|
7
|
-
* "produce a `Coin<T>` argument holding `amount` raw units of `coinType`,
|
|
8
|
-
* owned by `address`" pattern. Used by every wallet-mode appender that
|
|
9
|
-
* needs a coin input (save, send, swap, repay, stake, etc.).
|
|
10
|
-
*
|
|
11
|
-
* **2026-05-22 — address-balance migration.** Sui mainnet's address-balance
|
|
12
|
-
* feature ships funds account-style instead of as discrete `Coin<T>` objects.
|
|
13
|
-
* After a payment via `0x2::balance::send_funds`, the leftover lands in the
|
|
14
|
-
* sender's address balance with a synthetic "coin reservation" representing
|
|
15
|
-
* the deposit. `client.getCoins()` correctly filters those reservations out
|
|
16
|
-
* (they aren't real owned objects), so the old fetch+merge+split pattern
|
|
17
|
-
* threw `INSUFFICIENT_BALANCE` for users whose stables had drifted into
|
|
18
|
-
* address balance — even when `getBalance().totalBalance` showed plenty.
|
|
19
|
-
*
|
|
20
|
-
* The fix is structural: hand the work to `coinWithBalance({ type, balance })`
|
|
21
|
-
* from `@mysten/sui/transactions`. Its build-time resolver inspects coins +
|
|
22
|
-
* address balance together (`getBalance` + `listCoins`), then emits the
|
|
23
|
-
* right shape — direct `redeem_funds` from address balance when AB ≥
|
|
24
|
-
* required, or merge-and-split across coins + AB withdrawal when not. Multi
|
|
25
|
-
* intents per coin type get batched into a single merge in one PTB, so the
|
|
26
|
-
* old per-PTB merge cache is no longer needed.
|
|
27
|
-
*
|
|
28
|
-
* Pre-flight uses `client.getBalance().totalBalance` (sums coins + AB)
|
|
29
|
-
* instead of summing the paginated `getCoins` page. That's the OTHER half
|
|
30
|
-
* of the migration — the legacy path could see `0` from `getCoins` and
|
|
31
|
-
* mistakenly throw before `coinWithBalance` ever ran.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
interface CoinPage {
|
|
35
|
-
ids: string[];
|
|
36
|
-
totalBalance: bigint;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Sum every coin of `coinType` owned by `owner`, INCLUDING address balance.
|
|
40
|
-
* Returns the IDs of any discrete coin objects that exist (callers
|
|
41
|
-
* occasionally need this for non-`coinWithBalance` paths, e.g. SUIns name
|
|
42
|
-
* registration which expects raw object IDs).
|
|
43
|
-
*
|
|
44
|
-
* Pre-2026-05-22 this function paginated `client.getCoins` and summed
|
|
45
|
-
* the page balances. That misses address-balance funds (the SDK filters
|
|
46
|
-
* them out of `getCoins` for back-compat). The new implementation calls
|
|
47
|
-
* `getBalance` for the canonical total and `getCoins` for the optional
|
|
48
|
-
* ID list — both round-trips, but they happen in parallel.
|
|
49
|
-
*/
|
|
50
|
-
declare function fetchAllCoins(client: SuiJsonRpcClient, owner: string, coinType: string): Promise<CoinPage>;
|
|
51
|
-
interface SelectAndSplitResult {
|
|
52
|
-
/** TransactionObjectArgument for a coin holding `effectiveAmount` raw units. */
|
|
53
|
-
coin: TransactionObjectArgument;
|
|
54
|
-
/** Actual raw amount the returned coin holds. May be < requested if `swapAll` is true. */
|
|
55
|
-
effectiveAmount: bigint;
|
|
56
|
-
/** True iff the request consumed the entire wallet balance (no split needed). */
|
|
57
|
-
swapAll: boolean;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Wallet-mode coin selection prelude. Pre-flights against
|
|
61
|
-
* `getBalance().totalBalance` (coins + address balance combined), then
|
|
62
|
-
* returns a `coinWithBalance({ type, balance })` argument that the
|
|
63
|
-
* `@mysten/sui` resolver fulfills at build time.
|
|
64
|
-
*
|
|
65
|
-
* Throws `T2000Error` (`INSUFFICIENT_BALANCE`) when:
|
|
66
|
-
* - `amount` is bigger than the total balance AND the caller did NOT
|
|
67
|
-
* opt into `swapAll: true` clipping.
|
|
68
|
-
* - `amount === 'all'` AND total balance is zero.
|
|
69
|
-
*
|
|
70
|
-
* @param tx — PTB to register the `coinWithBalance` intent against.
|
|
71
|
-
* @param client — Sui RPC client for the pre-flight `getBalance` lookup.
|
|
72
|
-
* @param owner — wallet address whose coins to source from.
|
|
73
|
-
* @param coinType — fully-qualified Sui coin type (e.g. `"0x...::usdc::USDC"`).
|
|
74
|
-
* @param amount — raw amount to source (in MIST / smallest unit). Pass
|
|
75
|
-
* `'all'` to consume the entire balance.
|
|
76
|
-
* @param options.allowSwapAll — if true (default), `amount` >= totalBalance
|
|
77
|
-
* auto-clips to total. If false, throws when the request would over-consume.
|
|
78
|
-
* @param options.sponsoredContext — when true, source ONLY from discrete coin
|
|
79
|
-
* objects (never the address balance). See the long note below — this exists
|
|
80
|
-
* because Enoki's gas station can't yet deserialize a `TransactionData` that
|
|
81
|
-
* contains the address-balance `FundsWithdrawal` reservation that
|
|
82
|
-
* `coinWithBalance` emits. Self-funded callers leave this false: the fullnode
|
|
83
|
-
* handles `FundsWithdrawal` fine, so the address-balance path is preferred
|
|
84
|
-
* (it can reach funds that aren't held as coin objects).
|
|
85
|
-
*
|
|
86
|
-
* @returns
|
|
87
|
-
* - `coin` — `TransactionObjectArgument` ready for downstream consumption.
|
|
88
|
-
* - `effectiveAmount` — the raw amount the returned coin holds (handles
|
|
89
|
-
* swapAll clipping).
|
|
90
|
-
* - `swapAll` — true iff the entire balance was consumed.
|
|
91
|
-
*/
|
|
92
|
-
declare function selectAndSplitCoin(tx: Transaction, client: SuiJsonRpcClient, owner: string, coinType: string, amount: bigint | 'all', options?: {
|
|
93
|
-
allowSwapAll?: boolean;
|
|
94
|
-
sponsoredContext?: boolean;
|
|
95
|
-
mergeCache?: SponsoredCoinMergeCache;
|
|
96
|
-
}): Promise<SelectAndSplitResult>;
|
|
97
|
-
/**
|
|
98
|
-
* Coin-object-only selection for sponsored (Enoki) transactions. Fetches the
|
|
99
|
-
* owner's discrete `Coin<T>` objects (NOT the address balance — `getCoins`
|
|
100
|
-
* excludes it), merges them, and splits the requested amount. Never emits a
|
|
101
|
-
* `FundsWithdrawal` reservation, so the resulting `TransactionData` stays on
|
|
102
|
-
* the shape Enoki's gas station can serialize.
|
|
103
|
-
*
|
|
104
|
-
* Throws `ADDRESS_BALANCE_UNSPONSORABLE` when the coin objects don't cover the
|
|
105
|
-
* request — which, for a user whose `getBalance().totalBalance` shows funds,
|
|
106
|
-
* means those funds live in the address balance (e.g. received via a gasless
|
|
107
|
-
* stablecoin transfer) and can't be moved through a sponsored transaction yet.
|
|
108
|
-
*/
|
|
109
|
-
/**
|
|
110
|
-
* Per-PTB cache of merged sponsored coin-object primaries, keyed by coin
|
|
111
|
-
* type. The FIRST `selectCoinObjectsOnly` call for a given coin type in a
|
|
112
|
-
* PTB fetches the owner's discrete `Coin<T>` objects, merges them into one
|
|
113
|
-
* `primary`, and records it here alongside the remaining (unspent) balance.
|
|
114
|
-
* EVERY subsequent leg sourcing the same coin type splits from that cached
|
|
115
|
-
* `primary` instead of re-fetching + re-merging.
|
|
116
|
-
*
|
|
117
|
-
* Why this exists (S.xxx, 2026-06-02): a sponsored bundle with 2+ legs
|
|
118
|
-
* sourcing the same coin (e.g. `SUI→WAL` + `SUI→DEEP`, or `swap USDC` +
|
|
119
|
-
* `save USDC`) called `selectCoinObjectsOnly` once per leg. Each call
|
|
120
|
-
* emitted its own `mergeCoins` over the SAME coin objects, so the second
|
|
121
|
-
* leg's merge referenced coins the first leg already consumed → Enoki
|
|
122
|
-
* dry-run failed with `CommandArgumentError { ArgumentWithoutValue }`.
|
|
123
|
-
*
|
|
124
|
-
* This is NOT SUI-specific. Under sponsorship, `selectAndSplitCoin` routes
|
|
125
|
-
* EVERY asset through `selectCoinObjectsOnly` (the `coinWithBalance`
|
|
126
|
-
* batching that would otherwise dedup these merges only runs for
|
|
127
|
-
* non-sponsored CLI/direct flows — its address-balance `FundsWithdrawal`
|
|
128
|
-
* reservation is what Enoki can't deserialize, issue #93). So the cache is
|
|
129
|
-
* the dedup layer for ALL coin types in a sponsored multi-leg PTB, keyed
|
|
130
|
-
* by coin type. SUI was simply the first asset observed failing in the
|
|
131
|
-
* wild because it's the most common swap source.
|
|
132
|
-
*/
|
|
133
|
-
type SponsoredCoinMergeCache = Map<string, {
|
|
134
|
-
primary: TransactionObjectArgument;
|
|
135
|
-
remaining: bigint;
|
|
136
|
-
}>;
|
|
137
|
-
/**
|
|
138
|
-
* SUI-specific coin selection. Branches on sponsorship context:
|
|
139
|
-
*
|
|
140
|
-
* - **Self-funded (`sponsoredContext: false`)** — splits from `tx.gas`
|
|
141
|
-
* directly (the user's gas coin IS their SUI). More efficient — no
|
|
142
|
-
* `getBalance` RTT.
|
|
143
|
-
*
|
|
144
|
-
* - **Sponsored (`sponsoredContext: true`)** — sources from the user's
|
|
145
|
-
* discrete SUI coin objects (`selectCoinObjectsOnly`). This both (a) avoids
|
|
146
|
-
* `tx.gas`, which belongs to the Enoki sponsor — NOT the user — under
|
|
147
|
-
* sponsored flows (the original S.260 reason for `useGasCoin: false`), AND
|
|
148
|
-
* (b) avoids `coinWithBalance`'s address-balance `FundsWithdrawal`, which
|
|
149
|
-
* Enoki's gas station can't deserialize (issue #93). If the user's SUI is
|
|
150
|
-
* address-balance-only, it raises `ADDRESS_BALANCE_UNSPONSORABLE`.
|
|
151
|
-
*/
|
|
152
|
-
declare function selectSuiCoin(tx: Transaction, client: SuiJsonRpcClient, owner: string, amountMist: bigint, sponsoredContext: boolean, mergeCache?: SponsoredCoinMergeCache): Promise<SelectAndSplitResult>;
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Cetus Aggregator V3 SDK wrapper — the ONLY file that imports @cetusprotocol/aggregator-sdk.
|
|
156
|
-
* Documented CLAUDE.md exception: multi-DEX routing cannot be feasibly replaced by thin tx builders.
|
|
157
|
-
*
|
|
158
|
-
* [B5 v2 / @t2000/sdk@1.1.0 / 2026-04-30]
|
|
159
|
-
* Overlay fee config is now per-call instead of a module-level singleton. CLI / direct
|
|
160
|
-
* SDK callers (`T2000.swap()`) DON'T pass `overlayFee` → fee-free swap. Audric's
|
|
161
|
-
* prepare/route.ts ALWAYS passes `overlayFee = { rate: OVERLAY_FEE_RATE, receiver:
|
|
162
|
-
* T2000_OVERLAY_FEE_WALLET }` → fee charged. Structural inclusion (Audric's code can't
|
|
163
|
-
* forget to pass it because it IS the code), not a toggle that defaults to safe.
|
|
164
|
-
*
|
|
165
|
-
* Pre-1.1.0: a module-level `OVERLAY_FEE_RECEIVER` constant defaulted to a Move object
|
|
166
|
-
* ID. USDC sent there became OwnedObjects keyed to the object and was inaccessible.
|
|
167
|
-
* Fixed by making the receiver a regular wallet address (T2000_OVERLAY_FEE_WALLET) AND
|
|
168
|
-
* by removing the singleton pattern that hid the misconfig.
|
|
169
|
-
*/
|
|
170
|
-
|
|
171
|
-
interface OverlayFeeConfig {
|
|
172
|
-
/** Fee rate as a fraction (e.g. 0.001 = 0.1%). Pass 0 to disable. */
|
|
173
|
-
rate: number;
|
|
174
|
-
/** Wallet address that receives the overlay fee. */
|
|
175
|
-
receiver: string;
|
|
176
|
-
}
|
|
177
|
-
interface SwapRouteResult {
|
|
178
|
-
routerData: RouterDataV3;
|
|
179
|
-
amountIn: string;
|
|
180
|
-
amountOut: string;
|
|
181
|
-
byAmountIn: boolean;
|
|
182
|
-
priceImpact: number;
|
|
183
|
-
insufficientLiquidity: boolean;
|
|
184
|
-
}
|
|
185
|
-
interface SerializedCetusRoutePath {
|
|
186
|
-
id: string;
|
|
187
|
-
direction: boolean;
|
|
188
|
-
provider: string;
|
|
189
|
-
from: string;
|
|
190
|
-
target: string;
|
|
191
|
-
feeRate: number;
|
|
192
|
-
amountIn: string;
|
|
193
|
-
amountOut: string;
|
|
194
|
-
version?: string;
|
|
195
|
-
publishedAt?: string;
|
|
196
|
-
extendedDetails?: Record<string, unknown>;
|
|
197
|
-
}
|
|
198
|
-
interface SerializedRouterDataV3 {
|
|
199
|
-
quoteID?: string;
|
|
200
|
-
/** RouterDataV3.amountIn (BN) → decimal string */
|
|
201
|
-
amountIn: string;
|
|
202
|
-
/** RouterDataV3.amountOut (BN) → decimal string */
|
|
203
|
-
amountOut: string;
|
|
204
|
-
byAmountIn: boolean;
|
|
205
|
-
paths: SerializedCetusRoutePath[];
|
|
206
|
-
insufficientLiquidity: boolean;
|
|
207
|
-
deviationRatio: number;
|
|
208
|
-
/** RouterDataV3.packages (Map) → Record */
|
|
209
|
-
packages?: Record<string, string>;
|
|
210
|
-
totalDeepFee?: number;
|
|
211
|
-
error?: {
|
|
212
|
-
code: number;
|
|
213
|
-
msg: string;
|
|
214
|
-
};
|
|
215
|
-
overlayFee?: number;
|
|
216
|
-
}
|
|
217
|
-
interface SerializedCetusRoute {
|
|
218
|
-
routerData: SerializedRouterDataV3;
|
|
219
|
-
amountIn: string;
|
|
220
|
-
amountOut: string;
|
|
221
|
-
byAmountIn: boolean;
|
|
222
|
-
priceImpact: number;
|
|
223
|
-
insufficientLiquidity: boolean;
|
|
224
|
-
/**
|
|
225
|
-
* Wall-clock timestamp (ms since epoch) at which the route was discovered.
|
|
226
|
-
* Used by audric's prepare-route for SPEC 20.2 D-3 TTL re-validation: if
|
|
227
|
-
* the route is older than the threshold AND price impact has shifted
|
|
228
|
-
* beyond tolerance, fall back to a fresh `findSwapRoute()` call.
|
|
229
|
-
*/
|
|
230
|
-
discoveredAt: number;
|
|
231
|
-
/**
|
|
232
|
-
* Snapshot of the input/output coin types the route was discovered for.
|
|
233
|
-
* SPEC 20.2 D-2 (b) structural verification: prepare-route asserts
|
|
234
|
-
* input/output coins match before using the fast-path; mismatch falls
|
|
235
|
-
* back to fresh discovery (defense against client-side tampering and
|
|
236
|
-
* against legitimate token-type drift in the request).
|
|
237
|
-
*/
|
|
238
|
-
fromCoinType: string;
|
|
239
|
-
toCoinType: string;
|
|
240
|
-
}
|
|
241
|
-
declare function serializeCetusRoute(route: SwapRouteResult, context: {
|
|
242
|
-
fromCoinType: string;
|
|
243
|
-
toCoinType: string;
|
|
244
|
-
}): SerializedCetusRoute;
|
|
245
|
-
declare function deserializeCetusRoute(serialized: SerializedCetusRoute): SwapRouteResult;
|
|
246
|
-
/**
|
|
247
|
-
* SPEC 20.2 D-2 (b) structural verification helper. Returns true when the
|
|
248
|
-
* serialized route matches the requested coin types (i.e. it's safe to use
|
|
249
|
-
* as the prepare-route fast-path), false otherwise (tampered, or input
|
|
250
|
-
* mismatch from a legitimate but stale pending action). Caller falls back
|
|
251
|
-
* to a fresh `findSwapRoute()` call when verification fails.
|
|
252
|
-
*/
|
|
253
|
-
declare function verifyCetusRouteCoinMatch(serialized: SerializedCetusRoute, expected: {
|
|
254
|
-
fromCoinType: string;
|
|
255
|
-
toCoinType: string;
|
|
256
|
-
}): boolean;
|
|
257
|
-
/**
|
|
258
|
-
* SPEC 20.2 D-3 (b) TTL helper. Returns true when the serialized route is
|
|
259
|
-
* fresh enough to use as the fast-path (< `maxAgeMs` old). Returns false
|
|
260
|
-
* for stale routes — caller falls back to fresh `findSwapRoute()` to pick
|
|
261
|
-
* up any pool-price drift since route discovery.
|
|
262
|
-
*
|
|
263
|
-
* Default 30s aligns with the existing quote-freshness contract surfaced
|
|
264
|
-
* to users via `pending_action.quoteAge` (the PermissionCard "QUOTE Ns OLD"
|
|
265
|
-
* badge starts warning the user past 30s).
|
|
266
|
-
*/
|
|
267
|
-
declare function isCetusRouteFresh(serialized: SerializedCetusRoute, maxAgeMs?: number): boolean;
|
|
268
|
-
/**
|
|
269
|
-
* Default Audric swap overlay fee — 0.1%. Exported for consumers that want to use
|
|
270
|
-
* the canonical Audric rate (the Audric prepare-route does this). Changing this
|
|
271
|
-
* rate requires a coordinated SDK + audric release.
|
|
272
|
-
*/
|
|
273
|
-
declare const OVERLAY_FEE_RATE = 0.001;
|
|
274
|
-
/**
|
|
275
|
-
* Find the optimal swap route via Cetus Aggregator REST API.
|
|
276
|
-
*
|
|
277
|
-
* Pass `overlayFee` to charge an overlay fee on the output (Audric's pattern).
|
|
278
|
-
* Omit it for a fee-free swap (CLI / direct SDK pattern).
|
|
279
|
-
*/
|
|
280
|
-
declare function findSwapRoute(params: {
|
|
281
|
-
walletAddress: string;
|
|
282
|
-
from: string;
|
|
283
|
-
to: string;
|
|
284
|
-
amount: bigint;
|
|
285
|
-
byAmountIn: boolean;
|
|
286
|
-
overlayFee?: OverlayFeeConfig;
|
|
287
|
-
/**
|
|
288
|
-
* Optional Cetus provider allow-list. When omitted, all 30+ DEXes
|
|
289
|
-
* are eligible. Sponsored flows (Enoki) MUST pass an exclusion list
|
|
290
|
-
* computed via `getProvidersExcluding([...])` from the Cetus SDK to
|
|
291
|
-
* remove Pyth-dependent providers (HAEDALPMM, METASTABLE, OBRIC,
|
|
292
|
-
* STEAMM_OMM, STEAMM_OMM_V2, SEVENK, HAEDALHMMV2) — those reference
|
|
293
|
-
* `tx.gas` for oracle fees, which Enoki rejects in sponsored txs.
|
|
294
|
-
* Non-sponsored callers (CLI, direct SDK) leave this undefined.
|
|
295
|
-
*/
|
|
296
|
-
providers?: string[];
|
|
297
|
-
}): Promise<SwapRouteResult | null>;
|
|
298
|
-
/**
|
|
299
|
-
* Build a swap PTB from a route result. The caller must provide an input coin
|
|
300
|
-
* obtained by splitting/merging wallet coins.
|
|
301
|
-
*
|
|
302
|
-
* **Important:** Cetus's `routerSwap` reads the overlay-fee config from the
|
|
303
|
-
* AggregatorClient instance. The `overlayFee` param here MUST match the one
|
|
304
|
-
* passed to `findSwapRoute` for the same swap (otherwise you'll hit the cache
|
|
305
|
-
* boundary and get a different client with different overlay config).
|
|
306
|
-
*/
|
|
307
|
-
declare function buildSwapTx(params: {
|
|
308
|
-
walletAddress: string;
|
|
309
|
-
route: SwapRouteResult;
|
|
310
|
-
tx: Transaction;
|
|
311
|
-
inputCoin: TransactionObjectArgument;
|
|
312
|
-
slippage: number;
|
|
313
|
-
overlayFee?: OverlayFeeConfig;
|
|
314
|
-
}): Promise<TransactionObjectArgument>;
|
|
315
|
-
/**
|
|
316
|
-
* Append a swap fragment to an existing PTB. SPEC 7 § "Layer 1" Cetus
|
|
317
|
-
* appender. Two modes, dispatched by the presence of `input.inputCoin`:
|
|
318
|
-
*
|
|
319
|
-
* - **Wallet mode** (`inputCoin` omitted) — sources `from`-asset funds
|
|
320
|
-
* via `coinWithBalance({ type, balance })` (resolves coin objects +
|
|
321
|
-
* address balance at build time), runs the swap. Mirrors the audric
|
|
322
|
-
* host's `transactions/prepare/route.ts` swap branch (P2.2c will
|
|
323
|
-
* retire that branch in favor of this appender via `composeTx`).
|
|
324
|
-
*
|
|
325
|
-
* - **Chain mode** (`inputCoin` provided) — consumes the passed-in coin
|
|
326
|
-
* reference (typically produced by an upstream appender like
|
|
327
|
-
* `addWithdrawToTx`) directly, no wallet fetch / no merge / no
|
|
328
|
-
* split. This is the SPEC 7 multi-write enabler ("withdraw → swap →
|
|
329
|
-
* save" without intermediate wallet materialization).
|
|
330
|
-
*
|
|
331
|
-
* **SUI in wallet mode:** ALWAYS sources through `selectSuiCoin` (which
|
|
332
|
-
* routes via `coinWithBalance({ type: SUI, useGasCoin: false })` under
|
|
333
|
-
* sponsored flows, OR `tx.splitCoins(tx.gas, ...)` under self-funded
|
|
334
|
-
* flows). The caller MUST set `sponsoredContext` correctly — otherwise
|
|
335
|
-
* sponsored swaps with SUI source fail with `Cannot use GasCoin as a
|
|
336
|
-
* transaction argument` (Enoki owns `tx.gas`, the PTB body referencing
|
|
337
|
-
* it as an argument is invalid for sponsorship). 2.14.0 shipped without
|
|
338
|
-
* this branch and broke audric/web-v2 SUI→USDC swaps; restored in 2.14.1
|
|
339
|
-
* (S.260). For non-sponsored flows (CLI), `T2000.swap()` pre-builds the
|
|
340
|
-
* inputCoin via `tx.splitCoins(tx.gas, [rawAmount])[0]` and uses chain
|
|
341
|
-
* mode, sidestepping wallet-mode entirely — this branch is a defensive
|
|
342
|
-
* safety net for future direct SDK users who pass SUI in wallet mode.
|
|
343
|
-
*
|
|
344
|
-
* **`swapAll` semantics (wallet mode):** if the requested raw amount
|
|
345
|
-
* is >= the wallet's total `from` balance, the appender consumes the
|
|
346
|
-
* entire merged primary coin (not a split), matching audric's host
|
|
347
|
-
* route's `swapAll` clipping. The returned `effectiveAmountIn` reflects
|
|
348
|
-
* the actual consumed amount in display units.
|
|
349
|
-
*
|
|
350
|
-
* **Slippage:** clamped to [0.001, 0.05] (0.1% – 5%). Defaults to 0.01.
|
|
351
|
-
*
|
|
352
|
-
* @returns
|
|
353
|
-
* - `coin` — output coin reference, ready for downstream consumption
|
|
354
|
-
* (e.g. `addSaveToTx`) or wallet transfer (`tx.transferObjects`).
|
|
355
|
-
* - `effectiveAmountIn` — display-units input amount the swap actually
|
|
356
|
-
* consumes (handles `swapAll` clipping in wallet mode; in chain mode
|
|
357
|
-
* echoes the requested `input.amount`).
|
|
358
|
-
* - `expectedAmountOut` — display-units output amount per the route
|
|
359
|
-
* quote. Actual on-chain output may differ within slippage.
|
|
360
|
-
* - `route` — raw `SwapRouteResult` for downstream telemetry / logging.
|
|
361
|
-
*/
|
|
362
|
-
declare function addSwapToTx(tx: Transaction, client: SuiJsonRpcClient, address: string, input: {
|
|
363
|
-
from: string;
|
|
364
|
-
to: string;
|
|
365
|
-
amount: number;
|
|
366
|
-
slippage?: number;
|
|
367
|
-
byAmountIn?: boolean;
|
|
368
|
-
overlayFee?: OverlayFeeConfig;
|
|
369
|
-
inputCoin?: TransactionObjectArgument;
|
|
370
|
-
/**
|
|
371
|
-
* Optional Cetus provider allow-list. Forwarded to `findSwapRoute`.
|
|
372
|
-
* Sponsored flows (Enoki) MUST pass `getProvidersExcluding([...])`
|
|
373
|
-
* to remove Pyth-dependent providers — see `findSwapRoute`'s JSDoc
|
|
374
|
-
* for the exclusion list. Non-sponsored callers omit this.
|
|
375
|
-
*/
|
|
376
|
-
providers?: string[];
|
|
377
|
-
/**
|
|
378
|
-
* [SPEC 20.2 D-3 (b)] Precomputed route from a prior `findSwapRoute()`
|
|
379
|
-
* call (typically captured by `swap_quote` and threaded through
|
|
380
|
-
* `pending_action.cetusRoute`). When present AND not stale (per
|
|
381
|
-
* `isCetusRouteFresh`) AND the input/output coins match, this skips
|
|
382
|
-
* the ~400-500ms `findSwapRoute()` discovery call. Stale routes are
|
|
383
|
-
* silently ignored (caller falls back to fresh discovery).
|
|
384
|
-
*
|
|
385
|
-
* Caller responsibility: pass the SAME `overlayFee` / `providers` /
|
|
386
|
-
* `byAmountIn` that produced the precomputed route. Mismatch will
|
|
387
|
-
* still produce a working swap but may use the wrong overlay-fee
|
|
388
|
-
* config (the route data already encodes the chosen DEX path).
|
|
389
|
-
*/
|
|
390
|
-
precomputedRoute?: SwapRouteResult;
|
|
391
|
-
/**
|
|
392
|
-
* Whether this swap is being built inside a sponsored-tx flow (Enoki)
|
|
393
|
-
* vs self-funded (CLI / direct sign). Load-bearing for SUI-source
|
|
394
|
-
* swaps in wallet mode: under sponsored flows, `tx.gas` belongs to
|
|
395
|
-
* the sponsor and CANNOT be referenced as a transaction argument
|
|
396
|
-
* (Sui protocol rejects with `Cannot use GasCoin as a transaction
|
|
397
|
-
* argument`). When `true`, SUI source routes through `selectSuiCoin`
|
|
398
|
-
* with `useGasCoin: false` so the resolver sources from the user's
|
|
399
|
-
* SUI coin objects + address balance instead. Defaults to `false`
|
|
400
|
-
* (back-compat — pre-2.14.1 behavior). Audric/web-v2's compose path
|
|
401
|
-
* threads this through via `composeTx({ sponsoredContext: true })`.
|
|
402
|
-
*/
|
|
403
|
-
sponsoredContext?: boolean;
|
|
404
|
-
/**
|
|
405
|
-
* Per-PTB merge cache for sponsored coin-object sourcing (any coin
|
|
406
|
-
* type — SUI in the dedicated branch, USDC/USDsui/etc. in the wallet
|
|
407
|
-
* branch). Provided by `composeTx`'s orchestration loop so multiple
|
|
408
|
-
* legs sourcing the same coin in one bundle share a single merged
|
|
409
|
-
* primary coin instead of each emitting its own `mergeCoins` (the
|
|
410
|
-
* second of which references already-consumed coins → Enoki dry-run
|
|
411
|
-
* `ArgumentWithoutValue`). Single swaps don't need it; omit. See
|
|
412
|
-
* `SponsoredCoinMergeCache` JSDoc.
|
|
413
|
-
*/
|
|
414
|
-
coinMergeCache?: SponsoredCoinMergeCache;
|
|
415
|
-
}): Promise<{
|
|
416
|
-
coin: TransactionObjectArgument;
|
|
417
|
-
effectiveAmountIn: number;
|
|
418
|
-
expectedAmountOut: number;
|
|
419
|
-
route: SwapRouteResult;
|
|
420
|
-
/** True when `precomputedRoute` was used (no `findSwapRoute()` call). */
|
|
421
|
-
usedPrecomputedRoute: boolean;
|
|
422
|
-
}>;
|
|
423
|
-
|
|
424
|
-
interface T2000Options {
|
|
425
|
-
keyPath?: string;
|
|
426
|
-
/** PIN to decrypt the key file. Accepts any string (4+ chars). */
|
|
427
|
-
pin?: string;
|
|
428
|
-
/** @deprecated Use `pin` instead. */
|
|
429
|
-
passphrase?: string;
|
|
430
|
-
network?: 'mainnet' | 'testnet';
|
|
431
|
-
rpcUrl?: string;
|
|
432
|
-
}
|
|
433
|
-
interface GasReserve {
|
|
434
|
-
sui: number;
|
|
435
|
-
usdEquiv: number;
|
|
436
|
-
}
|
|
437
|
-
interface BalanceResponse {
|
|
438
|
-
available: number;
|
|
439
|
-
savings: number;
|
|
440
|
-
debt: number;
|
|
441
|
-
pendingRewards: number;
|
|
442
|
-
gasReserve: GasReserve;
|
|
443
|
-
total: number;
|
|
444
|
-
stables: Record<string, number>;
|
|
445
|
-
}
|
|
446
|
-
interface SendResult {
|
|
447
|
-
success: boolean;
|
|
448
|
-
tx: string;
|
|
449
|
-
amount: number;
|
|
450
|
-
to: string;
|
|
451
|
-
/** Set when the recipient was resolved via the legacy `contacts.json` alias. */
|
|
452
|
-
contactName?: string;
|
|
453
|
-
/**
|
|
454
|
-
* [S.279] Set when the recipient was resolved via SuiNS (e.g. `alex.sui`).
|
|
455
|
-
* CLI receipts render "Sent to alex.sui (0xabc...)" when present.
|
|
456
|
-
*/
|
|
457
|
-
suinsName?: string;
|
|
458
|
-
gasCost: number;
|
|
459
|
-
gasCostUnit: string;
|
|
460
|
-
balance: BalanceResponse;
|
|
461
|
-
}
|
|
462
|
-
interface SaveResult {
|
|
463
|
-
success: boolean;
|
|
464
|
-
tx: string;
|
|
465
|
-
amount: number;
|
|
466
|
-
apy: number;
|
|
467
|
-
fee: number;
|
|
468
|
-
gasCost: number;
|
|
469
|
-
savingsBalance: number;
|
|
470
|
-
}
|
|
471
|
-
interface WithdrawResult {
|
|
472
|
-
success: boolean;
|
|
473
|
-
tx: string;
|
|
474
|
-
amount: number;
|
|
475
|
-
asset?: string;
|
|
476
|
-
gasCost: number;
|
|
477
|
-
}
|
|
478
|
-
interface BorrowResult {
|
|
479
|
-
success: boolean;
|
|
480
|
-
tx: string;
|
|
481
|
-
amount: number;
|
|
482
|
-
/** [v0.51.0] Asset borrowed — 'USDC' or 'USDsui'. Optional for backward compat. */
|
|
483
|
-
asset?: string;
|
|
484
|
-
fee: number;
|
|
485
|
-
healthFactor: number;
|
|
486
|
-
gasCost: number;
|
|
487
|
-
}
|
|
488
|
-
interface RepayResult {
|
|
489
|
-
success: boolean;
|
|
490
|
-
tx: string;
|
|
491
|
-
amount: number;
|
|
492
|
-
/** [v0.51.1] Asset repaid — 'USDC' or 'USDsui'. Optional for backward compat. */
|
|
493
|
-
asset?: string;
|
|
494
|
-
remainingDebt: number;
|
|
495
|
-
gasCost: number;
|
|
496
|
-
}
|
|
497
|
-
interface HealthFactorResult {
|
|
498
|
-
healthFactor: number;
|
|
499
|
-
supplied: number;
|
|
500
|
-
borrowed: number;
|
|
501
|
-
maxBorrow: number;
|
|
502
|
-
liquidationThreshold: number;
|
|
503
|
-
}
|
|
504
|
-
interface MaxWithdrawResult {
|
|
505
|
-
maxAmount: number;
|
|
506
|
-
healthFactorAfter: number;
|
|
507
|
-
currentHF: number;
|
|
508
|
-
}
|
|
509
|
-
interface MaxBorrowResult {
|
|
510
|
-
maxAmount: number;
|
|
511
|
-
healthFactorAfter: number;
|
|
512
|
-
currentHF: number;
|
|
513
|
-
}
|
|
514
|
-
interface AssetRates {
|
|
515
|
-
saveApy: number;
|
|
516
|
-
borrowApy: number;
|
|
517
|
-
}
|
|
518
|
-
interface RatesResult {
|
|
519
|
-
[asset: string]: AssetRates;
|
|
520
|
-
}
|
|
521
|
-
interface PositionEntry {
|
|
522
|
-
protocol: string;
|
|
523
|
-
asset: string;
|
|
524
|
-
type: 'save' | 'borrow';
|
|
525
|
-
amount: number;
|
|
526
|
-
amountUsd?: number;
|
|
527
|
-
apy: number;
|
|
528
|
-
}
|
|
529
|
-
interface PositionsResult {
|
|
530
|
-
positions: PositionEntry[];
|
|
531
|
-
}
|
|
532
|
-
interface EarningsResult {
|
|
533
|
-
totalYieldEarned: number;
|
|
534
|
-
currentApy: number;
|
|
535
|
-
dailyEarning: number;
|
|
536
|
-
supplied: number;
|
|
537
|
-
}
|
|
538
|
-
interface FundStatusResult {
|
|
539
|
-
supplied: number;
|
|
540
|
-
apy: number;
|
|
541
|
-
earnedToday: number;
|
|
542
|
-
earnedAllTime: number;
|
|
543
|
-
projectedMonthly: number;
|
|
544
|
-
}
|
|
545
|
-
interface DepositInfo {
|
|
546
|
-
address: string;
|
|
547
|
-
network: string;
|
|
548
|
-
supportedAssets: string[];
|
|
549
|
-
instructions: string;
|
|
550
|
-
}
|
|
551
|
-
interface PaymentRequest {
|
|
552
|
-
address: string;
|
|
553
|
-
network: string;
|
|
554
|
-
amount: number | null;
|
|
555
|
-
currency: string;
|
|
556
|
-
memo: string | null;
|
|
557
|
-
label: string | null;
|
|
558
|
-
/** Unique payment identifier (UUID) for Payment Kit registry */
|
|
559
|
-
nonce: string;
|
|
560
|
-
/** Payment Kit URI (sui:pay?...) for QR codes and wallet deep links */
|
|
561
|
-
qrUri: string;
|
|
562
|
-
/** Human-readable summary */
|
|
563
|
-
displayText: string;
|
|
564
|
-
}
|
|
565
|
-
/**
|
|
566
|
-
* One non-zero user balance change for a transaction. Sui collapses
|
|
567
|
-
* balance changes by coin type, so a 3-step bundle that touches USDC
|
|
568
|
-
* three times surfaces as ONE leg of net USDC delta — not three.
|
|
569
|
-
*
|
|
570
|
-
* [Activity rebuild / 2026-05-10] Added so consumers can render swap
|
|
571
|
-
* + bundle txs accurately instead of picking a single "primary leg"
|
|
572
|
-
* (which made `Swapped 987.60 MANIFEST` look like +$987 of value when
|
|
573
|
-
* the user actually paid 1 USDC for it).
|
|
574
|
-
*/
|
|
575
|
-
interface TransactionLeg {
|
|
576
|
-
/** Full Sui coin type string (e.g. `0x...usdc::USDC`). */
|
|
577
|
-
coinType: string;
|
|
578
|
-
/** Display symbol (USDC, SUI, GOLD, MANIFEST, …) from the token registry. */
|
|
579
|
-
asset: string;
|
|
580
|
-
/** On-chain decimals for this coin (used to format `amount`). */
|
|
581
|
-
decimals: number;
|
|
582
|
-
/** Token quantity as a positive number (e.g. 987.60). */
|
|
583
|
-
amount: number;
|
|
584
|
-
/** Signed raw bigint as a string (preserves sign + precision). */
|
|
585
|
-
rawAmount: string;
|
|
586
|
-
/** `'out'` if the user spent this coin, `'in'` if they received it. */
|
|
587
|
-
direction: 'in' | 'out';
|
|
588
|
-
}
|
|
589
|
-
interface TransactionRecord {
|
|
590
|
-
digest: string;
|
|
591
|
-
/** Coarse bucket — `'send' | 'lending' | 'swap' | 'transaction'`. STABLE. */
|
|
592
|
-
action: string;
|
|
593
|
-
/**
|
|
594
|
-
* Finer-grained display label derived from the Move-call function
|
|
595
|
-
* name (e.g. `'deposit'`, `'withdraw'`, `'payment_link'`,
|
|
596
|
-
* `'on-chain'`). Optional — frontends should fall back to `action`
|
|
597
|
-
* when missing. Never used by ACI filters.
|
|
598
|
-
*/
|
|
599
|
-
label?: string;
|
|
600
|
-
/**
|
|
601
|
-
* All non-zero user balance legs for this transaction. Single-write
|
|
602
|
-
* txs have `legs.length === 1`; swaps have `2` (one `out`, one
|
|
603
|
-
* `in`); bundles have `> 2`. Order is RPC order — not sorted by
|
|
604
|
-
* size or USD value (audric's activity route prices + sorts).
|
|
605
|
-
*
|
|
606
|
-
* @since SDK v1.27.2 — was missing from earlier shapes; older
|
|
607
|
-
* consumers can keep using `amount` / `asset` / `direction` (which
|
|
608
|
-
* still resolve to the largest absolute leg).
|
|
609
|
-
*/
|
|
610
|
-
legs: TransactionLeg[];
|
|
611
|
-
/**
|
|
612
|
-
* Largest-absolute-leg amount, kept for back-compat with consumers
|
|
613
|
-
* that pre-date `legs[]`. New code should iterate `legs` instead.
|
|
614
|
-
*/
|
|
615
|
-
amount?: number;
|
|
616
|
-
/** @see {@link amount} — back-compat alias for `legs[primary].asset`. */
|
|
617
|
-
asset?: string;
|
|
618
|
-
recipient?: string;
|
|
619
|
-
/**
|
|
620
|
-
* Direction of the user's principal (non-gas) balance movement on
|
|
621
|
-
* this tx — `'out'` if they spent, `'in'` if they received.
|
|
622
|
-
* Computed from on-chain balance changes (NOT from `label`), so the
|
|
623
|
-
* card can render the correct sign even for opaque actions like
|
|
624
|
-
* `swap`/`router`. Undefined when no user balance change is
|
|
625
|
-
* detectable (e.g. pure read-only or admin txs).
|
|
626
|
-
*
|
|
627
|
-
* @see {@link amount} — back-compat alias for `legs[primary].direction`.
|
|
628
|
-
*/
|
|
629
|
-
direction?: 'in' | 'out';
|
|
630
|
-
timestamp: number;
|
|
631
|
-
gasCost?: number;
|
|
632
|
-
}
|
|
633
|
-
interface PendingReward {
|
|
634
|
-
protocol: string;
|
|
635
|
-
asset: string;
|
|
636
|
-
coinType: string;
|
|
637
|
-
symbol: string;
|
|
638
|
-
amount: number;
|
|
639
|
-
estimatedValueUsd: number;
|
|
640
|
-
}
|
|
641
|
-
interface ClaimRewardsResult {
|
|
642
|
-
success: boolean;
|
|
643
|
-
tx: string;
|
|
644
|
-
rewards: PendingReward[];
|
|
645
|
-
totalValueUsd: number;
|
|
646
|
-
gasCost: number;
|
|
647
|
-
}
|
|
648
|
-
interface CompoundRewardsResult {
|
|
649
|
-
success: boolean;
|
|
650
|
-
claimTx: string;
|
|
651
|
-
swapTxs: string[];
|
|
652
|
-
depositTx: string;
|
|
653
|
-
rewards: PendingReward[];
|
|
654
|
-
totalCompoundedUsdc: number;
|
|
655
|
-
totalGasCost: number;
|
|
656
|
-
}
|
|
657
|
-
interface SwapResult {
|
|
658
|
-
success: boolean;
|
|
659
|
-
tx: string;
|
|
660
|
-
fromToken: string;
|
|
661
|
-
toToken: string;
|
|
662
|
-
fromAmount: number;
|
|
663
|
-
toAmount: number;
|
|
664
|
-
priceImpact: number;
|
|
665
|
-
route: string;
|
|
666
|
-
gasCost: number;
|
|
667
|
-
}
|
|
668
|
-
interface SwapQuoteResult {
|
|
669
|
-
fromToken: string;
|
|
670
|
-
toToken: string;
|
|
671
|
-
fromAmount: number;
|
|
672
|
-
toAmount: number;
|
|
673
|
-
priceImpact: number;
|
|
674
|
-
route: string;
|
|
675
|
-
/**
|
|
676
|
-
* [SPEC 20.2 / D-1 (a)] Structured Cetus route captured at quote time.
|
|
677
|
-
* Threaded through `pending_action.cetusRoute` so the prepare-route can
|
|
678
|
-
* skip the ~400-500ms `findSwapRoute()` re-discovery, and so the
|
|
679
|
-
* post-write resume system prompt can ground LLM narration against the
|
|
680
|
-
* canonical route (closing S19-F2). Optional for backward compat with
|
|
681
|
-
* pre-SPEC-20.2 callers (CLI, server-only direct calls).
|
|
682
|
-
*/
|
|
683
|
-
serializedRoute?: SerializedCetusRoute;
|
|
684
|
-
}
|
|
685
|
-
interface PayOptions {
|
|
686
|
-
url: string;
|
|
687
|
-
method?: string;
|
|
688
|
-
body?: string;
|
|
689
|
-
headers?: Record<string, string>;
|
|
690
|
-
maxPrice?: number;
|
|
691
|
-
}
|
|
692
|
-
interface PayResult {
|
|
693
|
-
status: number;
|
|
694
|
-
body: unknown;
|
|
695
|
-
paid: boolean;
|
|
696
|
-
cost?: number;
|
|
697
|
-
/**
|
|
698
|
-
* SUI gas cost actually paid on chain. Zero for gasless payments —
|
|
699
|
-
* which means an MPP payment hit the protocol's gasless allowlist
|
|
700
|
-
* (USDC / USDsui / USDY / FdUSD / AUSD / BUCK / USDB / SUI_USDE) and
|
|
701
|
-
* was accepted with `gasPrice=0, gasBudget=0, gasPayment=[]`. See
|
|
702
|
-
* https://docs.sui.io/develop/transaction-payment/gasless-stablecoin-transfers
|
|
703
|
-
*/
|
|
704
|
-
gasCostSui?: number;
|
|
705
|
-
receipt?: {
|
|
706
|
-
reference: string;
|
|
707
|
-
timestamp: string;
|
|
708
|
-
};
|
|
709
|
-
}
|
|
710
|
-
type HFAlertLevel = 'none' | 'warn' | 'critical';
|
|
711
|
-
interface FinancialSummary {
|
|
712
|
-
walletAddress: string;
|
|
713
|
-
usdcAvailable: number;
|
|
714
|
-
savingsBalance: number;
|
|
715
|
-
debtBalance: number;
|
|
716
|
-
idleUsdc: number;
|
|
717
|
-
healthFactor: number;
|
|
718
|
-
hfAlertLevel: HFAlertLevel;
|
|
719
|
-
saveApy: number;
|
|
720
|
-
borrowApy: number;
|
|
721
|
-
dailyYield: number;
|
|
722
|
-
gasReserveSui: number;
|
|
723
|
-
gasReserveUsd: number;
|
|
724
|
-
fetchedAt: number;
|
|
725
|
-
}
|
|
726
|
-
|
|
727
|
-
export { type AssetRates as A, type BalanceResponse as B, type ClaimRewardsResult as C, type DepositInfo as D, type EarningsResult as E, type FundStatusResult as F, type GasReserve as G, type HealthFactorResult as H, addSwapToTx as I, deserializeCetusRoute as J, fetchAllCoins as K, isCetusRouteFresh as L, type MaxBorrowResult as M, selectAndSplitCoin as N, OVERLAY_FEE_RATE as O, type PayOptions as P, selectSuiCoin as Q, type RatesResult as R, type SaveResult as S, type TransactionLeg as T, serializeCetusRoute as U, verifyCetusRouteCoinMatch as V, type WithdrawResult as W, type BorrowResult as a, type MaxWithdrawResult as b, type OverlayFeeConfig as c, type PayResult as d, type PendingReward as e, type PositionEntry as f, type PositionsResult as g, type RepayResult as h, type SendResult as i, type SwapRouteResult as j, type TransactionRecord as k, buildSwapTx as l, findSwapRoute as m, type T2000Options as n, type SwapResult as o, type SwapQuoteResult as p, type PaymentRequest as q, type CompoundRewardsResult as r, type SponsoredCoinMergeCache as s, type FinancialSummary as t, type CoinPage as u, type HFAlertLevel as v, type SelectAndSplitResult as w, type SerializedCetusRoute as x, type SerializedCetusRoutePath as y, type SerializedRouterDataV3 as z };
|