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