@t2000/sdk 4.4.0 → 5.1.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 +333 -161
- 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 +333 -150
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +802 -6702
- 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 +805 -6677
- package/dist/index.js.map +1 -1
- package/dist/types-C01EGu76.d.cts +1222 -0
- package/dist/types-C01EGu76.d.ts +1222 -0
- package/package.json +3 -16
- 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
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @t2000/sdk
|
|
2
2
|
|
|
3
|
-
The TypeScript SDK for Agent Wallets on Sui. One class (`T2000`) — wallet signing, gasless USDC + USDsui sends, Cetus swap routing,
|
|
3
|
+
The TypeScript SDK for Agent Wallets on Sui. One class (`T2000`) — wallet signing, gasless USDC + USDsui sends, Cetus swap routing, and x402 paid-API access (pay any API in USDC, no keys).
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@t2000/sdk)
|
|
6
6
|
[](https://www.npmjs.com/package/@t2000/cli)
|
|
@@ -29,11 +29,11 @@ await agent.swap({ from: 'USDC', to: 'SUI', amount: 100 }); // Cetus, ne
|
|
|
29
29
|
await agent.pay({ url: 'https://mpp.t2000.ai/openai/v1/chat/completions', method: 'POST', body, maxPrice: 0.10 });
|
|
30
30
|
```
|
|
31
31
|
|
|
32
|
-
USDC + USDsui sends and
|
|
32
|
+
USDC + USDsui sends and x402 USDC payments are gasless (Sui foundation's `0x2::balance::send_funds` sponsor). SUI sends and Cetus swaps need gas — keep ~0.05 SUI on hand.
|
|
33
33
|
|
|
34
34
|
## Full reference
|
|
35
35
|
|
|
36
|
-
Factory methods, full API surface, supported assets,
|
|
36
|
+
Factory methods, full API surface, supported assets, Cetus swap routing, x402 payments, error handling, architecture →
|
|
37
37
|
**[developers.t2000.ai/agent-sdk](https://developers.t2000.ai/agent-sdk)**
|
|
38
38
|
|
|
39
39
|
## License
|
package/dist/browser.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
require('@mysten/sui/
|
|
4
|
-
require('@mysten/sui/grpc');
|
|
3
|
+
var transactions = require('@mysten/sui/transactions');
|
|
5
4
|
var utils = require('@mysten/sui/utils');
|
|
5
|
+
require('@mysten/sui/grpc');
|
|
6
|
+
require('@mysten/sui/graphql');
|
|
6
7
|
var aggregatorSdk = require('@cetusprotocol/aggregator-sdk');
|
|
7
8
|
require('bn.js');
|
|
8
9
|
|
|
@@ -106,20 +107,33 @@ var init_errors = __esm({
|
|
|
106
107
|
});
|
|
107
108
|
|
|
108
109
|
// src/token-registry.ts
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
110
|
+
var token_registry_exports = {};
|
|
111
|
+
__export(token_registry_exports, {
|
|
112
|
+
COIN_REGISTRY: () => exports.COIN_REGISTRY,
|
|
113
|
+
ETH_TYPE: () => exports.ETH_TYPE,
|
|
114
|
+
IKA_TYPE: () => exports.IKA_TYPE,
|
|
115
|
+
LOFI_TYPE: () => exports.LOFI_TYPE,
|
|
116
|
+
MANIFEST_TYPE: () => exports.MANIFEST_TYPE,
|
|
117
|
+
NAVX_TYPE: () => exports.NAVX_TYPE,
|
|
118
|
+
SUI_TYPE: () => exports.SUI_TYPE,
|
|
119
|
+
TOKEN_MAP: () => exports.TOKEN_MAP,
|
|
120
|
+
USDC_TYPE: () => exports.USDC_TYPE,
|
|
121
|
+
USDE_TYPE: () => exports.USDE_TYPE,
|
|
122
|
+
USDSUI_TYPE: () => exports.USDSUI_TYPE,
|
|
123
|
+
USDT_TYPE: () => exports.USDT_TYPE,
|
|
124
|
+
WAL_TYPE: () => exports.WAL_TYPE,
|
|
125
|
+
WBTC_TYPE: () => exports.WBTC_TYPE,
|
|
126
|
+
getCoinMeta: () => getCoinMeta,
|
|
127
|
+
getDecimalsForCoinType: () => getDecimalsForCoinType,
|
|
128
|
+
isInRegistry: () => isInRegistry,
|
|
129
|
+
resolveSymbol: () => resolveSymbol,
|
|
130
|
+
resolveTokenType: () => resolveTokenType
|
|
131
|
+
});
|
|
132
|
+
function getCoinMeta(coinType) {
|
|
133
|
+
return BY_TYPE.get(coinType);
|
|
120
134
|
}
|
|
121
|
-
function
|
|
122
|
-
return BY_TYPE.
|
|
135
|
+
function isInRegistry(coinType) {
|
|
136
|
+
return BY_TYPE.has(coinType);
|
|
123
137
|
}
|
|
124
138
|
function getDecimalsForCoinType(coinType) {
|
|
125
139
|
const direct = BY_TYPE.get(coinType);
|
|
@@ -153,25 +167,25 @@ exports.COIN_REGISTRY = void 0; var BY_TYPE; exports.TOKEN_MAP = void 0; exports
|
|
|
153
167
|
var init_token_registry = __esm({
|
|
154
168
|
"src/token-registry.ts"() {
|
|
155
169
|
exports.COIN_REGISTRY = {
|
|
156
|
-
// ──
|
|
157
|
-
USDC: { type: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC", decimals: 6, symbol: "USDC"
|
|
158
|
-
// ──
|
|
159
|
-
SUI: { type: "0x2::sui::SUI", decimals: 9, symbol: "SUI"
|
|
160
|
-
wBTC: { type: "0x0041f9f9344cac094454cd574e333c4fdb132d7bcc9379bcd4aab485b2a63942::wbtc::WBTC", decimals: 8, symbol: "wBTC"
|
|
161
|
-
ETH: { type: "0xd0e89b2af5e4910726fbcd8b8dd37bb79b29e5f83f7491bca830e94f7f226d29::eth::ETH", decimals: 8, symbol: "ETH"
|
|
162
|
-
GOLD: { type: "0x9d297676e7a4b771ab023291377b2adfaa4938fb9080b8d12430e4b108b836a9::xaum::XAUM", decimals: 9, symbol: "GOLD"
|
|
163
|
-
DEEP: { type: "0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP", decimals: 6, symbol: "DEEP"
|
|
164
|
-
WAL: { type: "0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL", decimals: 9, symbol: "WAL"
|
|
165
|
-
NS: { type: "0x5145494a5f5100e645e4b0aa950fa6b68f614e8c59e17bc5ded3495123a79178::ns::NS", decimals: 6, symbol: "NS"
|
|
166
|
-
IKA: { type: "0x7262fb2f7a3a14c888c438a3cd9b912469a58cf60f367352c46584262e8299aa::ika::IKA", decimals: 9, symbol: "IKA"
|
|
167
|
-
CETUS: { type: "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS", decimals: 9, symbol: "CETUS"
|
|
168
|
-
NAVX: { type: "0xa99b8952d4f7d947ea77fe0ecdcc9e5fc0bcab2841d6e2a5aa00c3044e5544b5::navx::NAVX", decimals: 9, symbol: "NAVX"
|
|
169
|
-
vSUI: { type: "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT", decimals: 9, symbol: "vSUI"
|
|
170
|
-
haSUI: { type: "0xbde4ba4c2e274a60ce15c1cfff9e5c42e41654ac8b6d906a57efa4bd3c29f47d::hasui::HASUI", decimals: 9, symbol: "haSUI"
|
|
171
|
-
afSUI: { type: "0xf325ce1300e8dac124071d3152c5c5ee6174914f8bc2161e88329cf579246efc::afsui::AFSUI", decimals: 9, symbol: "afSUI"
|
|
172
|
-
LOFI: { type: "0xf22da9a24ad027cccb5f2d496cbe91de953d363513db08a3a734d361c7c17503::LOFI::LOFI", decimals: 9, symbol: "LOFI"
|
|
173
|
-
MANIFEST: { type: "0xc466c28d87b3d5cd34f3d5c088751532d71a38d93a8aae4551dd56272cfb4355::manifest::MANIFEST", decimals: 9, symbol: "MANIFEST"
|
|
174
|
-
// ──
|
|
170
|
+
// ── Settlement stable ─────────────────────────────────────────────────
|
|
171
|
+
USDC: { type: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC", decimals: 6, symbol: "USDC" },
|
|
172
|
+
// ── Common swap assets (symbol ergonomics — any coin type still swaps) ─
|
|
173
|
+
SUI: { type: "0x2::sui::SUI", decimals: 9, symbol: "SUI" },
|
|
174
|
+
wBTC: { type: "0x0041f9f9344cac094454cd574e333c4fdb132d7bcc9379bcd4aab485b2a63942::wbtc::WBTC", decimals: 8, symbol: "wBTC" },
|
|
175
|
+
ETH: { type: "0xd0e89b2af5e4910726fbcd8b8dd37bb79b29e5f83f7491bca830e94f7f226d29::eth::ETH", decimals: 8, symbol: "ETH" },
|
|
176
|
+
GOLD: { type: "0x9d297676e7a4b771ab023291377b2adfaa4938fb9080b8d12430e4b108b836a9::xaum::XAUM", decimals: 9, symbol: "GOLD" },
|
|
177
|
+
DEEP: { type: "0xdeeb7a4662eec9f2f3def03fb937a663dddaa2e215b8078a284d026b7946c270::deep::DEEP", decimals: 6, symbol: "DEEP" },
|
|
178
|
+
WAL: { type: "0x356a26eb9e012a68958082340d4c4116e7f55615cf27affcff209cf0ae544f59::wal::WAL", decimals: 9, symbol: "WAL" },
|
|
179
|
+
NS: { type: "0x5145494a5f5100e645e4b0aa950fa6b68f614e8c59e17bc5ded3495123a79178::ns::NS", decimals: 6, symbol: "NS" },
|
|
180
|
+
IKA: { type: "0x7262fb2f7a3a14c888c438a3cd9b912469a58cf60f367352c46584262e8299aa::ika::IKA", decimals: 9, symbol: "IKA" },
|
|
181
|
+
CETUS: { type: "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS", decimals: 9, symbol: "CETUS" },
|
|
182
|
+
NAVX: { type: "0xa99b8952d4f7d947ea77fe0ecdcc9e5fc0bcab2841d6e2a5aa00c3044e5544b5::navx::NAVX", decimals: 9, symbol: "NAVX" },
|
|
183
|
+
vSUI: { type: "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT", decimals: 9, symbol: "vSUI" },
|
|
184
|
+
haSUI: { type: "0xbde4ba4c2e274a60ce15c1cfff9e5c42e41654ac8b6d906a57efa4bd3c29f47d::hasui::HASUI", decimals: 9, symbol: "haSUI" },
|
|
185
|
+
afSUI: { type: "0xf325ce1300e8dac124071d3152c5c5ee6174914f8bc2161e88329cf579246efc::afsui::AFSUI", decimals: 9, symbol: "afSUI" },
|
|
186
|
+
LOFI: { type: "0xf22da9a24ad027cccb5f2d496cbe91de953d363513db08a3a734d361c7c17503::LOFI::LOFI", decimals: 9, symbol: "LOFI" },
|
|
187
|
+
MANIFEST: { type: "0xc466c28d87b3d5cd34f3d5c088751532d71a38d93a8aae4551dd56272cfb4355::manifest::MANIFEST", decimals: 9, symbol: "MANIFEST" },
|
|
188
|
+
// ── Other stables (display / classification) ──────────────────────────
|
|
175
189
|
USDT: { type: "0x375f70cf2ae4c00bf37117d0c85a2c71545e6ee05c4a5c7d282cd66a4504b068::usdt::USDT", decimals: 6, symbol: "USDT" },
|
|
176
190
|
USDe: { type: "0x41d587e5336f1c86cad50d38a7136db99333bb9bda91cea4ba69115defeb1402::sui_usde::SUI_USDE", decimals: 6, symbol: "USDe" },
|
|
177
191
|
USDSUI: { type: "0x44f838219cf67b058f3b37907b655f226153c18e33dfcd0da559a844fea9b1c1::usdsui::USDSUI", decimals: 6, symbol: "USDsui" }
|
|
@@ -203,6 +217,136 @@ var init_token_registry = __esm({
|
|
|
203
217
|
}
|
|
204
218
|
});
|
|
205
219
|
|
|
220
|
+
// src/wallet/coinSelection.ts
|
|
221
|
+
var coinSelection_exports = {};
|
|
222
|
+
__export(coinSelection_exports, {
|
|
223
|
+
fetchAllCoins: () => fetchAllCoins,
|
|
224
|
+
selectAndSplitCoin: () => selectAndSplitCoin,
|
|
225
|
+
selectSuiCoin: () => selectSuiCoin
|
|
226
|
+
});
|
|
227
|
+
async function fetchAllCoins(client, owner, coinType) {
|
|
228
|
+
const [balance, ids] = await Promise.all([
|
|
229
|
+
client.core.getBalance({ owner, coinType }),
|
|
230
|
+
(async () => {
|
|
231
|
+
const out = [];
|
|
232
|
+
let cursor;
|
|
233
|
+
let hasNext = true;
|
|
234
|
+
while (hasNext) {
|
|
235
|
+
const page = await client.core.listCoins({ owner, coinType, cursor: cursor ?? void 0 });
|
|
236
|
+
for (const c of page.objects) out.push(c.objectId);
|
|
237
|
+
cursor = page.cursor;
|
|
238
|
+
hasNext = page.hasNextPage;
|
|
239
|
+
}
|
|
240
|
+
return out;
|
|
241
|
+
})()
|
|
242
|
+
]);
|
|
243
|
+
return { ids, totalBalance: BigInt(balance.balance.balance) };
|
|
244
|
+
}
|
|
245
|
+
async function selectAndSplitCoin(tx, client, owner, coinType, amount, options = {}) {
|
|
246
|
+
if (options.sponsoredContext) {
|
|
247
|
+
return selectCoinObjectsOnly(
|
|
248
|
+
tx,
|
|
249
|
+
client,
|
|
250
|
+
owner,
|
|
251
|
+
coinType,
|
|
252
|
+
amount,
|
|
253
|
+
options.allowSwapAll ?? true,
|
|
254
|
+
options.mergeCache
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
const balanceResp = await client.core.getBalance({ owner, coinType });
|
|
258
|
+
const totalBalance = BigInt(balanceResp.balance.balance);
|
|
259
|
+
if (totalBalance === 0n) {
|
|
260
|
+
throw new exports.T2000Error("INSUFFICIENT_BALANCE", `No balance found for ${coinType}`);
|
|
261
|
+
}
|
|
262
|
+
const allowSwapAll = options.allowSwapAll ?? true;
|
|
263
|
+
if (amount !== "all" && amount > totalBalance && !allowSwapAll) {
|
|
264
|
+
throw new exports.T2000Error("INSUFFICIENT_BALANCE", `Insufficient balance for ${coinType}`, {
|
|
265
|
+
available: totalBalance.toString(),
|
|
266
|
+
required: amount.toString()
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
const requested = amount === "all" ? totalBalance : amount;
|
|
270
|
+
const swapAll = amount === "all" || requested >= totalBalance;
|
|
271
|
+
const effectiveAmount = swapAll ? totalBalance : requested;
|
|
272
|
+
const coin = transactions.coinWithBalance({ type: coinType, balance: effectiveAmount })(tx);
|
|
273
|
+
return { coin, effectiveAmount, swapAll };
|
|
274
|
+
}
|
|
275
|
+
async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowSwapAll, mergeCache) {
|
|
276
|
+
const cached = mergeCache?.get(coinType);
|
|
277
|
+
if (cached) {
|
|
278
|
+
const requested2 = amount === "all" ? cached.remaining : amount;
|
|
279
|
+
if (cached.remaining === 0n || requested2 > cached.remaining) {
|
|
280
|
+
throw new exports.T2000Error(
|
|
281
|
+
"ADDRESS_BALANCE_UNSPONSORABLE",
|
|
282
|
+
`Not enough ${coinType} in coin objects to cover all legs of this sponsored bundle. The remaining funds are in your address balance, which sponsored transactions can't access yet.`,
|
|
283
|
+
{ remaining: cached.remaining.toString(), requested: requested2.toString(), coinType }
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
const swapAll2 = amount === "all" || requested2 >= cached.remaining;
|
|
287
|
+
const effectiveAmount2 = swapAll2 ? cached.remaining : requested2;
|
|
288
|
+
const coin2 = swapAll2 ? cached.primary : tx.splitCoins(cached.primary, [effectiveAmount2])[0];
|
|
289
|
+
cached.remaining -= effectiveAmount2;
|
|
290
|
+
return { coin: coin2, effectiveAmount: effectiveAmount2, swapAll: swapAll2 };
|
|
291
|
+
}
|
|
292
|
+
const objects = [];
|
|
293
|
+
let coinObjectTotal = 0n;
|
|
294
|
+
let cursor;
|
|
295
|
+
let hasNext = true;
|
|
296
|
+
while (hasNext) {
|
|
297
|
+
const page = await client.core.listCoins({ owner, coinType, cursor: cursor ?? void 0 });
|
|
298
|
+
for (const c of page.objects) {
|
|
299
|
+
objects.push({ objectId: c.objectId, balance: BigInt(c.balance) });
|
|
300
|
+
coinObjectTotal += BigInt(c.balance);
|
|
301
|
+
}
|
|
302
|
+
cursor = page.cursor;
|
|
303
|
+
hasNext = page.hasNextPage;
|
|
304
|
+
}
|
|
305
|
+
const unsponsorable = () => new exports.T2000Error(
|
|
306
|
+
"ADDRESS_BALANCE_UNSPONSORABLE",
|
|
307
|
+
`These funds are in your address balance, which sponsored transactions can't access yet. (Funds received via gasless transfers land there.) This will work once the gas sponsor adds address-balance support.`,
|
|
308
|
+
{ coinObjectTotal: coinObjectTotal.toString(), coinType }
|
|
309
|
+
);
|
|
310
|
+
if (coinObjectTotal === 0n) {
|
|
311
|
+
throw unsponsorable();
|
|
312
|
+
}
|
|
313
|
+
const requested = amount === "all" ? coinObjectTotal : amount;
|
|
314
|
+
if (requested > coinObjectTotal) {
|
|
315
|
+
if (allowSwapAll && amount === "all") ; else {
|
|
316
|
+
throw unsponsorable();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const swapAll = amount === "all" || requested >= coinObjectTotal;
|
|
320
|
+
const effectiveAmount = swapAll ? coinObjectTotal : requested;
|
|
321
|
+
const [first, ...rest] = objects;
|
|
322
|
+
const primary = tx.object(first.objectId);
|
|
323
|
+
if (rest.length > 0) {
|
|
324
|
+
tx.mergeCoins(
|
|
325
|
+
primary,
|
|
326
|
+
rest.map((o) => tx.object(o.objectId))
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
const coin = swapAll ? primary : tx.splitCoins(primary, [effectiveAmount])[0];
|
|
330
|
+
mergeCache?.set(coinType, {
|
|
331
|
+
primary,
|
|
332
|
+
remaining: coinObjectTotal - effectiveAmount
|
|
333
|
+
});
|
|
334
|
+
return { coin, effectiveAmount, swapAll };
|
|
335
|
+
}
|
|
336
|
+
async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext, mergeCache) {
|
|
337
|
+
if (sponsoredContext) {
|
|
338
|
+
const { SUI_TYPE: SUI_TYPE2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
|
|
339
|
+
return selectCoinObjectsOnly(tx, client, owner, SUI_TYPE2, amountMist, false, mergeCache);
|
|
340
|
+
}
|
|
341
|
+
const [coin] = tx.splitCoins(tx.gas, [amountMist]);
|
|
342
|
+
return { coin, effectiveAmount: amountMist, swapAll: false };
|
|
343
|
+
}
|
|
344
|
+
var init_coinSelection = __esm({
|
|
345
|
+
"src/wallet/coinSelection.ts"() {
|
|
346
|
+
init_errors();
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
|
|
206
350
|
// src/wallet/keypairSigner.ts
|
|
207
351
|
var KeypairSigner = class {
|
|
208
352
|
constructor(keypair) {
|
|
@@ -262,12 +406,8 @@ var ZkLoginSigner = class {
|
|
|
262
406
|
}
|
|
263
407
|
};
|
|
264
408
|
|
|
265
|
-
// src/
|
|
266
|
-
|
|
267
|
-
const raw = challenge?.request?.amount;
|
|
268
|
-
const n = typeof raw === "string" ? Number(raw) : typeof raw === "number" ? raw : Number.NaN;
|
|
269
|
-
return Number.isFinite(n) ? n : void 0;
|
|
270
|
-
}
|
|
409
|
+
// src/wallet/pay.ts
|
|
410
|
+
init_errors();
|
|
271
411
|
|
|
272
412
|
// src/wallet/executeTx.ts
|
|
273
413
|
async function executeTx(client, signer, buildTx, options = {}) {
|
|
@@ -275,63 +415,142 @@ async function executeTx(client, signer, buildTx, options = {}) {
|
|
|
275
415
|
tx.setSender(signer.getAddress());
|
|
276
416
|
const txBytes = await tx.build({ client: options.buildClient ?? client });
|
|
277
417
|
const { signature } = await signer.signTransaction(txBytes);
|
|
278
|
-
const result = await client.
|
|
279
|
-
|
|
280
|
-
signature,
|
|
281
|
-
|
|
418
|
+
const result = await client.core.executeTransaction({
|
|
419
|
+
transaction: txBytes,
|
|
420
|
+
signatures: [signature],
|
|
421
|
+
include: { effects: true }
|
|
282
422
|
});
|
|
283
|
-
|
|
284
|
-
|
|
423
|
+
const txn = result.$kind === "Transaction" ? result.Transaction : result.FailedTransaction;
|
|
424
|
+
await client.core.waitForTransaction({ digest: txn.digest });
|
|
425
|
+
const effects = txn.effects ?? void 0;
|
|
426
|
+
const gasUsed = effects?.gasUsed;
|
|
285
427
|
let gasCostSui = 0;
|
|
286
428
|
if (gasUsed) {
|
|
287
429
|
const total = BigInt(gasUsed.computationCost) + BigInt(gasUsed.storageCost) - BigInt(gasUsed.storageRebate);
|
|
288
430
|
gasCostSui = Number(total) / 1e9;
|
|
289
431
|
}
|
|
290
|
-
return { digest:
|
|
432
|
+
return { digest: txn.digest, gasCostSui, effects };
|
|
291
433
|
}
|
|
292
434
|
|
|
293
435
|
// src/wallet/pay.ts
|
|
294
436
|
async function payWithMpp(args) {
|
|
295
437
|
const { signer, client, options } = args;
|
|
296
|
-
const { Mppx } = await import('mppx/client');
|
|
297
|
-
const { sui, USDC } = await import('@suimpp/mpp/client');
|
|
298
|
-
const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
|
|
299
|
-
const signerAddress = signer.getAddress();
|
|
300
|
-
let paymentDigest;
|
|
301
|
-
let gasCostSui = 0;
|
|
302
|
-
let chargedAmount;
|
|
303
|
-
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
304
|
-
const grpcBaseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
305
|
-
const grpcClient = new SuiGrpcClient2({ baseUrl: grpcBaseUrl, network });
|
|
306
|
-
const mppx = Mppx.create({
|
|
307
|
-
polyfill: false,
|
|
308
|
-
onChallenge: async (challenge) => {
|
|
309
|
-
const parsed = parseChallengeAmount(challenge);
|
|
310
|
-
if (parsed !== void 0) chargedAmount = parsed;
|
|
311
|
-
return void 0;
|
|
312
|
-
},
|
|
313
|
-
methods: [sui({
|
|
314
|
-
client,
|
|
315
|
-
currency: USDC,
|
|
316
|
-
signer: {
|
|
317
|
-
toSuiAddress: () => signerAddress,
|
|
318
|
-
signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
|
|
319
|
-
},
|
|
320
|
-
execute: async (tx) => {
|
|
321
|
-
const result = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
|
|
322
|
-
paymentDigest = result.digest;
|
|
323
|
-
gasCostSui = result.gasCostSui;
|
|
324
|
-
return { digest: result.digest };
|
|
325
|
-
}
|
|
326
|
-
})]
|
|
327
|
-
});
|
|
328
438
|
const method = (options.method ?? "GET").toUpperCase();
|
|
329
439
|
const canHaveBody = method !== "GET" && method !== "HEAD";
|
|
330
|
-
const
|
|
440
|
+
const reqInit = {
|
|
331
441
|
method,
|
|
332
442
|
headers: options.headers,
|
|
333
443
|
body: canHaveBody ? options.body : void 0
|
|
444
|
+
};
|
|
445
|
+
const probe = await fetch(options.url, reqInit);
|
|
446
|
+
if (probe.status !== 402) {
|
|
447
|
+
return finalize(probe, { paid: false });
|
|
448
|
+
}
|
|
449
|
+
const requirements = await pickSuiExactRequirements(probe, client.network);
|
|
450
|
+
if (!requirements) {
|
|
451
|
+
throw new exports.T2000Error(
|
|
452
|
+
"FACILITATOR_REJECTION",
|
|
453
|
+
`Endpoint returned 402 without an x402 'exact' / sui:${client.network} payment requirement. This SDK only speaks the x402 dialect.`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
return payViaX402({ signer, client, options, reqInit, requirements });
|
|
457
|
+
}
|
|
458
|
+
async function pickSuiExactRequirements(response, network) {
|
|
459
|
+
try {
|
|
460
|
+
const body = await response.clone().json();
|
|
461
|
+
const want = `sui:${network === "testnet" ? "testnet" : "mainnet"}`;
|
|
462
|
+
return body.accepts?.find((a) => a.scheme === "exact" && a.network === want);
|
|
463
|
+
} catch {
|
|
464
|
+
return void 0;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
async function payViaX402(args) {
|
|
468
|
+
const { signer, client, options, reqInit, requirements } = args;
|
|
469
|
+
const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import('@suimpp/mpp/x402');
|
|
470
|
+
const amountRaw = BigInt(requirements.maxAmountRequired);
|
|
471
|
+
const migrationGasSui = await ensureAddressBalanceCovers({
|
|
472
|
+
signer,
|
|
473
|
+
client,
|
|
474
|
+
asset: requirements.asset,
|
|
475
|
+
amountRaw
|
|
476
|
+
});
|
|
477
|
+
const signerAdapter = {
|
|
478
|
+
toSuiAddress: () => signer.getAddress(),
|
|
479
|
+
signTransaction: (bytes) => signer.signTransaction(bytes)
|
|
480
|
+
};
|
|
481
|
+
const { header } = await buildX402SignedPayment({ requirements, signer: signerAdapter });
|
|
482
|
+
const res = await fetch(options.url, {
|
|
483
|
+
...reqInit,
|
|
484
|
+
headers: { ...options.headers ?? {}, [X402_PAYMENT_HEADER]: header }
|
|
334
485
|
});
|
|
486
|
+
const settleHeader = res.headers.get(X402_PAYMENT_RESPONSE_HEADER);
|
|
487
|
+
const paid = !!settleHeader;
|
|
488
|
+
let digest;
|
|
489
|
+
if (settleHeader) {
|
|
490
|
+
try {
|
|
491
|
+
digest = JSON.parse(new TextDecoder().decode(utils.fromBase64(settleHeader))).transaction;
|
|
492
|
+
} catch {
|
|
493
|
+
digest = void 0;
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
const result = await finalize(res, { paid });
|
|
497
|
+
if (!paid) return { ...result, dialect: "x402" };
|
|
498
|
+
return {
|
|
499
|
+
...result,
|
|
500
|
+
dialect: "x402",
|
|
501
|
+
cost: atomicToHuman(amountRaw, await assetDecimals(requirements.asset)),
|
|
502
|
+
gasCostSui: migrationGasSui,
|
|
503
|
+
receipt: digest ? { reference: digest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : result.receipt
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
async function ensureAddressBalanceCovers(args) {
|
|
507
|
+
const { signer, client, asset, amountRaw } = args;
|
|
508
|
+
const owner = signer.getAddress();
|
|
509
|
+
const balanceResp = await client.core.getBalance({ owner, coinType: asset });
|
|
510
|
+
const total = BigInt(balanceResp.balance.balance);
|
|
511
|
+
if (total < amountRaw) {
|
|
512
|
+
throw new exports.T2000Error("INSUFFICIENT_BALANCE", `Insufficient ${asset} to pay`, {
|
|
513
|
+
available: total.toString(),
|
|
514
|
+
required: amountRaw.toString()
|
|
515
|
+
});
|
|
516
|
+
}
|
|
517
|
+
let coinSum = 0n;
|
|
518
|
+
let cursor;
|
|
519
|
+
let hasNext = true;
|
|
520
|
+
while (hasNext) {
|
|
521
|
+
const page = await client.core.listCoins({ owner, coinType: asset, cursor: cursor ?? void 0 });
|
|
522
|
+
for (const c of page.objects) coinSum += BigInt(c.balance);
|
|
523
|
+
cursor = page.cursor;
|
|
524
|
+
hasNext = page.hasNextPage;
|
|
525
|
+
}
|
|
526
|
+
const addressBalance = total - coinSum;
|
|
527
|
+
if (addressBalance >= amountRaw) return 0;
|
|
528
|
+
const shortfall = amountRaw - addressBalance;
|
|
529
|
+
const { Transaction: Transaction2 } = await import('@mysten/sui/transactions');
|
|
530
|
+
const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
|
|
531
|
+
const grpcClient = await makeGrpcBuildClient(client);
|
|
532
|
+
const migration = await executeTx(
|
|
533
|
+
client,
|
|
534
|
+
signer,
|
|
535
|
+
async () => {
|
|
536
|
+
const tx = new Transaction2();
|
|
537
|
+
const { coin } = await selectAndSplitCoin2(tx, client, owner, asset, shortfall, {
|
|
538
|
+
sponsoredContext: true,
|
|
539
|
+
// coin-objects-only — never the address balance
|
|
540
|
+
allowSwapAll: false
|
|
541
|
+
});
|
|
542
|
+
tx.moveCall({
|
|
543
|
+
target: "0x2::coin::send_funds",
|
|
544
|
+
typeArguments: [asset],
|
|
545
|
+
arguments: [coin, tx.pure.address(owner)]
|
|
546
|
+
});
|
|
547
|
+
return tx;
|
|
548
|
+
},
|
|
549
|
+
{ buildClient: grpcClient }
|
|
550
|
+
);
|
|
551
|
+
return migration.gasCostSui;
|
|
552
|
+
}
|
|
553
|
+
async function finalize(response, opts) {
|
|
335
554
|
const contentType = response.headers.get("content-type") ?? "";
|
|
336
555
|
let body;
|
|
337
556
|
try {
|
|
@@ -339,15 +558,25 @@ async function payWithMpp(args) {
|
|
|
339
558
|
} catch {
|
|
340
559
|
body = null;
|
|
341
560
|
}
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
561
|
+
return { status: response.status, body, paid: opts.paid };
|
|
562
|
+
}
|
|
563
|
+
async function makeGrpcBuildClient(client) {
|
|
564
|
+
const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
|
|
565
|
+
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
566
|
+
const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
567
|
+
return new SuiGrpcClient2({ baseUrl, network });
|
|
568
|
+
}
|
|
569
|
+
function atomicToHuman(raw, decimals) {
|
|
570
|
+
return Number(raw) / 10 ** decimals;
|
|
571
|
+
}
|
|
572
|
+
async function assetDecimals(coinType) {
|
|
573
|
+
try {
|
|
574
|
+
const { getDecimalsForCoinType: getDecimalsForCoinType2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
|
|
575
|
+
const d = getDecimalsForCoinType2(coinType);
|
|
576
|
+
return typeof d === "number" ? d : 6;
|
|
577
|
+
} catch {
|
|
578
|
+
return 6;
|
|
579
|
+
}
|
|
351
580
|
}
|
|
352
581
|
|
|
353
582
|
// src/browser.ts
|
|
@@ -358,9 +587,6 @@ init_errors();
|
|
|
358
587
|
var MIST_PER_SUI = 1000000000n;
|
|
359
588
|
var SUI_DECIMALS = 9;
|
|
360
589
|
var USDC_DECIMALS = 6;
|
|
361
|
-
var BPS_DENOMINATOR = 10000n;
|
|
362
|
-
var SAVE_FEE_BPS = 10n;
|
|
363
|
-
var BORROW_FEE_BPS = 5n;
|
|
364
590
|
var CLOCK_ID = "0x6";
|
|
365
591
|
var SUPPORTED_ASSETS = {
|
|
366
592
|
USDC: {
|
|
@@ -419,7 +645,6 @@ var SUPPORTED_ASSETS = {
|
|
|
419
645
|
}
|
|
420
646
|
};
|
|
421
647
|
var STABLE_ASSETS = ["USDC", "USDsui"];
|
|
422
|
-
var ALL_NAVI_ASSETS = Object.keys(SUPPORTED_ASSETS);
|
|
423
648
|
({
|
|
424
649
|
USDC: SUPPORTED_ASSETS.USDC.type,
|
|
425
650
|
USDsui: SUPPORTED_ASSETS.USDsui.type
|
|
@@ -583,8 +808,13 @@ function extractAllUserLegs(changes, sender) {
|
|
|
583
808
|
}
|
|
584
809
|
return legs;
|
|
585
810
|
}
|
|
586
|
-
|
|
587
|
-
|
|
811
|
+
function buildRecord(args) {
|
|
812
|
+
const { digest, moveCallTargets, commandTypes, balanceChanges, timestampMs, gasCost, address } = args;
|
|
813
|
+
const legs = extractAllUserLegs(balanceChanges, address);
|
|
814
|
+
const { amount, asset, recipient, direction } = extractTransferDetails(balanceChanges, address);
|
|
815
|
+
const { action, label } = classifyTransaction(moveCallTargets, commandTypes, balanceChanges, address);
|
|
816
|
+
return { digest, action, label, legs, amount, asset, recipient, direction, timestamp: timestampMs, gasCost };
|
|
817
|
+
}
|
|
588
818
|
function parseSuiRpcTx(tx, address) {
|
|
589
819
|
return parseTxRecord(tx, address);
|
|
590
820
|
}
|
|
@@ -605,27 +835,15 @@ function parseTxRecord(tx, address) {
|
|
|
605
835
|
const gasUsed = tx.effects?.gasUsed;
|
|
606
836
|
const gasCost = gasUsed ? (Number(gasUsed.computationCost) + Number(gasUsed.storageCost) - Number(gasUsed.storageRebate)) / 1e9 : void 0;
|
|
607
837
|
const { moveCallTargets, commandTypes } = extractCommands(tx.transaction);
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
const { amount, asset, recipient, direction } = extractTransferDetails(balanceChanges, address);
|
|
611
|
-
const { action, label } = classifyTransaction(
|
|
838
|
+
return buildRecord({
|
|
839
|
+
digest: tx.digest,
|
|
612
840
|
moveCallTargets,
|
|
613
841
|
commandTypes,
|
|
614
|
-
balanceChanges,
|
|
842
|
+
balanceChanges: tx.balanceChanges ?? [],
|
|
843
|
+
timestampMs: Number(tx.timestampMs ?? 0),
|
|
844
|
+
gasCost,
|
|
615
845
|
address
|
|
616
|
-
);
|
|
617
|
-
return {
|
|
618
|
-
digest: tx.digest,
|
|
619
|
-
action,
|
|
620
|
-
label,
|
|
621
|
-
legs,
|
|
622
|
-
amount,
|
|
623
|
-
asset,
|
|
624
|
-
recipient,
|
|
625
|
-
direction,
|
|
626
|
-
timestamp: Number(tx.timestampMs ?? 0),
|
|
627
|
-
gasCost
|
|
628
|
-
};
|
|
846
|
+
});
|
|
629
847
|
}
|
|
630
848
|
function extractCommands(txBlock) {
|
|
631
849
|
const result = { moveCallTargets: [], commandTypes: [] };
|
|
@@ -700,44 +918,13 @@ function toBase64(bytes) {
|
|
|
700
918
|
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
701
919
|
return btoa(binary);
|
|
702
920
|
}
|
|
703
|
-
function
|
|
921
|
+
function fromBase642(b64) {
|
|
704
922
|
const binary = atob(b64);
|
|
705
923
|
const bytes = new Uint8Array(binary.length);
|
|
706
924
|
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
707
925
|
return bytes;
|
|
708
926
|
}
|
|
709
927
|
|
|
710
|
-
// src/protocols/protocolFee.ts
|
|
711
|
-
var FEE_RATES = {
|
|
712
|
-
save: SAVE_FEE_BPS,
|
|
713
|
-
borrow: BORROW_FEE_BPS,
|
|
714
|
-
// Swap uses Cetus's overlay-fee mechanism (taken from output by the aggregator
|
|
715
|
-
// and transferred to `overlayFee.receiver`). We list the rate here for display
|
|
716
|
-
// / quote calculations only — `addFeeTransfer` is NOT called for swaps.
|
|
717
|
-
swap: 10n
|
|
718
|
-
// 0.1%
|
|
719
|
-
};
|
|
720
|
-
function calculateFee(operation, amount) {
|
|
721
|
-
const bps = FEE_RATES[operation];
|
|
722
|
-
const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
|
|
723
|
-
const rawAmount = stableToRaw(feeAmount, USDC_DECIMALS);
|
|
724
|
-
return {
|
|
725
|
-
amount: feeAmount,
|
|
726
|
-
asset: "USDC",
|
|
727
|
-
rate: Number(bps) / Number(BPS_DENOMINATOR),
|
|
728
|
-
rawAmount
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
function addFeeTransfer(tx, paymentCoin, feeBps, receiver, amount, decimals = USDC_DECIMALS) {
|
|
732
|
-
if (feeBps <= 0n) return;
|
|
733
|
-
if (amount <= 0) return;
|
|
734
|
-
const feeAmount = amount * Number(feeBps) / Number(BPS_DENOMINATOR);
|
|
735
|
-
const rawFee = stableToRaw(feeAmount, decimals);
|
|
736
|
-
if (rawFee <= 0n) return;
|
|
737
|
-
const [feeCoin] = tx.splitCoins(paymentCoin, [tx.pure.u64(rawFee)]);
|
|
738
|
-
tx.transferObjects([feeCoin], tx.pure.address(receiver));
|
|
739
|
-
}
|
|
740
|
-
|
|
741
928
|
// src/protocols/cetus-swap.ts
|
|
742
929
|
init_token_registry();
|
|
743
930
|
init_token_registry();
|
|
@@ -840,10 +1027,6 @@ function buildMessage(rule, details) {
|
|
|
840
1027
|
}
|
|
841
1028
|
|
|
842
1029
|
// src/safeguards/types.ts
|
|
843
|
-
var OUTBOUND_OPS = /* @__PURE__ */ new Set([
|
|
844
|
-
"send",
|
|
845
|
-
"pay"
|
|
846
|
-
]);
|
|
847
1030
|
var DEFAULT_SAFEGUARD_CONFIG = {
|
|
848
1031
|
locked: false,
|
|
849
1032
|
maxPerTx: 0,
|
|
@@ -855,9 +1038,6 @@ var DEFAULT_SAFEGUARD_CONFIG = {
|
|
|
855
1038
|
// src/browser.ts
|
|
856
1039
|
init_token_registry();
|
|
857
1040
|
|
|
858
|
-
exports.ALL_NAVI_ASSETS = ALL_NAVI_ASSETS;
|
|
859
|
-
exports.BORROW_FEE_BPS = BORROW_FEE_BPS;
|
|
860
|
-
exports.BPS_DENOMINATOR = BPS_DENOMINATOR;
|
|
861
1041
|
exports.CLOCK_ID = CLOCK_ID;
|
|
862
1042
|
exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
|
|
863
1043
|
exports.DEFAULT_SAFEGUARD_CONFIG = DEFAULT_SAFEGUARD_CONFIG;
|
|
@@ -866,9 +1046,7 @@ exports.KNOWN_TARGETS = KNOWN_TARGETS;
|
|
|
866
1046
|
exports.KeypairSigner = KeypairSigner;
|
|
867
1047
|
exports.LABEL_PATTERNS = LABEL_PATTERNS;
|
|
868
1048
|
exports.MIST_PER_SUI = MIST_PER_SUI;
|
|
869
|
-
exports.OUTBOUND_OPS = OUTBOUND_OPS;
|
|
870
1049
|
exports.OVERLAY_FEE_RATE = OVERLAY_FEE_RATE;
|
|
871
|
-
exports.SAVE_FEE_BPS = SAVE_FEE_BPS;
|
|
872
1050
|
exports.STABLE_ASSETS = STABLE_ASSETS;
|
|
873
1051
|
exports.SUI_DECIMALS = SUI_DECIMALS;
|
|
874
1052
|
exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
|
|
@@ -876,9 +1054,7 @@ exports.SafeguardError = SafeguardError;
|
|
|
876
1054
|
exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
|
|
877
1055
|
exports.USDC_DECIMALS = USDC_DECIMALS;
|
|
878
1056
|
exports.ZkLoginSigner = ZkLoginSigner;
|
|
879
|
-
exports.addFeeTransfer = addFeeTransfer;
|
|
880
1057
|
exports.buildSwapTx = buildSwapTx;
|
|
881
|
-
exports.calculateFee = calculateFee;
|
|
882
1058
|
exports.classifyAction = classifyAction;
|
|
883
1059
|
exports.classifyLabel = classifyLabel;
|
|
884
1060
|
exports.classifyTransaction = classifyTransaction;
|
|
@@ -892,13 +1068,9 @@ exports.findSwapRoute = findSwapRoute;
|
|
|
892
1068
|
exports.formatAssetAmount = formatAssetAmount;
|
|
893
1069
|
exports.formatSui = formatSui;
|
|
894
1070
|
exports.formatUsd = formatUsd;
|
|
895
|
-
exports.fromBase64 =
|
|
1071
|
+
exports.fromBase64 = fromBase642;
|
|
896
1072
|
exports.getDecimals = getDecimals;
|
|
897
1073
|
exports.getDecimalsForCoinType = getDecimalsForCoinType;
|
|
898
|
-
exports.getTier = getTier;
|
|
899
|
-
exports.isSupported = isSupported;
|
|
900
|
-
exports.isTier1 = isTier1;
|
|
901
|
-
exports.isTier2 = isTier2;
|
|
902
1074
|
exports.mapMoveAbortCode = mapMoveAbortCode;
|
|
903
1075
|
exports.mapWalletError = mapWalletError;
|
|
904
1076
|
exports.mistToSui = mistToSui;
|