@bcswaper/apis
Version:
bcswaper apis
1 lines • 7.91 kB
JavaScript
import{IndexerConfig,ValidatorConfig,Network,IndexerClient,SocketClient,ValidatorClient,CompositeClient,LocalWallet,BECH32_PREFIX,SubaccountInfo,Order_TimeInForce,OrderExecution,OrderSide,OrderTimeInForce,OrderType,MAINNET_CHAIN_ID,ValidatorApiHost,IndexerApiHost,IndexerWSHost}from"@dydxprotocol/v4-client-js";import{IncomingMessageTypes}from"@dydxprotocol/v4-client-js/build/src/clients/socket-client";import{MarketsHandler}from"./marketsHandler";import{AccountHandler}from"./accountHandler";import{OrderbookHandler}from"./orderbookHandler";import{CandlesHandler}from"./candlesHandler";import{TradesHandler}from"./tradesHandler";import{convertResolution}from"./dydxContext";import{CandleResolution}from"../../context";import{AbstractClient,ClientSettings,conerr,conlog}from"../../client";export class DydxClient extends AbstractClient{constructor(e){super(e),this.mainnetIndexerConfig=new IndexerConfig(IndexerApiHost.MAINNET,IndexerWSHost.MAINNET),this.mainnetValidatorConfig=new ValidatorConfig(ValidatorApiHost.MAINNET,MAINNET_CHAIN_ID,{USDC_DENOM:"ibc/8E27BA2D5493AF5636760E354E46004562C46AB7EC0CC4C1CA14E9E20E2545B5",USDC_DECIMALS:6,USDC_GAS_DENOM:"uusdc",CHAINTOKEN_DENOM:"adydx",CHAINTOKEN_DECIMALS:18}),this.mainnetNetwork=new Network("mainnet",this.mainnetIndexerConfig,this.mainnetValidatorConfig),this.dydxAccInfo=e.account}async initialize(){conlog("initializing ..."),this.accountHandler=new AccountHandler(this.symbol,this.ccy,this.clientCallBackFuncs),this.candlesHandler=new CandlesHandler(this.symbol,this.clientCallBackFuncs),this.marketsHandler=new MarketsHandler(this.symbol),this.orderbookHandler=new OrderbookHandler(this.symbol),this.tradesHandler=new TradesHandler(this.symbol),this.indexerClient=new IndexerClient(this.mainnetNetwork.indexerConfig),this.validatorClient=await ValidatorClient.connect(this.mainnetNetwork.validatorConfig),this.compositeClient=await CompositeClient.connect(this.mainnetNetwork),this.localWallet=await LocalWallet.fromMnemonic(this.dydxAccInfo.mnemonic,BECH32_PREFIX),this.subaccount=new SubaccountInfo(this.localWallet,this.dydxAccInfo.subaccount),this.createSocketClient(),super.initialize(),conlog("done.")}createSocketClient(){conlog("clientCallBackFuncs ...",this.clientCallBackFuncs),this.socketClient=new SocketClient(this.mainnetNetwork.indexerConfig,(()=>{conlog("socket client opened."),conlog("subscribe to dydx account ..."),this.socketClient?.subscribeToSubaccount(this.dydxAccInfo.address,0),this.clientCallBackFuncs.orderBookFunc&&(conlog("subscribe to dydx orderbook ..."),this.socketClient?.subscribeToOrderbook(this.symbol)),this.clientCallBackFuncs.tradesFunc&&(conlog("subscribe to trade ... "),this.socketClient?.subscribeToTrades(this.symbol)),0===this.clientCandleMap?.size&&this.clientCandleMap.set(CandleResolution.DAY1,1),conlog("clientCandleMap ...",this.clientCandleMap),this.clientCandleMap?.forEach(((e,t)=>{conlog("subscribed candle: ",t);const r=convertResolution(t);r?this.socketClient?.subscribeToCandles(this.symbol,r):conerr("error subscribing resolution: ",t)}))}),(()=>{conlog("socket client closed."),this.running&&(conlog("reconnecting ..."),setTimeout((()=>{this.socketClient?.connect()}),1e3))}),(e=>{if("string"!=typeof e.data)return void conerr("error data received ",e);const t=e.data;try{const e=JSON.parse(t),r=e.channel;switch(e.type){case IncomingMessageTypes.CONNECTED:conlog("socket client connected.");break;case IncomingMessageTypes.SUBSCRIBED:switch(r){case ChannelTypes.Subaccounts:this.accountHandler.initialize(e);break;case ChannelTypes.Markets:this.marketsHandler.initialize(e);break;case ChannelTypes.Orderbook:this.orderbookHandler.initialize(e);break;case ChannelTypes.Candles:this.candlesHandler.initialize(e);break;case ChannelTypes.Trades:this.tradesHandler.initialize(e);break;default:conerr("unexpected channel: ",r)}break;case IncomingMessageTypes.CHANNEL_DATA:r===ChannelTypes.Subaccounts?this.accountHandler.update(e):conerr("unexpected channel data: ",r);break;case IncomingMessageTypes.CHANNEL_BATCH_DATA:switch(r){case ChannelTypes.Markets:this.marketsHandler.update(e);break;case ChannelTypes.Orderbook:this.orderbookHandler.update(e);break;case ChannelTypes.Candles:this.candlesHandler.update(e);break;case ChannelTypes.Trades:this.tradesHandler.update(e);break;default:conerr("unexpected channel batch data: ",r)}break;case IncomingMessageTypes.ERROR:conlog("error message received: ",e),conlog("restart client ..."),this.destroy(),setTimeout((()=>{this.initialize()}),3e3);break;default:conlog("unknown message received: ",e)}}catch(e){conerr("error resolving websocket message:",e)}}),(e=>{conerr("socket client error:",e)})),this.socketClient.connect()}getPrice(){return this.candlesHandler.getPrice()||0}getOrderbook(){return this.orderbookHandler.getOrderbook()}getAccountInfo(){return this.accountHandler.getAccountInfo()}getCandles(e){const t=convertResolution(e);return this.candlesHandler.getCandles(t)}async calculateGoodTilBlock(){return this.validatorClient?this.validatorClient.get.latestBlockHeight().then((e=>e+20)).catch((e=>{throw conerr("error fetching block height:",e),e})):0}async shortTermOrder(e,t,r,n){conlog(`open short term order ****** clientId: ${e}, side : ${t}, price: ${r}, size: ${n}`),this.placeShortTermOrder(e,t,r,n,Order_TimeInForce.TIME_IN_FORCE_UNSPECIFIED,!1)}placeShortTermOrder(e,t,r,n,o,i){this.calculateGoodTilBlock().then((c=>{this.compositeClient?.placeShortTermOrder(this.subaccount,this.symbol,t,r,n,e,c,o,i).catch((e=>conerr("error placing short term short term order:",e)))})).catch((e=>conerr("error calculating good til block on short term order:",e)))}placeMarketOrder(e,t,r,n,o,i){conlog(`market order ****** clientId: ${e}, side : ${t}, price: ${r}, size: ${n}`);const c=OrderType.MARKET,s=OrderExecution.DEFAULT;this.compositeClient?.placeOrder(this.subaccount,this.symbol,c,t,r,n,e,o,600,s,!1,i).catch((e=>conerr("error placing market order:",e)))}async buy(e,t,r){this.placeMarketOrder(e,OrderSide.BUY,t,r,OrderTimeInForce.GTT,!1)}async sell(e,t,r){this.placeMarketOrder(e,OrderSide.SELL,t,r,OrderTimeInForce.GTT,!1)}async close(e,t,r,n){conlog("close order ... "),await this.placeMarketOrder(e,t,r,n,OrderTimeInForce.GTT,!0)}placeLimitOrder(e,t,r,n,o,i=OrderTimeInForce.GTT,c=!1){conlog(`limit order ****** clientId: ${e}, side : ${t}, price: ${r}, size: ${n}, goodTillTime: ${o}`);const s=OrderType.LIMIT,a=OrderExecution.DEFAULT;this.compositeClient?.placeOrder(this.subaccount,this.symbol,s,t,r,n,e,i,o,a,!1,c).catch((e=>conerr("error placing long term post-only order:",e)))}async buyLimit(e,t,r,n=ClientSettings.GoodTillTime){this.placeLimitOrder(e,OrderSide.BUY,t,r,n)}async sellLimit(e,t,r,n=ClientSettings.GoodTillTime){this.placeLimitOrder(e,OrderSide.SELL,t,r,n)}async closeLimit(e,t,r,n,o=ClientSettings.GoodTillTime){conlog("close order limit ... "),await this.placeLimitOrder(e,t,r,n,o,OrderTimeInForce.GTT,!0)}async cancel(e){conlog(`cancel order ****** id : ${e.id}, clientId: ${e.clientId}, type: ${e.type}`);let t=Number(e.orderFlags),r=0,n=0;switch(e.type){case OrderType.LIMIT:switch(e.timeInForce){case OrderTimeInForce.IOC:case OrderTimeInForce.FOK:r=await this.calculateGoodTilBlock();break;default:n=ClientSettings.GoodTillTime}break;case OrderType.MARKET:r=await this.calculateGoodTilBlock()}conlog(`goodTilBlockTime: ${n}, goodTilBlock: ${r}`),this.compositeClient?.cancelOrder(this.subaccount,e.clientId,t,this.symbol,r,n).catch((e=>conerr("error cancelling order:",e)))}destroy(){conlog("dydx client release ..."),delete this.indexerClient,delete this.validatorClient,delete this.compositeClient,delete this.localWallet,this.socketClient?.close(),super.destroy(),conlog("dydx client released.")}}export var ChannelTypes;!function(e){e.Subaccounts="v4_subaccounts",e.Markets="v4_markets",e.Orderbook="v4_orderbook",e.Candles="v4_candles",e.Trades="v4_trades"}(ChannelTypes||(ChannelTypes={}));