@t2000/sdk 0.9.6 → 0.9.8

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
@@ -9,6 +9,7 @@ import { access, mkdir, writeFile, readFile } from 'fs/promises';
9
9
  import { dirname, resolve } from 'path';
10
10
  import { homedir } from 'os';
11
11
  import { bcs } from '@mysten/sui/bcs';
12
+ import { SuiPriceServiceConnection, SuiPythClient } from '@pythnetwork/pyth-sui-js';
12
13
  import { AggregatorClient, Env } from '@cetusprotocol/aggregator-sdk';
13
14
 
14
15
  // src/t2000.ts
@@ -508,6 +509,7 @@ var NAVI_BALANCE_DECIMALS = 9;
508
509
  var CONFIG_API = "https://open-api.naviprotocol.io/api/navi/config?env=prod";
509
510
  var POOLS_API = "https://open-api.naviprotocol.io/api/navi/pools?env=prod";
510
511
  var PACKAGE_API = "https://open-api.naviprotocol.io/api/package";
512
+ var PYTH_HERMES_URL = "https://hermes.pyth.network/";
511
513
  var packageCache = null;
512
514
  function toBigInt(v) {
513
515
  if (typeof v === "bigint") return v;
@@ -602,14 +604,33 @@ function addOracleUpdate(tx, config, pool) {
602
604
  ]
603
605
  });
604
606
  }
605
- function addOracleUpdatesForAllPools(tx, config, pools) {
606
- const updated = /* @__PURE__ */ new Set();
607
- for (const feed of config.oracle.feeds ?? []) {
608
- if (updated.has(feed.assetId)) continue;
609
- const pool = pools.find((p) => p.id === feed.assetId);
610
- if (!pool) continue;
607
+ async function refreshStableOracles(tx, client, config, pools) {
608
+ const stableTypes = STABLE_ASSETS.map((a) => SUPPORTED_ASSETS[a].type);
609
+ const stablePools = pools.filter((p) => {
610
+ const ct = p.suiCoinType || p.coinType || "";
611
+ return stableTypes.some((t) => matchesCoinType(ct, t));
612
+ });
613
+ const feeds = (config.oracle.feeds ?? []).filter(
614
+ (f2) => stablePools.some((p) => p.id === f2.assetId)
615
+ );
616
+ if (feeds.length === 0) return;
617
+ const pythFeedIds = feeds.map((f2) => f2.pythPriceFeedId).filter(Boolean);
618
+ if (pythFeedIds.length > 0 && config.oracle.pythStateId && config.oracle.wormholeStateId) {
619
+ try {
620
+ const connection = new SuiPriceServiceConnection(PYTH_HERMES_URL);
621
+ const priceUpdateData = await connection.getPriceFeedsUpdateData(pythFeedIds);
622
+ const pythClient = new SuiPythClient(
623
+ client,
624
+ config.oracle.pythStateId,
625
+ config.oracle.wormholeStateId
626
+ );
627
+ await pythClient.updatePriceFeeds(tx, priceUpdateData, pythFeedIds);
628
+ } catch (err) {
629
+ console.error("[t2000] Pyth oracle push failed, falling back to cached prices:", err.message ?? err);
630
+ }
631
+ }
632
+ for (const pool of stablePools) {
611
633
  addOracleUpdate(tx, config, pool);
612
- updated.add(feed.assetId);
613
634
  }
614
635
  }
615
636
  function rateToApy(rawRate) {
@@ -723,9 +744,13 @@ async function buildWithdrawTx(client, address, amount, options = {}) {
723
744
  const effectiveAmount = Math.min(amount, Math.max(0, deposited - WITHDRAW_DUST_BUFFER));
724
745
  if (effectiveAmount <= 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on NAVI`);
725
746
  const rawAmount = Number(stableToRaw(effectiveAmount, assetInfo.decimals));
747
+ if (rawAmount <= 0) {
748
+ throw new T2000Error("INVALID_AMOUNT", `Withdrawal amount too small to represent (effective=${effectiveAmount}, raw=${rawAmount}, decimals=${assetInfo.decimals})`);
749
+ }
750
+ console.error(`[t2000] withdraw: asset=${asset} poolId=${pool.id} amount=${amount} deposited=${deposited} effective=${effectiveAmount} raw=${rawAmount} supplyBal=${assetState?.supplyBalance} index=${pool.currentSupplyIndex}`);
726
751
  const tx = new Transaction();
727
752
  tx.setSender(address);
728
- addOracleUpdatesForAllPools(tx, config, pools);
753
+ await refreshStableOracles(tx, client, config, pools);
729
754
  const [balance] = tx.moveCall({
730
755
  target: `${config.package}::incentive_v3::withdraw_v2`,
731
756
  arguments: [
@@ -763,7 +788,11 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
763
788
  const effectiveAmount = Math.min(amount, Math.max(0, deposited - WITHDRAW_DUST_BUFFER));
764
789
  if (effectiveAmount <= 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on NAVI`);
765
790
  const rawAmount = Number(stableToRaw(effectiveAmount, assetInfo.decimals));
766
- addOracleUpdatesForAllPools(tx, config, pools);
791
+ if (rawAmount <= 0) {
792
+ throw new T2000Error("INVALID_AMOUNT", `Withdrawal amount too small to represent (effective=${effectiveAmount}, raw=${rawAmount}, decimals=${assetInfo.decimals})`);
793
+ }
794
+ console.error(`[t2000] withdraw: asset=${asset} poolId=${pool.id} amount=${amount} deposited=${deposited} effective=${effectiveAmount} raw=${rawAmount} supplyBal=${assetState?.supplyBalance} index=${pool.currentSupplyIndex}`);
795
+ await refreshStableOracles(tx, client, config, pools);
767
796
  const [balance] = tx.moveCall({
768
797
  target: `${config.package}::incentive_v3::withdraw_v2`,
769
798
  arguments: [
@@ -851,7 +880,7 @@ async function buildBorrowTx(client, address, amount, options = {}) {
851
880
  ]);
852
881
  const tx = new Transaction();
853
882
  tx.setSender(address);
854
- addOracleUpdatesForAllPools(tx, config, pools);
883
+ await refreshStableOracles(tx, client, config, pools);
855
884
  const [balance] = tx.moveCall({
856
885
  target: `${config.package}::incentive_v3::borrow_v2`,
857
886
  arguments: [