@t2000/sdk 1.0.1 → 1.1.2

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
@@ -145,6 +145,12 @@ var init_errors = __esm({
145
145
  });
146
146
 
147
147
  // src/token-registry.ts
148
+ function getCoinMeta(coinType) {
149
+ return BY_TYPE.get(coinType);
150
+ }
151
+ function isInRegistry(coinType) {
152
+ return BY_TYPE.has(coinType);
153
+ }
148
154
  function isTier1(coinType) {
149
155
  const meta = BY_TYPE.get(coinType);
150
156
  return meta?.tier === 1;
@@ -728,18 +734,22 @@ __export(cetus_swap_exports, {
728
734
  resolveTokenType: () => resolveTokenType,
729
735
  simulateSwap: () => simulateSwap
730
736
  });
731
- function getClient(walletAddress) {
732
- if (clientInstance) return clientInstance;
733
- clientInstance = new aggregatorSdk.AggregatorClient({
737
+ function getClient(walletAddress, overlayFee) {
738
+ const rate = overlayFee?.rate ?? 0;
739
+ const receiver = overlayFee?.receiver ?? "";
740
+ const key = `${walletAddress}|${rate}|${receiver}`;
741
+ const cached = clientCache.get(key);
742
+ if (cached) return cached;
743
+ const client = new aggregatorSdk.AggregatorClient({
734
744
  signer: walletAddress,
735
745
  env: aggregatorSdk.Env.Mainnet,
736
- overlayFeeRate: exports.OVERLAY_FEE_RATE,
737
- overlayFeeReceiver: OVERLAY_FEE_RECEIVER
746
+ ...rate > 0 && receiver ? { overlayFeeRate: rate, overlayFeeReceiver: receiver } : {}
738
747
  });
739
- return clientInstance;
748
+ clientCache.set(key, client);
749
+ return client;
740
750
  }
741
751
  async function findSwapRoute(params) {
742
- const client = getClient(params.walletAddress);
752
+ const client = getClient(params.walletAddress, params.overlayFee);
743
753
  const findParams = {
744
754
  from: params.from,
745
755
  target: params.to,
@@ -776,7 +786,7 @@ function normalizePriceImpact(value) {
776
786
  return Number.isFinite(n) ? n : 0;
777
787
  }
778
788
  async function buildSwapTx(params) {
779
- const client = getClient(params.walletAddress);
789
+ const client = getClient(params.walletAddress, params.overlayFee);
780
790
  const clampedSlippage = Math.max(1e-3, Math.min(params.slippage, 0.05));
781
791
  const outputCoin = await client.routerSwap({
782
792
  router: params.route.routerData,
@@ -787,7 +797,7 @@ async function buildSwapTx(params) {
787
797
  return outputCoin;
788
798
  }
789
799
  async function simulateSwap(params) {
790
- const client = getClient(params.walletAddress);
800
+ const client = getClient(params.walletAddress, params.overlayFee);
791
801
  try {
792
802
  await client.devInspectTransactionBlock(params.tx);
793
803
  return { success: true };
@@ -795,13 +805,12 @@ async function simulateSwap(params) {
795
805
  return { success: false, error: err instanceof Error ? err.message : String(err) };
796
806
  }
797
807
  }
798
- exports.OVERLAY_FEE_RATE = void 0; var OVERLAY_FEE_RECEIVER, clientInstance;
808
+ exports.OVERLAY_FEE_RATE = void 0; var clientCache;
799
809
  var init_cetus_swap = __esm({
800
810
  "src/protocols/cetus-swap.ts"() {
801
811
  init_token_registry();
802
812
  exports.OVERLAY_FEE_RATE = 1e-3;
803
- OVERLAY_FEE_RECEIVER = process.env.T2000_TREASURY_ADDRESS ?? "0x3bb501b8300125dca59019247941a42af6b292a150ce3cfcce9449456be2ec91";
804
- clientInstance = null;
813
+ clientCache = /* @__PURE__ */ new Map();
805
814
  }
806
815
  });
807
816
 
@@ -897,13 +906,11 @@ function assertAllowedAsset(op, asset) {
897
906
  );
898
907
  }
899
908
  }
900
- var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
901
- var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
902
- var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0xf420ec0dcad44433042fb56e1413fb88d3ff65be94fcf425ef9ff750164590e8";
909
+ var T2000_OVERLAY_FEE_WALLET = process.env.T2000_OVERLAY_FEE_WALLET ?? "0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a";
903
910
  var DEFAULT_NETWORK = "mainnet";
904
911
  var DEFAULT_RPC_URL = "https://fullnode.mainnet.sui.io:443";
905
912
  var DEFAULT_KEY_PATH = "~/.t2000/wallet.key";
906
- var API_BASE_URL = process.env.T2000_API_URL ?? "https://api.t2000.ai";
913
+ process.env.T2000_API_URL ?? "https://api.t2000.ai";
907
914
  var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
908
915
  var GAS_RESERVE_MIN = 0.05;
909
916
 
@@ -1445,57 +1452,6 @@ function extractCommands(txBlock) {
1445
1452
  // src/t2000.ts
1446
1453
  init_token_registry();
1447
1454
 
1448
- // src/protocols/protocolFee.ts
1449
- var FEE_RATES = {
1450
- save: SAVE_FEE_BPS,
1451
- borrow: BORROW_FEE_BPS
1452
- };
1453
- var OP_CODES = {
1454
- save: 0,
1455
- borrow: 2
1456
- };
1457
- function calculateFee(operation, amount) {
1458
- const bps = FEE_RATES[operation];
1459
- const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
1460
- const rawAmount = usdcToRaw(feeAmount);
1461
- return {
1462
- amount: feeAmount,
1463
- asset: "USDC",
1464
- rate: Number(bps) / Number(BPS_DENOMINATOR),
1465
- rawAmount
1466
- };
1467
- }
1468
- function addCollectFeeToTx(tx, paymentCoin, operation) {
1469
- const bps = FEE_RATES[operation];
1470
- if (bps <= 0n) return;
1471
- tx.moveCall({
1472
- target: `${T2000_PACKAGE_ID}::treasury::collect_fee`,
1473
- typeArguments: [SUPPORTED_ASSETS.USDC.type],
1474
- arguments: [
1475
- tx.object(T2000_TREASURY_ID),
1476
- tx.object(T2000_CONFIG_ID),
1477
- paymentCoin,
1478
- tx.pure.u8(OP_CODES[operation])
1479
- ]
1480
- });
1481
- }
1482
- async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest) {
1483
- try {
1484
- await fetch(`${API_BASE_URL}/api/fees`, {
1485
- method: "POST",
1486
- headers: { "Content-Type": "application/json" },
1487
- body: JSON.stringify({
1488
- agentAddress,
1489
- operation,
1490
- feeAmount: feeAmount.toString(),
1491
- feeRate: feeRate.toString(),
1492
- txDigest
1493
- })
1494
- });
1495
- } catch {
1496
- }
1497
- }
1498
-
1499
1455
  // ../../node_modules/.pnpm/@mysten+bcs@2.0.2/node_modules/@mysten/bcs/dist/uleb.mjs
1500
1456
  function ulebEncode(num) {
1501
1457
  let bigNum = BigInt(num);
@@ -5279,9 +5235,6 @@ async function buildSaveTx(client, address, amount, options = {}) {
5279
5235
  const tx = new transactions.Transaction();
5280
5236
  tx.setSender(address);
5281
5237
  const coinObj = mergeCoins(tx, coins);
5282
- if (options.collectFee) {
5283
- addCollectFeeToTx(tx, coinObj, "save");
5284
- }
5285
5238
  const rawAmount = Math.min(Number(stableToRaw(amount, assetInfo.decimals)), Number(totalBalance));
5286
5239
  try {
5287
5240
  await Ce(tx, assetInfo.type, coinObj, {
@@ -5352,9 +5305,6 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
5352
5305
  async function addSaveToTx(tx, _client, _address, coin, options = {}) {
5353
5306
  const asset = options.asset ?? "USDC";
5354
5307
  const assetInfo = resolveAssetInfo(asset);
5355
- if (options.collectFee) {
5356
- addCollectFeeToTx(tx, coin, "save");
5357
- }
5358
5308
  try {
5359
5309
  await Ce(tx, assetInfo.type, coin, { env: "prod" });
5360
5310
  } catch (err) {
@@ -5385,9 +5335,6 @@ async function buildBorrowTx(client, address, amount, options = {}) {
5385
5335
  await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5386
5336
  try {
5387
5337
  const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
5388
- if (options.collectFee) {
5389
- addCollectFeeToTx(tx, borrowedCoin, "borrow");
5390
- }
5391
5338
  tx.transferObjects([borrowedCoin], address);
5392
5339
  } catch (err) {
5393
5340
  const msg = err instanceof Error ? err.message : String(err);
@@ -5395,6 +5342,22 @@ async function buildBorrowTx(client, address, amount, options = {}) {
5395
5342
  }
5396
5343
  return tx;
5397
5344
  }
5345
+ async function addBorrowToTx(tx, client, address, amount, options = {}) {
5346
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
5347
+ throw new exports.T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
5348
+ }
5349
+ const asset = options.asset ?? "USDC";
5350
+ const assetInfo = resolveAssetInfo(asset);
5351
+ const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
5352
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5353
+ try {
5354
+ const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
5355
+ return borrowedCoin;
5356
+ } catch (err) {
5357
+ const msg = err instanceof Error ? err.message : String(err);
5358
+ throw new exports.T2000Error("PROTOCOL_UNAVAILABLE", `NAVI borrow failed: ${msg}`);
5359
+ }
5360
+ }
5398
5361
  async function buildRepayTx(client, address, amount, options = {}) {
5399
5362
  if (!amount || amount <= 0 || !Number.isFinite(amount)) {
5400
5363
  throw new exports.T2000Error("INVALID_AMOUNT", "Repay amount must be a positive number");
@@ -5722,9 +5685,9 @@ var NaviAdapter = class {
5722
5685
  async getHealth(address) {
5723
5686
  return getHealthFactor(this.client, address);
5724
5687
  }
5725
- async buildSaveTx(address, amount, asset, options) {
5688
+ async buildSaveTx(address, amount, asset) {
5726
5689
  const normalized = normalizeAsset(asset);
5727
- const tx = await buildSaveTx(this.client, address, amount, { ...options, asset: normalized });
5690
+ const tx = await buildSaveTx(this.client, address, amount, { asset: normalized });
5728
5691
  return { tx };
5729
5692
  }
5730
5693
  async buildWithdrawTx(address, amount, asset, options) {
@@ -5762,9 +5725,16 @@ var NaviAdapter = class {
5762
5725
  skipPythUpdate: options?.skipPythUpdate
5763
5726
  });
5764
5727
  }
5765
- async addSaveToTx(tx, address, coin, asset, options) {
5728
+ async addSaveToTx(tx, address, coin, asset) {
5729
+ const normalized = normalizeAsset(asset);
5730
+ return addSaveToTx(tx, this.client, address, coin, { asset: normalized });
5731
+ }
5732
+ async addBorrowToTx(tx, address, amount, asset, options) {
5766
5733
  const normalized = normalizeAsset(asset);
5767
- return addSaveToTx(tx, this.client, address, coin, { ...options, asset: normalized });
5734
+ return addBorrowToTx(tx, this.client, address, amount, {
5735
+ asset: normalized,
5736
+ skipPythUpdate: options?.skipPythUpdate
5737
+ });
5768
5738
  }
5769
5739
  async addRepayToTx(tx, address, coin, asset, options) {
5770
5740
  const normalized = normalizeAsset(asset);
@@ -6218,7 +6188,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6218
6188
  // -- Swap --
6219
6189
  async swap(params) {
6220
6190
  this.enforcer.assertNotLocked();
6221
- const { findSwapRoute: findSwapRoute2, buildSwapTx: buildSwapTx2, resolveTokenType: resolveTokenType2, TOKEN_MAP: TOKEN_MAP2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
6191
+ const { findSwapRoute: findSwapRoute2, buildSwapTx: buildSwapTx2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
6222
6192
  const fromType = resolveTokenType2(params.from);
6223
6193
  const toType = resolveTokenType2(params.to);
6224
6194
  if (!fromType) throw new exports.T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.from}. Provide the full coin type.`);
@@ -6319,7 +6289,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6319
6289
  };
6320
6290
  }
6321
6291
  async swapQuote(params) {
6322
- const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2, TOKEN_MAP: TOKEN_MAP2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
6292
+ const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
6323
6293
  const fromType = resolveTokenType2(params.from);
6324
6294
  const toType = resolveTokenType2(params.to);
6325
6295
  if (!fromType) throw new exports.T2000Error("ASSET_NOT_SUPPORTED", `Unknown token: ${params.from}. Provide the full coin type.`);
@@ -6506,7 +6476,6 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6506
6476
  );
6507
6477
  }
6508
6478
  }
6509
- const fee = calculateFee("save", amount);
6510
6479
  const saveAmount = amount;
6511
6480
  const adapter = await this.resolveLending(params.protocol, asset, "save");
6512
6481
  const canPTB = !!adapter.addSaveToTx;
@@ -6519,14 +6488,13 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6519
6488
  const merged = this._mergeCoinsInTx(tx2, coins);
6520
6489
  const rawAmount = BigInt(Math.floor(saveAmount * 10 ** assetInfo.decimals));
6521
6490
  const [inputCoin] = tx2.splitCoins(merged, [rawAmount]);
6522
- await adapter.addSaveToTx(tx2, this._address, inputCoin, asset, { collectFee: true });
6491
+ await adapter.addSaveToTx(tx2, this._address, inputCoin, asset);
6523
6492
  return tx2;
6524
6493
  }
6525
- const { tx } = await adapter.buildSaveTx(this._address, saveAmount, asset, { collectFee: true });
6494
+ const { tx } = await adapter.buildSaveTx(this._address, saveAmount, asset);
6526
6495
  return tx;
6527
6496
  });
6528
6497
  const rates = await adapter.getRates(asset);
6529
- reportFee(this._address, "save", fee.amount, fee.rate, gasResult.digest);
6530
6498
  this.emitBalanceChange(asset, saveAmount, "save", gasResult.digest);
6531
6499
  let savingsBalance = saveAmount;
6532
6500
  for (let attempt = 0; attempt < 3; attempt++) {
@@ -6546,7 +6514,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6546
6514
  tx: gasResult.digest,
6547
6515
  amount: saveAmount,
6548
6516
  apy: rates.saveApy,
6549
- fee: fee.amount,
6517
+ fee: 0,
6550
6518
  gasCost: gasResult.gasCostSui,
6551
6519
  savingsBalance
6552
6520
  };
@@ -6809,21 +6777,19 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6809
6777
  currentHF: maxResult.currentHF
6810
6778
  });
6811
6779
  }
6812
- const fee = calculateFee("borrow", params.amount);
6813
6780
  const borrowAmount = params.amount;
6814
6781
  const gasResult = await executeTx(this.client, this._signer, async () => {
6815
- const { tx } = await adapter.buildBorrowTx(this._address, borrowAmount, asset, { collectFee: true });
6782
+ const { tx } = await adapter.buildBorrowTx(this._address, borrowAmount, asset);
6816
6783
  return tx;
6817
6784
  });
6818
6785
  const hf = await adapter.getHealth(this._address);
6819
- reportFee(this._address, "borrow", fee.amount, fee.rate, gasResult.digest);
6820
6786
  this.emitBalanceChange(asset, borrowAmount, "borrow", gasResult.digest);
6821
6787
  return {
6822
6788
  success: true,
6823
6789
  tx: gasResult.digest,
6824
6790
  amount: borrowAmount,
6825
6791
  asset,
6826
- fee: fee.amount,
6792
+ fee: 0,
6827
6793
  healthFactor: hf.healthFactor,
6828
6794
  gasCost: gasResult.gasCostSui
6829
6795
  };
@@ -7096,7 +7062,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7096
7062
  if (coins.length === 0) throw new exports.T2000Error("INSUFFICIENT_BALANCE", "No USDC coins after swap");
7097
7063
  const merged = this._mergeCoinsInTx(tx, coins);
7098
7064
  const [inputCoin] = tx.splitCoins(merged, [gainedRaw]);
7099
- await adapter.addSaveToTx(tx, this._address, inputCoin, "USDC", { collectFee: false });
7065
+ await adapter.addSaveToTx(tx, this._address, inputCoin, "USDC");
7100
7066
  return tx;
7101
7067
  });
7102
7068
  depositTx = depositResult.digest;
@@ -7224,6 +7190,37 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7224
7190
  // src/index.ts
7225
7191
  init_errors();
7226
7192
 
7193
+ // src/protocols/protocolFee.ts
7194
+ var FEE_RATES = {
7195
+ save: SAVE_FEE_BPS,
7196
+ borrow: BORROW_FEE_BPS,
7197
+ // Swap uses Cetus's overlay-fee mechanism (taken from output by the aggregator
7198
+ // and transferred to `overlayFee.receiver`). We list the rate here for display
7199
+ // / quote calculations only — `addFeeTransfer` is NOT called for swaps.
7200
+ swap: 10n
7201
+ // 0.1%
7202
+ };
7203
+ function calculateFee(operation, amount) {
7204
+ const bps = FEE_RATES[operation];
7205
+ const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
7206
+ const rawAmount = usdcToRaw(feeAmount);
7207
+ return {
7208
+ amount: feeAmount,
7209
+ asset: "USDC",
7210
+ rate: Number(bps) / Number(BPS_DENOMINATOR),
7211
+ rawAmount
7212
+ };
7213
+ }
7214
+ function addFeeTransfer(tx, paymentCoin, feeBps, receiver, amount) {
7215
+ if (feeBps <= 0n) return;
7216
+ if (amount <= 0) return;
7217
+ const feeAmount = amount * Number(feeBps) / Number(BPS_DENOMINATOR);
7218
+ const rawFee = usdcToRaw(feeAmount);
7219
+ if (rawFee <= 0n) return;
7220
+ const [feeCoin] = tx.splitCoins(paymentCoin, [tx.pure.u64(rawFee)]);
7221
+ tx.transferObjects([feeCoin], tx.pure.address(receiver));
7222
+ }
7223
+
7227
7224
  // src/protocols/financialSummary.ts
7228
7225
  var HF_WARN_THRESHOLD = 1.8;
7229
7226
  var HF_CRITICAL_THRESHOLD = 1.3;
@@ -7365,7 +7362,7 @@ function parseMoveAbort(errorStr) {
7365
7362
  // src/swap-quote.ts
7366
7363
  init_token_registry();
7367
7364
  async function getSwapQuote(params) {
7368
- const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2, TOKEN_MAP: TOKEN_MAP2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
7365
+ const { findSwapRoute: findSwapRoute2, resolveTokenType: resolveTokenType2 } = await Promise.resolve().then(() => (init_cetus_swap(), cetus_swap_exports));
7369
7366
  const fromType = resolveTokenType2(params.from);
7370
7367
  const toType = resolveTokenType2(params.to);
7371
7368
  if (!fromType) throw new Error(`Unknown token: ${params.from}. Provide the full coin type.`);
@@ -7432,9 +7429,10 @@ exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
7432
7429
  exports.SafeguardEnforcer = SafeguardEnforcer;
7433
7430
  exports.SafeguardError = SafeguardError;
7434
7431
  exports.T2000 = T2000;
7432
+ exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
7435
7433
  exports.USDC_DECIMALS = USDC_DECIMALS;
7436
7434
  exports.ZkLoginSigner = ZkLoginSigner;
7437
- exports.addCollectFeeToTx = addCollectFeeToTx;
7435
+ exports.addFeeTransfer = addFeeTransfer;
7438
7436
  exports.allDescriptors = allDescriptors;
7439
7437
  exports.assertAllowedAsset = assertAllowedAsset;
7440
7438
  exports.buildStakeVSuiTx = buildStakeVSuiTx;
@@ -7455,6 +7453,7 @@ exports.formatSui = formatSui;
7455
7453
  exports.formatUsd = formatUsd;
7456
7454
  exports.generateKeypair = generateKeypair;
7457
7455
  exports.getAddress = getAddress;
7456
+ exports.getCoinMeta = getCoinMeta;
7458
7457
  exports.getDecimals = getDecimals;
7459
7458
  exports.getDecimalsForCoinType = getDecimalsForCoinType;
7460
7459
  exports.getFinancialSummary = getFinancialSummary;
@@ -7464,6 +7463,7 @@ exports.getSwapQuote = getSwapQuote;
7464
7463
  exports.getTier = getTier;
7465
7464
  exports.getVoloStats = getVoloStats;
7466
7465
  exports.isAllowedAsset = isAllowedAsset;
7466
+ exports.isInRegistry = isInRegistry;
7467
7467
  exports.isSupported = isSupported;
7468
7468
  exports.isTier1 = isTier1;
7469
7469
  exports.isTier2 = isTier2;