@t2000/sdk 0.6.0 → 0.6.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.js CHANGED
@@ -424,8 +424,6 @@ async function reportFee(agentAddress, operation, feeAmount, feeRate, txDigest)
424
424
  } catch {
425
425
  }
426
426
  }
427
-
428
- // src/protocols/navi.ts
429
427
  var USDC_TYPE = SUPPORTED_ASSETS.USDC.type;
430
428
  var RATE_DECIMALS = 27;
431
429
  var LTV_DECIMALS = 27;
@@ -495,6 +493,24 @@ async function getUsdcPool() {
495
493
  if (!usdc) throw new T2000Error("PROTOCOL_UNAVAILABLE", "USDC pool not found on NAVI");
496
494
  return usdc;
497
495
  }
496
+ function addOracleUpdate(tx, config, pool) {
497
+ const feed = config.oracle.feeds?.find((f2) => f2.assetId === pool.id);
498
+ if (!feed) {
499
+ throw new T2000Error("PROTOCOL_UNAVAILABLE", `Oracle feed not found for asset ${pool.token?.symbol ?? pool.id}`);
500
+ }
501
+ tx.moveCall({
502
+ target: `${config.oracle.packageId}::oracle_pro::update_single_price_v2`,
503
+ arguments: [
504
+ tx.object(CLOCK),
505
+ tx.object(config.oracle.oracleConfig),
506
+ tx.object(config.oracle.priceOracle),
507
+ tx.object(config.oracle.supraOracleHolder),
508
+ tx.object(feed.pythPriceInfoObject),
509
+ tx.object(config.oracle.switchboardAggregator),
510
+ tx.pure.address(feed.feedId)
511
+ ]
512
+ });
513
+ }
498
514
  function rateToApy(rawRate) {
499
515
  if (!rawRate || rawRate === "0") return 0;
500
516
  return Number(BigInt(rawRate)) / 10 ** RATE_DECIMALS * 100;
@@ -517,7 +533,7 @@ function compoundBalance(rawBalance, currentIndex) {
517
533
  if (!rawBalance || !currentIndex || currentIndex === "0") return 0;
518
534
  const scale = BigInt("1" + "0".repeat(RATE_DECIMALS));
519
535
  const half = scale / 2n;
520
- const result = (rawBalance * scale + half) / BigInt(currentIndex);
536
+ const result = (rawBalance * BigInt(currentIndex) + half) / scale;
521
537
  return Number(result) / 10 ** NAVI_BALANCE_DECIMALS;
522
538
  }
523
539
  async function getUserState(client, address) {
@@ -560,6 +576,9 @@ function mergeCoins(tx, coins) {
560
576
  return primary;
561
577
  }
562
578
  async function buildSaveTx(client, address, amount, options = {}) {
579
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
580
+ throw new T2000Error("INVALID_AMOUNT", "Save amount must be a positive number");
581
+ }
563
582
  const rawAmount = Number(usdcToRaw(amount));
564
583
  const [config, pool] = await Promise.all([getConfig(), getUsdcPool()]);
565
584
  const coins = await fetchCoins(client, address, USDC_TYPE);
@@ -600,6 +619,7 @@ async function buildWithdrawTx(client, address, amount) {
600
619
  const rawAmount = Number(usdcToRaw(effectiveAmount));
601
620
  const tx = new Transaction();
602
621
  tx.setSender(address);
622
+ addOracleUpdate(tx, config, pool);
603
623
  const [balance] = tx.moveCall({
604
624
  target: `${config.package}::incentive_v3::withdraw_v2`,
605
625
  arguments: [
@@ -624,10 +644,14 @@ async function buildWithdrawTx(client, address, amount) {
624
644
  return { tx, effectiveAmount };
625
645
  }
626
646
  async function buildBorrowTx(client, address, amount, options = {}) {
647
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
648
+ throw new T2000Error("INVALID_AMOUNT", "Borrow amount must be a positive number");
649
+ }
627
650
  const rawAmount = Number(usdcToRaw(amount));
628
651
  const [config, pool] = await Promise.all([getConfig(), getUsdcPool()]);
629
652
  const tx = new Transaction();
630
653
  tx.setSender(address);
654
+ addOracleUpdate(tx, config, pool);
631
655
  const [balance] = tx.moveCall({
632
656
  target: `${config.package}::incentive_v3::borrow_v2`,
633
657
  arguments: [
@@ -648,16 +672,23 @@ async function buildBorrowTx(client, address, amount, options = {}) {
648
672
  arguments: [balance],
649
673
  typeArguments: [pool.suiCoinType]
650
674
  });
675
+ if (options.collectFee) {
676
+ addCollectFeeToTx(tx, borrowedCoin, "borrow");
677
+ }
651
678
  tx.transferObjects([borrowedCoin], address);
652
679
  return tx;
653
680
  }
654
681
  async function buildRepayTx(client, address, amount) {
682
+ if (!amount || amount <= 0 || !Number.isFinite(amount)) {
683
+ throw new T2000Error("INVALID_AMOUNT", "Repay amount must be a positive number");
684
+ }
655
685
  const rawAmount = Number(usdcToRaw(amount));
656
686
  const [config, pool] = await Promise.all([getConfig(), getUsdcPool()]);
657
687
  const coins = await fetchCoins(client, address, USDC_TYPE);
658
688
  if (coins.length === 0) throw new T2000Error("INSUFFICIENT_BALANCE", "No USDC coins to repay with");
659
689
  const tx = new Transaction();
660
690
  tx.setSender(address);
691
+ addOracleUpdate(tx, config, pool);
661
692
  const coinObj = mergeCoins(tx, coins);
662
693
  tx.moveCall({
663
694
  target: `${config.package}::incentive_v3::entry_repay`,
@@ -1028,7 +1059,7 @@ var ProtocolRegistry = class {
1028
1059
  }
1029
1060
  }
1030
1061
  if (candidates.length === 0) {
1031
- throw new Error(`No lending adapter supports saving ${asset}`);
1062
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `No lending adapter supports saving ${asset}`);
1032
1063
  }
1033
1064
  candidates.sort((a, b) => b.rate.saveApy - a.rate.saveApy);
1034
1065
  return candidates[0];
@@ -1046,7 +1077,7 @@ var ProtocolRegistry = class {
1046
1077
  }
1047
1078
  }
1048
1079
  if (candidates.length === 0) {
1049
- throw new Error(`No lending adapter supports borrowing ${asset}`);
1080
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `No lending adapter supports borrowing ${asset}`);
1050
1081
  }
1051
1082
  candidates.sort((a, b) => a.rate.borrowApy - b.rate.borrowApy);
1052
1083
  return candidates[0];
@@ -1063,7 +1094,7 @@ var ProtocolRegistry = class {
1063
1094
  }
1064
1095
  }
1065
1096
  if (candidates.length === 0) {
1066
- throw new Error(`No swap adapter supports ${from} \u2192 ${to}`);
1097
+ throw new T2000Error("ASSET_NOT_SUPPORTED", `No swap adapter supports ${from} \u2192 ${to}`);
1067
1098
  }
1068
1099
  candidates.sort((a, b) => b.quote.expectedOutput - a.quote.expectedOutput);
1069
1100
  return candidates[0];
@@ -1126,7 +1157,7 @@ var NaviAdapter = class {
1126
1157
  const rates = await getRates(this.client);
1127
1158
  const key = asset.toUpperCase();
1128
1159
  const r = rates[key];
1129
- if (!r) throw new Error(`NAVI does not support ${asset}`);
1160
+ if (!r) throw new T2000Error("ASSET_NOT_SUPPORTED", `NAVI does not support ${asset}`);
1130
1161
  return { asset, saveApy: r.saveApy, borrowApy: r.borrowApy };
1131
1162
  }
1132
1163
  async getPositions(address) {
@@ -2329,7 +2360,10 @@ var T2000 = class _T2000 extends EventEmitter {
2329
2360
  return { positions };
2330
2361
  }
2331
2362
  async rates() {
2332
- return getRates(this.client);
2363
+ const allRatesResult = await this.registry.allRates("USDC");
2364
+ if (allRatesResult.length === 0) return { USDC: { saveApy: 0, borrowApy: 0 } };
2365
+ const best = allRatesResult.reduce((a, b) => b.rates.saveApy > a.rates.saveApy ? b : a);
2366
+ return { USDC: { saveApy: best.rates.saveApy, borrowApy: best.rates.borrowApy } };
2333
2367
  }
2334
2368
  async allRates(asset = "USDC") {
2335
2369
  return this.registry.allRates(asset);