@fileverse-dev/formulajs 4.4.11-mod-68-patch-7 → 4.4.11-mod-71
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/lib/browser/formula.js +333 -429
- package/lib/browser/formula.min.js +2 -2
- package/lib/browser/formula.min.js.map +1 -1
- package/lib/cjs/index.cjs +104 -245
- package/lib/esm/crypto-constants.mjs +2 -2
- package/lib/esm/index.mjs +104 -245
- package/package.json +1 -1
package/lib/esm/index.mjs
CHANGED
|
@@ -13142,131 +13142,15 @@ const SERVICES_API_KEY = {
|
|
|
13142
13142
|
Defillama: 'Defillama'
|
|
13143
13143
|
};
|
|
13144
13144
|
|
|
13145
|
-
// Proxy map configuration
|
|
13146
|
-
const PROXY_MAP = {
|
|
13147
|
-
Etherscan: {
|
|
13148
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13149
|
-
removeParams: ['apikey']
|
|
13150
|
-
},
|
|
13151
|
-
Basescan: {
|
|
13152
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13153
|
-
removeParams: ['apikey']
|
|
13154
|
-
},
|
|
13155
|
-
Gnosisscan: {
|
|
13156
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13157
|
-
removeParams: ['apikey']
|
|
13158
|
-
},
|
|
13159
|
-
Coingecko: {
|
|
13160
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13161
|
-
removeParams: ['apikey']
|
|
13162
|
-
},
|
|
13163
|
-
Firefly: {
|
|
13164
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13165
|
-
removeParams: ['apikey']
|
|
13166
|
-
},
|
|
13167
|
-
Neynar: {
|
|
13168
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13169
|
-
removeParams: ['api_key']
|
|
13170
|
-
},
|
|
13171
|
-
Safe: {
|
|
13172
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13173
|
-
removeParams: ['api_key']
|
|
13174
|
-
},
|
|
13175
|
-
Defillama: {
|
|
13176
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13177
|
-
removeParams: ['api_key']
|
|
13178
|
-
},
|
|
13179
|
-
GnosisPay: {
|
|
13180
|
-
url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
|
|
13181
|
-
removeParams: ['api_key']
|
|
13182
|
-
},
|
|
13183
|
-
// Add more services as needed. It can be direct url instead of ENV variable
|
|
13184
|
-
// ANOTHER_SERVICE: "https://another-proxy-url.com"
|
|
13185
|
-
};
|
|
13186
|
-
|
|
13187
|
-
/**
|
|
13188
|
-
* Removes specified parameters from a URL
|
|
13189
|
-
* @param {string} url - The original URL
|
|
13190
|
-
* @param {string[]} paramsToRemove - Array of parameter names to remove
|
|
13191
|
-
* @returns {string} URL with specified parameters removed
|
|
13192
|
-
*/
|
|
13193
|
-
function removeUrlParams(url, paramsToRemove) {
|
|
13194
|
-
if (!paramsToRemove || paramsToRemove.length === 0) {
|
|
13195
|
-
return url;
|
|
13196
|
-
}
|
|
13197
|
-
|
|
13198
|
-
const urlObj = new URL(url);
|
|
13199
|
-
|
|
13200
|
-
paramsToRemove.forEach(param => {
|
|
13201
|
-
if (urlObj.searchParams.has(param)) {
|
|
13202
|
-
urlObj.searchParams.delete(param);
|
|
13203
|
-
}
|
|
13204
|
-
});
|
|
13205
|
-
|
|
13206
|
-
return urlObj.toString();
|
|
13207
|
-
}
|
|
13208
|
-
|
|
13209
|
-
/**
|
|
13210
|
-
* Handles URL routing through proxy or direct API calls
|
|
13211
|
-
* @param {string} url - The original API URL
|
|
13212
|
-
* @param {string} serviceName - The name of the service (e.g., 'EOA')
|
|
13213
|
-
* @param {string} headers - The name of the service (e.g., 'EOA')
|
|
13214
|
-
* @returns {Object} Object containing URL and HEADERS for the fetch request
|
|
13215
|
-
*/
|
|
13216
|
-
function getUrlAndHeaders({ url, serviceName, headers = {} }) {
|
|
13217
|
-
console.log('getUrlAndHeaders new modified function from formulajs', url, serviceName);
|
|
13218
|
-
// Check if proxy is enabled in localStorage
|
|
13219
|
-
const apiKeyLS = window.localStorage.getItem(SERVICES_API_KEY[serviceName]);
|
|
13220
|
-
const isProxyModeEnabledValue = apiKeyLS === 'DEFAULT_PROXY_MODE';
|
|
13221
|
-
|
|
13222
|
-
// Check if proxy URL exists for this service
|
|
13223
|
-
const proxyConfig = PROXY_MAP[serviceName];
|
|
13224
|
-
|
|
13225
|
-
// If proxy mode is enabled AND proxy URL exists for this service
|
|
13226
|
-
if (isProxyModeEnabledValue && proxyConfig && serviceName && SERVICES_API_KEY[serviceName]) {
|
|
13227
|
-
console.log('isProxyModeEnabledValue', isProxyModeEnabledValue);
|
|
13228
|
-
// Remove specified parameters from the target URL
|
|
13229
|
-
const cleanedUrl = removeUrlParams(url, proxyConfig.removeParams);
|
|
13230
|
-
|
|
13231
|
-
return {
|
|
13232
|
-
URL: proxyConfig.url,
|
|
13233
|
-
HEADERS: {
|
|
13234
|
-
'target-url': cleanedUrl,
|
|
13235
|
-
method: 'GET',
|
|
13236
|
-
'Content-Type': 'application/json'
|
|
13237
|
-
}
|
|
13238
|
-
};
|
|
13239
|
-
}
|
|
13240
|
-
|
|
13241
|
-
|
|
13242
|
-
return {
|
|
13243
|
-
URL: url,
|
|
13244
|
-
HEADERS: {
|
|
13245
|
-
...headers,
|
|
13246
|
-
method: 'GET',
|
|
13247
|
-
'Content-Type': 'application/json'
|
|
13248
|
-
}
|
|
13249
|
-
};
|
|
13250
|
-
}
|
|
13251
|
-
|
|
13252
13145
|
const fromTimeStampToBlock = async (timestamp, chain, apiKey) => {
|
|
13253
|
-
|
|
13254
|
-
|
|
13255
|
-
|
|
13256
|
-
|
|
13257
|
-
|
|
13258
|
-
|
|
13259
|
-
const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url, serviceName: 'Etherscan', headers: {} });
|
|
13260
|
-
console.log('finalUrl', finalUrl, HEADERS);
|
|
13261
|
-
const res = await fetch(finalUrl, {
|
|
13262
|
-
method: 'GET',
|
|
13263
|
-
headers: HEADERS,
|
|
13264
|
-
});
|
|
13265
|
-
console.log('res', res, finalUrl, HEADERS);
|
|
13266
|
-
const json = await res.json();
|
|
13267
|
-
return parseInt(json.result);
|
|
13146
|
+
if(!timestamp || !chain || !apiKey) return
|
|
13147
|
+
const chainId = CHAIN_ID_MAP[chain];
|
|
13148
|
+
const url = `https://api.etherscan.io/v2/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before&apikey=${apiKey}&chainId=${chainId}`;
|
|
13149
|
+
const res = await fetch(url);
|
|
13150
|
+
const json = await res.json();
|
|
13151
|
+
return parseInt(json.result);
|
|
13268
13152
|
|
|
13269
|
-
};
|
|
13153
|
+
};
|
|
13270
13154
|
|
|
13271
13155
|
var fromTimestampToBlock = {
|
|
13272
13156
|
fromTimeStampToBlock
|
|
@@ -13403,13 +13287,14 @@ async function handleScanRequest({
|
|
|
13403
13287
|
'all-txns': 'txlist',
|
|
13404
13288
|
'token-txns': 'tokentx',
|
|
13405
13289
|
'nft-txns': 'tokennfttx',
|
|
13406
|
-
gas: '
|
|
13290
|
+
'gas': 'gasoracle'
|
|
13407
13291
|
};
|
|
13408
13292
|
|
|
13409
13293
|
const action = ACTION_MAP[type];
|
|
13410
13294
|
if (!action) throw new ValidationError(`Invalid type: ${type}`)
|
|
13411
13295
|
|
|
13412
|
-
|
|
13296
|
+
const module = action === 'gasoracle' ? 'gastracker' : 'account';
|
|
13297
|
+
let url = `${baseUrl}?chainid=${chainId}&module=${module}&action=${action}&apikey=${apiKey}`;
|
|
13413
13298
|
|
|
13414
13299
|
if (['all-txns', 'token-txns', 'nft-txns'].includes(type)) {
|
|
13415
13300
|
url += `&address=${address}&startblock=0&endblock=99999999&sort=asc`;
|
|
@@ -13423,11 +13308,7 @@ async function handleScanRequest({
|
|
|
13423
13308
|
}
|
|
13424
13309
|
url += `&page=${page}&offset=${offset}`;
|
|
13425
13310
|
}
|
|
13426
|
-
const
|
|
13427
|
-
const res = await fetch(finalUrl, {
|
|
13428
|
-
method: 'GET',
|
|
13429
|
-
headers: HEADERS,
|
|
13430
|
-
});
|
|
13311
|
+
const res = await fetch(url);
|
|
13431
13312
|
if (!res.ok) {
|
|
13432
13313
|
throw new NetworkError(apiInfo.apiKeyName, res.status)
|
|
13433
13314
|
}
|
|
@@ -13442,23 +13323,18 @@ async function handleScanRequest({
|
|
|
13442
13323
|
throw new RateLimitError(apiInfo.apiKeyName)
|
|
13443
13324
|
}
|
|
13444
13325
|
|
|
13445
|
-
return json.result
|
|
13326
|
+
return type === 'gas' && !Array.isArray(json.result) ? [json.result] : json.result
|
|
13446
13327
|
}
|
|
13447
13328
|
|
|
13448
13329
|
const fromUsernameToFid = async (username, apiKey) => {
|
|
13449
|
-
if
|
|
13330
|
+
if(!username) return null
|
|
13450
13331
|
const url = `https://api.neynar.com/v2/farcaster/user/search/?q=${username}&limit=5`;
|
|
13451
|
-
const
|
|
13452
|
-
|
|
13332
|
+
const res = await fetch(url, {
|
|
13333
|
+
headers: {
|
|
13453
13334
|
'x-api-key': apiKey,
|
|
13454
13335
|
'x-neynar-experimental': 'false'
|
|
13455
13336
|
}
|
|
13456
13337
|
});
|
|
13457
|
-
|
|
13458
|
-
const res = await fetch(finalUrl, {
|
|
13459
|
-
method: 'GET',
|
|
13460
|
-
headers: HEADERS,
|
|
13461
|
-
});
|
|
13462
13338
|
const json = await res.json();
|
|
13463
13339
|
const users = json.result ? json.result.users : [];
|
|
13464
13340
|
const user = users.find(user => user.username === username);
|
|
@@ -17471,7 +17347,7 @@ const farcasterSchema = objectType({
|
|
|
17471
17347
|
contentType: enumType(['posts', 'replies', 'channels']),
|
|
17472
17348
|
identifier: stringType().nonempty(),
|
|
17473
17349
|
start: numberType().int().nonnegative().default(0),
|
|
17474
|
-
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17350
|
+
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17475
17351
|
});
|
|
17476
17352
|
|
|
17477
17353
|
const lensSchema = objectType({
|
|
@@ -17479,7 +17355,7 @@ const lensSchema = objectType({
|
|
|
17479
17355
|
contentType: enumType(['posts', 'replies']),
|
|
17480
17356
|
identifier: stringType().nonempty(),
|
|
17481
17357
|
start: numberType().int().nonnegative().default(0),
|
|
17482
|
-
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17358
|
+
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17483
17359
|
});
|
|
17484
17360
|
|
|
17485
17361
|
const fireflyParamsSchema = discriminatedUnionType('platform', [
|
|
@@ -17502,31 +17378,33 @@ const lensParamsSchema = objectType({
|
|
|
17502
17378
|
contentType: enumType(['posts', 'replies']),
|
|
17503
17379
|
identifier: stringType().nonempty(),
|
|
17504
17380
|
start: numberType().int().nonnegative().default(0),
|
|
17505
|
-
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17381
|
+
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17506
17382
|
});
|
|
17507
17383
|
|
|
17508
17384
|
const farcasterParamsSchema = objectType({
|
|
17509
17385
|
contentType: enumType(['posts', 'replies', 'channels']),
|
|
17510
17386
|
identifier: stringType().nonempty(),
|
|
17511
17387
|
start: numberType().int().nonnegative().default(0),
|
|
17512
|
-
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17388
|
+
end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17513
17389
|
});
|
|
17514
17390
|
|
|
17515
17391
|
const dateStringToTimestamp = (val) => {
|
|
17516
|
-
const [
|
|
17517
|
-
|
|
17392
|
+
const [dd, mm, yyyy] = val.split('/');
|
|
17393
|
+
const date = new Date(`${yyyy}-${mm.padStart(2, '0')}-${dd.padStart(2, '0')}`);
|
|
17394
|
+
const timestamp = date.getTime();
|
|
17395
|
+
return isNaN(timestamp) ? NaN : Math.floor(timestamp / 1000);
|
|
17518
17396
|
};
|
|
17519
17397
|
|
|
17520
17398
|
/**
|
|
17521
|
-
* Accepts either a UNIX
|
|
17399
|
+
* Accepts either a UNIX timestamp number or a DD/MM/YYYY string,
|
|
17522
17400
|
* and always returns a nonnegative integer timestamp.
|
|
17523
17401
|
*/
|
|
17524
17402
|
const dateOrTimestamp = preprocessType(
|
|
17525
17403
|
(val) =>
|
|
17526
|
-
typeof val === 'string' && /^\d{2}\/\d{2}\/\d{4}$/.test(val)
|
|
17404
|
+
typeof val === 'string' && /^\d{1,2}\/\d{1,2}\/\d{4}$/.test(val)
|
|
17527
17405
|
? dateStringToTimestamp(val)
|
|
17528
17406
|
: val,
|
|
17529
|
-
numberType().int().nonnegative()
|
|
17407
|
+
numberType({ invalid_type_error: 'Date must be a valid DD/MM/YYYY or timestamp' }).int('Date must be an integer timestamp').nonnegative('Date must be a nonnegative timestamp').refine((n) => !isNaN(n), { message: 'Invalid date format or value: expected DD/MM/YYYY' })
|
|
17530
17408
|
);
|
|
17531
17409
|
|
|
17532
17410
|
const blockscoutParamsSchema = objectType({
|
|
@@ -17536,7 +17414,7 @@ const blockscoutParamsSchema = objectType({
|
|
|
17536
17414
|
startTimestamp: dateOrTimestamp.optional(),
|
|
17537
17415
|
endTimestamp: dateOrTimestamp.optional(),
|
|
17538
17416
|
page: numberType().int().nonnegative().default(1),
|
|
17539
|
-
offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17417
|
+
offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"offset" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17540
17418
|
});
|
|
17541
17419
|
|
|
17542
17420
|
const gasSchema$1 = objectType({
|
|
@@ -17544,7 +17422,7 @@ const gasSchema$1 = objectType({
|
|
|
17544
17422
|
startDate: dateOrTimestamp.optional(),
|
|
17545
17423
|
endDate: dateOrTimestamp.optional(),
|
|
17546
17424
|
page: numberType().int().nonnegative().default(1),
|
|
17547
|
-
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17425
|
+
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17548
17426
|
});
|
|
17549
17427
|
|
|
17550
17428
|
const txnSchema$1 = objectType({
|
|
@@ -17553,7 +17431,7 @@ const txnSchema$1 = objectType({
|
|
|
17553
17431
|
startDate: dateOrTimestamp.optional(),
|
|
17554
17432
|
endDate: dateOrTimestamp.optional(),
|
|
17555
17433
|
page: numberType().int().nonnegative().default(1),
|
|
17556
|
-
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17434
|
+
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17557
17435
|
});
|
|
17558
17436
|
|
|
17559
17437
|
const baseParamsSchema = discriminatedUnionType('type', [gasSchema$1, txnSchema$1]);
|
|
@@ -17563,7 +17441,7 @@ const gasSchema = objectType({
|
|
|
17563
17441
|
startDate: dateOrTimestamp.optional(),
|
|
17564
17442
|
endDate: dateOrTimestamp.optional(),
|
|
17565
17443
|
page: numberType().int().nonnegative().default(1),
|
|
17566
|
-
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17444
|
+
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17567
17445
|
});
|
|
17568
17446
|
|
|
17569
17447
|
const txnSchema = objectType({
|
|
@@ -17573,11 +17451,21 @@ const txnSchema = objectType({
|
|
|
17573
17451
|
endDate: dateOrTimestamp.optional(),
|
|
17574
17452
|
chain: enumType(['ethereum','base','gnosis']),
|
|
17575
17453
|
page: numberType().int().nonnegative().default(1),
|
|
17576
|
-
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17454
|
+
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17577
17455
|
});
|
|
17578
17456
|
|
|
17579
17457
|
const etherscanParamsSchema = discriminatedUnionType('type', [gasSchema, txnSchema]);
|
|
17580
17458
|
|
|
17459
|
+
const allowedValues = ['1h', '24h', '7d'];
|
|
17460
|
+
const param2Schema = stringType()
|
|
17461
|
+
.refine((val) => {
|
|
17462
|
+
const tokens = val.split(',').map((t) => t.trim().toLowerCase());
|
|
17463
|
+
return tokens.some((token) =>
|
|
17464
|
+
allowedValues.some((allowed) => token.includes(allowed))
|
|
17465
|
+
);
|
|
17466
|
+
}, {
|
|
17467
|
+
message: "param2 must contain at least one of: '1h', '24h', '7d'",
|
|
17468
|
+
}).optional();
|
|
17581
17469
|
const priceSchema = objectType({
|
|
17582
17470
|
category: literalType('price'),
|
|
17583
17471
|
param1: stringType().nonempty(),
|
|
@@ -17587,13 +17475,13 @@ const marketEcosystems = ['all','base','meme','aiagents','bitcoin','ethereum','h
|
|
|
17587
17475
|
const marketSchema = objectType({
|
|
17588
17476
|
category: literalType('market'),
|
|
17589
17477
|
param1: enumType(marketEcosystems),
|
|
17590
|
-
param2:
|
|
17478
|
+
param2: param2Schema,
|
|
17591
17479
|
});
|
|
17592
17480
|
const stablecoinsTypes = ['all','yield-bearing-stablecoins','crypto-backed-stablecoin'];
|
|
17593
17481
|
const stablecoinsSchema = objectType({
|
|
17594
17482
|
category: literalType('stablecoins'),
|
|
17595
17483
|
param1: enumType(stablecoinsTypes),
|
|
17596
|
-
param2:
|
|
17484
|
+
param2: param2Schema,
|
|
17597
17485
|
});
|
|
17598
17486
|
const derivativesSchema = objectType({
|
|
17599
17487
|
category: literalType('derivatives'),
|
|
@@ -17621,7 +17509,7 @@ const baseSchema = objectType({
|
|
|
17621
17509
|
startTime: dateOrTimestamp.optional(),
|
|
17622
17510
|
endTime: dateOrTimestamp.optional(),
|
|
17623
17511
|
page: numberType().int().nonnegative().default(1),
|
|
17624
|
-
offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17512
|
+
offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"offset" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17625
17513
|
});
|
|
17626
17514
|
|
|
17627
17515
|
const eoaParamsSchema = preprocessType(
|
|
@@ -17650,7 +17538,7 @@ const safeParamsSchema = objectType({
|
|
|
17650
17538
|
address: stringType().nonempty(),
|
|
17651
17539
|
utility: literalType('txns'),
|
|
17652
17540
|
chain: enumType(['ethereum','gnosis']),
|
|
17653
|
-
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
|
|
17541
|
+
limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
|
|
17654
17542
|
offset: numberType().int().nonnegative().default(0),
|
|
17655
17543
|
});
|
|
17656
17544
|
|
|
@@ -17686,9 +17574,9 @@ const aaveParamsSchema = objectType({
|
|
|
17686
17574
|
|
|
17687
17575
|
async function FIREFLY() {
|
|
17688
17576
|
try {
|
|
17689
|
-
|
|
17577
|
+
const [platform, contentType, identifier, start = 0, end = 10] = argsToArray(arguments);
|
|
17690
17578
|
|
|
17691
|
-
|
|
17579
|
+
validateParams(fireflyParamsSchema, {
|
|
17692
17580
|
platform,
|
|
17693
17581
|
contentType,
|
|
17694
17582
|
identifier,
|
|
@@ -17710,14 +17598,12 @@ async function FIREFLY() {
|
|
|
17710
17598
|
.filter(Boolean)
|
|
17711
17599
|
.join(',')
|
|
17712
17600
|
);
|
|
17713
|
-
|
|
17714
|
-
|
|
17715
|
-
|
|
17601
|
+
url.searchParams.set('type', fireFlyPlaformType[platform][contentType]);
|
|
17602
|
+
url.searchParams.set('start', String(start));
|
|
17603
|
+
url.searchParams.set('end', String(end));
|
|
17716
17604
|
|
|
17717
|
-
const
|
|
17718
|
-
|
|
17719
|
-
method: 'GET',
|
|
17720
|
-
headers: HEADERS,
|
|
17605
|
+
const response = await fetch(url.toString(), {
|
|
17606
|
+
headers: { 'x-api-key': apiKey }
|
|
17721
17607
|
});
|
|
17722
17608
|
if (!response.ok) {
|
|
17723
17609
|
throw new NetworkError(SERVICES_API_KEY.Firefly, response.status)
|
|
@@ -17775,18 +17661,15 @@ async function LENS() {
|
|
|
17775
17661
|
.join(',')
|
|
17776
17662
|
);
|
|
17777
17663
|
const typeMap = {
|
|
17778
|
-
posts:
|
|
17664
|
+
posts: 'lensid',
|
|
17779
17665
|
replies: 'lenspostid',
|
|
17780
17666
|
};
|
|
17781
17667
|
url.searchParams.set('type', typeMap[contentType]);
|
|
17782
17668
|
url.searchParams.set('start', String(start));
|
|
17783
|
-
url.searchParams.set('end',
|
|
17669
|
+
url.searchParams.set('end', String(end));
|
|
17784
17670
|
|
|
17785
|
-
const
|
|
17786
|
-
|
|
17787
|
-
const response = await fetch(finalUrl, {
|
|
17788
|
-
method: 'GET',
|
|
17789
|
-
headers: HEADERS,
|
|
17671
|
+
const response = await fetch(url.toString(), {
|
|
17672
|
+
headers: { 'x-api-key': apiKey },
|
|
17790
17673
|
});
|
|
17791
17674
|
if (!response.ok) {
|
|
17792
17675
|
throw new NetworkError(SERVICES_API_KEY.Firefly, response.status)
|
|
@@ -17813,7 +17696,7 @@ async function FARCASTER() {
|
|
|
17813
17696
|
try {
|
|
17814
17697
|
const [contentType, identifier, start = 0, end = 10] =
|
|
17815
17698
|
argsToArray(arguments);
|
|
17816
|
-
|
|
17699
|
+
validateParams(farcasterParamsSchema, {
|
|
17817
17700
|
contentType,
|
|
17818
17701
|
identifier,
|
|
17819
17702
|
start,
|
|
@@ -17839,19 +17722,16 @@ async function FARCASTER() {
|
|
|
17839
17722
|
.join(',')
|
|
17840
17723
|
);
|
|
17841
17724
|
const typeMap = {
|
|
17842
|
-
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17725
|
+
posts: 'farcasterid',
|
|
17726
|
+
replies: 'farcasterpostid',
|
|
17727
|
+
channels: 'farcasterchannels',
|
|
17728
|
+
};
|
|
17846
17729
|
url.searchParams.set('type', typeMap[contentType]);
|
|
17847
17730
|
url.searchParams.set('start', String(start));
|
|
17848
|
-
url.searchParams.set('end',
|
|
17849
|
-
|
|
17850
|
-
const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url: url.toString(), serviceName: 'Firefly', headers });
|
|
17731
|
+
url.searchParams.set('end', String(end));
|
|
17851
17732
|
|
|
17852
|
-
const response = await fetch(
|
|
17853
|
-
|
|
17854
|
-
headers: HEADERS,
|
|
17733
|
+
const response = await fetch(url.toString(), {
|
|
17734
|
+
headers: { 'x-api-key': apiKey },
|
|
17855
17735
|
});
|
|
17856
17736
|
if (!response.ok) {
|
|
17857
17737
|
throw new NetworkError(
|
|
@@ -17960,12 +17840,12 @@ async function BLOCKSCOUT() {
|
|
|
17960
17840
|
}
|
|
17961
17841
|
|
|
17962
17842
|
async function BASE() {
|
|
17963
|
-
|
|
17843
|
+
try {
|
|
17964
17844
|
const [type, address, startDate, endDate, page, limit] = argsToArray(arguments);
|
|
17965
|
-
|
|
17845
|
+
validateParams(baseParamsSchema, { type, address, startDate, endDate, page, limit });
|
|
17966
17846
|
const API_KEY = window.localStorage.getItem(SERVICES_API_KEY.Basescan);
|
|
17967
17847
|
if (!API_KEY) throw new MissingApiKeyError(SERVICES_API_KEY.Basescan)
|
|
17968
|
-
|
|
17848
|
+
|
|
17969
17849
|
return await handleScanRequest({
|
|
17970
17850
|
type,
|
|
17971
17851
|
address,
|
|
@@ -17978,9 +17858,9 @@ async function BASE() {
|
|
|
17978
17858
|
chainId: CHAIN_ID_MAP.base,
|
|
17979
17859
|
network: 'base'
|
|
17980
17860
|
})
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17861
|
+
} catch (error) {
|
|
17862
|
+
return errorMessageHandler(error, 'BASE')
|
|
17863
|
+
}
|
|
17984
17864
|
}
|
|
17985
17865
|
async function GNOSIS() {
|
|
17986
17866
|
try {
|
|
@@ -18021,9 +17901,9 @@ async function GNOSIS() {
|
|
|
18021
17901
|
|
|
18022
17902
|
async function NEYNAR() {
|
|
18023
17903
|
try {
|
|
18024
|
-
|
|
18025
|
-
|
|
18026
|
-
|
|
17904
|
+
const neynarParamsSchema = objectType({
|
|
17905
|
+
username: stringType().nonempty()
|
|
17906
|
+
});
|
|
18027
17907
|
|
|
18028
17908
|
const [username] = argsToArray(arguments);
|
|
18029
17909
|
|
|
@@ -18037,19 +17917,12 @@ async function NEYNAR() {
|
|
|
18037
17917
|
|
|
18038
17918
|
const url = `https://api.neynar.com/v2/farcaster/followers?fid=${fid}`;
|
|
18039
17919
|
|
|
18040
|
-
const
|
|
18041
|
-
|
|
18042
|
-
|
|
18043
|
-
|
|
18044
|
-
'x-neynar-experimental': 'false'
|
|
18045
|
-
}
|
|
17920
|
+
const response = await fetch(url, {
|
|
17921
|
+
headers: {
|
|
17922
|
+
'x-api-key': apiKey,
|
|
17923
|
+
'x-neynar-experimental': 'false',
|
|
18046
17924
|
}
|
|
18047
17925
|
});
|
|
18048
|
-
|
|
18049
|
-
const response = await fetch(finalUrl, {
|
|
18050
|
-
method: 'GET',
|
|
18051
|
-
headers: HEADERS,
|
|
18052
|
-
});
|
|
18053
17926
|
if (!response.ok) {
|
|
18054
17927
|
throw new NetworkError(SERVICES_API_KEY.Neynar, response.status)
|
|
18055
17928
|
}
|
|
@@ -18183,20 +18056,20 @@ async function COINGECKO() {
|
|
|
18183
18056
|
break
|
|
18184
18057
|
}
|
|
18185
18058
|
case 'market': {
|
|
18186
|
-
const map = { all:
|
|
18059
|
+
const map = { all:'', base:'base-ecosystem', meme:'meme-token', aiagents:'ai-agents', bitcoin:'bitcoin-ecosystem', ethereum:'ethereum-ecosystem', hyperliquid:'hyperliquid-ecosystem', pump:'pump-ecosystem', solana:'solana-ecosystem' };
|
|
18187
18060
|
const _category = map[param1] || '';
|
|
18188
18061
|
const trend = param2 ? `&price_change_percentage=${param2}` : '';
|
|
18189
|
-
url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&include_tokens=top&page=1&per_page=100${_category
|
|
18062
|
+
url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&include_tokens=top&page=1&per_page=100${_category?`&category=${_category}`:''}${trend}`;
|
|
18190
18063
|
break
|
|
18191
18064
|
}
|
|
18192
18065
|
case 'stablecoins': {
|
|
18193
|
-
const _category = param1
|
|
18066
|
+
const _category = param1==='all'? 'stablecoins' : param1;
|
|
18194
18067
|
const trend = param2 ? `&price_change_percentage=${param2}` : '';
|
|
18195
18068
|
url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category=${_category}&order=market_cap_desc&page=1&per_page=100${trend}`;
|
|
18196
18069
|
break
|
|
18197
18070
|
}
|
|
18198
18071
|
case 'derivatives': {
|
|
18199
|
-
url = (!param1 || param1
|
|
18072
|
+
url = (!param1 || param1==='all')
|
|
18200
18073
|
? 'https://api.coingecko.com/api/v3/derivatives'
|
|
18201
18074
|
: `https://api.coingecko.com/api/v3/derivatives/exchanges/${param1}?include_tickers=all`;
|
|
18202
18075
|
break
|
|
@@ -18211,17 +18084,17 @@ async function COINGECKO() {
|
|
|
18211
18084
|
throw new NetworkError(SERVICES_API_KEY.Coingecko, res.status)
|
|
18212
18085
|
}
|
|
18213
18086
|
|
|
18214
|
-
if (category
|
|
18087
|
+
if (category==='price') {
|
|
18215
18088
|
const out = {};
|
|
18216
18089
|
for (const [token, prices] of Object.entries(json))
|
|
18217
|
-
for (const [cur,
|
|
18218
|
-
out[`${token.charAt(0).toUpperCase()
|
|
18090
|
+
for (const [cur,val] of Object.entries(prices))
|
|
18091
|
+
out[`${token.charAt(0).toUpperCase()+token.slice(1)}_${cur.toUpperCase()}`]=val;
|
|
18219
18092
|
return [out]
|
|
18220
18093
|
}
|
|
18221
18094
|
|
|
18222
18095
|
const data = Array.isArray(json) ? json : [json];
|
|
18223
|
-
return data.map(item
|
|
18224
|
-
const flat
|
|
18096
|
+
return data.map(item=>{
|
|
18097
|
+
const flat={};
|
|
18225
18098
|
for (const [key, value] of Object.entries(item)) {
|
|
18226
18099
|
if (typeof value !== 'object' || value === null) {
|
|
18227
18100
|
flat[key] = value;
|
|
@@ -18229,24 +18102,22 @@ async function COINGECKO() {
|
|
|
18229
18102
|
}
|
|
18230
18103
|
return flat
|
|
18231
18104
|
})
|
|
18232
|
-
} catch
|
|
18233
|
-
return errorMessageHandler(err,
|
|
18105
|
+
} catch(err) {
|
|
18106
|
+
return errorMessageHandler(err,'COINGECKO')
|
|
18234
18107
|
}
|
|
18235
18108
|
}
|
|
18236
18109
|
|
|
18237
18110
|
async function EOA() {
|
|
18238
|
-
console.log('EOA');
|
|
18239
18111
|
try {
|
|
18240
18112
|
const [addresses, category, chains, startTime, endTime, page = 1, offset = 10] =
|
|
18241
18113
|
argsToArray(arguments);
|
|
18242
18114
|
validateParams(eoaParamsSchema, { addresses, category, chains, startTime, endTime, page, offset });
|
|
18243
18115
|
|
|
18244
18116
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Etherscan);
|
|
18245
|
-
console.log('apiKey', apiKey);
|
|
18246
18117
|
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Etherscan)
|
|
18247
18118
|
|
|
18248
|
-
const INPUTS = addresses.split(',').map(s
|
|
18249
|
-
const CHAINS = chains.split(',').map(s
|
|
18119
|
+
const INPUTS = addresses.split(',').map(s=>s.trim()).filter(Boolean);
|
|
18120
|
+
const CHAINS = chains.split(',').map(s=>s.trim()).filter(Boolean);
|
|
18250
18121
|
|
|
18251
18122
|
const ADDRESS_MAP = {};
|
|
18252
18123
|
for (const inp of INPUTS) {
|
|
@@ -18260,16 +18131,10 @@ async function EOA() {
|
|
|
18260
18131
|
}
|
|
18261
18132
|
}
|
|
18262
18133
|
const ADDRS = Object.keys(ADDRESS_MAP);
|
|
18263
|
-
console.log('ADDRS', ADDRS);
|
|
18264
18134
|
const out = [];
|
|
18265
18135
|
|
|
18266
18136
|
async function fetchJSON(url) {
|
|
18267
|
-
const
|
|
18268
|
-
console.log('finalUrl', finalUrl, HEADERS);
|
|
18269
|
-
const res = await fetch(finalUrl, {
|
|
18270
|
-
method: 'GET',
|
|
18271
|
-
headers: HEADERS,
|
|
18272
|
-
});
|
|
18137
|
+
const res = await fetch(url);
|
|
18273
18138
|
if (!res.ok) throw new NetworkError(SERVICES_API_KEY.Etherscan, res.status)
|
|
18274
18139
|
const json = await res.json();
|
|
18275
18140
|
|
|
@@ -18282,38 +18147,32 @@ async function EOA() {
|
|
|
18282
18147
|
|
|
18283
18148
|
|
|
18284
18149
|
for (const chain of CHAINS) {
|
|
18285
|
-
console.log('chain', chain);
|
|
18286
18150
|
const chainId = CHAIN_ID_MAP[chain];
|
|
18287
18151
|
if (!chainId) throw new ValidationError(`Invalid chain: ${chain}`)
|
|
18288
|
-
console.log('chain', chain);
|
|
18289
|
-
|
|
18290
18152
|
|
|
18291
18153
|
if (category === 'balance') {
|
|
18292
|
-
console.log('balance');
|
|
18293
18154
|
// chunk 20
|
|
18294
|
-
for (let i
|
|
18295
|
-
const slice = ADDRS.slice(i,
|
|
18155
|
+
for (let i=0; i<ADDRS.length; i+=20) {
|
|
18156
|
+
const slice = ADDRS.slice(i,i+20).join(',');
|
|
18296
18157
|
const url =
|
|
18297
|
-
`https://api.etherscan.io/v2/api?chainid=${chainId}
|
|
18298
|
-
`&module=account&action=addresstokenbalance&address=${slice}
|
|
18158
|
+
`https://api.etherscan.io/v2/api?chainid=${chainId}`+
|
|
18159
|
+
`&module=account&action=addresstokenbalance&address=${slice}`+
|
|
18299
18160
|
`&page=${page}&offset=${offset}&apikey=${apiKey}`;
|
|
18300
18161
|
const data = await fetchJSON(url);
|
|
18301
18162
|
if (!Array.isArray(data)) return data
|
|
18302
|
-
data.forEach((item, idx) => out.push({ chain, address: ADDRS[i
|
|
18163
|
+
data.forEach((item, idx) => out.push({ chain, address: ADDRS[i+idx], name: ADDRESS_MAP[ADDRS[i+idx]], ...item }));
|
|
18303
18164
|
}
|
|
18304
18165
|
} else {
|
|
18305
18166
|
// txns
|
|
18306
|
-
console.log('startTime', startTime, 'endTime', endTime, chain, apiKey);
|
|
18307
18167
|
const sb = await fromTimestampToBlock.fromTimeStampToBlock(toTimestamp(startTime), chain, apiKey);
|
|
18308
18168
|
const eb = await fromTimestampToBlock.fromTimeStampToBlock(toTimestamp(endTime), chain, apiKey);
|
|
18309
|
-
console.log('sb', sb, 'eb', eb);
|
|
18310
18169
|
if (!sb) throw new ValidationError(`Invalid startTime: ${startTime}`)
|
|
18311
18170
|
if (!eb) throw new ValidationError(`Invalid endTime: ${endTime}`)
|
|
18312
18171
|
for (const addr of ADDRS) {
|
|
18313
18172
|
const url =
|
|
18314
|
-
`https://api.etherscan.io/v2/api?chainid=${chainId}
|
|
18315
|
-
`&module=account&action=tokentx&address=${addr}
|
|
18316
|
-
`&startblock=${sb}&endblock=${eb}
|
|
18173
|
+
`https://api.etherscan.io/v2/api?chainid=${chainId}`+
|
|
18174
|
+
`&module=account&action=tokentx&address=${addr}`+
|
|
18175
|
+
`&startblock=${sb}&endblock=${eb}`+
|
|
18317
18176
|
`&page=${page}&offset=${offset}&sort=asc&apikey=${apiKey}`;
|
|
18318
18177
|
const data = await fetchJSON(url);
|
|
18319
18178
|
if (!Array.isArray(data)) return data
|
|
@@ -18388,20 +18247,20 @@ async function DEFILLAMA() {
|
|
|
18388
18247
|
|
|
18389
18248
|
switch (category) {
|
|
18390
18249
|
case 'protocols':
|
|
18391
|
-
json = Array.isArray(json) ? json.slice(0,
|
|
18250
|
+
json = Array.isArray(json) ? json.slice(0,500) : [];
|
|
18392
18251
|
break
|
|
18393
18252
|
case 'yields':
|
|
18394
|
-
json = Array.isArray(json.data) ? json.data.slice(0,
|
|
18253
|
+
json = Array.isArray(json.data) ? json.data.slice(0,500) : [];
|
|
18395
18254
|
break
|
|
18396
18255
|
case 'dex':
|
|
18397
18256
|
case 'fees':
|
|
18398
|
-
json = Array.isArray(json.protocols) ? json.protocols.slice(0,
|
|
18257
|
+
json = Array.isArray(json.protocols) ? json.protocols.slice(0,500) : [];
|
|
18399
18258
|
break
|
|
18400
18259
|
}
|
|
18401
18260
|
|
|
18402
18261
|
return (Array.isArray(json) ? json : [json]).map(item => {
|
|
18403
18262
|
const out = {};
|
|
18404
|
-
for (const [k,
|
|
18263
|
+
for (const [k,v] of Object.entries(item)) {
|
|
18405
18264
|
if (v === null || typeof v !== 'object') out[k] = v;
|
|
18406
18265
|
}
|
|
18407
18266
|
return out
|
|
@@ -18437,7 +18296,7 @@ async function UNISWAP() {
|
|
|
18437
18296
|
// flatten nested
|
|
18438
18297
|
return json.map(item => {
|
|
18439
18298
|
const flat = {};
|
|
18440
|
-
Object.entries(item).forEach(([k,
|
|
18299
|
+
Object.entries(item).forEach(([k,v]) => {
|
|
18441
18300
|
if (v === null || typeof v !== 'object') flat[k] = v;
|
|
18442
18301
|
});
|
|
18443
18302
|
return flat
|