From b17b840e0c1b7c2404212057c03725988c326b4d Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Sat, 22 Apr 2023 19:54:27 +0200 Subject: [PATCH 1/2] refactor: Rewrite to CurrencyCache --- src/index.ts | 67 ++++++++++++++++---------------- src/structures/Amount.ts | 33 +++------------- src/structures/CryptoCurrency.ts | 17 ++++++++ src/structures/CurrencyCache.ts | 30 ++++++++++++++ src/structures/ExchangeRate.ts | 3 +- src/structures/FiatCurrency.ts | 21 +++++++++- src/structures/Transaction.ts | 4 +- src/structures/Wallet.ts | 4 +- src/utils/CacheHandler.ts | 48 ----------------------- 9 files changed, 107 insertions(+), 120 deletions(-) create mode 100644 src/structures/CurrencyCache.ts delete mode 100644 src/utils/CacheHandler.ts diff --git a/src/index.ts b/src/index.ts index 8593474..f6762cc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,16 +1,14 @@ import { EventEmitter } from 'node:events'; import RequestHandler from './structures/RequestHandler'; import Transaction from './structures/Transaction'; -import { - getCachedCryptoCurrencies, - getCachedCryptoCurrency, - updateFiatCurrenciesCache, -} from './utils/CacheHandler'; -import { updateCurrenciesCache } from './utils/CacheHandler'; +import CurrencyCache from './structures/CurrencyCache'; import CryptoCurrency from './structures/CryptoCurrency'; +import FiatCurrency from './structures/FiatCurrency'; import ExchangeRate from './structures/ExchangeRate'; import Wallet from './structures/Wallet'; import { + RESTGetAPICurrenciesCryptoCurrenciesResult, + RESTGetAPICurrenciesFiatsResult, RESTGetAPIAccountTransactionResult, RESTGetAPIAccountTransactionsResult, RESTGetAPIAccountWalletResult, @@ -34,6 +32,10 @@ class TipccClient extends EventEmitter { public REST: RequestHandler; + public cryptos = new CurrencyCache(this._refreshCryptos); + + public fiats = new CurrencyCache(this._refreshFiats); + public isReady = false; public pollingInterval = 10000; @@ -74,10 +76,7 @@ class TipccClient extends EventEmitter { if (options.pollingInterval) this.pollingInterval = options.pollingInterval; if (options.maxRetries) this.maxRetries = options.maxRetries; - Promise.all([ - updateCurrenciesCache(this), - updateFiatCurrenciesCache(this), - ]).then(() => { + Promise.all([this.cryptos.refresh(), this.fiats.refresh()]).then(() => { this.emit('ready'); this.isReady = true; }); @@ -116,8 +115,8 @@ class TipccClient extends EventEmitter { if (this.pollingRetries > 0) this.pollingRetries = 0; for (const transaction of transactions) { - if (!getCachedCryptoCurrency(transaction.amount.currency)) - await updateCurrenciesCache(this); + if (!this.cryptos.get(transaction.amount.currency)) + await this.cryptos.refresh(); this.emit(transaction.type, new Transaction(transaction)); } @@ -136,6 +135,28 @@ class TipccClient extends EventEmitter { } } + private async _refreshCryptos(): Promise { + const { cryptocurrencies } = (await this.REST.request( + 'GET', + Routes.currenciesCryptocurrencies(), + )) as RESTGetAPICurrenciesCryptoCurrenciesResult; + + const processed = cryptocurrencies.map((c) => new CryptoCurrency(c)); + + return processed; + } + + private async _refreshFiats(): Promise { + const { fiats } = (await this.REST.request( + 'GET', + Routes.currenciesFiats(), + )) as RESTGetAPICurrenciesFiatsResult; + + const processed = fiats.map((c) => new FiatCurrency(c)); + + return processed; + } + public on(s: K, f: (arg: Events[K]) => void): this { super.on(s, f); this.polling.add(s); @@ -150,28 +171,6 @@ class TipccClient extends EventEmitter { return this; } - /** - * Get a list of cryptocurrencies. - * @param cache Whether to use the cache (`true` by default) - */ - public async getCryptoCurrencies(cache = true): Promise { - const currencies = getCachedCryptoCurrencies(); - if (currencies.length > 0 && cache) return currencies; - await updateCurrenciesCache(this); - return getCachedCryptoCurrencies(); - } - - /** - * Get a list of fiat currencies. - * @param cache Whether to use the cache (`true` by default) - */ - public async getFiatCurrencies(cache = true): Promise { - const currencies = getCachedCryptoCurrencies(); - if (currencies.length > 0 && cache) return currencies; - await updateCurrenciesCache(this); - return getCachedCryptoCurrencies(); - } - /** * Get a list of transactions based on options. * @param options Which options to use when requesting transactions diff --git a/src/structures/Amount.ts b/src/structures/Amount.ts index 032a519..be382b5 100644 --- a/src/structures/Amount.ts +++ b/src/structures/Amount.ts @@ -1,43 +1,20 @@ import BigNumber from 'bignumber.js'; import type { APICoin, APIMonetary } from '@tipccjs/tipcc-api-types'; -import CryptoCurrency from './CryptoCurrency'; -import { - getCachedCryptoCurrency, - getCachedFiatCurrency, -} from '../utils/CacheHandler'; -import FiatCurrency from './FiatCurrency'; - /** * A class for storing an API amount. This can be used for either fiats or cryptocurrencies. */ export default class Amount { - public value: BigNumber; + public valueRaw: BigNumber; - public currency: CryptoCurrency | FiatCurrency | null; + public currency: string; /** * Create an Amount. * @param payload An amount from the API - * @param currencyType The type of currency */ - constructor( - payload: APIMonetary | APICoin, - currencyType: 'fiat' | 'crypto' = 'crypto', - ) { - this.value = BigNumber(payload.value); - switch (currencyType) { - case 'crypto': - this.currency = getCachedCryptoCurrency(payload.currency) ?? null; - break; - case 'fiat': - this.currency = getCachedFiatCurrency(payload.currency) ?? null; - break; - } - } - - get humanValue(): BigNumber { - if (!this.currency) throw new Error('Currency is not defined'); - return this.value.shiftedBy(this.currency.format.scale * -1); + constructor(payload: APIMonetary | APICoin) { + this.valueRaw = BigNumber(payload.value); + this.currency = payload.currency; } } diff --git a/src/structures/CryptoCurrency.ts b/src/structures/CryptoCurrency.ts index a499daa..f853e84 100644 --- a/src/structures/CryptoCurrency.ts +++ b/src/structures/CryptoCurrency.ts @@ -1,3 +1,4 @@ +import BigNumber from 'bignumber.js'; import type { APICryptoCurrency } from '@tipccjs/tipcc-api-types'; import CryptoCurrencyFormat from './CurrencyFormat'; @@ -26,4 +27,20 @@ export default class CryptoCurrency { this.explorer = payload.explorer; this.format = new CryptoCurrencyFormat(payload.format); } + + /** + * Convert a raw value to an amount. + * @param value The raw value + */ + public convertToAmount(value: BigNumber): BigNumber { + return BigNumber(value).shiftedBy(this.format.scale * -1); + } + + /** + * Convert an amount to a raw value. + * @param value The amount + */ + public convertToRaw(value: BigNumber): BigNumber { + return value.shiftedBy(this.format.scale); + } } diff --git a/src/structures/CurrencyCache.ts b/src/structures/CurrencyCache.ts new file mode 100644 index 0000000..dae1cc3 --- /dev/null +++ b/src/structures/CurrencyCache.ts @@ -0,0 +1,30 @@ +export default class CurrencyCache extends Array { + private refreshFunction: () => T[] | Promise; + + constructor(refreshFunction: () => T[] | Promise) { + super(); + + this.refreshFunction = refreshFunction; + } + + /** + * Refresh this CurrencyCache with new values received from refreshFunction. + */ + public async refresh(): Promise> { + const refreshedData = await this.refreshFunction(); + this.splice(0, this.length, refreshedData); + + return this; + } + + /** + * A shortcut to find a currency by code. + * @param code The code to search for + */ + public async get(code: string): Promise { + const found = this.find((i) => i.code === code); + if (found) return found; + + return null; + } +} diff --git a/src/structures/ExchangeRate.ts b/src/structures/ExchangeRate.ts index a8af0fb..6c8f504 100644 --- a/src/structures/ExchangeRate.ts +++ b/src/structures/ExchangeRate.ts @@ -18,7 +18,6 @@ export default class ExchangeRate { constructor(payload: APIExchangeRate) { this.code = payload.code; this.name = payload.name; - if (payload.usd_value) - this.usdValue = new Amount(payload.usd_value, 'fiat'); + if (payload.usd_value) this.usdValue = new Amount(payload.usd_value); } } diff --git a/src/structures/FiatCurrency.ts b/src/structures/FiatCurrency.ts index 8c0dc97..e5f87af 100644 --- a/src/structures/FiatCurrency.ts +++ b/src/structures/FiatCurrency.ts @@ -1,8 +1,9 @@ +import BigNumber from 'bignumber.js'; import type { APIFiatCurrency } from '@tipccjs/tipcc-api-types'; import CurrencyFormat from './CurrencyFormat'; /** - * A class for storing an API cryptocurrency. + * A class for storing an API fiat currency. */ export default class FiatCurrency { public code: string; @@ -12,7 +13,7 @@ export default class FiatCurrency { public format: CurrencyFormat; /** - * Create a CryptoCurrency. + * Create a FiatCurrency. * @param payload The currency from the API */ constructor(payload: APIFiatCurrency) { @@ -20,4 +21,20 @@ export default class FiatCurrency { this.name = payload.name; this.format = new CurrencyFormat(payload.format); } + + /** + * Convert a raw value to an amount. + * @param value The raw value + */ + public convertToAmount(value: BigNumber): BigNumber { + return BigNumber(value).shiftedBy(this.format.scale * -1); + } + + /** + * Convert an amount to a raw value. + * @param value The amount + */ + public convertToRaw(value: BigNumber): BigNumber { + return value.shiftedBy(this.format.scale); + } } diff --git a/src/structures/Transaction.ts b/src/structures/Transaction.ts index 984a951..52817e9 100644 --- a/src/structures/Transaction.ts +++ b/src/structures/Transaction.ts @@ -37,9 +37,7 @@ export default class Transaction { this.type = payload.type; this.amount = new Amount(payload.amount); this.fee = payload.fee ? new Amount(payload.fee) : null; - this.usdValue = payload.usd_value - ? new Amount(payload.usd_value, 'fiat') - : null; + this.usdValue = payload.usd_value ? new Amount(payload.usd_value) : null; this.service = payload.service; this.chatId = payload.chat_id; this.subchatId = payload.subchat_id; diff --git a/src/structures/Wallet.ts b/src/structures/Wallet.ts index 6e43bd6..6c0ecfb 100644 --- a/src/structures/Wallet.ts +++ b/src/structures/Wallet.ts @@ -21,8 +21,6 @@ export default class Wallet { this.code = payload.code; this.name = payload.name; this.balance = new Amount(payload.balance); - this.usdValue = payload.usd_value - ? new Amount(payload.usd_value, 'fiat') - : null; + this.usdValue = payload.usd_value ? new Amount(payload.usd_value) : null; } } diff --git a/src/utils/CacheHandler.ts b/src/utils/CacheHandler.ts deleted file mode 100644 index 33e56d3..0000000 --- a/src/utils/CacheHandler.ts +++ /dev/null @@ -1,48 +0,0 @@ -import type { - RESTGetAPICurrenciesCryptoCurrenciesResult, - RESTGetAPICurrenciesFiatsResult, -} from '@tipccjs/tipcc-api-types'; -import TipccClient from '../'; -import CryptoCurrency from '../structures/CryptoCurrency'; -import FiatCurrency from '../structures/FiatCurrency'; - -const cryptoCurrenciesCache: CryptoCurrency[] = []; -const fiatCurrenciesCache: FiatCurrency[] = []; - -export const updateCurrenciesCache = async ( - client: TipccClient, -): Promise => { - const { cryptocurrencies } = (await client.REST.request( - 'GET', - '/currencies/cryptocurrencies', - )) as RESTGetAPICurrenciesCryptoCurrenciesResult; - cryptoCurrenciesCache.splice( - 0, - cryptoCurrenciesCache.length, - ...cryptocurrencies.map((c) => new CryptoCurrency(c)), - ); -}; -export const getCachedCryptoCurrency = ( - code: string, -): CryptoCurrency | undefined => - cryptoCurrenciesCache.find((c) => c.code === code); -export const getCachedCryptoCurrencies = (): CryptoCurrency[] => - cryptoCurrenciesCache; - -export const updateFiatCurrenciesCache = async ( - client: TipccClient, -): Promise => { - const { fiats } = (await client.REST.request( - 'GET', - '/currencies/fiats', - )) as RESTGetAPICurrenciesFiatsResult; - fiatCurrenciesCache.splice( - 0, - fiatCurrenciesCache.length, - ...fiats.map((c) => new FiatCurrency(c)), - ); -}; -export const getCachedFiatCurrency = (code: string): FiatCurrency | undefined => - fiatCurrenciesCache.find((c) => c.code === code); -export const getCachedFiatCurrencies = (): FiatCurrency[] => - fiatCurrenciesCache; From 7165da49a94c2ffbf12612c8b49a08004256311d Mon Sep 17 00:00:00 2001 From: ZeroWave022 <36341766+ZeroWave022@users.noreply.github.com> Date: Sat, 22 Apr 2023 20:29:06 +0200 Subject: [PATCH 2/2] refactor: Rename helper functions on currencies --- src/structures/CryptoCurrency.ts | 6 +++--- src/structures/FiatCurrency.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/structures/CryptoCurrency.ts b/src/structures/CryptoCurrency.ts index f853e84..750bb77 100644 --- a/src/structures/CryptoCurrency.ts +++ b/src/structures/CryptoCurrency.ts @@ -29,15 +29,15 @@ export default class CryptoCurrency { } /** - * Convert a raw value to an amount. + * Convert a raw value to a BigNumber in human readable format. * @param value The raw value */ - public convertToAmount(value: BigNumber): BigNumber { + public convertFromRaw(value: BigNumber): BigNumber { return BigNumber(value).shiftedBy(this.format.scale * -1); } /** - * Convert an amount to a raw value. + * Convert a BigNumber value in human readable format to a raw API BigNumber. * @param value The amount */ public convertToRaw(value: BigNumber): BigNumber { diff --git a/src/structures/FiatCurrency.ts b/src/structures/FiatCurrency.ts index e5f87af..56cafcf 100644 --- a/src/structures/FiatCurrency.ts +++ b/src/structures/FiatCurrency.ts @@ -23,15 +23,15 @@ export default class FiatCurrency { } /** - * Convert a raw value to an amount. + * Convert a raw value to a BigNumber in human readable format. * @param value The raw value */ - public convertToAmount(value: BigNumber): BigNumber { + public convertFromRaw(value: BigNumber): BigNumber { return BigNumber(value).shiftedBy(this.format.scale * -1); } /** - * Convert an amount to a raw value. + * Convert a BigNumber value in human readable format to a raw API BigNumber. * @param value The amount */ public convertToRaw(value: BigNumber): BigNumber {