98 lines
3.0 KiB
TypeScript
98 lines
3.0 KiB
TypeScript
import { create } from "zustand";
|
|
import axios, { AxiosError } from "axios";
|
|
import { join } from "../utils/path";
|
|
import { messages } from "../utils/constants";
|
|
import { apiBaseUrl, apiKey } from "../utils/conf";
|
|
import { ICoinPrice } from "../utils/interfaces"
|
|
|
|
const init = {
|
|
coinId: null,
|
|
coinPrices: null,
|
|
loading: false,
|
|
error: null,
|
|
}
|
|
|
|
interface ICoinPricesState {
|
|
coinId: string | null;
|
|
coinPrices: ICoinPrice[] | null;
|
|
loading: boolean;
|
|
error: string | null;
|
|
reset: () => void;
|
|
persistCoinPrices: (coinId: string, coinPrices: ICoinPrice[]) => void;
|
|
setError: (message: string) => void;
|
|
fetch: (coinId: string, limit: number) => void;
|
|
}
|
|
|
|
export const useCoinPricesStore = create<ICoinPricesState>((set, get) => {
|
|
return {
|
|
...init,
|
|
reset: () => {
|
|
set(state => ({
|
|
...init,
|
|
}))
|
|
},
|
|
persistCoinPrices: (coinId, coinPrices) => {
|
|
set(state => ({
|
|
coinId: coinId,
|
|
coinPrices: coinPrices,
|
|
}))
|
|
},
|
|
setError: (message) => {
|
|
set(state => ({
|
|
error: message,
|
|
}))
|
|
},
|
|
fetch: async (coinId, limit) => {
|
|
try {
|
|
set({ loading: true });
|
|
const keyParam = (apiKey()) ? `&x_cg_demo_api_key=${apiKey()}` : "";
|
|
const url = join(apiBaseUrl(), `coins/${coinId}/market_chart?vs_currency=usd&days=${limit}${keyParam}`);
|
|
const res = await axios.get(url);
|
|
|
|
let prices: ICoinPrice[] = res.data?.["prices"].map((item: any) => {
|
|
let price: ICoinPrice = {
|
|
price: item[1],
|
|
timestamp: item[0],
|
|
}
|
|
return price;
|
|
});
|
|
get().persistCoinPrices(coinId, prices);
|
|
|
|
} catch (err) {
|
|
if (axios.isAxiosError(err)) {
|
|
switch (err.code) {
|
|
case 'ERR_NETWORK':
|
|
get().setError(messages.serverOverload);
|
|
break;
|
|
default:
|
|
get().setError(err.message);
|
|
}
|
|
} else {
|
|
get().setError((err as Error).message);
|
|
}
|
|
} finally {
|
|
set({ loading: false });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
export const reset = () => {
|
|
useCoinPricesStore.getState().reset();
|
|
}
|
|
|
|
export const persist = (coinId: string, prices: ICoinPrice[]) => {
|
|
useCoinPricesStore.getState().persistCoinPrices(coinId, prices);
|
|
};
|
|
|
|
export const toggleLoading = (isLoading: boolean) => {
|
|
useCoinPricesStore.setState({ loading: isLoading })
|
|
};
|
|
|
|
export const errorLoading = (message: string) => {
|
|
useCoinPricesStore.setState({ error: message });
|
|
};
|
|
|
|
export const fetchCoinPrices = (coinId: string, limit = 10) => {
|
|
useCoinPricesStore.getState().fetch(coinId, limit);
|
|
}; |