import { Config } from '@blockworks-foundation/mango-client' ; import { MARKETS as DEFAULT_SERUM_MARKETS } from '@project-serum/serum' ; import didYouMean from 'didyoumean2' ; import { SerumMarket } from './types' ; export const wait = ( delayMS ) => new Promise ( ( resolve ) => setTimeout ( resolve , delayMS ) ) ; export function getDidYouMean ( input , allowedValues ) { let tip = '' ; if ( typeof input === 'string' ) { let result = didYouMean ( input , allowedValues , { } ) ; if ( result !== null ) { tip = ` Did you mean '${ result }'?` ; } } return tip ; } export function getAllowedValuesText ( allowedValues ) { return `Allowed values: ${ allowedValues . map ( ( val ) => `'${ val }'` ) . join ( ', ' ) }.` ; } export function * batch < T > ( items , batchSize ) { for ( let i = 0 ; i < items . length ; i += batchSize ) { yield items . slice ( i , i + batchSize ) ; } } export function decimalPlaces ( n ) { var s = '' + + n ; var match = /(?:\.(\d+))?(?:[eE]([+\-]?\d+))?$/ . exec ( s ) ; if ( ! match ) { return 0 ; } return Math . max ( 0 , ( match [ 1 ] == '0' ? 0 : ( match [ 1 ] || '' ) . length ) - ( + match [ 2 ] ! || 0 ) ) ; } export class CircularBuffer < T > { private _buffer : T [ ] = [ ] ; private _index : number = 0 ; constructor ( private readonly _bufferSize ) { } append ( value ) { const isFull = this . _buffer . length === this . _bufferSize ; let poppedValue ; if ( isFull ) { poppedValue = this . _buffer [ this . _index ] ; } this . _buffer [ this . _index ] = value ; this . _index = ( this . _index + 1 ) % this . _bufferSize ; return poppedValue ; } * items ( ) { for ( let i = 0 ; i < this . _buffer . length ; i ++ ) { const index = ( this . _index + i ) % this . _buffer . length ; yield this . _buffer [ index ] ! ; } } get count ( ) { return this . _buffer . length ; } clear ( ) { this . _buffer = [ ] ; this . _index = 0 ; } } const { BroadcastChannel } = require ( 'worker_threads' ) ; export const minionReadyChannel = new BroadcastChannel ( 'MinionReady' ) as BroadcastChannel ; export const serumProducerReadyChannel = new BroadcastChannel ( 'SerumProducerReady' ) as BroadcastChannel ; export const serumDataChannel = new BroadcastChannel ( 'SerumData' ) as BroadcastChannel ; export const serumMarketsChannel = new BroadcastChannel ( 'SerumMarkets' ) as BroadcastChannel ; export const cleanupChannel = new BroadcastChannel ( 'Cleanup' ) as BroadcastChannel ; export async function executeAndRetry < T > ( operation , { maxRetries } ) { let attempts = 0 ; while ( true ) { attempts ++ ; try { return await operation ( attempts ) ; } catch ( err ) { if ( attempts > maxRetries ) { throw err ; } await wait ( 500 * attempts * attempts ) ; } } } export function getMangoSpotMarkets ( ) { const mangoGroupConfig = Config . ids ( ) . groups . filter ( ( group ) => group . name === 'mainnet.1' ) [ 0 ] ! ; return mangoGroupConfig . spotMarkets . map ( ( market ) => { return { name : market . name , address : market . publicKey . toBase58 ( ) , programId : mangoGroupConfig . serumProgramId . toBase58 ( ) , deprecated : false } ; } ) ; } export function getDefaultMarkets ( ) { const defaultMarkets = [ ] ; for ( const market of DEFAULT_SERUM_MARKETS ) { if ( market . deprecated ) { continue ; } if ( defaultMarkets . some ( ( s ) => s . name === market . name ) ) { continue ; } defaultMarkets . push ( { name : market . name , address : market . address . toBase58 ( ) , programId : market . programId . toBase58 ( ) , deprecated : false } ) ; } for ( const mangoSpotMarket of getMangoSpotMarkets ( ) ) { if ( defaultMarkets . some ( ( s ) => s . name === mangoSpotMarket . name ) ) { continue ; } defaultMarkets . push ( mangoSpotMarket ) ; } return defaultMarkets ; }