@t2000/engine 1.1.0 → 1.2.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.
- package/dist/index.d.ts +119 -1
- package/dist/index.js +346 -98
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ALL_NAVI_ASSETS, getDecimalsForCoinType, resolveSymbol, normalizeCoinType, assertAllowedAsset, SUPPORTED_ASSETS, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
|
|
2
|
+
import { ALL_NAVI_ASSETS, getDecimalsForCoinType, resolveSymbol, isInRegistry, normalizeCoinType, assertAllowedAsset, SUPPORTED_ASSETS, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
4
|
import { readdirSync, readFileSync } from 'fs';
|
|
5
5
|
import { join } from 'path';
|
|
@@ -920,7 +920,7 @@ async function fetchPortfolioFromBlockVision(address, apiKey) {
|
|
|
920
920
|
const rawCoins = json.result.coins ?? [];
|
|
921
921
|
const coins = rawCoins.map((c) => {
|
|
922
922
|
const coinType = c.coinType;
|
|
923
|
-
const symbol = c.symbol || resolveSymbol(coinType);
|
|
923
|
+
const symbol = isInRegistry(coinType) ? resolveSymbol(coinType) : c.symbol || resolveSymbol(coinType);
|
|
924
924
|
const decimals = typeof c.decimals === "number" ? c.decimals : getDecimalsForCoinType(coinType);
|
|
925
925
|
const stablePrice = STABLE_USD_PRICES[coinType];
|
|
926
926
|
const apiPrice = parseNumberOrNull(c.price);
|
|
@@ -1642,9 +1642,96 @@ async function fetchAudricHistory(address, opts, env, signal) {
|
|
|
1642
1642
|
}
|
|
1643
1643
|
}
|
|
1644
1644
|
|
|
1645
|
+
// src/sui-address.ts
|
|
1646
|
+
var SUI_MAINNET_URL2 = "https://fullnode.mainnet.sui.io:443";
|
|
1647
|
+
var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/i;
|
|
1648
|
+
var SUI_ADDRESS_STRICT_REGEX = /^0x[a-fA-F0-9]{64}$/i;
|
|
1649
|
+
var SUINS_NAME_REGEX = /^[a-z0-9-]+(\.[a-z0-9-]+)*\.sui$/;
|
|
1650
|
+
var InvalidAddressError = class extends Error {
|
|
1651
|
+
constructor(raw) {
|
|
1652
|
+
super(
|
|
1653
|
+
`"${raw}" isn't a valid Sui address or SuiNS name. Pass a 0x-prefixed hex address (e.g. 0x40cd\u20263e62) or a SuiNS name ending in .sui (e.g. alex.sui).`
|
|
1654
|
+
);
|
|
1655
|
+
this.raw = raw;
|
|
1656
|
+
this.name = "InvalidAddressError";
|
|
1657
|
+
}
|
|
1658
|
+
};
|
|
1659
|
+
var SuinsNotRegisteredError = class extends Error {
|
|
1660
|
+
constructor(name_) {
|
|
1661
|
+
super(
|
|
1662
|
+
`"${name_}" isn't a registered SuiNS name. Double-check the spelling, or paste the full Sui address (0x\u2026 64 hex characters).`
|
|
1663
|
+
);
|
|
1664
|
+
this.name_ = name_;
|
|
1665
|
+
this.name = "SuinsNotRegisteredError";
|
|
1666
|
+
}
|
|
1667
|
+
};
|
|
1668
|
+
var SuinsRpcError = class extends Error {
|
|
1669
|
+
constructor(name_, detail) {
|
|
1670
|
+
super(`SuiNS lookup failed for "${name_}" (${detail}). Try again, or paste the full Sui address.`);
|
|
1671
|
+
this.name_ = name_;
|
|
1672
|
+
this.name = "SuinsRpcError";
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
function looksLikeSuiNs(value) {
|
|
1676
|
+
if (!value) return false;
|
|
1677
|
+
return SUINS_NAME_REGEX.test(value.trim().toLowerCase());
|
|
1678
|
+
}
|
|
1679
|
+
async function resolveSuinsViaRpc(rawName, ctx = {}) {
|
|
1680
|
+
const name = rawName.trim().toLowerCase();
|
|
1681
|
+
if (!SUINS_NAME_REGEX.test(name)) {
|
|
1682
|
+
throw new InvalidAddressError(rawName);
|
|
1683
|
+
}
|
|
1684
|
+
const url = ctx.suiRpcUrl || SUI_MAINNET_URL2;
|
|
1685
|
+
let res;
|
|
1686
|
+
try {
|
|
1687
|
+
res = await fetch(url, {
|
|
1688
|
+
method: "POST",
|
|
1689
|
+
headers: { "Content-Type": "application/json" },
|
|
1690
|
+
body: JSON.stringify({
|
|
1691
|
+
jsonrpc: "2.0",
|
|
1692
|
+
id: 1,
|
|
1693
|
+
method: "suix_resolveNameServiceAddress",
|
|
1694
|
+
params: [name]
|
|
1695
|
+
}),
|
|
1696
|
+
signal: ctx.signal ?? AbortSignal.timeout(8e3)
|
|
1697
|
+
});
|
|
1698
|
+
} catch (err) {
|
|
1699
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1700
|
+
throw new SuinsRpcError(name, msg);
|
|
1701
|
+
}
|
|
1702
|
+
if (!res.ok) {
|
|
1703
|
+
throw new SuinsRpcError(name, `HTTP ${res.status}`);
|
|
1704
|
+
}
|
|
1705
|
+
let body;
|
|
1706
|
+
try {
|
|
1707
|
+
body = await res.json();
|
|
1708
|
+
} catch (err) {
|
|
1709
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1710
|
+
throw new SuinsRpcError(name, `JSON parse failed: ${msg}`);
|
|
1711
|
+
}
|
|
1712
|
+
if (body.error) {
|
|
1713
|
+
throw new SuinsRpcError(name, body.error.message);
|
|
1714
|
+
}
|
|
1715
|
+
return body.result ?? null;
|
|
1716
|
+
}
|
|
1717
|
+
async function normalizeAddressInput(value, ctx = {}) {
|
|
1718
|
+
const trimmed = value.trim();
|
|
1719
|
+
if (SUI_ADDRESS_REGEX.test(trimmed)) {
|
|
1720
|
+
return { address: trimmed.toLowerCase(), suinsName: null, raw: value };
|
|
1721
|
+
}
|
|
1722
|
+
if (looksLikeSuiNs(trimmed)) {
|
|
1723
|
+
const name = trimmed.toLowerCase();
|
|
1724
|
+
const address = await resolveSuinsViaRpc(name, ctx);
|
|
1725
|
+
if (!address) {
|
|
1726
|
+
throw new SuinsNotRegisteredError(name);
|
|
1727
|
+
}
|
|
1728
|
+
return { address: address.toLowerCase(), suinsName: name, raw: value };
|
|
1729
|
+
}
|
|
1730
|
+
throw new InvalidAddressError(value);
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1645
1733
|
// src/tools/balance.ts
|
|
1646
1734
|
var GAS_RESERVE_SUI2 = 0.05;
|
|
1647
|
-
var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{1,64}$/;
|
|
1648
1735
|
var VSUI_COIN_TYPE = "0x549e8b69270defbfafd4f94e17ec44cdbdd99820b33bda2278dea3b9a32d3f55::cert::CERT";
|
|
1649
1736
|
var SUI_COIN_TYPE = "0x2::sui::SUI";
|
|
1650
1737
|
var VSUI_FALLBACK_RATE = 1.05;
|
|
@@ -1696,17 +1783,16 @@ async function loadPortfolio(address, blockvisionApiKey, fallbackRpcUrl, cache)
|
|
|
1696
1783
|
}
|
|
1697
1784
|
var balanceCheckTool = buildTool({
|
|
1698
1785
|
name: "balance_check",
|
|
1699
|
-
description:
|
|
1786
|
+
description: 'Get the full balance breakdown for the signed-in user OR any public Sui address or SuiNS name. Returns wallet holdings (tokens the address owns \u2014 NOT savings), NAVI savings deposits (USDC and/or USDsui deposited into NAVI Protocol earning yield), outstanding debt, pending rewards, gas reserve, total net worth, saveableUsdc (USDC wallet balance available to save), and saveableUsdsui (USDsui wallet balance available to save \u2014 surfaces only when > 0). IMPORTANT: wallet holdings like GOLD, SUI, USDT, USDe are NOT savings positions and are NOT saveable \u2014 only USDC and USDsui can be saved/borrowed. Pass `address` as a 0x address OR a SuiNS name (e.g. "alex.sui") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',
|
|
1700
1787
|
inputSchema: z.object({
|
|
1701
|
-
address: z.string().
|
|
1788
|
+
address: z.string().optional().describe("Sui address (0x\u2026) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.")
|
|
1702
1789
|
}),
|
|
1703
1790
|
jsonSchema: {
|
|
1704
1791
|
type: "object",
|
|
1705
1792
|
properties: {
|
|
1706
1793
|
address: {
|
|
1707
1794
|
type: "string",
|
|
1708
|
-
|
|
1709
|
-
description: "Sui address to inspect (defaults to the signed-in wallet)"
|
|
1795
|
+
description: "Sui address (0x\u2026) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet."
|
|
1710
1796
|
}
|
|
1711
1797
|
},
|
|
1712
1798
|
required: []
|
|
@@ -1718,7 +1804,18 @@ var balanceCheckTool = buildTool({
|
|
|
1718
1804
|
// calls — each one reflects a different on-chain + market snapshot.
|
|
1719
1805
|
cacheable: false,
|
|
1720
1806
|
async call(input, context) {
|
|
1721
|
-
|
|
1807
|
+
let suinsName = null;
|
|
1808
|
+
let targetAddress;
|
|
1809
|
+
if (input.address) {
|
|
1810
|
+
const normalized = await normalizeAddressInput(input.address, {
|
|
1811
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
1812
|
+
signal: context.signal
|
|
1813
|
+
});
|
|
1814
|
+
targetAddress = normalized.address;
|
|
1815
|
+
suinsName = normalized.suinsName;
|
|
1816
|
+
} else {
|
|
1817
|
+
targetAddress = context.walletAddress;
|
|
1818
|
+
}
|
|
1722
1819
|
const isSelfQuery = !!context.walletAddress && !!targetAddress && targetAddress.toLowerCase() === context.walletAddress.toLowerCase();
|
|
1723
1820
|
if (hasNaviMcpGlobal(context)) {
|
|
1724
1821
|
if (!targetAddress) {
|
|
@@ -1850,10 +1947,12 @@ var balanceCheckTool = buildTool({
|
|
|
1850
1947
|
saveableUsdsui,
|
|
1851
1948
|
priceSource: portfolio.source,
|
|
1852
1949
|
address,
|
|
1853
|
-
isSelfQuery
|
|
1950
|
+
isSelfQuery,
|
|
1951
|
+
suinsName
|
|
1854
1952
|
};
|
|
1855
1953
|
const holdingsList = visibleHoldings.map((h) => `${h.symbol}: ${h.balance < 1 ? h.balance.toFixed(6) : h.balance.toFixed(2)} ($${h.usdValue.toFixed(2)})`).join(", ");
|
|
1856
|
-
const
|
|
1954
|
+
const subjectLabel = suinsName ?? `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
|
|
1955
|
+
const subjectPrefix = isSelfQuery ? "Balance" : `Balance for ${subjectLabel}`;
|
|
1857
1956
|
const defiSummaryText = (() => {
|
|
1858
1957
|
if (defi2.source === "degraded") {
|
|
1859
1958
|
return ' DeFi positions (Bluefin / Suilend / Cetus / etc.): UNAVAILABLE \u2014 DeFi data source is currently unreachable. Do NOT assert "no DeFi positions"; tell the user this slice is temporarily unknown and the total above EXCLUDES DeFi.';
|
|
@@ -1877,9 +1976,9 @@ var balanceCheckTool = buildTool({
|
|
|
1877
1976
|
displayText: `${subjectPrefix}: $${bal.total.toFixed(2)} total. Wallet holdings (NOT savings): ${holdingsList || "none"}. NAVI savings deposits: $${bal.savings.toFixed(2)}.${defiSummaryText} ${saveableSummary}`
|
|
1878
1977
|
};
|
|
1879
1978
|
}
|
|
1880
|
-
if (
|
|
1979
|
+
if (targetAddress && context.walletAddress && targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()) {
|
|
1881
1980
|
throw new Error(
|
|
1882
|
-
`Cannot inspect ${
|
|
1981
|
+
`Cannot inspect ${targetAddress.slice(0, 8)}\u2026 without NAVI MCP enabled. Configure NAVI MCP to enable third-party address reads.`
|
|
1883
1982
|
);
|
|
1884
1983
|
}
|
|
1885
1984
|
const agent = requireAgent(context);
|
|
@@ -1941,7 +2040,8 @@ var balanceCheckTool = buildTool({
|
|
|
1941
2040
|
saveableUsdc: sdkSaveableUsdc,
|
|
1942
2041
|
saveableUsdsui: sdkSaveableUsdsui,
|
|
1943
2042
|
address: targetAddress ?? "",
|
|
1944
|
-
isSelfQuery: true
|
|
2043
|
+
isSelfQuery: true,
|
|
2044
|
+
suinsName
|
|
1945
2045
|
},
|
|
1946
2046
|
displayText: `Balance: $${sdkTotal.toFixed(2)} total. Wallet: $${balance.available.toFixed(2)} available. NAVI savings deposits: $${balance.savings.toFixed(2)}.${sdkDefiSummaryText} ${sdkSaveableUsdsui > 0 ? `Saveable: ${sdkSaveableUsdc.toFixed(2)} USDC + ${sdkSaveableUsdsui.toFixed(sdkSaveableUsdsui < 1 ? 4 : 2)} USDsui (only USDC and USDsui can be saved/borrowed).` : `Saveable USDC (only USDC and USDsui can be saved): ${sdkSaveableUsdc.toFixed(2)} USDC.`}`
|
|
1947
2047
|
};
|
|
@@ -2173,7 +2273,6 @@ async function fetchProtocolStats(manager, opts) {
|
|
|
2173
2273
|
|
|
2174
2274
|
// src/tools/savings.ts
|
|
2175
2275
|
var DUST_THRESHOLD_USD = 0.01;
|
|
2176
|
-
var SUI_ADDRESS_REGEX2 = /^0x[a-fA-F0-9]{1,64}$/;
|
|
2177
2276
|
function buildSavingsFromPositions(sp) {
|
|
2178
2277
|
const positions = [
|
|
2179
2278
|
...sp.supplies.filter((s) => s.amountUsd >= DUST_THRESHOLD_USD).map((s) => ({
|
|
@@ -2215,11 +2314,12 @@ function buildSavingsFromPositions(sp) {
|
|
|
2215
2314
|
}
|
|
2216
2315
|
};
|
|
2217
2316
|
}
|
|
2218
|
-
function formatSavingsDisplay(result, isSelfQuery = true, address) {
|
|
2317
|
+
function formatSavingsDisplay(result, isSelfQuery = true, address, suinsName) {
|
|
2219
2318
|
const { positions, earnings, fundStatus } = result;
|
|
2220
2319
|
const supplies = positions.filter((p) => p.type === "supply");
|
|
2221
2320
|
const borrows = positions.filter((p) => p.type === "borrow");
|
|
2222
|
-
const
|
|
2321
|
+
const subjectLabel = suinsName ?? (address ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : null);
|
|
2322
|
+
const subjectPrefix = isSelfQuery || !subjectLabel ? "" : `${subjectLabel} \u2014 `;
|
|
2223
2323
|
const lines = [];
|
|
2224
2324
|
if (supplies.length > 0) {
|
|
2225
2325
|
lines.push(`${subjectPrefix}Savings: $${fundStatus.supplied.toFixed(2)} at ${(earnings.currentApy * 100).toFixed(2)}% blended APY`);
|
|
@@ -2239,17 +2339,16 @@ function formatSavingsDisplay(result, isSelfQuery = true, address) {
|
|
|
2239
2339
|
}
|
|
2240
2340
|
var savingsInfoTool = buildTool({
|
|
2241
2341
|
name: "savings_info",
|
|
2242
|
-
description:
|
|
2342
|
+
description: 'Get detailed savings positions and earnings for the signed-in user OR any public Sui address or SuiNS name: current deposits by protocol, APY, total yield earned, daily earning rate, and projected monthly returns. Pass `address` as a 0x address OR a SuiNS name (e.g. "alex.sui") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',
|
|
2243
2343
|
inputSchema: z.object({
|
|
2244
|
-
address: z.string().
|
|
2344
|
+
address: z.string().optional().describe("Sui address (0x\u2026) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.")
|
|
2245
2345
|
}),
|
|
2246
2346
|
jsonSchema: {
|
|
2247
2347
|
type: "object",
|
|
2248
2348
|
properties: {
|
|
2249
2349
|
address: {
|
|
2250
2350
|
type: "string",
|
|
2251
|
-
|
|
2252
|
-
description: "Sui address to inspect (defaults to the signed-in wallet)"
|
|
2351
|
+
description: "Sui address (0x\u2026) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet."
|
|
2253
2352
|
}
|
|
2254
2353
|
},
|
|
2255
2354
|
required: []
|
|
@@ -2259,23 +2358,34 @@ var savingsInfoTool = buildTool({
|
|
|
2259
2358
|
// Each call reflects a fresh on-chain snapshot — never dedupe.
|
|
2260
2359
|
cacheable: false,
|
|
2261
2360
|
async call(input, context) {
|
|
2262
|
-
|
|
2361
|
+
let suinsName = null;
|
|
2362
|
+
let targetAddress;
|
|
2363
|
+
if (input.address) {
|
|
2364
|
+
const normalized = await normalizeAddressInput(input.address, {
|
|
2365
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
2366
|
+
signal: context.signal
|
|
2367
|
+
});
|
|
2368
|
+
targetAddress = normalized.address;
|
|
2369
|
+
suinsName = normalized.suinsName;
|
|
2370
|
+
} else {
|
|
2371
|
+
targetAddress = context.walletAddress;
|
|
2372
|
+
}
|
|
2263
2373
|
const isSelfQuery = !!context.walletAddress && !!targetAddress && targetAddress.toLowerCase() === context.walletAddress.toLowerCase();
|
|
2264
2374
|
if (context.positionFetcher && targetAddress) {
|
|
2265
2375
|
const sp = await context.positionFetcher(targetAddress);
|
|
2266
2376
|
const result2 = buildSavingsFromPositions(sp);
|
|
2267
|
-
const stamped2 = { ...result2, address: targetAddress, isSelfQuery };
|
|
2268
|
-
return { data: stamped2, displayText: formatSavingsDisplay(result2, isSelfQuery, targetAddress) };
|
|
2377
|
+
const stamped2 = { ...result2, address: targetAddress, isSelfQuery, suinsName };
|
|
2378
|
+
return { data: stamped2, displayText: formatSavingsDisplay(result2, isSelfQuery, targetAddress, suinsName) };
|
|
2269
2379
|
}
|
|
2270
2380
|
if (hasNaviMcpGlobal(context) && targetAddress) {
|
|
2271
2381
|
const savings = await fetchSavings(getMcpManager(context), targetAddress);
|
|
2272
2382
|
savings.positions = savings.positions.filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);
|
|
2273
|
-
const stamped2 = { ...savings, address: targetAddress, isSelfQuery };
|
|
2274
|
-
return { data: stamped2, displayText: formatSavingsDisplay(savings, isSelfQuery, targetAddress) };
|
|
2383
|
+
const stamped2 = { ...savings, address: targetAddress, isSelfQuery, suinsName };
|
|
2384
|
+
return { data: stamped2, displayText: formatSavingsDisplay(savings, isSelfQuery, targetAddress, suinsName) };
|
|
2275
2385
|
}
|
|
2276
|
-
if (
|
|
2386
|
+
if (targetAddress && context.walletAddress && targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()) {
|
|
2277
2387
|
throw new Error(
|
|
2278
|
-
`Cannot inspect ${
|
|
2388
|
+
`Cannot inspect ${targetAddress.slice(0, 8)}\u2026 without NAVI MCP or a positionFetcher. Configure NAVI MCP to enable third-party address reads.`
|
|
2279
2389
|
);
|
|
2280
2390
|
}
|
|
2281
2391
|
const agent = requireAgent(context);
|
|
@@ -2309,11 +2419,10 @@ var savingsInfoTool = buildTool({
|
|
|
2309
2419
|
projectedMonthly: fundStatus.projectedMonthly
|
|
2310
2420
|
}
|
|
2311
2421
|
};
|
|
2312
|
-
const stamped = { ...result, address: targetAddress ?? "", isSelfQuery: true };
|
|
2313
|
-
return { data: stamped, displayText: formatSavingsDisplay(result, true, void 0) };
|
|
2422
|
+
const stamped = { ...result, address: targetAddress ?? "", isSelfQuery: true, suinsName };
|
|
2423
|
+
return { data: stamped, displayText: formatSavingsDisplay(result, true, void 0, suinsName) };
|
|
2314
2424
|
}
|
|
2315
2425
|
});
|
|
2316
|
-
var SUI_ADDRESS_REGEX3 = /^0x[a-fA-F0-9]{1,64}$/;
|
|
2317
2426
|
var DEBT_DUST_USD = 0.01;
|
|
2318
2427
|
function hfStatus(hf, borrowed) {
|
|
2319
2428
|
if (borrowed <= DEBT_DUST_USD) return "healthy";
|
|
@@ -2327,8 +2436,9 @@ function serializeHf(hf, borrowed) {
|
|
|
2327
2436
|
if (hf == null || !Number.isFinite(hf)) return null;
|
|
2328
2437
|
return hf;
|
|
2329
2438
|
}
|
|
2330
|
-
function displayHfText(hf, borrowed, status, isSelfQuery = true, address) {
|
|
2331
|
-
const
|
|
2439
|
+
function displayHfText(hf, borrowed, status, isSelfQuery = true, address, suinsName) {
|
|
2440
|
+
const subjectLabel = suinsName ?? (address ? `${address.slice(0, 6)}\u2026${address.slice(-4)}` : null);
|
|
2441
|
+
const subject = isSelfQuery || !subjectLabel ? "Health Factor" : `Health Factor for ${subjectLabel}`;
|
|
2332
2442
|
if (hf == null) {
|
|
2333
2443
|
return `${subject}: \u221E (${status} \u2014 no debt)`;
|
|
2334
2444
|
}
|
|
@@ -2336,17 +2446,16 @@ function displayHfText(hf, borrowed, status, isSelfQuery = true, address) {
|
|
|
2336
2446
|
}
|
|
2337
2447
|
var healthCheckTool = buildTool({
|
|
2338
2448
|
name: "health_check",
|
|
2339
|
-
description: 'Check the lending health factor for the signed-in user OR any public Sui address: current HF ratio, total supplied collateral, total borrowed, max additional borrow capacity, and liquidation threshold. HF < 1.5 is risky, < 1.2 is critical. When the address has no debt the tool returns healthFactor=null (semantically infinity) \u2014 render that as "Healthy" / \u221E, never as 0 or "Critical". Pass `address` to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',
|
|
2449
|
+
description: 'Check the lending health factor for the signed-in user OR any public Sui address or SuiNS name: current HF ratio, total supplied collateral, total borrowed, max additional borrow capacity, and liquidation threshold. HF < 1.5 is risky, < 1.2 is critical. When the address has no debt the tool returns healthFactor=null (semantically infinity) \u2014 render that as "Healthy" / \u221E, never as 0 or "Critical". Pass `address` as a 0x address OR a SuiNS name (e.g. "alex.sui") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',
|
|
2340
2450
|
inputSchema: z.object({
|
|
2341
|
-
address: z.string().
|
|
2451
|
+
address: z.string().optional().describe("Sui address (0x\u2026) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.")
|
|
2342
2452
|
}),
|
|
2343
2453
|
jsonSchema: {
|
|
2344
2454
|
type: "object",
|
|
2345
2455
|
properties: {
|
|
2346
2456
|
address: {
|
|
2347
2457
|
type: "string",
|
|
2348
|
-
|
|
2349
|
-
description: "Sui address to inspect (defaults to the signed-in wallet)"
|
|
2458
|
+
description: "Sui address (0x\u2026) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet."
|
|
2350
2459
|
}
|
|
2351
2460
|
},
|
|
2352
2461
|
required: []
|
|
@@ -2356,7 +2465,18 @@ var healthCheckTool = buildTool({
|
|
|
2356
2465
|
// movement and even passively as oracle prices update. Never dedupe.
|
|
2357
2466
|
cacheable: false,
|
|
2358
2467
|
async call(input, context) {
|
|
2359
|
-
|
|
2468
|
+
let suinsName = null;
|
|
2469
|
+
let targetAddress;
|
|
2470
|
+
if (input.address) {
|
|
2471
|
+
const normalized = await normalizeAddressInput(input.address, {
|
|
2472
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
2473
|
+
signal: context.signal
|
|
2474
|
+
});
|
|
2475
|
+
targetAddress = normalized.address;
|
|
2476
|
+
suinsName = normalized.suinsName;
|
|
2477
|
+
} else {
|
|
2478
|
+
targetAddress = context.walletAddress;
|
|
2479
|
+
}
|
|
2360
2480
|
const isSelfQuery = !!context.walletAddress && !!targetAddress && targetAddress.toLowerCase() === context.walletAddress.toLowerCase();
|
|
2361
2481
|
if (context.positionFetcher && targetAddress) {
|
|
2362
2482
|
const sp = await context.positionFetcher(targetAddress);
|
|
@@ -2373,9 +2493,10 @@ var healthCheckTool = buildTool({
|
|
|
2373
2493
|
liquidationThreshold: 0,
|
|
2374
2494
|
status: status2,
|
|
2375
2495
|
address: targetAddress,
|
|
2376
|
-
isSelfQuery
|
|
2496
|
+
isSelfQuery,
|
|
2497
|
+
suinsName
|
|
2377
2498
|
},
|
|
2378
|
-
displayText: displayHfText(transportHf2, borrowed2, status2, isSelfQuery, targetAddress)
|
|
2499
|
+
displayText: displayHfText(transportHf2, borrowed2, status2, isSelfQuery, targetAddress, suinsName)
|
|
2379
2500
|
};
|
|
2380
2501
|
}
|
|
2381
2502
|
if (hasNaviMcpGlobal(context) && targetAddress) {
|
|
@@ -2384,13 +2505,13 @@ var healthCheckTool = buildTool({
|
|
|
2384
2505
|
const status2 = hfStatus(hf2.healthFactor, borrowed2);
|
|
2385
2506
|
const transportHf2 = serializeHf(hf2.healthFactor, borrowed2);
|
|
2386
2507
|
return {
|
|
2387
|
-
data: { ...hf2, healthFactor: transportHf2, status: status2, address: targetAddress, isSelfQuery },
|
|
2388
|
-
displayText: displayHfText(transportHf2, borrowed2, status2, isSelfQuery, targetAddress)
|
|
2508
|
+
data: { ...hf2, healthFactor: transportHf2, status: status2, address: targetAddress, isSelfQuery, suinsName },
|
|
2509
|
+
displayText: displayHfText(transportHf2, borrowed2, status2, isSelfQuery, targetAddress, suinsName)
|
|
2389
2510
|
};
|
|
2390
2511
|
}
|
|
2391
|
-
if (
|
|
2512
|
+
if (targetAddress && context.walletAddress && targetAddress.toLowerCase() !== context.walletAddress.toLowerCase()) {
|
|
2392
2513
|
throw new Error(
|
|
2393
|
-
`Cannot inspect ${
|
|
2514
|
+
`Cannot inspect ${targetAddress.slice(0, 8)}\u2026 without NAVI MCP or a positionFetcher. Configure NAVI MCP to enable third-party address reads.`
|
|
2394
2515
|
);
|
|
2395
2516
|
}
|
|
2396
2517
|
const agent = requireAgent(context);
|
|
@@ -2407,9 +2528,10 @@ var healthCheckTool = buildTool({
|
|
|
2407
2528
|
liquidationThreshold: hf.liquidationThreshold,
|
|
2408
2529
|
status,
|
|
2409
2530
|
address: targetAddress ?? "",
|
|
2410
|
-
isSelfQuery: true
|
|
2531
|
+
isSelfQuery: true,
|
|
2532
|
+
suinsName
|
|
2411
2533
|
},
|
|
2412
|
-
displayText: displayHfText(transportHf, borrowed, status, true, void 0)
|
|
2534
|
+
displayText: displayHfText(transportHf, borrowed, status, true, void 0, suinsName)
|
|
2413
2535
|
};
|
|
2414
2536
|
}
|
|
2415
2537
|
});
|
|
@@ -2633,14 +2755,13 @@ async function queryHistoryByDate(rpcUrl, address, targetDate, limit) {
|
|
|
2633
2755
|
}
|
|
2634
2756
|
var HISTORY_ACTIONS = ["send", "lending", "swap", "transaction"];
|
|
2635
2757
|
var DEFAULT_LOOKBACK_DAYS = 30;
|
|
2636
|
-
var SUI_ADDRESS_REGEX4 = /^0x[0-9a-fA-F]{64}$/;
|
|
2637
2758
|
var transactionHistoryTool = buildTool({
|
|
2638
2759
|
name: "transaction_history",
|
|
2639
2760
|
description: 'Retrieve recent transaction history (last 30 days by default): sends, saves, withdrawals, borrows, repayments, swaps, and rewards claims. Renders a rich transaction card.\n\nBy default, queries the SIGNED-IN USER\'S history. To inspect another wallet (a saved contact, a watched address, any public Sui address), pass `address` \u2014 e.g. user asks "show funkii\'s recent transactions" with funkii at 0x40cd\u20263e62, call with `address: "0x40cd\u20263e62"`. To filter the user\'s own history to a specific counterparty (user asks "show transactions WITH funkii"), pass `counterparty` \u2014 keeps the query rooted in the user\'s wallet but shows only rows where funkii is the recipient or sender.\n\nFilter args: `date` (YYYY-MM-DD), `action` (send/lending/swap), `minUsd` (minimum amount in USD \u2014 use this for "transactions over $X" instead of post-filtering), `assetSymbol` (e.g. "USDC", "SUI"), `direction` ("in" or "out"). The card itself respects all filters \u2014 never re-list the rows in narration.\n\nInternally queries both `FromAddress` and `ToAddress` filters in parallel and dedupes by digest, so pure-receive transactions (someone sends to the queried address with no balance-affecting outbound) are no longer dropped.',
|
|
2640
2761
|
inputSchema: z.object({
|
|
2641
2762
|
limit: z.number().int().min(1).max(50).optional(),
|
|
2642
|
-
address: z.string().
|
|
2643
|
-
counterparty: z.string().
|
|
2763
|
+
address: z.string().optional().describe(`Sui address (0x\u2026) or SuiNS name (e.g. "alex.sui") to query history FOR. When omitted, defaults to the signed-in user's wallet. Pass this when the user asks about a contact's, watched address's, or any other public wallet's history.`),
|
|
2764
|
+
counterparty: z.string().optional().describe('Sui address (0x\u2026) or SuiNS name (e.g. "alex.sui") to filter rows by \u2014 only transactions where the queried address sent to or received from this counterparty are returned. Use for "show transactions with <contact>" queries. Compares against `tx.recipient` (case-insensitive).'),
|
|
2644
2765
|
date: z.string().optional().describe("Specific date to search for transactions (YYYY-MM-DD format). Paginates back to find that day."),
|
|
2645
2766
|
action: z.enum(HISTORY_ACTIONS).optional().describe("Filter by action: send, lending, swap, or transaction."),
|
|
2646
2767
|
minUsd: z.number().min(0).optional().describe('Minimum transaction amount in USD. Use this for "transactions over $X" \u2014 the amount is converted to USD using the asset price snapshot.'),
|
|
@@ -2656,11 +2777,11 @@ var transactionHistoryTool = buildTool({
|
|
|
2656
2777
|
},
|
|
2657
2778
|
address: {
|
|
2658
2779
|
type: "string",
|
|
2659
|
-
description: "Sui address to query history FOR (defaults to the signed-in user when omitted). Use for queries about a contact's, watched address's, or any other wallet's history."
|
|
2780
|
+
description: "Sui address (0x\u2026) or SuiNS name (e.g. alex.sui) to query history FOR (defaults to the signed-in user when omitted). The engine resolves SuiNS names to addresses before querying. Use for queries about a contact's, watched address's, or any other wallet's history."
|
|
2660
2781
|
},
|
|
2661
2782
|
counterparty: {
|
|
2662
2783
|
type: "string",
|
|
2663
|
-
description: 'Sui address to filter rows by \u2014 only transactions where the queried address sent to or received from this counterparty are returned. Use for "show transactions with <contact>" queries.'
|
|
2784
|
+
description: 'Sui address (0x\u2026) or SuiNS name (e.g. alex.sui) to filter rows by \u2014 only transactions where the queried address sent to or received from this counterparty are returned. Use for "show transactions with <contact>" queries.'
|
|
2664
2785
|
},
|
|
2665
2786
|
date: {
|
|
2666
2787
|
type: "string",
|
|
@@ -2734,8 +2855,20 @@ var transactionHistoryTool = buildTool({
|
|
|
2734
2855
|
const assetSymbol = input.assetSymbol?.toLowerCase();
|
|
2735
2856
|
const direction = input.direction;
|
|
2736
2857
|
const minUsd = input.minUsd;
|
|
2737
|
-
const
|
|
2738
|
-
|
|
2858
|
+
const [normalizedAddress, normalizedCounterparty] = await Promise.all([
|
|
2859
|
+
input.address ? normalizeAddressInput(input.address, {
|
|
2860
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
2861
|
+
signal: context.signal
|
|
2862
|
+
}) : Promise.resolve(null),
|
|
2863
|
+
input.counterparty ? normalizeAddressInput(input.counterparty, {
|
|
2864
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
2865
|
+
signal: context.signal
|
|
2866
|
+
}) : Promise.resolve(null)
|
|
2867
|
+
]);
|
|
2868
|
+
const suinsName = normalizedAddress?.suinsName ?? null;
|
|
2869
|
+
const counterpartySuinsName = normalizedCounterparty?.suinsName ?? null;
|
|
2870
|
+
const counterpartyLower = normalizedCounterparty?.address.toLowerCase();
|
|
2871
|
+
const targetAddress = normalizedAddress?.address ?? context.walletAddress;
|
|
2739
2872
|
const isSelfQuery = !!targetAddress && !!context.walletAddress && targetAddress.toLowerCase() === context.walletAddress.toLowerCase();
|
|
2740
2873
|
const prices = context.tokenPrices;
|
|
2741
2874
|
const priceFor2 = (sym) => {
|
|
@@ -2772,9 +2905,13 @@ var transactionHistoryTool = buildTool({
|
|
|
2772
2905
|
minUsd: minUsd ?? null,
|
|
2773
2906
|
assetSymbol: input.assetSymbol ?? null,
|
|
2774
2907
|
direction: direction ?? null,
|
|
2775
|
-
counterparty
|
|
2908
|
+
// Pre-resolved counterparty address (for the LLM/UI). Original
|
|
2909
|
+
// SuiNS name is preserved in `counterpartySuinsName` below.
|
|
2910
|
+
counterparty: normalizedCounterparty?.address ?? null,
|
|
2911
|
+
counterpartySuinsName,
|
|
2776
2912
|
address: targetAddress ?? null,
|
|
2777
|
-
isSelfQuery
|
|
2913
|
+
isSelfQuery,
|
|
2914
|
+
suinsName
|
|
2778
2915
|
};
|
|
2779
2916
|
if (context.agent) {
|
|
2780
2917
|
if (input.address && !isSelfQuery) {
|
|
@@ -3761,23 +3898,37 @@ ${summary}`
|
|
|
3761
3898
|
}
|
|
3762
3899
|
});
|
|
3763
3900
|
var inputSchema3 = z.object({
|
|
3764
|
-
address: z.string().optional().describe("Sui address to analyze
|
|
3901
|
+
address: z.string().optional().describe("Sui address (0x\u2026) or SuiNS name (alex.sui) to analyze. Defaults to the signed-in wallet when omitted.")
|
|
3765
3902
|
});
|
|
3766
3903
|
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "USDe", "USDsui"]);
|
|
3767
3904
|
var portfolioAnalysisTool = buildTool({
|
|
3768
3905
|
name: "portfolio_analysis",
|
|
3769
|
-
description:
|
|
3906
|
+
description: 'Analyze portfolio allocation, risk exposure, and yield optimization for the signed-in user OR any public Sui address or SuiNS name. Shows asset breakdown, diversification score, health factor assessment, and actionable suggestions. Pass `address` as a 0x address OR a SuiNS name (e.g. "alex.sui") to analyze a contact / watched / public wallet.',
|
|
3770
3907
|
inputSchema: inputSchema3,
|
|
3771
3908
|
jsonSchema: {
|
|
3772
3909
|
type: "object",
|
|
3773
3910
|
properties: {
|
|
3774
|
-
address: {
|
|
3911
|
+
address: {
|
|
3912
|
+
type: "string",
|
|
3913
|
+
description: "Sui address (0x\u2026) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet."
|
|
3914
|
+
}
|
|
3775
3915
|
},
|
|
3776
3916
|
required: []
|
|
3777
3917
|
},
|
|
3778
3918
|
isReadOnly: true,
|
|
3779
3919
|
async call(input, context) {
|
|
3780
|
-
|
|
3920
|
+
let suinsName = null;
|
|
3921
|
+
let address;
|
|
3922
|
+
if (input.address) {
|
|
3923
|
+
const normalized = await normalizeAddressInput(input.address, {
|
|
3924
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
3925
|
+
signal: context.signal
|
|
3926
|
+
});
|
|
3927
|
+
address = normalized.address;
|
|
3928
|
+
suinsName = normalized.suinsName;
|
|
3929
|
+
} else {
|
|
3930
|
+
address = context.walletAddress;
|
|
3931
|
+
}
|
|
3781
3932
|
if (!address) {
|
|
3782
3933
|
throw new Error("No wallet address provided. Sign in first.");
|
|
3783
3934
|
}
|
|
@@ -3956,7 +4107,10 @@ var portfolioAnalysisTool = buildTool({
|
|
|
3956
4107
|
savingsApy,
|
|
3957
4108
|
dailyEarning,
|
|
3958
4109
|
weekChange,
|
|
3959
|
-
priceSource: portfolio.source
|
|
4110
|
+
priceSource: portfolio.source,
|
|
4111
|
+
address,
|
|
4112
|
+
isSelfQuery: !!context.walletAddress && address.toLowerCase() === context.walletAddress.toLowerCase(),
|
|
4113
|
+
suinsName
|
|
3960
4114
|
};
|
|
3961
4115
|
const defiSegment = defiValue > 0 ? ` | DeFi: $${defiValue.toFixed(2)}${defiSummary.source === "partial" ? " (partial)" : ""}` : "";
|
|
3962
4116
|
const topLine = `Total: $${totalValue.toFixed(2)} | Wallet: $${walletValue.toFixed(2)} | Savings: $${savingsValue.toFixed(2)}${defiSegment}`;
|
|
@@ -4422,15 +4576,26 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4422
4576
|
async call(input, context) {
|
|
4423
4577
|
const { template, params } = input;
|
|
4424
4578
|
const title = CANVAS_TITLES[template];
|
|
4579
|
+
let suinsName = null;
|
|
4580
|
+
let resolvedParamAddress = null;
|
|
4581
|
+
if (params?.address) {
|
|
4582
|
+
const normalized = await normalizeAddressInput(params.address, {
|
|
4583
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
4584
|
+
signal: context.signal
|
|
4585
|
+
});
|
|
4586
|
+
resolvedParamAddress = normalized.address;
|
|
4587
|
+
suinsName = normalized.suinsName;
|
|
4588
|
+
}
|
|
4425
4589
|
const resolveAddressTarget = () => {
|
|
4426
|
-
const fromParams =
|
|
4590
|
+
const fromParams = resolvedParamAddress;
|
|
4427
4591
|
const fromContext = context.walletAddress;
|
|
4428
4592
|
const target = fromParams ?? fromContext ?? null;
|
|
4429
4593
|
const isSelfRender = !!target && !!fromContext && target.toLowerCase() === fromContext.toLowerCase();
|
|
4430
|
-
return { address: target, isSelfRender };
|
|
4594
|
+
return { address: target, isSelfRender, suinsName };
|
|
4431
4595
|
};
|
|
4596
|
+
const formatAddrLabel = (address, suins) => suins ?? `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
|
|
4432
4597
|
if (template === "full_portfolio") {
|
|
4433
|
-
const { address, isSelfRender } = resolveAddressTarget();
|
|
4598
|
+
const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();
|
|
4434
4599
|
if (!address) {
|
|
4435
4600
|
return {
|
|
4436
4601
|
data: {
|
|
@@ -4442,7 +4607,8 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4442
4607
|
displayText: "Full Portfolio requires an address."
|
|
4443
4608
|
};
|
|
4444
4609
|
}
|
|
4445
|
-
const
|
|
4610
|
+
const addrLabel = formatAddrLabel(address, resolvedSuins);
|
|
4611
|
+
const titleSuffix = isSelfRender ? "" : ` \u2014 ${addrLabel}`;
|
|
4446
4612
|
const pos = isSelfRender ? context.serverPositions : null;
|
|
4447
4613
|
const rate = normalizeSavingsRate(pos?.savingsRate);
|
|
4448
4614
|
const savings = pos?.savings ?? 0;
|
|
@@ -4456,40 +4622,42 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4456
4622
|
available: true,
|
|
4457
4623
|
address,
|
|
4458
4624
|
isSelfRender,
|
|
4625
|
+
suinsName: resolvedSuins,
|
|
4459
4626
|
currentSavings: savings,
|
|
4460
4627
|
currentDebt: borrows,
|
|
4461
4628
|
healthFactor: pos?.healthFactor ?? null,
|
|
4462
4629
|
savingsRate: rate
|
|
4463
4630
|
}
|
|
4464
4631
|
},
|
|
4465
|
-
displayText: isSelfRender ? `Opened Full Portfolio Overview.` : `Opened Full Portfolio Overview for ${
|
|
4632
|
+
displayText: isSelfRender ? `Opened Full Portfolio Overview.` : `Opened Full Portfolio Overview for ${addrLabel}.`
|
|
4466
4633
|
};
|
|
4467
4634
|
}
|
|
4468
4635
|
if (template === "watch_address") {
|
|
4469
|
-
const targetAddress =
|
|
4470
|
-
if (!targetAddress
|
|
4636
|
+
const targetAddress = resolvedParamAddress ?? "";
|
|
4637
|
+
if (!targetAddress) {
|
|
4471
4638
|
return {
|
|
4472
4639
|
data: {
|
|
4473
4640
|
__canvas: true,
|
|
4474
4641
|
template,
|
|
4475
4642
|
title,
|
|
4476
|
-
templateData: { available: false, message: "Please provide a valid Sui address to watch." }
|
|
4643
|
+
templateData: { available: false, message: "Please provide a valid Sui address or SuiNS name to watch." }
|
|
4477
4644
|
},
|
|
4478
|
-
displayText: "No valid address provided. Ask the user for a Sui address."
|
|
4645
|
+
displayText: "No valid address provided. Ask the user for a Sui address or SuiNS name."
|
|
4479
4646
|
};
|
|
4480
4647
|
}
|
|
4648
|
+
const addrLabel = formatAddrLabel(targetAddress, suinsName);
|
|
4481
4649
|
return {
|
|
4482
4650
|
data: {
|
|
4483
4651
|
__canvas: true,
|
|
4484
4652
|
template,
|
|
4485
|
-
title: `Watch ${
|
|
4486
|
-
templateData: { available: true, address: targetAddress }
|
|
4653
|
+
title: `Watch ${addrLabel}`,
|
|
4654
|
+
templateData: { available: true, address: targetAddress, suinsName }
|
|
4487
4655
|
},
|
|
4488
|
-
displayText: `Opened Watch Address canvas for ${
|
|
4656
|
+
displayText: `Opened Watch Address canvas for ${addrLabel}.`
|
|
4489
4657
|
};
|
|
4490
4658
|
}
|
|
4491
4659
|
if (template === "portfolio_timeline") {
|
|
4492
|
-
const { address, isSelfRender } = resolveAddressTarget();
|
|
4660
|
+
const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();
|
|
4493
4661
|
if (!address) {
|
|
4494
4662
|
return {
|
|
4495
4663
|
data: {
|
|
@@ -4501,7 +4669,8 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4501
4669
|
displayText: "Portfolio Timeline requires an address."
|
|
4502
4670
|
};
|
|
4503
4671
|
}
|
|
4504
|
-
const
|
|
4672
|
+
const addrLabel = formatAddrLabel(address, resolvedSuins);
|
|
4673
|
+
const titleSuffix = isSelfRender ? "" : ` \u2014 ${addrLabel}`;
|
|
4505
4674
|
return {
|
|
4506
4675
|
data: {
|
|
4507
4676
|
__canvas: true,
|
|
@@ -4510,14 +4679,15 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4510
4679
|
templateData: {
|
|
4511
4680
|
available: true,
|
|
4512
4681
|
address,
|
|
4513
|
-
isSelfRender
|
|
4682
|
+
isSelfRender,
|
|
4683
|
+
suinsName: resolvedSuins
|
|
4514
4684
|
}
|
|
4515
4685
|
},
|
|
4516
|
-
displayText: isSelfRender ? `Opened Portfolio Timeline. Shows your net worth, savings, and debt over time.` : `Opened Portfolio Timeline for ${
|
|
4686
|
+
displayText: isSelfRender ? `Opened Portfolio Timeline. Shows your net worth, savings, and debt over time.` : `Opened Portfolio Timeline for ${addrLabel}.`
|
|
4517
4687
|
};
|
|
4518
4688
|
}
|
|
4519
4689
|
if (template === "spending_breakdown") {
|
|
4520
|
-
const { address, isSelfRender } = resolveAddressTarget();
|
|
4690
|
+
const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();
|
|
4521
4691
|
if (!address) {
|
|
4522
4692
|
return {
|
|
4523
4693
|
data: {
|
|
@@ -4529,7 +4699,8 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4529
4699
|
displayText: "Spending Breakdown requires an address."
|
|
4530
4700
|
};
|
|
4531
4701
|
}
|
|
4532
|
-
const
|
|
4702
|
+
const addrLabel = formatAddrLabel(address, resolvedSuins);
|
|
4703
|
+
const titleSuffix = isSelfRender ? "" : ` \u2014 ${addrLabel}`;
|
|
4533
4704
|
return {
|
|
4534
4705
|
data: {
|
|
4535
4706
|
__canvas: true,
|
|
@@ -4538,14 +4709,15 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4538
4709
|
templateData: {
|
|
4539
4710
|
available: true,
|
|
4540
4711
|
address,
|
|
4541
|
-
isSelfRender
|
|
4712
|
+
isSelfRender,
|
|
4713
|
+
suinsName: resolvedSuins
|
|
4542
4714
|
}
|
|
4543
4715
|
},
|
|
4544
|
-
displayText: isSelfRender ? `Opened Spending Breakdown. Shows your service spending by category.` : `Opened Spending Breakdown for ${
|
|
4716
|
+
displayText: isSelfRender ? `Opened Spending Breakdown. Shows your service spending by category.` : `Opened Spending Breakdown for ${addrLabel}.`
|
|
4545
4717
|
};
|
|
4546
4718
|
}
|
|
4547
4719
|
if (template === "activity_heatmap") {
|
|
4548
|
-
const { address, isSelfRender } = resolveAddressTarget();
|
|
4720
|
+
const { address, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();
|
|
4549
4721
|
if (!address) {
|
|
4550
4722
|
return {
|
|
4551
4723
|
data: {
|
|
@@ -4557,7 +4729,8 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4557
4729
|
displayText: "Activity Heatmap requires an address."
|
|
4558
4730
|
};
|
|
4559
4731
|
}
|
|
4560
|
-
const
|
|
4732
|
+
const addrLabel = formatAddrLabel(address, resolvedSuins);
|
|
4733
|
+
const titleSuffix = isSelfRender ? "" : ` \u2014 ${addrLabel}`;
|
|
4561
4734
|
return {
|
|
4562
4735
|
data: {
|
|
4563
4736
|
__canvas: true,
|
|
@@ -4566,10 +4739,11 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4566
4739
|
templateData: {
|
|
4567
4740
|
available: true,
|
|
4568
4741
|
address,
|
|
4569
|
-
isSelfRender
|
|
4742
|
+
isSelfRender,
|
|
4743
|
+
suinsName: resolvedSuins
|
|
4570
4744
|
}
|
|
4571
4745
|
},
|
|
4572
|
-
displayText: isSelfRender ? `Opened Activity Heatmap for your wallet. Click any day to explore transactions.` : `Opened Activity Heatmap for ${
|
|
4746
|
+
displayText: isSelfRender ? `Opened Activity Heatmap for your wallet. Click any day to explore transactions.` : `Opened Activity Heatmap for ${addrLabel}. Click any day to explore that address's transactions.`
|
|
4573
4747
|
};
|
|
4574
4748
|
}
|
|
4575
4749
|
const positions = context.serverPositions;
|
|
@@ -4593,13 +4767,13 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4593
4767
|
};
|
|
4594
4768
|
}
|
|
4595
4769
|
if (template === "health_simulator") {
|
|
4596
|
-
const { address: targetAddress, isSelfRender } = resolveAddressTarget();
|
|
4770
|
+
const { address: targetAddress, isSelfRender, suinsName: resolvedSuins } = resolveAddressTarget();
|
|
4597
4771
|
const seedFromPos = isSelfRender;
|
|
4598
4772
|
const seedSavings = seedFromPos ? totalSavings : 0;
|
|
4599
4773
|
const seedBorrows = seedFromPos ? totalBorrows : 0;
|
|
4600
4774
|
const seedHf = seedFromPos ? healthFactor : null;
|
|
4601
4775
|
const roundedDebt = seedBorrows >= 1 ? Math.round(seedBorrows) : seedBorrows > 0 ? parseFloat(seedBorrows.toFixed(4)) : 0;
|
|
4602
|
-
const titleSuffix = !targetAddress || isSelfRender ? "" : ` \u2014 ${targetAddress
|
|
4776
|
+
const titleSuffix = !targetAddress || isSelfRender ? "" : ` \u2014 ${formatAddrLabel(targetAddress, resolvedSuins)}`;
|
|
4603
4777
|
return {
|
|
4604
4778
|
data: {
|
|
4605
4779
|
__canvas: true,
|
|
@@ -4609,6 +4783,7 @@ Always prefer the canvas for visualisation requests. After rendering, offer to e
|
|
|
4609
4783
|
available: true,
|
|
4610
4784
|
address: targetAddress ?? "",
|
|
4611
4785
|
isSelfRender,
|
|
4786
|
+
suinsName: resolvedSuins,
|
|
4612
4787
|
initialCollateral: seedSavings > 0 ? Math.round(seedSavings) : 1500,
|
|
4613
4788
|
initialDebt: roundedDebt > 0 ? roundedDebt : seedSavings > 0 ? 0 : 500,
|
|
4614
4789
|
currentHf: seedHf
|
|
@@ -4729,13 +4904,12 @@ var yieldSummaryTool = buildTool({
|
|
|
4729
4904
|
}
|
|
4730
4905
|
}
|
|
4731
4906
|
});
|
|
4732
|
-
var SUI_ADDRESS_REGEX5 = /^0x[a-fA-F0-9]{1,64}$/;
|
|
4733
4907
|
var activitySummaryTool = buildTool({
|
|
4734
4908
|
name: "activity_summary",
|
|
4735
|
-
description:
|
|
4909
|
+
description: 'Returns a categorised DeFi activity summary for the signed-in user OR any public Sui address or SuiNS name: transaction count, breakdown by action type (saves, sends, borrows, repayments, swaps, payments), total moved, net savings change, and yield earned. Use when the user asks about activity, transaction history summary, or what someone has done recently. Pass `address` as a 0x address OR a SuiNS name (e.g. "alex.sui") to inspect a contact / watched / public wallet; defaults to the signed-in user when omitted.',
|
|
4736
4910
|
inputSchema: z.object({
|
|
4737
4911
|
period: z.enum(["week", "month", "year", "all"]).optional().describe("Time period. Defaults to current month."),
|
|
4738
|
-
address: z.string().
|
|
4912
|
+
address: z.string().optional().describe("Sui address (0x\u2026) or SuiNS name (alex.sui). Defaults to the signed-in wallet when omitted.")
|
|
4739
4913
|
}),
|
|
4740
4914
|
jsonSchema: {
|
|
4741
4915
|
type: "object",
|
|
@@ -4743,8 +4917,7 @@ var activitySummaryTool = buildTool({
|
|
|
4743
4917
|
period: { type: "string", enum: ["week", "month", "year", "all"] },
|
|
4744
4918
|
address: {
|
|
4745
4919
|
type: "string",
|
|
4746
|
-
|
|
4747
|
-
description: "Sui address to inspect (defaults to the signed-in wallet)"
|
|
4920
|
+
description: "Sui address (0x\u2026) or SuiNS name (e.g. alex.sui). The engine resolves the name to an on-chain address before querying. Omit to default to the signed-in wallet."
|
|
4748
4921
|
}
|
|
4749
4922
|
}
|
|
4750
4923
|
},
|
|
@@ -4752,7 +4925,18 @@ var activitySummaryTool = buildTool({
|
|
|
4752
4925
|
async call(input, context) {
|
|
4753
4926
|
const period = input.period ?? "month";
|
|
4754
4927
|
const apiUrl = context.env?.AUDRIC_INTERNAL_API_URL;
|
|
4755
|
-
|
|
4928
|
+
let suinsName = null;
|
|
4929
|
+
let targetAddress;
|
|
4930
|
+
if (input.address) {
|
|
4931
|
+
const normalized = await normalizeAddressInput(input.address, {
|
|
4932
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
4933
|
+
signal: context.signal
|
|
4934
|
+
});
|
|
4935
|
+
targetAddress = normalized.address;
|
|
4936
|
+
suinsName = normalized.suinsName;
|
|
4937
|
+
} else {
|
|
4938
|
+
targetAddress = context.walletAddress;
|
|
4939
|
+
}
|
|
4756
4940
|
const isSelfQuery = !!context.walletAddress && !!targetAddress && targetAddress.toLowerCase() === context.walletAddress.toLowerCase();
|
|
4757
4941
|
const empty = {
|
|
4758
4942
|
period,
|
|
@@ -4762,7 +4946,8 @@ var activitySummaryTool = buildTool({
|
|
|
4762
4946
|
netSavingsUsd: 0,
|
|
4763
4947
|
yieldEarnedUsd: 0,
|
|
4764
4948
|
address: targetAddress,
|
|
4765
|
-
isSelfQuery
|
|
4949
|
+
isSelfQuery,
|
|
4950
|
+
suinsName
|
|
4766
4951
|
};
|
|
4767
4952
|
if (!apiUrl || !targetAddress) {
|
|
4768
4953
|
return { data: empty, displayText: "Activity summary not available." };
|
|
@@ -4777,11 +4962,12 @@ var activitySummaryTool = buildTool({
|
|
|
4777
4962
|
return { data: empty, displayText: `Could not fetch activity data (HTTP ${res.status}).` };
|
|
4778
4963
|
}
|
|
4779
4964
|
const raw = await res.json();
|
|
4780
|
-
const data = { ...raw, address: targetAddress, isSelfQuery };
|
|
4965
|
+
const data = { ...raw, address: targetAddress, isSelfQuery, suinsName };
|
|
4781
4966
|
const sorted = [...data.byAction ?? []].sort((a, b) => b.count - a.count);
|
|
4782
4967
|
const top = sorted.slice(0, 3).map((a) => `${a.action} (${a.count})`).join(", ");
|
|
4783
4968
|
const periodLabel = data.period === "all" ? "all time" : `this ${data.period}`;
|
|
4784
|
-
const
|
|
4969
|
+
const subjectLabel = suinsName ?? `${targetAddress.slice(0, 6)}\u2026${targetAddress.slice(-4)}`;
|
|
4970
|
+
const subjectPrefix = isSelfQuery ? "" : `${subjectLabel} \u2014 `;
|
|
4785
4971
|
return {
|
|
4786
4972
|
data,
|
|
4787
4973
|
displayText: data.totalTransactions > 0 ? `${subjectPrefix}${data.totalTransactions} transactions ${periodLabel}. Top: ${top}. Total moved: $${data.totalMovedUsd.toFixed(2)}. Net savings: $${data.netSavingsUsd.toFixed(2)}.` : `${subjectPrefix}No activity recorded for ${periodLabel}.`
|
|
@@ -4791,6 +4977,67 @@ var activitySummaryTool = buildTool({
|
|
|
4791
4977
|
}
|
|
4792
4978
|
}
|
|
4793
4979
|
});
|
|
4980
|
+
var inputSchema5 = z.object({
|
|
4981
|
+
name: z.string().describe(
|
|
4982
|
+
'A SuiNS name ending in `.sui` (e.g. "alex.sui", "team.alex.sui"). The engine resolves the name on-chain via Sui JSON-RPC.'
|
|
4983
|
+
)
|
|
4984
|
+
});
|
|
4985
|
+
var resolveSuinsTool = buildTool({
|
|
4986
|
+
name: "resolve_suins",
|
|
4987
|
+
description: 'Resolve a SuiNS name (e.g. "alex.sui", "obehi.sui") to its on-chain Sui address. Use this whenever the user asks for the address of a `.sui` name, asks who owns a name, or wants to verify a SuiNS name is registered. Returns the 0x-prefixed 64-hex address, or `registered: false` when the name isn\'t registered. Never use `web_search` for this \u2014 web_search doesn\'t index SuiNS records, but this tool queries the canonical on-chain registry. NOTE: For lookup queries about money flows ("what\'s alex.sui\'s balance / portfolio / health / transactions"), call the relevant read tool directly with `address: "alex.sui"` \u2014 those tools normalize SuiNS names internally, so an explicit `resolve_suins` round-trip is wasted.',
|
|
4988
|
+
inputSchema: inputSchema5,
|
|
4989
|
+
jsonSchema: {
|
|
4990
|
+
type: "object",
|
|
4991
|
+
properties: {
|
|
4992
|
+
name: {
|
|
4993
|
+
type: "string",
|
|
4994
|
+
description: 'A SuiNS name ending in .sui (e.g. "alex.sui"). The engine resolves it on-chain.'
|
|
4995
|
+
}
|
|
4996
|
+
},
|
|
4997
|
+
required: ["name"]
|
|
4998
|
+
},
|
|
4999
|
+
isReadOnly: true,
|
|
5000
|
+
// Names map to addresses on a per-block basis (registry can change).
|
|
5001
|
+
// Cheap, deterministic for a given block — safe to dedupe within a turn.
|
|
5002
|
+
cacheable: true,
|
|
5003
|
+
preflight: (input) => {
|
|
5004
|
+
const trimmed = input.name?.trim().toLowerCase();
|
|
5005
|
+
if (!trimmed) {
|
|
5006
|
+
return { valid: false, error: "name is required" };
|
|
5007
|
+
}
|
|
5008
|
+
if (!SUINS_NAME_REGEX.test(trimmed)) {
|
|
5009
|
+
return {
|
|
5010
|
+
valid: false,
|
|
5011
|
+
error: `"${input.name}" doesn't look like a SuiNS name. Names must end in .sui and use only lowercase letters, digits, and hyphens (e.g. alex.sui).`
|
|
5012
|
+
};
|
|
5013
|
+
}
|
|
5014
|
+
return { valid: true };
|
|
5015
|
+
},
|
|
5016
|
+
async call(input, context) {
|
|
5017
|
+
const name = input.name.trim().toLowerCase();
|
|
5018
|
+
let address;
|
|
5019
|
+
try {
|
|
5020
|
+
address = await resolveSuinsViaRpc(name, {
|
|
5021
|
+
suiRpcUrl: context.suiRpcUrl,
|
|
5022
|
+
signal: context.signal
|
|
5023
|
+
});
|
|
5024
|
+
} catch (err) {
|
|
5025
|
+
if (err instanceof SuinsRpcError) {
|
|
5026
|
+
throw err;
|
|
5027
|
+
}
|
|
5028
|
+
throw err;
|
|
5029
|
+
}
|
|
5030
|
+
const result = {
|
|
5031
|
+
name,
|
|
5032
|
+
address,
|
|
5033
|
+
registered: address !== null
|
|
5034
|
+
};
|
|
5035
|
+
return {
|
|
5036
|
+
data: result,
|
|
5037
|
+
displayText: address ? `${name} \u2192 \`${address.slice(0, 10)}\u2026${address.slice(-6)}\`` : `${name} is not a registered SuiNS name.`
|
|
5038
|
+
};
|
|
5039
|
+
}
|
|
5040
|
+
});
|
|
4794
5041
|
var tokenPricesTool = buildTool({
|
|
4795
5042
|
name: "token_prices",
|
|
4796
5043
|
description: 'Get current USD prices for Sui tokens, with optional 24h change. Accepts full coin type strings (e.g. "0x2::sui::SUI"). Returns price per token and (when requested) 24h change percentage. Use for "what is X worth?" or "did Y move today?". For balance + portfolio rendering, prefer balance_check / portfolio_analysis instead \u2014 they bundle the same prices into the standard cards.',
|
|
@@ -4872,7 +5119,8 @@ var READ_TOOLS = [
|
|
|
4872
5119
|
createInvoiceTool,
|
|
4873
5120
|
spendingAnalyticsTool,
|
|
4874
5121
|
yieldSummaryTool,
|
|
4875
|
-
activitySummaryTool
|
|
5122
|
+
activitySummaryTool,
|
|
5123
|
+
resolveSuinsTool
|
|
4876
5124
|
];
|
|
4877
5125
|
var WRITE_TOOLS = [
|
|
4878
5126
|
saveDepositTool,
|
|
@@ -5274,7 +5522,7 @@ function guardCostWarning(tool, _call, conversationText) {
|
|
|
5274
5522
|
message: "This action has a monetary cost. Confirm the user is aware before proceeding."
|
|
5275
5523
|
};
|
|
5276
5524
|
}
|
|
5277
|
-
var
|
|
5525
|
+
var SUI_ADDRESS_REGEX2 = /^0x[a-fA-F0-9]{64}$/;
|
|
5278
5526
|
function normalizeAddress(addr) {
|
|
5279
5527
|
return addr.trim().toLowerCase();
|
|
5280
5528
|
}
|
|
@@ -5339,7 +5587,7 @@ function guardAddressSource(tool, call, userText, contacts, walletAddress) {
|
|
|
5339
5587
|
if (!rawTo) {
|
|
5340
5588
|
return { verdict: "pass", gate: "address_source", tier: "safety" };
|
|
5341
5589
|
}
|
|
5342
|
-
if (!
|
|
5590
|
+
if (!SUI_ADDRESS_REGEX2.test(rawTo)) {
|
|
5343
5591
|
return { verdict: "pass", gate: "address_source", tier: "safety" };
|
|
5344
5592
|
}
|
|
5345
5593
|
const normalizedTo = normalizeAddress(rawTo);
|
|
@@ -8268,6 +8516,6 @@ function sanitizeAnthropicMessages(messages) {
|
|
|
8268
8516
|
return merged;
|
|
8269
8517
|
}
|
|
8270
8518
|
|
|
8271
|
-
export { AnthropicProvider, BalanceTracker, CANVAS_TEMPLATES, ContextBudget, CostTracker, DEFAULT_GUARD_CONFIG, DEFAULT_LEASE_SEC, DEFAULT_PERMISSION_CONFIG, DEFAULT_POLL_BUDGET_MS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_SYSTEM_PROMPT, EarlyToolDispatcher, InMemoryDefiCacheStore, InMemoryFetchLock, InMemoryNaviCacheStore, InMemoryWalletCacheStore, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_ADDR_TTL_SEC, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_RATES_TTL_SEC, NAVI_SERVER_NAME, NaviTools, PERMISSION_PRESETS, QueryEngine, READ_TOOLS, RecipeRegistry, RetryTracker, TOOL_FLAGS, TOOL_MODIFIABLE_FIELDS, TxMutex, WRITE_TOOLS, _resetNaviCircuitBreaker, activitySummaryTool, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, applyToolFlags, awaitOrFetch, balanceCheckTool, borrowTool, budgetToolResult, buildCachedSystemPrompt, buildMcpTools, buildProactivenessInstructions, buildProfileContext, buildSelfEvaluationInstruction, buildStateContext, buildTool, claimRewardsTool, classifyEffort, clearPortfolioCache, clearPortfolioCacheFor, clearPriceMapCache, compactMessages, createGuardRunnerState, engineToSSE, estimateTokens, explainTxTool, extractConversationText, extractMcpText, fetchAddressDefiPortfolio, fetchAddressPortfolio, fetchAudricHistory, fetchAudricPortfolio, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchTokenPrices, fetchWalletCoins, findTool, getAudricApiBase, getDefaultTools, getDefiCacheStore, getFetchLock, getMcpManager, getModifiableFields, getNaviCacheStore, getTelemetrySink, getToolFlags, getWalletAddress, getWalletCacheStore, guardArtifactPreview, guardStaleData, hasNaviMcp, healthCheckTool, loadRecipes, microcompact, mppServicesTool, naviKey, parseMcpJson, parseRecipe, parseSSE, payApiTool, portfolioAnalysisTool, protocolDeepDiveTool, ratesInfoTool, registerEngineTools, renderCanvasTool, repayDebtTool, requireAgent, resetDefiCacheStore, resetFetchLock, resetNaviCacheStore, resetTelemetrySink, resetWalletCacheStore, resolvePermissionTier, resolveUsdValue, runGuards, runTools, saveContactTool, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, setDefiCacheStore, setFetchLock, setNaviCacheStore, setTelemetrySink, setWalletCacheStore, spendingAnalyticsTool, swapExecuteTool, swapQuoteTool, tokenPricesTool, toolNameToOperation, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, updateGuardStateAfterToolResult, validateHistory, voloStakeTool, voloStatsTool, voloUnstakeTool, webSearchTool, withdrawTool, yieldSummaryTool };
|
|
8519
|
+
export { AnthropicProvider, BalanceTracker, CANVAS_TEMPLATES, ContextBudget, CostTracker, DEFAULT_GUARD_CONFIG, DEFAULT_LEASE_SEC, DEFAULT_PERMISSION_CONFIG, DEFAULT_POLL_BUDGET_MS, DEFAULT_POLL_INTERVAL_MS, DEFAULT_SYSTEM_PROMPT, EarlyToolDispatcher, InMemoryDefiCacheStore, InMemoryFetchLock, InMemoryNaviCacheStore, InMemoryWalletCacheStore, InvalidAddressError, McpClientManager, McpResponseCache, MemorySessionStore, NAVI_ADDR_TTL_SEC, NAVI_MCP_CONFIG, NAVI_MCP_URL, NAVI_RATES_TTL_SEC, NAVI_SERVER_NAME, NaviTools, PERMISSION_PRESETS, QueryEngine, READ_TOOLS, RecipeRegistry, RetryTracker, SUINS_NAME_REGEX, SUI_ADDRESS_REGEX, SUI_ADDRESS_STRICT_REGEX, SuinsNotRegisteredError, SuinsRpcError, TOOL_FLAGS, TOOL_MODIFIABLE_FIELDS, TxMutex, WRITE_TOOLS, _resetNaviCircuitBreaker, activitySummaryTool, adaptAllMcpTools, adaptAllServerTools, adaptMcpTool, applyToolFlags, awaitOrFetch, balanceCheckTool, borrowTool, budgetToolResult, buildCachedSystemPrompt, buildMcpTools, buildProactivenessInstructions, buildProfileContext, buildSelfEvaluationInstruction, buildStateContext, buildTool, claimRewardsTool, classifyEffort, clearPortfolioCache, clearPortfolioCacheFor, clearPriceMapCache, compactMessages, createGuardRunnerState, engineToSSE, estimateTokens, explainTxTool, extractConversationText, extractMcpText, fetchAddressDefiPortfolio, fetchAddressPortfolio, fetchAudricHistory, fetchAudricPortfolio, fetchAvailableRewards, fetchBalance, fetchHealthFactor, fetchPositions, fetchProtocolStats, fetchRates, fetchSavings, fetchTokenPrices, fetchWalletCoins, findTool, getAudricApiBase, getDefaultTools, getDefiCacheStore, getFetchLock, getMcpManager, getModifiableFields, getNaviCacheStore, getTelemetrySink, getToolFlags, getWalletAddress, getWalletCacheStore, guardArtifactPreview, guardStaleData, hasNaviMcp, healthCheckTool, loadRecipes, looksLikeSuiNs, microcompact, mppServicesTool, naviKey, normalizeAddressInput, parseMcpJson, parseRecipe, parseSSE, payApiTool, portfolioAnalysisTool, protocolDeepDiveTool, ratesInfoTool, registerEngineTools, renderCanvasTool, repayDebtTool, requireAgent, resetDefiCacheStore, resetFetchLock, resetNaviCacheStore, resetTelemetrySink, resetWalletCacheStore, resolvePermissionTier, resolveSuinsTool, resolveSuinsViaRpc, resolveUsdValue, runGuards, runTools, saveContactTool, saveDepositTool, savingsInfoTool, sendTransferTool, serializeSSE, setDefiCacheStore, setFetchLock, setNaviCacheStore, setTelemetrySink, setWalletCacheStore, spendingAnalyticsTool, swapExecuteTool, swapQuoteTool, tokenPricesTool, toolNameToOperation, toolsToDefinitions, transactionHistoryTool, transformBalance, transformHealthFactor, transformPositions, transformRates, transformRewards, transformSavings, updateGuardStateAfterToolResult, validateHistory, voloStakeTool, voloStatsTool, voloUnstakeTool, webSearchTool, withdrawTool, yieldSummaryTool };
|
|
8272
8520
|
//# sourceMappingURL=index.js.map
|
|
8273
8521
|
//# sourceMappingURL=index.js.map
|