@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.
- package/dist/browser.cjs +293 -51
- 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 -51
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +132 -51
- 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 +133 -52
- package/dist/index.js.map +1 -1
- package/dist/{types-CgZWnHhs.d.cts → types-C01EGu76.d.cts} +8 -0
- package/dist/{types-CgZWnHhs.d.ts → types-C01EGu76.d.ts} +8 -0
- package/package.json +3 -4
package/dist/index.cjs
CHANGED
|
@@ -576,8 +576,8 @@ async function addSwapToTx(tx, client, address, input) {
|
|
|
576
576
|
inputCoin = result.coin;
|
|
577
577
|
effectiveRaw = result.effectiveAmount;
|
|
578
578
|
} else {
|
|
579
|
-
const { selectAndSplitCoin:
|
|
580
|
-
const result = await
|
|
579
|
+
const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
|
|
580
|
+
const result = await selectAndSplitCoin2(tx, client, address, fromType, requestedRaw, {
|
|
581
581
|
sponsoredContext: input.sponsoredContext ?? false,
|
|
582
582
|
mergeCache: input.coinMergeCache
|
|
583
583
|
});
|
|
@@ -997,55 +997,126 @@ async function executeTx(client, signer, buildTx, options = {}) {
|
|
|
997
997
|
return { digest: txn.digest, gasCostSui, effects };
|
|
998
998
|
}
|
|
999
999
|
|
|
1000
|
-
// src/mpp-cost.ts
|
|
1001
|
-
function parseChallengeAmount(challenge) {
|
|
1002
|
-
const raw = challenge?.request?.amount;
|
|
1003
|
-
const n = typeof raw === "string" ? Number(raw) : typeof raw === "number" ? raw : Number.NaN;
|
|
1004
|
-
return Number.isFinite(n) ? n : void 0;
|
|
1005
|
-
}
|
|
1006
|
-
|
|
1007
1000
|
// src/wallet/pay.ts
|
|
1001
|
+
init_errors();
|
|
1008
1002
|
async function payWithMpp(args) {
|
|
1009
1003
|
const { signer, client, options } = args;
|
|
1010
|
-
const { Mppx } = await import('mppx/client');
|
|
1011
|
-
const { sui, USDC } = await import('@suimpp/mpp/client');
|
|
1012
|
-
const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
|
|
1013
|
-
const signerAddress = signer.getAddress();
|
|
1014
|
-
let paymentDigest;
|
|
1015
|
-
let gasCostSui = 0;
|
|
1016
|
-
let chargedAmount;
|
|
1017
|
-
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
1018
|
-
const grpcBaseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
1019
|
-
const grpcClient = new SuiGrpcClient2({ baseUrl: grpcBaseUrl, network });
|
|
1020
|
-
const mppx = Mppx.create({
|
|
1021
|
-
polyfill: false,
|
|
1022
|
-
onChallenge: async (challenge) => {
|
|
1023
|
-
const parsed = parseChallengeAmount(challenge);
|
|
1024
|
-
if (parsed !== void 0) chargedAmount = parsed;
|
|
1025
|
-
return void 0;
|
|
1026
|
-
},
|
|
1027
|
-
methods: [sui({
|
|
1028
|
-
client,
|
|
1029
|
-
currency: USDC,
|
|
1030
|
-
signer: {
|
|
1031
|
-
toSuiAddress: () => signerAddress,
|
|
1032
|
-
signPersonalMessage: (bytes) => signer.signPersonalMessage(bytes)
|
|
1033
|
-
},
|
|
1034
|
-
execute: async (tx) => {
|
|
1035
|
-
const result = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
|
|
1036
|
-
paymentDigest = result.digest;
|
|
1037
|
-
gasCostSui = result.gasCostSui;
|
|
1038
|
-
return { digest: result.digest };
|
|
1039
|
-
}
|
|
1040
|
-
})]
|
|
1041
|
-
});
|
|
1042
1004
|
const method = (options.method ?? "GET").toUpperCase();
|
|
1043
1005
|
const canHaveBody = method !== "GET" && method !== "HEAD";
|
|
1044
|
-
const
|
|
1006
|
+
const reqInit = {
|
|
1045
1007
|
method,
|
|
1046
1008
|
headers: options.headers,
|
|
1047
1009
|
body: canHaveBody ? options.body : void 0
|
|
1010
|
+
};
|
|
1011
|
+
const probe = await fetch(options.url, reqInit);
|
|
1012
|
+
if (probe.status !== 402) {
|
|
1013
|
+
return finalize(probe, { paid: false });
|
|
1014
|
+
}
|
|
1015
|
+
const requirements = await pickSuiExactRequirements(probe, client.network);
|
|
1016
|
+
if (!requirements) {
|
|
1017
|
+
throw new exports.T2000Error(
|
|
1018
|
+
"FACILITATOR_REJECTION",
|
|
1019
|
+
`Endpoint returned 402 without an x402 'exact' / sui:${client.network} payment requirement. This SDK only speaks the x402 dialect.`
|
|
1020
|
+
);
|
|
1021
|
+
}
|
|
1022
|
+
return payViaX402({ signer, client, options, reqInit, requirements });
|
|
1023
|
+
}
|
|
1024
|
+
async function pickSuiExactRequirements(response, network) {
|
|
1025
|
+
try {
|
|
1026
|
+
const body = await response.clone().json();
|
|
1027
|
+
const want = `sui:${network === "testnet" ? "testnet" : "mainnet"}`;
|
|
1028
|
+
return body.accepts?.find((a) => a.scheme === "exact" && a.network === want);
|
|
1029
|
+
} catch {
|
|
1030
|
+
return void 0;
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
async function payViaX402(args) {
|
|
1034
|
+
const { signer, client, options, reqInit, requirements } = args;
|
|
1035
|
+
const { buildX402SignedPayment, X402_PAYMENT_HEADER, X402_PAYMENT_RESPONSE_HEADER } = await import('@suimpp/mpp/x402');
|
|
1036
|
+
const amountRaw = BigInt(requirements.maxAmountRequired);
|
|
1037
|
+
const migrationGasSui = await ensureAddressBalanceCovers({
|
|
1038
|
+
signer,
|
|
1039
|
+
client,
|
|
1040
|
+
asset: requirements.asset,
|
|
1041
|
+
amountRaw
|
|
1042
|
+
});
|
|
1043
|
+
const signerAdapter = {
|
|
1044
|
+
toSuiAddress: () => signer.getAddress(),
|
|
1045
|
+
signTransaction: (bytes) => signer.signTransaction(bytes)
|
|
1046
|
+
};
|
|
1047
|
+
const { header } = await buildX402SignedPayment({ requirements, signer: signerAdapter });
|
|
1048
|
+
const res = await fetch(options.url, {
|
|
1049
|
+
...reqInit,
|
|
1050
|
+
headers: { ...options.headers ?? {}, [X402_PAYMENT_HEADER]: header }
|
|
1048
1051
|
});
|
|
1052
|
+
const settleHeader = res.headers.get(X402_PAYMENT_RESPONSE_HEADER);
|
|
1053
|
+
const paid = !!settleHeader;
|
|
1054
|
+
let digest;
|
|
1055
|
+
if (settleHeader) {
|
|
1056
|
+
try {
|
|
1057
|
+
digest = JSON.parse(new TextDecoder().decode(utils.fromBase64(settleHeader))).transaction;
|
|
1058
|
+
} catch {
|
|
1059
|
+
digest = void 0;
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
const result = await finalize(res, { paid });
|
|
1063
|
+
if (!paid) return { ...result, dialect: "x402" };
|
|
1064
|
+
return {
|
|
1065
|
+
...result,
|
|
1066
|
+
dialect: "x402",
|
|
1067
|
+
cost: atomicToHuman(amountRaw, await assetDecimals(requirements.asset)),
|
|
1068
|
+
gasCostSui: migrationGasSui,
|
|
1069
|
+
receipt: digest ? { reference: digest, timestamp: (/* @__PURE__ */ new Date()).toISOString() } : result.receipt
|
|
1070
|
+
};
|
|
1071
|
+
}
|
|
1072
|
+
async function ensureAddressBalanceCovers(args) {
|
|
1073
|
+
const { signer, client, asset, amountRaw } = args;
|
|
1074
|
+
const owner = signer.getAddress();
|
|
1075
|
+
const balanceResp = await client.core.getBalance({ owner, coinType: asset });
|
|
1076
|
+
const total = BigInt(balanceResp.balance.balance);
|
|
1077
|
+
if (total < amountRaw) {
|
|
1078
|
+
throw new exports.T2000Error("INSUFFICIENT_BALANCE", `Insufficient ${asset} to pay`, {
|
|
1079
|
+
available: total.toString(),
|
|
1080
|
+
required: amountRaw.toString()
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
let coinSum = 0n;
|
|
1084
|
+
let cursor;
|
|
1085
|
+
let hasNext = true;
|
|
1086
|
+
while (hasNext) {
|
|
1087
|
+
const page = await client.core.listCoins({ owner, coinType: asset, cursor: cursor ?? void 0 });
|
|
1088
|
+
for (const c of page.objects) coinSum += BigInt(c.balance);
|
|
1089
|
+
cursor = page.cursor;
|
|
1090
|
+
hasNext = page.hasNextPage;
|
|
1091
|
+
}
|
|
1092
|
+
const addressBalance = total - coinSum;
|
|
1093
|
+
if (addressBalance >= amountRaw) return 0;
|
|
1094
|
+
const shortfall = amountRaw - addressBalance;
|
|
1095
|
+
const { Transaction: Transaction6 } = await import('@mysten/sui/transactions');
|
|
1096
|
+
const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
|
|
1097
|
+
const grpcClient = await makeGrpcBuildClient(client);
|
|
1098
|
+
const migration = await executeTx(
|
|
1099
|
+
client,
|
|
1100
|
+
signer,
|
|
1101
|
+
async () => {
|
|
1102
|
+
const tx = new Transaction6();
|
|
1103
|
+
const { coin } = await selectAndSplitCoin2(tx, client, owner, asset, shortfall, {
|
|
1104
|
+
sponsoredContext: true,
|
|
1105
|
+
// coin-objects-only — never the address balance
|
|
1106
|
+
allowSwapAll: false
|
|
1107
|
+
});
|
|
1108
|
+
tx.moveCall({
|
|
1109
|
+
target: "0x2::coin::send_funds",
|
|
1110
|
+
typeArguments: [asset],
|
|
1111
|
+
arguments: [coin, tx.pure.address(owner)]
|
|
1112
|
+
});
|
|
1113
|
+
return tx;
|
|
1114
|
+
},
|
|
1115
|
+
{ buildClient: grpcClient }
|
|
1116
|
+
);
|
|
1117
|
+
return migration.gasCostSui;
|
|
1118
|
+
}
|
|
1119
|
+
async function finalize(response, opts) {
|
|
1049
1120
|
const contentType = response.headers.get("content-type") ?? "";
|
|
1050
1121
|
let body;
|
|
1051
1122
|
try {
|
|
@@ -1053,15 +1124,25 @@ async function payWithMpp(args) {
|
|
|
1053
1124
|
} catch {
|
|
1054
1125
|
body = null;
|
|
1055
1126
|
}
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1127
|
+
return { status: response.status, body, paid: opts.paid };
|
|
1128
|
+
}
|
|
1129
|
+
async function makeGrpcBuildClient(client) {
|
|
1130
|
+
const { SuiGrpcClient: SuiGrpcClient2 } = await import('@mysten/sui/grpc');
|
|
1131
|
+
const network = client.network === "testnet" ? "testnet" : "mainnet";
|
|
1132
|
+
const baseUrl = network === "testnet" ? "https://fullnode.testnet.sui.io" : "https://fullnode.mainnet.sui.io";
|
|
1133
|
+
return new SuiGrpcClient2({ baseUrl, network });
|
|
1134
|
+
}
|
|
1135
|
+
function atomicToHuman(raw, decimals) {
|
|
1136
|
+
return Number(raw) / 10 ** decimals;
|
|
1137
|
+
}
|
|
1138
|
+
async function assetDecimals(coinType) {
|
|
1139
|
+
try {
|
|
1140
|
+
const { getDecimalsForCoinType: getDecimalsForCoinType2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
|
|
1141
|
+
const d = getDecimalsForCoinType2(coinType);
|
|
1142
|
+
return typeof d === "number" ? d : 6;
|
|
1143
|
+
} catch {
|
|
1144
|
+
return 6;
|
|
1145
|
+
}
|
|
1065
1146
|
}
|
|
1066
1147
|
|
|
1067
1148
|
// src/wallet/zkLoginSigner.ts
|