@elizaos/plugin-wallet 2.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +64 -0
- package/auto-enable.ts +76 -0
- package/dist/LpManagementService-BWrQ5-cO.mjs +353 -0
- package/dist/MockLpService-D_Apn4Fd.mjs +99 -0
- package/dist/aerodrome-CfnESC32.mjs +890 -0
- package/dist/chunk-hT5z_Zn9.mjs +35 -0
- package/dist/index.d.mts +34727 -0
- package/dist/index.mjs +21590 -0
- package/dist/lib/server-wallet-trade.d.mts +34 -0
- package/dist/lib/server-wallet-trade.mjs +306 -0
- package/dist/meteora-BPX39hZo.mjs +22640 -0
- package/dist/orca-Bybp1HXO.mjs +249 -0
- package/dist/pancakeswp-CkEXlXti.mjs +604 -0
- package/dist/plugin-ZO_MTyd0.mjs +529 -0
- package/dist/raydium-rfaM9yEf.mjs +539 -0
- package/dist/sdk/index.d.mts +32492 -0
- package/dist/sdk/index.mjs +6415 -0
- package/dist/types-D5252NZk.mjs +487 -0
- package/dist/uniswap-CReXgXVN.mjs +573 -0
- package/dist/wallet-action.d.mts +6 -0
- package/dist/wallet-action.mjs +820 -0
- package/package.json +152 -0
- package/src/actions/failure-codes.ts +79 -0
- package/src/actions/index.ts +1 -0
- package/src/analytics/birdeye/actions/wallet-search-address.ts +9 -0
- package/src/analytics/birdeye/birdeye-task.ts +175 -0
- package/src/analytics/birdeye/birdeye.ts +813 -0
- package/src/analytics/birdeye/constants.ts +74 -0
- package/src/analytics/birdeye/providers/agent-portfolio-provider.ts +18 -0
- package/src/analytics/birdeye/providers/market.ts +227 -0
- package/src/analytics/birdeye/providers/portfolio-factory.test.ts +138 -0
- package/src/analytics/birdeye/providers/portfolio-factory.ts +252 -0
- package/src/analytics/birdeye/providers/trending.ts +365 -0
- package/src/analytics/birdeye/providers/wallet.ts +14 -0
- package/src/analytics/birdeye/search-category.test.ts +207 -0
- package/src/analytics/birdeye/search-category.ts +506 -0
- package/src/analytics/birdeye/service.ts +992 -0
- package/src/analytics/birdeye/tasks/birdeye.ts +232 -0
- package/src/analytics/birdeye/types/api/common.ts +305 -0
- package/src/analytics/birdeye/types/api/defi.ts +220 -0
- package/src/analytics/birdeye/types/api/pair.ts +200 -0
- package/src/analytics/birdeye/types/api/search.ts +86 -0
- package/src/analytics/birdeye/types/api/token.ts +635 -0
- package/src/analytics/birdeye/types/api/trader.ts +76 -0
- package/src/analytics/birdeye/types/api/wallet.ts +181 -0
- package/src/analytics/birdeye/types/shared.ts +106 -0
- package/src/analytics/birdeye/utils.ts +700 -0
- package/src/analytics/dexscreener/errors.ts +28 -0
- package/src/analytics/dexscreener/index.ts +3 -0
- package/src/analytics/dexscreener/search-category.test.ts +49 -0
- package/src/analytics/dexscreener/search-category.ts +42 -0
- package/src/analytics/dexscreener/service.ts +595 -0
- package/src/analytics/dexscreener/types.ts +128 -0
- package/src/analytics/lpinfo/index.d.ts +7 -0
- package/src/analytics/lpinfo/index.ts +52 -0
- package/src/analytics/lpinfo/kamino/README.md +102 -0
- package/src/analytics/lpinfo/kamino/index.ts +24 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoLiquidityProvider.ts +422 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoPoolProvider.ts +365 -0
- package/src/analytics/lpinfo/kamino/providers/kaminoProvider.ts +496 -0
- package/src/analytics/lpinfo/kamino/services/kaminoLiquidityService.ts +1123 -0
- package/src/analytics/lpinfo/kamino/services/kaminoService.ts +758 -0
- package/src/analytics/lpinfo/steer/README.md +169 -0
- package/src/analytics/lpinfo/steer/index.ts +23 -0
- package/src/analytics/lpinfo/steer/providers/steerLiquidityProvider.ts +544 -0
- package/src/analytics/lpinfo/steer/services/steerLiquidityService.ts +1690 -0
- package/src/analytics/lpinfo/steer/steer-display-types.ts +99 -0
- package/src/analytics/news/index.ts +52 -0
- package/src/analytics/news/interfaces/types.ts +222 -0
- package/src/analytics/news/providers/defiNewsProvider.ts +734 -0
- package/src/analytics/news/services/newsDataService.ts +332 -0
- package/src/analytics/news/utils/formatters.ts +151 -0
- package/src/analytics/token-info/action.ts +240 -0
- package/src/analytics/token-info/index.ts +3 -0
- package/src/analytics/token-info/params.ts +215 -0
- package/src/analytics/token-info/providers.ts +681 -0
- package/src/analytics/token-info/service.ts +168 -0
- package/src/analytics/token-info/types.ts +74 -0
- package/src/audit/audit-log.ts +45 -0
- package/src/browser-shim/build-shim.ts +123 -0
- package/src/browser-shim/index.ts +5 -0
- package/src/browser-shim/shim.template.js +563 -0
- package/src/chains/evm/.github/workflows/npm-deploy.yml +112 -0
- package/src/chains/evm/LICENSE +21 -0
- package/src/chains/evm/README.md +106 -0
- package/src/chains/evm/actions/helpers.ts +147 -0
- package/src/chains/evm/actions/swap.ts +839 -0
- package/src/chains/evm/actions/transfer.ts +254 -0
- package/src/chains/evm/biome.json +61 -0
- package/src/chains/evm/bridge-router.ts +660 -0
- package/src/chains/evm/build.ts +89 -0
- package/src/chains/evm/chain-handler.ts +416 -0
- package/src/chains/evm/constants.ts +23 -0
- package/src/chains/evm/contracts/artifacts/OZGovernor.json +1707 -0
- package/src/chains/evm/contracts/artifacts/TimelockController.json +1007 -0
- package/src/chains/evm/contracts/artifacts/VoteToken.json +895 -0
- package/src/chains/evm/dex/aerodrome/index.ts +34 -0
- package/src/chains/evm/dex/aerodrome/services/AerodromeLpService.ts +558 -0
- package/src/chains/evm/dex/aerodrome/types.ts +318 -0
- package/src/chains/evm/dex/pancakeswp/index.ts +35 -0
- package/src/chains/evm/dex/pancakeswp/services/PancakeSwapV3LpService.ts +743 -0
- package/src/chains/evm/dex/pancakeswp/types.ts +65 -0
- package/src/chains/evm/dex/uniswap/index.ts +35 -0
- package/src/chains/evm/dex/uniswap/services/UniswapV3LpService.ts +759 -0
- package/src/chains/evm/dex/uniswap/types.ts +390 -0
- package/src/chains/evm/generated/specs/spec-helpers.ts +73 -0
- package/src/chains/evm/generated/specs/specs.ts +151 -0
- package/src/chains/evm/gov-router.ts +250 -0
- package/src/chains/evm/index.browser.ts +16 -0
- package/src/chains/evm/index.ts +31 -0
- package/src/chains/evm/prompts.ts +193 -0
- package/src/chains/evm/providers/get-balance.ts +123 -0
- package/src/chains/evm/providers/wallet.ts +715 -0
- package/src/chains/evm/routes/sign.ts +333 -0
- package/src/chains/evm/rpc-providers.ts +410 -0
- package/src/chains/evm/service.ts +140 -0
- package/src/chains/evm/templates/index.ts +10 -0
- package/src/chains/evm/types/index.ts +432 -0
- package/src/chains/evm/vitest.config.ts +18 -0
- package/src/chains/registry.ts +668 -0
- package/src/chains/solana/README.md +367 -0
- package/src/chains/wallet-action.ts +533 -0
- package/src/chains/wallet-router.test.ts +296 -0
- package/src/contracts.ts +65 -0
- package/src/core-augmentation.ts +10 -0
- package/src/index.ts +71 -0
- package/src/lib/server-wallet-trade.ts +192 -0
- package/src/lib/wallet-export-guard.ts +330 -0
- package/src/lp/actions/liquidity.ts +827 -0
- package/src/lp/e2e/real-token-tests.ts +428 -0
- package/src/lp/e2e/scenarios.ts +470 -0
- package/src/lp/e2e/test-utils.ts +145 -0
- package/src/lp/lp-manager-entry.ts +303 -0
- package/src/lp/services/ConcentratedLiquidityService.ts +120 -0
- package/src/lp/services/DexInteractionService.ts +226 -0
- package/src/lp/services/LpManagementService.test.ts +148 -0
- package/src/lp/services/LpManagementService.ts +632 -0
- package/src/lp/services/UserLpProfileService.ts +163 -0
- package/src/lp/services/VaultService.ts +153 -0
- package/src/lp/services/YieldOptimizationService.ts +344 -0
- package/src/lp/services/__tests__/MockLpService.ts +146 -0
- package/src/lp/tasks/LpAutoRebalanceTask.ts +117 -0
- package/src/lp/tasks/__tests__/LpAutoRebalanceTask.test.ts +370 -0
- package/src/lp/types.ts +582 -0
- package/src/lp/utils/solanaClient.ts +143 -0
- package/src/plugin.ts +125 -0
- package/src/policy/policy.ts +19 -0
- package/src/providers/canonical-provider.ts +27 -0
- package/src/providers/unified-wallet-provider.ts +79 -0
- package/src/register-routes.ts +11 -0
- package/src/routes/plugin.ts +47 -0
- package/src/routes/wallet-market-overview-route.ts +869 -0
- package/src/sdk/abi.ts +258 -0
- package/src/sdk/bridge/abis.ts +126 -0
- package/src/sdk/bridge/client.ts +518 -0
- package/src/sdk/bridge/index.ts +56 -0
- package/src/sdk/bridge/solana.ts +604 -0
- package/src/sdk/bridge/types.ts +202 -0
- package/src/sdk/convenience.ts +347 -0
- package/src/sdk/escrow/MutualStakeEscrow.ts +480 -0
- package/src/sdk/escrow/types.ts +64 -0
- package/src/sdk/escrow/verifiers.ts +73 -0
- package/src/sdk/identity/erc8004.ts +692 -0
- package/src/sdk/identity/reputation.ts +449 -0
- package/src/sdk/identity/uaid.ts +497 -0
- package/src/sdk/identity/validation.ts +372 -0
- package/src/sdk/index.ts +763 -0
- package/src/sdk/policy/SpendingPolicy.ts +260 -0
- package/src/sdk/policy/UptoBillingPolicy.ts +320 -0
- package/src/sdk/router/PaymentRouter.ts +215 -0
- package/src/sdk/router/index.ts +8 -0
- package/src/sdk/swap/SwapModule.ts +310 -0
- package/src/sdk/swap/abi.ts +117 -0
- package/src/sdk/swap/index.ts +34 -0
- package/src/sdk/swap/types.ts +135 -0
- package/src/sdk/tokens/decimals.ts +140 -0
- package/src/sdk/tokens/registry.ts +911 -0
- package/src/sdk/tokens/solana.ts +419 -0
- package/src/sdk/tokens/transfers.ts +327 -0
- package/src/sdk/types.ts +158 -0
- package/src/sdk/wallet-core.ts +115 -0
- package/src/sdk/x402/budget.ts +168 -0
- package/src/sdk/x402/chains/abstract/index.ts +280 -0
- package/src/sdk/x402/client.ts +320 -0
- package/src/sdk/x402/index.ts +46 -0
- package/src/sdk/x402/middleware.ts +92 -0
- package/src/sdk/x402/multi-asset.ts +144 -0
- package/src/sdk/x402/types.ts +156 -0
- package/src/services/wallet-backend-service.ts +328 -0
- package/src/types/wallet-router.ts +227 -0
- package/src/utils/intent-trajectory.ts +106 -0
- package/src/wallet/backend.ts +62 -0
- package/src/wallet/errors.ts +49 -0
- package/src/wallet/index.ts +27 -0
- package/src/wallet/local-eoa-backend.ts +201 -0
- package/src/wallet/pending.ts +60 -0
- package/src/wallet/select-backend.ts +47 -0
- package/src/wallet/steward-backend.ts +161 -0
- package/src/wallet-action.ts +1 -0
|
@@ -0,0 +1,496 @@
|
|
|
1
|
+
// @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
|
|
2
|
+
import type { IAgentRuntime, Memory, Provider, State } from "@elizaos/core";
|
|
3
|
+
import { ModelType } from "@elizaos/core";
|
|
4
|
+
import type { KaminoService } from "../services/kaminoService";
|
|
5
|
+
|
|
6
|
+
// Kamino Lend Program constants
|
|
7
|
+
const KAMINO_LEND_PROGRAM_ID = "GzFgdRJXmawPhGeBsyRCDLx4jAKPsvbUqoqitzppkzkW";
|
|
8
|
+
const MAX_KAMINO_WALLETS = 5;
|
|
9
|
+
const MAX_KAMINO_POSITIONS = 10;
|
|
10
|
+
const MAX_KAMINO_MARKETS = 10;
|
|
11
|
+
const MAX_KAMINO_REPORT_CHARS = 8000;
|
|
12
|
+
|
|
13
|
+
type AccountLike = {
|
|
14
|
+
id?: unknown;
|
|
15
|
+
username?: unknown;
|
|
16
|
+
name?: unknown;
|
|
17
|
+
metawallets?: Array<{
|
|
18
|
+
keypairs?: Record<string, { publicKey?: unknown }>;
|
|
19
|
+
}>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
function getSolanaWalletAddresses(account: unknown): string[] {
|
|
23
|
+
const walletAddresses: string[] = [];
|
|
24
|
+
const accountData = account as AccountLike;
|
|
25
|
+
|
|
26
|
+
if (!Array.isArray(accountData.metawallets)) {
|
|
27
|
+
return walletAddresses;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
for (const mw of accountData.metawallets) {
|
|
31
|
+
if (!mw?.keypairs) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const [chain, kp] of Object.entries(mw.keypairs)) {
|
|
36
|
+
if (chain === "solana" && kp.publicKey) {
|
|
37
|
+
walletAddresses.push(String(kp.publicKey));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return walletAddresses;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function formatAccountForPrompt(account: unknown): string {
|
|
46
|
+
if (!account) {
|
|
47
|
+
return "account_status: not found";
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const accountData = account as AccountLike;
|
|
51
|
+
const lines = ["account_status: available"];
|
|
52
|
+
const identifiers = {
|
|
53
|
+
id: accountData.id,
|
|
54
|
+
username: accountData.username,
|
|
55
|
+
name: accountData.name,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
for (const [key, value] of Object.entries(identifiers)) {
|
|
59
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
60
|
+
lines.push(`${key}: ${formatPromptValue(value)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const solanaWallets = getSolanaWalletAddresses(account);
|
|
65
|
+
lines.push(`solana_wallet_count: ${solanaWallets.length}`);
|
|
66
|
+
solanaWallets.slice(0, MAX_KAMINO_WALLETS).forEach((wallet, index) => {
|
|
67
|
+
lines.push(`solana_wallets[${index}]: ${wallet}`);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return lines.join("\n");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function formatPromptValue(value: unknown): string {
|
|
74
|
+
if (value === null || value === undefined) {
|
|
75
|
+
return "N/A";
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (typeof value === "string") {
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
83
|
+
return String(value);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return String(value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Kamino Lending Protocol Provider
|
|
91
|
+
* Provides information about Kamino lending positions and market data
|
|
92
|
+
*/
|
|
93
|
+
export const kaminoProvider: Provider = {
|
|
94
|
+
name: "KAMINO_LENDING",
|
|
95
|
+
description:
|
|
96
|
+
"Provides information about Kamino lending protocol positions, market data, and available lending/borrowing opportunities",
|
|
97
|
+
descriptionCompressed:
|
|
98
|
+
"provide information Kamino lend protocol position, market data, available lending/borrow opportunity",
|
|
99
|
+
dynamic: true,
|
|
100
|
+
contexts: ["finance", "crypto", "wallet"],
|
|
101
|
+
contextGate: { anyOf: ["finance", "crypto", "wallet"] },
|
|
102
|
+
cacheStable: false,
|
|
103
|
+
cacheScope: "turn",
|
|
104
|
+
roleGate: { minRole: "OWNER" },
|
|
105
|
+
get: async (runtime: IAgentRuntime, message: Memory, _state: State) => {
|
|
106
|
+
console.log("KAMINO_LENDING provider called");
|
|
107
|
+
|
|
108
|
+
let kaminoInfo = "";
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
// Check if this is a DM (private message)
|
|
112
|
+
const isDM = message.content.channelType?.toUpperCase() === "DM";
|
|
113
|
+
if (isDM) {
|
|
114
|
+
const account = await getAccountFromMessage(runtime, message);
|
|
115
|
+
if (!account) {
|
|
116
|
+
console.log("No account found for user");
|
|
117
|
+
return {
|
|
118
|
+
data: {},
|
|
119
|
+
values: {} as Record<string, unknown>,
|
|
120
|
+
text: "No account found for this user.",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
console.log("Account found, getting Kamino service...");
|
|
125
|
+
|
|
126
|
+
// Get Kamino service with proper type casting
|
|
127
|
+
const kaminoService = runtime.getService(
|
|
128
|
+
"KAMINO_SERVICE",
|
|
129
|
+
) as KaminoService;
|
|
130
|
+
if (!kaminoService) {
|
|
131
|
+
console.log("Kamino service not available");
|
|
132
|
+
return {
|
|
133
|
+
data: {},
|
|
134
|
+
values: {} as Record<string, unknown>,
|
|
135
|
+
text: "Kamino service not available.",
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
console.log("Kamino service found, generating report...");
|
|
140
|
+
|
|
141
|
+
kaminoInfo += `=== KAMINO LENDING PROTOCOL REPORT ===\n\n`;
|
|
142
|
+
|
|
143
|
+
// Get user's Kamino positions
|
|
144
|
+
const userPositions = await getUserKaminoPositions(
|
|
145
|
+
kaminoService,
|
|
146
|
+
account,
|
|
147
|
+
);
|
|
148
|
+
const availableReserves =
|
|
149
|
+
await getAvailableKaminoReserves(kaminoService);
|
|
150
|
+
const marketOverview = await getKaminoMarketOverview(kaminoService);
|
|
151
|
+
const discoveredMarkets =
|
|
152
|
+
await getDiscoveredKaminoMarkets(kaminoService);
|
|
153
|
+
|
|
154
|
+
// Generate enhanced response using LLM
|
|
155
|
+
const enhancedReport = await generateEnhancedKaminoLendingReport(
|
|
156
|
+
runtime,
|
|
157
|
+
{
|
|
158
|
+
account,
|
|
159
|
+
userPositions,
|
|
160
|
+
availableReserves,
|
|
161
|
+
marketOverview,
|
|
162
|
+
discoveredMarkets,
|
|
163
|
+
kaminoService,
|
|
164
|
+
},
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
kaminoInfo += enhancedReport.slice(0, MAX_KAMINO_REPORT_CHARS);
|
|
168
|
+
} else {
|
|
169
|
+
kaminoInfo =
|
|
170
|
+
"Kamino lending protocol information is only available in private messages.";
|
|
171
|
+
}
|
|
172
|
+
} catch (error) {
|
|
173
|
+
console.error("Error in Kamino provider:", error);
|
|
174
|
+
kaminoInfo = `Error generating Kamino report: ${error instanceof Error ? error.message : "Unknown error"}`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const data = {
|
|
178
|
+
kaminoLending: kaminoInfo,
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
const text = `${kaminoInfo}\n`.slice(0, MAX_KAMINO_REPORT_CHARS);
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
data,
|
|
185
|
+
values: {} as Record<string, unknown>,
|
|
186
|
+
text,
|
|
187
|
+
};
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Get user's Kamino positions
|
|
193
|
+
*/
|
|
194
|
+
async function getUserKaminoPositions(
|
|
195
|
+
kaminoService: KaminoService,
|
|
196
|
+
account: unknown,
|
|
197
|
+
): Promise<string> {
|
|
198
|
+
let positionsInfo = "📊 YOUR KAMINO POSITIONS:\n\n";
|
|
199
|
+
|
|
200
|
+
try {
|
|
201
|
+
// Extract wallet addresses from account
|
|
202
|
+
const walletAddresses = getSolanaWalletAddresses(account);
|
|
203
|
+
|
|
204
|
+
if (walletAddresses.length === 0) {
|
|
205
|
+
positionsInfo += "No Solana wallets found in your account.\n\n";
|
|
206
|
+
return positionsInfo;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Get positions for each wallet
|
|
210
|
+
for (const walletAddress of walletAddresses.slice(0, MAX_KAMINO_WALLETS)) {
|
|
211
|
+
positionsInfo += `🔸 Wallet: ${walletAddress.slice(0, 8)}...${walletAddress.slice(-8)}\n`;
|
|
212
|
+
|
|
213
|
+
try {
|
|
214
|
+
// Get real positions from Kamino service
|
|
215
|
+
const positions = await kaminoService.getUserPositions(walletAddress);
|
|
216
|
+
|
|
217
|
+
if (positions.error) {
|
|
218
|
+
positionsInfo += ` ❌ Error: ${positions.error}\n\n`;
|
|
219
|
+
} else if (positions.message) {
|
|
220
|
+
positionsInfo += ` ℹ️ ${positions.message}\n\n`;
|
|
221
|
+
} else if (
|
|
222
|
+
positions.lending.length === 0 &&
|
|
223
|
+
positions.borrowing.length === 0
|
|
224
|
+
) {
|
|
225
|
+
positionsInfo += " No Kamino positions found.\n\n";
|
|
226
|
+
|
|
227
|
+
// Show discovered markets info
|
|
228
|
+
if (positions.markets && positions.markets.length > 0) {
|
|
229
|
+
positionsInfo += ` 🔍 Discovered ${positions.markets.length} Kamino markets\n`;
|
|
230
|
+
positionsInfo += ` 📊 User has ${positions.userAccounts || 0} token accounts\n\n`;
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
// Display lending positions
|
|
234
|
+
if (positions.lending.length > 0) {
|
|
235
|
+
positionsInfo += ` 💰 LENDING POSITIONS (${positions.lending.length}):\n\n`;
|
|
236
|
+
|
|
237
|
+
for (const position of positions.lending.slice(
|
|
238
|
+
0,
|
|
239
|
+
MAX_KAMINO_POSITIONS,
|
|
240
|
+
)) {
|
|
241
|
+
positionsInfo += ` 📈 ${position.token || "Unknown Token"}\n`;
|
|
242
|
+
positionsInfo += ` Amount: ${position.amount?.toFixed(6) || "N/A"}\n`;
|
|
243
|
+
positionsInfo += ` Value: $${position.value?.toFixed(2) || "N/A"}\n`;
|
|
244
|
+
positionsInfo += ` APY: ${position.apy?.toFixed(2) || "N/A"}%\n`;
|
|
245
|
+
positionsInfo += ` Market: ${position.market?.slice(0, 8)}...${position.market?.slice(-8) || "N/A"}\n\n`;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Display borrowing positions
|
|
250
|
+
if (positions.borrowing.length > 0) {
|
|
251
|
+
positionsInfo += ` 💳 BORROWING POSITIONS (${positions.borrowing.length}):\n\n`;
|
|
252
|
+
|
|
253
|
+
for (const position of positions.borrowing.slice(
|
|
254
|
+
0,
|
|
255
|
+
MAX_KAMINO_POSITIONS,
|
|
256
|
+
)) {
|
|
257
|
+
positionsInfo += ` 📉 ${position.token || "Unknown Token"}\n`;
|
|
258
|
+
positionsInfo += ` Amount: ${position.amount?.toFixed(6) || "N/A"}\n`;
|
|
259
|
+
positionsInfo += ` Value: $${position.value?.toFixed(2) || "N/A"}\n`;
|
|
260
|
+
positionsInfo += ` APY: ${position.apy?.toFixed(2) || "N/A"}%\n`;
|
|
261
|
+
positionsInfo += ` Market: ${position.market?.slice(0, 8)}...${position.market?.slice(-8) || "N/A"}\n\n`;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Display total portfolio value
|
|
266
|
+
if (positions.totalValue !== undefined) {
|
|
267
|
+
positionsInfo += ` 💼 TOTAL PORTFOLIO VALUE: $${positions.totalValue.toFixed(2)}\n\n`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} catch (error) {
|
|
271
|
+
console.error(
|
|
272
|
+
`Error fetching positions for wallet ${walletAddress}:`,
|
|
273
|
+
error,
|
|
274
|
+
);
|
|
275
|
+
positionsInfo += " Error fetching positions for this wallet.\n\n";
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch (error) {
|
|
279
|
+
console.error("Error fetching user Kamino positions:", error);
|
|
280
|
+
positionsInfo += "Error fetching positions. Please try again later.\n\n";
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return positionsInfo;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Get available Kamino reserves for lending/borrowing
|
|
288
|
+
*/
|
|
289
|
+
async function getAvailableKaminoReserves(
|
|
290
|
+
kaminoService: KaminoService,
|
|
291
|
+
): Promise<string> {
|
|
292
|
+
let reservesInfo = "🏦 AVAILABLE KAMINO RESERVES:\n\n";
|
|
293
|
+
|
|
294
|
+
try {
|
|
295
|
+
// Get real reserves from Kamino service
|
|
296
|
+
const reserves = await kaminoService.getAvailableReserves();
|
|
297
|
+
|
|
298
|
+
if (reserves.length === 0) {
|
|
299
|
+
reservesInfo += "No reserves available at the moment.\n";
|
|
300
|
+
reservesInfo += "This may be due to:\n";
|
|
301
|
+
reservesInfo += "- Kamino SDK not being installed\n";
|
|
302
|
+
reservesInfo += "- Network connectivity issues\n";
|
|
303
|
+
reservesInfo += "- Service initialization problems\n\n";
|
|
304
|
+
return reservesInfo;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Show top reserves by supply APY
|
|
308
|
+
const topLendingReserves = reserves
|
|
309
|
+
.filter((r) => r.supplyApy > 0)
|
|
310
|
+
.sort((a, b) => (b.supplyApy || 0) - (a.supplyApy || 0))
|
|
311
|
+
.slice(0, 5); // Show top 5 lending opportunities
|
|
312
|
+
|
|
313
|
+
if (topLendingReserves.length > 0) {
|
|
314
|
+
reservesInfo += "💰 TOP LENDING OPPORTUNITIES:\n\n";
|
|
315
|
+
|
|
316
|
+
for (const reserve of topLendingReserves) {
|
|
317
|
+
reservesInfo += `🔸 ${reserve.symbol || "Unknown"}\n`;
|
|
318
|
+
reservesInfo += ` Supply APY: ${reserve.supplyApy?.toFixed(2) || "N/A"}%\n`;
|
|
319
|
+
reservesInfo += ` Borrow APY: ${reserve.borrowApy?.toFixed(2) || "N/A"}%\n`;
|
|
320
|
+
reservesInfo += ` Total Supply: $${reserve.totalSupply?.toLocaleString() || "N/A"}\n`;
|
|
321
|
+
reservesInfo += ` Total Borrow: $${reserve.totalBorrow?.toLocaleString() || "N/A"}\n`;
|
|
322
|
+
reservesInfo += ` Utilization: ${(reserve.utilization * 100)?.toFixed(2) || "N/A"}%\n`;
|
|
323
|
+
reservesInfo += ` Market: ${reserve.marketName || "Unknown"}\n\n`;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
reservesInfo += `Total reserves available: ${reserves.length}\n\n`;
|
|
328
|
+
} catch (error) {
|
|
329
|
+
console.error("Error fetching available Kamino reserves:", error);
|
|
330
|
+
reservesInfo += "Error fetching reserves. Please try again later.\n\n";
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return reservesInfo;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Get Kamino market overview
|
|
338
|
+
*/
|
|
339
|
+
async function getKaminoMarketOverview(
|
|
340
|
+
kaminoService: KaminoService,
|
|
341
|
+
): Promise<string> {
|
|
342
|
+
let marketInfo = "📈 KAMINO MARKET OVERVIEW:\n\n";
|
|
343
|
+
|
|
344
|
+
try {
|
|
345
|
+
// Get real market overview from Kamino service
|
|
346
|
+
const overview = await kaminoService.getMarketOverview();
|
|
347
|
+
|
|
348
|
+
if (!overview) {
|
|
349
|
+
marketInfo += "Market data not available at the moment.\n";
|
|
350
|
+
marketInfo += "This may be due to:\n";
|
|
351
|
+
marketInfo += "- Kamino SDK not being installed\n";
|
|
352
|
+
marketInfo += "- Network connectivity issues\n";
|
|
353
|
+
marketInfo += "- Service initialization problems\n\n";
|
|
354
|
+
return marketInfo;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
marketInfo += `📊 Total Markets: ${overview.totalMarkets}\n`;
|
|
358
|
+
marketInfo += `💰 Total TVL: $${overview.totalTvl?.toLocaleString() || "N/A"}\n`;
|
|
359
|
+
marketInfo += `💳 Total Borrowed: $${overview.totalBorrowed?.toLocaleString() || "N/A"}\n\n`;
|
|
360
|
+
|
|
361
|
+
// Show top markets by TVL
|
|
362
|
+
if (overview.markets && overview.markets.length > 0) {
|
|
363
|
+
marketInfo += "🏆 TOP MARKETS BY TVL:\n\n";
|
|
364
|
+
|
|
365
|
+
const topMarkets = overview.markets
|
|
366
|
+
.sort((a, b) => (b.tvl || 0) - (a.tvl || 0))
|
|
367
|
+
.slice(0, 3);
|
|
368
|
+
|
|
369
|
+
for (const market of topMarkets) {
|
|
370
|
+
marketInfo += `🔸 ${market.name || "Unknown Market"}\n`;
|
|
371
|
+
marketInfo += ` TVL: $${market.tvl?.toLocaleString() || "N/A"}\n`;
|
|
372
|
+
marketInfo += ` Borrowed: $${market.borrowed?.toLocaleString() || "N/A"}\n`;
|
|
373
|
+
marketInfo += ` Utilization: ${(market.utilization * 100)?.toFixed(2) || "N/A"}%\n\n`;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
} catch (error) {
|
|
377
|
+
console.error("Error fetching Kamino market overview:", error);
|
|
378
|
+
marketInfo += "Error fetching market data. Please try again later.\n\n";
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
return marketInfo;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Get discovered Kamino markets
|
|
386
|
+
*/
|
|
387
|
+
async function getDiscoveredKaminoMarkets(
|
|
388
|
+
kaminoService: KaminoService,
|
|
389
|
+
): Promise<string> {
|
|
390
|
+
let marketsInfo = "🔍 DISCOVERED KAMINO MARKETS:\n\n";
|
|
391
|
+
|
|
392
|
+
try {
|
|
393
|
+
// Get discovered markets from Kamino service
|
|
394
|
+
const markets = await kaminoService.discoverMarkets();
|
|
395
|
+
|
|
396
|
+
if (markets.length === 0) {
|
|
397
|
+
marketsInfo += "No markets discovered at the moment.\n\n";
|
|
398
|
+
return marketsInfo;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
marketsInfo += `📊 Total Markets Discovered: ${markets.length}\n\n`;
|
|
402
|
+
|
|
403
|
+
// Display discovered markets
|
|
404
|
+
marketsInfo += "🏪 DISCOVERED MARKET ADDRESSES:\n\n";
|
|
405
|
+
|
|
406
|
+
for (let i = 0; i < Math.min(markets.length, MAX_KAMINO_MARKETS); i++) {
|
|
407
|
+
const market = markets[i];
|
|
408
|
+
marketsInfo += `${i + 1}. ${market.toString()}\n`;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
marketsInfo += "\n";
|
|
412
|
+
|
|
413
|
+
// Show market discovery statistics
|
|
414
|
+
marketsInfo += "📈 MARKET DISCOVERY STATS:\n";
|
|
415
|
+
marketsInfo += `• Program ID: ${KAMINO_LEND_PROGRAM_ID}\n`;
|
|
416
|
+
marketsInfo += `• Discovery Method: Program Account Query\n`;
|
|
417
|
+
marketsInfo += `• Data Size Filter: 1024 bytes\n`;
|
|
418
|
+
marketsInfo += `• Discovery Time: ${new Date().toLocaleString()}\n\n`;
|
|
419
|
+
} catch (error) {
|
|
420
|
+
console.error("Error fetching discovered Kamino markets:", error);
|
|
421
|
+
marketsInfo += "Error discovering markets. Please try again later.\n\n";
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
return marketsInfo;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* Generate enhanced Kamino lending report using LLM
|
|
429
|
+
*/
|
|
430
|
+
async function generateEnhancedKaminoLendingReport(
|
|
431
|
+
runtime: IAgentRuntime,
|
|
432
|
+
data: {
|
|
433
|
+
account: unknown;
|
|
434
|
+
userPositions: string;
|
|
435
|
+
availableReserves: string;
|
|
436
|
+
marketOverview: string;
|
|
437
|
+
discoveredMarkets: string;
|
|
438
|
+
kaminoService: KaminoService;
|
|
439
|
+
},
|
|
440
|
+
): Promise<string> {
|
|
441
|
+
try {
|
|
442
|
+
// Create a focused prompt for the LLM
|
|
443
|
+
const lendingPrompt = `You are a professional DeFi analyst specializing in Kamino Finance lending protocols. Generate a comprehensive, well-crafted lending analysis report for the user.
|
|
444
|
+
|
|
445
|
+
USER ACCOUNT DATA:
|
|
446
|
+
${formatAccountForPrompt(data.account)}
|
|
447
|
+
|
|
448
|
+
USER POSITIONS:
|
|
449
|
+
${data.userPositions}
|
|
450
|
+
|
|
451
|
+
AVAILABLE RESERVES:
|
|
452
|
+
${data.availableReserves}
|
|
453
|
+
|
|
454
|
+
MARKET OVERVIEW:
|
|
455
|
+
${data.marketOverview}
|
|
456
|
+
|
|
457
|
+
DISCOVERED MARKETS:
|
|
458
|
+
${data.discoveredMarkets}
|
|
459
|
+
|
|
460
|
+
Please generate a professional, engaging report that includes:
|
|
461
|
+
|
|
462
|
+
1. **Portfolio Summary** - Overview of the user's current Kamino lending positions and performance
|
|
463
|
+
2. **Market Analysis** - Current state of Kamino lending markets and opportunities
|
|
464
|
+
3. **Position Analysis** - Detailed breakdown of user's lending and borrowing positions
|
|
465
|
+
4. **Opportunity Assessment** - Analysis of the best lending and borrowing opportunities available
|
|
466
|
+
5. **Risk Management** - Key risks and considerations for the user's current positions
|
|
467
|
+
6. **Strategy Recommendations** - Specific, actionable recommendations for portfolio optimization
|
|
468
|
+
7. **Market Trends** - How current market conditions affect lending strategies
|
|
469
|
+
|
|
470
|
+
Format the report with:
|
|
471
|
+
- Clear sections with descriptive headers
|
|
472
|
+
- Use emojis for visual appeal and quick scanning
|
|
473
|
+
- Include specific numbers and percentages
|
|
474
|
+
- Provide professional but engaging tone
|
|
475
|
+
- Focus on actionable insights for this specific user
|
|
476
|
+
- Include relevant comparisons to market standards
|
|
477
|
+
- End with a concise summary and next steps
|
|
478
|
+
|
|
479
|
+
Make it comprehensive yet easy to read. Be specific about the user's data and provide clear, personalized insights about their Kamino lending situation.
|
|
480
|
+
|
|
481
|
+
Generate a professional Kamino lending analysis report:`;
|
|
482
|
+
|
|
483
|
+
// Use LLM to generate the enhanced report
|
|
484
|
+
const enhancedReport = await runtime.useModel(ModelType.TEXT_LARGE, {
|
|
485
|
+
prompt: lendingPrompt,
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
return (
|
|
489
|
+
enhancedReport ||
|
|
490
|
+
`${data.userPositions}\n\n${data.availableReserves}\n\n${data.marketOverview}\n\n${data.discoveredMarkets}`
|
|
491
|
+
);
|
|
492
|
+
} catch (error) {
|
|
493
|
+
console.error("Error generating enhanced Kamino lending report:", error);
|
|
494
|
+
return `${data.userPositions}\n\n${data.availableReserves}\n\n${data.marketOverview}\n\n${data.discoveredMarkets}`; // Fallback to original data
|
|
495
|
+
}
|
|
496
|
+
}
|