@fileverse-dev/formulajs 4.4.11-mod-22-patch-5 → 4.4.11-mod-23-patch-1

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
@@ -13101,13 +13101,20 @@ const ERROR_MESSAGES_FLAG = {
13101
13101
  INVALID_API_KEY: '_INVALID_KEY',
13102
13102
  RATE_LIMIT: '_RATE_LIMIT_REACHED',
13103
13103
  DEFAULT: 'FETCH_ERROR',
13104
- MISSING_KEY: '_MISSING'
13104
+ MISSING_KEY: '_MISSING',
13105
+ INVALID_CHAIN: '_INVALID_CHAIN',
13106
+ INVALID_TYPE: '_INVALID_TYPE',
13107
+ INVALID_ADDRESS: '_INVALID_ADDRESS',
13108
+ INVALID_PARAM: '_INVALID_PARAM'
13105
13109
  };
13106
13110
 
13107
13111
  const SERVICE_API_KEY = {
13108
13112
  Etherscan: "ETHERSCAN_API_KEY",
13109
13113
  Coingecko: "COINGECKO_API_KEY",
13110
13114
  Safe: "SAFE_API_KEY",
13115
+ Basescan: "BASESCAN_API_KEY",
13116
+ Gnosisscan: "GNOSIS_API_KEY",
13117
+ Firefly: "FIRE_FLY_API_KEY"
13111
13118
  };
13112
13119
 
13113
13120
  const fromTimeStampToBlock = async (timestamp, chain, apiKey) => {
@@ -13120,6 +13127,131 @@ if(!timestamp || !chain || !apiKey) return
13120
13127
 
13121
13128
  };
13122
13129
 
13130
+ async function handleScanRequest({
13131
+ scanKey,
13132
+ baseUrl,
13133
+ type,
13134
+ chain,
13135
+ address,
13136
+ startDate,
13137
+ endDate,
13138
+ }) {
13139
+ const API_KEY = window.localStorage.getItem(scanKey);
13140
+ if (!API_KEY) return `${scanKey}${ERROR_MESSAGES_FLAG.MISSING_KEY}`;
13141
+ if (API_KEY === 'xxxx') return `${scanKey}${ERROR_MESSAGES_FLAG.RATE_LIMIT}`;
13142
+
13143
+ const chainId = CHAIN_ID_MAP[chain?.toLowerCase()];
13144
+ if (!chainId) return `${scanKey}${ERROR_MESSAGES_FLAG.INVALID_CHAIN}`;
13145
+
13146
+ const ACTION_MAP = {
13147
+ 'all-txns': 'txlist',
13148
+ 'token-txns': 'tokentx',
13149
+ 'nft-txns': 'tokennfttx',
13150
+ 'gas': 'gastracker',
13151
+ };
13152
+
13153
+ const action = ACTION_MAP[type];
13154
+ if (!action) return `${scanKey}${ERROR_MESSAGES_FLAG.INVALID_TYPE}`;
13155
+
13156
+ let url = `${baseUrl}?chainid=${chainId}&module=account&action=${action}&apikey=${API_KEY}`;
13157
+
13158
+ if (['all-txns', 'token-txns', 'nft-txns'].includes(type)) {
13159
+ if (!address) return `${scanKey}${ERROR_MESSAGES_FLAG.INVALID_ADDRESS}`;
13160
+ url += `&address=${address}&startblock=0&endblock=99999999&sort=asc`;
13161
+
13162
+ if (!isNaN(startDate) && !isNaN(endDate)) {
13163
+ const [startBlock, endBlock] = await Promise.all([
13164
+ fromTimeStampToBlock(startDate, chain, API_KEY),
13165
+ fromTimeStampToBlock(endDate, chain, API_KEY),
13166
+ ]);
13167
+ url += `&startblock=${startBlock}&endblock=${endBlock}`;
13168
+ }
13169
+ }
13170
+
13171
+ try {
13172
+ const res = await fetch(url);
13173
+ if (!res.ok) throw new Error(`HTTP error: ${res.status}`);
13174
+ const json = await res.json();
13175
+
13176
+ if (typeof json.result === 'string') {
13177
+ if (json.result.includes('Invalid API Key')) return `${scanKey}${ERROR_MESSAGES_FLAG.INVALID_API_KEY}`;
13178
+ if (json.result.includes('Max rate limit reached')) return `${scanKey}${ERROR_MESSAGES_FLAG.RATE_LIMIT}`;
13179
+ }
13180
+
13181
+ return json.result;
13182
+ } catch (err) {
13183
+ console.error(`[${scanKey}]`, err);
13184
+ return ERROR_MESSAGES_FLAG.DEFAULT;
13185
+ }
13186
+ }
13187
+
13188
+ async function FIREFLY(platform, contentType, identifier) {
13189
+ const API_KEY = window.localStorage.getItem(SERVICE_API_KEY.Firefly);
13190
+ if (!API_KEY) return `${SERVICE_API_KEY.Firefly}${ERROR_MESSAGES_FLAG.MISSING_KEY}`;
13191
+
13192
+ const baseUrl = "https://openapi.firefly.land/v1/fileverse/fetch";
13193
+ const headers = {
13194
+ "x-api-key": API_KEY,
13195
+ };
13196
+
13197
+ let query = "";
13198
+ let type = "";
13199
+
13200
+ // normalize input
13201
+ const normalizedId = identifier.trim().replace(/.*\/([^\/]+)$/, "$1"); // extract last part of URL if needed
13202
+
13203
+ if (platform === "farcaster") {
13204
+ if (contentType === "posts") {
13205
+ type = "farcasterid";
13206
+ query = normalizedId;
13207
+ } else if (contentType === "replies") {
13208
+ type = "farcasterpostid";
13209
+ query = normalizedId.startsWith("0x") ? normalizedId : Number(normalizedId).toString();
13210
+ } else {
13211
+ return `${SERVICE_API_KEY.Firefly}${ERROR_MESSAGES_FLAG.INVALID_TYPE}`;
13212
+ }
13213
+ } else if (platform === "lens") {
13214
+ if (contentType === "posts") {
13215
+ type = "lensid";
13216
+ query = normalizedId;
13217
+ } else if (contentType === "replies") {
13218
+ type = "lenspostid";
13219
+ query = normalizedId;
13220
+ } else {
13221
+ return `${SERVICE_API_KEY.Firefly}${ERROR_MESSAGES_FLAG.INVALID_TYPE}`;
13222
+ }
13223
+ } else {
13224
+ return `${SERVICE_API_KEY.Firefly}${ERROR_MESSAGES_FLAG.INVALID_PARAM}`;
13225
+ }
13226
+
13227
+ const url = new URL(baseUrl);
13228
+ url.searchParams.set("query", query);
13229
+ url.searchParams.set("type", type);
13230
+ url.searchParams.set("size", "10");
13231
+ url.searchParams.set("cursor", "0");
13232
+
13233
+ try {
13234
+ const res = await fetch(url.toString(), { headers });
13235
+ if (!res.ok) throw new Error(`HTTP ${res.status}`);
13236
+ const json = await res.json();
13237
+ const flattened = Array.isArray(json?.data)
13238
+ ? json.data.map(item => ({
13239
+ id: item?.id || null,
13240
+ author: item?.author?.username || item?.author?.handle || "",
13241
+ text: item?.text || item?.metadata?.content?.content || "",
13242
+ createdAt: item?.createdAt || "",
13243
+ platform: platform,
13244
+ }))
13245
+ : [];
13246
+
13247
+ return flattened;
13248
+ } catch (err) {
13249
+ console.error("FIREFLY fetch error:", err);
13250
+ return ERROR_MESSAGES_FLAG.DEFAULT;
13251
+ }
13252
+ }
13253
+
13254
+
13123
13255
  async function BLOCKSCOUT(address, type, chain, startTimestamp, endTimestamp, page, offset) {
13124
13256
  if (!chain) {
13125
13257
  chain = 'ethereum';
@@ -13189,38 +13321,146 @@ async function BLOCKSCOUT(address, type, chain, startTimestamp, endTimestamp, pa
13189
13321
  }
13190
13322
  }
13191
13323
 
13192
- async function ETHERSCAN(address, page, offset) {
13193
- const API_KEY = window.localStorage.getItem(SERVICE_API_KEY.Etherscan);
13194
- if(!API_KEY){
13195
- return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.MISSING_KEY}`
13324
+ async function BASESCAN(...args) {
13325
+ const [type, chain, address, startDate, endDate] = args;
13326
+ return handleScanRequest({
13327
+ scanKey: SERVICE_API_KEY.Basescan,
13328
+ baseUrl: 'https://api.basescan.org/api',
13329
+ type,
13330
+ chain,
13331
+ address,
13332
+ startDate,
13333
+ endDate,
13334
+ });
13335
+ }
13336
+ async function GNOSISSCAN(...args) {
13337
+ const [type, chain, address, startDate, endDate] = args;
13338
+ return handleScanRequest({
13339
+ scanKey: SERVICE_API_KEY.Gnosisscan,
13340
+ baseUrl: 'https://api.gnosisscan.io/api',
13341
+ type,
13342
+ chain,
13343
+ address,
13344
+ startDate,
13345
+ endDate,
13346
+ });
13347
+ }
13348
+
13349
+ async function NEYNAR(
13350
+ fid,
13351
+ viewerFid,
13352
+ sortType,
13353
+ limit,
13354
+ cursor
13355
+ ) {
13356
+ const API_KEY = window.localStorage.getItem(SERVICE_API_KEY.Neynar);
13357
+ if (!API_KEY) return `${SERVICE_API_KEY.Neynar}${ERROR_MESSAGES_FLAG.MISSING_KEY}`;
13358
+
13359
+
13360
+ const url = new URL('https://api.neynar.com/v2/farcaster/followers');
13361
+ url.searchParams.set('fid', fid.toString());
13362
+ url.searchParams.set('sort_type', sortType);
13363
+ url.searchParams.set('limit', limit.toString());
13364
+ if (viewerFid !== null) url.searchParams.set('viewer_fid', viewerFid.toString());
13365
+ if (cursor) url.searchParams.set('cursor', cursor);
13366
+
13367
+ try {
13368
+ const response = await fetch(url.toString(), {
13369
+ headers: {
13370
+ 'x-api-key': API_KEY,
13371
+ 'x-neynar-experimental': 'false'
13372
+ }
13373
+ });
13374
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
13375
+ const json = await response.json();
13376
+ if (!json?.users?.length) return [];
13377
+
13378
+ return json.users.map(({ user }) => ({
13379
+ username: user.username,
13380
+ custody_address: user.custody_address,
13381
+ follower_count: user.follower_count,
13382
+ country: user.profile?.location?.address?.country || '',
13383
+ city: user.profile?.location?.address?.city || ''
13384
+ }));
13385
+ } catch (err) {
13386
+ console.error('NEYNAR_FETCH_FOLLOWERS error:', err);
13387
+ return ERROR_MESSAGES_FLAG.DEFAULT;
13196
13388
  }
13197
- // temporary added for testing rate limit flow
13198
- if(API_KEY === 'xxxx'){
13199
- return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.RATE_LIMIT}`
13389
+ }
13390
+ async function GNOSIS({
13391
+ cardId,
13392
+ startDate,
13393
+ endDate,
13394
+ limit = 20,
13395
+ offset = 0,
13396
+ }) {
13397
+ const apiKeyKey = SERVICE_API_KEY.GnosisPay;
13398
+ const API_KEY = window.localStorage.getItem(apiKeyKey);
13399
+ if (!API_KEY) return `${apiKeyKey}${ERROR_MESSAGES_FLAG.MISSING_KEY}`;
13400
+ if (!cardId) return `${apiKeyKey}${ERROR_MESSAGES_FLAG.INVALID_PARAM}`;
13401
+
13402
+ const url = new URL(`https://api.gnosispay.com/cards/${cardId}/transactions`);
13403
+ url.searchParams.set('limit', limit.toString());
13404
+ url.searchParams.set('offset', offset.toString());
13405
+
13406
+ if (!isNaN(startDate)) {
13407
+ url.searchParams.set('startDate', new Date(startDate * 1000).toISOString());
13408
+ }
13409
+
13410
+ if (!isNaN(endDate)) {
13411
+ url.searchParams.set('endDate', new Date(endDate * 1000).toISOString());
13200
13412
  }
13201
- const url = `https://api.etherscan.io/v2/api?chainid=1&module=account&action=txlist&address=${address}&startblock=0&endblock=99999999&page=${page || 1}&offset=${offset || 10}&sort=asc&apikey=${API_KEY}`;
13202
13413
 
13203
13414
  try {
13204
- const response = await fetch(url);
13205
- if (!response.ok) {
13206
- throw new Error(`HTTP error! Status: ${response.status}`)
13207
- }
13208
- const json = await response.json();
13209
- if (json.result.includes("Invalid API Key")) {
13210
- return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.INVALID_API_KEY}`
13211
- }
13212
- if(json.result.includes('Max rate limit reached')){
13213
- return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.RATE_LIMIT}`
13214
- }
13215
- /*
13216
- [{blockNumber: '0x1d3d1', timeStamp: '0x5f7e4f', hash: '0x3c3c3c3c', nonce: '0x1',}]
13217
- */
13218
- return json.result;
13219
- } catch (error) {
13220
- return ERROR_MESSAGES_FLAG.DEFAULT
13415
+ const res = await fetch(url.toString(), {
13416
+ headers: {
13417
+ Authorization: `Bearer ${API_KEY}`,
13418
+ 'Content-Type': 'application/json',
13419
+ },
13420
+ });
13421
+
13422
+ if (!res.ok) throw new Error(`HTTP error! Status: ${res.status}`);
13423
+
13424
+ const json = await res.json();
13425
+
13426
+ if (!Array.isArray(json)) return [];
13427
+
13428
+ return json.map(tx => ({
13429
+ createdAt: tx.createdAt,
13430
+ clearedAt: tx.clearedAt,
13431
+ country: tx.country,
13432
+ merchant: tx.merchant,
13433
+ billingAmount: tx.billingAmount,
13434
+ billingCurrency: tx.billingCurrency,
13435
+ transactionAmount: tx.transactionAmount,
13436
+ transactionCurrency: tx.transactionCurrency,
13437
+ transactionType: tx.transactionType,
13438
+ kind: tx.kind,
13439
+ status: tx.status || null,
13440
+ mcc: tx.mcc,
13441
+ }));
13442
+ } catch (err) {
13443
+ console.error('GNOSISPAY_CARD_TXNS error:', err);
13444
+ return ERROR_MESSAGES_FLAG.DEFAULT;
13221
13445
  }
13222
13446
  }
13223
13447
 
13448
+
13449
+
13450
+ async function ETHERSCAN(...args) {
13451
+ const [type, chain, address, startDate, endDate] = args;
13452
+ return handleScanRequest({
13453
+ scanKey: SERVICE_API_KEY.Etherscan,
13454
+ baseUrl: 'https://api.etherscan.io/v2/api',
13455
+ type,
13456
+ chain,
13457
+ address,
13458
+ startDate,
13459
+ endDate,
13460
+ });
13461
+ }
13462
+
13463
+
13224
13464
  async function COINGECKO(token, vs_currencies) {
13225
13465
  const API_KEY = window.localStorage.getItem(SERVICE_API_KEY.Coingecko);
13226
13466
  const url = `https://api.coingecko.com/api/v3/simple/price?vs_currencies=${vs_currencies}&ids=${token}`;
@@ -13257,50 +13497,76 @@ async function COINGECKO(token, vs_currencies) {
13257
13497
  */
13258
13498
  return [output];
13259
13499
  } catch (error) {
13500
+ console.log(error);
13260
13501
  return ERROR_MESSAGES_FLAG.DEFAULT
13261
13502
  }
13262
13503
  }
13263
13504
 
13264
- async function EOA(address, categories, chain, startTime, endTime) {
13265
- const API_KEYS = {
13266
- ethereum: window.localStorage.getItem(SERVICE_API_KEY.Etherscan),
13267
- gnosis: window.localStorage.getItem(SERVICE_API_KEY.Gnosisscan),
13268
- base: window.localStorage.getItem(SERVICE_API_KEY.Basescan),
13269
- };
13270
- const apiKey = API_KEYS[chain];
13271
- const chainId = CHAIN_ID_MAP[chain];
13272
- if (!apiKey || !chainId) return `${chain.toUpperCase()}_MISSING`;
13273
-
13274
- let action = '';
13275
- if (categories === 'txns') action = 'account.txlist';
13276
- else { action = 'account.balance'; } let timeQuery = '';
13277
- if (!isNaN(startTime) && !isNaN(endTime)) {
13278
- const startBlock = await fromTimeStampToBlock(startTime, chain, apiKey);
13279
- const endBlock = await fromTimeStampToBlock(endTime, chain, apiKey);
13280
- timeQuery = `&startblock=${startBlock}&endblock=${endBlock}`;
13281
- } else if (categories === 'balance') {
13282
- timeQuery = `&tag=latest`;
13283
- } else {
13284
- throw new Error('Start and End Time is required for querying transaction list ')
13285
- }
13286
- const url = `https://api.etherscan.io/v2/api?module=${action.split('.')[0]}&action=${action.split('.')[1]}&address=${address}&sort=asc&chainid=${chainId}&apikey=${apiKey}${timeQuery}`;
13505
+ async function EOA(addresses, category, chains, startTime, endTime) {
13287
13506
  try {
13288
- const response = await fetch(url);
13289
- if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
13290
- const json = await response.json();
13291
- if (json.result?.includes?.("Invalid API Key")) {
13292
- return `${SERVICE_API_KEY[chain.charAt(0).toUpperCase() + chain.slice(1)]}_MISSING`;
13293
- }
13294
- if(json.result.includes('Max rate limit reached')){
13295
- return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.RATE_LIMIT}`
13507
+ const ADDRESSES = addresses.split(',').map(a => a.trim());
13508
+ const CHAINS = typeof chains === 'string' ? chains.split(',').map(c => c.trim()) : chains;
13509
+
13510
+ const flatResults = [];
13511
+ const API_KEY = window.localStorage.getItem(SERVICE_API_KEY.Etherscan);
13512
+
13513
+ if (!API_KEY) return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.MISSING_KEY}`;
13514
+
13515
+ for (const chain of CHAINS) {
13516
+ const chainId = CHAIN_ID_MAP[chain];
13517
+ if (!chainId) throw new Error('Unsupported chain');
13518
+
13519
+ for (const address of ADDRESSES) {
13520
+ let action = category === 'txns' ? 'account.txlist' : 'account.balance';
13521
+ let timeQuery = '';
13522
+
13523
+ if (category === 'txns') {
13524
+ const startBlock = await fromTimeStampToBlock(startTime, chain, API_KEY);
13525
+ const endBlock = await fromTimeStampToBlock(endTime, chain, API_KEY);
13526
+ timeQuery = `&startblock=${startBlock}&endblock=${endBlock}`;
13527
+ } else {
13528
+ timeQuery = `&tag=latest`;
13529
+ }
13530
+
13531
+ const url = `https://api.etherscan.io/v2/api?module=${action.split('.')[0]}&action=${action.split('.')[1]}&address=${address}&sort=asc&chainid=${chainId}&apikey=${API_KEY}${timeQuery}`;
13532
+
13533
+ try {
13534
+ const response = await fetch(url);
13535
+ if (!response.ok) {
13536
+ return `HTTP_${response.status}`;
13537
+ }
13538
+
13539
+ const json = await response.json();
13540
+
13541
+ if (json.result?.includes?.('Invalid API Key')) {
13542
+ return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.INVALID_API_KEY}`;
13543
+ }
13544
+
13545
+ if (json.result?.includes?.('Max rate limit reached')) {
13546
+ return `${SERVICE_API_KEY.Etherscan}${ERROR_MESSAGES_FLAG.RATE_LIMIT}`;
13547
+ }
13548
+
13549
+ const entries = Array.isArray(json.result) ? json.result : [json.result];
13550
+ for (const entry of entries) {
13551
+ flatResults.push({ chain, address, ...entry });
13552
+ }
13553
+
13554
+ } catch (e) {
13555
+ return ERROR_MESSAGES_FLAG.DEFAULT;
13556
+ }
13557
+ }
13296
13558
  }
13297
- return json.result;
13298
- } catch (e) {
13299
- console.log(e);
13559
+
13560
+ return flatResults;
13561
+ } catch (error) {
13562
+ console.log(error);
13300
13563
  return ERROR_MESSAGES_FLAG.DEFAULT;
13301
13564
  }
13302
13565
  }
13303
13566
 
13567
+
13568
+
13569
+
13304
13570
  async function FLVURL(token, vs_currencies) {
13305
13571
  return new Promise((resolve) => {
13306
13572
  setTimeout(() => {
@@ -13365,6 +13631,7 @@ exports.AVERAGEA = AVERAGEA;
13365
13631
  exports.AVERAGEIF = AVERAGEIF;
13366
13632
  exports.AVERAGEIFS = AVERAGEIFS;
13367
13633
  exports.BASE = BASE;
13634
+ exports.BASESCAN = BASESCAN;
13368
13635
  exports.BESSELI = BESSELI;
13369
13636
  exports.BESSELJ = BESSELJ;
13370
13637
  exports.BESSELK = BESSELK;
@@ -13481,6 +13748,7 @@ exports.FDISTRT = FDISTRT;
13481
13748
  exports.FIND = FIND;
13482
13749
  exports.FINV = FINV;
13483
13750
  exports.FINVRT = FINVRT;
13751
+ exports.FIREFLY = FIREFLY;
13484
13752
  exports.FISHER = FISHER;
13485
13753
  exports.FISHERINV = FISHERINV;
13486
13754
  exports.FIXED = FIXED;
@@ -13502,6 +13770,8 @@ exports.GAUSS = GAUSS;
13502
13770
  exports.GCD = GCD;
13503
13771
  exports.GEOMEAN = GEOMEAN;
13504
13772
  exports.GESTEP = GESTEP;
13773
+ exports.GNOSIS = GNOSIS;
13774
+ exports.GNOSISSCAN = GNOSISSCAN;
13505
13775
  exports.GROWTH = GROWTH;
13506
13776
  exports.HARMEAN = HARMEAN;
13507
13777
  exports.HEX2BIN = HEX2BIN;
@@ -13602,6 +13872,7 @@ exports.NEGBINOMDIST = NEGBINOMDIST;
13602
13872
  exports.NETWORKDAYS = NETWORKDAYS;
13603
13873
  exports.NETWORKDAYSINTL = NETWORKDAYSINTL;
13604
13874
  exports.NETWORKDAYS_INTL = NETWORKDAYS_INTL;
13875
+ exports.NEYNAR = NEYNAR;
13605
13876
  exports.NOMINAL = NOMINAL;
13606
13877
  exports.NORM = NORM;
13607
13878
  exports.NORMDIST = NORMDIST;