diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..d74f8d15 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +node_modules/ +dist/ +.env +__pycache__/ +*.log +.DS_Store +*.test.js +*.test.ts \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..014bc285 --- /dev/null +++ b/package.json @@ -0,0 +1,23 @@ +{ + "name": "coin-gekko-api", + "version": "1.0.0", + "description": "Coin Gekko API", + "main": "dist/index.js", + "scripts": { + "build": "tsc", + "test": "vitest", + "start": "node dist/index.js" + }, + "keywords": ["crypto", "api", "gekko"], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^16.11.6", + "typescript": "^4.4.4", + "vitest": "^0.25.3", + "axios-mock-adapter": "^1.20.0" + }, + "dependencies": { + "axios": "^0.24.0" + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..d73d510a --- /dev/null +++ b/src/index.ts @@ -0,0 +1,79 @@ +import axios from 'axios'; + +export interface CoinData { + id: string; + symbol: string; + name: string; + price: number; + marketCap: number; +} + +export class CoinGekkoApi { + private baseUrl: string; + + constructor(baseUrl: string = 'https://api.coingecko.com/api/v3') { + this.baseUrl = baseUrl; + } + + /** + * Fetch coin data by ID + * @param coinId - The ID of the coin + * @returns Promise resolving to CoinData + */ + async getCoinById(coinId: string): Promise { + if (!coinId) { + throw new Error('Coin ID is required'); + } + + try { + const response = await axios.get(`${this.baseUrl}/coins/${coinId}`); + return { + id: response.data.id, + symbol: response.data.symbol, + name: response.data.name, + price: response.data.market_data.current_price.usd, + marketCap: response.data.market_data.market_cap.usd + }; + } catch (error) { + if (axios.isAxiosError(error)) { + if (error.response?.status === 404) { + throw new Error(`Coin with ID ${coinId} not found`); + } + throw new Error(`API request failed: ${error.message}`); + } + throw error; + } + } + + /** + * List top cryptocurrencies by market cap + * @param limit - Number of coins to retrieve (default 10) + * @returns Promise resolving to array of CoinData + */ + async getTopCoins(limit: number = 10): Promise { + if (limit < 1) { + throw new Error('Limit must be at least 1'); + } + + try { + const response = await axios.get(`${this.baseUrl}/coins/markets`, { + params: { + vs_currency: 'usd', + order: 'market_cap_desc', + per_page: limit, + page: 1 + } + }); + + return response.data.map((coin: any) => ({ + id: coin.id, + symbol: coin.symbol, + name: coin.name, + price: coin.current_price, + marketCap: coin.market_cap + })); + } catch (error) { + throw new Error(`Failed to fetch top coins: ${error instanceof Error ? error.message : 'Unknown error'}`); + } + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..628bb47a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es2020", + "module": "commonjs", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "outDir": "./dist" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "**/*.spec.ts"] +} \ No newline at end of file