@t2000/sdk 9.1.0 → 9.3.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 CHANGED
@@ -447,6 +447,13 @@ var ZkLoginSigner = class {
447
447
  // src/wallet/pay.ts
448
448
  init_errors();
449
449
 
450
+ // src/mpp-cost.ts
451
+ function parseChallengeAmount(challenge) {
452
+ const raw = challenge?.request?.amount;
453
+ const n = typeof raw === "string" ? Number(raw) : typeof raw === "number" ? raw : Number.NaN;
454
+ return Number.isFinite(n) ? n : void 0;
455
+ }
456
+
450
457
  // src/wallet/executeTx.ts
451
458
  async function executeTx(client, signer, buildTx, options = {}) {
452
459
  const tx = await buildTx();
@@ -459,7 +466,11 @@ async function executeTx(client, signer, buildTx, options = {}) {
459
466
  include: { effects: true }
460
467
  });
461
468
  const txn = result.$kind === "Transaction" ? result.Transaction : result.FailedTransaction;
462
- await client.core.waitForTransaction({ digest: txn.digest });
469
+ try {
470
+ await client.core.waitForTransaction({ digest: txn.digest });
471
+ } catch (err) {
472
+ if (!txn.effects) throw err;
473
+ }
463
474
  const effects = txn.effects ?? void 0;
464
475
  const gasUsed = effects?.gasUsed;
465
476
  let gasCostSui = 0;
@@ -535,13 +546,35 @@ async function payWithMpp(args) {
535
546
  return finalize(probe, { paid: false });
536
547
  }
537
548
  const requirements = await pickSuiExactRequirements(probe, client.network);
538
- if (!requirements) {
539
- throw new exports.T2000Error(
540
- "FACILITATOR_REJECTION",
541
- `Endpoint returned 402 without an x402 'exact' / sui:${client.network} payment requirement. This SDK only speaks the x402 dialect.`
542
- );
549
+ if (requirements) {
550
+ return payViaX402({ signer, client, options, reqInit, requirements });
551
+ }
552
+ const headerChallenge = await parseMppSuiChallenge(probe);
553
+ if (headerChallenge) {
554
+ return payViaMppHeader({ signer, client, options });
555
+ }
556
+ throw new exports.T2000Error(
557
+ "FACILITATOR_REJECTION",
558
+ `Endpoint returned 402 without an x402 'exact' / sui:${client.network} requirement in the body or an MPP 'sui' challenge in WWW-Authenticate. Nothing this SDK can pay.`
559
+ );
560
+ }
561
+ async function parseMppSuiChallenge(response) {
562
+ try {
563
+ const { Challenge } = await import('mppx');
564
+ const challenges = Challenge.fromResponseList(response);
565
+ const suiChallenge = challenges.find((c) => c.method === "sui" && c.intent === "charge");
566
+ if (!suiChallenge) return void 0;
567
+ const req = suiChallenge.request;
568
+ if (typeof req?.amount !== "string" || typeof req?.recipient !== "string") return void 0;
569
+ return {
570
+ amount: req.amount,
571
+ currency: typeof req.currency === "string" ? req.currency : "",
572
+ recipient: req.recipient,
573
+ description: suiChallenge.description
574
+ };
575
+ } catch {
576
+ return void 0;
543
577
  }
544
- return payViaX402({ signer, client, options, reqInit, requirements });
545
578
  }
546
579
  async function pickSuiExactRequirements(response, network) {
547
580
  try {
@@ -556,6 +589,7 @@ async function payViaX402(args) {
556
589
  const { signer, client, options, reqInit, requirements } = args;
557
590
  const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import('@suimpp/mpp/x402');
558
591
  const amountRaw = BigInt(requirements.maxAmountRequired);
592
+ assertWithinMaxPrice(atomicToHuman(amountRaw, await assetDecimals(requirements.asset)), options.maxPrice);
559
593
  const migrationGasSui = await ensureAddressBalanceCovers({
560
594
  signer,
561
595
  client,
@@ -591,6 +625,70 @@ async function payViaX402(args) {
591
625
  receipt: digest ? { reference: digest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : result.receipt
592
626
  };
593
627
  }
628
+ async function payViaMppHeader(args) {
629
+ const { signer, client, options } = args;
630
+ const { Mppx } = await import('mppx/client');
631
+ const { sui, USDC, USDC_TESTNET } = await import('@suimpp/mpp/client');
632
+ const signerAddress = signer.getAddress();
633
+ const network = client.network === "testnet" ? "testnet" : "mainnet";
634
+ const grpcClient = await makeGrpcBuildClient(client);
635
+ let paymentDigest;
636
+ let gasCostSui = 0;
637
+ let chargedAmount;
638
+ const mppx = Mppx.create({
639
+ polyfill: false,
640
+ onChallenge: async (challenge) => {
641
+ const parsed = parseChallengeAmount(challenge);
642
+ if (parsed !== void 0) {
643
+ chargedAmount = parsed;
644
+ assertWithinMaxPrice(parsed, options.maxPrice);
645
+ }
646
+ return void 0;
647
+ },
648
+ methods: [
649
+ sui({
650
+ client,
651
+ currency: network === "testnet" ? USDC_TESTNET : USDC,
652
+ signer: {
653
+ toSuiAddress: () => signerAddress,
654
+ signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
655
+ },
656
+ execute: async (tx) => {
657
+ const result2 = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
658
+ paymentDigest = result2.digest;
659
+ gasCostSui = result2.gasCostSui;
660
+ return { digest: result2.digest };
661
+ }
662
+ })
663
+ ]
664
+ });
665
+ const method = (options.method ?? "GET").toUpperCase();
666
+ const canHaveBody = method !== "GET" && method !== "HEAD";
667
+ const response = await mppx.fetch(options.url, {
668
+ method,
669
+ headers: options.headers,
670
+ body: canHaveBody ? options.body : void 0
671
+ });
672
+ const paid = !!paymentDigest;
673
+ const result = await finalize(response, { paid });
674
+ if (!paid) return { ...result, dialect: "legacy" };
675
+ return {
676
+ ...result,
677
+ dialect: "legacy",
678
+ cost: chargedAmount ?? options.maxPrice ?? void 0,
679
+ gasCostSui,
680
+ receipt: paymentDigest ? { reference: paymentDigest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : void 0
681
+ };
682
+ }
683
+ function assertWithinMaxPrice(price, maxPrice) {
684
+ if (maxPrice !== void 0 && price > maxPrice) {
685
+ throw new exports.T2000Error(
686
+ "PRICE_EXCEEDS_LIMIT",
687
+ `Service price $${price} exceeds maxPrice ceiling $${maxPrice}`,
688
+ { price, maxPrice }
689
+ );
690
+ }
691
+ }
594
692
  async function ensureAddressBalanceCovers(args) {
595
693
  const { signer, client, asset, amountRaw } = args;
596
694
  const owner = signer.getAddress();
@@ -1211,6 +1309,7 @@ exports.getDecimalsForCoinType = getDecimalsForCoinType;
1211
1309
  exports.mapMoveAbortCode = mapMoveAbortCode;
1212
1310
  exports.mapWalletError = mapWalletError;
1213
1311
  exports.mistToSui = mistToSui;
1312
+ exports.parseMppSuiChallenge = parseMppSuiChallenge;
1214
1313
  exports.parseSuiRpcTx = parseSuiRpcTx;
1215
1314
  exports.payWithMpp = payWithMpp;
1216
1315
  exports.preflightFail = preflightFail;