@fileverse-dev/formulajs 4.4.11-mod-70 → 4.4.11-mod-68-patch-3

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/cjs/index.cjs CHANGED
@@ -13144,15 +13144,126 @@ const SERVICES_API_KEY = {
13144
13144
  Defillama: 'Defillama'
13145
13145
  };
13146
13146
 
13147
+ // Proxy map configuration
13148
+ const PROXY_MAP = {
13149
+ Etherscan: {
13150
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13151
+ removeParams: ['apikey']
13152
+ },
13153
+ Basescan: {
13154
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13155
+ removeParams: ['apikey']
13156
+ },
13157
+ Gnosisscan: {
13158
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13159
+ removeParams: ['apikey']
13160
+ },
13161
+ Coingecko: {
13162
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13163
+ removeParams: ['apikey']
13164
+ },
13165
+ Firefly: {
13166
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13167
+ removeParams: ['apikey']
13168
+ },
13169
+ Neynar: {
13170
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13171
+ removeParams: ['api_key']
13172
+ },
13173
+ Safe: {
13174
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13175
+ removeParams: ['api_key']
13176
+ },
13177
+ Defillama: {
13178
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13179
+ removeParams: ['api_key']
13180
+ },
13181
+ GnosisPay: {
13182
+ url: "https://staging-api-proxy-ca4268d7d581.herokuapp.com/proxy",
13183
+ removeParams: ['api_key']
13184
+ },
13185
+ // Add more services as needed. It can be direct url instead of ENV variable
13186
+ // ANOTHER_SERVICE: "https://another-proxy-url.com"
13187
+ };
13188
+
13189
+ /**
13190
+ * Removes specified parameters from a URL
13191
+ * @param {string} url - The original URL
13192
+ * @param {string[]} paramsToRemove - Array of parameter names to remove
13193
+ * @returns {string} URL with specified parameters removed
13194
+ */
13195
+ function removeUrlParams(url, paramsToRemove) {
13196
+ if (!paramsToRemove || paramsToRemove.length === 0) {
13197
+ return url;
13198
+ }
13199
+
13200
+ const urlObj = new URL(url);
13201
+
13202
+ paramsToRemove.forEach(param => {
13203
+ if (urlObj.searchParams.has(param)) {
13204
+ urlObj.searchParams.delete(param);
13205
+ }
13206
+ });
13207
+
13208
+ return urlObj.toString();
13209
+ }
13210
+
13211
+ /**
13212
+ * Handles URL routing through proxy or direct API calls
13213
+ * @param {string} url - The original API URL
13214
+ * @param {string} serviceName - The name of the service (e.g., 'EOA')
13215
+ * @param {string} headers - The name of the service (e.g., 'EOA')
13216
+ * @returns {Object} Object containing URL and HEADERS for the fetch request
13217
+ */
13218
+ function getUrlAndHeaders({ url, serviceName, headers = {} }) {
13219
+ console.log('getUrlAndHeaders new modified function from formulajs', url, apiKeyName, serviceName);
13220
+ // Check if proxy is enabled in localStorage
13221
+ const apiKeyLS = window.localStorage.getItem(SERVICES_API_KEY[serviceName]);
13222
+ const isProxyModeEnabledValue = apiKeyLS === 'DEFAULT_PROXY_MODE';
13223
+
13224
+ // Check if proxy URL exists for this service
13225
+ const proxyConfig = PROXY_MAP[serviceName];
13226
+
13227
+ // If proxy mode is enabled AND proxy URL exists for this service
13228
+ if (isProxyModeEnabledValue && proxyConfig && serviceName && SERVICES_API_KEY[serviceName]) {
13229
+ console.log('isProxyModeEnabledValue', isProxyModeEnabledValue);
13230
+ // Remove specified parameters from the target URL
13231
+ const cleanedUrl = removeUrlParams(url, proxyConfig.removeParams);
13232
+
13233
+ return {
13234
+ URL: proxyConfig.url,
13235
+ HEADERS: {
13236
+ 'target-url': cleanedUrl,
13237
+ method: 'GET',
13238
+ 'Content-Type': 'application/json'
13239
+ }
13240
+ };
13241
+ }
13242
+
13243
+
13244
+ return {
13245
+ URL: url,
13246
+ HEADERS: {
13247
+ ...headers,
13248
+ method: 'GET',
13249
+ 'Content-Type': 'application/json'
13250
+ }
13251
+ };
13252
+ }
13253
+
13147
13254
  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&timestamp=${timestamp}&closest=before&apikey=${apiKey}&chainId=${chainId}`;
13151
- const res = await fetch(url);
13152
- const json = await res.json();
13153
- return parseInt(json.result);
13255
+ if (!timestamp || !chain || !apiKey) return
13256
+ const chainId = CHAIN_ID_MAP[chain];
13257
+ const url = `https://api.etherscan.io/v2/api?module=block&action=getblocknobytime&timestamp=${timestamp}&closest=before&apikey=${apiKey}&chainId=${chainId}`;
13258
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url, serviceName: 'Etherscan', headers: {} });
13259
+ const res = await fetch(finalUrl, {
13260
+ method: 'GET',
13261
+ headers: HEADERS,
13262
+ });
13263
+ const json = await res.json();
13264
+ return parseInt(json.result);
13154
13265
 
13155
- };
13266
+ };
13156
13267
 
13157
13268
  var fromTimestampToBlock = {
13158
13269
  fromTimeStampToBlock
@@ -13289,14 +13400,13 @@ async function handleScanRequest({
13289
13400
  'all-txns': 'txlist',
13290
13401
  'token-txns': 'tokentx',
13291
13402
  'nft-txns': 'tokennfttx',
13292
- 'gas': 'gasoracle'
13403
+ gas: 'gastracker'
13293
13404
  };
13294
13405
 
13295
13406
  const action = ACTION_MAP[type];
13296
13407
  if (!action) throw new ValidationError(`Invalid type: ${type}`)
13297
13408
 
13298
- const module = action === 'gasoracle' ? 'gastracker' : 'account';
13299
- let url = `${baseUrl}?chainid=${chainId}&module=${module}&action=${action}&apikey=${apiKey}`;
13409
+ let url = `${baseUrl}?chainid=${chainId}&module=account&action=${action}&apikey=${apiKey}`;
13300
13410
 
13301
13411
  if (['all-txns', 'token-txns', 'nft-txns'].includes(type)) {
13302
13412
  url += `&address=${address}&startblock=0&endblock=99999999&sort=asc`;
@@ -13310,7 +13420,11 @@ async function handleScanRequest({
13310
13420
  }
13311
13421
  url += `&page=${page}&offset=${offset}`;
13312
13422
  }
13313
- const res = await fetch(url);
13423
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({url, serviceName: 'Etherscan', headers: {}});
13424
+ const res = await fetch(finalUrl, {
13425
+ method: 'GET',
13426
+ headers: HEADERS,
13427
+ });
13314
13428
  if (!res.ok) {
13315
13429
  throw new NetworkError(apiInfo.apiKeyName, res.status)
13316
13430
  }
@@ -13325,18 +13439,23 @@ async function handleScanRequest({
13325
13439
  throw new RateLimitError(apiInfo.apiKeyName)
13326
13440
  }
13327
13441
 
13328
- return type === 'gas' ? [json.result] : json.result
13442
+ return json.result
13329
13443
  }
13330
13444
 
13331
13445
  const fromUsernameToFid = async (username, apiKey) => {
13332
- if(!username) return null
13446
+ if (!username) return null
13333
13447
  const url = `https://api.neynar.com/v2/farcaster/user/search/?q=${username}&limit=5`;
13334
- const res = await fetch(url, {
13335
- headers: {
13448
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({
13449
+ url, serviceName: 'Neynar', headers: {
13336
13450
  'x-api-key': apiKey,
13337
13451
  'x-neynar-experimental': 'false'
13338
13452
  }
13339
13453
  });
13454
+
13455
+ const res = await fetch(finalUrl, {
13456
+ method: 'GET',
13457
+ headers: HEADERS,
13458
+ });
13340
13459
  const json = await res.json();
13341
13460
  const users = json.result ? json.result.users : [];
13342
13461
  const user = users.find(user => user.username === username);
@@ -17349,7 +17468,7 @@ const farcasterSchema = objectType({
17349
17468
  contentType: enumType(['posts', 'replies', 'channels']),
17350
17469
  identifier: stringType().nonempty(),
17351
17470
  start: numberType().int().nonnegative().default(0),
17352
- end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17471
+ end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17353
17472
  });
17354
17473
 
17355
17474
  const lensSchema = objectType({
@@ -17357,7 +17476,7 @@ const lensSchema = objectType({
17357
17476
  contentType: enumType(['posts', 'replies']),
17358
17477
  identifier: stringType().nonempty(),
17359
17478
  start: numberType().int().nonnegative().default(0),
17360
- end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17479
+ end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17361
17480
  });
17362
17481
 
17363
17482
  const fireflyParamsSchema = discriminatedUnionType('platform', [
@@ -17380,33 +17499,31 @@ const lensParamsSchema = objectType({
17380
17499
  contentType: enumType(['posts', 'replies']),
17381
17500
  identifier: stringType().nonempty(),
17382
17501
  start: numberType().int().nonnegative().default(0),
17383
- end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17502
+ end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17384
17503
  });
17385
17504
 
17386
17505
  const farcasterParamsSchema = objectType({
17387
17506
  contentType: enumType(['posts', 'replies', 'channels']),
17388
17507
  identifier: stringType().nonempty(),
17389
17508
  start: numberType().int().nonnegative().default(0),
17390
- end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"end" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17509
+ end: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17391
17510
  });
17392
17511
 
17393
17512
  const dateStringToTimestamp = (val) => {
17394
- const [dd, mm, yyyy] = val.split('/');
17395
- const date = new Date(`${yyyy}-${mm.padStart(2, '0')}-${dd.padStart(2, '0')}`);
17396
- const timestamp = date.getTime();
17397
- return isNaN(timestamp) ? NaN : Math.floor(timestamp / 1000);
17513
+ const [mm, dd, yyyy] = val.split('/');
17514
+ return Math.floor(new Date(`${yyyy}-${mm}-${dd}`).getTime() / 1000);
17398
17515
  };
17399
17516
 
17400
17517
  /**
17401
- * Accepts either a UNIX timestamp number or a DD/MM/YYYY string,
17518
+ * Accepts either a UNIXtimestamp number or a MM/DD/YYYY string,
17402
17519
  * and always returns a nonnegative integer timestamp.
17403
17520
  */
17404
17521
  const dateOrTimestamp = preprocessType(
17405
17522
  (val) =>
17406
- typeof val === 'string' && /^\d{1,2}\/\d{1,2}\/\d{4}$/.test(val)
17523
+ typeof val === 'string' && /^\d{2}\/\d{2}\/\d{4}$/.test(val)
17407
17524
  ? dateStringToTimestamp(val)
17408
17525
  : val,
17409
- 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' })
17526
+ numberType().int().nonnegative()
17410
17527
  );
17411
17528
 
17412
17529
  const blockscoutParamsSchema = objectType({
@@ -17416,7 +17533,7 @@ const blockscoutParamsSchema = objectType({
17416
17533
  startTimestamp: dateOrTimestamp.optional(),
17417
17534
  endTimestamp: dateOrTimestamp.optional(),
17418
17535
  page: numberType().int().nonnegative().default(1),
17419
- offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"offset" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17536
+ offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17420
17537
  });
17421
17538
 
17422
17539
  const gasSchema$1 = objectType({
@@ -17424,7 +17541,7 @@ const gasSchema$1 = objectType({
17424
17541
  startDate: dateOrTimestamp.optional(),
17425
17542
  endDate: dateOrTimestamp.optional(),
17426
17543
  page: numberType().int().nonnegative().default(1),
17427
- limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17544
+ limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17428
17545
  });
17429
17546
 
17430
17547
  const txnSchema$1 = objectType({
@@ -17433,7 +17550,7 @@ const txnSchema$1 = objectType({
17433
17550
  startDate: dateOrTimestamp.optional(),
17434
17551
  endDate: dateOrTimestamp.optional(),
17435
17552
  page: numberType().int().nonnegative().default(1),
17436
- limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17553
+ limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17437
17554
  });
17438
17555
 
17439
17556
  const baseParamsSchema = discriminatedUnionType('type', [gasSchema$1, txnSchema$1]);
@@ -17443,7 +17560,7 @@ const gasSchema = objectType({
17443
17560
  startDate: dateOrTimestamp.optional(),
17444
17561
  endDate: dateOrTimestamp.optional(),
17445
17562
  page: numberType().int().nonnegative().default(1),
17446
- limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17563
+ limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17447
17564
  });
17448
17565
 
17449
17566
  const txnSchema = objectType({
@@ -17453,21 +17570,11 @@ const txnSchema = objectType({
17453
17570
  endDate: dateOrTimestamp.optional(),
17454
17571
  chain: enumType(['ethereum','base','gnosis']),
17455
17572
  page: numberType().int().nonnegative().default(1),
17456
- limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17573
+ limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17457
17574
  });
17458
17575
 
17459
17576
  const etherscanParamsSchema = discriminatedUnionType('type', [gasSchema, txnSchema]);
17460
17577
 
17461
- const allowedValues = ['1h', '24h', '7d'];
17462
- const param2Schema = stringType()
17463
- .refine((val) => {
17464
- const tokens = val.split(',').map((t) => t.trim().toLowerCase());
17465
- return tokens.some((token) =>
17466
- allowedValues.some((allowed) => token.includes(allowed))
17467
- );
17468
- }, {
17469
- message: "param2 must contain at least one of: '1h', '24h', '7d'",
17470
- }).optional();
17471
17578
  const priceSchema = objectType({
17472
17579
  category: literalType('price'),
17473
17580
  param1: stringType().nonempty(),
@@ -17477,13 +17584,13 @@ const marketEcosystems = ['all','base','meme','aiagents','bitcoin','ethereum','h
17477
17584
  const marketSchema = objectType({
17478
17585
  category: literalType('market'),
17479
17586
  param1: enumType(marketEcosystems),
17480
- param2: param2Schema,
17587
+ param2: enumType(['1h','24h','7d']).optional(),
17481
17588
  });
17482
17589
  const stablecoinsTypes = ['all','yield-bearing-stablecoins','crypto-backed-stablecoin'];
17483
17590
  const stablecoinsSchema = objectType({
17484
17591
  category: literalType('stablecoins'),
17485
17592
  param1: enumType(stablecoinsTypes),
17486
- param2: param2Schema,
17593
+ param2: enumType(['1h','24h','7d']).optional(),
17487
17594
  });
17488
17595
  const derivativesSchema = objectType({
17489
17596
  category: literalType('derivatives'),
@@ -17511,7 +17618,7 @@ const baseSchema = objectType({
17511
17618
  startTime: dateOrTimestamp.optional(),
17512
17619
  endTime: dateOrTimestamp.optional(),
17513
17620
  page: numberType().int().nonnegative().default(1),
17514
- offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"offset" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17621
+ offset: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17515
17622
  });
17516
17623
 
17517
17624
  const eoaParamsSchema = preprocessType(
@@ -17540,7 +17647,7 @@ const safeParamsSchema = objectType({
17540
17647
  address: stringType().nonempty(),
17541
17648
  utility: literalType('txns'),
17542
17649
  chain: enumType(['ethereum','gnosis']),
17543
- limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT, {message: `"limit" must be less than or equal to ${MAX_PAGE_LIMIT}`}).default(10),
17650
+ limit: numberType().int().nonnegative().max(MAX_PAGE_LIMIT).default(10),
17544
17651
  offset: numberType().int().nonnegative().default(0),
17545
17652
  });
17546
17653
 
@@ -17576,9 +17683,9 @@ const aaveParamsSchema = objectType({
17576
17683
 
17577
17684
  async function FIREFLY() {
17578
17685
  try {
17579
- const [platform, contentType, identifier, start = 0, end = 10] = argsToArray(arguments);
17686
+ const [platform, contentType, identifier, start = 0, end = 10] = argsToArray(arguments);
17580
17687
 
17581
- validateParams(fireflyParamsSchema, {
17688
+ validateParams(fireflyParamsSchema, {
17582
17689
  platform,
17583
17690
  contentType,
17584
17691
  identifier,
@@ -17600,12 +17707,14 @@ validateParams(fireflyParamsSchema, {
17600
17707
  .filter(Boolean)
17601
17708
  .join(',')
17602
17709
  );
17603
- url.searchParams.set('type', fireFlyPlaformType[platform][contentType]);
17604
- url.searchParams.set('start', String(start));
17605
- url.searchParams.set('end', String(end));
17710
+ url.searchParams.set('type', fireFlyPlaformType[platform][contentType]);
17711
+ url.searchParams.set('start', String(start));
17712
+ url.searchParams.set('end', String(end));
17606
17713
 
17607
- const response = await fetch(url.toString(), {
17608
- headers: { 'x-api-key': apiKey }
17714
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url: url.toString(), serviceName: 'Firefly', headers });
17715
+ const response = await fetch(finalUrl, {
17716
+ method: 'GET',
17717
+ headers: HEADERS,
17609
17718
  });
17610
17719
  if (!response.ok) {
17611
17720
  throw new NetworkError(SERVICES_API_KEY.Firefly, response.status)
@@ -17663,15 +17772,18 @@ async function LENS() {
17663
17772
  .join(',')
17664
17773
  );
17665
17774
  const typeMap = {
17666
- posts: 'lensid',
17775
+ posts: 'lensid',
17667
17776
  replies: 'lenspostid',
17668
17777
  };
17669
17778
  url.searchParams.set('type', typeMap[contentType]);
17670
17779
  url.searchParams.set('start', String(start));
17671
- url.searchParams.set('end', String(end));
17780
+ url.searchParams.set('end', String(end));
17672
17781
 
17673
- const response = await fetch(url.toString(), {
17674
- headers: { 'x-api-key': apiKey },
17782
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url: url.toString(), serviceName: 'Firefly', headers });
17783
+
17784
+ const response = await fetch(finalUrl, {
17785
+ method: 'GET',
17786
+ headers: HEADERS,
17675
17787
  });
17676
17788
  if (!response.ok) {
17677
17789
  throw new NetworkError(SERVICES_API_KEY.Firefly, response.status)
@@ -17698,7 +17810,7 @@ async function FARCASTER() {
17698
17810
  try {
17699
17811
  const [contentType, identifier, start = 0, end = 10] =
17700
17812
  argsToArray(arguments);
17701
- validateParams(farcasterParamsSchema, {
17813
+ validateParams(farcasterParamsSchema, {
17702
17814
  contentType,
17703
17815
  identifier,
17704
17816
  start,
@@ -17724,16 +17836,19 @@ validateParams(farcasterParamsSchema, {
17724
17836
  .join(',')
17725
17837
  );
17726
17838
  const typeMap = {
17727
- posts: 'farcasterid',
17728
- replies: 'farcasterpostid',
17729
- channels: 'farcasterchannels',
17730
- };
17839
+ posts: 'farcasterid',
17840
+ replies: 'farcasterpostid',
17841
+ channels: 'farcasterchannels',
17842
+ };
17731
17843
  url.searchParams.set('type', typeMap[contentType]);
17732
17844
  url.searchParams.set('start', String(start));
17733
- url.searchParams.set('end', String(end));
17845
+ url.searchParams.set('end', String(end));
17846
+
17847
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url: url.toString(), serviceName: 'Firefly', headers });
17734
17848
 
17735
- const response = await fetch(url.toString(), {
17736
- headers: { 'x-api-key': apiKey },
17849
+ const response = await fetch(finalUrl, {
17850
+ method: 'GET',
17851
+ headers: HEADERS,
17737
17852
  });
17738
17853
  if (!response.ok) {
17739
17854
  throw new NetworkError(
@@ -17842,12 +17957,12 @@ async function BLOCKSCOUT() {
17842
17957
  }
17843
17958
 
17844
17959
  async function BASE() {
17845
- try {
17960
+ try {
17846
17961
  const [type, address, startDate, endDate, page, limit] = argsToArray(arguments);
17847
- validateParams(baseParamsSchema, { type, address, startDate, endDate, page, limit });
17962
+ validateParams(baseParamsSchema, { type, address, startDate, endDate, page, limit });
17848
17963
  const API_KEY = window.localStorage.getItem(SERVICES_API_KEY.Basescan);
17849
17964
  if (!API_KEY) throw new MissingApiKeyError(SERVICES_API_KEY.Basescan)
17850
-
17965
+
17851
17966
  return await handleScanRequest({
17852
17967
  type,
17853
17968
  address,
@@ -17860,9 +17975,9 @@ try {
17860
17975
  chainId: CHAIN_ID_MAP.base,
17861
17976
  network: 'base'
17862
17977
  })
17863
- } catch (error) {
17864
- return errorMessageHandler(error, 'BASE')
17865
- }
17978
+ } catch (error) {
17979
+ return errorMessageHandler(error, 'BASE')
17980
+ }
17866
17981
  }
17867
17982
  async function GNOSIS() {
17868
17983
  try {
@@ -17903,9 +18018,9 @@ async function GNOSIS() {
17903
18018
 
17904
18019
  async function NEYNAR() {
17905
18020
  try {
17906
- const neynarParamsSchema = objectType({
17907
- username: stringType().nonempty()
17908
- });
18021
+ const neynarParamsSchema = objectType({
18022
+ username: stringType().nonempty()
18023
+ });
17909
18024
 
17910
18025
  const [username] = argsToArray(arguments);
17911
18026
 
@@ -17919,12 +18034,19 @@ async function NEYNAR() {
17919
18034
 
17920
18035
  const url = `https://api.neynar.com/v2/farcaster/followers?fid=${fid}`;
17921
18036
 
17922
- const response = await fetch(url, {
17923
- headers: {
17924
- 'x-api-key': apiKey,
17925
- 'x-neynar-experimental': 'false',
18037
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({
18038
+ url: url.toString(), serviceName: 'Firefly', headers: {
18039
+ headers: {
18040
+ 'x-api-key': API_KEY,
18041
+ 'x-neynar-experimental': 'false'
18042
+ }
17926
18043
  }
17927
18044
  });
18045
+
18046
+ const response = await fetch(finalUrl, {
18047
+ method: 'GET',
18048
+ headers: HEADERS,
18049
+ });
17928
18050
  if (!response.ok) {
17929
18051
  throw new NetworkError(SERVICES_API_KEY.Neynar, response.status)
17930
18052
  }
@@ -18058,20 +18180,20 @@ async function COINGECKO() {
18058
18180
  break
18059
18181
  }
18060
18182
  case 'market': {
18061
- 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
+ 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' };
18062
18184
  const _category = map[param1] || '';
18063
18185
  const trend = param2 ? `&price_change_percentage=${param2}` : '';
18064
- 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
+ url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&include_tokens=top&page=1&per_page=100${_category ? `&category=${_category}` : ''}${trend}`;
18065
18187
  break
18066
18188
  }
18067
18189
  case 'stablecoins': {
18068
- const _category = param1==='all'? 'stablecoins' : param1;
18190
+ const _category = param1 === 'all' ? 'stablecoins' : param1;
18069
18191
  const trend = param2 ? `&price_change_percentage=${param2}` : '';
18070
18192
  url = `https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&category=${_category}&order=market_cap_desc&page=1&per_page=100${trend}`;
18071
18193
  break
18072
18194
  }
18073
18195
  case 'derivatives': {
18074
- url = (!param1 || param1==='all')
18196
+ url = (!param1 || param1 === 'all')
18075
18197
  ? 'https://api.coingecko.com/api/v3/derivatives'
18076
18198
  : `https://api.coingecko.com/api/v3/derivatives/exchanges/${param1}?include_tickers=all`;
18077
18199
  break
@@ -18086,17 +18208,17 @@ async function COINGECKO() {
18086
18208
  throw new NetworkError(SERVICES_API_KEY.Coingecko, res.status)
18087
18209
  }
18088
18210
 
18089
- if (category==='price') {
18211
+ if (category === 'price') {
18090
18212
  const out = {};
18091
18213
  for (const [token, prices] of Object.entries(json))
18092
- for (const [cur,val] of Object.entries(prices))
18093
- out[`${token.charAt(0).toUpperCase()+token.slice(1)}_${cur.toUpperCase()}`]=val;
18214
+ for (const [cur, val] of Object.entries(prices))
18215
+ out[`${token.charAt(0).toUpperCase() + token.slice(1)}_${cur.toUpperCase()}`] = val;
18094
18216
  return [out]
18095
18217
  }
18096
18218
 
18097
18219
  const data = Array.isArray(json) ? json : [json];
18098
- return data.map(item=>{
18099
- const flat={};
18220
+ return data.map(item => {
18221
+ const flat = {};
18100
18222
  for (const [key, value] of Object.entries(item)) {
18101
18223
  if (typeof value !== 'object' || value === null) {
18102
18224
  flat[key] = value;
@@ -18104,22 +18226,24 @@ async function COINGECKO() {
18104
18226
  }
18105
18227
  return flat
18106
18228
  })
18107
- } catch(err) {
18108
- return errorMessageHandler(err,'COINGECKO')
18229
+ } catch (err) {
18230
+ return errorMessageHandler(err, 'COINGECKO')
18109
18231
  }
18110
18232
  }
18111
18233
 
18112
18234
  async function EOA() {
18235
+ console.log('EOA');
18113
18236
  try {
18114
18237
  const [addresses, category, chains, startTime, endTime, page = 1, offset = 10] =
18115
18238
  argsToArray(arguments);
18116
18239
  validateParams(eoaParamsSchema, { addresses, category, chains, startTime, endTime, page, offset });
18117
18240
 
18118
18241
  const apiKey = window.localStorage.getItem(SERVICES_API_KEY.Etherscan);
18242
+ console.log('apiKey', apiKey);
18119
18243
  if (!apiKey) throw new MissingApiKeyError(SERVICES_API_KEY.Etherscan)
18120
18244
 
18121
- const INPUTS = addresses.split(',').map(s=>s.trim()).filter(Boolean);
18122
- const CHAINS = chains.split(',').map(s=>s.trim()).filter(Boolean);
18245
+ const INPUTS = addresses.split(',').map(s => s.trim()).filter(Boolean);
18246
+ const CHAINS = chains.split(',').map(s => s.trim()).filter(Boolean);
18123
18247
 
18124
18248
  const ADDRESS_MAP = {};
18125
18249
  for (const inp of INPUTS) {
@@ -18133,10 +18257,16 @@ async function EOA() {
18133
18257
  }
18134
18258
  }
18135
18259
  const ADDRS = Object.keys(ADDRESS_MAP);
18260
+ console.log('ADDRS', ADDRS);
18136
18261
  const out = [];
18137
18262
 
18138
18263
  async function fetchJSON(url) {
18139
- const res = await fetch(url);
18264
+ const { URL: finalUrl, HEADERS } = getUrlAndHeaders({ url, serviceName: 'Etherscan', headers: {} });
18265
+ console.log('finalUrl', finalUrl, HEADERS);
18266
+ const res = await fetch(finalUrl, {
18267
+ method: 'GET',
18268
+ headers: HEADERS,
18269
+ });
18140
18270
  if (!res.ok) throw new NetworkError(SERVICES_API_KEY.Etherscan, res.status)
18141
18271
  const json = await res.json();
18142
18272
 
@@ -18154,15 +18284,15 @@ async function EOA() {
18154
18284
 
18155
18285
  if (category === 'balance') {
18156
18286
  // chunk 20
18157
- for (let i=0; i<ADDRS.length; i+=20) {
18158
- const slice = ADDRS.slice(i,i+20).join(',');
18287
+ for (let i = 0; i < ADDRS.length; i += 20) {
18288
+ const slice = ADDRS.slice(i, i + 20).join(',');
18159
18289
  const url =
18160
- `https://api.etherscan.io/v2/api?chainid=${chainId}`+
18161
- `&module=account&action=addresstokenbalance&address=${slice}`+
18290
+ `https://api.etherscan.io/v2/api?chainid=${chainId}` +
18291
+ `&module=account&action=addresstokenbalance&address=${slice}` +
18162
18292
  `&page=${page}&offset=${offset}&apikey=${apiKey}`;
18163
18293
  const data = await fetchJSON(url);
18164
18294
  if (!Array.isArray(data)) return data
18165
- data.forEach((item, idx) => out.push({ chain, address: ADDRS[i+idx], name: ADDRESS_MAP[ADDRS[i+idx]], ...item }));
18295
+ data.forEach((item, idx) => out.push({ chain, address: ADDRS[i + idx], name: ADDRESS_MAP[ADDRS[i + idx]], ...item }));
18166
18296
  }
18167
18297
  } else {
18168
18298
  // txns
@@ -18172,9 +18302,9 @@ async function EOA() {
18172
18302
  if (!eb) throw new ValidationError(`Invalid endTime: ${endTime}`)
18173
18303
  for (const addr of ADDRS) {
18174
18304
  const url =
18175
- `https://api.etherscan.io/v2/api?chainid=${chainId}`+
18176
- `&module=account&action=tokentx&address=${addr}`+
18177
- `&startblock=${sb}&endblock=${eb}`+
18305
+ `https://api.etherscan.io/v2/api?chainid=${chainId}` +
18306
+ `&module=account&action=tokentx&address=${addr}` +
18307
+ `&startblock=${sb}&endblock=${eb}` +
18178
18308
  `&page=${page}&offset=${offset}&sort=asc&apikey=${apiKey}`;
18179
18309
  const data = await fetchJSON(url);
18180
18310
  if (!Array.isArray(data)) return data
@@ -18249,20 +18379,20 @@ async function DEFILLAMA() {
18249
18379
 
18250
18380
  switch (category) {
18251
18381
  case 'protocols':
18252
- json = Array.isArray(json) ? json.slice(0,500) : [];
18382
+ json = Array.isArray(json) ? json.slice(0, 500) : [];
18253
18383
  break
18254
18384
  case 'yields':
18255
- json = Array.isArray(json.data) ? json.data.slice(0,500) : [];
18385
+ json = Array.isArray(json.data) ? json.data.slice(0, 500) : [];
18256
18386
  break
18257
18387
  case 'dex':
18258
18388
  case 'fees':
18259
- json = Array.isArray(json.protocols) ? json.protocols.slice(0,500) : [];
18389
+ json = Array.isArray(json.protocols) ? json.protocols.slice(0, 500) : [];
18260
18390
  break
18261
18391
  }
18262
18392
 
18263
18393
  return (Array.isArray(json) ? json : [json]).map(item => {
18264
18394
  const out = {};
18265
- for (const [k,v] of Object.entries(item)) {
18395
+ for (const [k, v] of Object.entries(item)) {
18266
18396
  if (v === null || typeof v !== 'object') out[k] = v;
18267
18397
  }
18268
18398
  return out
@@ -18298,7 +18428,7 @@ async function UNISWAP() {
18298
18428
  // flatten nested
18299
18429
  return json.map(item => {
18300
18430
  const flat = {};
18301
- Object.entries(item).forEach(([k,v]) => {
18431
+ Object.entries(item).forEach(([k, v]) => {
18302
18432
  if (v === null || typeof v !== 'object') flat[k] = v;
18303
18433
  });
18304
18434
  return flat
@@ -286,14 +286,14 @@ If "derivatives": exchange name (e.g., "binance_futures", "hyperliquid", "weex-f
286
286
  {
287
287
  name: "page",
288
288
  detail: "Page number for paginated transaction results. Applies only to 'txns', 'token-txns', and 'nft-txns'.",
289
- example: `1`,
289
+ example: `"1"`,
290
290
  require: "o",
291
291
  type: "number"
292
292
  },
293
293
  {
294
294
  name: "offset",
295
295
  detail: "Number of results per page (limit). Applies only to 'txns', 'token-txns', and 'nft-txns'.",
296
- example: `50`,
296
+ example: `"50"`,
297
297
  require: "o",
298
298
  type: "number"
299
299
  }