@t2000/engine 0.6.2 → 0.6.3

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.d.ts CHANGED
@@ -1050,7 +1050,8 @@ interface ProtocolProfile {
1050
1050
  mcap: number | null;
1051
1051
  fees24h: number | null;
1052
1052
  revenue24h: number | null;
1053
- audits: string[];
1053
+ auditCount: number;
1054
+ auditLinks: string[];
1054
1055
  url: string;
1055
1056
  twitter: string | null;
1056
1057
  riskFactors: string[];
@@ -1063,6 +1064,7 @@ declare const protocolDeepDiveTool: Tool<{
1063
1064
  declare const defillamaYieldPoolsTool: Tool<{
1064
1065
  limit?: number | undefined;
1065
1066
  chain?: string | undefined;
1067
+ project?: string | undefined;
1066
1068
  minTvl?: number | undefined;
1067
1069
  }, {
1068
1070
  pool: string;
package/dist/index.js CHANGED
@@ -245,6 +245,9 @@ var NaviTools = {
245
245
  };
246
246
 
247
247
  // src/tools/utils.ts
248
+ function hasAgent(context) {
249
+ return !!context.agent;
250
+ }
248
251
  function requireAgent(context) {
249
252
  if (!context.agent) {
250
253
  throw new Error(
@@ -845,29 +848,43 @@ var healthCheckTool = buildTool({
845
848
  };
846
849
  }
847
850
  });
851
+ var YIELDS_API = "https://yields.llama.fi";
848
852
  function formatRatesSummary(rates) {
849
853
  return Object.entries(rates).map(([asset, r]) => `${asset}: Save ${(r.saveApy * 100).toFixed(2)}% / Borrow ${(r.borrowApy * 100).toFixed(2)}%`).join(", ");
850
854
  }
855
+ async function fetchRatesFromDefiLlama() {
856
+ const res = await fetch(`${YIELDS_API}/pools`, { signal: AbortSignal.timeout(15e3) });
857
+ if (!res.ok) throw new Error(`DefiLlama API error: HTTP ${res.status}`);
858
+ const data = await res.json();
859
+ const naviPools = (data.data ?? []).filter(
860
+ (p) => p.chain === "Sui" && p.project === "navi-lending" && p.tvlUsd > 1e4
861
+ );
862
+ const result = {};
863
+ for (const pool of naviPools) {
864
+ const saveApy = (pool.apy ?? 0) / 100;
865
+ const borrowApy = pool.apyBorrow != null ? Math.abs(pool.apyBorrow) / 100 : 0;
866
+ result[pool.symbol] = { saveApy, borrowApy };
867
+ }
868
+ return result;
869
+ }
851
870
  var ratesInfoTool = buildTool({
852
871
  name: "rates_info",
853
- description: "Get current lending/borrowing interest rates (APY) for all supported assets. Returns save APY and borrow APY per asset.",
872
+ description: "Get current NAVI Protocol lending/savings rates (APY) for supported assets on Sui. Returns save APY and borrow APY per asset.",
854
873
  inputSchema: z.object({}),
855
874
  jsonSchema: { type: "object", properties: {}, required: [] },
856
875
  isReadOnly: true,
857
876
  async call(_input, context) {
858
877
  if (hasNaviMcp(context)) {
859
878
  const rates2 = await fetchRates(getMcpManager(context));
860
- return {
861
- data: rates2,
862
- displayText: formatRatesSummary(rates2)
863
- };
879
+ return { data: rates2, displayText: formatRatesSummary(rates2) };
864
880
  }
865
- const agent = requireAgent(context);
866
- const rates = await agent.rates();
867
- return {
868
- data: rates,
869
- displayText: formatRatesSummary(rates)
870
- };
881
+ if (hasAgent(context)) {
882
+ const agent = requireAgent(context);
883
+ const rates2 = await agent.rates();
884
+ return { data: rates2, displayText: formatRatesSummary(rates2) };
885
+ }
886
+ const rates = await fetchRatesFromDefiLlama();
887
+ return { data: rates, displayText: formatRatesSummary(rates) };
871
888
  }
872
889
  });
873
890
  var SUI_TYPE = "0x2::sui::SUI";
@@ -1784,9 +1801,32 @@ ${insightLines}`
1784
1801
  }
1785
1802
  });
1786
1803
  var LLAMA_API = "https://api.llama.fi";
1804
+ var SLUG_ALIASES = {
1805
+ "navi": "navi-lending",
1806
+ "navi-protocol": "navi-lending",
1807
+ "scallop": "scallop-lend"
1808
+ };
1787
1809
  var inputSchema4 = z.object({
1788
- protocol: z.string().describe('Protocol slug (e.g. "navi-protocol", "cetus", "scallop-lend")')
1810
+ protocol: z.string().describe('Protocol slug (e.g. "navi-lending", "cetus", "scallop-lend")')
1789
1811
  });
1812
+ function extractCurrentTvl(proto) {
1813
+ const chainTvls = proto.currentChainTvls;
1814
+ if (chainTvls && typeof chainTvls === "object") {
1815
+ return Object.values(chainTvls).filter((v) => typeof v === "number" && v > 0).reduce((sum, v) => sum + v, 0);
1816
+ }
1817
+ if (Array.isArray(proto.tvl) && proto.tvl.length > 0) {
1818
+ const last = proto.tvl[proto.tvl.length - 1];
1819
+ return last.totalLiquidityUSD ?? 0;
1820
+ }
1821
+ if (typeof proto.tvl === "number") return proto.tvl;
1822
+ return 0;
1823
+ }
1824
+ function fmtTvl(tvl) {
1825
+ if (tvl >= 1e9) return `$${(tvl / 1e9).toFixed(2)}B`;
1826
+ if (tvl >= 1e6) return `$${(tvl / 1e6).toFixed(1)}M`;
1827
+ if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(0)}K`;
1828
+ return `$${tvl.toFixed(0)}`;
1829
+ }
1790
1830
  var protocolDeepDiveTool = buildTool({
1791
1831
  name: "protocol_deep_dive",
1792
1832
  description: 'Get a comprehensive safety and financial profile of a DeFi protocol. Includes TVL trends, revenue, audit status, and risk assessment. Use when users ask "is X safe?" or "tell me about protocol Y".',
@@ -1794,13 +1834,14 @@ var protocolDeepDiveTool = buildTool({
1794
1834
  jsonSchema: {
1795
1835
  type: "object",
1796
1836
  properties: {
1797
- protocol: { type: "string", description: 'Protocol slug (e.g. "navi-protocol", "cetus")' }
1837
+ protocol: { type: "string", description: 'Protocol slug (e.g. "navi-lending", "cetus")' }
1798
1838
  },
1799
1839
  required: ["protocol"]
1800
1840
  },
1801
1841
  isReadOnly: true,
1802
1842
  async call(input) {
1803
- const slug = input.protocol.toLowerCase().replace(/\s+/g, "-");
1843
+ let slug = input.protocol.toLowerCase().replace(/\s+/g, "-");
1844
+ slug = SLUG_ALIASES[slug] ?? slug;
1804
1845
  const [protocolRes, feesRes] = await Promise.allSettled([
1805
1846
  fetch(`${LLAMA_API}/protocol/${slug}`, { signal: AbortSignal.timeout(1e4) }).then((r) => {
1806
1847
  if (!r.ok) throw new Error(`HTTP ${r.status}`);
@@ -1815,14 +1856,15 @@ var protocolDeepDiveTool = buildTool({
1815
1856
  throw new Error(`Protocol "${slug}" not found on DefiLlama.`);
1816
1857
  }
1817
1858
  const proto = protocolRes.value;
1818
- const tvl = Number(proto.tvl ?? 0);
1859
+ const tvl = extractCurrentTvl(proto);
1819
1860
  const tvlChange1d = Number(proto.change_1d ?? 0);
1820
1861
  const tvlChange7d = Number(proto.change_7d ?? 0);
1821
1862
  const tvlChange30d = Number(proto.change_1m ?? 0);
1822
- const chains = proto.chains ?? [];
1863
+ const chains = Array.isArray(proto.chains) ? proto.chains : [];
1823
1864
  const category = proto.category ?? "Unknown";
1824
- const audits = proto.audits ?? proto.audit_links ?? [];
1825
- const auditNote = proto.audit_note ?? proto.audits;
1865
+ const auditCount = Number(proto.audits) || 0;
1866
+ const auditLinks = Array.isArray(proto.audit_links) ? proto.audit_links : [];
1867
+ const hasAudits = auditCount > 0 || auditLinks.length > 0;
1826
1868
  let fees24h = null;
1827
1869
  let revenue24h = null;
1828
1870
  if (feesRes.status === "fulfilled" && feesRes.value) {
@@ -1832,13 +1874,13 @@ var protocolDeepDiveTool = buildTool({
1832
1874
  }
1833
1875
  const riskFactors = [];
1834
1876
  if (tvl < 1e6) riskFactors.push("TVL under $1M \u2014 low liquidity risk");
1835
- if (tvl < 1e7) riskFactors.push("TVL under $10M \u2014 moderate liquidity");
1877
+ else if (tvl < 1e7) riskFactors.push("TVL under $10M \u2014 moderate liquidity");
1836
1878
  if (tvlChange7d < -15) riskFactors.push(`TVL dropped ${tvlChange7d.toFixed(1)}% in 7 days`);
1837
1879
  if (chains.length === 1) riskFactors.push("Single-chain deployment");
1838
- if (!audits.length && !auditNote) riskFactors.push("No published audits found");
1839
- if (audits.length > 0) riskFactors.push(`${audits.length} audit(s) on file`);
1880
+ if (!hasAudits) riskFactors.push("No published audits found");
1881
+ else riskFactors.push(`${auditCount || auditLinks.length} audit(s) on file`);
1840
1882
  let safetyScore;
1841
- if (tvl > 1e8 && audits.length > 0 && tvlChange7d > -10) {
1883
+ if (tvl > 1e8 && hasAudits && tvlChange7d > -10) {
1842
1884
  safetyScore = "High \u2014 established protocol with audits and significant TVL";
1843
1885
  } else if (tvl > 1e7 && tvlChange7d > -20) {
1844
1886
  safetyScore = "Moderate \u2014 decent TVL, use with caution";
@@ -1857,18 +1899,18 @@ var protocolDeepDiveTool = buildTool({
1857
1899
  mcap: proto.mcap ? Number(proto.mcap) : null,
1858
1900
  fees24h,
1859
1901
  revenue24h,
1860
- audits: typeof auditNote === "string" ? [auditNote] : audits.map(String),
1902
+ auditCount,
1903
+ auditLinks,
1861
1904
  url: proto.url ?? "",
1862
1905
  twitter: proto.twitter ?? null,
1863
1906
  riskFactors,
1864
1907
  safetyScore
1865
1908
  };
1866
- const tvlStr = tvl > 1e9 ? `$${(tvl / 1e9).toFixed(2)}B` : `$${(tvl / 1e6).toFixed(1)}M`;
1867
1909
  const feesStr = fees24h != null ? ` | Fees 24h: $${fees24h.toLocaleString()}` : "";
1868
1910
  return {
1869
1911
  data: result,
1870
1912
  displayText: `**${result.name}** (${category})
1871
- TVL: ${tvlStr} (7d: ${tvlChange7d > 0 ? "+" : ""}${tvlChange7d.toFixed(1)}%)${feesStr}
1913
+ TVL: ${fmtTvl(tvl)} (7d: ${tvlChange7d > 0 ? "+" : ""}${tvlChange7d.toFixed(1)}%)${feesStr}
1872
1914
  Chains: ${chains.join(", ")}
1873
1915
  Safety: ${safetyScore}
1874
1916
  Risks: ${riskFactors.join("; ")}`
@@ -1876,7 +1918,7 @@ Risks: ${riskFactors.join("; ")}`
1876
1918
  }
1877
1919
  });
1878
1920
  var LLAMA_API2 = "https://api.llama.fi";
1879
- var YIELDS_API = "https://yields.llama.fi";
1921
+ var YIELDS_API2 = "https://yields.llama.fi";
1880
1922
  var COINS_API = "https://coins.llama.fi";
1881
1923
  var CACHE_TTL3 = 6e4;
1882
1924
  var apiCache = /* @__PURE__ */ new Map();
@@ -1897,9 +1939,10 @@ function fmtToolTvl(tvl) {
1897
1939
  }
1898
1940
  var defillamaYieldPoolsTool = buildTool({
1899
1941
  name: "defillama_yield_pools",
1900
- description: 'Get top DeFi yield pools across all protocols. Filter by chain (e.g. "Sui") and sort by APY. Shows pool name, protocol, TVL, and APY breakdown. Use minTvl to filter out low-liquidity pools.',
1942
+ description: 'Get top DeFi yield pools across protocols. Filter by chain (e.g. "Sui"), project (e.g. "navi-lending"), and minimum TVL. For NAVI lending rates, use project "navi-lending".',
1901
1943
  inputSchema: z.object({
1902
1944
  chain: z.string().optional().describe('Filter by chain name (e.g. "Sui", "Ethereum")'),
1945
+ project: z.string().optional().describe('Filter by protocol project name (e.g. "navi-lending", "cetus-clmm")'),
1903
1946
  limit: z.number().min(1).max(20).optional().describe("Max results (default 5)"),
1904
1947
  minTvl: z.number().optional().describe("Minimum TVL in USD to filter out small/risky pools (default 100000)")
1905
1948
  }),
@@ -1907,6 +1950,7 @@ var defillamaYieldPoolsTool = buildTool({
1907
1950
  type: "object",
1908
1951
  properties: {
1909
1952
  chain: { type: "string", description: "Filter by chain name" },
1953
+ project: { type: "string", description: 'Filter by protocol project name (e.g. "navi-lending")' },
1910
1954
  limit: { type: "number", description: "Max results (default 5)" },
1911
1955
  minTvl: { type: "number", description: "Minimum TVL in USD (default 100000)" }
1912
1956
  },
@@ -1914,12 +1958,16 @@ var defillamaYieldPoolsTool = buildTool({
1914
1958
  },
1915
1959
  isReadOnly: true,
1916
1960
  async call(input) {
1917
- const data = await cachedFetch(`${YIELDS_API}/pools`);
1961
+ const data = await cachedFetch(`${YIELDS_API2}/pools`);
1918
1962
  let pools = data.data ?? [];
1919
1963
  if (input.chain) {
1920
1964
  const chain = input.chain.toLowerCase();
1921
1965
  pools = pools.filter((p) => p.chain.toLowerCase() === chain);
1922
1966
  }
1967
+ if (input.project) {
1968
+ const project = input.project.toLowerCase();
1969
+ pools = pools.filter((p) => p.project.toLowerCase() === project);
1970
+ }
1923
1971
  const minTvl = input.minTvl ?? 1e5;
1924
1972
  pools = pools.filter((p) => p.tvlUsd >= minTvl);
1925
1973
  pools.sort((a, b) => b.apy - a.apy);