This commit is contained in:
geoffsee
2025-05-23 09:48:26 -04:00
commit 66d3c06230
84 changed files with 6529 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
import {ApiResponse} from "./types";
export async function collect_quote(x: { symbol: string, apiKey: string }) {
const {symbol, apiKey} = x;
const data: ApiResponse = await fetch(`https://pro-api.coinmarketcap.com/v2/cryptocurrency/quotes/latest?symbol=${symbol}`, {
headers: {
"x-cmc_pro_api_key": apiKey
}
}).then((symbolDataRequest) => symbolDataRequest.json());
return data;
}

View File

@@ -0,0 +1,77 @@
import {types, flow, Instance} from "mobx-state-tree";
import {collect_quote} from './index';
const QuoteData = types.optional(types.frozen(), {})
export const QuoteStore = types
.model("QuoteStore", {
apiKey: types.string,
quotes: types.map(QuoteData),
})
.views(self => ({
getQuote(symbol) {
return self.quotes.get(symbol);
},
hasQuote(symbol) {
return self.quotes.has(symbol);
}
}))
.actions(self => {
const extractUsefulData = (data, symbol) => {
return data.data[symbol].map(qd => ({
symbol: qd.symbol,
slug: qd.slug,
tags: qd.tags,
id: qd.id,
...qd.quote.USD
})).at(0);
};
const fetchQuote = flow(function* (symbol) {
try {
const data = yield collect_quote({symbol, apiKey: self.apiKey});
const usefulData = extractUsefulData(data, symbol);
self.quotes.set(symbol, usefulData);
return usefulData;
} catch (error) {
console.error(`An error occurred fetching the quote for symbol: ${symbol}`, error);
throw error;
}
});
const fetchQuotes = flow(function* (symbols) {
const results = {};
for (const symbol of symbols) {
if (self.quotes.has(symbol)) {
results[symbol] = self.quotes.get(symbol);
} else {
const data = yield fetchQuote(symbol);
results[symbol] = extractUsefulData(data, symbol);
}
}
return results;
});
const clearCache = () => {
self.quotes.clear();
};
return {
fetchQuote,
fetchQuotes,
clearCache
};
});
export type QuoteManagerType = Instance<typeof QuoteStore>;

View File

@@ -0,0 +1,17 @@
import {describe, it} from 'vitest';
import {QuoteStore} from "./models";
describe('QuoteStore', () => {
it('should get data for symbols using the quoteManager', async () => {
const testApiKey = '';
const quoteManager = QuoteStore.create({
apiKey: testApiKey,
});
const symbol = 'BTC';
const data = await quoteManager.fetchQuote(symbol);
console.log(JSON.stringify(data));
});
});

View File

@@ -0,0 +1,71 @@
type Status = {
timestamp: string;
error_code: number;
error_message: string | null;
elapsed: number;
credit_count: number;
notice: string | null;
};
type Tag = {
slug: string;
name: string;
category: string;
};
type Quote = {
USD: {
price: number | null;
volume_24h: number;
volume_change_24h: number;
percent_change_1h: number;
percent_change_24h: number;
percent_change_7d: number;
percent_change_30d: number;
percent_change_60d: number;
percent_change_90d: number;
market_cap: number | null;
market_cap_dominance: number | null;
fully_diluted_market_cap: number | null;
tvl: number | null;
last_updated: string;
};
};
type Platform = {
id: number;
name: string;
symbol: string;
slug: string;
token_address: string;
};
type Cryptocurrency = {
id: number;
name: string;
symbol: string;
slug: string;
num_market_pairs: number;
date_added: string;
tags: Tag[];
max_supply: number | null;
circulating_supply: number | null;
total_supply: number;
platform: Platform | null;
is_active: number;
infinite_supply: boolean;
cmc_rank: number | null;
is_fiat: number;
self_reported_circulating_supply: number | null;
self_reported_market_cap: number | null;
tvl_ratio: number | null;
last_updated: string;
quote: Quote;
};
export type ApiResponse = {
status: Status;
data: {
[SYMBOL: string]: Cryptocurrency[];
};
};