import { asNumberIfValid , upperCaseSymbols } from '../handy' ; import { BookChange , BookTicker , Trade } from '../types' ; import { Mapper } from './mapper' ; export const krakenTradesMapper = { canHandle ( message ) { if ( ! Array . isArray ( message ) ) { return false ; } const channel = message [ message . length - 2 ] as string ; return channel === 'trade' ; } , getFilters ( symbols ? ) { symbols = upperCaseSymbols ( symbols ) ; return [ { channel : 'trade' , symbols } ] ; } , * map ( message , localTimestamp ) { const [ _ , trades , __ , symbol ] = message ; for ( const [ price , amount , time , side ] of trades ) { const timeExchange = Number ( time ) ; const timestamp = new Date ( timeExchange * 1000 ) ; timestamp . μs = Math . floor ( timeExchange * 1000000 ) % 1000 ; yield { type : 'trade' , symbol , exchange : 'kraken' , id : undefined , price : Number ( price ) , amount : Number ( amount ) , side : side === 'b' ? 'buy' : 'sell' , timestamp , localTimestamp } ; } } } ; const mapBookLevel = ( level ) => { const [ price , amount ] = level ; return { price : Number ( price ) , amount : Number ( amount ) } ; } ; const getLatestTimestamp = ( bids , asks ) : Date => { const timestampsSorted = [ ... bids . map ( ( b ) => Number ( b [ 2 ] ) ) , ... asks . map ( ( b ) => Number ( b [ 2 ] ) ) ] . sort ( ) ; const lastBookUpdateTime = timestampsSorted [ timestampsSorted . length - 1 ] ; const timestamp = new Date ( lastBookUpdateTime * 1000 ) ; timestamp . μs = Math . floor ( lastBookUpdateTime * 1000000 ) % 1000 ; return timestamp ; } ; export const krakenBookChangeMapper = { canHandle ( message ) { if ( ! Array . isArray ( message ) ) { return false ; } const channel = message [ message . length - 2 ] as string ; return channel . startsWith ( 'book' ) ; } , getFilters ( symbols ? ) { symbols = upperCaseSymbols ( symbols ) ; return [ { channel : 'book' , symbols } ] ; } , * map ( message , localTimestamp ) { if ( 'as' in message [ 1 ] ) { const [ _ , { as , bs } , __ , symbol ] = message ; yield { type : 'book_change' , symbol : symbol , exchange : 'kraken' , isSnapshot : true , bids : bs . map ( mapBookLevel ) , asks : as . map ( mapBookLevel ) , timestamp : getLatestTimestamp ( as , bs ) , localTimestamp : localTimestamp } ; } else { const symbol = message [ message . length - 1 ] as string ; const asks = 'a' in message [ 1 ] ? message [ 1 ] . a : [ ] ; const bids = 'b' in message [ 1 ] ? message [ 1 ] . b : typeof message [ 2 ] !== 'string' && 'b' in message [ 2 ] ? message [ 2 ] . b : [ ] ; yield { type : 'book_change' , symbol , exchange : 'kraken' , isSnapshot : false , bids : bids . map ( mapBookLevel ) , asks : asks . map ( mapBookLevel ) , timestamp : getLatestTimestamp ( asks , bids ) , localTimestamp : localTimestamp } ; } } } ; export const krakenBookTickerMapper = { canHandle ( message ) { if ( ! Array . isArray ( message ) ) { return false ; } const channel = message [ message . length - 2 ] as string ; return channel === 'spread' ; } , getFilters ( symbols ? ) { symbols = upperCaseSymbols ( symbols ) ; return [ { channel : 'spread' , symbols } ] ; } , * map ( message , localTimestamp ) { const [ bid , ask , time , bidVolume , askVolume ] = message [ 1 ] ; const timeExchange = Number ( time ) ; if ( timeExchange === 0 ) { return ; } const timestamp = new Date ( timeExchange * 1000 ) ; timestamp . μs = Math . floor ( timeExchange * 1000000 ) % 1000 ; const ticker = { type : 'book_ticker' , symbol : message [ 3 ] , exchange : 'kraken' , askAmount : asNumberIfValid ( askVolume ) , askPrice : asNumberIfValid ( ask ) , bidPrice : asNumberIfValid ( bidVolume ) , bidAmount : asNumberIfValid ( bid ) , timestamp , localTimestamp : localTimestamp } ; yield ticker ; } } ; type KrakenTrades = [ number , [ string , string , string , 's' | 'b' , string , string ] [ ] , string , string ] ; type KrakenBookLevel = [ string , string , string ] ; type KrakenBookSnapshot = [ number , { as : KrakenBookLevel [ ] ; bs : KrakenBookLevel [ ] ; } , string , string ] ; type KrakenBookUpdate = [ number , ( { a : KrakenBookLevel [ ] ; } | { b : KrakenBookLevel [ ] ; } ) , string , string ] | [ number , { a : KrakenBookLevel [ ] ; } , { b : KrakenBookLevel [ ] ; } , string , string ] ; type KrakenSpread = [ 325 , [ bid : '43770.20000' , ask : '43770.30000' , timestamp : '1633053779.916349' , bidVolume : '0.00917717' , askVolume : '0.31670440' ] , 'spread' , 'XBT/USD' ] ;