|
1 | 1 | import { Aftermath } from 'aftermath-ts-sdk'; |
2 | | -import { COIN_ADDRESSES, COIN_SYNONYMS } from '../../@types/interface'; |
3 | 2 | import { handleError } from '../../utils'; |
4 | 3 |
|
5 | | -const af = new Aftermath('MAINNET'); |
6 | | -const prices = af.Prices(); |
| 4 | +class PriceTool { |
| 5 | + private static sdk: Aftermath | null = null; |
7 | 6 |
|
8 | | -/** |
9 | | - * Normalizes a coin symbol by handling various formats and synonyms |
10 | | - * @param symbol - Raw coin symbol input |
11 | | - * @returns Normalized coin symbol or null if not recognized |
12 | | - */ |
13 | | -function normalizeCoinSymbol(symbol: string): string | null { |
14 | | - const normalized = symbol |
15 | | - .trim() |
16 | | - .toUpperCase() |
17 | | - .replace(/[^A-Z_]/g, ''); |
18 | | - return COIN_SYNONYMS[normalized] || null; |
19 | | -} |
20 | | - |
21 | | -/** |
22 | | - * Fetches current price for a single coin from Aftermath Finance |
23 | | - * @param coin - Coin symbol or address |
24 | | - * @returns Formatted price string or error message |
25 | | - */ |
26 | | -export async function getCoinPrice( |
27 | | - ...args: (string | number | bigint | boolean)[] |
28 | | -): Promise<string> { |
29 | | - const coin = args[0] as string; // Cast first argument to string |
30 | | - try { |
31 | | - // Handle direct addresses vs symbols |
32 | | - let coinType = coin; |
33 | | - if (!coin.includes('::')) { |
34 | | - const normalizedSymbol = normalizeCoinSymbol(coin); |
35 | | - if (!normalizedSymbol) { |
36 | | - throw new Error(`Unknown coin symbol: ${coin}`); |
37 | | - } |
38 | | - coinType = |
39 | | - COIN_ADDRESSES[normalizedSymbol as keyof typeof COIN_ADDRESSES]; |
40 | | - if (!coinType) { |
41 | | - throw new Error(`No address mapping for coin: ${coin}`); |
42 | | - } |
| 7 | + private static initSDK(): Aftermath { |
| 8 | + if (!PriceTool.sdk) { |
| 9 | + PriceTool.sdk = new Aftermath('MAINNET'); |
43 | 10 | } |
| 11 | + return PriceTool.sdk; |
| 12 | + } |
44 | 13 |
|
45 | | - const price = await prices.getCoinPrice({ coin: coinType }); |
| 14 | + /** |
| 15 | + * Gets current price for a single coin |
| 16 | + */ |
| 17 | + public static async getCoinPrice(coinType: string): Promise<string> { |
| 18 | + try { |
| 19 | + const sdk = PriceTool.initSDK(); |
| 20 | + await sdk.init(); |
46 | 21 |
|
47 | | - return JSON.stringify([ |
48 | | - { |
49 | | - reasoning: |
50 | | - 'Successfully retrieved current price from Aftermath Finance', |
51 | | - response: `The current price of ${coin} is $${price}`, |
52 | | - status: 'success', |
53 | | - query: `Fetched price for ${coin}`, |
54 | | - errors: [], |
55 | | - }, |
56 | | - ]); |
57 | | - } catch (error: unknown) { |
58 | | - return JSON.stringify([ |
59 | | - handleError(error, { |
60 | | - reasoning: 'Failed to fetch price from Aftermath Finance', |
61 | | - query: `Attempted to fetch price for ${coin}`, |
62 | | - }), |
63 | | - ]); |
| 22 | + const priceInfo = await sdk.Prices().getCoinPriceInfo({ |
| 23 | + coin: coinType, |
| 24 | + }); |
| 25 | + |
| 26 | + return JSON.stringify([ |
| 27 | + { |
| 28 | + reasoning: 'Successfully retrieved current price', |
| 29 | + response: { |
| 30 | + price: priceInfo.price, |
| 31 | + priceChange24h: priceInfo.priceChange24HoursPercentage, |
| 32 | + coin: coinType, |
| 33 | + }, |
| 34 | + status: 'success', |
| 35 | + query: `Get price for ${coinType}`, |
| 36 | + errors: [], |
| 37 | + }, |
| 38 | + ]); |
| 39 | + } catch (error) { |
| 40 | + return JSON.stringify([ |
| 41 | + handleError(error, { |
| 42 | + reasoning: 'Failed to fetch price', |
| 43 | + query: `Get price for ${coinType}`, |
| 44 | + }), |
| 45 | + ]); |
| 46 | + } |
64 | 47 | } |
65 | | -} |
66 | 48 |
|
67 | | -/** |
68 | | - * Gets price information for multiple coins from Aftermath Finance |
69 | | - * @param coins - Comma-separated string of coin symbols or addresses |
70 | | - * @returns JSON string containing price information or error response |
71 | | - * @throws Error if price fetch fails or invalid token addresses |
72 | | - */ |
73 | | -export async function coinsToPrice( |
74 | | - ...args: (string | number | bigint | boolean)[] |
75 | | -): Promise<string> { |
76 | | - const coins = args[0] as string; |
77 | | - try { |
78 | | - // Convert coin symbols to addresses |
79 | | - const coinTypes = coins.split(',').map((coin) => { |
80 | | - const trimmed = coin.trim(); |
81 | | - // Handle direct addresses |
82 | | - if (trimmed.includes('::')) { |
83 | | - return trimmed; |
84 | | - } |
85 | | - // Handle symbols |
86 | | - const normalizedSymbol = normalizeCoinSymbol(trimmed); |
87 | | - if (!normalizedSymbol) { |
88 | | - throw new Error(`Unknown coin symbol: ${trimmed}`); |
89 | | - } |
90 | | - const address = |
91 | | - COIN_ADDRESSES[normalizedSymbol as keyof typeof COIN_ADDRESSES]; |
92 | | - if (!address) { |
93 | | - throw new Error(`No address mapping for coin: ${trimmed}`); |
94 | | - } |
95 | | - return address; |
96 | | - }); |
| 49 | + /** |
| 50 | + * Gets prices for multiple coins |
| 51 | + */ |
| 52 | + public static async getCoinsPrice(coinTypes: string[]): Promise<string> { |
| 53 | + try { |
| 54 | + const sdk = PriceTool.initSDK(); |
| 55 | + await sdk.init(); |
| 56 | + |
| 57 | + const priceInfos = await sdk.Prices().getCoinsToPriceInfo({ |
| 58 | + coins: coinTypes, |
| 59 | + }); |
97 | 60 |
|
98 | | - // Fetch prices from Aftermath |
99 | | - const priceInfo = await prices.getCoinsToPrice({ coins: coinTypes }); |
100 | | - return JSON.stringify([ |
101 | | - { |
102 | | - reasoning: |
103 | | - 'Successfully retrieved current price information from Aftermath Finance for the requested coins.', |
104 | | - response: JSON.stringify(priceInfo, null, 2), |
105 | | - status: 'success', |
106 | | - query: `Fetched prices for coins: ${coins}`, |
107 | | - errors: [], |
108 | | - }, |
109 | | - ]); |
110 | | - } catch (error: unknown) { |
111 | | - return JSON.stringify([ |
112 | | - handleError(error, { |
113 | | - reasoning: 'Failed to retrieve prices from Aftermath Finance', |
114 | | - query: `Attempted to fetch prices for coins: ${coins}`, |
115 | | - }), |
116 | | - ]); |
| 61 | + return JSON.stringify([ |
| 62 | + { |
| 63 | + reasoning: 'Successfully retrieved prices', |
| 64 | + response: { |
| 65 | + prices: priceInfos, |
| 66 | + timestamp: new Date().toISOString(), |
| 67 | + }, |
| 68 | + status: 'success', |
| 69 | + query: `Get prices for ${coinTypes.join(', ')}`, |
| 70 | + errors: [], |
| 71 | + }, |
| 72 | + ]); |
| 73 | + } catch (error) { |
| 74 | + return JSON.stringify([ |
| 75 | + handleError(error, { |
| 76 | + reasoning: 'Failed to fetch prices', |
| 77 | + query: `Get prices for ${coinTypes.join(', ')}`, |
| 78 | + }), |
| 79 | + ]); |
| 80 | + } |
117 | 81 | } |
118 | 82 | } |
| 83 | + |
| 84 | +export { PriceTool }; |
0 commit comments