@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.
@@ -1,5 +1,6 @@
1
1
  import { Transaction } from '@mysten/sui/transactions';
2
2
  import { bcs } from '@mysten/sui/bcs';
3
+ import { SuiPriceServiceConnection, SuiPythClient } from '@pythnetwork/pyth-sui-js';
3
4
  import { AggregatorClient, Env } from '@cetusprotocol/aggregator-sdk';
4
5
  import { normalizeStructTag } from '@mysten/sui/utils';
5
6
 
@@ -257,6 +258,7 @@ var NAVI_BALANCE_DECIMALS = 9;
257
258
  var CONFIG_API = "https://open-api.naviprotocol.io/api/navi/config?env=prod";
258
259
  var POOLS_API = "https://open-api.naviprotocol.io/api/navi/pools?env=prod";
259
260
  var PACKAGE_API = "https://open-api.naviprotocol.io/api/package";
261
+ var PYTH_HERMES_URL = "https://hermes.pyth.network/";
260
262
  var packageCache = null;
261
263
  function toBigInt(v) {
262
264
  if (typeof v === "bigint") return v;
@@ -351,14 +353,33 @@ function addOracleUpdate(tx, config, pool) {
351
353
  ]
352
354
  });
353
355
  }
354
- function addOracleUpdatesForAllPools(tx, config, pools) {
355
- const updated = /* @__PURE__ */ new Set();
356
- for (const feed of config.oracle.feeds ?? []) {
357
- if (updated.has(feed.assetId)) continue;
358
- const pool = pools.find((p) => p.id === feed.assetId);
359
- if (!pool) continue;
356
+ async function refreshStableOracles(tx, client, config, pools) {
357
+ const stableTypes = STABLE_ASSETS.map((a) => SUPPORTED_ASSETS[a].type);
358
+ const stablePools = pools.filter((p) => {
359
+ const ct = p.suiCoinType || p.coinType || "";
360
+ return stableTypes.some((t) => matchesCoinType(ct, t));
361
+ });
362
+ const feeds = (config.oracle.feeds ?? []).filter(
363
+ (f2) => stablePools.some((p) => p.id === f2.assetId)
364
+ );
365
+ if (feeds.length === 0) return;
366
+ const pythFeedIds = feeds.map((f2) => f2.pythPriceFeedId).filter(Boolean);
367
+ if (pythFeedIds.length > 0 && config.oracle.pythStateId && config.oracle.wormholeStateId) {
368
+ try {
369
+ const connection = new SuiPriceServiceConnection(PYTH_HERMES_URL);
370
+ const priceUpdateData = await connection.getPriceFeedsUpdateData(pythFeedIds);
371
+ const pythClient = new SuiPythClient(
372
+ client,
373
+ config.oracle.pythStateId,
374
+ config.oracle.wormholeStateId
375
+ );
376
+ await pythClient.updatePriceFeeds(tx, priceUpdateData, pythFeedIds);
377
+ } catch (err) {
378
+ console.error("[t2000] Pyth oracle push failed, falling back to cached prices:", err.message ?? err);
379
+ }
380
+ }
381
+ for (const pool of stablePools) {
360
382
  addOracleUpdate(tx, config, pool);
361
- updated.add(feed.assetId);
362
383
  }
363
384
  }
364
385
  function rateToApy(rawRate) {
@@ -472,9 +493,13 @@ async function buildWithdrawTx(client, address, amount, options = {}) {
472
493
  const effectiveAmount = Math.min(amount, Math.max(0, deposited - WITHDRAW_DUST_BUFFER));
473
494
  if (effectiveAmount <= 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on NAVI`);
474
495
  const rawAmount = Number(stableToRaw(effectiveAmount, assetInfo.decimals));
496
+ if (rawAmount <= 0) {
497
+ throw new T2000Error("INVALID_AMOUNT", `Withdrawal amount too small to represent (effective=${effectiveAmount}, raw=${rawAmount}, decimals=${assetInfo.decimals})`);
498
+ }
499
+ console.error(`[t2000] withdraw: asset=${asset} poolId=${pool.id} amount=${amount} deposited=${deposited} effective=${effectiveAmount} raw=${rawAmount} supplyBal=${assetState?.supplyBalance} index=${pool.currentSupplyIndex}`);
475
500
  const tx = new Transaction();
476
501
  tx.setSender(address);
477
- addOracleUpdatesForAllPools(tx, config, pools);
502
+ await refreshStableOracles(tx, client, config, pools);
478
503
  const [balance] = tx.moveCall({
479
504
  target: `${config.package}::incentive_v3::withdraw_v2`,
480
505
  arguments: [
@@ -512,7 +537,11 @@ async function addWithdrawToTx(tx, client, address, amount, options = {}) {
512
537
  const effectiveAmount = Math.min(amount, Math.max(0, deposited - WITHDRAW_DUST_BUFFER));
513
538
  if (effectiveAmount <= 0) throw new T2000Error("NO_COLLATERAL", `Nothing to withdraw for ${assetInfo.displayName} on NAVI`);
514
539
  const rawAmount = Number(stableToRaw(effectiveAmount, assetInfo.decimals));
515
- addOracleUpdatesForAllPools(tx, config, pools);
540
+ if (rawAmount <= 0) {
541
+ throw new T2000Error("INVALID_AMOUNT", `Withdrawal amount too small to represent (effective=${effectiveAmount}, raw=${rawAmount}, decimals=${assetInfo.decimals})`);
542
+ }
543
+ console.error(`[t2000] withdraw: asset=${asset} poolId=${pool.id} amount=${amount} deposited=${deposited} effective=${effectiveAmount} raw=${rawAmount} supplyBal=${assetState?.supplyBalance} index=${pool.currentSupplyIndex}`);
544
+ await refreshStableOracles(tx, client, config, pools);
516
545
  const [balance] = tx.moveCall({
517
546
  target: `${config.package}::incentive_v3::withdraw_v2`,
518
547
  arguments: [
@@ -600,7 +629,7 @@ async function buildBorrowTx(client, address, amount, options = {}) {
600
629
  ]);
601
630
  const tx = new Transaction();
602
631
  tx.setSender(address);
603
- addOracleUpdatesForAllPools(tx, config, pools);
632
+ await refreshStableOracles(tx, client, config, pools);
604
633
  const [balance] = tx.moveCall({
605
634
  target: `${config.package}::incentive_v3::borrow_v2`,
606
635
  arguments: [