@t2000/sdk 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.cjs +293 -94
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.d.cts +1 -1
- package/dist/browser.d.ts +1 -1
- package/dist/browser.js +293 -92
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +330 -205
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -19
- package/dist/index.d.ts +100 -19
- package/dist/index.js +320 -204
- package/dist/index.js.map +1 -1
- package/dist/{types-CgZWnHhs.d.cts → simulate-BTIIpnXc.d.cts} +11 -39
- package/dist/{types-CgZWnHhs.d.ts → simulate-BTIIpnXc.d.ts} +11 -39
- package/package.json +3 -4
package/dist/browser.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var transactions = require('@mysten/sui/transactions');
|
|
4
|
+
var utils = require('@mysten/sui/utils');
|
|
3
5
|
require('@mysten/sui/grpc');
|
|
4
6
|
require('@mysten/sui/graphql');
|
|
5
|
-
var utils = require('@mysten/sui/utils');
|
|
6
7
|
var aggregatorSdk = require('@cetusprotocol/aggregator-sdk');
|
|
7
8
|
require('bn.js');
|
|
8
9
|
|
|
@@ -106,6 +107,34 @@ var init_errors = __esm({
|
|
|
106
107
|
});
|
|
107
108
|
|
|
108
109
|
// src/token-registry.ts
|
|
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);
|
|
134
|
+
}
|
|
135
|
+
function isInRegistry(coinType) {
|
|
136
|
+
return BY_TYPE.has(coinType);
|
|
137
|
+
}
|
|
109
138
|
function getDecimalsForCoinType(coinType) {
|
|
110
139
|
const direct = BY_TYPE.get(coinType);
|
|
111
140
|
if (direct) return direct.decimals;
|
|
@@ -188,6 +217,136 @@ var init_token_registry = __esm({
|
|
|
188
217
|
}
|
|
189
218
|
});
|
|
190
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
|
+
|
|
191
350
|
// src/wallet/keypairSigner.ts
|
|
192
351
|
var KeypairSigner = class {
|
|
193
352
|
constructor(keypair) {
|
|
@@ -247,12 +406,8 @@ var ZkLoginSigner = class {
|
|
|
247
406
|
}
|
|
248
407
|
};
|
|
249
408
|
|
|
250
|
-
// src/
|
|
251
|
-
|
|
252
|
-
const raw = challenge?.request?.amount;
|
|
253
|
-
const n = typeof raw === "string" ? Number(raw) : typeof raw === "number" ? raw : Number.NaN;
|
|
254
|
-
return Number.isFinite(n) ? n : void 0;
|
|
255
|
-
}
|
|
409
|
+
// src/wallet/pay.ts
|
|
410
|
+
init_errors();
|
|
256
411
|
|
|
257
412
|
// src/wallet/executeTx.ts
|
|
258
413
|
async function executeTx(client, signer, buildTx, options = {}) {
|
|
@@ -280,45 +435,122 @@ async function executeTx(client, signer, buildTx, options = {}) {
|
|
|
280
435
|
// src/wallet/pay.ts
|
|
281
436
|
async function payWithMpp(args) {
|
|
282
437
|
const { signer, client, options } = args;
|
|
283
|
-
const { Mppx } = await import('mppx/client');
|
|
284
|
-
const { sui, USDC } = await import('@suimpp/mpp/client');
|
|
285
|
-
const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
|
|
286
|
-
const signerAddress = signer.getAddress();
|
|
287
|
-
let paymentDigest;
|
|
288
|
-
let gasCostSui = 0;
|
|
289
|
-
let chargedAmount;
|
|
290
|
-
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
291
|
-
const grpcBaseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
292
|
-
const grpcClient = new SuiGrpcClient2({ baseUrl: grpcBaseUrl, network });
|
|
293
|
-
const mppx = Mppx.create({
|
|
294
|
-
polyfill: false,
|
|
295
|
-
onChallenge: async (challenge) => {
|
|
296
|
-
const parsed = parseChallengeAmount(challenge);
|
|
297
|
-
if (parsed !== void 0) chargedAmount = parsed;
|
|
298
|
-
return void 0;
|
|
299
|
-
},
|
|
300
|
-
methods: [sui({
|
|
301
|
-
client,
|
|
302
|
-
currency: USDC,
|
|
303
|
-
signer: {
|
|
304
|
-
toSuiAddress: () => signerAddress,
|
|
305
|
-
signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
|
|
306
|
-
},
|
|
307
|
-
execute: async (tx) => {
|
|
308
|
-
const result = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
|
|
309
|
-
paymentDigest = result.digest;
|
|
310
|
-
gasCostSui = result.gasCostSui;
|
|
311
|
-
return { digest: result.digest };
|
|
312
|
-
}
|
|
313
|
-
})]
|
|
314
|
-
});
|
|
315
438
|
const method = (options.method ?? "GET").toUpperCase();
|
|
316
439
|
const canHaveBody = method !== "GET" && method !== "HEAD";
|
|
317
|
-
const
|
|
440
|
+
const reqInit = {
|
|
318
441
|
method,
|
|
319
442
|
headers: options.headers,
|
|
320
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
|
|
321
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 }
|
|
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) {
|
|
322
554
|
const contentType = response.headers.get("content-type") ?? "";
|
|
323
555
|
let body;
|
|
324
556
|
try {
|
|
@@ -326,15 +558,25 @@ async function payWithMpp(args) {
|
|
|
326
558
|
} catch {
|
|
327
559
|
body = null;
|
|
328
560
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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
|
+
}
|
|
338
580
|
}
|
|
339
581
|
|
|
340
582
|
// src/browser.ts
|
|
@@ -676,7 +918,7 @@ function toBase64(bytes) {
|
|
|
676
918
|
for (const byte of bytes) binary += String.fromCharCode(byte);
|
|
677
919
|
return btoa(binary);
|
|
678
920
|
}
|
|
679
|
-
function
|
|
921
|
+
function fromBase642(b64) {
|
|
680
922
|
const binary = atob(b64);
|
|
681
923
|
const bytes = new Uint8Array(binary.length);
|
|
682
924
|
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
@@ -752,53 +994,11 @@ async function buildSwapTx(params) {
|
|
|
752
994
|
return outputCoin;
|
|
753
995
|
}
|
|
754
996
|
|
|
755
|
-
// src/safeguards/errors.ts
|
|
756
|
-
init_errors();
|
|
757
|
-
var SafeguardError = class extends exports.T2000Error {
|
|
758
|
-
rule;
|
|
759
|
-
details;
|
|
760
|
-
constructor(rule, details, message) {
|
|
761
|
-
const msg = message ?? buildMessage(rule, details);
|
|
762
|
-
super("SAFEGUARD_BLOCKED", msg, { rule, ...details });
|
|
763
|
-
this.name = "SafeguardError";
|
|
764
|
-
this.rule = rule;
|
|
765
|
-
this.details = details;
|
|
766
|
-
}
|
|
767
|
-
toJSON() {
|
|
768
|
-
return {
|
|
769
|
-
error: "SAFEGUARD_BLOCKED",
|
|
770
|
-
message: this.message,
|
|
771
|
-
retryable: this.retryable,
|
|
772
|
-
data: { rule: this.rule, ...this.details }
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
};
|
|
776
|
-
function buildMessage(rule, details) {
|
|
777
|
-
switch (rule) {
|
|
778
|
-
case "locked":
|
|
779
|
-
return "Agent is locked. All operations are frozen.";
|
|
780
|
-
case "maxPerTx":
|
|
781
|
-
return `Amount $${(details.attempted ?? 0).toFixed(2)} exceeds per-transaction limit ($${(details.limit ?? 0).toFixed(2)})`;
|
|
782
|
-
case "maxDailySend":
|
|
783
|
-
return `Daily send limit reached ($${(details.current ?? 0).toFixed(2)}/$${(details.limit ?? 0).toFixed(2)} used today)`;
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
// src/safeguards/types.ts
|
|
788
|
-
var DEFAULT_SAFEGUARD_CONFIG = {
|
|
789
|
-
locked: false,
|
|
790
|
-
maxPerTx: 0,
|
|
791
|
-
maxDailySend: 0,
|
|
792
|
-
dailyUsed: 0,
|
|
793
|
-
dailyResetDate: ""
|
|
794
|
-
};
|
|
795
|
-
|
|
796
997
|
// src/browser.ts
|
|
797
998
|
init_token_registry();
|
|
798
999
|
|
|
799
1000
|
exports.CLOCK_ID = CLOCK_ID;
|
|
800
1001
|
exports.DEFAULT_NETWORK = DEFAULT_NETWORK;
|
|
801
|
-
exports.DEFAULT_SAFEGUARD_CONFIG = DEFAULT_SAFEGUARD_CONFIG;
|
|
802
1002
|
exports.GAS_RESERVE_MIN = GAS_RESERVE_MIN;
|
|
803
1003
|
exports.KNOWN_TARGETS = KNOWN_TARGETS;
|
|
804
1004
|
exports.KeypairSigner = KeypairSigner;
|
|
@@ -808,7 +1008,6 @@ exports.OVERLAY_FEE_RATE = OVERLAY_FEE_RATE;
|
|
|
808
1008
|
exports.STABLE_ASSETS = STABLE_ASSETS;
|
|
809
1009
|
exports.SUI_DECIMALS = SUI_DECIMALS;
|
|
810
1010
|
exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
|
|
811
|
-
exports.SafeguardError = SafeguardError;
|
|
812
1011
|
exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
|
|
813
1012
|
exports.USDC_DECIMALS = USDC_DECIMALS;
|
|
814
1013
|
exports.ZkLoginSigner = ZkLoginSigner;
|
|
@@ -826,7 +1025,7 @@ exports.findSwapRoute = findSwapRoute;
|
|
|
826
1025
|
exports.formatAssetAmount = formatAssetAmount;
|
|
827
1026
|
exports.formatSui = formatSui;
|
|
828
1027
|
exports.formatUsd = formatUsd;
|
|
829
|
-
exports.fromBase64 =
|
|
1028
|
+
exports.fromBase64 = fromBase642;
|
|
830
1029
|
exports.getDecimals = getDecimals;
|
|
831
1030
|
exports.getDecimalsForCoinType = getDecimalsForCoinType;
|
|
832
1031
|
exports.mapMoveAbortCode = mapMoveAbortCode;
|