@t2000/sdk 5.0.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.
@@ -1,4 +1,4 @@
1
- export { B as BalanceResponse, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, D as DEFAULT_NETWORK, e as DEFAULT_SAFEGUARD_CONFIG, f as DepositInfo, E as ETH_TYPE, g as ExtractedTransfer, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, O as OVERLAY_FEE_RATE, k as OverlayFeeConfig, P as PayOptions, l as PayResult, S as STABLE_ASSETS, m as SUI_DECIMALS, n as SUI_TYPE, o as SUPPORTED_ASSETS, p as SafeguardConfig, q as SafeguardError, r as SafeguardErrorDetails, s as SafeguardRule, t as SendResult, u as SimulationResult, v as StableAsset, w as SuiHolding, x as SuiRpcTxBlock, y as SupportedAsset, z as SwapRouteResult, T as T2000Error, A as T2000ErrorCode, F as T2000ErrorData, H as T2000_OVERLAY_FEE_WALLET, J as TOKEN_MAP, Q as TransactionLeg, R as TransactionRecord, U as TransactionSigner, V as TxDirection, W as TxMetadata, X as USDC_DECIMALS, Y as USDC_TYPE, Z as USDE_TYPE, _ as USDSUI_TYPE, $ as USDT_TYPE, a0 as WAL_TYPE, a1 as WBTC_TYPE, a2 as ZkLoginProof, a3 as ZkLoginSigner, a4 as buildSwapTx, a5 as classifyAction, a6 as classifyLabel, a7 as classifyTransaction, a8 as executeTx, a9 as extractAllUserLegs, aa as extractTransferDetails, ab as extractTxCommands, ac as extractTxSender, ad as fallbackLabel, ae as findSwapRoute, af as formatAssetAmount, ag as formatSui, ah as formatUsd, ai as getDecimals, aj as getDecimalsForCoinType, ak as mapMoveAbortCode, al as mapWalletError, am as mistToSui, an as parseSuiRpcTx, ao as payWithMpp, ap as rawToStable, aq as rawToUsdc, ar as refineLendingLabel, as as resolveSymbol, at as resolveTokenType, au as stableToRaw, av as suiToMist, aw as truncateAddress, ax as usdcToRaw, ay as validateAddress } from './types-CgZWnHhs.cjs';
1
+ export { B as BalanceResponse, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, D as DEFAULT_NETWORK, e as DEFAULT_SAFEGUARD_CONFIG, f as DepositInfo, E as ETH_TYPE, g as ExtractedTransfer, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, O as OVERLAY_FEE_RATE, k as OverlayFeeConfig, P as PayOptions, l as PayResult, S as STABLE_ASSETS, m as SUI_DECIMALS, n as SUI_TYPE, o as SUPPORTED_ASSETS, p as SafeguardConfig, q as SafeguardError, r as SafeguardErrorDetails, s as SafeguardRule, t as SendResult, u as SimulationResult, v as StableAsset, w as SuiHolding, x as SuiRpcTxBlock, y as SupportedAsset, z as SwapRouteResult, T as T2000Error, A as T2000ErrorCode, F as T2000ErrorData, H as T2000_OVERLAY_FEE_WALLET, J as TOKEN_MAP, Q as TransactionLeg, R as TransactionRecord, U as TransactionSigner, V as TxDirection, W as TxMetadata, X as USDC_DECIMALS, Y as USDC_TYPE, Z as USDE_TYPE, _ as USDSUI_TYPE, $ as USDT_TYPE, a0 as WAL_TYPE, a1 as WBTC_TYPE, a2 as ZkLoginProof, a3 as ZkLoginSigner, a4 as buildSwapTx, a5 as classifyAction, a6 as classifyLabel, a7 as classifyTransaction, a8 as executeTx, a9 as extractAllUserLegs, aa as extractTransferDetails, ab as extractTxCommands, ac as extractTxSender, ad as fallbackLabel, ae as findSwapRoute, af as formatAssetAmount, ag as formatSui, ah as formatUsd, ai as getDecimals, aj as getDecimalsForCoinType, ak as mapMoveAbortCode, al as mapWalletError, am as mistToSui, an as parseSuiRpcTx, ao as payWithMpp, ap as rawToStable, aq as rawToUsdc, ar as refineLendingLabel, as as resolveSymbol, at as resolveTokenType, au as stableToRaw, av as suiToMist, aw as truncateAddress, ax as usdcToRaw, ay as validateAddress } from './types-C01EGu76.cjs';
2
2
  import '@mysten/sui/keypairs/ed25519';
3
3
  import '@mysten/sui/grpc';
4
4
  import '@mysten/sui/client';
package/dist/browser.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { B as BalanceResponse, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, D as DEFAULT_NETWORK, e as DEFAULT_SAFEGUARD_CONFIG, f as DepositInfo, E as ETH_TYPE, g as ExtractedTransfer, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, O as OVERLAY_FEE_RATE, k as OverlayFeeConfig, P as PayOptions, l as PayResult, S as STABLE_ASSETS, m as SUI_DECIMALS, n as SUI_TYPE, o as SUPPORTED_ASSETS, p as SafeguardConfig, q as SafeguardError, r as SafeguardErrorDetails, s as SafeguardRule, t as SendResult, u as SimulationResult, v as StableAsset, w as SuiHolding, x as SuiRpcTxBlock, y as SupportedAsset, z as SwapRouteResult, T as T2000Error, A as T2000ErrorCode, F as T2000ErrorData, H as T2000_OVERLAY_FEE_WALLET, J as TOKEN_MAP, Q as TransactionLeg, R as TransactionRecord, U as TransactionSigner, V as TxDirection, W as TxMetadata, X as USDC_DECIMALS, Y as USDC_TYPE, Z as USDE_TYPE, _ as USDSUI_TYPE, $ as USDT_TYPE, a0 as WAL_TYPE, a1 as WBTC_TYPE, a2 as ZkLoginProof, a3 as ZkLoginSigner, a4 as buildSwapTx, a5 as classifyAction, a6 as classifyLabel, a7 as classifyTransaction, a8 as executeTx, a9 as extractAllUserLegs, aa as extractTransferDetails, ab as extractTxCommands, ac as extractTxSender, ad as fallbackLabel, ae as findSwapRoute, af as formatAssetAmount, ag as formatSui, ah as formatUsd, ai as getDecimals, aj as getDecimalsForCoinType, ak as mapMoveAbortCode, al as mapWalletError, am as mistToSui, an as parseSuiRpcTx, ao as payWithMpp, ap as rawToStable, aq as rawToUsdc, ar as refineLendingLabel, as as resolveSymbol, at as resolveTokenType, au as stableToRaw, av as suiToMist, aw as truncateAddress, ax as usdcToRaw, ay as validateAddress } from './types-CgZWnHhs.js';
1
+ export { B as BalanceResponse, C as CLOCK_ID, a as COIN_REGISTRY, b as ClassifyBalanceChange, c as ClassifyResult, d as CoinMeta, D as DEFAULT_NETWORK, e as DEFAULT_SAFEGUARD_CONFIG, f as DepositInfo, E as ETH_TYPE, g as ExtractedTransfer, G as GAS_RESERVE_MIN, I as IKA_TYPE, K as KNOWN_TARGETS, h as KeypairSigner, L as LABEL_PATTERNS, i as LOFI_TYPE, M as MANIFEST_TYPE, j as MIST_PER_SUI, N as NAVX_TYPE, O as OVERLAY_FEE_RATE, k as OverlayFeeConfig, P as PayOptions, l as PayResult, S as STABLE_ASSETS, m as SUI_DECIMALS, n as SUI_TYPE, o as SUPPORTED_ASSETS, p as SafeguardConfig, q as SafeguardError, r as SafeguardErrorDetails, s as SafeguardRule, t as SendResult, u as SimulationResult, v as StableAsset, w as SuiHolding, x as SuiRpcTxBlock, y as SupportedAsset, z as SwapRouteResult, T as T2000Error, A as T2000ErrorCode, F as T2000ErrorData, H as T2000_OVERLAY_FEE_WALLET, J as TOKEN_MAP, Q as TransactionLeg, R as TransactionRecord, U as TransactionSigner, V as TxDirection, W as TxMetadata, X as USDC_DECIMALS, Y as USDC_TYPE, Z as USDE_TYPE, _ as USDSUI_TYPE, $ as USDT_TYPE, a0 as WAL_TYPE, a1 as WBTC_TYPE, a2 as ZkLoginProof, a3 as ZkLoginSigner, a4 as buildSwapTx, a5 as classifyAction, a6 as classifyLabel, a7 as classifyTransaction, a8 as executeTx, a9 as extractAllUserLegs, aa as extractTransferDetails, ab as extractTxCommands, ac as extractTxSender, ad as fallbackLabel, ae as findSwapRoute, af as formatAssetAmount, ag as formatSui, ah as formatUsd, ai as getDecimals, aj as getDecimalsForCoinType, ak as mapMoveAbortCode, al as mapWalletError, am as mistToSui, an as parseSuiRpcTx, ao as payWithMpp, ap as rawToStable, aq as rawToUsdc, ar as refineLendingLabel, as as resolveSymbol, at as resolveTokenType, au as stableToRaw, av as suiToMist, aw as truncateAddress, ax as usdcToRaw, ay as validateAddress } from './types-C01EGu76.js';
2
2
  import '@mysten/sui/keypairs/ed25519';
3
3
  import '@mysten/sui/grpc';
4
4
  import '@mysten/sui/client';
package/dist/browser.js CHANGED
@@ -1,6 +1,7 @@
1
+ import { coinWithBalance } from '@mysten/sui/transactions';
2
+ import { fromBase64, normalizeSuiAddress, isValidSuiAddress } from '@mysten/sui/utils';
1
3
  import '@mysten/sui/grpc';
2
4
  import '@mysten/sui/graphql';
3
- import { normalizeSuiAddress, isValidSuiAddress } from '@mysten/sui/utils';
4
5
  import { AggregatorClient, Env } from '@cetusprotocol/aggregator-sdk';
5
6
  import 'bn.js';
6
7
 
@@ -104,6 +105,34 @@ var init_errors = __esm({
104
105
  });
105
106
 
106
107
  // src/token-registry.ts
108
+ var token_registry_exports = {};
109
+ __export(token_registry_exports, {
110
+ COIN_REGISTRY: () => COIN_REGISTRY,
111
+ ETH_TYPE: () => ETH_TYPE,
112
+ IKA_TYPE: () => IKA_TYPE,
113
+ LOFI_TYPE: () => LOFI_TYPE,
114
+ MANIFEST_TYPE: () => MANIFEST_TYPE,
115
+ NAVX_TYPE: () => NAVX_TYPE,
116
+ SUI_TYPE: () => SUI_TYPE,
117
+ TOKEN_MAP: () => TOKEN_MAP,
118
+ USDC_TYPE: () => USDC_TYPE,
119
+ USDE_TYPE: () => USDE_TYPE,
120
+ USDSUI_TYPE: () => USDSUI_TYPE,
121
+ USDT_TYPE: () => USDT_TYPE,
122
+ WAL_TYPE: () => WAL_TYPE,
123
+ WBTC_TYPE: () => WBTC_TYPE,
124
+ getCoinMeta: () => getCoinMeta,
125
+ getDecimalsForCoinType: () => getDecimalsForCoinType,
126
+ isInRegistry: () => isInRegistry,
127
+ resolveSymbol: () => resolveSymbol,
128
+ resolveTokenType: () => resolveTokenType
129
+ });
130
+ function getCoinMeta(coinType) {
131
+ return BY_TYPE.get(coinType);
132
+ }
133
+ function isInRegistry(coinType) {
134
+ return BY_TYPE.has(coinType);
135
+ }
107
136
  function getDecimalsForCoinType(coinType) {
108
137
  const direct = BY_TYPE.get(coinType);
109
138
  if (direct) return direct.decimals;
@@ -186,6 +215,136 @@ var init_token_registry = __esm({
186
215
  }
187
216
  });
188
217
 
218
+ // src/wallet/coinSelection.ts
219
+ var coinSelection_exports = {};
220
+ __export(coinSelection_exports, {
221
+ fetchAllCoins: () => fetchAllCoins,
222
+ selectAndSplitCoin: () => selectAndSplitCoin,
223
+ selectSuiCoin: () => selectSuiCoin
224
+ });
225
+ async function fetchAllCoins(client, owner, coinType) {
226
+ const [balance, ids] = await Promise.all([
227
+ client.core.getBalance({ owner, coinType }),
228
+ (async () => {
229
+ const out = [];
230
+ let cursor;
231
+ let hasNext = true;
232
+ while (hasNext) {
233
+ const page = await client.core.listCoins({ owner, coinType, cursor: cursor ?? void 0 });
234
+ for (const c of page.objects) out.push(c.objectId);
235
+ cursor = page.cursor;
236
+ hasNext = page.hasNextPage;
237
+ }
238
+ return out;
239
+ })()
240
+ ]);
241
+ return { ids, totalBalance: BigInt(balance.balance.balance) };
242
+ }
243
+ async function selectAndSplitCoin(tx, client, owner, coinType, amount, options = {}) {
244
+ if (options.sponsoredContext) {
245
+ return selectCoinObjectsOnly(
246
+ tx,
247
+ client,
248
+ owner,
249
+ coinType,
250
+ amount,
251
+ options.allowSwapAll ?? true,
252
+ options.mergeCache
253
+ );
254
+ }
255
+ const balanceResp = await client.core.getBalance({ owner, coinType });
256
+ const totalBalance = BigInt(balanceResp.balance.balance);
257
+ if (totalBalance === 0n) {
258
+ throw new T2000Error("INSUFFICIENT_BALANCE", `No balance found for ${coinType}`);
259
+ }
260
+ const allowSwapAll = options.allowSwapAll ?? true;
261
+ if (amount !== "all" && amount > totalBalance && !allowSwapAll) {
262
+ throw new T2000Error("INSUFFICIENT_BALANCE", `Insufficient balance for ${coinType}`, {
263
+ available: totalBalance.toString(),
264
+ required: amount.toString()
265
+ });
266
+ }
267
+ const requested = amount === "all" ? totalBalance : amount;
268
+ const swapAll = amount === "all" || requested >= totalBalance;
269
+ const effectiveAmount = swapAll ? totalBalance : requested;
270
+ const coin = coinWithBalance({ type: coinType, balance: effectiveAmount })(tx);
271
+ return { coin, effectiveAmount, swapAll };
272
+ }
273
+ async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowSwapAll, mergeCache) {
274
+ const cached = mergeCache?.get(coinType);
275
+ if (cached) {
276
+ const requested2 = amount === "all" ? cached.remaining : amount;
277
+ if (cached.remaining === 0n || requested2 > cached.remaining) {
278
+ throw new T2000Error(
279
+ "ADDRESS_BALANCE_UNSPONSORABLE",
280
+ `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.`,
281
+ { remaining: cached.remaining.toString(), requested: requested2.toString(), coinType }
282
+ );
283
+ }
284
+ const swapAll2 = amount === "all" || requested2 >= cached.remaining;
285
+ const effectiveAmount2 = swapAll2 ? cached.remaining : requested2;
286
+ const coin2 = swapAll2 ? cached.primary : tx.splitCoins(cached.primary, [effectiveAmount2])[0];
287
+ cached.remaining -= effectiveAmount2;
288
+ return { coin: coin2, effectiveAmount: effectiveAmount2, swapAll: swapAll2 };
289
+ }
290
+ const objects = [];
291
+ let coinObjectTotal = 0n;
292
+ let cursor;
293
+ let hasNext = true;
294
+ while (hasNext) {
295
+ const page = await client.core.listCoins({ owner, coinType, cursor: cursor ?? void 0 });
296
+ for (const c of page.objects) {
297
+ objects.push({ objectId: c.objectId, balance: BigInt(c.balance) });
298
+ coinObjectTotal += BigInt(c.balance);
299
+ }
300
+ cursor = page.cursor;
301
+ hasNext = page.hasNextPage;
302
+ }
303
+ const unsponsorable = () => new T2000Error(
304
+ "ADDRESS_BALANCE_UNSPONSORABLE",
305
+ `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.`,
306
+ { coinObjectTotal: coinObjectTotal.toString(), coinType }
307
+ );
308
+ if (coinObjectTotal === 0n) {
309
+ throw unsponsorable();
310
+ }
311
+ const requested = amount === "all" ? coinObjectTotal : amount;
312
+ if (requested > coinObjectTotal) {
313
+ if (allowSwapAll && amount === "all") ; else {
314
+ throw unsponsorable();
315
+ }
316
+ }
317
+ const swapAll = amount === "all" || requested >= coinObjectTotal;
318
+ const effectiveAmount = swapAll ? coinObjectTotal : requested;
319
+ const [first, ...rest] = objects;
320
+ const primary = tx.object(first.objectId);
321
+ if (rest.length > 0) {
322
+ tx.mergeCoins(
323
+ primary,
324
+ rest.map((o) => tx.object(o.objectId))
325
+ );
326
+ }
327
+ const coin = swapAll ? primary : tx.splitCoins(primary, [effectiveAmount])[0];
328
+ mergeCache?.set(coinType, {
329
+ primary,
330
+ remaining: coinObjectTotal - effectiveAmount
331
+ });
332
+ return { coin, effectiveAmount, swapAll };
333
+ }
334
+ async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext, mergeCache) {
335
+ if (sponsoredContext) {
336
+ const { SUI_TYPE: SUI_TYPE2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
337
+ return selectCoinObjectsOnly(tx, client, owner, SUI_TYPE2, amountMist, false, mergeCache);
338
+ }
339
+ const [coin] = tx.splitCoins(tx.gas, [amountMist]);
340
+ return { coin, effectiveAmount: amountMist, swapAll: false };
341
+ }
342
+ var init_coinSelection = __esm({
343
+ "src/wallet/coinSelection.ts"() {
344
+ init_errors();
345
+ }
346
+ });
347
+
189
348
  // src/wallet/keypairSigner.ts
190
349
  var KeypairSigner = class {
191
350
  constructor(keypair) {
@@ -245,12 +404,8 @@ var ZkLoginSigner = class {
245
404
  }
246
405
  };
247
406
 
248
- // src/mpp-cost.ts
249
- function parseChallengeAmount(challenge) {
250
- const raw = challenge?.request?.amount;
251
- const n = typeof raw === "string" ? Number(raw) : typeof raw === "number" ? raw : Number.NaN;
252
- return Number.isFinite(n) ? n : void 0;
253
- }
407
+ // src/wallet/pay.ts
408
+ init_errors();
254
409
 
255
410
  // src/wallet/executeTx.ts
256
411
  async function executeTx(client, signer, buildTx, options = {}) {
@@ -278,45 +433,122 @@ async function executeTx(client, signer, buildTx, options = {}) {
278
433
  // src/wallet/pay.ts
279
434
  async function payWithMpp(args) {
280
435
  const { signer, client, options } = args;
281
- const { Mppx } = await import('mppx/client');
282
- const { sui, USDC } = await import('@suimpp/mpp/client');
283
- const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
284
- const signerAddress = signer.getAddress();
285
- let paymentDigest;
286
- let gasCostSui = 0;
287
- let chargedAmount;
288
- const network = client.network === "testnet" ? "testnet" : "mainnet";
289
- const grpcBaseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
290
- const grpcClient = new SuiGrpcClient2({ baseUrl: grpcBaseUrl, network });
291
- const mppx = Mppx.create({
292
- polyfill: false,
293
- onChallenge: async (challenge) => {
294
- const parsed = parseChallengeAmount(challenge);
295
- if (parsed !== void 0) chargedAmount = parsed;
296
- return void 0;
297
- },
298
- methods: [sui({
299
- client,
300
- currency: USDC,
301
- signer: {
302
- toSuiAddress: () => signerAddress,
303
- signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
304
- },
305
- execute: async (tx) => {
306
- const result = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
307
- paymentDigest = result.digest;
308
- gasCostSui = result.gasCostSui;
309
- return { digest: result.digest };
310
- }
311
- })]
312
- });
313
436
  const method = (options.method ?? "GET").toUpperCase();
314
437
  const canHaveBody = method !== "GET" && method !== "HEAD";
315
- const response = await mppx.fetch(options.url, {
438
+ const reqInit = {
316
439
  method,
317
440
  headers: options.headers,
318
441
  body: canHaveBody ? options.body : void 0
442
+ };
443
+ const probe = await fetch(options.url, reqInit);
444
+ if (probe.status !== 402) {
445
+ return finalize(probe, { paid: false });
446
+ }
447
+ const requirements = await pickSuiExactRequirements(probe, client.network);
448
+ if (!requirements) {
449
+ throw new T2000Error(
450
+ "FACILITATOR_REJECTION",
451
+ `Endpoint returned 402 without an x402 'exact' / sui:${client.network} payment requirement. This SDK only speaks the x402 dialect.`
452
+ );
453
+ }
454
+ return payViaX402({ signer, client, options, reqInit, requirements });
455
+ }
456
+ async function pickSuiExactRequirements(response, network) {
457
+ try {
458
+ const body = await response.clone().json();
459
+ const want = `sui:${network === "testnet" ? "testnet" : "mainnet"}`;
460
+ return body.accepts?.find((a) => a.scheme === "exact" && a.network === want);
461
+ } catch {
462
+ return void 0;
463
+ }
464
+ }
465
+ async function payViaX402(args) {
466
+ const { signer, client, options, reqInit, requirements } = args;
467
+ const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import('@suimpp/mpp/x402');
468
+ const amountRaw = BigInt(requirements.maxAmountRequired);
469
+ const migrationGasSui = await ensureAddressBalanceCovers({
470
+ signer,
471
+ client,
472
+ asset: requirements.asset,
473
+ amountRaw
474
+ });
475
+ const signerAdapter = {
476
+ toSuiAddress: () => signer.getAddress(),
477
+ signTransaction: (bytes) => signer.signTransaction(bytes)
478
+ };
479
+ const { header } = await buildX402SignedPayment({ requirements, signer: signerAdapter });
480
+ const res = await fetch(options.url, {
481
+ ...reqInit,
482
+ headers: { ...options.headers ?? {}, [X402_PAYMENT_HEADER]: header }
319
483
  });
484
+ const settleHeader = res.headers.get(X402_PAYMENT_RESPONSE_HEADER);
485
+ const paid = !!settleHeader;
486
+ let digest;
487
+ if (settleHeader) {
488
+ try {
489
+ digest = JSON.parse(new TextDecoder().decode(fromBase64(settleHeader))).transaction;
490
+ } catch {
491
+ digest = void 0;
492
+ }
493
+ }
494
+ const result = await finalize(res, { paid });
495
+ if (!paid) return { ...result, dialect: "x402" };
496
+ return {
497
+ ...result,
498
+ dialect: "x402",
499
+ cost: atomicToHuman(amountRaw, await assetDecimals(requirements.asset)),
500
+ gasCostSui: migrationGasSui,
501
+ receipt: digest ? { reference: digest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : result.receipt
502
+ };
503
+ }
504
+ async function ensureAddressBalanceCovers(args) {
505
+ const { signer, client, asset, amountRaw } = args;
506
+ const owner = signer.getAddress();
507
+ const balanceResp = await client.core.getBalance({ owner, coinType: asset });
508
+ const total = BigInt(balanceResp.balance.balance);
509
+ if (total < amountRaw) {
510
+ throw new T2000Error("INSUFFICIENT_BALANCE", `Insufficient ${asset} to pay`, {
511
+ available: total.toString(),
512
+ required: amountRaw.toString()
513
+ });
514
+ }
515
+ let coinSum = 0n;
516
+ let cursor;
517
+ let hasNext = true;
518
+ while (hasNext) {
519
+ const page = await client.core.listCoins({ owner, coinType: asset, cursor: cursor ?? void 0 });
520
+ for (const c of page.objects) coinSum += BigInt(c.balance);
521
+ cursor = page.cursor;
522
+ hasNext = page.hasNextPage;
523
+ }
524
+ const addressBalance = total - coinSum;
525
+ if (addressBalance >= amountRaw) return 0;
526
+ const shortfall = amountRaw - addressBalance;
527
+ const { Transaction: Transaction2 } = await import('@mysten/sui/transactions');
528
+ const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
529
+ const grpcClient = await makeGrpcBuildClient(client);
530
+ const migration = await executeTx(
531
+ client,
532
+ signer,
533
+ async () => {
534
+ const tx = new Transaction2();
535
+ const { coin } = await selectAndSplitCoin2(tx, client, owner, asset, shortfall, {
536
+ sponsoredContext: true,
537
+ // coin-objects-only — never the address balance
538
+ allowSwapAll: false
539
+ });
540
+ tx.moveCall({
541
+ target: "0x2::coin::send_funds",
542
+ typeArguments: [asset],
543
+ arguments: [coin, tx.pure.address(owner)]
544
+ });
545
+ return tx;
546
+ },
547
+ { buildClient: grpcClient }
548
+ );
549
+ return migration.gasCostSui;
550
+ }
551
+ async function finalize(response, opts) {
320
552
  const contentType = response.headers.get("content-type") ?? "";
321
553
  let body;
322
554
  try {
@@ -324,15 +556,25 @@ async function payWithMpp(args) {
324
556
  } catch {
325
557
  body = null;
326
558
  }
327
- const paid = !!paymentDigest;
328
- return {
329
- status: response.status,
330
- body,
331
- paid,
332
- cost: paid ? chargedAmount ?? options.maxPrice ?? void 0 : void 0,
333
- gasCostSui: paid ? gasCostSui : void 0,
334
- receipt: paymentDigest ? { reference: paymentDigest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : void 0
335
- };
559
+ return { status: response.status, body, paid: opts.paid };
560
+ }
561
+ async function makeGrpcBuildClient(client) {
562
+ const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
563
+ const network = client.network === "testnet" ? "testnet" : "mainnet";
564
+ const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
565
+ return new SuiGrpcClient2({ baseUrl, network });
566
+ }
567
+ function atomicToHuman(raw, decimals) {
568
+ return Number(raw) / 10 ** decimals;
569
+ }
570
+ async function assetDecimals(coinType) {
571
+ try {
572
+ const { getDecimalsForCoinType: getDecimalsForCoinType2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
573
+ const d = getDecimalsForCoinType2(coinType);
574
+ return typeof d === "number" ? d : 6;
575
+ } catch {
576
+ return 6;
577
+ }
336
578
  }
337
579
 
338
580
  // src/browser.ts
@@ -674,7 +916,7 @@ function toBase64(bytes) {
674
916
  for (const byte of bytes) binary += String.fromCharCode(byte);
675
917
  return btoa(binary);
676
918
  }
677
- function fromBase64(b64) {
919
+ function fromBase642(b64) {
678
920
  const binary = atob(b64);
679
921
  const bytes = new Uint8Array(binary.length);
680
922
  for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
@@ -794,6 +1036,6 @@ var DEFAULT_SAFEGUARD_CONFIG = {
794
1036
  // src/browser.ts
795
1037
  init_token_registry();
796
1038
 
797
- export { CLOCK_ID, COIN_REGISTRY, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, OVERLAY_FEE_RATE, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardError, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, WAL_TYPE, WBTC_TYPE, ZkLoginSigner, buildSwapTx, classifyAction, classifyLabel, classifyTransaction, executeTx, extractAllUserLegs, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, findSwapRoute, formatAssetAmount, formatSui, formatUsd, fromBase64, getDecimals, getDecimalsForCoinType, mapMoveAbortCode, mapWalletError, mistToSui, parseSuiRpcTx, payWithMpp, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, stableToRaw, suiToMist, toBase64, truncateAddress, usdcToRaw, validateAddress };
1039
+ export { CLOCK_ID, COIN_REGISTRY, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, OVERLAY_FEE_RATE, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardError, T2000Error, T2000_OVERLAY_FEE_WALLET, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, WAL_TYPE, WBTC_TYPE, ZkLoginSigner, buildSwapTx, classifyAction, classifyLabel, classifyTransaction, executeTx, extractAllUserLegs, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, findSwapRoute, formatAssetAmount, formatSui, formatUsd, fromBase642 as fromBase64, getDecimals, getDecimalsForCoinType, mapMoveAbortCode, mapWalletError, mistToSui, parseSuiRpcTx, payWithMpp, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, stableToRaw, suiToMist, toBase64, truncateAddress, usdcToRaw, validateAddress };
798
1040
  //# sourceMappingURL=browser.js.map
799
1041
  //# sourceMappingURL=browser.js.map