@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,252 @@
|
|
|
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 { BIRDEYE_SERVICE_NAME } from "../constants";
|
|
4
|
+
import type { WalletPortfolioResponse } from "../types/api/wallet";
|
|
5
|
+
import { extractChain, formatJsonScalar, formatJsonTable } from "../utils";
|
|
6
|
+
|
|
7
|
+
type PortfolioService = {
|
|
8
|
+
fetchWalletTokenList?: (
|
|
9
|
+
chain: unknown,
|
|
10
|
+
walletAddr: string,
|
|
11
|
+
opts: { notOlderThan: number },
|
|
12
|
+
) => Promise<unknown>;
|
|
13
|
+
fetchWalletTxList?: (
|
|
14
|
+
chain: unknown,
|
|
15
|
+
walletAddr: string,
|
|
16
|
+
opts: { notOlderThan: number },
|
|
17
|
+
) => Promise<unknown[]>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export interface BirdeyePortfolioProviderOptions {
|
|
21
|
+
name: string;
|
|
22
|
+
description: string;
|
|
23
|
+
descriptionCompressed: string;
|
|
24
|
+
includeTrades?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function statusJson(name: string, status: string, reason: string): string {
|
|
28
|
+
return [
|
|
29
|
+
`${name}:`,
|
|
30
|
+
` status: ${formatJsonScalar(status)}`,
|
|
31
|
+
` reason: ${formatJsonScalar(reason)}`,
|
|
32
|
+
].join("\n");
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function normalizePortfolioResponse(response: unknown) {
|
|
36
|
+
if (response?.data?.items) {
|
|
37
|
+
return response.data;
|
|
38
|
+
}
|
|
39
|
+
return response ?? {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const formatPortfolio = (response: WalletPortfolioResponse) => {
|
|
43
|
+
const portfolio = normalizePortfolioResponse(response);
|
|
44
|
+
const items = portfolio.items ?? [];
|
|
45
|
+
if (!items.length) return "holdings[0]: []";
|
|
46
|
+
|
|
47
|
+
return formatJsonTable(
|
|
48
|
+
"holdings",
|
|
49
|
+
items.map((item) => ({
|
|
50
|
+
symbol: item.symbol || "unknown",
|
|
51
|
+
address: item.address || "unknown",
|
|
52
|
+
amount:
|
|
53
|
+
typeof item.uiAmount === "number"
|
|
54
|
+
? Number(item.uiAmount.toFixed(4))
|
|
55
|
+
: "unknown",
|
|
56
|
+
priceUsd:
|
|
57
|
+
typeof item.priceUsd === "number"
|
|
58
|
+
? Number(item.priceUsd.toFixed(6))
|
|
59
|
+
: "unknown",
|
|
60
|
+
valueUsd:
|
|
61
|
+
typeof item.valueUsd === "number"
|
|
62
|
+
? Number(item.valueUsd.toFixed(2))
|
|
63
|
+
: "unknown",
|
|
64
|
+
chainId: item.chainId || "unknown",
|
|
65
|
+
})),
|
|
66
|
+
["symbol", "address", "amount", "priceUsd", "valueUsd", "chainId"],
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
function formatPortfolioProviderText({
|
|
71
|
+
wallet,
|
|
72
|
+
chain,
|
|
73
|
+
portfolio,
|
|
74
|
+
trades,
|
|
75
|
+
}: {
|
|
76
|
+
wallet: string;
|
|
77
|
+
chain: string;
|
|
78
|
+
portfolio: unknown;
|
|
79
|
+
trades?: unknown[];
|
|
80
|
+
}): string {
|
|
81
|
+
const normalized = normalizePortfolioResponse(portfolio);
|
|
82
|
+
const holdings = normalized.items ?? [];
|
|
83
|
+
const lines = [
|
|
84
|
+
"birdeye_wallet_portfolio:",
|
|
85
|
+
" status: ok",
|
|
86
|
+
` wallet: ${formatJsonScalar(normalized.wallet ?? wallet)}`,
|
|
87
|
+
` chain: ${formatJsonScalar(chain)}`,
|
|
88
|
+
` totalUsd: ${formatJsonScalar(normalized.totalUsd ?? 0)}`,
|
|
89
|
+
formatJsonTable(
|
|
90
|
+
" holdings",
|
|
91
|
+
holdings.slice(0, 20).map((item) => ({
|
|
92
|
+
symbol: item.symbol || "unknown",
|
|
93
|
+
address: item.address || "unknown",
|
|
94
|
+
amount:
|
|
95
|
+
typeof item.uiAmount === "number"
|
|
96
|
+
? Number(item.uiAmount.toFixed(4))
|
|
97
|
+
: "unknown",
|
|
98
|
+
priceUsd:
|
|
99
|
+
typeof item.priceUsd === "number"
|
|
100
|
+
? Number(item.priceUsd.toFixed(6))
|
|
101
|
+
: "unknown",
|
|
102
|
+
valueUsd:
|
|
103
|
+
typeof item.valueUsd === "number"
|
|
104
|
+
? Number(item.valueUsd.toFixed(2))
|
|
105
|
+
: "unknown",
|
|
106
|
+
chainId: item.chainId || "unknown",
|
|
107
|
+
})),
|
|
108
|
+
["symbol", "address", "amount", "priceUsd", "valueUsd", "chainId"],
|
|
109
|
+
),
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
if (trades) {
|
|
113
|
+
lines.push(` tradeCount: ${trades.length}`);
|
|
114
|
+
lines.push(
|
|
115
|
+
formatJsonTable(
|
|
116
|
+
" trades",
|
|
117
|
+
trades.slice(0, 10).map((trade) => ({
|
|
118
|
+
txHash: trade.txHash ?? "unknown",
|
|
119
|
+
action: trade.mainAction ?? "unknown",
|
|
120
|
+
status: trade.status ?? "unknown",
|
|
121
|
+
blockTime: trade.blockTime ?? "unknown",
|
|
122
|
+
from: trade.from ?? "unknown",
|
|
123
|
+
to: trade.to ?? "unknown",
|
|
124
|
+
})),
|
|
125
|
+
["txHash", "action", "status", "blockTime", "from", "to"],
|
|
126
|
+
),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return lines.join("\n");
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function getPortfolioService(
|
|
134
|
+
runtime: IAgentRuntime,
|
|
135
|
+
includeTrades: boolean,
|
|
136
|
+
): PortfolioService | undefined {
|
|
137
|
+
const beService = runtime.getService(BIRDEYE_SERVICE_NAME) as
|
|
138
|
+
| PortfolioService
|
|
139
|
+
| undefined;
|
|
140
|
+
if (!beService || typeof beService.fetchWalletTokenList !== "function") {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
if (includeTrades && typeof beService.fetchWalletTxList !== "function") {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
return beService;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function createBirdeyePortfolioProvider(
|
|
150
|
+
options: BirdeyePortfolioProviderOptions,
|
|
151
|
+
): Provider {
|
|
152
|
+
const includeTrades = options.includeTrades ?? false;
|
|
153
|
+
return {
|
|
154
|
+
name: options.name,
|
|
155
|
+
description: options.description,
|
|
156
|
+
descriptionCompressed: options.descriptionCompressed,
|
|
157
|
+
dynamic: true,
|
|
158
|
+
contexts: ["finance", "crypto", "wallet"],
|
|
159
|
+
contextGate: { anyOf: ["finance", "crypto", "wallet"] },
|
|
160
|
+
cacheStable: false,
|
|
161
|
+
cacheScope: "turn",
|
|
162
|
+
roleGate: { minRole: "OWNER" },
|
|
163
|
+
get: async (runtime: IAgentRuntime, _message: Memory, _state?: State) => {
|
|
164
|
+
try {
|
|
165
|
+
const walletAddr = runtime.getSetting("BIRDEYE_WALLET_ADDR");
|
|
166
|
+
if (!walletAddr) {
|
|
167
|
+
runtime.logger?.error(
|
|
168
|
+
"BIRDEYE_WALLET_ADDR setting is not configured",
|
|
169
|
+
);
|
|
170
|
+
return {
|
|
171
|
+
values: {},
|
|
172
|
+
text: statusJson(
|
|
173
|
+
"birdeye_wallet_portfolio",
|
|
174
|
+
"error",
|
|
175
|
+
"missing BIRDEYE_WALLET_ADDR",
|
|
176
|
+
),
|
|
177
|
+
data: {},
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const explicitChain = runtime.getSetting("BIRDEYE_CHAIN");
|
|
182
|
+
const chain = extractChain(walletAddr, explicitChain);
|
|
183
|
+
const beService = getPortfolioService(runtime, includeTrades);
|
|
184
|
+
if (!beService) {
|
|
185
|
+
runtime.logger?.error(
|
|
186
|
+
"Birdeye service is unavailable or missing required portfolio methods",
|
|
187
|
+
);
|
|
188
|
+
return {
|
|
189
|
+
values: {},
|
|
190
|
+
text: statusJson(
|
|
191
|
+
"birdeye_wallet_portfolio",
|
|
192
|
+
"unavailable",
|
|
193
|
+
includeTrades
|
|
194
|
+
? "missing fetchWalletTokenList or fetchWalletTxList"
|
|
195
|
+
: "missing fetchWalletTokenList",
|
|
196
|
+
),
|
|
197
|
+
data: {},
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const portfolioPromise = beService.fetchWalletTokenList(
|
|
202
|
+
chain,
|
|
203
|
+
walletAddr,
|
|
204
|
+
{ notOlderThan: 30 * 1000 },
|
|
205
|
+
);
|
|
206
|
+
const tradesPromise = includeTrades
|
|
207
|
+
? beService.fetchWalletTxList(chain, walletAddr, {
|
|
208
|
+
notOlderThan: 30 * 1000,
|
|
209
|
+
})
|
|
210
|
+
: Promise.resolve(undefined);
|
|
211
|
+
const [portfolio, trades] = await Promise.all([
|
|
212
|
+
portfolioPromise,
|
|
213
|
+
tradesPromise,
|
|
214
|
+
]);
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
data: includeTrades ? { portfolio, trades } : portfolio,
|
|
218
|
+
values: {},
|
|
219
|
+
text: formatPortfolioProviderText({
|
|
220
|
+
wallet: walletAddr,
|
|
221
|
+
chain,
|
|
222
|
+
portfolio,
|
|
223
|
+
trades,
|
|
224
|
+
}),
|
|
225
|
+
};
|
|
226
|
+
} catch (error) {
|
|
227
|
+
const errorMessage =
|
|
228
|
+
error instanceof Error ? error.message : String(error);
|
|
229
|
+
runtime.logger?.error(
|
|
230
|
+
`Error fetching Birdeye portfolio: ${errorMessage}`,
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
const isConfigError =
|
|
234
|
+
errorMessage.includes("BIRDEYE_CHAIN") ||
|
|
235
|
+
errorMessage.includes("address") ||
|
|
236
|
+
errorMessage.includes("Invalid");
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
values: {},
|
|
240
|
+
text: statusJson(
|
|
241
|
+
"birdeye_wallet_portfolio",
|
|
242
|
+
"error",
|
|
243
|
+
isConfigError
|
|
244
|
+
? errorMessage
|
|
245
|
+
: "unable to fetch wallet portfolio data",
|
|
246
|
+
),
|
|
247
|
+
data: {},
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
};
|
|
252
|
+
}
|
|
@@ -0,0 +1,365 @@
|
|
|
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 { formatJsonScalar, formatJsonTable } from "../utils";
|
|
4
|
+
|
|
5
|
+
const TRENDING_ROW_LIMIT = 18;
|
|
6
|
+
|
|
7
|
+
interface TrendingToken {
|
|
8
|
+
address: string;
|
|
9
|
+
symbol: string;
|
|
10
|
+
price: number;
|
|
11
|
+
volume24hUSD: number;
|
|
12
|
+
price24hChangePercent: number;
|
|
13
|
+
liquidity: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function getCacheTimed<T>(
|
|
17
|
+
runtime: IAgentRuntime,
|
|
18
|
+
key: string,
|
|
19
|
+
options: { notOlderThan?: number } = {},
|
|
20
|
+
): Promise<T | false> {
|
|
21
|
+
const wrapper = await runtime.getCache<{ data: T; setAt: number }>(key);
|
|
22
|
+
if (!wrapper) return false;
|
|
23
|
+
if (options.notOlderThan) {
|
|
24
|
+
const diff = Date.now() - wrapper.setAt;
|
|
25
|
+
//console.log('checking notOlderThan', diff + 'ms', 'setAt', wrapper.setAt, 'asking', options.notOlderThan)
|
|
26
|
+
if (diff > options.notOlderThan) {
|
|
27
|
+
// no data
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
// return data
|
|
32
|
+
return wrapper.data;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Provider for Birdeye trending coins
|
|
37
|
+
*
|
|
38
|
+
* @typedef {import('./Provider').Provider} Provider
|
|
39
|
+
* @typedef {import('./Runtime').IAgentRuntime} IAgentRuntime
|
|
40
|
+
* @typedef {import('./Memory').Memory} Memory
|
|
41
|
+
* @typedef {import('./State').State} State
|
|
42
|
+
* @typedef {import('./Action').Action} Action
|
|
43
|
+
*
|
|
44
|
+
* @type {Provider}
|
|
45
|
+
* @property {string} name - The name of the provider
|
|
46
|
+
* @property {string} description - Description of the provider
|
|
47
|
+
* @property {number} position - The position of the provider
|
|
48
|
+
* @property {Function} get - Asynchronous function to get actions that validate for a given message
|
|
49
|
+
*
|
|
50
|
+
* @param {IAgentRuntime} runtime - The agent runtime
|
|
51
|
+
* @param {Memory} message - The message memory
|
|
52
|
+
* @param {State} state - The state of the agent
|
|
53
|
+
* @returns {Object} Object containing data, values, and text related to actions
|
|
54
|
+
*/
|
|
55
|
+
export const trendingProvider: Provider = {
|
|
56
|
+
name: "BIRDEYE_TRENDING_CRYPTOCURRENCY",
|
|
57
|
+
description: "Birdeye's trending cryptocurrencies",
|
|
58
|
+
descriptionCompressed: "Read Birdeye trending cryptocurrency tokens.",
|
|
59
|
+
dynamic: true,
|
|
60
|
+
contexts: ["finance", "crypto", "wallet"],
|
|
61
|
+
contextGate: { anyOf: ["finance", "crypto", "wallet"] },
|
|
62
|
+
cacheStable: false,
|
|
63
|
+
cacheScope: "turn",
|
|
64
|
+
roleGate: { minRole: "USER" },
|
|
65
|
+
//position: -1,
|
|
66
|
+
get: async (runtime: IAgentRuntime, _message: Memory, _state: State) => {
|
|
67
|
+
try {
|
|
68
|
+
runtime.logger?.log("birdeye:provider:trending - get birdeye");
|
|
69
|
+
// Get all sentiments
|
|
70
|
+
|
|
71
|
+
/*
|
|
72
|
+
const chains = ['solana', 'eth', 'base'];
|
|
73
|
+
const tokenData = []
|
|
74
|
+
for(const chain of chains) {
|
|
75
|
+
tokenData = [...tokenData, ...(await runtime.getCache<IToken[]>('tokens_' + chain)) || []];
|
|
76
|
+
}
|
|
77
|
+
console.log('tokenData', tokenData)
|
|
78
|
+
*/
|
|
79
|
+
const solanaCache = await runtime.getCache<{
|
|
80
|
+
data: TrendingToken[];
|
|
81
|
+
setAt: number;
|
|
82
|
+
}>("tokens_v2_solana");
|
|
83
|
+
if (!solanaCache?.data) {
|
|
84
|
+
runtime.logger?.warn(
|
|
85
|
+
"birdeye:provider:trending - no birdeye token data found",
|
|
86
|
+
);
|
|
87
|
+
return {
|
|
88
|
+
values: {},
|
|
89
|
+
text: [
|
|
90
|
+
"birdeye_trending_tokens:",
|
|
91
|
+
" status: empty",
|
|
92
|
+
" reason: no cached Solana trending token data",
|
|
93
|
+
].join("\n"),
|
|
94
|
+
data: {},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const solanaTokens = solanaCache.data;
|
|
98
|
+
//console.log('intel:provider - birdeye data', tokens)
|
|
99
|
+
if (!solanaTokens.length) {
|
|
100
|
+
runtime.logger?.warn(
|
|
101
|
+
"birdeye:provider:trending - no birdeye token data found",
|
|
102
|
+
);
|
|
103
|
+
return {
|
|
104
|
+
values: {},
|
|
105
|
+
text: [
|
|
106
|
+
"birdeye_trending_tokens:",
|
|
107
|
+
" status: empty",
|
|
108
|
+
" reason: no Solana trending tokens",
|
|
109
|
+
].join("\n"),
|
|
110
|
+
data: {},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
//console.log('birdeye:provider:trending - birdeye token data', tokens)
|
|
115
|
+
/*
|
|
116
|
+
name: "Bitcoin",
|
|
117
|
+
rank: 1,
|
|
118
|
+
chain: "L1",
|
|
119
|
+
price: 93768.60351119141,
|
|
120
|
+
symbol: "BTC",
|
|
121
|
+
address: "bitcoin",
|
|
122
|
+
logoURI: "https://s2.coinmarketcap.com/static/img/coins/128x128/1.png",
|
|
123
|
+
decimals: null,
|
|
124
|
+
provider: "coinmarketcap",
|
|
125
|
+
liquidity: null,
|
|
126
|
+
marketcap: 0,
|
|
127
|
+
last_updated: "2025-04-23T22:50:00.000Z",
|
|
128
|
+
volume24hUSD: 43588891208.92652,
|
|
129
|
+
price24hChangePercent: 1.17760374,
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
const rows = [];
|
|
133
|
+
|
|
134
|
+
const solanaService = runtime.getService("chain_solana") as
|
|
135
|
+
| {
|
|
136
|
+
getSupply?: (addresses: string[]) => Promise<
|
|
137
|
+
Record<
|
|
138
|
+
string,
|
|
139
|
+
{
|
|
140
|
+
human?: {
|
|
141
|
+
multipliedBy: (n: number) => {
|
|
142
|
+
toFixed: (p: number) => string;
|
|
143
|
+
};
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
>
|
|
147
|
+
>;
|
|
148
|
+
}
|
|
149
|
+
| undefined;
|
|
150
|
+
if (!solanaService) {
|
|
151
|
+
runtime.logger?.warn(
|
|
152
|
+
"no chain_solana service found - market cap calculation will be skipped for Solana tokens",
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const topSolanaTokens = solanaTokens.slice(0, 33);
|
|
157
|
+
let tokens = [...topSolanaTokens];
|
|
158
|
+
|
|
159
|
+
// Try to get supply data if solanaService is available
|
|
160
|
+
let supplies: Record<
|
|
161
|
+
string,
|
|
162
|
+
{
|
|
163
|
+
human?: {
|
|
164
|
+
multipliedBy: (n: number) => { toFixed: (p: number) => string };
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
> = {};
|
|
168
|
+
if (solanaService) {
|
|
169
|
+
try {
|
|
170
|
+
const CAs = topSolanaTokens.map((t) => t.address);
|
|
171
|
+
supplies = await solanaService.getSupply(CAs);
|
|
172
|
+
} catch (error) {
|
|
173
|
+
runtime.logger?.warn(
|
|
174
|
+
`Failed to get supply data from Solana service: ${error instanceof Error ? error.message : String(error)}`,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
for (const token of topSolanaTokens) {
|
|
180
|
+
// has a marketcap but seems to always be 0
|
|
181
|
+
//console.log('token', token)
|
|
182
|
+
const rugKey = `rugcheck_solana_${token.address}`;
|
|
183
|
+
const rugCache = await getCacheTimed(runtime, rugKey, {
|
|
184
|
+
notOlderThan: 6 * 60 * 60 * 1000,
|
|
185
|
+
});
|
|
186
|
+
//console.log('rugKey', rugKey, 'rugCache', rugCache)
|
|
187
|
+
|
|
188
|
+
// Damnatio memoriae
|
|
189
|
+
if (rugCache && rugCache === "rug") {
|
|
190
|
+
runtime.logger?.log("omitting", token.address, "because in rugCache");
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Calculate market cap if supply data is available
|
|
195
|
+
let mcapValue = "?";
|
|
196
|
+
if (supplies[token.address]?.human) {
|
|
197
|
+
const supply = supplies[token.address].human;
|
|
198
|
+
const mcap = supply.multipliedBy(token.price);
|
|
199
|
+
mcapValue = mcap.toFixed(0);
|
|
200
|
+
//console.log('Hum supply', supply.toFormat(), 'price', token.price, 'mcap', mcap.toFormat(2))
|
|
201
|
+
//console.log('Mac supply', supply, 'price', token.price, 'mcap', mcap.toFixed(0))
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
rows.push({
|
|
205
|
+
chain: "solana",
|
|
206
|
+
address: token.address,
|
|
207
|
+
symbol: token.symbol,
|
|
208
|
+
priceUsd: token.price.toFixed(4),
|
|
209
|
+
marketCapUsd: mcapValue,
|
|
210
|
+
volume24hUsd: token.volume24hUSD.toFixed(0),
|
|
211
|
+
change24hPct: token.price24hChangePercent.toFixed(2),
|
|
212
|
+
liquidityUsd: token.liquidity.toFixed(2),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
// if in cache, then it's a lot of data, maybe too much
|
|
216
|
+
const ethCache = await runtime.getCache<{
|
|
217
|
+
data: TrendingToken[];
|
|
218
|
+
setAt: number;
|
|
219
|
+
}>("tokens_v2_ethereum");
|
|
220
|
+
if (ethCache?.data) {
|
|
221
|
+
const ethTokens = ethCache.data.slice(0, 33);
|
|
222
|
+
tokens = [...tokens, ...ethTokens];
|
|
223
|
+
for (const token of ethTokens) {
|
|
224
|
+
// has a marketcap but seems to always be 0
|
|
225
|
+
//console.log('token', token)
|
|
226
|
+
/*
|
|
227
|
+
const rugKey = 'rugcheck_eth_' + token.address
|
|
228
|
+
const rugCache = await getCacheTimed(runtime, rugKey, { notOlderThan: 6 * 60 * 60 * 1000 })
|
|
229
|
+
//console.log('rugKey', rugKey, 'rugCache', rugCache)
|
|
230
|
+
|
|
231
|
+
// Damnatio memoriae
|
|
232
|
+
if (rugCache && rugCache === 'rug') {
|
|
233
|
+
console.log('omitting', token.address, 'because in rugCache')
|
|
234
|
+
continue
|
|
235
|
+
}
|
|
236
|
+
*/
|
|
237
|
+
rows.push({
|
|
238
|
+
chain: "ethereum",
|
|
239
|
+
address: token.address,
|
|
240
|
+
symbol: token.symbol,
|
|
241
|
+
priceUsd: token.price?.toFixed(4) || "0",
|
|
242
|
+
marketCapUsd: "unknown",
|
|
243
|
+
volume24hUsd: token.volume24hUSD?.toFixed(0) || "0",
|
|
244
|
+
change24hPct: token.price24hChangePercent?.toFixed(2) || "0",
|
|
245
|
+
liquidityUsd: token.liquidity?.toFixed(2) || "0",
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
const baseCache = await runtime.getCache<{
|
|
250
|
+
data: TrendingToken[];
|
|
251
|
+
setAt: number;
|
|
252
|
+
}>("tokens_v2_base");
|
|
253
|
+
if (baseCache?.data) {
|
|
254
|
+
const baseTokens = baseCache.data.slice(0, 33);
|
|
255
|
+
tokens = [...tokens, ...baseTokens];
|
|
256
|
+
for (const token of baseTokens) {
|
|
257
|
+
// has a marketcap but seems to always be 0
|
|
258
|
+
//console.log('token', token)
|
|
259
|
+
/*
|
|
260
|
+
const rugKey = 'rugcheck_eth_' + token.address
|
|
261
|
+
const rugCache = await getCacheTimed(runtime, rugKey, { notOlderThan: 6 * 60 * 60 * 1000 })
|
|
262
|
+
//console.log('rugKey', rugKey, 'rugCache', rugCache)
|
|
263
|
+
|
|
264
|
+
// Damnatio memoriae
|
|
265
|
+
if (rugCache && rugCache === 'rug') {
|
|
266
|
+
console.log('omitting', token.address, 'because in rugCache')
|
|
267
|
+
continue
|
|
268
|
+
}
|
|
269
|
+
*/
|
|
270
|
+
rows.push({
|
|
271
|
+
chain: "base",
|
|
272
|
+
address: token.address,
|
|
273
|
+
symbol: token.symbol,
|
|
274
|
+
priceUsd: token.price?.toFixed(4) || "0",
|
|
275
|
+
marketCapUsd: "unknown",
|
|
276
|
+
volume24hUsd: token.volume24hUSD?.toFixed(0) || "0",
|
|
277
|
+
change24hPct: token.price24hChangePercent?.toFixed(2) || "0",
|
|
278
|
+
liquidityUsd: token.liquidity?.toFixed(2) || "0",
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/*
|
|
284
|
+
let idx = 1;
|
|
285
|
+
// maybe filter by active chains
|
|
286
|
+
const reduceTokens = tokens.map((t) => {
|
|
287
|
+
const obj = {
|
|
288
|
+
name: t.name,
|
|
289
|
+
rank: t.rank,
|
|
290
|
+
chain: t.chain,
|
|
291
|
+
priceUsd: t.price,
|
|
292
|
+
symbol: t.symbol,
|
|
293
|
+
address: t.address,
|
|
294
|
+
// skip logo, decimals
|
|
295
|
+
// liquidity/marketcap are optimal
|
|
296
|
+
// last_updated
|
|
297
|
+
volume24hUSD: t.volume24hUSD,
|
|
298
|
+
price24hChangePercent: t.price24hChangePercent,
|
|
299
|
+
};
|
|
300
|
+
// optional fields
|
|
301
|
+
if (t.liquidity !== null) obj.liquidity = t.liquidity;
|
|
302
|
+
if (t.marketcap !== 0) obj.marketcap = t.marketcap;
|
|
303
|
+
return obj;
|
|
304
|
+
});
|
|
305
|
+
*/
|
|
306
|
+
|
|
307
|
+
/*
|
|
308
|
+
for (const t of tokens) {
|
|
309
|
+
if (!sentiment?.occuringTokens?.length) continue;
|
|
310
|
+
sentiments += `ENTRY ${idx}\nTIME: ${sentiment.timeslot}\nTOKEN ANALYSIS:\n`;
|
|
311
|
+
for (const token of sentiment.occuringTokens) {
|
|
312
|
+
sentiments += `${token.token} - Sentiment: ${token.sentiment}\n${token.reason}\n`;
|
|
313
|
+
}
|
|
314
|
+
latestTxt += '\n-------------------\n';
|
|
315
|
+
idx++;
|
|
316
|
+
}
|
|
317
|
+
*/
|
|
318
|
+
//latestTxt += '\n' + JSON.stringify(reduceTokens) + '\n';
|
|
319
|
+
|
|
320
|
+
//console.log('intel:provider - cmc token text', rows)
|
|
321
|
+
|
|
322
|
+
const boundedRows = rows.slice(0, TRENDING_ROW_LIMIT);
|
|
323
|
+
const data = {
|
|
324
|
+
tokens: tokens.slice(0, TRENDING_ROW_LIMIT),
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
const values = {};
|
|
328
|
+
|
|
329
|
+
// Combine all text sections
|
|
330
|
+
const text = [
|
|
331
|
+
"birdeye_trending_tokens:",
|
|
332
|
+
" status: ok",
|
|
333
|
+
formatJsonTable(" tokens", boundedRows, [
|
|
334
|
+
"chain",
|
|
335
|
+
"address",
|
|
336
|
+
"symbol",
|
|
337
|
+
"priceUsd",
|
|
338
|
+
"marketCapUsd",
|
|
339
|
+
"volume24hUsd",
|
|
340
|
+
"change24hPct",
|
|
341
|
+
"liquidityUsd",
|
|
342
|
+
]),
|
|
343
|
+
].join("\n");
|
|
344
|
+
|
|
345
|
+
return {
|
|
346
|
+
data,
|
|
347
|
+
values,
|
|
348
|
+
text,
|
|
349
|
+
};
|
|
350
|
+
} catch (error) {
|
|
351
|
+
runtime.logger?.error(
|
|
352
|
+
`Error fetching trending data: ${error instanceof Error ? error.message : String(error)}`,
|
|
353
|
+
);
|
|
354
|
+
return {
|
|
355
|
+
values: {},
|
|
356
|
+
text: [
|
|
357
|
+
"birdeye_trending_tokens:",
|
|
358
|
+
" status: error",
|
|
359
|
+
` reason: ${formatJsonScalar(error instanceof Error ? error.message : String(error))}`,
|
|
360
|
+
].join("\n"),
|
|
361
|
+
data: {},
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// @ts-nocheck — legacy code from absorbed plugins (lp-manager, lpinfo, dexscreener, defi-news, birdeye); strict types pending cleanup
|
|
2
|
+
import { createBirdeyePortfolioProvider } from "./portfolio-factory";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Optional wallet trade provider. It shares wallet, chain, service, error, and JSON
|
|
6
|
+
* formatting behavior with the agent portfolio provider through the portfolio factory.
|
|
7
|
+
*/
|
|
8
|
+
export const tradePortfolioProvider = createBirdeyePortfolioProvider({
|
|
9
|
+
name: "BIRDEYE_TRADE_PORTFOLIO",
|
|
10
|
+
description: "Birdeye wallet portfolio and recent trade history",
|
|
11
|
+
descriptionCompressed:
|
|
12
|
+
"Read Birdeye wallet portfolio and recent trade history.",
|
|
13
|
+
includeTrades: true,
|
|
14
|
+
});
|