Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 33 additions & 34 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -34,6 +32,10 @@ class TipccClient extends EventEmitter {

public REST: RequestHandler;

public cryptos = new CurrencyCache<CryptoCurrency>(this._refreshCryptos);

public fiats = new CurrencyCache<FiatCurrency>(this._refreshFiats);

public isReady = false;

public pollingInterval = 10000;
Expand Down Expand Up @@ -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;
});
Expand Down Expand Up @@ -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));
}

Expand All @@ -136,6 +135,28 @@ class TipccClient extends EventEmitter {
}
}

private async _refreshCryptos(): Promise<CryptoCurrency[]> {
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<FiatCurrency[]> {
const { fiats } = (await this.REST.request(
'GET',
Routes.currenciesFiats(),
)) as RESTGetAPICurrenciesFiatsResult;

const processed = fiats.map((c) => new FiatCurrency(c));

return processed;
}

public on<K extends keyof Events>(s: K, f: (arg: Events[K]) => void): this {
super.on(s, f);
this.polling.add(s);
Expand All @@ -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<CryptoCurrency[]> {
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<CryptoCurrency[]> {
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
Expand Down
33 changes: 5 additions & 28 deletions src/structures/Amount.ts
Original file line number Diff line number Diff line change
@@ -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;
}
}
17 changes: 17 additions & 0 deletions src/structures/CryptoCurrency.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import BigNumber from 'bignumber.js';
import type { APICryptoCurrency } from '@tipccjs/tipcc-api-types';
import CryptoCurrencyFormat from './CurrencyFormat';

Expand Down Expand Up @@ -26,4 +27,20 @@ export default class CryptoCurrency {
this.explorer = payload.explorer;
this.format = new CryptoCurrencyFormat(payload.format);
}

/**
* Convert a raw value to a BigNumber in human readable format.
* @param value The raw value
*/
public convertFromRaw(value: BigNumber): BigNumber {
return BigNumber(value).shiftedBy(this.format.scale * -1);
}

/**
* Convert a BigNumber value in human readable format to a raw API BigNumber.
* @param value The amount
*/
public convertToRaw(value: BigNumber): BigNumber {
return value.shiftedBy(this.format.scale);
}
}
30 changes: 30 additions & 0 deletions src/structures/CurrencyCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
export default class CurrencyCache<T> extends Array {
private refreshFunction: () => T[] | Promise<T[]>;

constructor(refreshFunction: () => T[] | Promise<T[]>) {
super();

this.refreshFunction = refreshFunction;
}

/**
* Refresh this CurrencyCache with new values received from refreshFunction.
*/
public async refresh(): Promise<CurrencyCache<T>> {
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<T | null> {
const found = this.find((i) => i.code === code);
if (found) return found;

return null;
}
}
3 changes: 1 addition & 2 deletions src/structures/ExchangeRate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
21 changes: 19 additions & 2 deletions src/structures/FiatCurrency.ts
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -12,12 +13,28 @@ export default class FiatCurrency {
public format: CurrencyFormat;

/**
* Create a CryptoCurrency.
* Create a FiatCurrency.
* @param payload The currency from the API
*/
constructor(payload: APIFiatCurrency) {
this.code = payload.code;
this.name = payload.name;
this.format = new CurrencyFormat(payload.format);
}

/**
* Convert a raw value to a BigNumber in human readable format.
* @param value The raw value
*/
public convertFromRaw(value: BigNumber): BigNumber {
return BigNumber(value).shiftedBy(this.format.scale * -1);
}

/**
* Convert a BigNumber value in human readable format to a raw API BigNumber.
* @param value The amount
*/
public convertToRaw(value: BigNumber): BigNumber {
return value.shiftedBy(this.format.scale);
}
}
4 changes: 1 addition & 3 deletions src/structures/Transaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 1 addition & 3 deletions src/structures/Wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
48 changes: 0 additions & 48 deletions src/utils/CacheHandler.ts

This file was deleted.