@t2000/engine 1.11.0 → 1.11.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
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { ALL_NAVI_ASSETS, getDecimalsForCoinType, resolveSymbol, isInRegistry, normalizeCoinType, assertAllowedAsset, SUPPORTED_ASSETS, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
2
+ import { ALL_NAVI_ASSETS, getDecimalsForCoinType, resolveSymbol, isInRegistry, normalizeCoinType, assertAllowedAsset, normalizeAsset, SUPPORTED_ASSETS, getSwapQuote, resolveTokenType, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
3
3
  import { randomUUID } from 'crypto';
4
4
  import { readdirSync, readFileSync } from 'fs';
5
5
  import { join } from 'path';
@@ -2338,9 +2338,22 @@ async function fetchProtocolStats(manager, opts) {
2338
2338
 
2339
2339
  // src/tools/savings.ts
2340
2340
  var DUST_THRESHOLD_USD = 0.01;
2341
+ function isDustOnChain(symbol, amount) {
2342
+ const coinType = resolveTokenType(symbol);
2343
+ if (!coinType) return true;
2344
+ const decimals = getDecimalsForCoinType(coinType);
2345
+ const scale = Math.pow(10, decimals);
2346
+ const dustBuffer = 1e3 / scale;
2347
+ const effective = Math.max(0, amount - dustBuffer);
2348
+ return Math.floor(effective * scale) <= 0;
2349
+ }
2341
2350
  function buildSavingsFromPositions(sp) {
2351
+ const filteredSupplies = sp.supplies.filter(
2352
+ (s) => s.amountUsd >= DUST_THRESHOLD_USD && !isDustOnChain(s.asset, s.amount)
2353
+ );
2354
+ const filteredBorrows = sp.borrows_detail.filter((b) => b.amountUsd >= DUST_THRESHOLD_USD);
2342
2355
  const positions = [
2343
- ...sp.supplies.filter((s) => s.amountUsd >= DUST_THRESHOLD_USD).map((s) => ({
2356
+ ...filteredSupplies.map((s) => ({
2344
2357
  protocol: s.protocol,
2345
2358
  type: "supply",
2346
2359
  symbol: s.asset,
@@ -2349,7 +2362,7 @@ function buildSavingsFromPositions(sp) {
2349
2362
  apy: s.apy,
2350
2363
  liquidationThreshold: 0
2351
2364
  })),
2352
- ...sp.borrows_detail.filter((b) => b.amountUsd >= DUST_THRESHOLD_USD).map((b) => ({
2365
+ ...filteredBorrows.map((b) => ({
2353
2366
  protocol: b.protocol,
2354
2367
  type: "borrow",
2355
2368
  symbol: b.asset,
@@ -2359,8 +2372,8 @@ function buildSavingsFromPositions(sp) {
2359
2372
  liquidationThreshold: 0
2360
2373
  }))
2361
2374
  ];
2362
- const supplied = sp.savings;
2363
- const weightedApy = supplied > 0 ? sp.savingsRate : 0;
2375
+ const supplied = filteredSupplies.reduce((sum, s) => sum + s.amountUsd, 0);
2376
+ const weightedApy = supplied > 0 ? filteredSupplies.reduce((sum, s) => sum + s.apy * s.amountUsd, 0) / supplied : 0;
2364
2377
  const dailyEarning = supplied * weightedApy / 365;
2365
2378
  return {
2366
2379
  positions,
@@ -2444,7 +2457,9 @@ var savingsInfoTool = buildTool({
2444
2457
  }
2445
2458
  if (hasNaviMcpGlobal(context) && targetAddress) {
2446
2459
  const savings = await fetchSavings(getMcpManager(context), targetAddress);
2447
- savings.positions = savings.positions.filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);
2460
+ savings.positions = savings.positions.filter(
2461
+ (p) => p.valueUsd >= DUST_THRESHOLD_USD && (p.type !== "supply" || !isDustOnChain(p.symbol, p.amount))
2462
+ );
2448
2463
  const stamped2 = { ...savings, address: targetAddress, isSelfQuery, suinsName };
2449
2464
  return { data: stamped2, displayText: formatSavingsDisplay(savings, isSelfQuery, targetAddress, suinsName) };
2450
2465
  }
@@ -2467,7 +2482,9 @@ var savingsInfoTool = buildTool({
2467
2482
  valueUsd: p.amountUsd ?? p.valueUsd ?? 0,
2468
2483
  apy: p.apy ?? 0,
2469
2484
  liquidationThreshold: p.liquidationThreshold ?? 0
2470
- })).filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);
2485
+ })).filter(
2486
+ (p) => p.valueUsd >= DUST_THRESHOLD_USD && (p.type !== "supply" || !isDustOnChain(p.symbol, p.amount))
2487
+ );
2471
2488
  const result = {
2472
2489
  positions,
2473
2490
  earnings: {
@@ -3109,10 +3126,10 @@ var saveDepositTool = buildTool({
3109
3126
  });
3110
3127
  var withdrawTool = buildTool({
3111
3128
  name: "withdraw",
3112
- description: 'Withdraw from NAVI lending back to wallet. Defaults to USDC; also withdraws USDsui (the second active saveable stable). Legacy positions in other assets (USDe, SUI) can still be withdrawn if the user has them \u2014 but only USDC and USDsui are eligible to be re-deposited via save_deposit. Payment Stream: bundleable \u2014 when paired with another bundleable write in the same request (e.g. "withdraw and send to Mom"), emit all calls in the same assistant turn so the engine collapses them into one atomic PTB the user signs once.',
3129
+ description: `Withdraw USDC or USDsui from NAVI lending back to wallet. Defaults to USDC. Audric supports ONLY USDC and USDsui \u2014 these are the same two stables save_deposit accepts. NAVI may also surface legacy positions (USDe, SUI, etc.) in savings_info / balance_check; those are READ-ONLY through Audric. For non-canonical positions, direct the user to NAVI's app (https://app.naviprotocol.io) \u2014 Audric will not withdraw them. Payment Stream: bundleable \u2014 when paired with another bundleable write in the same request (e.g. "withdraw and send to Mom"), emit all calls in the same assistant turn so the engine collapses them into one atomic PTB the user signs once.`,
3113
3130
  inputSchema: z.object({
3114
3131
  amount: z.number().positive(),
3115
- asset: z.string().optional().describe("Asset to withdraw (default: USDC). Active: USDsui. Legacy positions: USDe, SUI.")
3132
+ asset: z.string().optional().describe("Asset to withdraw \u2014 must be USDC (default) or USDsui. Other assets surfaced in savings_info are read-only via Audric.")
3116
3133
  }),
3117
3134
  jsonSchema: {
3118
3135
  type: "object",
@@ -3122,7 +3139,7 @@ var withdrawTool = buildTool({
3122
3139
  },
3123
3140
  asset: {
3124
3141
  type: "string",
3125
- description: "Asset to withdraw (default: USDC). Active: USDsui. Legacy positions: USDe, SUI."
3142
+ description: "Asset to withdraw \u2014 USDC (default) or USDsui only. Other assets surfaced in savings_info are read-only via Audric; direct the user to https://app.naviprotocol.io for those."
3126
3143
  }
3127
3144
  },
3128
3145
  required: ["amount"]
@@ -3196,7 +3213,7 @@ var sendTransferTool = buildTool({
3196
3213
  return { valid: false, error: "Amount must be positive." };
3197
3214
  }
3198
3215
  if (input.asset !== void 0) {
3199
- const normalized = String(input.asset).toUpperCase();
3216
+ const normalized = normalizeAsset(String(input.asset));
3200
3217
  if (!(normalized in SUPPORTED_ASSETS)) {
3201
3218
  return {
3202
3219
  valid: false,
@@ -3208,7 +3225,7 @@ var sendTransferTool = buildTool({
3208
3225
  },
3209
3226
  async call(input, context) {
3210
3227
  const agent = requireAgent(context);
3211
- const asset = input.asset ? String(input.asset).toUpperCase() : "USDC";
3228
+ const asset = input.asset ? normalizeAsset(String(input.asset)) : "USDC";
3212
3229
  const result = await agent.send({ to: input.to, amount: input.amount, asset });
3213
3230
  return {
3214
3231
  data: {