@t2000/sdk 1.0.0 → 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, {
@@ -5311,7 +5260,7 @@ async function buildWithdrawTx(client, address, amount, options = {}) {
5311
5260
  }
5312
5261
  const tx = new transactions.Transaction();
5313
5262
  tx.setSender(address);
5314
- await refreshOracle(tx, client, address);
5263
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5315
5264
  try {
5316
5265
  const coin = await Qe(tx, assetInfo.type, rawAmount, sdkOptions(client));
5317
5266
  tx.transferObjects([coin], address);
@@ -5340,7 +5289,7 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
5340
5289
  });
5341
5290
  return { coin, effectiveAmount: 0 };
5342
5291
  }
5343
- await refreshOracle(tx, client, address);
5292
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5344
5293
  try {
5345
5294
  const coin = await Qe(tx, assetInfo.type, rawAmount, sdkOptions(client));
5346
5295
  return { coin, effectiveAmount };
@@ -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) {
@@ -5365,7 +5311,7 @@ async function addSaveToTx(tx, _client, _address, coin, options = {}) {
5365
5311
  async function addRepayToTx(tx, client, address, coin, options = {}) {
5366
5312
  const asset = options.asset ?? "USDC";
5367
5313
  const assetInfo = resolveAssetInfo(asset);
5368
- await refreshOracle(tx, client, address);
5314
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
5369
5315
  try {
5370
5316
  await xe(tx, assetInfo.type, coin, { env: "prod" });
5371
5317
  } catch (err) {
@@ -5382,12 +5328,9 @@ async function buildBorrowTx(client, address, amount, options = {}) {
5382
5328
  const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
5383
5329
  const tx = new transactions.Transaction();
5384
5330
  tx.setSender(address);
5385
- await refreshOracle(tx, client, address);
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");
@@ -5413,7 +5372,10 @@ async function buildRepayTx(client, address, amount, options = {}) {
5413
5372
  const coinObj = mergeCoins(tx, coins);
5414
5373
  const rawAmount = Math.min(rawRequested, Number(totalBalance));
5415
5374
  const [repayCoin] = tx.splitCoins(coinObj, [rawAmount]);
5416
- await refreshOracle(tx, client, address, { skipOracle: options.skipOracle });
5375
+ await refreshOracle(tx, client, address, {
5376
+ skipOracle: options.skipOracle,
5377
+ skipPythUpdate: options.skipPythUpdate
5378
+ });
5417
5379
  try {
5418
5380
  await xe(tx, assetInfo.type, repayCoin, {
5419
5381
  ...sdkOptions(client),
@@ -5719,14 +5681,17 @@ var NaviAdapter = class {
5719
5681
  async getHealth(address) {
5720
5682
  return getHealthFactor(this.client, address);
5721
5683
  }
5722
- async buildSaveTx(address, amount, asset, options) {
5684
+ async buildSaveTx(address, amount, asset) {
5723
5685
  const normalized = normalizeAsset(asset);
5724
- const tx = await buildSaveTx(this.client, address, amount, { ...options, asset: normalized });
5686
+ const tx = await buildSaveTx(this.client, address, amount, { asset: normalized });
5725
5687
  return { tx };
5726
5688
  }
5727
- async buildWithdrawTx(address, amount, asset) {
5689
+ async buildWithdrawTx(address, amount, asset, options) {
5728
5690
  const normalized = normalizeAsset(asset);
5729
- const result = await buildWithdrawTx(this.client, address, amount, { asset: normalized });
5691
+ const result = await buildWithdrawTx(this.client, address, amount, {
5692
+ asset: normalized,
5693
+ skipPythUpdate: options?.skipPythUpdate
5694
+ });
5730
5695
  return { tx: result.tx, effectiveAmount: result.effectiveAmount };
5731
5696
  }
5732
5697
  async buildBorrowTx(address, amount, asset, options) {
@@ -5738,7 +5703,8 @@ var NaviAdapter = class {
5738
5703
  const normalized = normalizeAsset(asset);
5739
5704
  const tx = await buildRepayTx(this.client, address, amount, {
5740
5705
  asset: normalized,
5741
- skipOracle: options?.skipOracle
5706
+ skipOracle: options?.skipOracle,
5707
+ skipPythUpdate: options?.skipPythUpdate
5742
5708
  });
5743
5709
  return { tx };
5744
5710
  }
@@ -5748,17 +5714,30 @@ var NaviAdapter = class {
5748
5714
  async maxBorrow(address, _asset) {
5749
5715
  return maxBorrowAmount(this.client, address);
5750
5716
  }
5751
- async addWithdrawToTx(tx, address, amount, asset) {
5717
+ async addWithdrawToTx(tx, address, amount, asset, options) {
5752
5718
  const normalized = normalizeAsset(asset);
5753
- return addWithdrawToTx(tx, this.client, address, amount, { asset: normalized });
5719
+ return addWithdrawToTx(tx, this.client, address, amount, {
5720
+ asset: normalized,
5721
+ skipPythUpdate: options?.skipPythUpdate
5722
+ });
5754
5723
  }
5755
- async addSaveToTx(tx, address, coin, asset, options) {
5724
+ async addSaveToTx(tx, address, coin, asset) {
5756
5725
  const normalized = normalizeAsset(asset);
5757
- return addSaveToTx(tx, this.client, address, coin, { ...options, asset: normalized });
5726
+ return addSaveToTx(tx, this.client, address, coin, { asset: normalized });
5758
5727
  }
5759
- async addRepayToTx(tx, address, coin, asset) {
5728
+ async addBorrowToTx(tx, address, amount, asset, options) {
5760
5729
  const normalized = normalizeAsset(asset);
5761
- return addRepayToTx(tx, this.client, address, coin, { asset: normalized });
5730
+ return addBorrowToTx(tx, this.client, address, amount, {
5731
+ asset: normalized,
5732
+ skipPythUpdate: options?.skipPythUpdate
5733
+ });
5734
+ }
5735
+ async addRepayToTx(tx, address, coin, asset, options) {
5736
+ const normalized = normalizeAsset(asset);
5737
+ return addRepayToTx(tx, this.client, address, coin, {
5738
+ asset: normalized,
5739
+ skipPythUpdate: options?.skipPythUpdate
5740
+ });
5762
5741
  }
5763
5742
  async getPendingRewards(address) {
5764
5743
  return getPendingRewards(this.client, address);
@@ -6493,7 +6472,6 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6493
6472
  );
6494
6473
  }
6495
6474
  }
6496
- const fee = calculateFee("save", amount);
6497
6475
  const saveAmount = amount;
6498
6476
  const adapter = await this.resolveLending(params.protocol, asset, "save");
6499
6477
  const canPTB = !!adapter.addSaveToTx;
@@ -6506,14 +6484,13 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6506
6484
  const merged = this._mergeCoinsInTx(tx2, coins);
6507
6485
  const rawAmount = BigInt(Math.floor(saveAmount * 10 ** assetInfo.decimals));
6508
6486
  const [inputCoin] = tx2.splitCoins(merged, [rawAmount]);
6509
- await adapter.addSaveToTx(tx2, this._address, inputCoin, asset, { collectFee: true });
6487
+ await adapter.addSaveToTx(tx2, this._address, inputCoin, asset);
6510
6488
  return tx2;
6511
6489
  }
6512
- const { tx } = await adapter.buildSaveTx(this._address, saveAmount, asset, { collectFee: true });
6490
+ const { tx } = await adapter.buildSaveTx(this._address, saveAmount, asset);
6513
6491
  return tx;
6514
6492
  });
6515
6493
  const rates = await adapter.getRates(asset);
6516
- reportFee(this._address, "save", fee.amount, fee.rate, gasResult.digest);
6517
6494
  this.emitBalanceChange(asset, saveAmount, "save", gasResult.digest);
6518
6495
  let savingsBalance = saveAmount;
6519
6496
  for (let attempt = 0; attempt < 3; attempt++) {
@@ -6533,7 +6510,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6533
6510
  tx: gasResult.digest,
6534
6511
  amount: saveAmount,
6535
6512
  apy: rates.saveApy,
6536
- fee: fee.amount,
6513
+ fee: 0,
6537
6514
  gasCost: gasResult.gasCostSui,
6538
6515
  savingsBalance
6539
6516
  };
@@ -6796,21 +6773,19 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
6796
6773
  currentHF: maxResult.currentHF
6797
6774
  });
6798
6775
  }
6799
- const fee = calculateFee("borrow", params.amount);
6800
6776
  const borrowAmount = params.amount;
6801
6777
  const gasResult = await executeTx(this.client, this._signer, async () => {
6802
- const { tx } = await adapter.buildBorrowTx(this._address, borrowAmount, asset, { collectFee: true });
6778
+ const { tx } = await adapter.buildBorrowTx(this._address, borrowAmount, asset);
6803
6779
  return tx;
6804
6780
  });
6805
6781
  const hf = await adapter.getHealth(this._address);
6806
- reportFee(this._address, "borrow", fee.amount, fee.rate, gasResult.digest);
6807
6782
  this.emitBalanceChange(asset, borrowAmount, "borrow", gasResult.digest);
6808
6783
  return {
6809
6784
  success: true,
6810
6785
  tx: gasResult.digest,
6811
6786
  amount: borrowAmount,
6812
6787
  asset,
6813
- fee: fee.amount,
6788
+ fee: 0,
6814
6789
  healthFactor: hf.healthFactor,
6815
6790
  gasCost: gasResult.gasCostSui
6816
6791
  };
@@ -7083,7 +7058,7 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7083
7058
  if (coins.length === 0) throw new exports.T2000Error("INSUFFICIENT_BALANCE", "No USDC coins after swap");
7084
7059
  const merged = this._mergeCoinsInTx(tx, coins);
7085
7060
  const [inputCoin] = tx.splitCoins(merged, [gainedRaw]);
7086
- await adapter.addSaveToTx(tx, this._address, inputCoin, "USDC", { collectFee: false });
7061
+ await adapter.addSaveToTx(tx, this._address, inputCoin, "USDC");
7087
7062
  return tx;
7088
7063
  });
7089
7064
  depositTx = depositResult.digest;
@@ -7211,6 +7186,37 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7211
7186
  // src/index.ts
7212
7187
  init_errors();
7213
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
+
7214
7220
  // src/protocols/financialSummary.ts
7215
7221
  var HF_WARN_THRESHOLD = 1.8;
7216
7222
  var HF_CRITICAL_THRESHOLD = 1.3;
@@ -7419,9 +7425,10 @@ exports.SUPPORTED_ASSETS = SUPPORTED_ASSETS;
7419
7425
  exports.SafeguardEnforcer = SafeguardEnforcer;
7420
7426
  exports.SafeguardError = SafeguardError;
7421
7427
  exports.T2000 = T2000;
7428
+ exports.T2000_OVERLAY_FEE_WALLET = T2000_OVERLAY_FEE_WALLET;
7422
7429
  exports.USDC_DECIMALS = USDC_DECIMALS;
7423
7430
  exports.ZkLoginSigner = ZkLoginSigner;
7424
- exports.addCollectFeeToTx = addCollectFeeToTx;
7431
+ exports.addFeeTransfer = addFeeTransfer;
7425
7432
  exports.allDescriptors = allDescriptors;
7426
7433
  exports.assertAllowedAsset = assertAllowedAsset;
7427
7434
  exports.buildStakeVSuiTx = buildStakeVSuiTx;