@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/README.md CHANGED
@@ -277,7 +277,7 @@ isSupported(USDT_TYPE); // false (legacy — no tier)
277
277
  getTier(SUI_TYPE); // 2
278
278
  ```
279
279
 
280
- Swap uses Cetus Aggregator V3 (with a **0.1% t2000 overlay fee** on executed swaps). Use `COIN_REGISTRY`, `getDecimalsForCoinType()`, `resolveSymbol()`, and `resolveTokenType()` for token data.
280
+ Swap uses Cetus Aggregator V3. Per-call `overlayFee` is opt-in — the SDK and CLI never charge fees by default. Consumer apps that want to charge an overlay (e.g. Audric) pass `overlayFee: { rate: 10n, receiver: T2000_OVERLAY_FEE_WALLET }` to `findSwapRoute` / `buildSwapTx`. Use `COIN_REGISTRY`, `getDecimalsForCoinType()`, `resolveSymbol()`, and `resolveTokenType()` for token data.
281
281
 
282
282
  ## Error Handling
283
283
 
@@ -318,20 +318,20 @@ SMOKE=1 pnpm --filter @t2000/sdk test -- src/__smoke__
318
318
 
319
319
  ## Protocol Fees
320
320
 
321
- | Operation | Fee | Notes |
322
- |-----------|-----|-------|
323
- | Save (deposit) | 0.10% | Protocol fee on deposit |
324
- | Borrow | 0.05% | Protocol fee on loan |
325
- | Withdraw | Free | |
326
- | Repay | Free | |
327
- | Send | Free | |
328
- | Receive | Free | QR payment request generation, no fee |
329
- | Swap | 0.10% | t2000 overlay on swap amount; Cetus Aggregator network fees still apply |
330
- | Stake (vSUI) | Free | VOLO protocol fees only |
331
- | Unstake (vSUI) | Free | |
332
- | Pay (MPP) | Free | Agent pays the API price, no t2000 surcharge |
333
-
334
- Fees are collected by the t2000 protocol treasury on-chain.
321
+ > **The SDK and CLI are fee-free by design (as of `@t2000/sdk@1.1.0`, B5 v2 / 2026-04-30).** Direct SDK / CLI calls — `t2000 save`, `t2000 borrow`, `t2000 swap`, plus `T2000.save()` / `T2000.borrow()` / `swapExecute()` from any third-party integrator — never charge a t2000 protocol fee. The CLI is dev-focused tooling and intentionally has no monetization.
322
+
323
+ Fees only apply when the **Audric** consumer app calls these primitives. Audric layers a fee transfer step (`addFeeTransfer`) inside the same PTB and routes the USDC to `T2000_OVERLAY_FEE_WALLET`.
324
+
325
+ | Operation | Audric fee | SDK / CLI fee | Notes |
326
+ |-----------|-----------|--------------|-------|
327
+ | Save (deposit) | 0.10% | Free | USDC only; USDsui save is free in Audric too |
328
+ | Borrow | 0.05% | Free | USDC only; USDsui borrow is free in Audric too |
329
+ | Swap | 0.10% | Free | Audric passes Cetus `overlayFee`. CLI omits it. Cetus Aggregator network fees still apply both ways. |
330
+ | Withdraw / Repay / Send / Receive / Stake / Unstake / Pay (MPP) | Free | Free | No surcharge anywhere. |
331
+
332
+ How Audric collects fees: `prepare/route.ts` calls `addFeeTransfer(tx, paymentCoin, FEE_BPS, T2000_OVERLAY_FEE_WALLET, amount)` for save/borrow and passes `overlayFee.receiver = T2000_OVERLAY_FEE_WALLET` for swaps. Both flows produce a USDC transfer to the treasury wallet inside the same atomic PTB. The t2000 server-side indexer detects the on-chain USDC inflow and records a `ProtocolFeeLedger` row — no off-chain submission is involved. The deprecated `t2000::treasury::collect_fee` Move call is no longer used.
333
+
334
+ Need to charge an overlay fee in your own consumer app? Import `addFeeTransfer` and `T2000_OVERLAY_FEE_WALLET` from `@t2000/sdk` (or use your own receiver address — the SDK never assumes the t2000 treasury).
335
335
 
336
336
  ## MCP Server
337
337
 
@@ -1,3 +1,3 @@
1
- export { d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from '../descriptors-3YmGYl63.cjs';
1
+ export { d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from '../descriptors-BnbL3xN8.cjs';
2
2
  import '@mysten/sui/transactions';
3
3
  import '@mysten/sui/jsonRpc';
@@ -1,3 +1,3 @@
1
- export { d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from '../descriptors-3YmGYl63.js';
1
+ export { d as ProtocolDescriptor, e as allDescriptors, n as naviDescriptor } from '../descriptors-BnbL3xN8.js';
2
2
  import '@mysten/sui/transactions';
3
3
  import '@mysten/sui/jsonRpc';
@@ -432,8 +432,6 @@ var T2000Error = class extends Error {
432
432
  };
433
433
 
434
434
  // src/constants.ts
435
- var SAVE_FEE_BPS = 10n;
436
- var BORROW_FEE_BPS = 5n;
437
435
  var SUPPORTED_ASSETS = {
438
436
  USDC: {
439
437
  type: "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
@@ -492,9 +490,9 @@ var SUPPORTED_ASSETS = {
492
490
  };
493
491
  var STABLE_ASSETS = ["USDC"];
494
492
  var ALL_NAVI_ASSETS = Object.keys(SUPPORTED_ASSETS);
495
- var T2000_PACKAGE_ID = process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
496
- var T2000_CONFIG_ID = process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
497
- var T2000_TREASURY_ID = process.env.T2000_TREASURY_ID ?? "0xf420ec0dcad44433042fb56e1413fb88d3ff65be94fcf425ef9ff750164590e8";
493
+ process.env.T2000_PACKAGE_ID ?? "0xd775fcc66eae26797654d435d751dea56b82eeb999de51fd285348e573b968ad";
494
+ process.env.T2000_CONFIG_ID ?? "0x08ba26f0d260b5edf6a19c71492b3eb914906a7419baf2df1426765157e5862a";
495
+ process.env.T2000_OVERLAY_FEE_WALLET ?? "0x5366efbf2b4fe5767fe2e78eb197aa5f5d138d88ac3333fbf3f80a1927da473a";
498
496
  process.env.T2000_API_URL ?? "https://api.t2000.ai";
499
497
 
500
498
  // src/adapters/registry.ts
@@ -4231,30 +4229,6 @@ async function Ct(e, n, o) {
4231
4229
  return a;
4232
4230
  }
4233
4231
 
4234
- // src/protocols/protocolFee.ts
4235
- var FEE_RATES = {
4236
- save: SAVE_FEE_BPS,
4237
- borrow: BORROW_FEE_BPS
4238
- };
4239
- var OP_CODES = {
4240
- save: 0,
4241
- borrow: 2
4242
- };
4243
- function addCollectFeeToTx(tx, paymentCoin, operation) {
4244
- const bps = FEE_RATES[operation];
4245
- if (bps <= 0n) return;
4246
- tx.moveCall({
4247
- target: `${T2000_PACKAGE_ID}::treasury::collect_fee`,
4248
- typeArguments: [SUPPORTED_ASSETS.USDC.type],
4249
- arguments: [
4250
- tx.object(T2000_TREASURY_ID),
4251
- tx.object(T2000_CONFIG_ID),
4252
- paymentCoin,
4253
- tx.pure.u8(OP_CODES[operation])
4254
- ]
4255
- });
4256
- }
4257
-
4258
4232
  // src/protocols/navi.ts
4259
4233
  var MIN_HEALTH_FACTOR = 1.5;
4260
4234
  function sdkOptions(client) {
@@ -4435,9 +4409,6 @@ async function buildSaveTx(client, address, amount, options = {}) {
4435
4409
  const tx = new transactions.Transaction();
4436
4410
  tx.setSender(address);
4437
4411
  const coinObj = mergeCoins(tx, coins);
4438
- if (options.collectFee) {
4439
- addCollectFeeToTx(tx, coinObj, "save");
4440
- }
4441
4412
  const rawAmount = Math.min(Number(stableToRaw(amount, assetInfo.decimals)), Number(totalBalance));
4442
4413
  try {
4443
4414
  await Ce(tx, assetInfo.type, coinObj, {
@@ -4467,7 +4438,7 @@ async function buildWithdrawTx(client, address, amount, options = {}) {
4467
4438
  }
4468
4439
  const tx = new transactions.Transaction();
4469
4440
  tx.setSender(address);
4470
- await refreshOracle(tx, client, address);
4441
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
4471
4442
  try {
4472
4443
  const coin = await Qe(tx, assetInfo.type, rawAmount, sdkOptions(client));
4473
4444
  tx.transferObjects([coin], address);
@@ -4496,7 +4467,7 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
4496
4467
  });
4497
4468
  return { coin, effectiveAmount: 0 };
4498
4469
  }
4499
- await refreshOracle(tx, client, address);
4470
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
4500
4471
  try {
4501
4472
  const coin = await Qe(tx, assetInfo.type, rawAmount, sdkOptions(client));
4502
4473
  return { coin, effectiveAmount };
@@ -4508,9 +4479,6 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
4508
4479
  async function addSaveToTx(tx, _client, _address, coin, options = {}) {
4509
4480
  const asset = options.asset ?? "USDC";
4510
4481
  const assetInfo = resolveAssetInfo(asset);
4511
- if (options.collectFee) {
4512
- addCollectFeeToTx(tx, coin, "save");
4513
- }
4514
4482
  try {
4515
4483
  await Ce(tx, assetInfo.type, coin, { env: "prod" });
4516
4484
  } catch (err) {
@@ -4521,7 +4489,7 @@ async function addSaveToTx(tx, _client, _address, coin, options = {}) {
4521
4489
  async function addRepayToTx(tx, client, address, coin, options = {}) {
4522
4490
  const asset = options.asset ?? "USDC";
4523
4491
  const assetInfo = resolveAssetInfo(asset);
4524
- await refreshOracle(tx, client, address);
4492
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
4525
4493
  try {
4526
4494
  await xe(tx, assetInfo.type, coin, { env: "prod" });
4527
4495
  } catch (err) {
@@ -4538,12 +4506,9 @@ async function buildBorrowTx(client, address, amount, options = {}) {
4538
4506
  const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
4539
4507
  const tx = new transactions.Transaction();
4540
4508
  tx.setSender(address);
4541
- await refreshOracle(tx, client, address);
4509
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
4542
4510
  try {
4543
4511
  const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
4544
- if (options.collectFee) {
4545
- addCollectFeeToTx(tx, borrowedCoin, "borrow");
4546
- }
4547
4512
  tx.transferObjects([borrowedCoin], address);
4548
4513
  } catch (err) {
4549
4514
  const msg = err instanceof Error ? err.message : String(err);
@@ -4551,6 +4516,22 @@ async function buildBorrowTx(client, address, amount, options = {}) {
4551
4516
  }
4552
4517
  return tx;
4553
4518
  }
4519
+ async function addBorrowToTx(tx, client, address, amount, options = {}) {
4520
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
4521
+ throw new T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
4522
+ }
4523
+ const asset = options.asset ?? "USDC";
4524
+ const assetInfo = resolveAssetInfo(asset);
4525
+ const rawAmount = Number(stableToRaw(amount, assetInfo.decimals));
4526
+ await refreshOracle(tx, client, address, { skipPythUpdate: options.skipPythUpdate });
4527
+ try {
4528
+ const borrowedCoin = await Xe(tx, assetInfo.type, rawAmount, sdkOptions(client));
4529
+ return borrowedCoin;
4530
+ } catch (err) {
4531
+ const msg = err instanceof Error ? err.message : String(err);
4532
+ throw new T2000Error("PROTOCOL_UNAVAILABLE", `NAVI borrow failed: ${msg}`);
4533
+ }
4534
+ }
4554
4535
  async function buildRepayTx(client, address, amount, options = {}) {
4555
4536
  if (!amount || amount <= 0 || !Number.isFinite(amount)) {
4556
4537
  throw new T2000Error("INVALID_AMOUNT", "Repay amount must be a positive number");
@@ -4569,7 +4550,10 @@ async function buildRepayTx(client, address, amount, options = {}) {
4569
4550
  const coinObj = mergeCoins(tx, coins);
4570
4551
  const rawAmount = Math.min(rawRequested, Number(totalBalance));
4571
4552
  const [repayCoin] = tx.splitCoins(coinObj, [rawAmount]);
4572
- await refreshOracle(tx, client, address, { skipOracle: options.skipOracle });
4553
+ await refreshOracle(tx, client, address, {
4554
+ skipOracle: options.skipOracle,
4555
+ skipPythUpdate: options.skipPythUpdate
4556
+ });
4573
4557
  try {
4574
4558
  await xe(tx, assetInfo.type, repayCoin, {
4575
4559
  ...sdkOptions(client),
@@ -4727,14 +4711,17 @@ var NaviAdapter = class {
4727
4711
  async getHealth(address) {
4728
4712
  return getHealthFactor(this.client, address);
4729
4713
  }
4730
- async buildSaveTx(address, amount, asset, options) {
4714
+ async buildSaveTx(address, amount, asset) {
4731
4715
  const normalized = normalizeAsset(asset);
4732
- const tx = await buildSaveTx(this.client, address, amount, { ...options, asset: normalized });
4716
+ const tx = await buildSaveTx(this.client, address, amount, { asset: normalized });
4733
4717
  return { tx };
4734
4718
  }
4735
- async buildWithdrawTx(address, amount, asset) {
4719
+ async buildWithdrawTx(address, amount, asset, options) {
4736
4720
  const normalized = normalizeAsset(asset);
4737
- const result = await buildWithdrawTx(this.client, address, amount, { asset: normalized });
4721
+ const result = await buildWithdrawTx(this.client, address, amount, {
4722
+ asset: normalized,
4723
+ skipPythUpdate: options?.skipPythUpdate
4724
+ });
4738
4725
  return { tx: result.tx, effectiveAmount: result.effectiveAmount };
4739
4726
  }
4740
4727
  async buildBorrowTx(address, amount, asset, options) {
@@ -4746,7 +4733,8 @@ var NaviAdapter = class {
4746
4733
  const normalized = normalizeAsset(asset);
4747
4734
  const tx = await buildRepayTx(this.client, address, amount, {
4748
4735
  asset: normalized,
4749
- skipOracle: options?.skipOracle
4736
+ skipOracle: options?.skipOracle,
4737
+ skipPythUpdate: options?.skipPythUpdate
4750
4738
  });
4751
4739
  return { tx };
4752
4740
  }
@@ -4756,17 +4744,30 @@ var NaviAdapter = class {
4756
4744
  async maxBorrow(address, _asset) {
4757
4745
  return maxBorrowAmount(this.client, address);
4758
4746
  }
4759
- async addWithdrawToTx(tx, address, amount, asset) {
4747
+ async addWithdrawToTx(tx, address, amount, asset, options) {
4760
4748
  const normalized = normalizeAsset(asset);
4761
- return addWithdrawToTx(tx, this.client, address, amount, { asset: normalized });
4749
+ return addWithdrawToTx(tx, this.client, address, amount, {
4750
+ asset: normalized,
4751
+ skipPythUpdate: options?.skipPythUpdate
4752
+ });
4753
+ }
4754
+ async addSaveToTx(tx, address, coin, asset) {
4755
+ const normalized = normalizeAsset(asset);
4756
+ return addSaveToTx(tx, this.client, address, coin, { asset: normalized });
4762
4757
  }
4763
- async addSaveToTx(tx, address, coin, asset, options) {
4758
+ async addBorrowToTx(tx, address, amount, asset, options) {
4764
4759
  const normalized = normalizeAsset(asset);
4765
- return addSaveToTx(tx, this.client, address, coin, { ...options, asset: normalized });
4760
+ return addBorrowToTx(tx, this.client, address, amount, {
4761
+ asset: normalized,
4762
+ skipPythUpdate: options?.skipPythUpdate
4763
+ });
4766
4764
  }
4767
- async addRepayToTx(tx, address, coin, asset) {
4765
+ async addRepayToTx(tx, address, coin, asset, options) {
4768
4766
  const normalized = normalizeAsset(asset);
4769
- return addRepayToTx(tx, this.client, address, coin, { asset: normalized });
4767
+ return addRepayToTx(tx, this.client, address, coin, {
4768
+ asset: normalized,
4769
+ skipPythUpdate: options?.skipPythUpdate
4770
+ });
4770
4771
  }
4771
4772
  async getPendingRewards(address) {
4772
4773
  return getPendingRewards(this.client, address);