crypull 1.0.0

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/dist/index.js ADDED
@@ -0,0 +1,711 @@
1
+ 'use strict';
2
+
3
+ // src/providers/coingecko.ts
4
+ var CoinGeckoProvider = class {
5
+ name = "CoinGecko";
6
+ baseUrl = "https://api.coingecko.com/api/v3";
7
+ async search(query) {
8
+ try {
9
+ const res = await fetch(`${this.baseUrl}/search?query=${query}`);
10
+ if (!res.ok) return [];
11
+ const data = await res.json();
12
+ return (data.coins || []).slice(0, 10).map((coin) => ({
13
+ id: coin.id,
14
+ name: coin.name,
15
+ symbol: coin.symbol.toUpperCase(),
16
+ source: this.name
17
+ }));
18
+ } catch (e) {
19
+ return [];
20
+ }
21
+ }
22
+ async getPrice(symbolOrId) {
23
+ try {
24
+ let id = symbolOrId.toLowerCase();
25
+ const searchRes = await this.search(id);
26
+ const match = searchRes.find((s) => s.symbol.toLowerCase() === id || s.id === id);
27
+ if (match && match.id) {
28
+ id = match.id;
29
+ }
30
+ const res = await fetch(`${this.baseUrl}/simple/price?ids=${id}&vs_currencies=usd`);
31
+ if (!res.ok) return null;
32
+ const data = await res.json();
33
+ if (!data[id] || typeof data[id].usd === "undefined") return null;
34
+ return {
35
+ symbol: match ? match.symbol : id.toUpperCase(),
36
+ priceUsd: data[id].usd,
37
+ source: this.name,
38
+ lastUpdated: Date.now()
39
+ };
40
+ } catch (e) {
41
+ return null;
42
+ }
43
+ }
44
+ async getTokenInfo(id) {
45
+ try {
46
+ const res = await fetch(`${this.baseUrl}/coins/${id.toLowerCase()}?localization=false&tickers=false&market_data=true&community_data=false&developer_data=false&sparkline=false`);
47
+ if (!res.ok) return null;
48
+ const data = await res.json();
49
+ if (data.error) return null;
50
+ return {
51
+ name: data.name,
52
+ symbol: data.symbol.toUpperCase(),
53
+ description: data.description?.en,
54
+ priceUsd: data.market_data?.current_price?.usd || 0,
55
+ marketCap: data.market_data?.market_cap?.usd,
56
+ marketCapRank: data.market_cap_rank,
57
+ fdv: data.market_data?.fully_diluted_valuation?.usd,
58
+ circulatingSupply: data.market_data?.circulating_supply,
59
+ totalSupply: data.market_data?.total_supply,
60
+ maxSupply: data.market_data?.max_supply,
61
+ volume24h: data.market_data?.total_volume?.usd,
62
+ priceChange24h: data.market_data?.price_change_24h,
63
+ priceChangePercentage24h: data.market_data?.price_change_percentage_24h,
64
+ priceChangePercentage7d: data.market_data?.price_change_percentage_7d,
65
+ ath: data.market_data?.ath?.usd,
66
+ athDate: data.market_data?.ath_date?.usd,
67
+ atl: data.market_data?.atl?.usd,
68
+ atlDate: data.market_data?.atl_date?.usd,
69
+ links: {
70
+ website: data.links?.homepage?.[0],
71
+ twitter: data.links?.twitter_screen_name ? `https://twitter.com/${data.links.twitter_screen_name}` : void 0,
72
+ telegram: data.links?.telegram_channel_identifier ? `https://t.me/${data.links.telegram_channel_identifier}` : void 0,
73
+ discord: data.links?.chat_url?.find((url) => url.includes("discord")),
74
+ github: data.links?.repos_url?.github?.[0]
75
+ },
76
+ source: this.name,
77
+ lastUpdated: Date.now()
78
+ };
79
+ } catch (e) {
80
+ return null;
81
+ }
82
+ }
83
+ };
84
+
85
+ // src/providers/dexscreener.ts
86
+ var DexScreenerProvider = class {
87
+ name = "DexScreener";
88
+ baseUrl = "https://api.dexscreener.com/latest/dex";
89
+ async search(query) {
90
+ try {
91
+ const res = await fetch(`${this.baseUrl}/search?q=${query}`);
92
+ if (!res.ok) return [];
93
+ const data = await res.json();
94
+ return (data.pairs || []).slice(0, 10).map((pair) => ({
95
+ id: pair.baseToken.address,
96
+ name: pair.baseToken.name,
97
+ symbol: pair.baseToken.symbol.toUpperCase(),
98
+ network: pair.chainId,
99
+ source: this.name
100
+ }));
101
+ } catch (e) {
102
+ return [];
103
+ }
104
+ }
105
+ async getPrice(address) {
106
+ const info = await this.getTokenInfo(address);
107
+ if (!info) return null;
108
+ return {
109
+ symbol: info.symbol,
110
+ priceUsd: info.priceUsd,
111
+ source: this.name,
112
+ lastUpdated: info.lastUpdated
113
+ };
114
+ }
115
+ async getTokenInfo(address) {
116
+ try {
117
+ const res = await fetch(`${this.baseUrl}/tokens/${address}`);
118
+ if (!res.ok) return null;
119
+ const data = await res.json();
120
+ if (!data.pairs || data.pairs.length === 0) return null;
121
+ const pair = data.pairs[0];
122
+ const mappedPairs = data.pairs.slice(0, 10).map((p) => ({
123
+ dexId: p.dexId,
124
+ url: p.url,
125
+ pairAddress: p.pairAddress,
126
+ baseTokenSymbol: p.baseToken.symbol,
127
+ quoteTokenSymbol: p.quoteToken.symbol,
128
+ priceUsd: parseFloat(p.priceUsd) || 0,
129
+ volume24h: p.volume?.h24,
130
+ liquidityUsd: p.liquidity?.usd
131
+ }));
132
+ return {
133
+ name: pair.baseToken.name,
134
+ symbol: pair.baseToken.symbol.toUpperCase(),
135
+ address: pair.baseToken.address,
136
+ network: pair.chainId,
137
+ priceUsd: parseFloat(pair.priceUsd) || 0,
138
+ fdv: pair.fdv,
139
+ volume24h: pair.volume?.h24,
140
+ liquidityUsd: pair.liquidity?.usd,
141
+ priceChangePercentage24h: pair.priceChange?.h24,
142
+ pairs: mappedPairs,
143
+ links: {
144
+ website: pair.info?.websites?.[0]?.url,
145
+ twitter: pair.info?.socials?.find((s) => s.type === "twitter")?.url,
146
+ telegram: pair.info?.socials?.find((s) => s.type === "telegram")?.url,
147
+ discord: pair.info?.socials?.find((s) => s.type === "discord")?.url
148
+ },
149
+ source: this.name,
150
+ lastUpdated: Date.now()
151
+ };
152
+ } catch (e) {
153
+ return null;
154
+ }
155
+ }
156
+ };
157
+
158
+ // src/providers/geckoterminal.ts
159
+ var GeckoTerminalProvider = class {
160
+ name = "GeckoTerminal";
161
+ baseUrl = "https://api.geckoterminal.com/api/v2";
162
+ async search(query) {
163
+ try {
164
+ const res = await fetch(`${this.baseUrl}/search/pools?query=${query}`);
165
+ if (!res.ok) return [];
166
+ const data = await res.json();
167
+ const pools = data.data || [];
168
+ return pools.slice(0, 10).map((pool) => {
169
+ const attributes = pool.attributes;
170
+ const baseToken = attributes.name.split(" / ")[0];
171
+ return {
172
+ id: pool.id,
173
+ // e.g. "eth_0x..."
174
+ name: attributes.name,
175
+ symbol: baseToken,
176
+ network: pool.relationships.network.data.id,
177
+ source: this.name
178
+ };
179
+ });
180
+ } catch (e) {
181
+ return [];
182
+ }
183
+ }
184
+ async getPrice(address, network = "eth") {
185
+ const info = await this.getTokenInfo(address, network);
186
+ if (!info) return null;
187
+ return {
188
+ symbol: info.symbol,
189
+ priceUsd: info.priceUsd,
190
+ source: this.name,
191
+ lastUpdated: info.lastUpdated
192
+ };
193
+ }
194
+ async getTokenInfo(address, network = "eth") {
195
+ try {
196
+ const res = await fetch(`${this.baseUrl}/networks/${network}/tokens/${address}`);
197
+ if (!res.ok) return null;
198
+ const json = await res.json();
199
+ if (!json.data || !json.data.attributes) return null;
200
+ const attrs = json.data.attributes;
201
+ return {
202
+ name: attrs.name,
203
+ symbol: attrs.symbol.toUpperCase(),
204
+ address: attrs.address,
205
+ network,
206
+ priceUsd: parseFloat(attrs.price_usd) || 0,
207
+ fdv: parseFloat(attrs.fdv_usd),
208
+ volume24h: parseFloat(attrs.volume_usd?.h24 || 0),
209
+ source: this.name,
210
+ lastUpdated: Date.now()
211
+ };
212
+ } catch (e) {
213
+ return null;
214
+ }
215
+ }
216
+ };
217
+
218
+ // src/providers/binance.ts
219
+ var BinanceProvider = class {
220
+ name = "Binance";
221
+ baseUrl = "https://api.binance.com/api/v3";
222
+ async search(query) {
223
+ try {
224
+ const symbol = query.toUpperCase();
225
+ const res = await fetch(`${this.baseUrl}/ticker/price?symbol=${symbol}USDT`);
226
+ if (res.ok) {
227
+ return [{
228
+ id: `${symbol}USDT`,
229
+ name: symbol,
230
+ symbol,
231
+ source: this.name
232
+ }];
233
+ }
234
+ return [];
235
+ } catch (e) {
236
+ return [];
237
+ }
238
+ }
239
+ async getPrice(symbol) {
240
+ try {
241
+ let querySymbol = symbol.toUpperCase();
242
+ if (!querySymbol.endsWith("USDT") && !querySymbol.endsWith("BUSD") && !querySymbol.endsWith("BTC")) {
243
+ querySymbol += "USDT";
244
+ }
245
+ const res = await fetch(`${this.baseUrl}/ticker/price?symbol=${querySymbol}`);
246
+ if (!res.ok) return null;
247
+ const data = await res.json();
248
+ return {
249
+ symbol: symbol.toUpperCase(),
250
+ priceUsd: parseFloat(data.price) || 0,
251
+ source: this.name,
252
+ lastUpdated: Date.now()
253
+ };
254
+ } catch (e) {
255
+ return null;
256
+ }
257
+ }
258
+ async getTokenInfo(symbol) {
259
+ try {
260
+ let querySymbol = symbol.toUpperCase();
261
+ if (!querySymbol.endsWith("USDT") && !querySymbol.endsWith("BUSD") && !querySymbol.endsWith("BTC")) {
262
+ querySymbol += "USDT";
263
+ }
264
+ const res = await fetch(`${this.baseUrl}/ticker/24hr?symbol=${querySymbol}`);
265
+ if (!res.ok) return null;
266
+ const data = await res.json();
267
+ return {
268
+ name: symbol.toUpperCase(),
269
+ symbol: symbol.toUpperCase(),
270
+ priceUsd: parseFloat(data.lastPrice) || 0,
271
+ volume24h: parseFloat(data.quoteVolume) || 0,
272
+ // Quote volume in USDT roughly = USD volume
273
+ source: this.name,
274
+ lastUpdated: Date.now()
275
+ };
276
+ } catch (e) {
277
+ return null;
278
+ }
279
+ }
280
+ };
281
+
282
+ // src/providers/coinpaprika.ts
283
+ var CoinpaprikaProvider = class {
284
+ name = "Coinpaprika";
285
+ baseUrl = "https://api.coinpaprika.com/v1";
286
+ async search(query) {
287
+ try {
288
+ const res = await fetch(`${this.baseUrl}/search?q=${query}&c=currencies&limit=10`);
289
+ if (!res.ok) return [];
290
+ const data = await res.json();
291
+ return (data.currencies || []).map((coin) => ({
292
+ id: coin.id,
293
+ name: coin.name,
294
+ symbol: coin.symbol.toUpperCase(),
295
+ source: this.name
296
+ }));
297
+ } catch (e) {
298
+ return [];
299
+ }
300
+ }
301
+ async getPrice(symbolOrId) {
302
+ const info = await this.getTokenInfo(symbolOrId);
303
+ if (!info) return null;
304
+ return {
305
+ symbol: info.symbol,
306
+ priceUsd: info.priceUsd,
307
+ source: this.name,
308
+ lastUpdated: info.lastUpdated
309
+ };
310
+ }
311
+ async getTokenInfo(symbolOrId) {
312
+ try {
313
+ let id = symbolOrId.toLowerCase();
314
+ if (!id.includes("-")) {
315
+ const searchRes = await this.search(id);
316
+ const match = searchRes.find((s) => s.symbol.toLowerCase() === id || s.id === id);
317
+ if (match && match.id) {
318
+ id = match.id;
319
+ } else if (searchRes.length > 0 && searchRes[0].id) {
320
+ id = searchRes[0].id;
321
+ }
322
+ }
323
+ const res = await fetch(`${this.baseUrl}/tickers/${id}`);
324
+ if (!res.ok) return null;
325
+ const data = await res.json();
326
+ return {
327
+ name: data.name,
328
+ symbol: data.symbol.toUpperCase(),
329
+ description: data.description,
330
+ priceUsd: data.quotes?.USD?.price || 0,
331
+ marketCap: data.quotes?.USD?.market_cap,
332
+ marketCapRank: data.rank,
333
+ circulatingSupply: data.circulating_supply,
334
+ totalSupply: data.total_supply,
335
+ maxSupply: data.max_supply,
336
+ volume24h: data.quotes?.USD?.volume_24h,
337
+ priceChangePercentage24h: data.quotes?.USD?.percent_change_24h,
338
+ priceChangePercentage7d: data.quotes?.USD?.percent_change_7d,
339
+ ath: data.quotes?.USD?.ath_price,
340
+ athDate: data.quotes?.USD?.ath_date,
341
+ links: {
342
+ website: data.links?.website?.[0],
343
+ twitter: data.links?.twitter?.[0],
344
+ discord: data.links?.discord?.[0],
345
+ github: data.links?.source_code?.[0]
346
+ },
347
+ source: this.name,
348
+ lastUpdated: Date.now()
349
+ };
350
+ } catch (e) {
351
+ return null;
352
+ }
353
+ }
354
+ };
355
+
356
+ // src/providers/coincap.ts
357
+ var CoinCapProvider = class {
358
+ name = "CoinCap";
359
+ baseUrl = "https://api.coincap.io/v2";
360
+ async search(query) {
361
+ try {
362
+ const res = await fetch(`${this.baseUrl}/assets?search=${query}&limit=10`);
363
+ if (!res.ok) return [];
364
+ const data = await res.json();
365
+ return (data.data || []).map((coin) => ({
366
+ id: coin.id,
367
+ name: coin.name,
368
+ symbol: coin.symbol.toUpperCase(),
369
+ source: this.name
370
+ }));
371
+ } catch (e) {
372
+ return [];
373
+ }
374
+ }
375
+ async getPrice(symbolOrId) {
376
+ const info = await this.getTokenInfo(symbolOrId);
377
+ if (!info) return null;
378
+ return {
379
+ symbol: info.symbol,
380
+ priceUsd: info.priceUsd,
381
+ source: this.name,
382
+ lastUpdated: info.lastUpdated
383
+ };
384
+ }
385
+ async getTokenInfo(symbolOrId) {
386
+ try {
387
+ let id = symbolOrId.toLowerCase();
388
+ const searchRes = await this.search(id);
389
+ const match = searchRes.find((s) => s.symbol.toLowerCase() === id || s.id === id);
390
+ if (match && match.id) {
391
+ id = match.id;
392
+ }
393
+ const res = await fetch(`${this.baseUrl}/assets/${id}`);
394
+ if (!res.ok) return null;
395
+ const data = await res.json();
396
+ const asset = data.data;
397
+ if (!asset) return null;
398
+ return {
399
+ name: asset.name,
400
+ symbol: asset.symbol.toUpperCase(),
401
+ priceUsd: parseFloat(asset.priceUsd) || 0,
402
+ marketCap: parseFloat(asset.marketCapUsd),
403
+ volume24h: parseFloat(asset.volumeUsd24Hr),
404
+ source: this.name,
405
+ lastUpdated: Date.now()
406
+ };
407
+ } catch (e) {
408
+ return null;
409
+ }
410
+ }
411
+ };
412
+
413
+ // src/providers/cryptocompare.ts
414
+ var CryptoCompareProvider = class {
415
+ name = "CryptoCompare";
416
+ baseUrl = "https://min-api.cryptocompare.com/data";
417
+ async search(query) {
418
+ return [];
419
+ }
420
+ async getPrice(symbol) {
421
+ try {
422
+ const sym = symbol.toUpperCase();
423
+ const res = await fetch(`${this.baseUrl}/price?fsym=${sym}&tsyms=USD`);
424
+ if (!res.ok) return null;
425
+ const data = await res.json();
426
+ if (data.Response === "Error" || !data.USD) return null;
427
+ return {
428
+ symbol: sym,
429
+ priceUsd: data.USD,
430
+ source: this.name,
431
+ lastUpdated: Date.now()
432
+ };
433
+ } catch (e) {
434
+ return null;
435
+ }
436
+ }
437
+ async getTokenInfo(symbol) {
438
+ try {
439
+ const sym = symbol.toUpperCase();
440
+ const res = await fetch(`${this.baseUrl}/pricemultifull?fsyms=${sym}&tsyms=USD`);
441
+ if (!res.ok) return null;
442
+ const data = await res.json();
443
+ if (!data.RAW || !data.RAW[sym] || !data.RAW[sym].USD) return null;
444
+ const raw = data.RAW[sym].USD;
445
+ return {
446
+ name: sym,
447
+ // CryptoCompare doesn't give full name in this endpoint
448
+ symbol: sym,
449
+ priceUsd: raw.PRICE || 0,
450
+ marketCap: raw.MKTCAP,
451
+ volume24h: raw.TOTALVOLUME24HTO,
452
+ source: this.name,
453
+ lastUpdated: Date.now()
454
+ };
455
+ } catch (e) {
456
+ return null;
457
+ }
458
+ }
459
+ };
460
+
461
+ // src/Crypull.ts
462
+ var Crypull = class {
463
+ providers;
464
+ // Standard free providers
465
+ coinGecko = new CoinGeckoProvider();
466
+ dexScreener = new DexScreenerProvider();
467
+ geckoTerminal = new GeckoTerminalProvider();
468
+ binance = new BinanceProvider();
469
+ coinpaprika = new CoinpaprikaProvider();
470
+ coincap = new CoinCapProvider();
471
+ cryptoCompare = new CryptoCompareProvider();
472
+ constructor(options) {
473
+ this.providers = options?.providers || [
474
+ this.binance,
475
+ this.coinGecko,
476
+ this.coinpaprika,
477
+ this.coincap,
478
+ this.dexScreener,
479
+ this.geckoTerminal,
480
+ this.cryptoCompare
481
+ ];
482
+ }
483
+ isAddress(query) {
484
+ return query.startsWith("0x") && query.length === 42 || query.length > 30;
485
+ }
486
+ /**
487
+ * Search for a token or coin across multiple providers in parallel
488
+ */
489
+ async search(query) {
490
+ const promises = [
491
+ this.coinGecko.search(query),
492
+ this.dexScreener.search(query),
493
+ this.coinpaprika.search(query),
494
+ this.coincap.search(query)
495
+ ];
496
+ const results = await Promise.allSettled(promises);
497
+ const combined = [];
498
+ for (const res of results) {
499
+ if (res.status === "fulfilled" && res.value) {
500
+ combined.push(...res.value);
501
+ }
502
+ }
503
+ const seen = /* @__PURE__ */ new Set();
504
+ return combined.filter((item) => {
505
+ const key = `${item.symbol}`;
506
+ if (seen.has(key)) return false;
507
+ seen.add(key);
508
+ return true;
509
+ });
510
+ }
511
+ /**
512
+ * Get the current price of a cryptocurrency
513
+ * @param query Can be a symbol (e.g., 'BTC') or a contract address
514
+ * @param network Optional network for DEX addresses (e.g., 'eth', 'bsc')
515
+ */
516
+ async price(query, network) {
517
+ if (this.isAddress(query)) {
518
+ let res = await this.dexScreener.getPrice(query);
519
+ if (res) return res;
520
+ if (network) {
521
+ res = await this.geckoTerminal.getPrice(query, network);
522
+ if (res) return res;
523
+ }
524
+ } else {
525
+ let res = await this.binance.getPrice(query);
526
+ if (res) return res;
527
+ res = await this.coincap.getPrice(query);
528
+ if (res) return res;
529
+ res = await this.coinGecko.getPrice(query);
530
+ if (res) return res;
531
+ res = await this.coinpaprika.getPrice(query);
532
+ if (res) return res;
533
+ res = await this.cryptoCompare.getPrice(query);
534
+ if (res) return res;
535
+ }
536
+ return null;
537
+ }
538
+ /**
539
+ * Get detailed token info (market cap, volume, liquidity, etc.)
540
+ * @param query Can be a symbol (e.g., 'BTC') or a contract address
541
+ * @param network Optional network for DEX addresses
542
+ */
543
+ async info(query, network) {
544
+ if (this.isAddress(query)) {
545
+ let res = await this.dexScreener.getTokenInfo(query);
546
+ if (res) return res;
547
+ if (network) {
548
+ res = await this.geckoTerminal.getTokenInfo(query, network);
549
+ if (res) return res;
550
+ }
551
+ } else {
552
+ let res = await this.coinGecko.getTokenInfo(query);
553
+ if (res) return res;
554
+ res = await this.coinpaprika.getTokenInfo(query);
555
+ if (res) return res;
556
+ res = await this.coincap.getTokenInfo(query);
557
+ if (res) return res;
558
+ res = await this.binance.getTokenInfo(query);
559
+ if (res) return res;
560
+ res = await this.cryptoCompare.getTokenInfo(query);
561
+ if (res) return res;
562
+ }
563
+ return null;
564
+ }
565
+ /**
566
+ * Get global market data
567
+ */
568
+ async market() {
569
+ try {
570
+ const res = await fetch(`https://api.coingecko.com/api/v3/global`);
571
+ if (!res.ok) return null;
572
+ const data = await res.json();
573
+ const d = data.data;
574
+ return {
575
+ totalMarketCapUsd: d.total_market_cap.usd,
576
+ totalVolume24hUsd: d.total_volume.usd,
577
+ bitcoinDominancePercentage: d.market_cap_percentage.btc,
578
+ ethereumDominancePercentage: d.market_cap_percentage.eth,
579
+ activeCryptocurrencies: d.active_cryptocurrencies,
580
+ lastUpdated: d.updated_at * 1e3
581
+ };
582
+ } catch (e) {
583
+ return null;
584
+ }
585
+ }
586
+ /**
587
+ * Get trending coins
588
+ */
589
+ async trending() {
590
+ try {
591
+ const res = await fetch(`https://api.coingecko.com/api/v3/search/trending`);
592
+ if (!res.ok) return [];
593
+ const data = await res.json();
594
+ return data.coins.slice(0, 10).map((c) => ({
595
+ id: c.item.id,
596
+ name: c.item.name,
597
+ symbol: c.item.symbol.toUpperCase(),
598
+ marketCapRank: c.item.market_cap_rank,
599
+ priceUsd: c.item.data?.price,
600
+ priceChange24h: c.item.data?.price_change_percentage_24h?.usd,
601
+ volume24h: c.item.data?.total_volume
602
+ }));
603
+ } catch (e) {
604
+ return [];
605
+ }
606
+ }
607
+ /**
608
+ * Get top 50 coins by market cap
609
+ */
610
+ async top() {
611
+ try {
612
+ const res = await fetch(`https://api.coingecko.com/api/v3/coins/markets?vs_currency=usd&order=market_cap_desc&per_page=50&page=1&sparkline=false`);
613
+ if (!res.ok) return [];
614
+ const data = await res.json();
615
+ return data.map((c) => ({
616
+ id: c.id,
617
+ name: c.name,
618
+ symbol: c.symbol.toUpperCase(),
619
+ marketCapRank: c.market_cap_rank,
620
+ priceUsd: c.current_price,
621
+ marketCap: c.market_cap,
622
+ volume24h: c.total_volume,
623
+ priceChange24h: c.price_change_percentage_24h
624
+ }));
625
+ } catch (e) {
626
+ return [];
627
+ }
628
+ }
629
+ /**
630
+ * Get fear and greed index
631
+ */
632
+ async sentiment() {
633
+ try {
634
+ const res = await fetch(`https://api.alternative.me/fng/?limit=1`);
635
+ if (!res.ok) return null;
636
+ const data = await res.json();
637
+ const item = data.data[0];
638
+ return {
639
+ value: parseInt(item.value),
640
+ classification: item.value_classification,
641
+ lastUpdated: parseInt(item.timestamp) * 1e3
642
+ };
643
+ } catch (e) {
644
+ return null;
645
+ }
646
+ }
647
+ /**
648
+ * Get current ethereum gas prices (in Gwei)
649
+ */
650
+ async gas() {
651
+ try {
652
+ const res = await fetch(`https://api.etherscan.io/api?module=gastracker&action=gasoracle`);
653
+ if (!res.ok) return null;
654
+ const data = await res.json();
655
+ if (data.status !== "1") return null;
656
+ return {
657
+ network: "Ethereum",
658
+ low: parseFloat(data.result.SafeGasPrice),
659
+ average: parseFloat(data.result.ProposeGasPrice),
660
+ high: parseFloat(data.result.FastGasPrice),
661
+ baseFee: parseFloat(data.result.suggestBaseFee)
662
+ };
663
+ } catch (e) {
664
+ return null;
665
+ }
666
+ }
667
+ /**
668
+ * Get historical chart data for a coin
669
+ * @param query Coin symbol or ID
670
+ * @param days Number of days (e.g. 1, 7, 30)
671
+ */
672
+ async chart(query, days = 7) {
673
+ try {
674
+ let id = query.toLowerCase();
675
+ const searchRes = await this.coinGecko.search(id);
676
+ const match = searchRes.find((s) => s.symbol.toLowerCase() === id || s.id === id);
677
+ if (match && match.id) {
678
+ id = match.id;
679
+ }
680
+ const res = await fetch(`https://api.coingecko.com/api/v3/coins/${id}/market_chart?vs_currency=usd&days=${days}`);
681
+ if (!res.ok) return null;
682
+ const data = await res.json();
683
+ if (!data.prices || data.prices.length === 0) return null;
684
+ const prices = data.prices.map((p) => p[1]);
685
+ const timestamps = data.prices.map((p) => p[0]);
686
+ return {
687
+ prices,
688
+ timestamps,
689
+ minPrice: Math.min(...prices),
690
+ maxPrice: Math.max(...prices)
691
+ };
692
+ } catch (e) {
693
+ return null;
694
+ }
695
+ }
696
+ };
697
+
698
+ // src/index.ts
699
+ var crypull = new Crypull();
700
+
701
+ exports.BinanceProvider = BinanceProvider;
702
+ exports.CoinCapProvider = CoinCapProvider;
703
+ exports.CoinGeckoProvider = CoinGeckoProvider;
704
+ exports.CoinpaprikaProvider = CoinpaprikaProvider;
705
+ exports.CryptoCompareProvider = CryptoCompareProvider;
706
+ exports.Crypull = Crypull;
707
+ exports.DexScreenerProvider = DexScreenerProvider;
708
+ exports.GeckoTerminalProvider = GeckoTerminalProvider;
709
+ exports.crypull = crypull;
710
+ //# sourceMappingURL=index.js.map
711
+ //# sourceMappingURL=index.js.map