@t2000/engine 0.7.0 → 0.7.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/README.md +6 -2
- package/dist/index.js +54 -29
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -87,7 +87,7 @@ QueryEngine.submitMessage()
|
|
|
87
87
|
|
|
88
88
|
## Built-in Tools
|
|
89
89
|
|
|
90
|
-
### Read Tools (
|
|
90
|
+
### Read Tools (19 — parallel, auto-approved)
|
|
91
91
|
|
|
92
92
|
| Tool | Description |
|
|
93
93
|
|------|-------------|
|
|
@@ -100,6 +100,9 @@ QueryEngine.submitMessage()
|
|
|
100
100
|
| `web_search` | Web search via Brave Search API |
|
|
101
101
|
| `swap_quote` | Preview swap route, output amount, and price impact (no execution) |
|
|
102
102
|
| `volo_stats` | VOLO liquid staking stats — vSUI/SUI rate, APY, TVL |
|
|
103
|
+
| `portfolio_analysis` | Portfolio breakdown with diversification insights |
|
|
104
|
+
| `protocol_deep_dive` | Deep protocol analysis — TVL, yields, risks, alternatives |
|
|
105
|
+
| `mpp_services` | Browse available MPP gateway services and endpoints |
|
|
103
106
|
| `defillama_yield_pools` | Top yield pools by APY, filterable by chain |
|
|
104
107
|
| `defillama_protocol_info` | Protocol TVL, category, chains |
|
|
105
108
|
| `defillama_token_prices` | Current USD prices for Sui tokens |
|
|
@@ -108,7 +111,7 @@ QueryEngine.submitMessage()
|
|
|
108
111
|
| `defillama_protocol_fees` | Protocol fees/revenue rankings |
|
|
109
112
|
| `defillama_sui_protocols` | Sui ecosystem protocols — TVL, category, changes |
|
|
110
113
|
|
|
111
|
-
### Write Tools (
|
|
114
|
+
### Write Tools (11 — serial, confirmation required)
|
|
112
115
|
|
|
113
116
|
| Tool | Description |
|
|
114
117
|
|------|-------------|
|
|
@@ -122,6 +125,7 @@ QueryEngine.submitMessage()
|
|
|
122
125
|
| `swap_execute` | Swap any token pair via Cetus Aggregator (20+ DEXs) |
|
|
123
126
|
| `volo_stake` | Stake SUI for vSUI (VOLO liquid staking) |
|
|
124
127
|
| `volo_unstake` | Unstake vSUI back to SUI |
|
|
128
|
+
| `save_contact` | Save a contact name + address for quick sends |
|
|
125
129
|
|
|
126
130
|
## Configuration
|
|
127
131
|
|
package/dist/index.js
CHANGED
|
@@ -336,11 +336,10 @@ function transformRewards(raw) {
|
|
|
336
336
|
var STABLECOIN_SYMBOLS = /* @__PURE__ */ new Set([
|
|
337
337
|
"USDC",
|
|
338
338
|
"USDT",
|
|
339
|
+
"USDe",
|
|
340
|
+
"USDsui",
|
|
339
341
|
"wUSDC",
|
|
340
342
|
"wUSDT",
|
|
341
|
-
"FDUSD",
|
|
342
|
-
"AUSD",
|
|
343
|
-
"BUCK",
|
|
344
343
|
"suiUSDe",
|
|
345
344
|
"USDSUI"
|
|
346
345
|
]);
|
|
@@ -539,7 +538,7 @@ var balanceCheckTool = buildTool({
|
|
|
539
538
|
let availableUsd = 0;
|
|
540
539
|
let stablesUsd = 0;
|
|
541
540
|
let gasReserveUsd2 = 0;
|
|
542
|
-
const STABLE_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USDT", "
|
|
541
|
+
const STABLE_SYMBOLS = /* @__PURE__ */ new Set(["USDC", "USDT", "USDe", "USDsui", "wUSDC", "wUSDT"]);
|
|
543
542
|
const holdings = [];
|
|
544
543
|
for (const coin of coins) {
|
|
545
544
|
const balance2 = Number(coin.totalBalance) / 10 ** coin.decimals;
|
|
@@ -578,6 +577,7 @@ var balanceCheckTool = buildTool({
|
|
|
578
577
|
debt = posEntries.filter((p) => p.type === "borrow").reduce((sum, p) => sum + p.valueUsd, 0);
|
|
579
578
|
pendingRewardsUsd = rewardEntries.reduce((sum, r) => sum + r.valueUsd, 0);
|
|
580
579
|
}
|
|
580
|
+
const visibleHoldings = holdings.filter((h) => h.usdValue >= 0.01).sort((a, b) => b.usdValue - a.usdValue);
|
|
581
581
|
const bal = {
|
|
582
582
|
available: availableUsd,
|
|
583
583
|
savings,
|
|
@@ -586,7 +586,7 @@ var balanceCheckTool = buildTool({
|
|
|
586
586
|
gasReserve: gasReserveUsd2,
|
|
587
587
|
total: availableUsd + savings + gasReserveUsd2 + pendingRewardsUsd - debt,
|
|
588
588
|
stables: stablesUsd,
|
|
589
|
-
holdings:
|
|
589
|
+
holdings: visibleHoldings
|
|
590
590
|
};
|
|
591
591
|
return {
|
|
592
592
|
data: bal,
|
|
@@ -701,9 +701,10 @@ async function fetchProtocolStats(manager, opts) {
|
|
|
701
701
|
}
|
|
702
702
|
|
|
703
703
|
// src/tools/savings.ts
|
|
704
|
+
var DUST_THRESHOLD_USD = 0.01;
|
|
704
705
|
function buildSavingsFromPositions(sp) {
|
|
705
706
|
const positions = [
|
|
706
|
-
...sp.supplies.map((s) => ({
|
|
707
|
+
...sp.supplies.filter((s) => s.amountUsd >= DUST_THRESHOLD_USD).map((s) => ({
|
|
707
708
|
protocol: s.protocol,
|
|
708
709
|
type: "supply",
|
|
709
710
|
symbol: s.asset,
|
|
@@ -712,7 +713,7 @@ function buildSavingsFromPositions(sp) {
|
|
|
712
713
|
apy: s.apy,
|
|
713
714
|
liquidationThreshold: 0
|
|
714
715
|
})),
|
|
715
|
-
...sp.borrows_detail.map((b) => ({
|
|
716
|
+
...sp.borrows_detail.filter((b) => b.amountUsd >= DUST_THRESHOLD_USD).map((b) => ({
|
|
716
717
|
protocol: b.protocol,
|
|
717
718
|
type: "borrow",
|
|
718
719
|
symbol: b.asset,
|
|
@@ -742,6 +743,27 @@ function buildSavingsFromPositions(sp) {
|
|
|
742
743
|
}
|
|
743
744
|
};
|
|
744
745
|
}
|
|
746
|
+
function formatSavingsDisplay(result) {
|
|
747
|
+
const { positions, earnings, fundStatus } = result;
|
|
748
|
+
const supplies = positions.filter((p) => p.type === "supply");
|
|
749
|
+
const borrows = positions.filter((p) => p.type === "borrow");
|
|
750
|
+
const lines = [];
|
|
751
|
+
if (supplies.length > 0) {
|
|
752
|
+
lines.push(`Savings: $${fundStatus.supplied.toFixed(2)} at ${(earnings.currentApy * 100).toFixed(2)}% blended APY`);
|
|
753
|
+
for (const s of supplies) {
|
|
754
|
+
lines.push(` ${s.symbol}: ${s.amount.toFixed(s.amount < 1 ? 6 : 2)} ($${s.valueUsd.toFixed(2)}) at ${(s.apy * 100).toFixed(2)}% APY`);
|
|
755
|
+
}
|
|
756
|
+
} else {
|
|
757
|
+
lines.push("No savings positions.");
|
|
758
|
+
}
|
|
759
|
+
if (borrows.length > 0) {
|
|
760
|
+
const totalDebt = borrows.reduce((s, b) => s + b.valueUsd, 0);
|
|
761
|
+
lines.push(`Debt: $${totalDebt.toFixed(2)}`);
|
|
762
|
+
}
|
|
763
|
+
lines.push(`Daily earnings: $${fundStatus.earnedToday.toFixed(4)}`);
|
|
764
|
+
lines.push(`Monthly projected: $${fundStatus.projectedMonthly.toFixed(4)}`);
|
|
765
|
+
return lines.join("\n");
|
|
766
|
+
}
|
|
745
767
|
var savingsInfoTool = buildTool({
|
|
746
768
|
name: "savings_info",
|
|
747
769
|
description: "Get detailed savings positions and earnings: current deposits by protocol, APY, total yield earned, daily earning rate, and projected monthly returns.",
|
|
@@ -751,14 +773,16 @@ var savingsInfoTool = buildTool({
|
|
|
751
773
|
async call(_input, context) {
|
|
752
774
|
if (context.positionFetcher && context.walletAddress) {
|
|
753
775
|
const sp = await context.positionFetcher(context.walletAddress);
|
|
754
|
-
|
|
776
|
+
const result2 = buildSavingsFromPositions(sp);
|
|
777
|
+
return { data: result2, displayText: formatSavingsDisplay(result2) };
|
|
755
778
|
}
|
|
756
779
|
if (hasNaviMcp(context)) {
|
|
757
780
|
const savings = await fetchSavings(
|
|
758
781
|
getMcpManager(context),
|
|
759
782
|
getWalletAddress(context)
|
|
760
783
|
);
|
|
761
|
-
|
|
784
|
+
savings.positions = savings.positions.filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);
|
|
785
|
+
return { data: savings, displayText: formatSavingsDisplay(savings) };
|
|
762
786
|
}
|
|
763
787
|
const agent = requireAgent(context);
|
|
764
788
|
const [posResult, earnings, fundStatus] = await Promise.all([
|
|
@@ -774,25 +798,24 @@ var savingsInfoTool = buildTool({
|
|
|
774
798
|
valueUsd: p.amountUsd ?? p.valueUsd ?? 0,
|
|
775
799
|
apy: p.apy ?? 0,
|
|
776
800
|
liquidationThreshold: p.liquidationThreshold ?? 0
|
|
777
|
-
}));
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
projectedMonthly: fundStatus.projectedMonthly
|
|
793
|
-
}
|
|
801
|
+
})).filter((p) => p.valueUsd >= DUST_THRESHOLD_USD);
|
|
802
|
+
const result = {
|
|
803
|
+
positions,
|
|
804
|
+
earnings: {
|
|
805
|
+
totalYieldEarned: earnings.totalYieldEarned,
|
|
806
|
+
currentApy: earnings.currentApy,
|
|
807
|
+
dailyEarning: earnings.dailyEarning,
|
|
808
|
+
supplied: earnings.supplied
|
|
809
|
+
},
|
|
810
|
+
fundStatus: {
|
|
811
|
+
supplied: fundStatus.supplied,
|
|
812
|
+
apy: fundStatus.apy,
|
|
813
|
+
earnedToday: fundStatus.earnedToday,
|
|
814
|
+
earnedAllTime: fundStatus.earnedAllTime,
|
|
815
|
+
projectedMonthly: fundStatus.projectedMonthly
|
|
794
816
|
}
|
|
795
817
|
};
|
|
818
|
+
return { data: result, displayText: formatSavingsDisplay(result) };
|
|
796
819
|
}
|
|
797
820
|
});
|
|
798
821
|
function hfStatus(hf) {
|
|
@@ -1710,7 +1733,7 @@ ${summary}`
|
|
|
1710
1733
|
var inputSchema3 = z.object({
|
|
1711
1734
|
address: z.string().optional().describe("Sui address to analyze (defaults to connected wallet)")
|
|
1712
1735
|
});
|
|
1713
|
-
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "USDe", "USDsui"
|
|
1736
|
+
var STABLECOINS = /* @__PURE__ */ new Set(["USDC", "USDT", "USDe", "USDsui"]);
|
|
1714
1737
|
var portfolioAnalysisTool = buildTool({
|
|
1715
1738
|
name: "portfolio_analysis",
|
|
1716
1739
|
description: "Analyze portfolio allocation, risk exposure, and yield optimization. Shows asset breakdown, diversification score, health factor assessment, and actionable suggestions.",
|
|
@@ -1729,18 +1752,20 @@ var portfolioAnalysisTool = buildTool({
|
|
|
1729
1752
|
throw new Error("No wallet address provided. Sign in first.");
|
|
1730
1753
|
}
|
|
1731
1754
|
const rpcUrl = context.suiRpcUrl ?? "https://fullnode.mainnet.sui.io:443";
|
|
1755
|
+
const DUST_USD = 0.01;
|
|
1732
1756
|
const coins = await fetchWalletCoins(address, rpcUrl);
|
|
1733
1757
|
const nonZero = coins.filter((c) => Number(c.totalBalance) > 0);
|
|
1734
1758
|
const prices = await fetchTokenPrices(nonZero.map((c) => c.coinType)).catch(() => ({}));
|
|
1735
1759
|
let walletValue = 0;
|
|
1736
|
-
const
|
|
1760
|
+
const allAllocations = [];
|
|
1737
1761
|
for (const coin of nonZero) {
|
|
1738
1762
|
const amount = Number(coin.totalBalance) / 10 ** coin.decimals;
|
|
1739
1763
|
const price = prices[coin.coinType] ?? 0;
|
|
1740
1764
|
const usdValue = amount * price;
|
|
1741
1765
|
walletValue += usdValue;
|
|
1742
|
-
|
|
1766
|
+
allAllocations.push({ symbol: coin.symbol, amount, usdValue, percentage: 0 });
|
|
1743
1767
|
}
|
|
1768
|
+
const allocations = allAllocations.filter((a) => a.usdValue >= DUST_USD);
|
|
1744
1769
|
let savingsValue = 0;
|
|
1745
1770
|
let debtValue = 0;
|
|
1746
1771
|
let healthFactor = null;
|