@t2000/engine 0.6.2 → 0.6.4

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(
@@ -258,6 +261,11 @@ function hasNaviMcp(context) {
258
261
  const mgr = context.mcpManager;
259
262
  return mgr.isConnected(NAVI_SERVER_NAME);
260
263
  }
264
+ function hasNaviMcpGlobal(context) {
265
+ if (!context.mcpManager) return false;
266
+ const mgr = context.mcpManager;
267
+ return mgr.isConnected(NAVI_SERVER_NAME);
268
+ }
261
269
  function getMcpManager(context) {
262
270
  return context.mcpManager;
263
271
  }
@@ -845,29 +853,43 @@ var healthCheckTool = buildTool({
845
853
  };
846
854
  }
847
855
  });
856
+ var YIELDS_API = "https://yields.llama.fi";
848
857
  function formatRatesSummary(rates) {
849
858
  return Object.entries(rates).map(([asset, r]) => `${asset}: Save ${(r.saveApy * 100).toFixed(2)}% / Borrow ${(r.borrowApy * 100).toFixed(2)}%`).join(", ");
850
859
  }
860
+ async function fetchRatesFromDefiLlama() {
861
+ const res = await fetch(`${YIELDS_API}/pools`, { signal: AbortSignal.timeout(15e3) });
862
+ if (!res.ok) throw new Error(`DefiLlama API error: HTTP ${res.status}`);
863
+ const data = await res.json();
864
+ const naviPools = (data.data ?? []).filter(
865
+ (p) => p.chain === "Sui" && p.project === "navi-lending" && p.tvlUsd > 1e4
866
+ );
867
+ const result = {};
868
+ for (const pool of naviPools) {
869
+ const saveApy = (pool.apy ?? 0) / 100;
870
+ const borrowApy = pool.apyBorrow != null ? Math.abs(pool.apyBorrow) / 100 : 0;
871
+ result[pool.symbol] = { saveApy, borrowApy };
872
+ }
873
+ return result;
874
+ }
851
875
  var ratesInfoTool = buildTool({
852
876
  name: "rates_info",
853
- description: "Get current lending/borrowing interest rates (APY) for all supported assets. Returns save APY and borrow APY per asset.",
877
+ description: "Get current NAVI Protocol lending/savings rates (APY) for supported assets on Sui. Returns save APY and borrow APY per asset.",
854
878
  inputSchema: z.object({}),
855
879
  jsonSchema: { type: "object", properties: {}, required: [] },
856
880
  isReadOnly: true,
857
881
  async call(_input, context) {
858
- if (hasNaviMcp(context)) {
882
+ if (hasNaviMcpGlobal(context)) {
859
883
  const rates2 = await fetchRates(getMcpManager(context));
860
- return {
861
- data: rates2,
862
- displayText: formatRatesSummary(rates2)
863
- };
884
+ return { data: rates2, displayText: formatRatesSummary(rates2) };
864
885
  }
865
- const agent = requireAgent(context);
866
- const rates = await agent.rates();
867
- return {
868
- data: rates,
869
- displayText: formatRatesSummary(rates)
870
- };
886
+ if (hasAgent(context)) {
887
+ const agent = requireAgent(context);
888
+ const rates2 = await agent.rates();
889
+ return { data: rates2, displayText: formatRatesSummary(rates2) };
890
+ }
891
+ const rates = await fetchRatesFromDefiLlama();
892
+ return { data: rates, displayText: formatRatesSummary(rates) };
871
893
  }
872
894
  });
873
895
  var SUI_TYPE = "0x2::sui::SUI";
@@ -1784,9 +1806,32 @@ ${insightLines}`
1784
1806
  }
1785
1807
  });
1786
1808
  var LLAMA_API = "https://api.llama.fi";
1809
+ var SLUG_ALIASES = {
1810
+ "navi": "navi-lending",
1811
+ "navi-protocol": "navi-lending",
1812
+ "scallop": "scallop-lend"
1813
+ };
1787
1814
  var inputSchema4 = z.object({
1788
- protocol: z.string().describe('Protocol slug (e.g. "navi-protocol", "cetus", "scallop-lend")')
1815
+ protocol: z.string().describe('Protocol slug (e.g. "navi-lending", "cetus", "scallop-lend")')
1789
1816
  });
1817
+ function extractCurrentTvl(proto) {
1818
+ const chainTvls = proto.currentChainTvls;
1819
+ if (chainTvls && typeof chainTvls === "object") {
1820
+ return Object.values(chainTvls).filter((v) => typeof v === "number" && v > 0).reduce((sum, v) => sum + v, 0);
1821
+ }
1822
+ if (Array.isArray(proto.tvl) && proto.tvl.length > 0) {
1823
+ const last = proto.tvl[proto.tvl.length - 1];
1824
+ return last.totalLiquidityUSD ?? 0;
1825
+ }
1826
+ if (typeof proto.tvl === "number") return proto.tvl;
1827
+ return 0;
1828
+ }
1829
+ function fmtTvl(tvl) {
1830
+ if (tvl >= 1e9) return `$${(tvl / 1e9).toFixed(2)}B`;
1831
+ if (tvl >= 1e6) return `$${(tvl / 1e6).toFixed(1)}M`;
1832
+ if (tvl >= 1e3) return `$${(tvl / 1e3).toFixed(0)}K`;
1833
+ return `$${tvl.toFixed(0)}`;
1834
+ }
1790
1835
  var protocolDeepDiveTool = buildTool({
1791
1836
  name: "protocol_deep_dive",
1792
1837
  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 +1839,14 @@ var protocolDeepDiveTool = buildTool({
1794
1839
  jsonSchema: {
1795
1840
  type: "object",
1796
1841
  properties: {
1797
- protocol: { type: "string", description: 'Protocol slug (e.g. "navi-protocol", "cetus")' }
1842
+ protocol: { type: "string", description: 'Protocol slug (e.g. "navi-lending", "cetus")' }
1798
1843
  },
1799
1844
  required: ["protocol"]
1800
1845
  },
1801
1846
  isReadOnly: true,
1802
1847
  async call(input) {
1803
- const slug = input.protocol.toLowerCase().replace(/\s+/g, "-");
1848
+ let slug = input.protocol.toLowerCase().replace(/\s+/g, "-");
1849
+ slug = SLUG_ALIASES[slug] ?? slug;
1804
1850
  const [protocolRes, feesRes] = await Promise.allSettled([
1805
1851
  fetch(`${LLAMA_API}/protocol/${slug}`, { signal: AbortSignal.timeout(1e4) }).then((r) => {
1806
1852
  if (!r.ok) throw new Error(`HTTP ${r.status}`);
@@ -1815,14 +1861,15 @@ var protocolDeepDiveTool = buildTool({
1815
1861
  throw new Error(`Protocol "${slug}" not found on DefiLlama.`);
1816
1862
  }
1817
1863
  const proto = protocolRes.value;
1818
- const tvl = Number(proto.tvl ?? 0);
1864
+ const tvl = extractCurrentTvl(proto);
1819
1865
  const tvlChange1d = Number(proto.change_1d ?? 0);
1820
1866
  const tvlChange7d = Number(proto.change_7d ?? 0);
1821
1867
  const tvlChange30d = Number(proto.change_1m ?? 0);
1822
- const chains = proto.chains ?? [];
1868
+ const chains = Array.isArray(proto.chains) ? proto.chains : [];
1823
1869
  const category = proto.category ?? "Unknown";
1824
- const audits = proto.audits ?? proto.audit_links ?? [];
1825
- const auditNote = proto.audit_note ?? proto.audits;
1870
+ const auditCount = Number(proto.audits) || 0;
1871
+ const auditLinks = Array.isArray(proto.audit_links) ? proto.audit_links : [];
1872
+ const hasAudits = auditCount > 0 || auditLinks.length > 0;
1826
1873
  let fees24h = null;
1827
1874
  let revenue24h = null;
1828
1875
  if (feesRes.status === "fulfilled" && feesRes.value) {
@@ -1832,13 +1879,13 @@ var protocolDeepDiveTool = buildTool({
1832
1879
  }
1833
1880
  const riskFactors = [];
1834
1881
  if (tvl < 1e6) riskFactors.push("TVL under $1M \u2014 low liquidity risk");
1835
- if (tvl < 1e7) riskFactors.push("TVL under $10M \u2014 moderate liquidity");
1882
+ else if (tvl < 1e7) riskFactors.push("TVL under $10M \u2014 moderate liquidity");
1836
1883
  if (tvlChange7d < -15) riskFactors.push(`TVL dropped ${tvlChange7d.toFixed(1)}% in 7 days`);
1837
1884
  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`);
1885
+ if (!hasAudits) riskFactors.push("No published audits found");
1886
+ else riskFactors.push(`${auditCount || auditLinks.length} audit(s) on file`);
1840
1887
  let safetyScore;
1841
- if (tvl > 1e8 && audits.length > 0 && tvlChange7d > -10) {
1888
+ if (tvl > 1e8 && hasAudits && tvlChange7d > -10) {
1842
1889
  safetyScore = "High \u2014 established protocol with audits and significant TVL";
1843
1890
  } else if (tvl > 1e7 && tvlChange7d > -20) {
1844
1891
  safetyScore = "Moderate \u2014 decent TVL, use with caution";
@@ -1857,18 +1904,18 @@ var protocolDeepDiveTool = buildTool({
1857
1904
  mcap: proto.mcap ? Number(proto.mcap) : null,
1858
1905
  fees24h,
1859
1906
  revenue24h,
1860
- audits: typeof auditNote === "string" ? [auditNote] : audits.map(String),
1907
+ auditCount,
1908
+ auditLinks,
1861
1909
  url: proto.url ?? "",
1862
1910
  twitter: proto.twitter ?? null,
1863
1911
  riskFactors,
1864
1912
  safetyScore
1865
1913
  };
1866
- const tvlStr = tvl > 1e9 ? `$${(tvl / 1e9).toFixed(2)}B` : `$${(tvl / 1e6).toFixed(1)}M`;
1867
1914
  const feesStr = fees24h != null ? ` | Fees 24h: $${fees24h.toLocaleString()}` : "";
1868
1915
  return {
1869
1916
  data: result,
1870
1917
  displayText: `**${result.name}** (${category})
1871
- TVL: ${tvlStr} (7d: ${tvlChange7d > 0 ? "+" : ""}${tvlChange7d.toFixed(1)}%)${feesStr}
1918
+ TVL: ${fmtTvl(tvl)} (7d: ${tvlChange7d > 0 ? "+" : ""}${tvlChange7d.toFixed(1)}%)${feesStr}
1872
1919
  Chains: ${chains.join(", ")}
1873
1920
  Safety: ${safetyScore}
1874
1921
  Risks: ${riskFactors.join("; ")}`
@@ -1876,7 +1923,7 @@ Risks: ${riskFactors.join("; ")}`
1876
1923
  }
1877
1924
  });
1878
1925
  var LLAMA_API2 = "https://api.llama.fi";
1879
- var YIELDS_API = "https://yields.llama.fi";
1926
+ var YIELDS_API2 = "https://yields.llama.fi";
1880
1927
  var COINS_API = "https://coins.llama.fi";
1881
1928
  var CACHE_TTL3 = 6e4;
1882
1929
  var apiCache = /* @__PURE__ */ new Map();
@@ -1897,9 +1944,10 @@ function fmtToolTvl(tvl) {
1897
1944
  }
1898
1945
  var defillamaYieldPoolsTool = buildTool({
1899
1946
  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.',
1947
+ 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
1948
  inputSchema: z.object({
1902
1949
  chain: z.string().optional().describe('Filter by chain name (e.g. "Sui", "Ethereum")'),
1950
+ project: z.string().optional().describe('Filter by protocol project name (e.g. "navi-lending", "cetus-clmm")'),
1903
1951
  limit: z.number().min(1).max(20).optional().describe("Max results (default 5)"),
1904
1952
  minTvl: z.number().optional().describe("Minimum TVL in USD to filter out small/risky pools (default 100000)")
1905
1953
  }),
@@ -1907,6 +1955,7 @@ var defillamaYieldPoolsTool = buildTool({
1907
1955
  type: "object",
1908
1956
  properties: {
1909
1957
  chain: { type: "string", description: "Filter by chain name" },
1958
+ project: { type: "string", description: 'Filter by protocol project name (e.g. "navi-lending")' },
1910
1959
  limit: { type: "number", description: "Max results (default 5)" },
1911
1960
  minTvl: { type: "number", description: "Minimum TVL in USD (default 100000)" }
1912
1961
  },
@@ -1914,12 +1963,16 @@ var defillamaYieldPoolsTool = buildTool({
1914
1963
  },
1915
1964
  isReadOnly: true,
1916
1965
  async call(input) {
1917
- const data = await cachedFetch(`${YIELDS_API}/pools`);
1966
+ const data = await cachedFetch(`${YIELDS_API2}/pools`);
1918
1967
  let pools = data.data ?? [];
1919
1968
  if (input.chain) {
1920
1969
  const chain = input.chain.toLowerCase();
1921
1970
  pools = pools.filter((p) => p.chain.toLowerCase() === chain);
1922
1971
  }
1972
+ if (input.project) {
1973
+ const project = input.project.toLowerCase();
1974
+ pools = pools.filter((p) => p.project.toLowerCase() === project);
1975
+ }
1923
1976
  const minTvl = input.minTvl ?? 1e5;
1924
1977
  pools = pools.filter((p) => p.tvlUsd >= minTvl);
1925
1978
  pools.sort((a, b) => b.apy - a.apy);