@cyberdrk/onchain 0.1.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.
Files changed (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +135 -0
  3. package/dist/cli/program.d.ts +4 -0
  4. package/dist/cli/program.d.ts.map +1 -0
  5. package/dist/cli/program.js +43 -0
  6. package/dist/cli/program.js.map +1 -0
  7. package/dist/cli/setup-wizard.d.ts +7 -0
  8. package/dist/cli/setup-wizard.d.ts.map +1 -0
  9. package/dist/cli/setup-wizard.js +96 -0
  10. package/dist/cli/setup-wizard.js.map +1 -0
  11. package/dist/cli/shared.d.ts +35 -0
  12. package/dist/cli/shared.d.ts.map +1 -0
  13. package/dist/cli/shared.js +120 -0
  14. package/dist/cli/shared.js.map +1 -0
  15. package/dist/cli.d.ts +3 -0
  16. package/dist/cli.d.ts.map +1 -0
  17. package/dist/cli.js +10 -0
  18. package/dist/cli.js.map +1 -0
  19. package/dist/commands/balance.d.ts +4 -0
  20. package/dist/commands/balance.d.ts.map +1 -0
  21. package/dist/commands/balance.js +141 -0
  22. package/dist/commands/balance.js.map +1 -0
  23. package/dist/commands/binance.d.ts +4 -0
  24. package/dist/commands/binance.d.ts.map +1 -0
  25. package/dist/commands/binance.js +129 -0
  26. package/dist/commands/binance.js.map +1 -0
  27. package/dist/commands/coinbase.d.ts +4 -0
  28. package/dist/commands/coinbase.d.ts.map +1 -0
  29. package/dist/commands/coinbase.js +122 -0
  30. package/dist/commands/coinbase.js.map +1 -0
  31. package/dist/commands/config.d.ts +4 -0
  32. package/dist/commands/config.d.ts.map +1 -0
  33. package/dist/commands/config.js +90 -0
  34. package/dist/commands/config.js.map +1 -0
  35. package/dist/commands/history.d.ts +4 -0
  36. package/dist/commands/history.d.ts.map +1 -0
  37. package/dist/commands/history.js +124 -0
  38. package/dist/commands/history.js.map +1 -0
  39. package/dist/commands/markets.d.ts +4 -0
  40. package/dist/commands/markets.d.ts.map +1 -0
  41. package/dist/commands/markets.js +59 -0
  42. package/dist/commands/markets.js.map +1 -0
  43. package/dist/commands/polymarket.d.ts +4 -0
  44. package/dist/commands/polymarket.d.ts.map +1 -0
  45. package/dist/commands/polymarket.js +180 -0
  46. package/dist/commands/polymarket.js.map +1 -0
  47. package/dist/commands/portfolio.d.ts +4 -0
  48. package/dist/commands/portfolio.d.ts.map +1 -0
  49. package/dist/commands/portfolio.js +162 -0
  50. package/dist/commands/portfolio.js.map +1 -0
  51. package/dist/commands/price.d.ts +4 -0
  52. package/dist/commands/price.d.ts.map +1 -0
  53. package/dist/commands/price.js +95 -0
  54. package/dist/commands/price.js.map +1 -0
  55. package/dist/commands/setup.d.ts +4 -0
  56. package/dist/commands/setup.d.ts.map +1 -0
  57. package/dist/commands/setup.js +47 -0
  58. package/dist/commands/setup.js.map +1 -0
  59. package/dist/commands/test.d.ts +4 -0
  60. package/dist/commands/test.d.ts.map +1 -0
  61. package/dist/commands/test.js +198 -0
  62. package/dist/commands/test.js.map +1 -0
  63. package/dist/index.d.ts +5 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +6 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/lib/browser-scraper.d.ts +39 -0
  68. package/dist/lib/browser-scraper.d.ts.map +1 -0
  69. package/dist/lib/browser-scraper.js +214 -0
  70. package/dist/lib/browser-scraper.js.map +1 -0
  71. package/dist/lib/config.d.ts +19 -0
  72. package/dist/lib/config.d.ts.map +1 -0
  73. package/dist/lib/config.js +52 -0
  74. package/dist/lib/config.js.map +1 -0
  75. package/dist/lib/credentials.d.ts +23 -0
  76. package/dist/lib/credentials.d.ts.map +1 -0
  77. package/dist/lib/credentials.js +49 -0
  78. package/dist/lib/credentials.js.map +1 -0
  79. package/dist/lib/mixins/binance.d.ts +12 -0
  80. package/dist/lib/mixins/binance.d.ts.map +1 -0
  81. package/dist/lib/mixins/binance.js +167 -0
  82. package/dist/lib/mixins/binance.js.map +1 -0
  83. package/dist/lib/mixins/coinbase.d.ts +11 -0
  84. package/dist/lib/mixins/coinbase.d.ts.map +1 -0
  85. package/dist/lib/mixins/coinbase.js +266 -0
  86. package/dist/lib/mixins/coinbase.js.map +1 -0
  87. package/dist/lib/mixins/coingecko.d.ts +10 -0
  88. package/dist/lib/mixins/coingecko.d.ts.map +1 -0
  89. package/dist/lib/mixins/coingecko.js +217 -0
  90. package/dist/lib/mixins/coingecko.js.map +1 -0
  91. package/dist/lib/mixins/coinmarketcap.d.ts +9 -0
  92. package/dist/lib/mixins/coinmarketcap.d.ts.map +1 -0
  93. package/dist/lib/mixins/coinmarketcap.js +142 -0
  94. package/dist/lib/mixins/coinmarketcap.js.map +1 -0
  95. package/dist/lib/mixins/debank.d.ts +21 -0
  96. package/dist/lib/mixins/debank.d.ts.map +1 -0
  97. package/dist/lib/mixins/debank.js +280 -0
  98. package/dist/lib/mixins/debank.js.map +1 -0
  99. package/dist/lib/mixins/helius.d.ts +12 -0
  100. package/dist/lib/mixins/helius.d.ts.map +1 -0
  101. package/dist/lib/mixins/helius.js +281 -0
  102. package/dist/lib/mixins/helius.js.map +1 -0
  103. package/dist/lib/mixins/polymarket.d.ts +13 -0
  104. package/dist/lib/mixins/polymarket.d.ts.map +1 -0
  105. package/dist/lib/mixins/polymarket.js +186 -0
  106. package/dist/lib/mixins/polymarket.js.map +1 -0
  107. package/dist/lib/onchain-client-base.d.ts +20 -0
  108. package/dist/lib/onchain-client-base.d.ts.map +1 -0
  109. package/dist/lib/onchain-client-base.js +45 -0
  110. package/dist/lib/onchain-client-base.js.map +1 -0
  111. package/dist/lib/onchain-client-types.d.ts +228 -0
  112. package/dist/lib/onchain-client-types.d.ts.map +1 -0
  113. package/dist/lib/onchain-client-types.js +2 -0
  114. package/dist/lib/onchain-client-types.js.map +1 -0
  115. package/dist/lib/onchain-client.d.ts +15 -0
  116. package/dist/lib/onchain-client.d.ts.map +1 -0
  117. package/dist/lib/onchain-client.js +13 -0
  118. package/dist/lib/onchain-client.js.map +1 -0
  119. package/dist/lib/output.d.ts +28 -0
  120. package/dist/lib/output.d.ts.map +1 -0
  121. package/dist/lib/output.js +94 -0
  122. package/dist/lib/output.js.map +1 -0
  123. package/dist/lib/utils/address.d.ts +26 -0
  124. package/dist/lib/utils/address.d.ts.map +1 -0
  125. package/dist/lib/utils/address.js +61 -0
  126. package/dist/lib/utils/address.js.map +1 -0
  127. package/dist/lib/utils/formatters.d.ts +42 -0
  128. package/dist/lib/utils/formatters.d.ts.map +1 -0
  129. package/dist/lib/utils/formatters.js +173 -0
  130. package/dist/lib/utils/formatters.js.map +1 -0
  131. package/package.json +77 -0
@@ -0,0 +1,266 @@
1
+ import { createPrivateKey, createSign, randomBytes } from 'node:crypto';
2
+ const COINBASE_API_BASE = 'https://api.coinbase.com';
3
+ /**
4
+ * Base64url encode a buffer or string
5
+ */
6
+ function base64urlEncode(data) {
7
+ const buffer = typeof data === 'string' ? Buffer.from(data) : data;
8
+ return buffer.toString('base64url');
9
+ }
10
+ /**
11
+ * Normalize a PEM key string by converting escaped newlines to actual newlines
12
+ */
13
+ function normalizePem(pem) {
14
+ // Replace literal \n with actual newlines
15
+ return pem.replace(/\\n/g, '\n');
16
+ }
17
+ /**
18
+ * Generate a JWT for Coinbase CDP API authentication (ES256)
19
+ * See: https://docs.cdp.coinbase.com/coinbase-app/docs/api-key-authentication
20
+ */
21
+ function generateCoinbaseJwt(keyName, privateKeyPem, method, host, path) {
22
+ const now = Math.floor(Date.now() / 1000);
23
+ const nonce = randomBytes(16).toString('hex');
24
+ // JWT Header
25
+ const header = {
26
+ alg: 'ES256',
27
+ kid: keyName,
28
+ nonce,
29
+ typ: 'JWT',
30
+ };
31
+ // JWT Payload
32
+ const payload = {
33
+ iss: 'cdp',
34
+ nbf: now,
35
+ exp: now + 120, // 2 minutes expiry
36
+ sub: keyName,
37
+ uri: `${method} ${host}${path}`,
38
+ };
39
+ // Encode header and payload
40
+ const encodedHeader = base64urlEncode(JSON.stringify(header));
41
+ const encodedPayload = base64urlEncode(JSON.stringify(payload));
42
+ const signingInput = `${encodedHeader}.${encodedPayload}`;
43
+ // Normalize PEM (convert escaped \n to actual newlines)
44
+ const normalizedPem = normalizePem(privateKeyPem);
45
+ // Sign with ES256 (ECDSA with P-256 / secp256r1)
46
+ const privateKey = createPrivateKey({
47
+ key: normalizedPem,
48
+ format: 'pem',
49
+ });
50
+ const sign = createSign('SHA256');
51
+ sign.update(signingInput);
52
+ const derSignature = sign.sign(privateKey);
53
+ // Convert DER signature to raw R||S format (64 bytes)
54
+ // DER format: 0x30 [total-length] 0x02 [r-length] [r] 0x02 [s-length] [s]
55
+ const rLength = derSignature[3];
56
+ const rStart = 4;
57
+ let r = derSignature.subarray(rStart, rStart + rLength);
58
+ const sLength = derSignature[rStart + rLength + 1];
59
+ const sStart = rStart + rLength + 2;
60
+ let s = derSignature.subarray(sStart, sStart + sLength);
61
+ // Remove leading zeros if present (DER uses signed integers)
62
+ if (r.length === 33 && r[0] === 0) {
63
+ r = r.subarray(1);
64
+ }
65
+ if (s.length === 33 && s[0] === 0) {
66
+ s = s.subarray(1);
67
+ }
68
+ // Pad to 32 bytes if needed
69
+ if (r.length < 32) {
70
+ r = Buffer.concat([Buffer.alloc(32 - r.length), r]);
71
+ }
72
+ if (s.length < 32) {
73
+ s = Buffer.concat([Buffer.alloc(32 - s.length), s]);
74
+ }
75
+ const rawSignature = Buffer.concat([r, s]);
76
+ const encodedSignature = base64urlEncode(rawSignature);
77
+ return `${signingInput}.${encodedSignature}`;
78
+ }
79
+ export function withCoinbase(Base) {
80
+ class CoinbaseMixin extends Base {
81
+ getCoinbaseHeaders(method, path) {
82
+ if (!this.coinbaseApiKeyId || !this.coinbaseApiKeySecret) {
83
+ throw new Error('Coinbase CDP API credentials required');
84
+ }
85
+ const jwt = generateCoinbaseJwt(this.coinbaseApiKeyId, this.coinbaseApiKeySecret, method, 'api.coinbase.com', path);
86
+ return {
87
+ Authorization: `Bearer ${jwt}`,
88
+ 'Content-Type': 'application/json',
89
+ };
90
+ }
91
+ async getCoinbaseBalances() {
92
+ if (!this.coinbaseApiKeyId || !this.coinbaseApiKeySecret) {
93
+ return { success: false, error: 'Coinbase CDP API credentials not configured' };
94
+ }
95
+ try {
96
+ // Use the v2 Coinbase App API for consumer wallet balances
97
+ const path = '/v2/accounts';
98
+ const url = `${COINBASE_API_BASE}${path}?limit=300`;
99
+ const response = await this.fetchWithTimeout(url, {
100
+ headers: this.getCoinbaseHeaders('GET', path),
101
+ });
102
+ if (!response.ok) {
103
+ const errorText = await response.text();
104
+ return { success: false, error: `Coinbase API error: ${response.status} - ${errorText}` };
105
+ }
106
+ const data = (await response.json());
107
+ let totalValueUsd = 0;
108
+ const balances = [];
109
+ // We need to get prices to calculate USD values for crypto
110
+ const cryptoAssets = new Set();
111
+ for (const account of data.data) {
112
+ const total = Number.parseFloat(account.balance.amount);
113
+ if (total > 0 && account.currency.type === 'crypto') {
114
+ cryptoAssets.add(account.currency.code);
115
+ }
116
+ }
117
+ // Fetch spot prices for crypto assets
118
+ const prices = new Map();
119
+ for (const asset of cryptoAssets) {
120
+ try {
121
+ const pricePath = `/v2/prices/${asset}-USD/spot`;
122
+ const priceResponse = await this.fetchWithTimeout(`${COINBASE_API_BASE}${pricePath}`, {
123
+ headers: this.getCoinbaseHeaders('GET', pricePath),
124
+ });
125
+ if (priceResponse.ok) {
126
+ const priceData = (await priceResponse.json());
127
+ prices.set(asset, Number.parseFloat(priceData.data.amount));
128
+ }
129
+ }
130
+ catch {
131
+ // Skip assets without prices
132
+ }
133
+ }
134
+ for (const account of data.data) {
135
+ const total = Number.parseFloat(account.balance.amount);
136
+ if (total <= 0) {
137
+ continue;
138
+ }
139
+ let valueUsd;
140
+ if (account.currency.type === 'fiat' && account.currency.code === 'USD') {
141
+ // USD fiat account
142
+ valueUsd = total;
143
+ }
144
+ else if (account.currency.type === 'fiat') {
145
+ // Other fiat - we'd need exchange rates, skip USD value for now
146
+ valueUsd = undefined;
147
+ }
148
+ else {
149
+ // Crypto - use fetched price
150
+ const price = prices.get(account.currency.code);
151
+ valueUsd = price ? total * price : undefined;
152
+ }
153
+ if (valueUsd !== undefined) {
154
+ totalValueUsd += valueUsd;
155
+ }
156
+ balances.push({
157
+ exchange: 'coinbase',
158
+ asset: account.currency.code,
159
+ free: total, // Coinbase v2 API doesn't separate free/locked
160
+ locked: 0,
161
+ total,
162
+ valueUsd,
163
+ });
164
+ }
165
+ // Sort by value descending
166
+ balances.sort((a, b) => (b.valueUsd ?? 0) - (a.valueUsd ?? 0));
167
+ return { success: true, balances, totalValueUsd };
168
+ }
169
+ catch (error) {
170
+ return {
171
+ success: false,
172
+ error: `Failed to fetch Coinbase balances: ${error instanceof Error ? error.message : String(error)}`,
173
+ };
174
+ }
175
+ }
176
+ async getCoinbaseHistory(options) {
177
+ if (!this.coinbaseApiKeyId || !this.coinbaseApiKeySecret) {
178
+ return { success: false, error: 'Coinbase CDP API credentials not configured' };
179
+ }
180
+ try {
181
+ // First get accounts to fetch transactions from each
182
+ const accountsPath = '/v2/accounts';
183
+ const accountsResponse = await this.fetchWithTimeout(`${COINBASE_API_BASE}${accountsPath}?limit=300`, {
184
+ headers: this.getCoinbaseHeaders('GET', accountsPath),
185
+ });
186
+ if (!accountsResponse.ok) {
187
+ return { success: false, error: `Coinbase API error: ${accountsResponse.status}` };
188
+ }
189
+ const accountsData = (await accountsResponse.json());
190
+ const trades = [];
191
+ const limit = options?.limit ?? 20;
192
+ // Get transactions from accounts with balance or that are crypto type
193
+ for (const account of accountsData.data) {
194
+ const hasBalance = Number.parseFloat(account.balance.amount) > 0;
195
+ const isCrypto = account.currency.type === 'crypto';
196
+ if (!hasBalance && !isCrypto) {
197
+ continue;
198
+ }
199
+ const txPath = `/v2/accounts/${account.id}/transactions`;
200
+ let txUrl = `${COINBASE_API_BASE}${txPath}?limit=${Math.min(limit, 25)}`;
201
+ if (options?.cursor) {
202
+ txUrl += `&starting_after=${options.cursor}`;
203
+ }
204
+ try {
205
+ const txResponse = await this.fetchWithTimeout(txUrl, {
206
+ headers: this.getCoinbaseHeaders('GET', txPath),
207
+ });
208
+ if (!txResponse.ok) {
209
+ continue;
210
+ }
211
+ const txData = (await txResponse.json());
212
+ for (const tx of txData.data) {
213
+ // Include buy, sell, trade, send, and receive transactions
214
+ const validTypes = ['buy', 'sell', 'trade', 'send', 'receive', 'fiat_deposit', 'fiat_withdrawal'];
215
+ if (!validTypes.includes(tx.type)) {
216
+ continue;
217
+ }
218
+ const amount = Math.abs(Number.parseFloat(tx.amount.amount));
219
+ const nativeAmount = Math.abs(Number.parseFloat(tx.native_amount.amount));
220
+ const price = amount > 0 ? nativeAmount / amount : 0;
221
+ // Determine side based on transaction type and amount sign
222
+ let side;
223
+ if (tx.type === 'sell' || tx.type === 'send' || tx.type === 'fiat_withdrawal') {
224
+ side = 'sell';
225
+ }
226
+ else if (tx.type === 'buy' || tx.type === 'receive' || tx.type === 'fiat_deposit') {
227
+ side = 'buy';
228
+ }
229
+ else {
230
+ // For 'trade' type, check amount sign
231
+ side = Number.parseFloat(tx.amount.amount) < 0 ? 'sell' : 'buy';
232
+ }
233
+ trades.push({
234
+ exchange: 'coinbase',
235
+ id: tx.id,
236
+ symbol: `${tx.amount.currency}/${tx.native_amount.currency}`,
237
+ side,
238
+ price,
239
+ quantity: amount,
240
+ total: nativeAmount,
241
+ timestamp: new Date(tx.created_at).getTime() / 1000,
242
+ });
243
+ }
244
+ }
245
+ catch {
246
+ // Continue to next account on error
247
+ }
248
+ }
249
+ // Sort by timestamp descending
250
+ trades.sort((a, b) => b.timestamp - a.timestamp);
251
+ // Limit results
252
+ const limitedTrades = trades.slice(0, limit);
253
+ const nextCursor = limitedTrades.length === limit ? limitedTrades[limitedTrades.length - 1]?.id : undefined;
254
+ return { success: true, trades: limitedTrades, nextCursor };
255
+ }
256
+ catch (error) {
257
+ return {
258
+ success: false,
259
+ error: `Failed to fetch Coinbase history: ${error instanceof Error ? error.message : String(error)}`,
260
+ };
261
+ }
262
+ }
263
+ }
264
+ return CoinbaseMixin;
265
+ }
266
+ //# sourceMappingURL=coinbase.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coinbase.js","sourceRoot":"","sources":["../../../src/lib/mixins/coinbase.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { AbstractConstructor, Mixin, OnchainClientBase } from '../onchain-client-base.js';
2
+ import type { MarketResult, PriceResult, PricesResult } from '../onchain-client-types.js';
3
+ export interface CoinGeckoMethods {
4
+ getTokenPrice(tokenIdOrSymbol: string): Promise<PriceResult>;
5
+ getTokenPrices(tokenIdsOrSymbols: string[]): Promise<PricesResult>;
6
+ getMarketOverview(): Promise<MarketResult>;
7
+ getTrendingTokens(): Promise<PricesResult>;
8
+ }
9
+ export declare function withCoinGecko<TBase extends AbstractConstructor<OnchainClientBase>>(Base: TBase): Mixin<TBase, CoinGeckoMethods>;
10
+ //# sourceMappingURL=coingecko.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coingecko.d.ts","sourceRoot":"","sources":["../../../src/lib/mixins/coingecko.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,KAAK,EAAkB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAc,MAAM,4BAA4B,CAAC;AA6CtH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7D,cAAc,CAAC,iBAAiB,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnE,iBAAiB,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IAC3C,iBAAiB,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5C;AAmDD,wBAAgB,aAAa,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EAChF,IAAI,EAAE,KAAK,GACV,KAAK,CAAC,KAAK,EAAE,gBAAgB,CAAC,CA+NhC"}
@@ -0,0 +1,217 @@
1
+ const COINGECKO_API_BASE = 'https://api.coingecko.com/api/v3';
2
+ const COINGECKO_PRO_API_BASE = 'https://pro-api.coingecko.com/api/v3';
3
+ // Common token ID mappings (symbol -> coingecko id)
4
+ const TOKEN_ID_MAP = {
5
+ btc: 'bitcoin',
6
+ eth: 'ethereum',
7
+ sol: 'solana',
8
+ bnb: 'binancecoin',
9
+ xrp: 'ripple',
10
+ ada: 'cardano',
11
+ doge: 'dogecoin',
12
+ dot: 'polkadot',
13
+ matic: 'matic-network',
14
+ shib: 'shiba-inu',
15
+ avax: 'avalanche-2',
16
+ link: 'chainlink',
17
+ atom: 'cosmos',
18
+ uni: 'uniswap',
19
+ ltc: 'litecoin',
20
+ xlm: 'stellar',
21
+ etc: 'ethereum-classic',
22
+ near: 'near',
23
+ apt: 'aptos',
24
+ arb: 'arbitrum',
25
+ op: 'optimism',
26
+ sui: 'sui',
27
+ inj: 'injective-protocol',
28
+ sei: 'sei-network',
29
+ tia: 'celestia',
30
+ jup: 'jupiter-exchange-solana',
31
+ wif: 'dogwifcoin',
32
+ pepe: 'pepe',
33
+ bonk: 'bonk',
34
+ usdt: 'tether',
35
+ usdc: 'usd-coin',
36
+ dai: 'dai',
37
+ busd: 'binance-usd',
38
+ wbtc: 'wrapped-bitcoin',
39
+ weth: 'weth',
40
+ steth: 'staked-ether',
41
+ };
42
+ export function withCoinGecko(Base) {
43
+ class CoinGeckoMixin extends Base {
44
+ getApiBase() {
45
+ return this.coingeckoApiKey ? COINGECKO_PRO_API_BASE : COINGECKO_API_BASE;
46
+ }
47
+ getApiHeaders() {
48
+ const headers = {
49
+ Accept: 'application/json',
50
+ };
51
+ if (this.coingeckoApiKey) {
52
+ headers['x-cg-pro-api-key'] = this.coingeckoApiKey;
53
+ }
54
+ return headers;
55
+ }
56
+ resolveTokenId(tokenIdOrSymbol) {
57
+ const lower = tokenIdOrSymbol.toLowerCase();
58
+ return TOKEN_ID_MAP[lower] ?? lower;
59
+ }
60
+ async getTokenPrice(tokenIdOrSymbol) {
61
+ try {
62
+ const tokenId = this.resolveTokenId(tokenIdOrSymbol);
63
+ const url = `${this.getApiBase()}/coins/${tokenId}?localization=false&tickers=false&community_data=false&developer_data=false&sparkline=false`;
64
+ const response = await this.fetchWithTimeout(url, {
65
+ headers: this.getApiHeaders(),
66
+ });
67
+ if (!response.ok) {
68
+ if (response.status === 404) {
69
+ return { success: false, error: `Token "${tokenIdOrSymbol}" not found` };
70
+ }
71
+ return { success: false, error: `CoinGecko API error: ${response.status}` };
72
+ }
73
+ const data = (await response.json());
74
+ const token = {
75
+ id: data.id,
76
+ symbol: data.symbol.toUpperCase(),
77
+ name: data.name,
78
+ priceUsd: data.market_data?.current_price?.usd ?? 0,
79
+ priceChange1h: data.market_data?.price_change_percentage_1h_in_currency?.usd,
80
+ priceChange24h: data.market_data?.price_change_percentage_24h,
81
+ priceChange7d: data.market_data?.price_change_percentage_7d,
82
+ priceChange30d: data.market_data?.price_change_percentage_30d,
83
+ marketCap: data.market_data?.market_cap?.usd,
84
+ marketCapRank: data.market_data?.market_cap_rank,
85
+ volume24h: data.market_data?.total_volume?.usd,
86
+ circulatingSupply: data.market_data?.circulating_supply,
87
+ totalSupply: data.market_data?.total_supply,
88
+ maxSupply: data.market_data?.max_supply,
89
+ ath: data.market_data?.ath?.usd,
90
+ athDate: data.market_data?.ath_date?.usd,
91
+ athChangePercent: data.market_data?.ath_change_percentage?.usd,
92
+ atl: data.market_data?.atl?.usd,
93
+ atlDate: data.market_data?.atl_date?.usd,
94
+ atlChangePercent: data.market_data?.atl_change_percentage?.usd,
95
+ lastUpdated: data.last_updated,
96
+ logoUrl: data.image?.large,
97
+ };
98
+ return { success: true, token };
99
+ }
100
+ catch (error) {
101
+ return {
102
+ success: false,
103
+ error: `Failed to fetch token price: ${error instanceof Error ? error.message : String(error)}`,
104
+ };
105
+ }
106
+ }
107
+ async getTokenPrices(tokenIdsOrSymbols) {
108
+ try {
109
+ const tokenIds = tokenIdsOrSymbols.map((t) => this.resolveTokenId(t));
110
+ const url = `${this.getApiBase()}/coins/markets?vs_currency=usd&ids=${tokenIds.join(',')}&order=market_cap_desc&per_page=250&page=1&sparkline=false&price_change_percentage=1h,24h,7d,30d`;
111
+ const response = await this.fetchWithTimeout(url, {
112
+ headers: this.getApiHeaders(),
113
+ });
114
+ if (!response.ok) {
115
+ return { success: false, error: `CoinGecko API error: ${response.status}` };
116
+ }
117
+ const data = (await response.json());
118
+ const tokens = data.map((item) => ({
119
+ id: item.id,
120
+ symbol: item.symbol.toUpperCase(),
121
+ name: item.name,
122
+ priceUsd: item.current_price ?? 0,
123
+ priceChange1h: item.price_change_percentage_1h_in_currency,
124
+ priceChange24h: item.price_change_percentage_24h,
125
+ priceChange7d: item.price_change_percentage_7d_in_currency,
126
+ priceChange30d: item.price_change_percentage_30d_in_currency,
127
+ marketCap: item.market_cap,
128
+ marketCapRank: item.market_cap_rank,
129
+ volume24h: item.total_volume,
130
+ circulatingSupply: item.circulating_supply,
131
+ totalSupply: item.total_supply,
132
+ maxSupply: item.max_supply,
133
+ ath: item.ath,
134
+ athDate: item.ath_date,
135
+ athChangePercent: item.ath_change_percentage,
136
+ atl: item.atl,
137
+ atlDate: item.atl_date,
138
+ atlChangePercent: item.atl_change_percentage,
139
+ lastUpdated: item.last_updated,
140
+ logoUrl: item.image,
141
+ }));
142
+ return { success: true, tokens };
143
+ }
144
+ catch (error) {
145
+ return {
146
+ success: false,
147
+ error: `Failed to fetch token prices: ${error instanceof Error ? error.message : String(error)}`,
148
+ };
149
+ }
150
+ }
151
+ async getMarketOverview() {
152
+ try {
153
+ const url = `${this.getApiBase()}/global`;
154
+ const response = await this.fetchWithTimeout(url, {
155
+ headers: this.getApiHeaders(),
156
+ });
157
+ if (!response.ok) {
158
+ return { success: false, error: `CoinGecko API error: ${response.status}` };
159
+ }
160
+ const data = (await response.json());
161
+ // Also get trending
162
+ const trendingResult = await this.getTrendingTokens();
163
+ const trending = trendingResult.success ? trendingResult.tokens.slice(0, 5) : undefined;
164
+ const market = {
165
+ totalMarketCap: data.data.total_market_cap.usd,
166
+ totalVolume24h: data.data.total_volume.usd,
167
+ btcDominance: data.data.market_cap_percentage.btc,
168
+ ethDominance: data.data.market_cap_percentage.eth,
169
+ marketCapChange24h: data.data.market_cap_change_percentage_24h_usd,
170
+ trending: trending?.map((t) => ({
171
+ id: t.id,
172
+ symbol: t.symbol,
173
+ name: t.name,
174
+ priceChange24h: t.priceChange24h,
175
+ marketCapRank: t.marketCapRank,
176
+ })),
177
+ };
178
+ return { success: true, market };
179
+ }
180
+ catch (error) {
181
+ return {
182
+ success: false,
183
+ error: `Failed to fetch market overview: ${error instanceof Error ? error.message : String(error)}`,
184
+ };
185
+ }
186
+ }
187
+ async getTrendingTokens() {
188
+ try {
189
+ const url = `${this.getApiBase()}/search/trending`;
190
+ const response = await this.fetchWithTimeout(url, {
191
+ headers: this.getApiHeaders(),
192
+ });
193
+ if (!response.ok) {
194
+ return { success: false, error: `CoinGecko API error: ${response.status}` };
195
+ }
196
+ const data = (await response.json());
197
+ const tokens = data.coins.map((coin) => ({
198
+ id: coin.item.id,
199
+ symbol: coin.item.symbol.toUpperCase(),
200
+ name: coin.item.name,
201
+ priceUsd: 0, // Trending endpoint doesn't include USD price
202
+ priceChange24h: coin.item.data?.price_change_percentage_24h?.usd,
203
+ marketCapRank: coin.item.market_cap_rank,
204
+ }));
205
+ return { success: true, tokens };
206
+ }
207
+ catch (error) {
208
+ return {
209
+ success: false,
210
+ error: `Failed to fetch trending tokens: ${error instanceof Error ? error.message : String(error)}`,
211
+ };
212
+ }
213
+ }
214
+ }
215
+ return CoinGeckoMixin;
216
+ }
217
+ //# sourceMappingURL=coingecko.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coingecko.js","sourceRoot":"","sources":["../../../src/lib/mixins/coingecko.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { AbstractConstructor, Mixin, OnchainClientBase } from '../onchain-client-base.js';
2
+ import type { MarketResult, PriceResult, PricesResult } from '../onchain-client-types.js';
3
+ export interface CoinMarketCapMethods {
4
+ cmcGetTokenPrice(symbolOrSlug: string): Promise<PriceResult>;
5
+ cmcGetTokenPrices(symbols: string[]): Promise<PricesResult>;
6
+ cmcGetMarketOverview(): Promise<MarketResult>;
7
+ }
8
+ export declare function withCoinMarketCap<TBase extends AbstractConstructor<OnchainClientBase>>(Base: TBase): Mixin<TBase, CoinMarketCapMethods>;
9
+ //# sourceMappingURL=coinmarketcap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coinmarketcap.d.ts","sourceRoot":"","sources":["../../../src/lib/mixins/coinmarketcap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC/F,OAAO,KAAK,EAAkB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAc,MAAM,4BAA4B,CAAC;AAItH,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7D,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5D,oBAAoB,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;CAC/C;AA2CD,wBAAgB,iBAAiB,CAAC,KAAK,SAAS,mBAAmB,CAAC,iBAAiB,CAAC,EACpF,IAAI,EAAE,KAAK,GACV,KAAK,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAmKpC"}