@t2000/sdk 9.2.0 → 9.3.1
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 +126 -8
- 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 +126 -9
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +128 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +128 -9
- package/dist/index.js.map +1 -1
- package/dist/{send-CUUOLK_H.d.cts → send-DEK6aOGe.d.cts} +14 -1
- package/dist/{send-CUUOLK_H.d.ts → send-DEK6aOGe.d.ts} +14 -1
- package/package.json +3 -2
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
|
-
|
|
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() === "") {
|
|
@@ -1115,11 +1128,18 @@ function preflightPay(input) {
|
|
|
1115
1128
|
return exports.PREFLIGHT_OK;
|
|
1116
1129
|
}
|
|
1117
1130
|
async function payWithMpp(args) {
|
|
1118
|
-
const { signer, client
|
|
1131
|
+
const { signer, client } = args;
|
|
1132
|
+
let options = args.options;
|
|
1119
1133
|
const pf = preflightPay({ url: options.url, maxPrice: options.maxPrice });
|
|
1120
1134
|
if (!pf.valid) throw new exports.T2000Error(pf.code, pf.error);
|
|
1121
1135
|
const method = (options.method ?? "GET").toUpperCase();
|
|
1122
1136
|
const canHaveBody = method !== "GET" && method !== "HEAD";
|
|
1137
|
+
if (canHaveBody && typeof options.body === "string" && isJsonText(options.body) && !hasContentType(options.headers)) {
|
|
1138
|
+
options = {
|
|
1139
|
+
...options,
|
|
1140
|
+
headers: { ...options.headers ?? {}, "content-type": "application/json" }
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1123
1143
|
const reqInit = {
|
|
1124
1144
|
method,
|
|
1125
1145
|
headers: options.headers,
|
|
@@ -1130,13 +1150,35 @@ async function payWithMpp(args) {
|
|
|
1130
1150
|
return finalize(probe, { paid: false });
|
|
1131
1151
|
}
|
|
1132
1152
|
const requirements = await pickSuiExactRequirements(probe, client.network);
|
|
1133
|
-
if (
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1153
|
+
if (requirements) {
|
|
1154
|
+
return payViaX402({ signer, client, options, reqInit, requirements });
|
|
1155
|
+
}
|
|
1156
|
+
const headerChallenge = await parseMppSuiChallenge(probe);
|
|
1157
|
+
if (headerChallenge) {
|
|
1158
|
+
return payViaMppHeader({ signer, client, options });
|
|
1159
|
+
}
|
|
1160
|
+
throw new exports.T2000Error(
|
|
1161
|
+
"FACILITATOR_REJECTION",
|
|
1162
|
+
`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.`
|
|
1163
|
+
);
|
|
1164
|
+
}
|
|
1165
|
+
async function parseMppSuiChallenge(response) {
|
|
1166
|
+
try {
|
|
1167
|
+
const { Challenge } = await import('mppx');
|
|
1168
|
+
const challenges = Challenge.fromResponseList(response);
|
|
1169
|
+
const suiChallenge = challenges.find((c) => c.method === "sui" && c.intent === "charge");
|
|
1170
|
+
if (!suiChallenge) return void 0;
|
|
1171
|
+
const req = suiChallenge.request;
|
|
1172
|
+
if (typeof req?.amount !== "string" || typeof req?.recipient !== "string") return void 0;
|
|
1173
|
+
return {
|
|
1174
|
+
amount: req.amount,
|
|
1175
|
+
currency: typeof req.currency === "string" ? req.currency : "",
|
|
1176
|
+
recipient: req.recipient,
|
|
1177
|
+
description: suiChallenge.description
|
|
1178
|
+
};
|
|
1179
|
+
} catch {
|
|
1180
|
+
return void 0;
|
|
1138
1181
|
}
|
|
1139
|
-
return payViaX402({ signer, client, options, reqInit, requirements });
|
|
1140
1182
|
}
|
|
1141
1183
|
async function pickSuiExactRequirements(response, network) {
|
|
1142
1184
|
try {
|
|
@@ -1151,6 +1193,7 @@ async function payViaX402(args) {
|
|
|
1151
1193
|
const { signer, client, options, reqInit, requirements } = args;
|
|
1152
1194
|
const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import('@suimpp/mpp/x402');
|
|
1153
1195
|
const amountRaw = BigInt(requirements.maxAmountRequired);
|
|
1196
|
+
assertWithinMaxPrice(atomicToHuman(amountRaw, await assetDecimals(requirements.asset)), options.maxPrice);
|
|
1154
1197
|
const migrationGasSui = await ensureAddressBalanceCovers({
|
|
1155
1198
|
signer,
|
|
1156
1199
|
client,
|
|
@@ -1186,6 +1229,70 @@ async function payViaX402(args) {
|
|
|
1186
1229
|
receipt: digest ? { reference: digest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : result.receipt
|
|
1187
1230
|
};
|
|
1188
1231
|
}
|
|
1232
|
+
async function payViaMppHeader(args) {
|
|
1233
|
+
const { signer, client, options } = args;
|
|
1234
|
+
const { Mppx } = await import('mppx/client');
|
|
1235
|
+
const { sui, USDC, USDC_TESTNET } = await import('@suimpp/mpp/client');
|
|
1236
|
+
const signerAddress = signer.getAddress();
|
|
1237
|
+
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
1238
|
+
const grpcClient = await makeGrpcBuildClient(client);
|
|
1239
|
+
let paymentDigest;
|
|
1240
|
+
let gasCostSui = 0;
|
|
1241
|
+
let chargedAmount;
|
|
1242
|
+
const mppx = Mppx.create({
|
|
1243
|
+
polyfill: false,
|
|
1244
|
+
onChallenge: async (challenge) => {
|
|
1245
|
+
const parsed = parseChallengeAmount(challenge);
|
|
1246
|
+
if (parsed !== void 0) {
|
|
1247
|
+
chargedAmount = parsed;
|
|
1248
|
+
assertWithinMaxPrice(parsed, options.maxPrice);
|
|
1249
|
+
}
|
|
1250
|
+
return void 0;
|
|
1251
|
+
},
|
|
1252
|
+
methods: [
|
|
1253
|
+
sui({
|
|
1254
|
+
client,
|
|
1255
|
+
currency: network === "testnet" ? USDC_TESTNET : USDC,
|
|
1256
|
+
signer: {
|
|
1257
|
+
toSuiAddress: () => signerAddress,
|
|
1258
|
+
signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
|
|
1259
|
+
},
|
|
1260
|
+
execute: async (tx) => {
|
|
1261
|
+
const result2 = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
|
|
1262
|
+
paymentDigest = result2.digest;
|
|
1263
|
+
gasCostSui = result2.gasCostSui;
|
|
1264
|
+
return { digest: result2.digest };
|
|
1265
|
+
}
|
|
1266
|
+
})
|
|
1267
|
+
]
|
|
1268
|
+
});
|
|
1269
|
+
const method = (options.method ?? "GET").toUpperCase();
|
|
1270
|
+
const canHaveBody = method !== "GET" && method !== "HEAD";
|
|
1271
|
+
const response = await mppx.fetch(options.url, {
|
|
1272
|
+
method,
|
|
1273
|
+
headers: options.headers,
|
|
1274
|
+
body: canHaveBody ? options.body : void 0
|
|
1275
|
+
});
|
|
1276
|
+
const paid = !!paymentDigest;
|
|
1277
|
+
const result = await finalize(response, { paid });
|
|
1278
|
+
if (!paid) return { ...result, dialect: "legacy" };
|
|
1279
|
+
return {
|
|
1280
|
+
...result,
|
|
1281
|
+
dialect: "legacy",
|
|
1282
|
+
cost: chargedAmount ?? options.maxPrice ?? void 0,
|
|
1283
|
+
gasCostSui,
|
|
1284
|
+
receipt: paymentDigest ? { reference: paymentDigest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : void 0
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
function assertWithinMaxPrice(price, maxPrice) {
|
|
1288
|
+
if (maxPrice !== void 0 && price > maxPrice) {
|
|
1289
|
+
throw new exports.T2000Error(
|
|
1290
|
+
"PRICE_EXCEEDS_LIMIT",
|
|
1291
|
+
`Service price $${price} exceeds maxPrice ceiling $${maxPrice}`,
|
|
1292
|
+
{ price, maxPrice }
|
|
1293
|
+
);
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1189
1296
|
async function ensureAddressBalanceCovers(args) {
|
|
1190
1297
|
const { signer, client, asset, amountRaw } = args;
|
|
1191
1298
|
const owner = signer.getAddress();
|
|
@@ -1219,6 +1326,18 @@ async function ensureAddressBalanceCovers(args) {
|
|
|
1219
1326
|
const migration = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
|
|
1220
1327
|
return migration.gasCostSui;
|
|
1221
1328
|
}
|
|
1329
|
+
function isJsonText(text) {
|
|
1330
|
+
try {
|
|
1331
|
+
JSON.parse(text);
|
|
1332
|
+
return true;
|
|
1333
|
+
} catch {
|
|
1334
|
+
return false;
|
|
1335
|
+
}
|
|
1336
|
+
}
|
|
1337
|
+
function hasContentType(headers) {
|
|
1338
|
+
if (!headers) return false;
|
|
1339
|
+
return Object.keys(headers).some((k) => k.toLowerCase() === "content-type");
|
|
1340
|
+
}
|
|
1222
1341
|
async function finalize(response, opts) {
|
|
1223
1342
|
const contentType = response.headers.get("content-type") ?? "";
|
|
1224
1343
|
let body2;
|
|
@@ -3503,6 +3622,7 @@ exports.mistToSui = mistToSui;
|
|
|
3503
3622
|
exports.normalizeAddressInput = normalizeAddressInput;
|
|
3504
3623
|
exports.normalizeAsset = normalizeAsset;
|
|
3505
3624
|
exports.normalizeCoinType = normalizeCoinType;
|
|
3625
|
+
exports.parseMppSuiChallenge = parseMppSuiChallenge;
|
|
3506
3626
|
exports.parseSuiRpcTx = parseSuiRpcTx;
|
|
3507
3627
|
exports.payWithMpp = payWithMpp;
|
|
3508
3628
|
exports.preflightFail = preflightFail;
|