@t2000/sdk 1.0.1 → 1.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/index.cjs CHANGED
@@ -728,18 +728,22 @@ __export(cetus_swap_exports, {
728
728
  resolveTokenType: () => resolveTokenType,
729
729
  simulateSwap: () => simulateSwap
730
730
  });
731
- function getClient(walletAddress) {
732
- if (clientInstance) return clientInstance;
733
- clientInstance = new aggregatorSdk.AggregatorClient({
731
+ function getClient(walletAddress, overlayFee) {
732
+ const rate = overlayFee?.rate ?? 0;
733
+ const receiver = overlayFee?.receiver ?? "";
734
+ const key = `${walletAddress}|${rate}|${receiver}`;
735
+ const cached = clientCache.get(key);
736
+ if (cached) return cached;
737
+ const client = new aggregatorSdk.AggregatorClient({
734
738
  signer: walletAddress,
735
739
  env: aggregatorSdk.Env.Mainnet,
736
- overlayFeeRate: exports.OVERLAY_FEE_RATE,
737
- overlayFeeReceiver: OVERLAY_FEE_RECEIVER
740
+ ...rate > 0 && receiver ? { overlayFeeRate: rate, overlayFeeReceiver: receiver } : {}
738
741
  });
739
- return clientInstance;
742
+ clientCache.set(key, client);
743
+ return client;
740
744
  }
741
745
  async function findSwapRoute(params) {
742
- const client = getClient(params.walletAddress);
746
+ const client = getClient(params.walletAddress, params.overlayFee);
743
747
  const findParams = {
744
748
  from: params.from,
745
749
  target: params.to,
@@ -776,7 +780,7 @@ function normalizePriceImpact(value) {
776
780
  return Number.isFinite(n) ? n : 0;
777
781
  }
778
782
  async function buildSwapTx(params) {
779
- const client = getClient(params.walletAddress);
783
+ const client = getClient(params.walletAddress, params.overlayFee);
780
784
  const clampedSlippage = Math.max(1e-3, Math.min(params.slippage, 0.05));
781
785
  const outputCoin = await client.routerSwap({
782
786
  router: params.route.routerData,
@@ -787,7 +791,7 @@ async function buildSwapTx(params) {
787
791
  return outputCoin;
788
792
  }
789
793
  async function simulateSwap(params) {
790
- const client = getClient(params.walletAddress);
794
+ const client = getClient(params.walletAddress, params.overlayFee);
791
795
  try {
792
796
  await client.devInspectTransactionBlock(params.tx);
793
797
  return { success: true };
@@ -795,13 +799,12 @@ async function simulateSwap(params) {
795
799
  return { success: false, error: err instanceof Error ? err.message : String(err) };
796
800
  }
797
801
  }
798
- exports.OVERLAY_FEE_RATE = void 0; var OVERLAY_FEE_RECEIVER, clientInstance;
802
+ exports.OVERLAY_FEE_RATE = void 0; var clientCache;
799
803
  var init_cetus_swap = __esm({
800
804
  "src/protocols/cetus-swap.ts"() {
801
805
  init_token_registry();
802
806
  exports.OVERLAY_FEE_RATE = 1e-3;
803
- OVERLAY_FEE_RECEIVER = process.env.T2000_TREASURY_ADDRESS ?? "0x3bb501b8300125dca59019247941a42af6b292a150ce3cfcce9449456be2ec91";
804
- clientInstance = null;
807
+ clientCache = /* @__PURE__ */ new Map();
805
808
  }
806
809
  });
807
810
 
@@ -897,13 +900,13 @@ function assertAllowedAsset(op, asset) {
897
900
  );
898
901
  }
899
902
  }
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";
903
+ process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
904
+ process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
905
+ var T2000_OVERLAY_FEE_WALLET = process.env.T2000_OVERLAY_FEE_WALLET ?? "0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a";
903
906
  var DEFAULT_NETWORK = "mainnet";
904
907
  var DEFAULT_RPC_URL = "https://fullnode.mainnet.sui.io:443";
905
908
  var DEFAULT_KEY_PATH = "~/.t2000/wallet.key";
906
- var API_BASE_URL = process.env.T2000_API_URL ?? "https://api.t2000.ai";
909
+ process.env.T2000_API_URL ?? "https://api.t2000.ai";
907
910
  var CETUS_USDC_SUI_POOL = "0x51e883ba7c0b566a26cbc8a94cd33eb0abd418a77cc1e60ad22fd9b1f29cd2ab";
908
911
  var GAS_RESERVE_MIN = 0.05;
909
912
 
@@ -1445,57 +1448,6 @@ function extractCommands(txBlock) {
1445
1448
  // src/t2000.ts
1446
1449
  init_token_registry();
1447
1450
 
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
1451
  // ../../node_modules/.pnpm/@mysten+bcs@2.0.2/node_modules/@mysten/bcs/dist/uleb.mjs
1500
1452
  function ulebEncode(num) {
1501
1453
  let bigNum = BigInt(num);
@@ -5279,9 +5231,6 @@ async function buildSaveTx(client, address, amount, options = {}) {
5279
5231
  const tx = new transactions.Transaction();
5280
5232
  tx.setSender(address);
5281
5233
  const coinObj = mergeCoins(tx, coins);
5282
- if (options.collectFee) {
5283
- addCollectFeeToTx(tx, coinObj, "save");
5284
- }
5285
5234
  const rawAmount = Math.min(Number(stableToRaw(amount, assetInfo.decimals)), Number(totalBalance));
5286
5235
  try {
5287
5236
  await Ce(tx, assetInfo.type, coinObj, {
@@ -5352,9 +5301,6 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
5352
5301
  async function addSaveToTx(tx, _client, _address, coin, options = {}) {
5353
5302
  const asset = options.asset ?? "USDC";
5354
5303
  const assetInfo = resolveAssetInfo(asset);
5355
- if (options.collectFee) {
5356
- addCollectFeeToTx(tx, coin, "save");
5357
- }
5358
5304
  try {
5359
5305
  await Ce(tx, assetInfo.type, coin, { env: "prod" });
5360
5306
  } catch (err) {
@@ -5385,9 +5331,6 @@ async function buildBorrowTx(client, address, amount, options = {}) {
5385
5331
  await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5386
5332
  try {
5387
5333
  const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
5388
- if (options.collectFee) {
5389
- addCollectFeeToTx(tx, borrowedCoin, "borrow");
5390
- }
5391
5334
  tx.transferObjects([borrowedCoin], address);
5392
5335
  } catch (err) {
5393
5336
  const msg = err instanceof Error ? err.message : String(err);
@@ -5395,6 +5338,22 @@ async function buildBorrowTx(client, address, amount, options = {}) {
5395
5338
  }
5396
5339
  return tx;
5397
5340
  }
5341
+ async function addBorrowToTx(tx, client, address, amount, options = {}) {
5342
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
5343
+ throw new exports.T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
5344
+ }
5345
+ const asset = options.asset ?? "USDC";
5346
+ const assetInfo = resolveAssetInfo(asset);
5347
+ const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
5348
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5349
+ try {
5350
+ const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
5351
+ return borrowedCoin;
5352
+ } catch (err) {
5353
+ const msg = err instanceof Error ? err.message : String(err);
5354
+ throw new exports.T2000Error("PROTOCOL_UNAVAILABLE", `NAVI borrow failed: ${msg}`);
5355
+ }
5356
+ }
5398
5357
  async function buildRepayTx(client, address, amount, options = {}) {
5399
5358
  if (!amount || amount <= 0 || !Number.isFinite(amount)) {
5400
5359
  throw new exports.T2000Error("INVALID_AMOUNT", "Repay amount must be a positive number");
@@ -5722,9 +5681,9 @@ var NaviAdapter = class {
5722
5681
  async getHealth(address) {
5723
5682
  return getHealthFactor(this.client, address);
5724
5683
  }
5725
- async buildSaveTx(address, amount, asset, options) {
5684
+ async buildSaveTx(address, amount, asset) {
5726
5685
  const normalized = normalizeAsset(asset);
5727
- const tx = await buildSaveTx(this.client, address, amount, { ...options, asset: normalized });
5686
+ const tx = await buildSaveTx(this.client, address, amount, { asset: normalized });
5728
5687
  return { tx };
5729
5688
  }
5730
5689
  async buildWithdrawTx(address, amount, asset, options) {
@@ -5762,9 +5721,16 @@ var NaviAdapter = class {
5762
5721
  skipPythUpdate: options?.skipPythUpdate
5763
5722
  });
5764
5723
  }
5765
- async addSaveToTx(tx, address, coin, asset, options) {
5724
+ async addSaveToTx(tx, address, coin, asset) {
5725
+ const normalized = normalizeAsset(asset);
5726
+ return addSaveToTx(tx, this.client, address, coin, { asset: normalized });
5727
+ }
5728
+ async addBorrowToTx(tx, address, amount, asset, options) {
5766
5729
  const normalized = normalizeAsset(asset);
5767
- return addSaveToTx(tx, this.client, address, coin, { ...options, asset: normalized });
5730
+ return addBorrowToTx(tx, this.client, address, amount, {
5731
+ asset: normalized,
5732
+ skipPythUpdate: options?.skipPythUpdate
5733
+ });
5768
5734
  }
5769
5735
  async addRepayToTx(tx, address, coin, asset, options) {
5770
5736
  const normalized = normalizeAsset(asset);
@@ -6506,7 +6472,6 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6506
6472
  );
6507
6473
  }
6508
6474
  }
6509
- const fee = calculateFee("save", amount);
6510
6475
  const saveAmount = amount;
6511
6476
  const adapter = await this.resolveLending(params.protocol, asset, "save");
6512
6477
  const canPTB = !!adapter.addSaveToTx;
@@ -6519,14 +6484,13 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6519
6484
  const merged = this._mergeCoinsInTx(tx2, coins);
6520
6485
  const rawAmount = BigInt(Math.floor(saveAmount * 10 ** assetInfo.decimals));
6521
6486
  const [inputCoin] = tx2.splitCoins(merged, [rawAmount]);
6522
- await adapter.addSaveToTx(tx2, this._address, inputCoin, asset, { collectFee: true });
6487
+ await adapter.addSaveToTx(tx2, this._address, inputCoin, asset);
6523
6488
  return tx2;
6524
6489
  }
6525
- const { tx } = await adapter.buildSaveTx(this._address, saveAmount, asset, { collectFee: true });
6490
+ const { tx } = await adapter.buildSaveTx(this._address, saveAmount, asset);
6526
6491
  return tx;
6527
6492
  });
6528
6493
  const rates = await adapter.getRates(asset);
6529
- reportFee(this._address, "save", fee.amount, fee.rate, gasResult.digest);
6530
6494
  this.emitBalanceChange(asset, saveAmount, "save", gasResult.digest);
6531
6495
  let savingsBalance = saveAmount;
6532
6496
  for (let attempt = 0; attempt < 3; attempt++) {
@@ -6546,7 +6510,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6546
6510
  tx: gasResult.digest,
6547
6511
  amount: saveAmount,
6548
6512
  apy: rates.saveApy,
6549
- fee: fee.amount,
6513
+ fee: 0,
6550
6514
  gasCost: gasResult.gasCostSui,
6551
6515
  savingsBalance
6552
6516
  };
@@ -6809,21 +6773,19 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6809
6773
  currentHF: maxResult.currentHF
6810
6774
  });
6811
6775
  }
6812
- const fee = calculateFee("borrow", params.amount);
6813
6776
  const borrowAmount = params.amount;
6814
6777
  const gasResult = await executeTx(this.client, this._signer, async () => {
6815
- const { tx } = await adapter.buildBorrowTx(this._address, borrowAmount, asset, { collectFee: true });
6778
+ const { tx } = await adapter.buildBorrowTx(this._address, borrowAmount, asset);
6816
6779
  return tx;
6817
6780
  });
6818
6781
  const hf = await adapter.getHealth(this._address);
6819
- reportFee(this._address, "borrow", fee.amount, fee.rate, gasResult.digest);
6820
6782
  this.emitBalanceChange(asset, borrowAmount, "borrow", gasResult.digest);
6821
6783
  return {
6822
6784
  success: true,
6823
6785
  tx: gasResult.digest,
6824
6786
  amount: borrowAmount,
6825
6787
  asset,
6826
- fee: fee.amount,
6788
+ fee: 0,
6827
6789
  healthFactor: hf.healthFactor,
6828
6790
  gasCost: gasResult.gasCostSui
6829
6791
  };
@@ -7096,7 +7058,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7096
7058
  if (coins.length === 0) throw new exports.T2000Error("INSUFFICIENT_BALANCE", "No USDC coins after swap");
7097
7059
  const merged = this._mergeCoinsInTx(tx, coins);
7098
7060
  const [inputCoin] = tx.splitCoins(merged, [gainedRaw]);
7099
- await adapter.addSaveToTx(tx, this._address, inputCoin, "USDC", { collectFee: false });
7061
+ await adapter.addSaveToTx(tx, this._address, inputCoin, "USDC");
7100
7062
  return tx;
7101
7063
  });
7102
7064
  depositTx = depositResult.digest;
@@ -7224,6 +7186,37 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7224
7186
  // src/index.ts
7225
7187
  init_errors();
7226
7188
 
7189
+ // src/protocols/protocolFee.ts
7190
+ var FEE_RATES = {
7191
+ save: SAVE_FEE_BPS,
7192
+ borrow: BORROW_FEE_BPS,
7193
+ // Swap uses Cetus's overlay-fee mechanism (taken from output by the aggregator
7194
+ // and transferred to `overlayFee.receiver`). We list the rate here for display
7195
+ // / quote calculations only — `addFeeTransfer` is NOT called for swaps.
7196
+ swap: 10n
7197
+ // 0.1%
7198
+ };
7199
+ function calculateFee(operation, amount) {
7200
+ const bps = FEE_RATES[operation];
7201
+ const feeAmount = amount * Number(bps) / Number(BPS_DENOMINATOR);
7202
+ const rawAmount = usdcToRaw(feeAmount);
7203
+ return {
7204
+ amount: feeAmount,
7205
+ asset: "USDC",
7206
+ rate: Number(bps) / Number(BPS_DENOMINATOR),
7207
+ rawAmount
7208
+ };
7209
+ }
7210
+ function addFeeTransfer(tx, paymentCoin, feeBps, receiver, amount) {
7211
+ if (feeBps <= 0n) return;
7212
+ if (amount <= 0) return;
7213
+ const feeAmount = amount * Number(feeBps) / Number(BPS_DENOMINATOR);
7214
+ const rawFee = usdcToRaw(feeAmount);
7215
+ if (rawFee <= 0n) return;
7216
+ const [feeCoin] = tx.splitCoins(paymentCoin, [tx.pure.u64(rawFee)]);
7217
+ tx.transferObjects([feeCoin], tx.pure.address(receiver));
7218
+ }
7219
+
7227
7220
  // src/protocols/financialSummary.ts
7228
7221
  var HF_WARN_THRESHOLD = 1.8;
7229
7222
  var HF_CRITICAL_THRESHOLD = 1.3;
@@ -7432,9 +7425,10 @@ exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
7432
7425
  exports.SafeguardEnforcer = SafeguardEnforcer;
7433
7426
  exports.SafeguardError = SafeguardError;
7434
7427
  exports.T2000 = T2000;
7428
+ exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
7435
7429
  exports.USDC_DECIMALS = USDC_DECIMALS;
7436
7430
  exports.ZkLoginSigner = ZkLoginSigner;
7437
- exports.addCollectFeeToTx = addCollectFeeToTx;
7431
+ exports.addFeeTransfer = addFeeTransfer;
7438
7432
  exports.allDescriptors = allDescriptors;
7439
7433
  exports.assertAllowedAsset = assertAllowedAsset;
7440
7434
  exports.buildStakeVSuiTx = buildStakeVSuiTx;