@t2000/sdk 0.56.2 → 1.0.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.js CHANGED
@@ -98,37 +98,12 @@ function mapMoveAbortCode(code) {
98
98
  };
99
99
  return abortMessages[code] ?? `Move abort code: ${code}`;
100
100
  }
101
- function isMoveAbort(msg) {
102
- return msg.includes("MoveAbort") || msg.includes("MovePrimitiveRuntimeError");
103
- }
104
- function parseMoveAbortMessage(msg) {
105
- const abortMatch = msg.match(/abort code:\s*(\d+)/i) ?? msg.match(/MoveAbort[^,]*,\s*(\d+)/);
106
- if (abortMatch) {
107
- const code = parseInt(abortMatch[1], 10);
108
- const moduleMatch = msg.match(/Identifier\("([^"]+)"\)/) ?? msg.match(/in '([^']+)'/);
109
- const fnMatch = msg.match(/function_name:\s*Some\("([^"]+)"\)/);
110
- const context = `${moduleMatch?.[1] ?? ""}${fnMatch ? `::${fnMatch[1]}` : ""}`.toLowerCase();
111
- const suffix = moduleMatch ? ` [${moduleMatch[1]}${fnMatch ? `::${fnMatch[1]}` : ""}]` : "";
112
- if (context.includes("slippage")) {
113
- return `Slippage too high \u2014 price moved during execution${suffix}`;
114
- }
115
- if (context.includes("balance::split") || context.includes("balance::ENotEnough")) {
116
- return `Insufficient on-chain balance${suffix}`;
117
- }
118
- const mapped = mapMoveAbortCode(code);
119
- return `${mapped}${suffix}`;
120
- }
121
- return msg;
122
- }
123
101
 
124
102
  // src/constants.ts
125
103
  var MIST_PER_SUI = 1000000000n;
126
104
  var SUI_DECIMALS = 9;
127
105
  var USDC_DECIMALS = 6;
128
106
  var BPS_DENOMINATOR = 10000n;
129
- var AUTO_TOPUP_THRESHOLD = 50000000n;
130
- var GAS_RESERVE_TARGET = 150000000n;
131
- var AUTO_TOPUP_MIN_USDC = 2000000n;
132
107
  var SAVE_FEE_BPS = 10n;
133
108
  var BORROW_FEE_BPS = 5n;
134
109
  var CLOCK_ID = "0x6";
@@ -194,313 +169,8 @@ var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d4
194
169
  var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
195
170
  var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0xf420ec0dcad44433042fb56e1413fb88d3ff65be94fcf425ef9ff750164590e8";
196
171
  var DEFAULT_NETWORK = "mainnet";
197
- var API_BASE_URL = process.env.T2000_API_URL ?? "https://api.t2000.ai";
172
+ process.env.T2000_API_URL ?? "https://api.t2000.ai";
198
173
  var GAS_RESERVE_MIN = 0.05;
199
-
200
- // src/gas/autoTopUp.ts
201
- async function shouldAutoTopUp(client, address) {
202
- const [suiBalance, usdcBalance] = await Promise.all([
203
- client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.SUI.type }),
204
- client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.USDC.type })
205
- ]);
206
- const suiRaw = BigInt(suiBalance.totalBalance);
207
- const usdcRaw = BigInt(usdcBalance.totalBalance);
208
- if (suiRaw < GAS_RESERVE_TARGET && usdcRaw >= AUTO_TOPUP_MIN_USDC) {
209
- return false;
210
- }
211
- return false;
212
- }
213
- async function executeAutoTopUp(_client, _signer) {
214
- return { success: false, tx: "", usdcSpent: 0, suiReceived: 0 };
215
- }
216
-
217
- // src/utils/base64.ts
218
- function toBase64(bytes) {
219
- let binary = "";
220
- for (const byte of bytes) binary += String.fromCharCode(byte);
221
- return btoa(binary);
222
- }
223
- function fromBase64(b64) {
224
- const binary = atob(b64);
225
- const bytes = new Uint8Array(binary.length);
226
- for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
227
- return bytes;
228
- }
229
-
230
- // src/gas/gasStation.ts
231
- async function requestGasSponsorship(txJson, sender, type, txBcsBytes) {
232
- const payload = { sender, type };
233
- if (txBcsBytes) {
234
- payload.txBcsBytes = txBcsBytes;
235
- } else {
236
- payload.txJson = txJson;
237
- payload.txBytes = toBase64(new TextEncoder().encode(txJson));
238
- }
239
- const res = await fetch(`${API_BASE_URL}/api/gas`, {
240
- method: "POST",
241
- headers: { "Content-Type": "application/json" },
242
- body: JSON.stringify(payload)
243
- });
244
- const data = await res.json();
245
- if (!res.ok) {
246
- const errorCode = data.error;
247
- if (errorCode === "CIRCUIT_BREAKER" || errorCode === "POOL_DEPLETED" || errorCode === "PRICE_STALE") {
248
- throw new T2000Error(
249
- "GAS_STATION_UNAVAILABLE",
250
- data.message ?? "Gas station temporarily unavailable",
251
- { retryAfter: data.retryAfter, reason: errorCode },
252
- true
253
- );
254
- }
255
- if (errorCode === "GAS_FEE_EXCEEDED") {
256
- throw new T2000Error(
257
- "GAS_FEE_EXCEEDED",
258
- data.message ?? "Gas fee exceeds ceiling",
259
- { retryAfter: data.retryAfter },
260
- true
261
- );
262
- }
263
- throw new T2000Error(
264
- "GAS_STATION_UNAVAILABLE",
265
- data.message ?? "Gas sponsorship request failed",
266
- { reason: errorCode },
267
- true
268
- );
269
- }
270
- return data;
271
- }
272
- async function reportGasUsage(sender, txDigest, gasCostSui, usdcCharged, type) {
273
- try {
274
- await fetch(`${API_BASE_URL}/api/gas/report`, {
275
- method: "POST",
276
- headers: { "Content-Type": "application/json" },
277
- body: JSON.stringify({ sender, txDigest, gasCostSui, usdcCharged, type })
278
- });
279
- } catch {
280
- }
281
- }
282
- async function getGasStatus(address) {
283
- const url = new URL(`${API_BASE_URL}/api/gas/status`);
284
- if (address) url.searchParams.set("address", address);
285
- const res = await fetch(url.toString());
286
- if (!res.ok) {
287
- throw new T2000Error("GAS_STATION_UNAVAILABLE", "Failed to fetch gas status", void 0, true);
288
- }
289
- return await res.json();
290
- }
291
-
292
- // src/gas/manager.ts
293
- function extractGasCost(effects) {
294
- if (!effects?.gasUsed) return 0;
295
- return (Number(effects.gasUsed.computationCost) + Number(effects.gasUsed.storageCost) - Number(effects.gasUsed.storageRebate)) / 1e9;
296
- }
297
- async function getSuiBalance(client, address) {
298
- const bal = await client.getBalance({ owner: address, coinType: SUPPORTED_ASSETS.SUI.type });
299
- return BigInt(bal.totalBalance);
300
- }
301
- async function assertTxSuccess(effects, digest) {
302
- const eff = effects;
303
- if (eff?.status?.status === "failure") {
304
- const errMsg = eff.status.error ?? "unknown on-chain error";
305
- if (isMoveAbort(errMsg)) {
306
- throw new T2000Error("TRANSACTION_FAILED", parseMoveAbortMessage(errMsg));
307
- }
308
- throw new T2000Error("TRANSACTION_FAILED", `Transaction ${digest} failed on-chain: ${errMsg}`);
309
- }
310
- }
311
- async function trySelfFunded(client, signer, tx) {
312
- const address = signer.getAddress();
313
- const suiBalance = await getSuiBalance(client, address);
314
- if (suiBalance < AUTO_TOPUP_THRESHOLD) return null;
315
- tx.setSender(address);
316
- const builtBytes = await tx.build({ client });
317
- const { signature } = await signer.signTransaction(builtBytes);
318
- const result = await client.executeTransactionBlock({
319
- transactionBlock: toBase64(builtBytes),
320
- signature: [signature],
321
- options: { showEffects: true, showBalanceChanges: true }
322
- });
323
- await client.waitForTransaction({ digest: result.digest });
324
- await assertTxSuccess(result.effects, result.digest);
325
- return {
326
- digest: result.digest,
327
- effects: result.effects,
328
- balanceChanges: result.balanceChanges,
329
- gasMethod: "self-funded",
330
- gasCostSui: extractGasCost(result.effects),
331
- preTxSuiMist: suiBalance
332
- };
333
- }
334
- async function tryAutoTopUpThenSelfFund(client, signer, buildTx) {
335
- const address = signer.getAddress();
336
- const canTopUp = await shouldAutoTopUp(client, address);
337
- if (!canTopUp) return null;
338
- await executeAutoTopUp();
339
- const tx = await buildTx();
340
- tx.setSender(address);
341
- const suiAfterTopUp = await getSuiBalance(client, address);
342
- const builtBytes = await tx.build({ client });
343
- const { signature } = await signer.signTransaction(builtBytes);
344
- const result = await client.executeTransactionBlock({
345
- transactionBlock: toBase64(builtBytes),
346
- signature: [signature],
347
- options: { showEffects: true, showBalanceChanges: true }
348
- });
349
- await client.waitForTransaction({ digest: result.digest });
350
- await assertTxSuccess(result.effects, result.digest);
351
- return {
352
- digest: result.digest,
353
- effects: result.effects,
354
- balanceChanges: result.balanceChanges,
355
- gasMethod: "auto-topup",
356
- gasCostSui: extractGasCost(result.effects),
357
- preTxSuiMist: suiAfterTopUp
358
- };
359
- }
360
- async function trySponsored(client, signer, tx) {
361
- const address = signer.getAddress();
362
- const suiBalance = await getSuiBalance(client, address);
363
- tx.setSender(address);
364
- let txJson;
365
- let txBcsBase64;
366
- try {
367
- txJson = tx.serialize();
368
- } catch {
369
- const bcsBytes = await tx.build({ client });
370
- txBcsBase64 = toBase64(bcsBytes);
371
- }
372
- const sponsoredResult = await requestGasSponsorship(txJson ?? "", address, void 0, txBcsBase64);
373
- const sponsoredTxBytes = fromBase64(sponsoredResult.txBytes);
374
- const { signature: agentSig } = await signer.signTransaction(sponsoredTxBytes);
375
- const result = await client.executeTransactionBlock({
376
- transactionBlock: sponsoredResult.txBytes,
377
- signature: [agentSig, sponsoredResult.sponsorSignature],
378
- options: { showEffects: true, showBalanceChanges: true }
379
- });
380
- await client.waitForTransaction({ digest: result.digest });
381
- await assertTxSuccess(result.effects, result.digest);
382
- const gasCost = extractGasCost(result.effects);
383
- reportGasUsage(address, result.digest, gasCost, 0, sponsoredResult.type);
384
- return {
385
- digest: result.digest,
386
- effects: result.effects,
387
- balanceChanges: result.balanceChanges,
388
- gasMethod: "sponsored",
389
- gasCostSui: gasCost,
390
- preTxSuiMist: suiBalance
391
- };
392
- }
393
- async function waitForIndexer(client, digest) {
394
- for (let i = 0; i < 3; i++) {
395
- try {
396
- await client.getTransactionBlock({ digest, options: { showObjectChanges: true } });
397
- return;
398
- } catch {
399
- await new Promise((r) => setTimeout(r, 500));
400
- }
401
- }
402
- }
403
- async function executeWithGas(client, signer, buildTx, options) {
404
- if (options?.enforcer && options?.metadata) {
405
- options.enforcer.check(options.metadata);
406
- }
407
- const result = await resolveGas(client, signer, buildTx);
408
- try {
409
- if (result.preTxSuiMist !== void 0) {
410
- const gasCostMist = result.gasMethod === "sponsored" ? 0n : BigInt(Math.round(result.gasCostSui * 1e9));
411
- const estimatedRemaining = result.preTxSuiMist - gasCostMist;
412
- if (estimatedRemaining < GAS_RESERVE_TARGET) {
413
- const address = signer.getAddress();
414
- const usdcBal = await client.getBalance({
415
- owner: address,
416
- coinType: SUPPORTED_ASSETS.USDC.type
417
- });
418
- if (BigInt(usdcBal.totalBalance) >= AUTO_TOPUP_MIN_USDC) {
419
- await executeAutoTopUp(client, signer);
420
- }
421
- }
422
- }
423
- } catch {
424
- }
425
- return result;
426
- }
427
- var GAS_RESOLUTION_CODES = /* @__PURE__ */ new Set([
428
- "INSUFFICIENT_GAS",
429
- "GAS_STATION_UNAVAILABLE",
430
- "GAS_FEE_EXCEEDED",
431
- "AUTO_TOPUP_FAILED",
432
- "SPONSOR_UNAVAILABLE"
433
- ]);
434
- function isBuildError(err) {
435
- return err instanceof T2000Error && !GAS_RESOLUTION_CODES.has(err.code);
436
- }
437
- async function resolveGas(client, signer, buildTx) {
438
- const errors = [];
439
- let lastBuildError;
440
- try {
441
- const tx = await buildTx();
442
- const result = await trySelfFunded(client, signer, tx);
443
- if (result) {
444
- await waitForIndexer(client, result.digest);
445
- return result;
446
- }
447
- errors.push("self-funded: SUI below threshold");
448
- } catch (err) {
449
- if (err instanceof T2000Error && err.code === "TRANSACTION_FAILED") throw err;
450
- const msg = err instanceof Error ? err.message : String(err);
451
- if (isMoveAbort(msg)) {
452
- throw new T2000Error("TRANSACTION_FAILED", parseMoveAbortMessage(msg));
453
- }
454
- if (isBuildError(err)) lastBuildError = err;
455
- errors.push(`self-funded: ${msg}`);
456
- }
457
- try {
458
- const result = await tryAutoTopUpThenSelfFund(client, signer, buildTx);
459
- if (result) {
460
- await waitForIndexer(client, result.digest);
461
- return result;
462
- }
463
- errors.push("auto-topup: not eligible (low USDC or sufficient SUI)");
464
- } catch (err) {
465
- if (err instanceof T2000Error && err.code === "TRANSACTION_FAILED") throw err;
466
- errors.push(`auto-topup: ${err instanceof Error ? err.message : String(err)}`);
467
- }
468
- try {
469
- const tx = await buildTx();
470
- const result = await trySelfFunded(client, signer, tx);
471
- if (result) {
472
- await waitForIndexer(client, result.digest);
473
- return result;
474
- }
475
- } catch (err) {
476
- if (err instanceof T2000Error && err.code === "TRANSACTION_FAILED") throw err;
477
- const msg = err instanceof Error ? err.message : String(err);
478
- if (isMoveAbort(msg)) {
479
- throw new T2000Error("TRANSACTION_FAILED", parseMoveAbortMessage(msg));
480
- }
481
- if (isBuildError(err)) lastBuildError = err;
482
- errors.push(`self-funded-retry: ${msg}`);
483
- }
484
- try {
485
- const tx = await buildTx();
486
- const result = await trySponsored(client, signer, tx);
487
- if (result) {
488
- await waitForIndexer(client, result.digest);
489
- return result;
490
- }
491
- errors.push("sponsored: returned null");
492
- } catch (err) {
493
- if (err instanceof T2000Error && err.code === "TRANSACTION_FAILED") throw err;
494
- if (isBuildError(err)) lastBuildError = err;
495
- errors.push(`sponsored: ${err instanceof Error ? err.message : String(err)}`);
496
- }
497
- if (lastBuildError) throw lastBuildError;
498
- throw new T2000Error(
499
- "INSUFFICIENT_GAS",
500
- `No SUI for gas and sponsorship unavailable. Fund your wallet with SUI or USDC. [${errors.join(" | ")}]`,
501
- { reason: "all_gas_methods_exhausted", errors }
502
- );
503
- }
504
174
  function validateAddress(address) {
505
175
  const normalized = normalizeSuiAddress(address);
506
176
  if (!isValidSuiAddress(normalized)) {
@@ -837,6 +507,19 @@ for (const [key, info] of Object.entries(SUPPORTED_ASSETS)) {
837
507
  }
838
508
  }
839
509
 
510
+ // src/utils/base64.ts
511
+ function toBase64(bytes) {
512
+ let binary = "";
513
+ for (const byte of bytes) binary += String.fromCharCode(byte);
514
+ return btoa(binary);
515
+ }
516
+ function fromBase64(b64) {
517
+ const binary = atob(b64);
518
+ const bytes = new Uint8Array(binary.length);
519
+ for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
520
+ return bytes;
521
+ }
522
+
840
523
  // src/protocols/protocolFee.ts
841
524
  var FEE_RATES = {
842
525
  save: SAVE_FEE_BPS,
@@ -916,6 +599,6 @@ var DEFAULT_SAFEGUARD_CONFIG = {
916
599
  dailyResetDate: ""
917
600
  };
918
601
 
919
- export { ALL_NAVI_ASSETS, BPS_DENOMINATOR, CLOCK_ID, COIN_REGISTRY, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, OUTBOUND_OPS, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardError, T2000Error, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, WAL_TYPE, WBTC_TYPE, ZkLoginSigner, addCollectFeeToTx, calculateFee, classifyAction, classifyLabel, classifyTransaction, executeAutoTopUp, executeWithGas, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, formatAssetAmount, formatSui, formatUsd, fromBase64, getDecimals, getDecimalsForCoinType, getGasStatus, getTier, isSupported, isTier1, isTier2, mapMoveAbortCode, mapWalletError, mistToSui, parseSuiRpcTx, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, shouldAutoTopUp, stableToRaw, suiToMist, toBase64, truncateAddress, usdcToRaw, validateAddress };
602
+ export { ALL_NAVI_ASSETS, BPS_DENOMINATOR, CLOCK_ID, COIN_REGISTRY, DEFAULT_NETWORK, DEFAULT_SAFEGUARD_CONFIG, ETH_TYPE, GAS_RESERVE_MIN, IKA_TYPE, KNOWN_TARGETS, KeypairSigner, LABEL_PATTERNS, LOFI_TYPE, MANIFEST_TYPE, MIST_PER_SUI, NAVX_TYPE, OUTBOUND_OPS, STABLE_ASSETS, SUI_DECIMALS, SUI_TYPE, SUPPORTED_ASSETS, SafeguardError, T2000Error, TOKEN_MAP, USDC_DECIMALS, USDC_TYPE, USDE_TYPE, USDSUI_TYPE, USDT_TYPE, WAL_TYPE, WBTC_TYPE, ZkLoginSigner, addCollectFeeToTx, calculateFee, classifyAction, classifyLabel, classifyTransaction, extractTransferDetails, extractTxCommands, extractTxSender, fallbackLabel, formatAssetAmount, formatSui, formatUsd, fromBase64, getDecimals, getDecimalsForCoinType, getTier, isSupported, isTier1, isTier2, mapMoveAbortCode, mapWalletError, mistToSui, parseSuiRpcTx, rawToStable, rawToUsdc, refineLendingLabel, resolveSymbol, resolveTokenType, stableToRaw, suiToMist, toBase64, truncateAddress, usdcToRaw, validateAddress };
920
603
  //# sourceMappingURL=browser.js.map
921
604
  //# sourceMappingURL=browser.js.map