import { FetchError } from 'node-fetch' ; import { Big } from '@goldenagellc/web3-blocks' ; import { CoinbaseKey , coinbaseKeyMap } from './types/CoinbaseKeys' ; import IPrice from './types/IPrice' ; import CoinbaseReporter from './CoinbaseReporter' ; import PriceLedger from './PriceLedger' ; export default class StatefulPricesCoinbase extends CoinbaseReporter { private readonly ledger : PriceLedger ; private fetchHandle : NodeJS . Timeout | null = null ; private consumers : ( ( ) => Promise < void > | void ) [ ] = [ ] ; constructor ( ledger , coinbaseEndpoint , coinbaseKey , coinbaseSecret , coinbasePassphrase ) { super ( coinbaseEndpoint , coinbaseKey , coinbaseSecret , coinbasePassphrase ) ; this . ledger = ledger ; } public async init ( fetchInterval = 120000 ) { await this . update ( ) ; if ( this . fetchHandle !== null ) clearInterval ( this . fetchHandle ) ; this . fetchHandle = setInterval ( this . update . bind ( this ) , fetchInterval ) ; } public register ( consumer ) { return this . consumers . push ( consumer ) - 1 ; } public remove ( consumerId ) { this . consumers . splice ( consumerId , 1 ) ; } private async update ( ) { const updatedKeys = await this . fetch ( ) ; if ( updatedKeys . length > 0 ) { this . consumers . forEach ( ( consumer ) => consumer ( ) ) ; } } private async fetch ( ) { try { const updatedKeys = [ ] ; const report = await this . fetchCoinbasePrices ( ) ; if ( report . message === 'request timestamp expired' ) { console . warn ( 'Coinbase fetch failed -- request timestamp outdated' ) ; return [ ] ; } for ( let i = 0 ; i < report . messages . length ; i += 1 ) { const message = report . messages [ i ] ; const signature = report . signatures [ i ] ; const { timestamp , key , price : value } = StatefulPricesCoinbase . decode ( message ) ; if ( ! Object . keys ( coinbaseKeyMap ) . includes ( key ) ) continue ; const knownKey = key as CoinbaseKey ; const price = { value : new Big ( value ) , timestamp : timestamp } ; if ( this . ledger . append ( knownKey , price , message , signature ) ) updatedKeys . push ( knownKey ) ; } return updatedKeys ; } catch ( e ) { if ( e instanceof FetchError ) console . warn ( 'Coinbase fetch failed -- probably lost internet' ) ; else console . warn ( e ) ; return [ ] ; } } public stop ( ) { if ( this . fetchHandle !== null ) clearInterval ( this . fetchHandle ) ; } }