@fileverse-dev/formulajs 4.4.11-mod-75 → 4.4.11-mod-77
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 +985 -1051
- package/lib/browser/formula.min.js +2 -2
- package/lib/browser/formula.min.js.map +1 -1
- package/lib/cjs/index.cjs +122 -255
- package/lib/esm/index.mjs +122 -255
- package/package.json +4 -2
package/lib/esm/index.mjs
CHANGED
|
@@ -13130,7 +13130,6 @@ const UTILITY = {
|
|
|
13130
13130
|
};
|
|
13131
13131
|
const MAX_PAGE_LIMIT = 250;
|
|
13132
13132
|
|
|
13133
|
-
// if data block need API key
|
|
13134
13133
|
const SERVICES_API_KEY = {
|
|
13135
13134
|
Etherscan: 'Etherscan',
|
|
13136
13135
|
Coingecko: 'Coingecko',
|
|
@@ -13143,6 +13142,27 @@ const SERVICES_API_KEY = {
|
|
|
13143
13142
|
Defillama: 'Defillama'
|
|
13144
13143
|
};
|
|
13145
13144
|
|
|
13145
|
+
const fromTimeStampToBlock = async (timestamp, chain, apiKey) => {
|
|
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);
|
|
13152
|
+
|
|
13153
|
+
};
|
|
13154
|
+
|
|
13155
|
+
var fromTimestampToBlock = {
|
|
13156
|
+
fromTimeStampToBlock
|
|
13157
|
+
};
|
|
13158
|
+
|
|
13159
|
+
function toTimestamp(dateStr) {
|
|
13160
|
+
// Expecting format: "DD/MM/YYYY"
|
|
13161
|
+
const [day, month, year] = dateStr.split("/").map(Number);
|
|
13162
|
+
const date = new Date(year, month - 1, day);
|
|
13163
|
+
return Math.floor(date.getTime() / 1000); // Unix timestamp in seconds
|
|
13164
|
+
}
|
|
13165
|
+
|
|
13146
13166
|
class ValidationError extends Error {
|
|
13147
13167
|
constructor(message) {
|
|
13148
13168
|
super(message);
|
|
@@ -13187,139 +13207,6 @@ class InvalidApiKeyError extends Error {
|
|
|
13187
13207
|
}
|
|
13188
13208
|
}
|
|
13189
13209
|
|
|
13190
|
-
const stagingFileverseProxyUrl = "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy";
|
|
13191
|
-
const productionFileverseProxyUrl = `${process.env.NEXT_PUBLIC_PROXY_BASE_URL}/proxy`;
|
|
13192
|
-
// Proxy map configuration
|
|
13193
|
-
const PROXY_MAP = {
|
|
13194
|
-
Etherscan: {
|
|
13195
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13196
|
-
removeParams: ['apikey']
|
|
13197
|
-
},
|
|
13198
|
-
Basescan: {
|
|
13199
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13200
|
-
removeParams: ['apikey']
|
|
13201
|
-
},
|
|
13202
|
-
Gnosisscan: {
|
|
13203
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13204
|
-
removeParams: ['apikey']
|
|
13205
|
-
},
|
|
13206
|
-
Coingecko: {
|
|
13207
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13208
|
-
removeParams: ['apikey']
|
|
13209
|
-
},
|
|
13210
|
-
Firefly: {
|
|
13211
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13212
|
-
removeParams: ['apikey']
|
|
13213
|
-
},
|
|
13214
|
-
Neynar: {
|
|
13215
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13216
|
-
removeParams: ['api_key']
|
|
13217
|
-
},
|
|
13218
|
-
Safe: {
|
|
13219
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13220
|
-
removeParams: ['api_key']
|
|
13221
|
-
},
|
|
13222
|
-
Defillama: {
|
|
13223
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13224
|
-
removeParams: ['api_key']
|
|
13225
|
-
},
|
|
13226
|
-
GnosisPay: {
|
|
13227
|
-
url: productionFileverseProxyUrl || stagingFileverseProxyUrl,
|
|
13228
|
-
removeParams: ['api_key']
|
|
13229
|
-
},
|
|
13230
|
-
// Add more services as needed. It can be direct url instead of ENV variable
|
|
13231
|
-
// ANOTHER_SERVICE: "https://another-proxy-url.com"
|
|
13232
|
-
};
|
|
13233
|
-
|
|
13234
|
-
/**
|
|
13235
|
-
* Removes specified parameters from a URL
|
|
13236
|
-
* @param {string} url - The original URL
|
|
13237
|
-
* @param {string[]} paramsToRemove - Array of parameter names to remove
|
|
13238
|
-
* @returns {string} URL with specified parameters removed
|
|
13239
|
-
*/
|
|
13240
|
-
function removeUrlParams(url, paramsToRemove) {
|
|
13241
|
-
if (!paramsToRemove || paramsToRemove.length === 0) {
|
|
13242
|
-
return url;
|
|
13243
|
-
}
|
|
13244
|
-
|
|
13245
|
-
const urlObj = new URL(url);
|
|
13246
|
-
|
|
13247
|
-
paramsToRemove.forEach(param => {
|
|
13248
|
-
if (urlObj.searchParams.has(param)) {
|
|
13249
|
-
urlObj.searchParams.delete(param);
|
|
13250
|
-
}
|
|
13251
|
-
});
|
|
13252
|
-
|
|
13253
|
-
return urlObj.toString();
|
|
13254
|
-
}
|
|
13255
|
-
|
|
13256
|
-
/**
|
|
13257
|
-
* Handles URL routing through proxy or direct API calls
|
|
13258
|
-
* @param {string} url - The original API URL
|
|
13259
|
-
* @param {string} serviceName - [OPTIONAL] The name of the service (e.g., 'EOA')
|
|
13260
|
-
* @param {object} headers - [OPTIONAL] The name of the service (e.g., 'EOA')
|
|
13261
|
-
* @returns {Object} Object containing URL and HEADERS for the fetch request
|
|
13262
|
-
*/
|
|
13263
|
-
function getUrlAndHeaders({ url, serviceName, headers = {} }) {
|
|
13264
|
-
// Check if proxy is enabled in localStorage
|
|
13265
|
-
const apiKeyLS = window.localStorage.getItem(SERVICES_API_KEY[serviceName]);
|
|
13266
|
-
const isProxyModeEnabledValue = apiKeyLS === 'DEFAULT_PROXY_MODE';
|
|
13267
|
-
|
|
13268
|
-
// Check if proxy URL exists for this service
|
|
13269
|
-
const proxyConfig = PROXY_MAP[serviceName];
|
|
13270
|
-
|
|
13271
|
-
if (!proxyConfig && SERVICES_API_KEY[serviceName] && (!apiKeyLS || apiKeyLS === '')) {
|
|
13272
|
-
throw new MissingApiKeyError(SERVICES_API_KEY[serviceName])
|
|
13273
|
-
}
|
|
13274
|
-
|
|
13275
|
-
// If proxy mode is enabled AND proxy URL exists for this service
|
|
13276
|
-
if ((isProxyModeEnabledValue || !apiKeyLS || apiKeyLS === '') && proxyConfig) {
|
|
13277
|
-
// Remove specified parameters from the target URL
|
|
13278
|
-
const cleanedUrl = removeUrlParams(url, proxyConfig.removeParams);
|
|
13279
|
-
|
|
13280
|
-
return {
|
|
13281
|
-
URL: proxyConfig.url,
|
|
13282
|
-
HEADERS: {
|
|
13283
|
-
'target-url': cleanedUrl,
|
|
13284
|
-
method: 'GET',
|
|
13285
|
-
'Content-Type': 'application/json'
|
|
13286
|
-
}
|
|
13287
|
-
};
|
|
13288
|
-
}
|
|
13289
|
-
|
|
13290
|
-
return {
|
|
13291
|
-
URL: url,
|
|
13292
|
-
HEADERS: {
|
|
13293
|
-
...headers,
|
|
13294
|
-
}
|
|
13295
|
-
};
|
|
13296
|
-
}
|
|
13297
|
-
|
|
13298
|
-
const fromTimeStampToBlock = async (timestamp, chain, apiKey) => {
|
|
13299
|
-
if (!timestamp || !chain || !apiKey) return
|
|
13300
|
-
const chainId = CHAIN_ID_MAP[chain];
|
|
13301
|
-
const url = `https://api.etherscan.io/v2/api?module=block&action=getblocknobytime×tamp=${timestamp}&closest=before&apikey=${apiKey}&chainId=${chainId}`;
|
|
13302
|
-
const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url, serviceName: 'Etherscan', headers: {} });
|
|
13303
|
-
const res = await fetch(finalUrl, {
|
|
13304
|
-
method: 'GET',
|
|
13305
|
-
headers: HEADERS,
|
|
13306
|
-
});
|
|
13307
|
-
const json = await res.json();
|
|
13308
|
-
return parseInt(json.result);
|
|
13309
|
-
|
|
13310
|
-
};
|
|
13311
|
-
|
|
13312
|
-
var fromTimestampToBlock = {
|
|
13313
|
-
fromTimeStampToBlock
|
|
13314
|
-
};
|
|
13315
|
-
|
|
13316
|
-
function toTimestamp(dateStr) {
|
|
13317
|
-
// Expecting format: "DD/MM/YYYY"
|
|
13318
|
-
const [day, month, year] = dateStr.split("/").map(Number);
|
|
13319
|
-
const date = new Date(year, month - 1, day);
|
|
13320
|
-
return Math.floor(date.getTime() / 1000); // Unix timestamp in seconds
|
|
13321
|
-
}
|
|
13322
|
-
|
|
13323
13210
|
const isAddress = (input) => {
|
|
13324
13211
|
return (/^0x[a-fA-F0-9]{40}$/.test(input))
|
|
13325
13212
|
};
|
|
@@ -13360,9 +13247,16 @@ async function fromEnsNameToAddress(name) {
|
|
|
13360
13247
|
return null
|
|
13361
13248
|
}
|
|
13362
13249
|
}
|
|
13250
|
+
const validateAndGetAddress = async (address) => {
|
|
13251
|
+
if(isAddress$1.isAddress(address)) return address
|
|
13252
|
+
|
|
13253
|
+
const resolvedAddress = await fromEnsNameToAddress(address);
|
|
13254
|
+
if(resolvedAddress) return resolvedAddress
|
|
13255
|
+
throw new ValidationError("Invalid address")
|
|
13256
|
+
};
|
|
13363
13257
|
|
|
13364
13258
|
var fromEnsNameToAddress$1 = {
|
|
13365
|
-
|
|
13259
|
+
validateAndGetAddress
|
|
13366
13260
|
};
|
|
13367
13261
|
|
|
13368
13262
|
async function handleScanRequest({
|
|
@@ -13383,12 +13277,8 @@ async function handleScanRequest({
|
|
|
13383
13277
|
GNOSIS: { url: 'https://api.gnosisscan.io/api', apiKeyName: SERVICES_API_KEY.Gnosisscan }
|
|
13384
13278
|
};
|
|
13385
13279
|
|
|
13386
|
-
if (
|
|
13387
|
-
|
|
13388
|
-
address = await fromEnsNameToAddress$1.fromEnsNameToAddress(address);
|
|
13389
|
-
if (!address) {
|
|
13390
|
-
throw new EnsError(ensName)
|
|
13391
|
-
}
|
|
13280
|
+
if (type !== 'gas') {
|
|
13281
|
+
address = await fromEnsNameToAddress$1.validateAndGetAddress(address);
|
|
13392
13282
|
}
|
|
13393
13283
|
|
|
13394
13284
|
const apiInfo = API_INFO_MAP[functionName];
|
|
@@ -13421,11 +13311,7 @@ async function handleScanRequest({
|
|
|
13421
13311
|
}
|
|
13422
13312
|
url += `&page=${page}&offset=${offset}`;
|
|
13423
13313
|
}
|
|
13424
|
-
const
|
|
13425
|
-
const res = await fetch(finalUrl, {
|
|
13426
|
-
method: 'GET',
|
|
13427
|
-
headers: HEADERS,
|
|
13428
|
-
});
|
|
13314
|
+
const res = await fetch(url);
|
|
13429
13315
|
if (!res.ok) {
|
|
13430
13316
|
throw new NetworkError(apiInfo.apiKeyName, res.status)
|
|
13431
13317
|
}
|
|
@@ -13444,19 +13330,14 @@ async function handleScanRequest({
|
|
|
13444
13330
|
}
|
|
13445
13331
|
|
|
13446
13332
|
const fromUsernameToFid = async (username, apiKey) => {
|
|
13447
|
-
if
|
|
13333
|
+
if(!username) return null
|
|
13448
13334
|
const url = `https://api.neynar.com/v2/farcaster/user/search/?q=${username}&limit=5`;
|
|
13449
|
-
const
|
|
13450
|
-
|
|
13335
|
+
const res = await fetch(url, {
|
|
13336
|
+
headers: {
|
|
13451
13337
|
'x-api-key': apiKey,
|
|
13452
13338
|
'x-neynar-experimental': 'false'
|
|
13453
13339
|
}
|
|
13454
13340
|
});
|
|
13455
|
-
|
|
13456
|
-
const res = await fetch(finalUrl, {
|
|
13457
|
-
method: 'GET',
|
|
13458
|
-
headers: HEADERS,
|
|
13459
|
-
});
|
|
13460
13341
|
const json = await res.json();
|
|
13461
13342
|
const users = json.result ? json.result.users : [];
|
|
13462
13343
|
const user = users.find(user => user.username === username);
|
|
@@ -17696,9 +17577,9 @@ const aaveParamsSchema = objectType({
|
|
|
17696
17577
|
|
|
17697
17578
|
async function FIREFLY() {
|
|
17698
17579
|
try {
|
|
17699
|
-
|
|
17580
|
+
const [platform, contentType, identifier, start = 0, end = 10] = argsToArray(arguments);
|
|
17700
17581
|
|
|
17701
|
-
|
|
17582
|
+
validateParams(fireflyParamsSchema, {
|
|
17702
17583
|
platform,
|
|
17703
17584
|
contentType,
|
|
17704
17585
|
identifier,
|
|
@@ -17707,6 +17588,9 @@ async function FIREFLY() {
|
|
|
17707
17588
|
});
|
|
17708
17589
|
|
|
17709
17590
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Firefly);
|
|
17591
|
+
if (!apiKey) {
|
|
17592
|
+
throw new MissingApiKeyError(SERVICES_API_KEY.Firefly)
|
|
17593
|
+
}
|
|
17710
17594
|
|
|
17711
17595
|
const url = new URL('https://openapi.firefly.land/v1/fileverse/fetch');
|
|
17712
17596
|
url.searchParams
|
|
@@ -17717,14 +17601,12 @@ async function FIREFLY() {
|
|
|
17717
17601
|
.filter(Boolean)
|
|
17718
17602
|
.join(',')
|
|
17719
17603
|
);
|
|
17720
|
-
|
|
17721
|
-
|
|
17722
|
-
|
|
17604
|
+
url.searchParams.set('type', fireFlyPlaformType[platform][contentType]);
|
|
17605
|
+
url.searchParams.set('start', String(start));
|
|
17606
|
+
url.searchParams.set('end', String(end));
|
|
17723
17607
|
|
|
17724
|
-
const
|
|
17725
|
-
|
|
17726
|
-
method: 'GET',
|
|
17727
|
-
headers: HEADERS,
|
|
17608
|
+
const response = await fetch(url.toString(), {
|
|
17609
|
+
headers: { 'x-api-key': apiKey }
|
|
17728
17610
|
});
|
|
17729
17611
|
if (!response.ok) {
|
|
17730
17612
|
throw new NetworkError(SERVICES_API_KEY.Firefly, response.status)
|
|
@@ -17766,6 +17648,9 @@ async function LENS() {
|
|
|
17766
17648
|
const apiKey = window.localStorage.getItem(
|
|
17767
17649
|
SERVICES_API_KEY.Firefly
|
|
17768
17650
|
);
|
|
17651
|
+
if (!apiKey) {
|
|
17652
|
+
throw new MissingApiKeyError(SERVICES_API_KEY.Firefly)
|
|
17653
|
+
}
|
|
17769
17654
|
|
|
17770
17655
|
const url = new URL(
|
|
17771
17656
|
'https://openapi.firefly.land/v1/fileverse/fetch'
|
|
@@ -17779,18 +17664,15 @@ async function LENS() {
|
|
|
17779
17664
|
.join(',')
|
|
17780
17665
|
);
|
|
17781
17666
|
const typeMap = {
|
|
17782
|
-
posts:
|
|
17667
|
+
posts: 'lensid',
|
|
17783
17668
|
replies: 'lenspostid',
|
|
17784
17669
|
};
|
|
17785
17670
|
url.searchParams.set('type', typeMap[contentType]);
|
|
17786
17671
|
url.searchParams.set('start', String(start));
|
|
17787
|
-
url.searchParams.set('end',
|
|
17788
|
-
|
|
17789
|
-
const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url: url.toString(), serviceName: 'Firefly', headers: { 'x-api-key': apiKey } });
|
|
17672
|
+
url.searchParams.set('end', String(end));
|
|
17790
17673
|
|
|
17791
|
-
const response = await fetch(
|
|
17792
|
-
|
|
17793
|
-
headers: HEADERS,
|
|
17674
|
+
const response = await fetch(url.toString(), {
|
|
17675
|
+
headers: { 'x-api-key': apiKey },
|
|
17794
17676
|
});
|
|
17795
17677
|
if (!response.ok) {
|
|
17796
17678
|
throw new NetworkError(SERVICES_API_KEY.Firefly, response.status)
|
|
@@ -17817,7 +17699,7 @@ async function FARCASTER() {
|
|
|
17817
17699
|
try {
|
|
17818
17700
|
const [contentType, identifier, start = 0, end = 10] =
|
|
17819
17701
|
argsToArray(arguments);
|
|
17820
|
-
|
|
17702
|
+
validateParams(farcasterParamsSchema, {
|
|
17821
17703
|
contentType,
|
|
17822
17704
|
identifier,
|
|
17823
17705
|
start,
|
|
@@ -17827,6 +17709,9 @@ async function FARCASTER() {
|
|
|
17827
17709
|
const apiKey = window.localStorage.getItem(
|
|
17828
17710
|
SERVICES_API_KEY.Firefly
|
|
17829
17711
|
);
|
|
17712
|
+
if (!apiKey) {
|
|
17713
|
+
throw new MissingApiKeyError(SERVICES_API_KEY.Firefly)
|
|
17714
|
+
}
|
|
17830
17715
|
|
|
17831
17716
|
const url = new URL(
|
|
17832
17717
|
'https://openapi.firefly.land/v1/fileverse/fetch'
|
|
@@ -17840,19 +17725,16 @@ async function FARCASTER() {
|
|
|
17840
17725
|
.join(',')
|
|
17841
17726
|
);
|
|
17842
17727
|
const typeMap = {
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
|
|
17728
|
+
posts: 'farcasterid',
|
|
17729
|
+
replies: 'farcasterpostid',
|
|
17730
|
+
channels: 'farcasterchannels',
|
|
17731
|
+
};
|
|
17847
17732
|
url.searchParams.set('type', typeMap[contentType]);
|
|
17848
17733
|
url.searchParams.set('start', String(start));
|
|
17849
|
-
url.searchParams.set('end',
|
|
17734
|
+
url.searchParams.set('end', String(end));
|
|
17850
17735
|
|
|
17851
|
-
const
|
|
17852
|
-
|
|
17853
|
-
const response = await fetch(finalUrl, {
|
|
17854
|
-
method: 'GET',
|
|
17855
|
-
headers: HEADERS,
|
|
17736
|
+
const response = await fetch(url.toString(), {
|
|
17737
|
+
headers: { 'x-api-key': apiKey },
|
|
17856
17738
|
});
|
|
17857
17739
|
if (!response.ok) {
|
|
17858
17740
|
throw new NetworkError(
|
|
@@ -17906,14 +17788,7 @@ async function BLOCKSCOUT() {
|
|
|
17906
17788
|
startTimestamp ?? Math.floor((Date.now() - 30 * 24 * 3600 * 1000) / 1000);
|
|
17907
17789
|
const endTs = endTimestamp;
|
|
17908
17790
|
|
|
17909
|
-
|
|
17910
|
-
if (!isAddress$1.isAddress(resolvedAddress)) {
|
|
17911
|
-
const ensName = resolvedAddress;
|
|
17912
|
-
resolvedAddress = await fromEnsNameToAddress$1.fromEnsNameToAddress(ensName);
|
|
17913
|
-
if (!resolvedAddress) {
|
|
17914
|
-
throw new EnsError(ensName)
|
|
17915
|
-
}
|
|
17916
|
-
}
|
|
17791
|
+
const resolvedAddress = await fromEnsNameToAddress$1.validateAndGetAddress(address);
|
|
17917
17792
|
|
|
17918
17793
|
const hostname = BLOCKSCOUT_CHAINS_MAP[chain];
|
|
17919
17794
|
|
|
@@ -17961,11 +17836,12 @@ async function BLOCKSCOUT() {
|
|
|
17961
17836
|
}
|
|
17962
17837
|
|
|
17963
17838
|
async function BASE() {
|
|
17964
|
-
|
|
17839
|
+
try {
|
|
17965
17840
|
const [type, address, startDate, endDate, page, limit] = argsToArray(arguments);
|
|
17966
|
-
|
|
17841
|
+
validateParams(baseParamsSchema, { type, address, startDate, endDate, page, limit });
|
|
17967
17842
|
const API_KEY = window.localStorage.getItem(SERVICES_API_KEY.Basescan);
|
|
17968
|
-
|
|
17843
|
+
if (!API_KEY) throw new MissingApiKeyError(SERVICES_API_KEY.Basescan)
|
|
17844
|
+
|
|
17969
17845
|
return await handleScanRequest({
|
|
17970
17846
|
type,
|
|
17971
17847
|
address,
|
|
@@ -17978,9 +17854,9 @@ async function BASE() {
|
|
|
17978
17854
|
chainId: CHAIN_ID_MAP.base,
|
|
17979
17855
|
network: 'base'
|
|
17980
17856
|
})
|
|
17981
|
-
|
|
17982
|
-
|
|
17983
|
-
|
|
17857
|
+
} catch (error) {
|
|
17858
|
+
return errorMessageHandler(error, 'BASE')
|
|
17859
|
+
}
|
|
17984
17860
|
}
|
|
17985
17861
|
async function GNOSIS() {
|
|
17986
17862
|
try {
|
|
@@ -18000,6 +17876,7 @@ async function GNOSIS() {
|
|
|
18000
17876
|
const apiKey = window.localStorage.getItem(
|
|
18001
17877
|
SERVICES_API_KEY.Gnosisscan
|
|
18002
17878
|
);
|
|
17879
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Gnosisscan)
|
|
18003
17880
|
|
|
18004
17881
|
return await handleScanRequest({
|
|
18005
17882
|
type,
|
|
@@ -18020,33 +17897,27 @@ async function GNOSIS() {
|
|
|
18020
17897
|
|
|
18021
17898
|
async function NEYNAR() {
|
|
18022
17899
|
try {
|
|
18023
|
-
|
|
18024
|
-
|
|
18025
|
-
|
|
17900
|
+
const neynarParamsSchema = objectType({
|
|
17901
|
+
username: stringType().nonempty()
|
|
17902
|
+
});
|
|
18026
17903
|
|
|
18027
17904
|
const [username] = argsToArray(arguments);
|
|
18028
17905
|
|
|
18029
17906
|
validateParams(neynarParamsSchema, { username });
|
|
18030
17907
|
|
|
18031
17908
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Neynar);
|
|
17909
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Neynar)
|
|
18032
17910
|
|
|
18033
17911
|
const fid = await fromUsernameToFid$1.fromUsernameToFid(username, apiKey);
|
|
18034
17912
|
if (!fid) throw new ValidationError(`Invalid username: ${username}`)
|
|
18035
17913
|
|
|
18036
17914
|
const url = `https://api.neynar.com/v2/farcaster/followers?fid=${fid}`;
|
|
18037
17915
|
|
|
18038
|
-
const
|
|
18039
|
-
|
|
18040
|
-
|
|
18041
|
-
|
|
18042
|
-
|
|
18043
|
-
}
|
|
18044
|
-
|
|
18045
|
-
});
|
|
18046
|
-
|
|
18047
|
-
const response = await fetch(finalUrl, {
|
|
18048
|
-
method: 'GET',
|
|
18049
|
-
headers: HEADERS,
|
|
17916
|
+
const response = await fetch(url, {
|
|
17917
|
+
headers: {
|
|
17918
|
+
'x-api-key': apiKey,
|
|
17919
|
+
'x-neynar-experimental': 'false',
|
|
17920
|
+
}
|
|
18050
17921
|
});
|
|
18051
17922
|
if (!response.ok) {
|
|
18052
17923
|
throw new NetworkError(SERVICES_API_KEY.Neynar, response.status)
|
|
@@ -18141,6 +18012,7 @@ async function ETHERSCAN() {
|
|
|
18141
18012
|
if (!chainId) throw new ValidationError(`Invalid chain: ${chain}`)
|
|
18142
18013
|
|
|
18143
18014
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Etherscan);
|
|
18015
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Etherscan)
|
|
18144
18016
|
|
|
18145
18017
|
return await handleScanRequest({
|
|
18146
18018
|
type,
|
|
@@ -18166,6 +18038,7 @@ async function COINGECKO() {
|
|
|
18166
18038
|
validateParams(coingeckoParamsSchema, { category, param1, param2 });
|
|
18167
18039
|
|
|
18168
18040
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Coingecko);
|
|
18041
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Coingecko)
|
|
18169
18042
|
|
|
18170
18043
|
const headers = {
|
|
18171
18044
|
accept: 'application/json',
|
|
@@ -18179,28 +18052,27 @@ async function COINGECKO() {
|
|
|
18179
18052
|
break
|
|
18180
18053
|
}
|
|
18181
18054
|
case 'market': {
|
|
18182
|
-
const map = { all:
|
|
18055
|
+
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' };
|
|
18183
18056
|
const _category = map[param1] || '';
|
|
18184
18057
|
const trend = param2 ? `&price_change_percentage=${param2}` : '';
|
|
18185
|
-
url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&include_tokens=top&page=1&per_page=100${_category
|
|
18058
|
+
url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&include_tokens=top&page=1&per_page=100${_category?`&category=${_category}`:''}${trend}`;
|
|
18186
18059
|
break
|
|
18187
18060
|
}
|
|
18188
18061
|
case 'stablecoins': {
|
|
18189
|
-
const _category = param1
|
|
18062
|
+
const _category = param1==='all'? 'stablecoins' : param1;
|
|
18190
18063
|
const trend = param2 ? `&price_change_percentage=${param2}` : '';
|
|
18191
18064
|
url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category=${_category}&order=market_cap_desc&page=1&per_page=100${trend}`;
|
|
18192
18065
|
break
|
|
18193
18066
|
}
|
|
18194
18067
|
case 'derivatives': {
|
|
18195
|
-
url = (!param1 || param1
|
|
18068
|
+
url = (!param1 || param1==='all')
|
|
18196
18069
|
? 'https://api.coingecko.com/api/v3/derivatives'
|
|
18197
18070
|
: `https://api.coingecko.com/api/v3/derivatives/exchanges/${param1}?include_tickers=all`;
|
|
18198
18071
|
break
|
|
18199
18072
|
}
|
|
18200
18073
|
}
|
|
18201
|
-
const {URL: finalUrl, HEADERS} = getUrlAndHeaders({url, serviceName: 'Coingecko', headers});
|
|
18202
18074
|
|
|
18203
|
-
const res = await fetch(
|
|
18075
|
+
const res = await fetch(url, { headers });
|
|
18204
18076
|
const json = await res.json();
|
|
18205
18077
|
if (!res.ok) {
|
|
18206
18078
|
const msg = json?.status?.error_message || '';
|
|
@@ -18208,17 +18080,17 @@ async function COINGECKO() {
|
|
|
18208
18080
|
throw new NetworkError(SERVICES_API_KEY.Coingecko, res.status)
|
|
18209
18081
|
}
|
|
18210
18082
|
|
|
18211
|
-
if (category
|
|
18083
|
+
if (category==='price') {
|
|
18212
18084
|
const out = {};
|
|
18213
18085
|
for (const [token, prices] of Object.entries(json))
|
|
18214
|
-
for (const [cur,
|
|
18215
|
-
out[`${token.charAt(0).toUpperCase()
|
|
18086
|
+
for (const [cur,val] of Object.entries(prices))
|
|
18087
|
+
out[`${token.charAt(0).toUpperCase()+token.slice(1)}_${cur.toUpperCase()}`]=val;
|
|
18216
18088
|
return [out]
|
|
18217
18089
|
}
|
|
18218
18090
|
|
|
18219
18091
|
const data = Array.isArray(json) ? json : [json];
|
|
18220
|
-
return data.map(item
|
|
18221
|
-
const flat
|
|
18092
|
+
return data.map(item=>{
|
|
18093
|
+
const flat={};
|
|
18222
18094
|
for (const [key, value] of Object.entries(item)) {
|
|
18223
18095
|
if (typeof value !== 'object' || value === null) {
|
|
18224
18096
|
flat[key] = value;
|
|
@@ -18226,8 +18098,8 @@ async function COINGECKO() {
|
|
|
18226
18098
|
}
|
|
18227
18099
|
return flat
|
|
18228
18100
|
})
|
|
18229
|
-
} catch
|
|
18230
|
-
return errorMessageHandler(err,
|
|
18101
|
+
} catch(err) {
|
|
18102
|
+
return errorMessageHandler(err,'COINGECKO')
|
|
18231
18103
|
}
|
|
18232
18104
|
}
|
|
18233
18105
|
|
|
@@ -18238,30 +18110,25 @@ async function EOA() {
|
|
|
18238
18110
|
validateParams(eoaParamsSchema, { addresses, category, chains, startTime, endTime, page, offset });
|
|
18239
18111
|
|
|
18240
18112
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Etherscan);
|
|
18113
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Etherscan)
|
|
18241
18114
|
|
|
18242
|
-
const INPUTS = addresses.split(',').map(s
|
|
18243
|
-
const CHAINS = chains.split(',').map(s
|
|
18115
|
+
const INPUTS = addresses.split(',').map(s=>s.trim()).filter(Boolean);
|
|
18116
|
+
const CHAINS = chains.split(',').map(s=>s.trim()).filter(Boolean);
|
|
18244
18117
|
|
|
18245
18118
|
const ADDRESS_MAP = {};
|
|
18246
18119
|
for (const inp of INPUTS) {
|
|
18247
18120
|
if (isAddress$1.isAddress(inp)) {
|
|
18248
18121
|
ADDRESS_MAP[inp.toLowerCase()] = null;
|
|
18249
18122
|
} else {
|
|
18250
|
-
|
|
18251
|
-
|
|
18252
|
-
if (!resolved) throw new EnsError(ens)
|
|
18253
|
-
ADDRESS_MAP[resolved.toLowerCase()] = ens;
|
|
18123
|
+
const _address = await fromEnsNameToAddress$1.validateAndGetAddress(inp);
|
|
18124
|
+
ADDRESS_MAP[_address.toLowerCase()] = _address;
|
|
18254
18125
|
}
|
|
18255
18126
|
}
|
|
18256
18127
|
const ADDRS = Object.keys(ADDRESS_MAP);
|
|
18257
18128
|
const out = [];
|
|
18258
18129
|
|
|
18259
18130
|
async function fetchJSON(url) {
|
|
18260
|
-
const
|
|
18261
|
-
const res = await fetch(finalUrl, {
|
|
18262
|
-
method: 'GET',
|
|
18263
|
-
headers: HEADERS,
|
|
18264
|
-
});
|
|
18131
|
+
const res = await fetch(url);
|
|
18265
18132
|
if (!res.ok) throw new NetworkError(SERVICES_API_KEY.Etherscan, res.status)
|
|
18266
18133
|
const json = await res.json();
|
|
18267
18134
|
|
|
@@ -18279,15 +18146,15 @@ async function EOA() {
|
|
|
18279
18146
|
|
|
18280
18147
|
if (category === 'balance') {
|
|
18281
18148
|
// chunk 20
|
|
18282
|
-
for (let i
|
|
18283
|
-
const slice = ADDRS.slice(i,
|
|
18149
|
+
for (let i=0; i<ADDRS.length; i+=20) {
|
|
18150
|
+
const slice = ADDRS.slice(i,i+20).join(',');
|
|
18284
18151
|
const url =
|
|
18285
|
-
`https://api.etherscan.io/v2/api?chainid=${chainId}
|
|
18286
|
-
`&module=account&action=addresstokenbalance&address=${slice}
|
|
18152
|
+
`https://api.etherscan.io/v2/api?chainid=${chainId}`+
|
|
18153
|
+
`&module=account&action=addresstokenbalance&address=${slice}`+
|
|
18287
18154
|
`&page=${page}&offset=${offset}&apikey=${apiKey}`;
|
|
18288
18155
|
const data = await fetchJSON(url);
|
|
18289
18156
|
if (!Array.isArray(data)) return data
|
|
18290
|
-
data.forEach((item, idx) => out.push({ chain, address: ADDRS[i
|
|
18157
|
+
data.forEach((item, idx) => out.push({ chain, address: ADDRS[i+idx], name: ADDRESS_MAP[ADDRS[i+idx]], ...item }));
|
|
18291
18158
|
}
|
|
18292
18159
|
} else {
|
|
18293
18160
|
// txns
|
|
@@ -18297,9 +18164,9 @@ async function EOA() {
|
|
|
18297
18164
|
if (!eb) throw new ValidationError(`Invalid endTime: ${endTime}`)
|
|
18298
18165
|
for (const addr of ADDRS) {
|
|
18299
18166
|
const url =
|
|
18300
|
-
`https://api.etherscan.io/v2/api?chainid=${chainId}
|
|
18301
|
-
`&module=account&action=tokentx&address=${addr}
|
|
18302
|
-
`&startblock=${sb}&endblock=${eb}
|
|
18167
|
+
`https://api.etherscan.io/v2/api?chainid=${chainId}`+
|
|
18168
|
+
`&module=account&action=tokentx&address=${addr}`+
|
|
18169
|
+
`&startblock=${sb}&endblock=${eb}`+
|
|
18303
18170
|
`&page=${page}&offset=${offset}&sort=asc&apikey=${apiKey}`;
|
|
18304
18171
|
const data = await fetchJSON(url);
|
|
18305
18172
|
if (!Array.isArray(data)) return data
|
|
@@ -18328,22 +18195,21 @@ async function SAFE() {
|
|
|
18328
18195
|
validateParams(safeParamsSchema, { address, utility, chain, limit, offset });
|
|
18329
18196
|
|
|
18330
18197
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Safe);
|
|
18198
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Safe)
|
|
18331
18199
|
|
|
18332
18200
|
const chainId = SAFE_CHAIN_MAP[chain];
|
|
18333
18201
|
if (!chainId) throw new ValidationError(`Invalid chain: ${chain}`)
|
|
18334
18202
|
|
|
18335
|
-
|
|
18336
|
-
|
|
18337
|
-
|
|
18338
|
-
|
|
18339
|
-
if (!resolved) throw new EnsError(ens)
|
|
18340
|
-
}
|
|
18203
|
+
|
|
18204
|
+
|
|
18205
|
+
|
|
18206
|
+
const resolved = await fromEnsNameToAddress$1.validateAndGetAddress(address);
|
|
18341
18207
|
|
|
18342
18208
|
|
|
18343
18209
|
const url = `https://api.safe.global/tx-service/${chainId}/api/v2/safes/${resolved}/multisig-transactions?limit=${limit}&offset=${offset}`;
|
|
18344
18210
|
|
|
18345
|
-
|
|
18346
|
-
const res = await fetch(
|
|
18211
|
+
|
|
18212
|
+
const res = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
|
|
18347
18213
|
if (!res.ok) throw new NetworkError(SERVICES_API_KEY.Safe, res.status)
|
|
18348
18214
|
const json = await res.json();
|
|
18349
18215
|
|
|
@@ -18364,6 +18230,7 @@ async function DEFILLAMA() {
|
|
|
18364
18230
|
const [category] = argsToArray(arguments);
|
|
18365
18231
|
validateParams(defillamaParamsSchema, { category });
|
|
18366
18232
|
const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Defillama);
|
|
18233
|
+
if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Defillama)
|
|
18367
18234
|
const url = CATEGORY_URLS[category];
|
|
18368
18235
|
if (!url) throw new ValidationError(`Invalid category: ${category}`)
|
|
18369
18236
|
const res = await fetch(url);
|
|
@@ -18372,20 +18239,20 @@ async function DEFILLAMA() {
|
|
|
18372
18239
|
|
|
18373
18240
|
switch (category) {
|
|
18374
18241
|
case 'protocols':
|
|
18375
|
-
json = Array.isArray(json) ? json.slice(0,
|
|
18242
|
+
json = Array.isArray(json) ? json.slice(0,500) : [];
|
|
18376
18243
|
break
|
|
18377
18244
|
case 'yields':
|
|
18378
|
-
json = Array.isArray(json.data) ? json.data.slice(0,
|
|
18245
|
+
json = Array.isArray(json.data) ? json.data.slice(0,500) : [];
|
|
18379
18246
|
break
|
|
18380
18247
|
case 'dex':
|
|
18381
18248
|
case 'fees':
|
|
18382
|
-
json = Array.isArray(json.protocols) ? json.protocols.slice(0,
|
|
18249
|
+
json = Array.isArray(json.protocols) ? json.protocols.slice(0,500) : [];
|
|
18383
18250
|
break
|
|
18384
18251
|
}
|
|
18385
18252
|
|
|
18386
18253
|
return (Array.isArray(json) ? json : [json]).map(item => {
|
|
18387
18254
|
const out = {};
|
|
18388
|
-
for (const [k,
|
|
18255
|
+
for (const [k,v] of Object.entries(item)) {
|
|
18389
18256
|
if (v === null || typeof v !== 'object') out[k] = v;
|
|
18390
18257
|
}
|
|
18391
18258
|
return out
|
|
@@ -18421,7 +18288,7 @@ async function UNISWAP() {
|
|
|
18421
18288
|
// flatten nested
|
|
18422
18289
|
return json.map(item => {
|
|
18423
18290
|
const flat = {};
|
|
18424
|
-
Object.entries(item).forEach(([k,
|
|
18291
|
+
Object.entries(item).forEach(([k,v]) => {
|
|
18425
18292
|
if (v === null || typeof v !== 'object') flat[k] = v;
|
|
18426
18293
|
});
|
|
18427
18294
|
return flat
|