const { DydxClient } = require('@dydxprotocol/v3-client') const Web3 = require('web3') const web31 = new Web3(process.env.RPC_NODE) const web32 = new Web3(process.env.RPC_NODE) const signer1 = web31.eth.accounts.wallet.add(process.env.TRADING_ZERO_PVT_KEY) const signer2 = web32.eth.accounts.wallet.add(process.env.TRADING_ONE_PVT_KEY) const { dateutils } = require('../utils') const { iso8601, dateNowUTC, timeFmtDb } = dateutils client1 = new DydxClient('https://api.dydx.exchange', { web3: web31, web3Provider: process.env.RPC_NODE }) client2 = new DydxClient('https://api.dydx.exchange', { web3: web32, web3Provider: process.env.RPC_NODE }) let inited = false const init = async () => { try { const apiCreds1 = await client1.onboarding.recoverDefaultApiCredentials(signer1.address) client1.apiKeyCredentials = apiCreds1 const keyPairWithYCoordinate1 = await client1.onboarding.deriveStarkKey(signer1.address) client1.starkPrivateKey = keyPairWithYCoordinate1.privateKey const apiCreds2 = await client2.onboarding.recoverDefaultApiCredentials(signer2.address) client2.apiKeyCredentials = apiCreds2 const keyPairWithYCoordinate2 = await client2.onboarding.deriveStarkKey(signer2.address) client2.starkPrivateKey = keyPairWithYCoordinate2.privateKey inited = true } catch (error) { console.log(error) console.log('WARNING: An error occurred initializing dydx client') } } module.exports = { getFills: async (market, createdBeforeOrAt, limit = 100, orderId = undefined, clientId = 1) => { try { if (!inited) await init() let req = { market: market, limit: limit, createdBeforeOrAt: createdBeforeOrAt, } if (typeof orderid !== 'undefined') { req['orderId'] = orderId } if (clientId === 1) { const resp = await client1.private.getFills(req) return resp.fills } else if (clientId === 2) { const resp = await client2.private.getFills(req) return resp.fills } } catch (error) { console.log(error) console.log('Could not retrieve fills') } }, /* Get an order by id from the active orderbook and order history NOTE: a way to retrieve an unknown orderId is to poll for fills and then call for the exact orderId from the fill */ getOrderById: async (orderId, clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const resp = await client1.private.getOrderById(orderId) return resp.order } else if (clientId === 2) { const resp = await client2.private.getOrderById(orderId) return resp.order } } catch (error) { console.log(error) console.log('Could not retrieve order') } }, /* Get active (not filled or canceled) orders for a user, stingey rate limit */ getOrders: async (market, createdBeforeOrAt, limit = 100, clientId = 1) => { try { if (!inited) await init() let req = { market: market, limit: limit, createdBeforeOrAt: createdBeforeOrAt, returnLatestOrders: true } if (clientId === 1) { const orders = await client1.private.getOrders(req) return orders.orders } else if (clientId === 2) { const orders = await client2.private.getOrders(req) return orders.orders } } catch (error) { console.log(error) console.log('Could not retrieve orders') } }, /* Get active (not filled or canceled) orders for a user, relaxed rate limit Bug: id is not optional, and should be */ getActiveOrders: async (market, side, orderId, clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const resp = await client1.private.getActiveOrders(market, side, orderId) return resp.orders } else if (clientId === 2) { const resp = await client2.private.getActiveOrders(market, side, orderId) return resp.orders } } catch (error) { console.log(error) console.log('Could not retrieve orders') } }, /* contains price info for index and oracle also contains future funding rate for market */ getMarket: async (market) => { try { if (!inited) await init() const orders = await client1.public.getMarkets(market) return orders.markets[market] } catch (error) { console.log(error) console.log('Could not retrieve market') } }, getHistoricalPrices: async (market, resolution, fromISO, toISO, limit) => { function translateCandle (resolution) { let res switch (resolution) { case "1d": res = "1DAY"; break; case "4h": res = "4HOURS"; break; case "1h": res = "1HOUR"; break; case "30m": res = "30MINS"; break; case "15m": res = "15MINS"; break; case "5m": res = "5MINS"; break; case "1m": res = "1MIN"; break; default: res = "1DAY" } return res } try { if (!inited) await init() const orders = await client1.public.getCandles({ market, resolution:translateCandle(resolution), fromISO, toISO, limit}) return orders } catch (error) { console.log(error) console.log('Could not retrieve historical prices') } }, /* gets funding rate for the past hours */ getPastFundingRates: async (market, effectiveBeforeOrAt) => { try { if (!inited) await init() const orders = await client1.public.getHistoricalFunding({ market, effectiveBeforeOrAt }) return orders.historicalFunding } catch (error) { console.log(error) console.log('Could not retrieve funding history') } }, getFundingPayments: async (market, limit, effectiveBeforeOrAt, clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const payments = await client1.private.getFundingPayments({ market, limit, effectiveBeforeOrAt }) return payments.fundingPayments } else if (clientId === 2) { const payments = await client2.private.getFundingPayments({ market, limit, effectiveBeforeOrAt }) return payments.fundingPayments } } catch (error) { console.log(error) console.log('Could not retrieve funding payments') } }, getHistoricalFunding: async (market, effectiveBeforeOrAt) => { try { if (!inited) await init() const funding = await client1.public.getHistoricalFunding({ market, effectiveBeforeOrAt }) return funding.historicalFunding } catch (error) { console.log(error) console.log('Could not retrieve funding payments') } }, getAccount: async(clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const account = (await client1.private.getAccount(signer1.address)).account return account } else if (clientId === 2) { const account = (await client2.private.getAccount(signer2.address)).account return account } } catch (error) { console.log(error) console.log('Could not retrieve account') } }, getAccounts: async(clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const account = await client1.private.getAccounts() if (account.accounts.length > 0) { return account.accounts } } else if (clientId === 2) { const account = await client2.private.getAccounts() if (account.accounts.length > 0) { return account.accounts } } return [] } catch (error) { console.log(error) console.log('Could not retrieve account') } }, getPositions: async (market, status, limit, createdBeforeOrAt, clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const response = await client1.private.getPositions({ market: market, status: status, limit: limit, createdBeforeOrAt: createdBeforeOrAt, }) if (response.positions.length > 0) { return response.positions } } else if (clientId === 2) { const response = await client2.private.getPositions({ market: market, status: status, limit: limit, createdBeforeOrAt: createdBeforeOrAt, }) if (response.positions.length > 0) { return response.positions } } return [] } catch (error) { console.log(error) console.log('Could not retrieve account') } }, /** *@description place a new order * * @market BTC-USD ETH-USD etc * @side BUY SELL * @type MARKET LIMIT STOP_LIMIT TRAILING_STOP TAKE_PROFIT * @timeInForce GTT FOK IOC * @postOnly true false * @size * @price * @limitFee highest accepted fee for the trade * @expiration when the order will expire if not filled * @cancelId if the order is replacing an existing one * @triggerPrice price the order if the order is a triggerable order * @trailingPercent percent that the triggerPrice trails the index price of the market * @param positionId associated with the order */ placeOrder: async (market, side, type, timeInForce, postOnly, size, price, expiration, clientId = 1) => { console.log('A dydx order was received:',market, side, type, timeInForce, postOnly, size, price, expiration) if (!inited) await init() try { if (clientId === 1) { const account = (await client1.private.getAccount(signer1.address)).account const user = (await client1.private.getUser()).user let req = { market: market, side: side.toUpperCase(), type: type.toUpperCase(), timeInForce: timeInForce, postOnly: postOnly, size: size, price: price, limitFee: user.takerFeeRate, expiration: expiration } const order = await client1.private.createOrder(req, account.positionId) return order } else if (clientId === 2) { const account = (await client2.private.getAccount(signer2.address)).account const user = (await client2.private.getUser()).user let req = { market: market, side: side.toUpperCase(), type: type.toUpperCase(), timeInForce: timeInForce, postOnly: postOnly, size: size, price: price, limitFee: user.takerFeeRate, expiration: expiration } const order = await client2.private.createOrder(req, account.positionId) return order } } catch (error) { console.log(error) console.log('An error occurred placing an order') console.log(Object.keys(error)) } }, cancelOrder: async (orderId, clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const result = await client1.private.cancelOrder(orderId) return result.cancelOrder } else if (clientId === 2) { const result = await client2.private.cancelOrder(orderId) return result.cancelOrder } } catch (error) { console.log(error) console.log('Could not retrieve apiKeys') } }, cancelAllOrders: async (market, clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const result = await client1.private.cancelAllOrders(market) return result } else if (clientId === 2) { const result = await client2.private.cancelAllOrders(market) return result } } catch (error) { console.log(error) console.log('Could not retrieve apiKeys') } }, getApikeys: async(clientId = 1) => { try { if (!inited) await init() if (clientId === 1) { const keys = await client1.private.getApiKeys() return keys.apiKeys } else if (clientId === 2) { const keys = await client2.private.getApiKeys() return keys.apiKeys } } catch (error) { console.log(error) console.log('Could not retrieve apiKeys') } } } // ; (async () => { // await init() // const orders = await module.exports.getActiveOrders('BTC-USD', 'BUY') // console.log(orders) // const fills = await module.exports.getFills('BTC-USD', iso8601(dateNowUTC()), 10) // console.log(fills) // for (let i = 0; i < fills.length; i++) { // const order = await module.exports.getOrderById(fills[i].orderId) // console.log(order) // } // const market = await module.exports.getMarket('BTC-USD') // console.log(market) // const days = 86400 * 1000 * 90 // const past = iso8601(dateNowUTC() - days) // const histo = await module.exports.getHistoricalPrices('BTC-USD', '1h', past, iso8601(dateNowUTC()), 10) // console.log(histo) // const funding = await module.exports.getPastFundingRates('BTC-USD', iso8601(dateNowUTC())) // console.log(funding) // const effectiveBeforeOrAt = iso8601(dateNowUTC()) // const fundingPayments = await module.exports.getFundingPayments('BTC-USD', 10, effectiveBeforeOrAt) // console.log(fundingPayments) // const account = await module.exports.getAccount() // console.log(account) // const accounts = await module.exports.getAccounts() // console.log(accounts) // const positions = await module.exports.getPositions('BTC-USD', 'OPEN', 100, iso8601(dateNowUTC())) // console.log(positions) // const apiKeys = await module.exports.getApikeys() // console.log(apiKeys) /* // create an order setup const market = await module.exports.getMarket('BTC-USD') // last price of btc const user = (await client1.private.getUser()).user // get fee for user const account = (await client1.private.getAccount(signer1.address)).account // get positionId const plus30m = iso8601(dateNowUTC() + 1800000) // expiration time const response = await client1.private.getPositions({ market: 'BTC-USD', status: 'OPEN', limit: 10, createdBeforeOrAt: iso8601(dateNowUTC()), }) if (response.positions.length > 0) { let p = response.positions[0] console.log(p) // lets close whatever is open at market: let side switch (p.side) { case "SHORT": side = "BUY" break; case "LONG": side = "SELL" break; default: return; } const order = await module.exports.newOrder('BTC-USD', side, 'MARKET', 'FOK', false, String(Math.abs(p.size)), String(Math.floor(market.indexPrice)), user.takerFeeRate, plus30m, account.positionId) console.log(order) } */ // cancel order setup // const orders = await module.exports.getActiveOrders('BTC-USD', 'BUY') // const result = await module.exports.cancelOrder(orders[0].id) // console.log(result) // const result = await module.exports.cancelAllOrders('ETH-USD') // console.log(result) // })()