@elizaos/plugin-social-alpha 2.0.3-beta.5 → 2.0.3-beta.7
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/clients.d.ts +354 -0
- package/dist/clients.d.ts.map +1 -0
- package/dist/clients.js +670 -0
- package/dist/clients.js.map +1 -0
- package/dist/config.d.ts +144 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +122 -0
- package/dist/config.js.map +1 -0
- package/dist/events.d.ts +5 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +426 -0
- package/dist/events.js.map +1 -0
- package/dist/frontend/LeaderboardView.helpers.d.ts +6 -0
- package/dist/frontend/LeaderboardView.helpers.d.ts.map +1 -0
- package/dist/frontend/LeaderboardView.helpers.js +59 -0
- package/dist/frontend/LeaderboardView.helpers.js.map +1 -0
- package/dist/frontend/SocialAlphaSpatialView.d.ts +52 -0
- package/dist/frontend/SocialAlphaSpatialView.d.ts.map +1 -0
- package/dist/frontend/SocialAlphaSpatialView.js +72 -0
- package/dist/frontend/SocialAlphaSpatialView.js.map +1 -0
- package/dist/frontend/SocialAlphaView.d.ts +35 -0
- package/dist/frontend/SocialAlphaView.d.ts.map +1 -0
- package/dist/frontend/SocialAlphaView.js +125 -0
- package/dist/frontend/SocialAlphaView.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/mockPriceService.d.ts +22 -0
- package/dist/mockPriceService.d.ts.map +1 -0
- package/dist/mockPriceService.js +21 -0
- package/dist/mockPriceService.js.map +1 -0
- package/dist/providers/socialAlphaProvider.d.ts +15 -0
- package/dist/providers/socialAlphaProvider.d.ts.map +1 -0
- package/dist/providers/socialAlphaProvider.js +261 -0
- package/dist/providers/socialAlphaProvider.js.map +1 -0
- package/dist/register-terminal-view.d.ts +15 -0
- package/dist/register-terminal-view.d.ts.map +1 -0
- package/dist/register-terminal-view.js +21 -0
- package/dist/register-terminal-view.js.map +1 -0
- package/dist/register.d.ts +10 -0
- package/dist/register.d.ts.map +1 -0
- package/dist/register.js +5 -0
- package/dist/register.js.map +1 -0
- package/dist/reports.d.ts +57 -0
- package/dist/reports.d.ts.map +1 -0
- package/dist/reports.js +455 -0
- package/dist/reports.js.map +1 -0
- package/dist/routes.d.ts +3 -0
- package/dist/routes.d.ts.map +1 -0
- package/dist/routes.js +59 -0
- package/dist/routes.js.map +1 -0
- package/dist/schemas.d.ts +151 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +258 -0
- package/dist/schemas.js.map +1 -0
- package/dist/service.d.ts +306 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +3078 -0
- package/dist/service.js.map +1 -0
- package/dist/services/balancedTrustScoreCalculator.d.ts +61 -0
- package/dist/services/balancedTrustScoreCalculator.d.ts.map +1 -0
- package/dist/services/balancedTrustScoreCalculator.js +207 -0
- package/dist/services/balancedTrustScoreCalculator.js.map +1 -0
- package/dist/services/historicalPriceService.d.ts +59 -0
- package/dist/services/historicalPriceService.d.ts.map +1 -0
- package/dist/services/historicalPriceService.js +291 -0
- package/dist/services/historicalPriceService.js.map +1 -0
- package/dist/services/index.d.ts +12 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +17 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/priceEnrichmentService.d.ts +109 -0
- package/dist/services/priceEnrichmentService.d.ts.map +1 -0
- package/dist/services/priceEnrichmentService.js +780 -0
- package/dist/services/priceEnrichmentService.js.map +1 -0
- package/dist/services/simulationActorsV2.d.ts +54 -0
- package/dist/services/simulationActorsV2.d.ts.map +1 -0
- package/dist/services/simulationActorsV2.js +362 -0
- package/dist/services/simulationActorsV2.js.map +1 -0
- package/dist/services/simulationRunner.d.ts +113 -0
- package/dist/services/simulationRunner.d.ts.map +1 -0
- package/dist/services/simulationRunner.js +771 -0
- package/dist/services/simulationRunner.js.map +1 -0
- package/dist/services/tokenSimulationService.d.ts +34 -0
- package/dist/services/tokenSimulationService.d.ts.map +1 -0
- package/dist/services/tokenSimulationService.js +297 -0
- package/dist/services/tokenSimulationService.js.map +1 -0
- package/dist/services/trustScoreOptimizer.d.ts +110 -0
- package/dist/services/trustScoreOptimizer.d.ts.map +1 -0
- package/dist/services/trustScoreOptimizer.js +635 -0
- package/dist/services/trustScoreOptimizer.js.map +1 -0
- package/dist/simulationActors.d.ts +35 -0
- package/dist/simulationActors.d.ts.map +1 -0
- package/dist/simulationActors.js +160 -0
- package/dist/simulationActors.js.map +1 -0
- package/dist/social-alpha-view-bundle.d.ts +2 -0
- package/dist/social-alpha-view-bundle.d.ts.map +1 -0
- package/dist/social-alpha-view-bundle.js +5 -0
- package/dist/social-alpha-view-bundle.js.map +1 -0
- package/dist/types.d.ts +937 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +46 -0
- package/dist/types.js.map +1 -0
- package/dist/views/brand/background/clouds_background.jpg +0 -0
- package/dist/views/brand/banners/eliza_banner.svg +20 -0
- package/dist/views/brand/banners/elizacloud_banner.svg +20 -0
- package/dist/views/brand/banners/elizaos_banner.svg +20 -0
- package/dist/views/brand/concepts/billboard_concept_1200.jpg +0 -0
- package/dist/views/brand/concepts/chibi_usb_concept_900.jpg +0 -0
- package/dist/views/brand/concepts/concept_minipc_900.jpg +0 -0
- package/dist/views/brand/concepts/concept_phone_800.jpg +0 -0
- package/dist/views/brand/concepts/concept_usbdrive_900.jpg +0 -0
- package/dist/views/brand/favicons/android-chrome-192x192.png +0 -0
- package/dist/views/brand/favicons/android-chrome-512x512.png +0 -0
- package/dist/views/brand/favicons/apple-touch-icon.png +0 -0
- package/dist/views/brand/favicons/favicon-16x16.png +0 -0
- package/dist/views/brand/favicons/favicon-32x32.png +0 -0
- package/dist/views/brand/favicons/favicon.ico +0 -0
- package/dist/views/brand/favicons/favicon.svg +17 -0
- package/dist/views/brand/logos/elizaOS_text_black.svg +3 -0
- package/dist/views/brand/logos/elizaOS_text_white.svg +3 -0
- package/dist/views/brand/logos/eliza_logotext.svg +26 -0
- package/dist/views/brand/logos/eliza_logotext_black.svg +26 -0
- package/dist/views/brand/logos/eliza_text_black.svg +3 -0
- package/dist/views/brand/logos/eliza_text_white.svg +3 -0
- package/dist/views/brand/logos/elizacloud_logotext.svg +26 -0
- package/dist/views/brand/logos/elizacloud_logotext_black.svg +26 -0
- package/dist/views/brand/logos/elizacloud_text_black.svg +3 -0
- package/dist/views/brand/logos/elizacloud_text_white.svg +3 -0
- package/dist/views/brand/logos/elizaos_logotext.svg +26 -0
- package/dist/views/brand/logos/elizaos_logotext_black.svg +26 -0
- package/dist/views/brand/logos/logo_blue_blackbg.svg +18 -0
- package/dist/views/brand/logos/logo_blue_nobg.svg +17 -0
- package/dist/views/brand/logos/logo_orange_blackbg.svg +18 -0
- package/dist/views/brand/logos/logo_orange_nobg.svg +17 -0
- package/dist/views/brand/logos/logo_white_blackbg.svg +25 -0
- package/dist/views/brand/logos/logo_white_bluebg.svg +25 -0
- package/dist/views/brand/logos/logo_white_graybg.svg +18 -0
- package/dist/views/brand/logos/logo_white_nobg.svg +24 -0
- package/dist/views/brand/logos/logo_white_orangebg.svg +25 -0
- package/dist/views/brand/ogembeds/eliza_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/eliza_ogembed.svg +20 -0
- package/dist/views/brand/ogembeds/elizacloud_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/elizacloud_ogembed.svg +20 -0
- package/dist/views/brand/ogembeds/elizaos_ogembed.png +0 -0
- package/dist/views/brand/ogembeds/elizaos_ogembed.svg +20 -0
- package/dist/views/bundle.js +268 -0
- package/dist/views/bundle.js.map +1 -0
- package/dist/views/site.webmanifest +19 -0
- package/package.json +5 -5
package/dist/clients.js
ADDED
|
@@ -0,0 +1,670 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import * as dotenv from "dotenv";
|
|
3
|
+
import { BTC_ADDRESS, ETH_ADDRESS, SOL_ADDRESS } from "./config.js";
|
|
4
|
+
dotenv.config();
|
|
5
|
+
let nextRpcRequestId = 1;
|
|
6
|
+
const DEFAULT_RETRY_OPTIONS = {
|
|
7
|
+
maxRetries: 3,
|
|
8
|
+
initialDelay: 1e3,
|
|
9
|
+
maxDelay: 3e4,
|
|
10
|
+
backoffFactor: 2,
|
|
11
|
+
retryableStatuses: [408, 429, 500, 502, 503, 504]
|
|
12
|
+
};
|
|
13
|
+
class RequestError extends Error {
|
|
14
|
+
/**
|
|
15
|
+
* Constructor for creating a RequestError instance.
|
|
16
|
+
*
|
|
17
|
+
* @param {string} message - The error message for the RequestError instance.
|
|
18
|
+
* @param {Response} [response] - Optional response object associated with the error.
|
|
19
|
+
*/
|
|
20
|
+
constructor(message, response) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.response = response;
|
|
23
|
+
this.name = "RequestError";
|
|
24
|
+
}
|
|
25
|
+
response;
|
|
26
|
+
}
|
|
27
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
28
|
+
const calculateDelay = (attempt, options) => {
|
|
29
|
+
const delay = options.initialDelay * options.backoffFactor ** (attempt - 1);
|
|
30
|
+
return Math.min(delay, options.maxDelay);
|
|
31
|
+
};
|
|
32
|
+
const isRetryableError = (error) => error instanceof Error && (error.name === "TypeError" || error.name === "AbortError") || error instanceof RequestError;
|
|
33
|
+
const buildUrl = (url, params) => {
|
|
34
|
+
if (!params) return url;
|
|
35
|
+
const searchParams = params instanceof URLSearchParams ? params : new URLSearchParams(
|
|
36
|
+
Object.entries(params).filter(([_, value]) => value != null).map(([key, value]) => [key, String(value)])
|
|
37
|
+
);
|
|
38
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
39
|
+
const queryString = searchParams.toString();
|
|
40
|
+
return queryString ? `${url}${separator}${queryString}` : url;
|
|
41
|
+
};
|
|
42
|
+
const http = {
|
|
43
|
+
async request(url, options) {
|
|
44
|
+
const { params, ...fetchOptions } = options || {};
|
|
45
|
+
const fullUrl = buildUrl(url, params);
|
|
46
|
+
const retryOptions = {
|
|
47
|
+
...DEFAULT_RETRY_OPTIONS,
|
|
48
|
+
...options?.retryOptions
|
|
49
|
+
};
|
|
50
|
+
let attempt = 1;
|
|
51
|
+
while (true) {
|
|
52
|
+
try {
|
|
53
|
+
const res = await fetch(fullUrl, fetchOptions);
|
|
54
|
+
if (!res.ok) {
|
|
55
|
+
const errorText = await res.text();
|
|
56
|
+
throw new RequestError(
|
|
57
|
+
`Request failed with status ${res.status}: ${errorText}`,
|
|
58
|
+
res
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return res;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
if (isRetryableError(error) && attempt < retryOptions.maxRetries) {
|
|
64
|
+
const delay = calculateDelay(attempt, retryOptions);
|
|
65
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
66
|
+
console.warn(
|
|
67
|
+
`Request failed with error: ${errorMessage}. Retrying in ${delay}ms (attempt ${attempt}/${retryOptions.maxRetries})`
|
|
68
|
+
);
|
|
69
|
+
await sleep(delay);
|
|
70
|
+
attempt++;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
console.error(`Request failed after ${attempt} attempts:`, error);
|
|
74
|
+
throw error;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
async json(url, options) {
|
|
79
|
+
const res = await this.request(url, {
|
|
80
|
+
...options,
|
|
81
|
+
headers: {
|
|
82
|
+
"Content-Type": "application/json",
|
|
83
|
+
...options?.headers
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
return await res.json();
|
|
87
|
+
},
|
|
88
|
+
get: {
|
|
89
|
+
async request(url, params, options) {
|
|
90
|
+
return http.request(url, {
|
|
91
|
+
...options,
|
|
92
|
+
method: "GET",
|
|
93
|
+
params
|
|
94
|
+
});
|
|
95
|
+
},
|
|
96
|
+
async json(url, params, options) {
|
|
97
|
+
return http.json(url, {
|
|
98
|
+
...options,
|
|
99
|
+
method: "GET",
|
|
100
|
+
params
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
post: {
|
|
105
|
+
async request(url, body, options) {
|
|
106
|
+
return http.request(url, {
|
|
107
|
+
...options,
|
|
108
|
+
method: "POST",
|
|
109
|
+
body: JSON.stringify(body)
|
|
110
|
+
});
|
|
111
|
+
},
|
|
112
|
+
async json(url, body, options) {
|
|
113
|
+
return http.json(url, {
|
|
114
|
+
...options,
|
|
115
|
+
method: "POST",
|
|
116
|
+
body: JSON.stringify(body)
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
async jsonrpc(url, method, params, headers) {
|
|
121
|
+
return http.post.json(
|
|
122
|
+
url,
|
|
123
|
+
{
|
|
124
|
+
jsonrpc: "2.0",
|
|
125
|
+
id: nextRpcRequestId++,
|
|
126
|
+
method,
|
|
127
|
+
params
|
|
128
|
+
},
|
|
129
|
+
{ headers }
|
|
130
|
+
);
|
|
131
|
+
},
|
|
132
|
+
async graphql(url, query, variables, headers) {
|
|
133
|
+
return http.post.json(
|
|
134
|
+
url,
|
|
135
|
+
{
|
|
136
|
+
query,
|
|
137
|
+
variables
|
|
138
|
+
},
|
|
139
|
+
{ headers }
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
class DexscreenerClient {
|
|
144
|
+
/**
|
|
145
|
+
* Constructor for the class.
|
|
146
|
+
* @param {IAgentRuntime} runtime - The runtime passed as a parameter to the constructor.
|
|
147
|
+
*/
|
|
148
|
+
constructor(runtime) {
|
|
149
|
+
this.runtime = runtime;
|
|
150
|
+
}
|
|
151
|
+
runtime;
|
|
152
|
+
/**
|
|
153
|
+
* Create a new DexscreenerClient instance using the provided agent runtime.
|
|
154
|
+
*
|
|
155
|
+
* @param {IAgentRuntime} runtime - The agent runtime to use for creating the DexscreenerClient instance.
|
|
156
|
+
* @returns {DexscreenerClient} A new instance of DexscreenerClient.
|
|
157
|
+
*/
|
|
158
|
+
static createFromRuntime(runtime) {
|
|
159
|
+
return new DexscreenerClient(runtime);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Makes an asynchronous HTTP request to the DexScreener API.
|
|
163
|
+
*
|
|
164
|
+
* @template T - The type of data expected to be returned
|
|
165
|
+
* @param {string} path - The endpoint path for the API request
|
|
166
|
+
* @param {QueryParams} [params] - Optional query parameters for the request
|
|
167
|
+
* @param {DexscreenerOptions} [options] - Optional options for the request
|
|
168
|
+
* @returns {Promise<T>} - A promise that resolves with the data returned from the API
|
|
169
|
+
*/
|
|
170
|
+
async request(path, params, options) {
|
|
171
|
+
const cacheKey = [
|
|
172
|
+
"dexscreener",
|
|
173
|
+
buildUrl(path, params)
|
|
174
|
+
// remove first "/"
|
|
175
|
+
].filter(Boolean).join("/");
|
|
176
|
+
if (options?.expires) {
|
|
177
|
+
const cached = await this.runtime.getCache(cacheKey);
|
|
178
|
+
if (cached) return cached;
|
|
179
|
+
}
|
|
180
|
+
const res = await http.get.json(
|
|
181
|
+
`https://api.dexscreener.com/${path}`,
|
|
182
|
+
params
|
|
183
|
+
);
|
|
184
|
+
if (options?.expires) {
|
|
185
|
+
await this.runtime.setCache(cacheKey, res);
|
|
186
|
+
}
|
|
187
|
+
return res;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Asynchronously searches for DexScreener data based on the provided address.
|
|
191
|
+
*
|
|
192
|
+
* @param {string} address - The address to search for in DexScreener data.
|
|
193
|
+
* @param {DexscreenerOptions} [options] - Optional parameters for the request.
|
|
194
|
+
* @returns {Promise<DexScreenerData>} A promise that resolves with the DexScreener data.
|
|
195
|
+
*/
|
|
196
|
+
async search(address, options) {
|
|
197
|
+
try {
|
|
198
|
+
const data = await this.request(
|
|
199
|
+
"latest/dex/search",
|
|
200
|
+
{
|
|
201
|
+
q: address
|
|
202
|
+
},
|
|
203
|
+
options
|
|
204
|
+
);
|
|
205
|
+
if (!data?.pairs) {
|
|
206
|
+
throw new Error("No DexScreener data available");
|
|
207
|
+
}
|
|
208
|
+
return data;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error("Error fetching DexScreener data:", error);
|
|
211
|
+
return {
|
|
212
|
+
schemaVersion: "1.0.0",
|
|
213
|
+
pairs: []
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Asynchronously searches for the pair with the highest liquidity based on the given address.
|
|
219
|
+
*
|
|
220
|
+
* @param {string} address The address to search for liquidity pairs from.
|
|
221
|
+
* @param {string} [chain] The chain ID to filter the liquidity pairs by.
|
|
222
|
+
* @param {DexscreenerOptions} [options] Additional options for searching.
|
|
223
|
+
* @returns {Promise<DexScreenerPair | null>} The pair with the highest liquidity, or null if no pairs were found.
|
|
224
|
+
*/
|
|
225
|
+
async searchForHighestLiquidityPair(address, chain, options) {
|
|
226
|
+
let { pairs } = await this.search(address, options);
|
|
227
|
+
if (pairs.length === 0) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
if (chain) {
|
|
231
|
+
pairs = pairs.filter((pair) => pair.chainId === chain);
|
|
232
|
+
}
|
|
233
|
+
return pairs.sort((a, b) => {
|
|
234
|
+
const liquidityA = a.liquidity?.usd ?? 0;
|
|
235
|
+
const liquidityB = b.liquidity?.usd ?? 0;
|
|
236
|
+
return liquidityB < liquidityA ? -1 : 1;
|
|
237
|
+
})[0];
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
class HeliusClient {
|
|
241
|
+
/**
|
|
242
|
+
* Constructor for initializing an instance of class.
|
|
243
|
+
*
|
|
244
|
+
* @param apiKey - The API key to be used for authentication.
|
|
245
|
+
* @param _runtime - The runtime environment for the agent.
|
|
246
|
+
*/
|
|
247
|
+
constructor(apiKey, runtime) {
|
|
248
|
+
this.apiKey = apiKey;
|
|
249
|
+
this.runtime = runtime;
|
|
250
|
+
}
|
|
251
|
+
apiKey;
|
|
252
|
+
runtime;
|
|
253
|
+
/**
|
|
254
|
+
* Creates a new HeliusClient instance using the provided IAgentRuntime.
|
|
255
|
+
*
|
|
256
|
+
* @param {IAgentRuntime} runtime - The IAgentRuntime to use for creating the HeliusClient.
|
|
257
|
+
* @returns {HeliusClient} A new instance of HeliusClient.
|
|
258
|
+
* @throws {Error} Thrown if HELIUS_API_KEY is missing from the runtime settings.
|
|
259
|
+
*/
|
|
260
|
+
static createFromRuntime(runtime) {
|
|
261
|
+
const apiKey = runtime.getSetting("HELIUS_API_KEY");
|
|
262
|
+
if (!apiKey) {
|
|
263
|
+
throw new Error("missing HELIUS_API_KEY");
|
|
264
|
+
}
|
|
265
|
+
return new HeliusClient(String(apiKey), runtime);
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Fetches the list of token holders for a given address asynchronously.
|
|
269
|
+
* If the option `expires` is provided and there is a cached version available, it returns the cached data.
|
|
270
|
+
* Otherwise, it fetches the data from the Helius API using the provided address.
|
|
271
|
+
*
|
|
272
|
+
* @param {string} address - The address for which to fetch the list of token holders.
|
|
273
|
+
* @param {Object} [options] - Optional parameters.
|
|
274
|
+
* @param {string | CacheOptions["expires"]} [options.expires] - The expiration date for caching the data.
|
|
275
|
+
*
|
|
276
|
+
* @returns {Promise<HolderData[]>} A promise that resolves to an array of HolderData objects representing the token holders.
|
|
277
|
+
*/
|
|
278
|
+
async fetchHolderList(address, options) {
|
|
279
|
+
if (options?.expires) {
|
|
280
|
+
const cached = await this.runtime.getCache(
|
|
281
|
+
`helius/token-holders/${address}`
|
|
282
|
+
);
|
|
283
|
+
if (cached) return cached;
|
|
284
|
+
}
|
|
285
|
+
const allHoldersMap = /* @__PURE__ */ new Map();
|
|
286
|
+
let page = 1;
|
|
287
|
+
const limit = 1e3;
|
|
288
|
+
let cursor;
|
|
289
|
+
const url = `https://mainnet.helius-rpc.com/?api-key=${this.apiKey}`;
|
|
290
|
+
try {
|
|
291
|
+
while (true) {
|
|
292
|
+
const params = {
|
|
293
|
+
limit,
|
|
294
|
+
displayOptions: {},
|
|
295
|
+
mint: address
|
|
296
|
+
};
|
|
297
|
+
if (cursor) {
|
|
298
|
+
params.cursor = cursor;
|
|
299
|
+
}
|
|
300
|
+
if (page > 2) break;
|
|
301
|
+
const data = await http.jsonrpc(url, "getTokenAccounts", params);
|
|
302
|
+
if (!data?.result?.token_accounts?.length) break;
|
|
303
|
+
data.result.token_accounts.forEach((account) => {
|
|
304
|
+
const owner = account.owner;
|
|
305
|
+
const balance = Number.parseFloat(String(account.amount ?? 0));
|
|
306
|
+
if (owner && Number.isFinite(balance)) {
|
|
307
|
+
allHoldersMap.set(owner, (allHoldersMap.get(owner) || 0) + balance);
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
cursor = data.result.cursor;
|
|
311
|
+
page++;
|
|
312
|
+
}
|
|
313
|
+
const holders = Array.from(allHoldersMap.entries()).map(
|
|
314
|
+
([address2, balance]) => ({
|
|
315
|
+
address: address2,
|
|
316
|
+
balance: balance.toString()
|
|
317
|
+
})
|
|
318
|
+
);
|
|
319
|
+
if (options?.expires)
|
|
320
|
+
await this.runtime.setCache(
|
|
321
|
+
`helius/token-holders/${address}`,
|
|
322
|
+
holders
|
|
323
|
+
);
|
|
324
|
+
return holders;
|
|
325
|
+
} catch (error) {
|
|
326
|
+
console.error("Error fetching holder list from Helius:", error);
|
|
327
|
+
throw new Error("Failed to fetch holder list from Helius.");
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
class CoingeckoClient {
|
|
332
|
+
/**
|
|
333
|
+
* Constructor for initializing a new instance of the class.
|
|
334
|
+
* @param apiKey The API key used for authentication.
|
|
335
|
+
* @param runtime The agent runtime implementation.
|
|
336
|
+
*/
|
|
337
|
+
constructor(apiKey, runtime) {
|
|
338
|
+
this.apiKey = apiKey;
|
|
339
|
+
this.runtime = runtime;
|
|
340
|
+
}
|
|
341
|
+
apiKey;
|
|
342
|
+
runtime;
|
|
343
|
+
/**
|
|
344
|
+
* Creates a new instance of CoingeckoClient using the apiKey retrieved from the provided runtime.
|
|
345
|
+
* @param {IAgentRuntime} runtime - The runtime object that contains the COINGECKO_API_KEY setting.
|
|
346
|
+
* @throws {Error} If COINGECKO_API_KEY setting is missing in the runtime object.
|
|
347
|
+
* @returns {CoingeckoClient} A new instance of CoingeckoClient initialized with the apiKey and runtime.
|
|
348
|
+
*/
|
|
349
|
+
static createFromRuntime(runtime) {
|
|
350
|
+
const apiKey = runtime.getSetting("COINGECKO_API_KEY");
|
|
351
|
+
if (!apiKey) {
|
|
352
|
+
throw new Error("missing COINGECKO_API_KEY");
|
|
353
|
+
}
|
|
354
|
+
return new CoingeckoClient(String(apiKey), runtime);
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Makes an asynchronous HTTP request to the Coingecko API.
|
|
358
|
+
* @template T
|
|
359
|
+
* @param {string} path - The API endpoint to call.
|
|
360
|
+
* @param {QueryParams} [params] - Optional query parameters to include in the request.
|
|
361
|
+
* @param {CoingeckoOptions} [options] - Additional options for the request.
|
|
362
|
+
* @returns {Promise<T>} The response data from the API.
|
|
363
|
+
*/
|
|
364
|
+
async request(path, params, options) {
|
|
365
|
+
const cacheKey = ["coingecko", buildUrl(path, params)].filter(Boolean).join("/");
|
|
366
|
+
if (options?.expires) {
|
|
367
|
+
const cached = await this.runtime.getCache(cacheKey);
|
|
368
|
+
if (cached) return cached;
|
|
369
|
+
}
|
|
370
|
+
const res = await http.get.json(
|
|
371
|
+
`https://api.coingecko.com/api/v3/${path}`,
|
|
372
|
+
params,
|
|
373
|
+
{
|
|
374
|
+
headers: {
|
|
375
|
+
"x-cg-demo-api-key": this.apiKey
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
);
|
|
379
|
+
if (options?.expires) {
|
|
380
|
+
await this.runtime.setCache(cacheKey, res);
|
|
381
|
+
}
|
|
382
|
+
return res;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Fetches prices for specified cryptocurrencies from the Coingecko API.
|
|
386
|
+
*
|
|
387
|
+
* @param {CoingeckoOptions} [options] The options for the Coingecko API request.
|
|
388
|
+
* @returns {Promise<Prices>} A Promise that resolves to the prices of the specified cryptocurrencies.
|
|
389
|
+
*/
|
|
390
|
+
async fetchPrices(options) {
|
|
391
|
+
const prices = await this.request(
|
|
392
|
+
"simple/price",
|
|
393
|
+
{
|
|
394
|
+
ids: "solana,bitcoin,ethereum",
|
|
395
|
+
vs_currencies: "usd"
|
|
396
|
+
},
|
|
397
|
+
options
|
|
398
|
+
);
|
|
399
|
+
return prices;
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Asynchronously fetches global data.
|
|
403
|
+
*
|
|
404
|
+
* @returns {Promise} The promise containing the global data.
|
|
405
|
+
*/
|
|
406
|
+
async fetchGlobal() {
|
|
407
|
+
return this.request(
|
|
408
|
+
"global",
|
|
409
|
+
{},
|
|
410
|
+
{
|
|
411
|
+
expires: "30m"
|
|
412
|
+
}
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Asynchronously fetches a list of coin categories.
|
|
417
|
+
* @returns {Promise} The Promise object representing the result of the fetch operation.
|
|
418
|
+
*/
|
|
419
|
+
async fetchCategories() {
|
|
420
|
+
return this.request(
|
|
421
|
+
"coins/categories",
|
|
422
|
+
{},
|
|
423
|
+
{
|
|
424
|
+
expires: "30m"
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
class BirdeyeClient {
|
|
430
|
+
/**
|
|
431
|
+
* Constructor for initializing a new instance.
|
|
432
|
+
*
|
|
433
|
+
* @param apiKey The API key to be used.
|
|
434
|
+
* @param runtime The agent runtime for handling communication with the runtime environment.
|
|
435
|
+
*/
|
|
436
|
+
constructor(apiKey, runtime) {
|
|
437
|
+
this.apiKey = apiKey;
|
|
438
|
+
this.runtime = runtime;
|
|
439
|
+
}
|
|
440
|
+
apiKey;
|
|
441
|
+
static url = "https://public-api.birdeye.so/";
|
|
442
|
+
runtime;
|
|
443
|
+
/**
|
|
444
|
+
* Send a request to the Birdeye API using the provided API key, path, query parameters, and headers.
|
|
445
|
+
*
|
|
446
|
+
* @param {string} apiKey - The API key for authenticating the request.
|
|
447
|
+
* @param {string} path - The endpoint path to send the request to.
|
|
448
|
+
* @param {QueryParams} [params] - Optional query parameters to include in the request.
|
|
449
|
+
* @param {BirdeyeClientHeaders} [headers] - Optional additional headers to include in the request.
|
|
450
|
+
* @returns {Promise<T>} A Promise that resolves with the data received from the API request.
|
|
451
|
+
*/
|
|
452
|
+
static async request(apiKey, path, params, headers) {
|
|
453
|
+
const res = await http.get.json(
|
|
454
|
+
BirdeyeClient.url + path,
|
|
455
|
+
params,
|
|
456
|
+
{
|
|
457
|
+
headers: {
|
|
458
|
+
...headers,
|
|
459
|
+
"X-API-KEY": apiKey
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
);
|
|
463
|
+
if (!res.success || !res.data) {
|
|
464
|
+
console.error({ res });
|
|
465
|
+
throw new Error(`Birdeye request failed:${path}`);
|
|
466
|
+
}
|
|
467
|
+
return res.data;
|
|
468
|
+
}
|
|
469
|
+
/**
|
|
470
|
+
* Create a new BirdeyeClient instance using the provided IAgentRuntime object.
|
|
471
|
+
*
|
|
472
|
+
* @param {IAgentRuntime} runtime - The IAgentRuntime object that provides access to runtime settings.
|
|
473
|
+
* @returns {BirdeyeClient} A new instance of BirdeyeClient initialized with the provided API key and runtime.
|
|
474
|
+
* @throws {Error} Thrown if the BIRDEYE_API_KEY setting is missing in the runtime object.
|
|
475
|
+
*/
|
|
476
|
+
static createFromRuntime(runtime) {
|
|
477
|
+
const apiKey = runtime.getSetting("BIRDEYE_API_KEY");
|
|
478
|
+
if (!apiKey) {
|
|
479
|
+
throw new Error("missing BIRDEYE_API_KEY");
|
|
480
|
+
}
|
|
481
|
+
return new BirdeyeClient(String(apiKey), runtime);
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Performs a request to the specified path with given query parameters and options.
|
|
485
|
+
* @template T
|
|
486
|
+
* @param {string} path - The path to request.
|
|
487
|
+
* @param {QueryParams} params - The query parameters to include in the request.
|
|
488
|
+
* @param {BirdeyeRequestOptions} [options] - Optional request options.
|
|
489
|
+
* @param {boolean} [forceRefresh] - Flag to force refresh the cache.
|
|
490
|
+
* @returns {Promise<T>} The response data from the request.
|
|
491
|
+
*/
|
|
492
|
+
async request(path, params, options, forceRefresh) {
|
|
493
|
+
const cacheKey = ["birdeye", options?.chain, buildUrl(path, params)].filter(Boolean).join("/");
|
|
494
|
+
if (options?.expires && !forceRefresh) {
|
|
495
|
+
const cached = await this.runtime.getCache(cacheKey);
|
|
496
|
+
if (cached) return cached;
|
|
497
|
+
}
|
|
498
|
+
const response = await BirdeyeClient.request(
|
|
499
|
+
this.apiKey,
|
|
500
|
+
path,
|
|
501
|
+
params,
|
|
502
|
+
options?.chain ? {
|
|
503
|
+
"x-chain": options.chain
|
|
504
|
+
} : void 0
|
|
505
|
+
);
|
|
506
|
+
if (options?.expires) {
|
|
507
|
+
await this.runtime.setCache(cacheKey, response);
|
|
508
|
+
}
|
|
509
|
+
return response;
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* Fetches the price for a given address.
|
|
513
|
+
*
|
|
514
|
+
* @param {string} address - The address for which to fetch the price.
|
|
515
|
+
* @param {BirdeyeRequestOptions} [options] - The options for the Birdeye request.
|
|
516
|
+
* @returns {Promise<number>} The price value fetched for the given address.
|
|
517
|
+
*/
|
|
518
|
+
async fetchPrice(address, options) {
|
|
519
|
+
const price = await this.request(
|
|
520
|
+
"defi/price",
|
|
521
|
+
{ address },
|
|
522
|
+
options
|
|
523
|
+
);
|
|
524
|
+
return price.value;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Fetches the latest prices for Bitcoin, Ethereum, and Solana in USD from the DeFi API.
|
|
528
|
+
* @returns {Promise<Prices>} The latest prices for Bitcoin, Ethereum, and Solana in USD.
|
|
529
|
+
*/
|
|
530
|
+
async fetchPrices() {
|
|
531
|
+
const prices = await this.request(
|
|
532
|
+
"defi/multi_price",
|
|
533
|
+
{ list_address: [SOL_ADDRESS, ETH_ADDRESS, BTC_ADDRESS].join(",") },
|
|
534
|
+
{
|
|
535
|
+
chain: "solana",
|
|
536
|
+
expires: "5m"
|
|
537
|
+
}
|
|
538
|
+
);
|
|
539
|
+
return {
|
|
540
|
+
bitcoin: { usd: prices[BTC_ADDRESS].value.toString() },
|
|
541
|
+
ethereum: { usd: prices[ETH_ADDRESS].value.toString() },
|
|
542
|
+
solana: { usd: prices[SOL_ADDRESS].value.toString() }
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Fetches token overview for a specific address.
|
|
547
|
+
*
|
|
548
|
+
* @param {string} address The address of the token for which overview is to be fetched.
|
|
549
|
+
* @param {BirdeyeRequestOptions} [options] Additional options for the Birdeye request.
|
|
550
|
+
* @param {boolean} [forceRefresh=false] Flag to force refresh the data.
|
|
551
|
+
* @returns {Promise<TokenOverview>} Promise that resolves to the token overview.
|
|
552
|
+
*/
|
|
553
|
+
async fetchTokenOverview(address, options, forceRefresh = false) {
|
|
554
|
+
const token = await this.request(
|
|
555
|
+
"defi/token_overview",
|
|
556
|
+
{ address },
|
|
557
|
+
options,
|
|
558
|
+
forceRefresh
|
|
559
|
+
);
|
|
560
|
+
return token;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* Fetches token security data from the API for a given address.
|
|
564
|
+
* @param {string} address - The address of the token for which to fetch security data.
|
|
565
|
+
* @param {BirdeyeRequestOptions} [options] - Optional request options.
|
|
566
|
+
* @returns {Promise<TokenSecurityData>} A promise that resolves with the token security data.
|
|
567
|
+
*/
|
|
568
|
+
async fetchTokenSecurity(address, options) {
|
|
569
|
+
const security = await this.request(
|
|
570
|
+
"defi/token_security",
|
|
571
|
+
{ address },
|
|
572
|
+
options
|
|
573
|
+
);
|
|
574
|
+
return security;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Fetches token trade data for a specific address.
|
|
578
|
+
* @param {string} address - The address of the token.
|
|
579
|
+
* @param {BirdeyeRequestOptions} [options] - Optional request options.
|
|
580
|
+
* @returns {Promise<TokenTradeData>} - A promise that resolves with the token trade data.
|
|
581
|
+
*/
|
|
582
|
+
async fetchTokenTradeData(address, options) {
|
|
583
|
+
const tradeData = await this.request(
|
|
584
|
+
"defi/v3/token/trade-data/single",
|
|
585
|
+
{ address },
|
|
586
|
+
options
|
|
587
|
+
);
|
|
588
|
+
return tradeData;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Fetches the wallet token list for a given address.
|
|
592
|
+
*
|
|
593
|
+
* @param {string} address - The address of the wallet to fetch the token list for.
|
|
594
|
+
* @param {BirdeyeRequestOptions} [options] - Additional options for the request.
|
|
595
|
+
* @returns {Promise<WalletTokenList>} The wallet token list for the specified address.
|
|
596
|
+
*/
|
|
597
|
+
async fetchWalletTokenList(address, options) {
|
|
598
|
+
const tokenList = await this.request(
|
|
599
|
+
"v1/wallet/token_list",
|
|
600
|
+
{ wallet: address },
|
|
601
|
+
options
|
|
602
|
+
);
|
|
603
|
+
return tokenList;
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
* Asynchronously fetches the portfolio value for a given address.
|
|
607
|
+
*
|
|
608
|
+
* @param {string} address - The address for which to fetch the portfolio value.
|
|
609
|
+
* @param {BirdeyeRequestOptions} [options] - The optional request options.
|
|
610
|
+
* @returns {Promise<WalletPortfolio>} - A promise that resolves to the wallet portfolio object containing total USD, total SOL, and portfolio items.
|
|
611
|
+
* @throws {Error} - If an error occurs while fetching the portfolio value.
|
|
612
|
+
*/
|
|
613
|
+
async fetchPortfolioValue(address, options) {
|
|
614
|
+
try {
|
|
615
|
+
const portfolio = {
|
|
616
|
+
totalUsd: "0",
|
|
617
|
+
totalSol: "0",
|
|
618
|
+
items: []
|
|
619
|
+
};
|
|
620
|
+
const tokenList = await this.fetchWalletTokenList(address, options);
|
|
621
|
+
const totalUsd = new BigNumber(tokenList.totalUsd.toString());
|
|
622
|
+
const solPriceInUSD = new BigNumber(await this.fetchPrice(SOL_ADDRESS));
|
|
623
|
+
const items = tokenList.items.map((item) => ({
|
|
624
|
+
address: item.address,
|
|
625
|
+
name: item.name || "Unknown",
|
|
626
|
+
symbol: item.symbol || "Unknown",
|
|
627
|
+
decimals: item.decimals,
|
|
628
|
+
valueSol: new BigNumber(item.valueUsd || 0).div(solPriceInUSD).toFixed(6),
|
|
629
|
+
priceUsd: item.priceUsd?.toString() || "0",
|
|
630
|
+
valueUsd: item.valueUsd?.toString() || "0",
|
|
631
|
+
uiAmount: item.uiAmount?.toString() || "0",
|
|
632
|
+
balance: item.balance?.toString() || "0"
|
|
633
|
+
}));
|
|
634
|
+
const totalSol = totalUsd.div(solPriceInUSD);
|
|
635
|
+
portfolio.totalUsd = totalUsd.toString();
|
|
636
|
+
portfolio.totalSol = totalSol.toFixed(6);
|
|
637
|
+
portfolio.items = items.sort(
|
|
638
|
+
(a, b) => new BigNumber(b.valueUsd).minus(new BigNumber(a.valueUsd)).toNumber()
|
|
639
|
+
);
|
|
640
|
+
return portfolio;
|
|
641
|
+
} catch (error) {
|
|
642
|
+
console.error("Error fetching portfolio:", error);
|
|
643
|
+
throw error;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const units = {
|
|
648
|
+
ms: 1,
|
|
649
|
+
s: 1e3,
|
|
650
|
+
m: 60 * 1e3,
|
|
651
|
+
h: 60 * 60 * 1e3,
|
|
652
|
+
d: 24 * 60 * 60 * 1e3
|
|
653
|
+
};
|
|
654
|
+
function parseTimeToMs(timeStr) {
|
|
655
|
+
const match = timeStr.match(/^(\d+)([a-z]+)$/i);
|
|
656
|
+
if (!match) return 0;
|
|
657
|
+
const [_, value, unit] = match;
|
|
658
|
+
return units[unit.toLowerCase()] * Number.parseInt(value, 10);
|
|
659
|
+
}
|
|
660
|
+
function _parseExpires(expires) {
|
|
661
|
+
return typeof expires === "string" ? parseTimeToMs(expires) : expires;
|
|
662
|
+
}
|
|
663
|
+
export {
|
|
664
|
+
BirdeyeClient,
|
|
665
|
+
CoingeckoClient,
|
|
666
|
+
DexscreenerClient,
|
|
667
|
+
HeliusClient,
|
|
668
|
+
http
|
|
669
|
+
};
|
|
670
|
+
//# sourceMappingURL=clients.js.map
|