@t2000/sdk 5.5.1 → 5.6.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 +197 -24
- 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 +191 -27
- package/dist/browser.js.map +1 -1
- package/dist/index.cjs +145 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -70
- package/dist/index.d.ts +17 -70
- package/dist/index.js +139 -33
- package/dist/index.js.map +1 -1
- package/dist/{simulate-KETPmlDo.d.cts → send-D2nKpwJN.d.cts} +162 -21
- package/dist/{simulate-KETPmlDo.d.ts → send-D2nKpwJN.d.ts} +162 -21
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var utils = require('@mysten/sui/utils');
|
|
3
4
|
var transactions = require('@mysten/sui/transactions');
|
|
4
5
|
var aggregatorSdk = require('@cetusprotocol/aggregator-sdk');
|
|
5
6
|
var BN = require('bn.js');
|
|
@@ -7,7 +8,6 @@ var eventemitter3 = require('eventemitter3');
|
|
|
7
8
|
var paymentKit = require('@mysten/payment-kit');
|
|
8
9
|
var grpc = require('@mysten/sui/grpc');
|
|
9
10
|
var graphql = require('@mysten/sui/graphql');
|
|
10
|
-
var utils = require('@mysten/sui/utils');
|
|
11
11
|
var ed25519 = require('@mysten/sui/keypairs/ed25519');
|
|
12
12
|
var cryptography = require('@mysten/sui/cryptography');
|
|
13
13
|
var promises = require('fs/promises');
|
|
@@ -118,6 +118,37 @@ var init_errors = __esm({
|
|
|
118
118
|
};
|
|
119
119
|
}
|
|
120
120
|
});
|
|
121
|
+
function preflightFail(code, error) {
|
|
122
|
+
return { valid: false, code, error };
|
|
123
|
+
}
|
|
124
|
+
function checkPositiveAmount(amount, label = "Amount", max = exports.PREFLIGHT_MAX_AMOUNT) {
|
|
125
|
+
if (typeof amount !== "number" || !Number.isFinite(amount)) {
|
|
126
|
+
return preflightFail("INVALID_AMOUNT", `${label} must be a finite number`);
|
|
127
|
+
}
|
|
128
|
+
if (amount <= 0) {
|
|
129
|
+
return preflightFail("INVALID_AMOUNT", `${label} must be greater than zero`);
|
|
130
|
+
}
|
|
131
|
+
if (amount > max) {
|
|
132
|
+
return preflightFail("INVALID_AMOUNT", `${label} ${amount} exceeds the sane maximum (${max})`);
|
|
133
|
+
}
|
|
134
|
+
return exports.PREFLIGHT_OK;
|
|
135
|
+
}
|
|
136
|
+
function checkSuiAddress(address, label = "recipient") {
|
|
137
|
+
try {
|
|
138
|
+
if (typeof address === "string" && address.trim() !== "" && utils.isValidSuiAddress(utils.normalizeSuiAddress(address))) {
|
|
139
|
+
return exports.PREFLIGHT_OK;
|
|
140
|
+
}
|
|
141
|
+
} catch {
|
|
142
|
+
}
|
|
143
|
+
return preflightFail("INVALID_ADDRESS", `Invalid ${label} address: ${address}`);
|
|
144
|
+
}
|
|
145
|
+
exports.PREFLIGHT_MAX_AMOUNT = void 0; exports.PREFLIGHT_OK = void 0;
|
|
146
|
+
var init_preflight = __esm({
|
|
147
|
+
"src/preflight.ts"() {
|
|
148
|
+
exports.PREFLIGHT_MAX_AMOUNT = 1e6;
|
|
149
|
+
exports.PREFLIGHT_OK = { valid: true };
|
|
150
|
+
}
|
|
151
|
+
});
|
|
121
152
|
|
|
122
153
|
// src/token-registry.ts
|
|
123
154
|
var token_registry_exports = {};
|
|
@@ -244,6 +275,7 @@ var init_token_registry = __esm({
|
|
|
244
275
|
// src/wallet/coinSelection.ts
|
|
245
276
|
var coinSelection_exports = {};
|
|
246
277
|
__export(coinSelection_exports, {
|
|
278
|
+
buildCoinToAddressBalanceMigration: () => buildCoinToAddressBalanceMigration,
|
|
247
279
|
fetchAllCoins: () => fetchAllCoins,
|
|
248
280
|
selectAndSplitCoin: () => selectAndSplitCoin,
|
|
249
281
|
selectSuiCoin: () => selectSuiCoin
|
|
@@ -357,6 +389,32 @@ async function selectCoinObjectsOnly(tx, client, owner, coinType, amount, allowS
|
|
|
357
389
|
});
|
|
358
390
|
return { coin, effectiveAmount, swapAll };
|
|
359
391
|
}
|
|
392
|
+
function buildCoinToAddressBalanceMigration(args) {
|
|
393
|
+
const { coins, coinType, owner, minAmount } = args;
|
|
394
|
+
const sorted = [...coins].filter((c) => c.balance > 0n).sort((a, b) => b.balance > a.balance ? 1 : b.balance < a.balance ? -1 : 0);
|
|
395
|
+
const selected = [];
|
|
396
|
+
let migratedRaw = 0n;
|
|
397
|
+
for (const c of sorted) {
|
|
398
|
+
if (migratedRaw >= minAmount) break;
|
|
399
|
+
selected.push(c);
|
|
400
|
+
migratedRaw += c.balance;
|
|
401
|
+
}
|
|
402
|
+
if (migratedRaw < minAmount) {
|
|
403
|
+
throw new exports.T2000Error("INSUFFICIENT_BALANCE", `Insufficient ${coinType} coin objects to migrate`, {
|
|
404
|
+
available: migratedRaw.toString(),
|
|
405
|
+
required: minAmount.toString()
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
const tx = new transactions.Transaction();
|
|
409
|
+
for (const c of selected) {
|
|
410
|
+
tx.moveCall({
|
|
411
|
+
target: "0x2::coin::send_funds",
|
|
412
|
+
typeArguments: [coinType],
|
|
413
|
+
arguments: [tx.object(c.objectId), tx.pure.address(owner)]
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
return { tx, migratedRaw };
|
|
417
|
+
}
|
|
360
418
|
async function selectSuiCoin(tx, client, owner, amountMist, sponsoredContext, mergeCache) {
|
|
361
419
|
if (sponsoredContext) {
|
|
362
420
|
const { SUI_TYPE: SUI_TYPE2 } = await Promise.resolve().then(() => (init_token_registry(), token_registry_exports));
|
|
@@ -382,10 +440,28 @@ __export(cetus_swap_exports, {
|
|
|
382
440
|
findSwapRoute: () => findSwapRoute,
|
|
383
441
|
isCetusRouteFresh: () => isCetusRouteFresh,
|
|
384
442
|
isPrecomputedRouteCompatibleWithProviders: () => isPrecomputedRouteCompatibleWithProviders,
|
|
443
|
+
preflightSwap: () => preflightSwap,
|
|
385
444
|
resolveTokenType: () => resolveTokenType,
|
|
386
445
|
serializeCetusRoute: () => serializeCetusRoute,
|
|
387
446
|
verifyCetusRouteCoinMatch: () => verifyCetusRouteCoinMatch
|
|
388
447
|
});
|
|
448
|
+
function preflightSwap(input) {
|
|
449
|
+
if (typeof input.from !== "string" || input.from.trim() === "") {
|
|
450
|
+
return preflightFail("INVALID_ASSET", "A `from` token is required to swap");
|
|
451
|
+
}
|
|
452
|
+
if (typeof input.to !== "string" || input.to.trim() === "") {
|
|
453
|
+
return preflightFail("INVALID_ASSET", "A `to` token is required to swap");
|
|
454
|
+
}
|
|
455
|
+
const amountCheck = checkPositiveAmount(input.amount, "Amount", Number.POSITIVE_INFINITY);
|
|
456
|
+
if (!amountCheck.valid) return amountCheck;
|
|
457
|
+
const resolvedFrom = resolveTokenType(input.from);
|
|
458
|
+
const resolvedTo = resolveTokenType(input.to);
|
|
459
|
+
const sameToken = input.from.trim() === input.to.trim() || resolvedFrom !== null && resolvedFrom === resolvedTo;
|
|
460
|
+
if (sameToken) {
|
|
461
|
+
return preflightFail("INVALID_ASSET", `Cannot swap ${input.from} to itself`);
|
|
462
|
+
}
|
|
463
|
+
return exports.PREFLIGHT_OK;
|
|
464
|
+
}
|
|
389
465
|
function serializeCetusRoute(route, context) {
|
|
390
466
|
return {
|
|
391
467
|
routerData: serializeRouterDataV3(route.routerData),
|
|
@@ -637,6 +713,7 @@ exports.OVERLAY_FEE_RATE = void 0; var clientCache;
|
|
|
637
713
|
var init_cetus_swap = __esm({
|
|
638
714
|
"src/protocols/cetus-swap.ts"() {
|
|
639
715
|
init_token_registry();
|
|
716
|
+
init_preflight();
|
|
640
717
|
init_token_registry();
|
|
641
718
|
exports.OVERLAY_FEE_RATE = 1e-3;
|
|
642
719
|
clientCache = /* @__PURE__ */ new Map();
|
|
@@ -1010,8 +1087,33 @@ async function executeTx(client, signer, buildTx, options = {}) {
|
|
|
1010
1087
|
|
|
1011
1088
|
// src/wallet/pay.ts
|
|
1012
1089
|
init_errors();
|
|
1090
|
+
init_preflight();
|
|
1091
|
+
function preflightPay(input) {
|
|
1092
|
+
if (typeof input.url !== "string" || input.url.trim() === "") {
|
|
1093
|
+
return preflightFail("FACILITATOR_REJECTION", "A target URL is required to pay");
|
|
1094
|
+
}
|
|
1095
|
+
let parsed;
|
|
1096
|
+
try {
|
|
1097
|
+
parsed = new URL(input.url);
|
|
1098
|
+
} catch {
|
|
1099
|
+
return preflightFail("FACILITATOR_REJECTION", `Invalid URL: ${input.url}`);
|
|
1100
|
+
}
|
|
1101
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
1102
|
+
return preflightFail(
|
|
1103
|
+
"FACILITATOR_REJECTION",
|
|
1104
|
+
`URL must be http(s): got ${parsed.protocol}//`
|
|
1105
|
+
);
|
|
1106
|
+
}
|
|
1107
|
+
if (input.maxPrice !== void 0) {
|
|
1108
|
+
const priceCheck = checkPositiveAmount(input.maxPrice, "maxPrice");
|
|
1109
|
+
if (!priceCheck.valid) return priceCheck;
|
|
1110
|
+
}
|
|
1111
|
+
return exports.PREFLIGHT_OK;
|
|
1112
|
+
}
|
|
1013
1113
|
async function payWithMpp(args) {
|
|
1014
1114
|
const { signer, client, options } = args;
|
|
1115
|
+
const pf = preflightPay({ url: options.url, maxPrice: options.maxPrice });
|
|
1116
|
+
if (!pf.valid) throw new exports.T2000Error(pf.code, pf.error);
|
|
1015
1117
|
const method = (options.method ?? "GET").toUpperCase();
|
|
1016
1118
|
const canHaveBody = method !== "GET" && method !== "HEAD";
|
|
1017
1119
|
const reqInit = {
|
|
@@ -1091,40 +1193,26 @@ async function ensureAddressBalanceCovers(args) {
|
|
|
1091
1193
|
required: amountRaw.toString()
|
|
1092
1194
|
});
|
|
1093
1195
|
}
|
|
1196
|
+
const coins = [];
|
|
1094
1197
|
let coinSum = 0n;
|
|
1095
1198
|
let cursor;
|
|
1096
1199
|
let hasNext = true;
|
|
1097
1200
|
while (hasNext) {
|
|
1098
1201
|
const page = await client.core.listCoins({ owner, coinType: asset, cursor: cursor ?? void 0 });
|
|
1099
|
-
for (const c of page.objects)
|
|
1202
|
+
for (const c of page.objects) {
|
|
1203
|
+
coins.push({ objectId: c.objectId, balance: BigInt(c.balance) });
|
|
1204
|
+
coinSum += BigInt(c.balance);
|
|
1205
|
+
}
|
|
1100
1206
|
cursor = page.cursor;
|
|
1101
1207
|
hasNext = page.hasNextPage;
|
|
1102
1208
|
}
|
|
1103
1209
|
const addressBalance = total - coinSum;
|
|
1104
1210
|
if (addressBalance >= amountRaw) return 0;
|
|
1105
1211
|
const shortfall = amountRaw - addressBalance;
|
|
1106
|
-
const {
|
|
1107
|
-
const { selectAndSplitCoin: selectAndSplitCoin2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
|
|
1212
|
+
const { buildCoinToAddressBalanceMigration: buildCoinToAddressBalanceMigration2 } = await Promise.resolve().then(() => (init_coinSelection(), coinSelection_exports));
|
|
1108
1213
|
const grpcClient = await makeGrpcBuildClient(client);
|
|
1109
|
-
const
|
|
1110
|
-
|
|
1111
|
-
signer,
|
|
1112
|
-
async () => {
|
|
1113
|
-
const tx = new Transaction6();
|
|
1114
|
-
const { coin } = await selectAndSplitCoin2(tx, client, owner, asset, shortfall, {
|
|
1115
|
-
sponsoredContext: true,
|
|
1116
|
-
// coin-objects-only — never the address balance
|
|
1117
|
-
allowSwapAll: false
|
|
1118
|
-
});
|
|
1119
|
-
tx.moveCall({
|
|
1120
|
-
target: "0x2::coin::send_funds",
|
|
1121
|
-
typeArguments: [asset],
|
|
1122
|
-
arguments: [coin, tx.pure.address(owner)]
|
|
1123
|
-
});
|
|
1124
|
-
return tx;
|
|
1125
|
-
},
|
|
1126
|
-
{ buildClient: grpcClient }
|
|
1127
|
-
);
|
|
1214
|
+
const { tx } = buildCoinToAddressBalanceMigration2({ coins, coinType: asset, owner, minAmount: shortfall });
|
|
1215
|
+
const migration = await executeTx(client, signer, () => tx, { buildClient: grpcClient });
|
|
1128
1216
|
return migration.gasCostSui;
|
|
1129
1217
|
}
|
|
1130
1218
|
async function finalize(response, opts) {
|
|
@@ -1246,6 +1334,25 @@ function normalizeAsset(input) {
|
|
|
1246
1334
|
}
|
|
1247
1335
|
|
|
1248
1336
|
// src/wallet/send.ts
|
|
1337
|
+
init_preflight();
|
|
1338
|
+
function preflightSend(input) {
|
|
1339
|
+
try {
|
|
1340
|
+
assertAllowedAsset("send", input.asset);
|
|
1341
|
+
} catch (e) {
|
|
1342
|
+
return preflightFail("INVALID_ASSET", e.message);
|
|
1343
|
+
}
|
|
1344
|
+
const amountCheck = checkPositiveAmount(input.amount);
|
|
1345
|
+
if (!amountCheck.valid) return amountCheck;
|
|
1346
|
+
if ((input.asset === "USDC" || input.asset === "USDsui") && input.amount < GASLESS_MIN_STABLE_AMOUNT) {
|
|
1347
|
+
return preflightFail(
|
|
1348
|
+
"INVALID_AMOUNT",
|
|
1349
|
+
`Minimum gasless transfer is ${GASLESS_MIN_STABLE_AMOUNT} ${input.asset}. Got ${input.amount}.`
|
|
1350
|
+
);
|
|
1351
|
+
}
|
|
1352
|
+
const addressCheck = checkSuiAddress(input.to);
|
|
1353
|
+
if (!addressCheck.valid) return addressCheck;
|
|
1354
|
+
return exports.PREFLIGHT_OK;
|
|
1355
|
+
}
|
|
1249
1356
|
async function buildSendTx({
|
|
1250
1357
|
client,
|
|
1251
1358
|
address,
|
|
@@ -1253,17 +1360,11 @@ async function buildSendTx({
|
|
|
1253
1360
|
amount,
|
|
1254
1361
|
asset
|
|
1255
1362
|
}) {
|
|
1256
|
-
|
|
1363
|
+
const pf = preflightSend({ to, amount, asset });
|
|
1364
|
+
if (!pf.valid) throw new exports.T2000Error(pf.code, pf.error);
|
|
1257
1365
|
const recipient = validateAddress(to);
|
|
1258
1366
|
const assetInfo = SUPPORTED_ASSETS[asset];
|
|
1259
1367
|
if (!assetInfo) throw new exports.T2000Error("ASSET_NOT_SUPPORTED", `Asset ${asset} is not supported`);
|
|
1260
|
-
if (amount <= 0) throw new exports.T2000Error("INVALID_AMOUNT", "Amount must be greater than zero");
|
|
1261
|
-
if ((asset === "USDC" || asset === "USDsui") && amount < GASLESS_MIN_STABLE_AMOUNT) {
|
|
1262
|
-
throw new exports.T2000Error(
|
|
1263
|
-
"INVALID_AMOUNT",
|
|
1264
|
-
`Minimum gasless transfer is ${GASLESS_MIN_STABLE_AMOUNT} ${asset}. Got ${amount}.`
|
|
1265
|
-
);
|
|
1266
|
-
}
|
|
1267
1368
|
const rawAmount = displayToRaw(amount, assetInfo.decimals);
|
|
1268
1369
|
const tx = new transactions.Transaction();
|
|
1269
1370
|
tx.setSender(address);
|
|
@@ -2059,7 +2160,9 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
|
|
|
2059
2160
|
amountUsd: approxUsdValue(params.from, params.amount) ?? 0,
|
|
2060
2161
|
force: params.force
|
|
2061
2162
|
});
|
|
2062
|
-
const { findSwapRoute: findSwapRoute2, buildSwapTx: buildSwapTx2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
|
|
2163
|
+
const { findSwapRoute: findSwapRoute2, buildSwapTx: buildSwapTx2, resolveTokenType: resolveTokenType2, preflightSwap: preflightSwap2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
|
|
2164
|
+
const pf = preflightSwap2({ from: params.from, to: params.to, amount: params.amount });
|
|
2165
|
+
if (!pf.valid) throw new exports.T2000Error(pf.code, pf.error);
|
|
2063
2166
|
const fromType = resolveTokenType2(params.from);
|
|
2064
2167
|
const toType = resolveTokenType2(params.to);
|
|
2065
2168
|
if (!fromType) throw new exports.T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.from}. Provide the full coin type.`);
|
|
@@ -2789,6 +2892,9 @@ function displayHandle(label) {
|
|
|
2789
2892
|
return `${label}@${parentDisplay}`;
|
|
2790
2893
|
}
|
|
2791
2894
|
|
|
2895
|
+
// src/index.ts
|
|
2896
|
+
init_preflight();
|
|
2897
|
+
|
|
2792
2898
|
exports.AUDRIC_PARENT_NAME = AUDRIC_PARENT_NAME;
|
|
2793
2899
|
exports.AUDRIC_PARENT_NFT_ID = AUDRIC_PARENT_NFT_ID;
|
|
2794
2900
|
exports.CETUS_USDC_SUI_POOL = CETUS_USDC_SUI_POOL;
|
|
@@ -2830,6 +2936,8 @@ exports.buildAddLeafTx = buildAddLeafTx;
|
|
|
2830
2936
|
exports.buildRevokeLeafTx = buildRevokeLeafTx;
|
|
2831
2937
|
exports.buildSendTx = buildSendTx;
|
|
2832
2938
|
exports.buildSwapTx = buildSwapTx;
|
|
2939
|
+
exports.checkPositiveAmount = checkPositiveAmount;
|
|
2940
|
+
exports.checkSuiAddress = checkSuiAddress;
|
|
2833
2941
|
exports.classifyAction = classifyAction;
|
|
2834
2942
|
exports.classifyLabel = classifyLabel;
|
|
2835
2943
|
exports.classifyTransaction = classifyTransaction;
|
|
@@ -2877,6 +2985,11 @@ exports.normalizeAsset = normalizeAsset;
|
|
|
2877
2985
|
exports.normalizeCoinType = normalizeCoinType;
|
|
2878
2986
|
exports.parseSuiRpcTx = parseSuiRpcTx;
|
|
2879
2987
|
exports.payWithMpp = payWithMpp;
|
|
2988
|
+
exports.preflightFail = preflightFail;
|
|
2989
|
+
exports.preflightPay = preflightPay;
|
|
2990
|
+
exports.preflightSend = preflightSend;
|
|
2991
|
+
exports.preflightSwap = preflightSwap;
|
|
2992
|
+
exports.queryBalance = queryBalance;
|
|
2880
2993
|
exports.queryHistory = queryHistory;
|
|
2881
2994
|
exports.queryTransaction = queryTransaction;
|
|
2882
2995
|
exports.rawToStable = rawToStable;
|