@t2000/sdk 9.2.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/index.cjs CHANGED
@@ -1078,7 +1078,11 @@ async function executeTx(client, signer, buildTx, options = {}) {
1078
1078
  include: { effects: true }
1079
1079
  });
1080
1080
  const txn = result.$kind === "Transaction" ? result.Transaction : result.FailedTransaction;
1081
- await client.core.waitForTransaction({ digest: txn.digest });
1081
+ try {
1082
+ await client.core.waitForTransaction({ digest: txn.digest });
1083
+ } catch (err) {
1084
+ if (!txn.effects) throw err;
1085
+ }
1082
1086
  const effects = txn.effects ?? void 0;
1083
1087
  const gasUsed = effects?.gasUsed;
1084
1088
  let gasCostSui = 0;
@@ -1091,6 +1095,15 @@ async function executeTx(client, signer, buildTx, options = {}) {
1091
1095
 
1092
1096
  // src/wallet/pay.ts
1093
1097
  init_errors();
1098
+
1099
+ // src/mpp-cost.ts
1100
+ function parseChallengeAmount(challenge) {
1101
+ const raw = challenge?.request?.amount;
1102
+ const n = typeof raw === "string" ? Number(raw) : typeof raw === "number" ? raw : Number.NaN;
1103
+ return Number.isFinite(n) ? n : void 0;
1104
+ }
1105
+
1106
+ // src/wallet/pay.ts
1094
1107
  init_preflight();
1095
1108
  function preflightPay(input) {
1096
1109
  if (typeof input.url !== "string" || input.url.trim() === "") {
@@ -1130,13 +1143,35 @@ async function payWithMpp(args) {
1130
1143
  return finalize(probe, { paid: false });
1131
1144
  }
1132
1145
  const requirements = await pickSuiExactRequirements(probe, client.network);
1133
- if (!requirements) {
1134
- throw new exports.T2000Error(
1135
- "FACILITATOR_REJECTION",
1136
- `Endpoint returned 402 without an x402 'exact' / sui:${client.network} payment requirement. This SDK only speaks the x402 dialect.`
1137
- );
1146
+ if (requirements) {
1147
+ return payViaX402({ signer, client, options, reqInit, requirements });
1148
+ }
1149
+ const headerChallenge = await parseMppSuiChallenge(probe);
1150
+ if (headerChallenge) {
1151
+ return payViaMppHeader({ signer, client, options });
1152
+ }
1153
+ throw new exports.T2000Error(
1154
+ "FACILITATOR_REJECTION",
1155
+ `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.`
1156
+ );
1157
+ }
1158
+ async function parseMppSuiChallenge(response) {
1159
+ try {
1160
+ const { Challenge } = await import('mppx');
1161
+ const challenges = Challenge.fromResponseList(response);
1162
+ const suiChallenge = challenges.find((c) => c.method === "sui" && c.intent === "charge");
1163
+ if (!suiChallenge) return void 0;
1164
+ const req = suiChallenge.request;
1165
+ if (typeof req?.amount !== "string" || typeof req?.recipient !== "string") return void 0;
1166
+ return {
1167
+ amount: req.amount,
1168
+ currency: typeof req.currency === "string" ? req.currency : "",
1169
+ recipient: req.recipient,
1170
+ description: suiChallenge.description
1171
+ };
1172
+ } catch {
1173
+ return void 0;
1138
1174
  }
1139
- return payViaX402({ signer, client, options, reqInit, requirements });
1140
1175
  }
1141
1176
  async function pickSuiExactRequirements(response, network) {
1142
1177
  try {
@@ -1151,6 +1186,7 @@ async function payViaX402(args) {
1151
1186
  const { signer, client, options, reqInit, requirements } = args;
1152
1187
  const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import('@suimpp/mpp/x402');
1153
1188
  const amountRaw = BigInt(requirements.maxAmountRequired);
1189
+ assertWithinMaxPrice(atomicToHuman(amountRaw, await assetDecimals(requirements.asset)), options.maxPrice);
1154
1190
  const migrationGasSui = await ensureAddressBalanceCovers({
1155
1191
  signer,
1156
1192
  client,
@@ -1186,6 +1222,70 @@ async function payViaX402(args) {
1186
1222
  receipt: digest ? { reference: digest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : result.receipt
1187
1223
  };
1188
1224
  }
1225
+ async function payViaMppHeader(args) {
1226
+ const { signer, client, options } = args;
1227
+ const { Mppx } = await import('mppx/client');
1228
+ const { sui, USDC, USDC_TESTNET } = await import('@suimpp/mpp/client');
1229
+ const signerAddress = signer.getAddress();
1230
+ const network = client.network === "testnet" ? "testnet" : "mainnet";
1231
+ const grpcClient = await makeGrpcBuildClient(client);
1232
+ let paymentDigest;
1233
+ let gasCostSui = 0;
1234
+ let chargedAmount;
1235
+ const mppx = Mppx.create({
1236
+ polyfill: false,
1237
+ onChallenge: async (challenge) => {
1238
+ const parsed = parseChallengeAmount(challenge);
1239
+ if (parsed !== void 0) {
1240
+ chargedAmount = parsed;
1241
+ assertWithinMaxPrice(parsed, options.maxPrice);
1242
+ }
1243
+ return void 0;
1244
+ },
1245
+ methods: [
1246
+ sui({
1247
+ client,
1248
+ currency: network === "testnet" ? USDC_TESTNET : USDC,
1249
+ signer: {
1250
+ toSuiAddress: () => signerAddress,
1251
+ signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
1252
+ },
1253
+ execute: async (tx) => {
1254
+ const result2 = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
1255
+ paymentDigest = result2.digest;
1256
+ gasCostSui = result2.gasCostSui;
1257
+ return { digest: result2.digest };
1258
+ }
1259
+ })
1260
+ ]
1261
+ });
1262
+ const method = (options.method ?? "GET").toUpperCase();
1263
+ const canHaveBody = method !== "GET" && method !== "HEAD";
1264
+ const response = await mppx.fetch(options.url, {
1265
+ method,
1266
+ headers: options.headers,
1267
+ body: canHaveBody ? options.body : void 0
1268
+ });
1269
+ const paid = !!paymentDigest;
1270
+ const result = await finalize(response, { paid });
1271
+ if (!paid) return { ...result, dialect: "legacy" };
1272
+ return {
1273
+ ...result,
1274
+ dialect: "legacy",
1275
+ cost: chargedAmount ?? options.maxPrice ?? void 0,
1276
+ gasCostSui,
1277
+ receipt: paymentDigest ? { reference: paymentDigest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : void 0
1278
+ };
1279
+ }
1280
+ function assertWithinMaxPrice(price, maxPrice) {
1281
+ if (maxPrice !== void 0 && price > maxPrice) {
1282
+ throw new exports.T2000Error(
1283
+ "PRICE_EXCEEDS_LIMIT",
1284
+ `Service price $${price} exceeds maxPrice ceiling $${maxPrice}`,
1285
+ { price, maxPrice }
1286
+ );
1287
+ }
1288
+ }
1189
1289
  async function ensureAddressBalanceCovers(args) {
1190
1290
  const { signer, client, asset, amountRaw } = args;
1191
1291
  const owner = signer.getAddress();
@@ -3503,6 +3603,7 @@ exports.mistToSui = mistToSui;
3503
3603
  exports.normalizeAddressInput = normalizeAddressInput;
3504
3604
  exports.normalizeAsset = normalizeAsset;
3505
3605
  exports.normalizeCoinType = normalizeCoinType;
3606
+ exports.parseMppSuiChallenge = parseMppSuiChallenge;
3506
3607
  exports.parseSuiRpcTx = parseSuiRpcTx;
3507
3608
  exports.payWithMpp = payWithMpp;
3508
3609
  exports.preflightFail = preflightFail;