UNPKG

@benshi.ai/js-sdk

Version:

Benshi SDK

131 lines (103 loc) 3.84 kB
import { NetworkProxy } from "../../../drivers/network/typings" import { CurrencyCode } from "../../commonTypes" import * as defaultConversions from "./usd.json" export interface Conversion { usd: number } export interface ICurrencyRepository { convertCurrencyToUSD(currencyFrom: CurrencyCode): Promise<Conversion> } interface PendingRequest { currencyFrom: CurrencyCode resolve: any } export default class CurrencyRepository implements ICurrencyRepository { private url: string private networkDriver: NetworkProxy private cache private requesting = false private pendingRequests:Array<PendingRequest> = [] public constructor(url, networkDriver) { this.url = url this.networkDriver = networkDriver const datesAreWithinAnHour = (newerDate, olderDate) => { const ONE_HOUR = 60 * 60 * 1000 return (newerDate - olderDate) < ONE_HOUR } const cacheHandler = { get: function(cache, currency) { const now = new Date() if ((cache[currency] !== undefined) && datesAreWithinAnHour(now, cache[currency].date)) { return cache[currency] } else { return undefined } } } this.cache = new Proxy({}, cacheHandler) } private purgeQueue() { // Those pending requests that already have a value in the cache will be resolved. // For the rest, the process will start again by calling the `request` method // again for them const metaPendingRequests = this.pendingRequests.map( item => ({...item, ready: false})) metaPendingRequests.forEach( (pendingRequest) => { const {currencyFrom, resolve} = pendingRequest if (this.cache[currencyFrom] !== undefined) { resolve(this.cache[currencyFrom]) pendingRequest.ready = true return } }) metaPendingRequests .filter( request => !request.ready) .forEach( request => this.request(request.currencyFrom, request.resolve)) this.pendingRequests = [] } private request(currencyFrom, resolve) { if (this.requesting) { this.pendingRequests.push({currencyFrom, resolve}) return } this.requesting = true this.networkDriver.get(`${this.url}?from=${currencyFrom}`).then((data) => { let { usd } = data as Conversion const now = new Date() if (isNaN(usd) || usd === null) { usd = 1 / defaultConversions.usd[currencyFrom.toLowerCase()] } else { this.cache[currencyFrom] = { date: now, usd: usd } } resolve({ usd: usd }) this.requesting = false this.purgeQueue() }).catch(e => { resolve({ usd: 1 / defaultConversions.usd[currencyFrom.toLowerCase()], }) return }) } public convertCurrencyToUSD = (currencyFrom: CurrencyCode): Promise<Conversion> => { return new Promise((resolve, reject) => { if (currencyFrom === CurrencyCode.USD) { resolve({ usd: 1 }) return } if ( this.cache[currencyFrom] !== undefined) { resolve(this.cache[currencyFrom]) return } // this.request(currencyFrom, resolve) const usd = 1 / defaultConversions.usd[currencyFrom.toLowerCase()] this.cache[currencyFrom] = { date: new Date(), usd: usd } resolve({ usd: usd }) }) } }