@t2000/cli 1.23.0 → 1.24.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.
@@ -22466,35 +22466,6 @@ async function vt(e, n) {
22466
22466
  );
22467
22467
  return await De(e, t, n);
22468
22468
  }
22469
- function wt(e) {
22470
- const n = /* @__PURE__ */ new Map();
22471
- e.forEach((r) => {
22472
- const t = r.assetId, a = r.option, s = `${t}-${a}-${r.rewardCoinType}-${r.market}`;
22473
- n.has(s) ? n.get(s).total += r.userClaimableReward : n.set(s, {
22474
- assetId: t,
22475
- rewardType: a,
22476
- coinType: r.rewardCoinType,
22477
- total: Number(r.userClaimableReward),
22478
- market: r.market
22479
- });
22480
- });
22481
- const o = /* @__PURE__ */ new Map();
22482
- for (const { assetId: r, rewardType: t, coinType: a, total: s, market: i } of n.values()) {
22483
- const c = `${r}-${t}-${i}`;
22484
- o.has(c) || o.set(c, { assetId: r, rewardType: t, market: i, rewards: /* @__PURE__ */ new Map() });
22485
- const u = o.get(c);
22486
- u.rewards.set(a, (u.rewards.get(a) || 0) + s);
22487
- }
22488
- return Array.from(o.values()).map((r) => ({
22489
- assetId: r.assetId,
22490
- rewardType: r.rewardType,
22491
- market: r.market,
22492
- rewards: Array.from(r.rewards.entries()).map(([t, a]) => ({
22493
- coinType: t,
22494
- available: a.toFixed(6)
22495
- }))
22496
- }));
22497
- }
22498
22469
  async function Ct(e, n, o) {
22499
22470
  const r = await R({
22500
22471
  ...o,
@@ -22670,6 +22641,7 @@ async function Ct(e, n, o) {
22670
22641
  return a;
22671
22642
  }
22672
22643
  init_errors();
22644
+ init_token_registry();
22673
22645
  var MIN_HEALTH_FACTOR = 1.5;
22674
22646
  function sdkOptions(client) {
22675
22647
  return { env: "prod", client, cacheTime: 0, disableCache: true };
@@ -23044,24 +23016,8 @@ async function getPendingRewards(client, address) {
23044
23016
  );
23045
23017
  }
23046
23018
  if (!rewards || rewards.length === 0) return [];
23047
- const summary = wt(rewards);
23048
- const result = [];
23049
- for (const s of summary) {
23050
- for (const rw of s.rewards) {
23051
- const available = Number(rw.available);
23052
- if (available <= 0) continue;
23053
- const symbol = rw.coinType.split("::").pop() ?? "UNKNOWN";
23054
- result.push({
23055
- protocol: "navi",
23056
- asset: String(s.assetId),
23057
- coinType: rw.coinType,
23058
- symbol,
23059
- amount: available,
23060
- estimatedValueUsd: 0
23061
- });
23062
- }
23063
- }
23064
- return result;
23019
+ const claimable = rewards.filter((r) => Number(r.userClaimableReward) > 0);
23020
+ return aggregateClaimableRewards(claimable);
23065
23021
  }
23066
23022
  async function addClaimRewardsToTx(tx, client, address) {
23067
23023
  let rewards;
@@ -23111,7 +23067,8 @@ function aggregateClaimableRewards(claimable) {
23111
23067
  for (const c of claimable) {
23112
23068
  const coinType = c.rewardCoinType;
23113
23069
  if (!coinType) continue;
23114
- const symbol = coinType.split("::").pop() ?? "REWARD";
23070
+ const meta = getCoinMeta(coinType);
23071
+ const symbol = meta?.symbol ?? coinType.split("::").pop() ?? "REWARD";
23115
23072
  const amount = Number(c.userClaimableReward);
23116
23073
  if (!Number.isFinite(amount) || amount <= 0) continue;
23117
23074
  const existing = aggregated.get(coinType);
@@ -24830,6 +24787,181 @@ var T2000 = class _T2000 extends import_index.default {
24830
24787
  };
24831
24788
  init_errors();
24832
24789
  init_coinSelection();
24790
+ init_errors();
24791
+ init_token_registry();
24792
+ init_cetus_swap();
24793
+ async function addHarvestToTx(tx, client, address, options = {}) {
24794
+ const slippage = options.slippage ?? 0.01;
24795
+ const minRewardUsd = options.minRewardUsd ?? 0.01;
24796
+ const priceCache = options.priceCache;
24797
+ let rawRewards;
24798
+ try {
24799
+ rawRewards = await vt(address, {
24800
+ env: "prod",
24801
+ client,
24802
+ markets: ["main"]
24803
+ });
24804
+ } catch (err) {
24805
+ const msg = err instanceof Error ? err.message : String(err);
24806
+ throw new T2000Error(
24807
+ "PROTOCOL_UNAVAILABLE",
24808
+ `NAVI rewards lookup failed: ${msg}`,
24809
+ { source: "navi-harvest-read" },
24810
+ true
24811
+ );
24812
+ }
24813
+ const claimable = (rawRewards ?? []).filter((r) => Number(r.userClaimableReward) > 0);
24814
+ if (claimable.length === 0) {
24815
+ throw new T2000Error(
24816
+ "INVALID_AMOUNT",
24817
+ "No pending rewards to harvest.",
24818
+ { source: "navi-harvest" }
24819
+ );
24820
+ }
24821
+ const aggregated = aggregateClaimableRewards(claimable);
24822
+ let claimed;
24823
+ try {
24824
+ const claimResult = await Ct(tx, claimable, {
24825
+ env: "prod",
24826
+ // 'skip' = NAVI doesn't auto-transfer; coin handles stay in the PTB
24827
+ // for downstream consumption. Verified against NAVI lending source
24828
+ // (index.esm.js@1828–1911) — when type !== 'transfer' && type !==
24829
+ // 'depositNAVI', the `else` branch pushes `{ coin, identifier, ... }`
24830
+ // to the return without consuming the handle.
24831
+ customCoinReceive: { type: "skip" }
24832
+ });
24833
+ const grouped = /* @__PURE__ */ new Map();
24834
+ for (const c of claimResult) {
24835
+ const ct2 = c.identifier.suiCoinType ?? "";
24836
+ if (!ct2) continue;
24837
+ const list = grouped.get(ct2) ?? [];
24838
+ list.push(c.coin);
24839
+ grouped.set(ct2, list);
24840
+ }
24841
+ claimed = [];
24842
+ for (const [coinType, handles] of grouped.entries()) {
24843
+ if (handles.length === 1) {
24844
+ claimed.push({ coin: handles[0], coinType });
24845
+ } else {
24846
+ const [dest, ...rest] = handles;
24847
+ tx.mergeCoins(dest, rest);
24848
+ claimed.push({ coin: dest, coinType });
24849
+ }
24850
+ }
24851
+ } catch (err) {
24852
+ const msg = err instanceof Error ? err.message : String(err);
24853
+ throw new T2000Error(
24854
+ "PROTOCOL_UNAVAILABLE",
24855
+ `NAVI claim PTB build failed: ${msg}`,
24856
+ { source: "navi-harvest-claim-ptb" },
24857
+ true
24858
+ );
24859
+ }
24860
+ const usdcHandles = [];
24861
+ const swaps = [];
24862
+ const skipped = [];
24863
+ let expectedUsdcDeposited = 0;
24864
+ for (const { coin, coinType } of claimed) {
24865
+ const aggRow = aggregated.find((r) => r.coinType === coinType);
24866
+ if (!aggRow) {
24867
+ continue;
24868
+ }
24869
+ if (coinType === USDC_TYPE) {
24870
+ usdcHandles.push(coin);
24871
+ expectedUsdcDeposited += aggRow.amount;
24872
+ continue;
24873
+ }
24874
+ const meta = getCoinMeta(coinType);
24875
+ const isTradeable = meta && (meta.tier === 1 || meta.tier === 2);
24876
+ if (!isTradeable) {
24877
+ tx.transferObjects([coin], address);
24878
+ skipped.push({
24879
+ symbol: aggRow.symbol,
24880
+ coinType,
24881
+ amount: aggRow.amount,
24882
+ reason: "untradeable"
24883
+ });
24884
+ continue;
24885
+ }
24886
+ if (priceCache && minRewardUsd > 0) {
24887
+ const px = priceCache.get(aggRow.symbol.toUpperCase());
24888
+ if (px && px > 0 && aggRow.amount * px < minRewardUsd) {
24889
+ tx.transferObjects([coin], address);
24890
+ skipped.push({
24891
+ symbol: aggRow.symbol,
24892
+ coinType,
24893
+ amount: aggRow.amount,
24894
+ reason: "dust"
24895
+ });
24896
+ continue;
24897
+ }
24898
+ }
24899
+ try {
24900
+ const swapResult = await addSwapToTx(tx, client, address, {
24901
+ from: aggRow.symbol,
24902
+ to: "USDC",
24903
+ amount: aggRow.amount,
24904
+ slippage,
24905
+ inputCoin: coin,
24906
+ providers: options.providers
24907
+ });
24908
+ usdcHandles.push(swapResult.coin);
24909
+ expectedUsdcDeposited += swapResult.expectedAmountOut;
24910
+ swaps.push({
24911
+ fromSymbol: aggRow.symbol,
24912
+ fromCoinType: coinType,
24913
+ toSymbol: "USDC",
24914
+ inputAmount: swapResult.effectiveAmountIn,
24915
+ expectedOutputUsdc: swapResult.expectedAmountOut
24916
+ });
24917
+ } catch (err) {
24918
+ const code = err instanceof T2000Error ? err.code : "UNKNOWN";
24919
+ if (code !== "SWAP_NO_ROUTE" && code !== "SWAP_FAILED") {
24920
+ throw err;
24921
+ }
24922
+ tx.transferObjects([coin], address);
24923
+ skipped.push({
24924
+ symbol: aggRow.symbol,
24925
+ coinType,
24926
+ amount: aggRow.amount,
24927
+ reason: "no-route"
24928
+ });
24929
+ }
24930
+ }
24931
+ if (usdcHandles.length > 0) {
24932
+ let depositCoin;
24933
+ if (usdcHandles.length === 1) {
24934
+ depositCoin = usdcHandles[0];
24935
+ } else {
24936
+ const [primary, ...rest] = usdcHandles;
24937
+ tx.mergeCoins(primary, rest);
24938
+ depositCoin = primary;
24939
+ }
24940
+ try {
24941
+ await addSaveToTx(tx, client, address, depositCoin, { asset: "USDC" });
24942
+ } catch (err) {
24943
+ const msg = err instanceof Error ? err.message : String(err);
24944
+ throw new T2000Error(
24945
+ "PROTOCOL_UNAVAILABLE",
24946
+ `NAVI deposit failed during harvest: ${msg}`,
24947
+ { source: "navi-harvest-deposit" },
24948
+ true
24949
+ );
24950
+ }
24951
+ }
24952
+ return {
24953
+ claimed: aggregated,
24954
+ swaps,
24955
+ skipped,
24956
+ expectedUsdcDeposited
24957
+ };
24958
+ }
24959
+ async function buildHarvestRewardsTx(client, address, options = {}) {
24960
+ const tx = new Transaction();
24961
+ tx.setSender(address);
24962
+ const plan = await addHarvestToTx(tx, client, address, options);
24963
+ return { tx, plan };
24964
+ }
24833
24965
  init_cetus_swap();
24834
24966
  init_volo();
24835
24967
  init_coinSelection();
@@ -25029,6 +25161,29 @@ var WRITE_APPENDER_REGISTRY = {
25029
25161
  const rewards = await addClaimRewardsToTx(tx, ctx.client, ctx.sender);
25030
25162
  return { preview: { toolName: "claim_rewards", rewards } };
25031
25163
  },
25164
+ // [Track B / 2026-05-08] Macro appender — assembles claim → swap(s) →
25165
+ // save inline. The audric host wires `getSponsoredSwapProviders()` into
25166
+ // `options.providers` automatically when `ctx.sponsoredContext === true`
25167
+ // (parity with `swap_execute` below). Slippage + dust-floor pulled from
25168
+ // the input; price cache is forwarded from the host so the dust filter
25169
+ // can compare claimed amounts to USD.
25170
+ harvest_rewards: async (tx, input, ctx) => {
25171
+ const providers = ctx.sponsoredContext ? await getSponsoredSwapProviders() : void 0;
25172
+ const plan = await addHarvestToTx(tx, ctx.client, ctx.sender, {
25173
+ slippage: input.slippage,
25174
+ minRewardUsd: input.minRewardUsd,
25175
+ providers
25176
+ });
25177
+ return {
25178
+ preview: {
25179
+ toolName: "harvest_rewards",
25180
+ claimed: plan.claimed,
25181
+ swaps: plan.swaps,
25182
+ skipped: plan.skipped,
25183
+ expectedUsdcDeposited: plan.expectedUsdcDeposited
25184
+ }
25185
+ };
25186
+ },
25032
25187
  volo_stake: async (tx, input, ctx) => {
25033
25188
  if (input.amountSui <= 0) {
25034
25189
  throw new T2000Error("INVALID_AMOUNT", "Stake amount must be greater than zero");
@@ -25529,7 +25684,9 @@ export {
25529
25684
  extractTxCommands,
25530
25685
  getRates,
25531
25686
  getPendingRewards,
25687
+ addClaimRewardsToTx,
25532
25688
  buildClaimRewardsTx,
25689
+ aggregateClaimableRewards,
25533
25690
  ProtocolRegistry,
25534
25691
  naviDescriptor,
25535
25692
  allDescriptors,
@@ -25540,6 +25697,7 @@ export {
25540
25697
  SafeguardEnforcer,
25541
25698
  ContactManager,
25542
25699
  T2000,
25700
+ buildHarvestRewardsTx,
25543
25701
  WRITE_APPENDER_REGISTRY,
25544
25702
  deriveAllowedAddressesFromPtb,
25545
25703
  composeTx,
@@ -25582,4 +25740,4 @@ axios/dist/node/axios.cjs:
25582
25740
  @scure/bip39/index.js:
25583
25741
  (*! scure-bip39 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
25584
25742
  */
25585
- //# sourceMappingURL=chunk-JKL4VB6Z.js.map
25743
+ //# sourceMappingURL=chunk-JDOIQPNR.js.map