@t2000/sdk 1.23.1 → 1.24.1

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
@@ -5636,6 +5636,14 @@ async function maxBorrowAmount(client, address) {
5636
5636
  const maxAmount = Math.max(0, hf.supplied * ltv / MIN_HEALTH_FACTOR - hf.borrowed);
5637
5637
  return { maxAmount, healthFactorAfter: MIN_HEALTH_FACTOR, currentHF: hf.healthFactor };
5638
5638
  }
5639
+ async function getPendingRewardsByAddress(address, suiRpcUrl) {
5640
+ const { SuiJsonRpcClient: SuiJsonRpcClient2, getJsonRpcFullnodeUrl: getJsonRpcFullnodeUrl2 } = await import('@mysten/sui/jsonRpc');
5641
+ const client = new SuiJsonRpcClient2({
5642
+ url: suiRpcUrl ?? getJsonRpcFullnodeUrl2("mainnet"),
5643
+ network: "mainnet"
5644
+ });
5645
+ return getPendingRewards(client, address);
5646
+ }
5639
5647
  async function getPendingRewards(client, address) {
5640
5648
  let rewards;
5641
5649
  try {
@@ -7444,6 +7452,183 @@ var T2000 = class _T2000 extends eventemitter3.EventEmitter {
7444
7452
  // src/index.ts
7445
7453
  init_errors();
7446
7454
  init_coinSelection();
7455
+ init_errors();
7456
+ init_token_registry();
7457
+ init_cetus_swap();
7458
+ async function addHarvestToTx(tx, client, address, options = {}) {
7459
+ const slippage = options.slippage ?? 0.01;
7460
+ const minRewardUsd = options.minRewardUsd ?? 0.01;
7461
+ const priceCache = options.priceCache;
7462
+ let rawRewards;
7463
+ try {
7464
+ rawRewards = await vt(address, {
7465
+ env: "prod",
7466
+ client,
7467
+ markets: ["main"]
7468
+ });
7469
+ } catch (err) {
7470
+ const msg = err instanceof Error ? err.message : String(err);
7471
+ throw new exports.T2000Error(
7472
+ "PROTOCOL_UNAVAILABLE",
7473
+ `NAVI rewards lookup failed: ${msg}`,
7474
+ { source: "navi-harvest-read" },
7475
+ true
7476
+ );
7477
+ }
7478
+ const claimable = (rawRewards ?? []).filter((r) => Number(r.userClaimableReward) > 0);
7479
+ if (claimable.length === 0) {
7480
+ throw new exports.T2000Error(
7481
+ "INVALID_AMOUNT",
7482
+ "No pending rewards to harvest.",
7483
+ { source: "navi-harvest" }
7484
+ );
7485
+ }
7486
+ const aggregated = aggregateClaimableRewards(claimable);
7487
+ let claimed;
7488
+ try {
7489
+ const claimResult = await Ct(tx, claimable, {
7490
+ env: "prod",
7491
+ // 'skip' = NAVI doesn't auto-transfer; coin handles stay in the PTB
7492
+ // for downstream consumption. Verified against NAVI lending source
7493
+ // (index.esm.js@1828–1911) — when type !== 'transfer' && type !==
7494
+ // 'depositNAVI', the `else` branch pushes `{ coin, identifier, ... }`
7495
+ // to the return without consuming the handle.
7496
+ customCoinReceive: { type: "skip" }
7497
+ });
7498
+ const grouped = /* @__PURE__ */ new Map();
7499
+ for (const c of claimResult) {
7500
+ const ct2 = c.identifier.suiCoinType ?? "";
7501
+ if (!ct2) continue;
7502
+ const list = grouped.get(ct2) ?? [];
7503
+ list.push(c.coin);
7504
+ grouped.set(ct2, list);
7505
+ }
7506
+ claimed = [];
7507
+ for (const [coinType, handles] of grouped.entries()) {
7508
+ if (handles.length === 1) {
7509
+ claimed.push({ coin: handles[0], coinType });
7510
+ } else {
7511
+ const [dest, ...rest] = handles;
7512
+ tx.mergeCoins(dest, rest);
7513
+ claimed.push({ coin: dest, coinType });
7514
+ }
7515
+ }
7516
+ } catch (err) {
7517
+ const msg = err instanceof Error ? err.message : String(err);
7518
+ throw new exports.T2000Error(
7519
+ "PROTOCOL_UNAVAILABLE",
7520
+ `NAVI claim PTB build failed: ${msg}`,
7521
+ { source: "navi-harvest-claim-ptb" },
7522
+ true
7523
+ );
7524
+ }
7525
+ const usdcHandles = [];
7526
+ const swaps = [];
7527
+ const skipped = [];
7528
+ let expectedUsdcDeposited = 0;
7529
+ for (const { coin, coinType } of claimed) {
7530
+ const aggRow = aggregated.find((r) => r.coinType === coinType);
7531
+ if (!aggRow) {
7532
+ continue;
7533
+ }
7534
+ if (coinType === exports.USDC_TYPE) {
7535
+ usdcHandles.push(coin);
7536
+ expectedUsdcDeposited += aggRow.amount;
7537
+ continue;
7538
+ }
7539
+ const meta = getCoinMeta(coinType);
7540
+ const isTradeable = meta && (meta.tier === 1 || meta.tier === 2);
7541
+ if (!isTradeable) {
7542
+ tx.transferObjects([coin], address);
7543
+ skipped.push({
7544
+ symbol: aggRow.symbol,
7545
+ coinType,
7546
+ amount: aggRow.amount,
7547
+ reason: "untradeable"
7548
+ });
7549
+ continue;
7550
+ }
7551
+ if (priceCache && minRewardUsd > 0) {
7552
+ const px = priceCache.get(aggRow.symbol.toUpperCase());
7553
+ if (px && px > 0 && aggRow.amount * px < minRewardUsd) {
7554
+ tx.transferObjects([coin], address);
7555
+ skipped.push({
7556
+ symbol: aggRow.symbol,
7557
+ coinType,
7558
+ amount: aggRow.amount,
7559
+ reason: "dust"
7560
+ });
7561
+ continue;
7562
+ }
7563
+ }
7564
+ try {
7565
+ const swapResult = await addSwapToTx(tx, client, address, {
7566
+ from: aggRow.symbol,
7567
+ to: "USDC",
7568
+ amount: aggRow.amount,
7569
+ slippage,
7570
+ inputCoin: coin,
7571
+ providers: options.providers
7572
+ });
7573
+ usdcHandles.push(swapResult.coin);
7574
+ expectedUsdcDeposited += swapResult.expectedAmountOut;
7575
+ swaps.push({
7576
+ fromSymbol: aggRow.symbol,
7577
+ fromCoinType: coinType,
7578
+ toSymbol: "USDC",
7579
+ inputAmount: swapResult.effectiveAmountIn,
7580
+ expectedOutputUsdc: swapResult.expectedAmountOut
7581
+ });
7582
+ } catch (err) {
7583
+ const code = err instanceof exports.T2000Error ? err.code : "UNKNOWN";
7584
+ if (code !== "SWAP_NO_ROUTE" && code !== "SWAP_FAILED") {
7585
+ throw err;
7586
+ }
7587
+ tx.transferObjects([coin], address);
7588
+ skipped.push({
7589
+ symbol: aggRow.symbol,
7590
+ coinType,
7591
+ amount: aggRow.amount,
7592
+ reason: "no-route"
7593
+ });
7594
+ }
7595
+ }
7596
+ if (usdcHandles.length > 0) {
7597
+ let depositCoin;
7598
+ if (usdcHandles.length === 1) {
7599
+ depositCoin = usdcHandles[0];
7600
+ } else {
7601
+ const [primary, ...rest] = usdcHandles;
7602
+ tx.mergeCoins(primary, rest);
7603
+ depositCoin = primary;
7604
+ }
7605
+ try {
7606
+ await addSaveToTx(tx, client, address, depositCoin, { asset: "USDC" });
7607
+ } catch (err) {
7608
+ const msg = err instanceof Error ? err.message : String(err);
7609
+ throw new exports.T2000Error(
7610
+ "PROTOCOL_UNAVAILABLE",
7611
+ `NAVI deposit failed during harvest: ${msg}`,
7612
+ { source: "navi-harvest-deposit" },
7613
+ true
7614
+ );
7615
+ }
7616
+ }
7617
+ return {
7618
+ claimed: aggregated,
7619
+ swaps,
7620
+ skipped,
7621
+ expectedUsdcDeposited
7622
+ };
7623
+ }
7624
+ async function buildHarvestRewardsTx(client, address, options = {}) {
7625
+ const tx = new transactions.Transaction();
7626
+ tx.setSender(address);
7627
+ const plan = await addHarvestToTx(tx, client, address, options);
7628
+ return { tx, plan };
7629
+ }
7630
+
7631
+ // src/composeTx.ts
7447
7632
  init_cetus_swap();
7448
7633
  init_volo();
7449
7634
  init_coinSelection();
@@ -7643,6 +7828,29 @@ var WRITE_APPENDER_REGISTRY = {
7643
7828
  const rewards = await addClaimRewardsToTx(tx, ctx.client, ctx.sender);
7644
7829
  return { preview: { toolName: "claim_rewards", rewards } };
7645
7830
  },
7831
+ // [Track B / 2026-05-08] Macro appender — assembles claim → swap(s) →
7832
+ // save inline. The audric host wires `getSponsoredSwapProviders()` into
7833
+ // `options.providers` automatically when `ctx.sponsoredContext === true`
7834
+ // (parity with `swap_execute` below). Slippage + dust-floor pulled from
7835
+ // the input; price cache is forwarded from the host so the dust filter
7836
+ // can compare claimed amounts to USD.
7837
+ harvest_rewards: async (tx, input, ctx) => {
7838
+ const providers = ctx.sponsoredContext ? await getSponsoredSwapProviders() : void 0;
7839
+ const plan = await addHarvestToTx(tx, ctx.client, ctx.sender, {
7840
+ slippage: input.slippage,
7841
+ minRewardUsd: input.minRewardUsd,
7842
+ providers
7843
+ });
7844
+ return {
7845
+ preview: {
7846
+ toolName: "harvest_rewards",
7847
+ claimed: plan.claimed,
7848
+ swaps: plan.swaps,
7849
+ skipped: plan.skipped,
7850
+ expectedUsdcDeposited: plan.expectedUsdcDeposited
7851
+ }
7852
+ };
7853
+ },
7646
7854
  volo_stake: async (tx, input, ctx) => {
7647
7855
  if (input.amountSui <= 0) {
7648
7856
  throw new exports.T2000Error("INVALID_AMOUNT", "Stake amount must be greater than zero");
@@ -8101,6 +8309,7 @@ exports.allDescriptors = allDescriptors;
8101
8309
  exports.assertAllowedAsset = assertAllowedAsset;
8102
8310
  exports.buildAddLeafTx = buildAddLeafTx;
8103
8311
  exports.buildClaimRewardsTx = buildClaimRewardsTx;
8312
+ exports.buildHarvestRewardsTx = buildHarvestRewardsTx;
8104
8313
  exports.buildRevokeLeafTx = buildRevokeLeafTx;
8105
8314
  exports.buildSendTx = buildSendTx;
8106
8315
  exports.buildStakeVSuiTx = buildStakeVSuiTx;
@@ -8131,6 +8340,7 @@ exports.getDecimals = getDecimals;
8131
8340
  exports.getDecimalsForCoinType = getDecimalsForCoinType;
8132
8341
  exports.getFinancialSummary = getFinancialSummary;
8133
8342
  exports.getPendingRewards = getPendingRewards;
8343
+ exports.getPendingRewardsByAddress = getPendingRewardsByAddress;
8134
8344
  exports.getRates = getRates;
8135
8345
  exports.getSwapQuote = getSwapQuote;
8136
8346
  exports.getTier = getTier;