UNPKG

@d8x/perpetuals-sdk

Version:

Node TypeScript SDK for D8X Perpetual Futures

317 lines 14.9 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const ethers_1 = require("ethers"); const constants_1 = require("./constants"); const d8XMath_1 = require("./d8XMath"); const marketData_1 = __importDefault(require("./marketData")); const perpetualDataHandler_1 = __importDefault(require("./perpetualDataHandler")); const traderDigests_1 = __importDefault(require("./traderDigests")); /** * Interface that can be used by front-end that wraps all private functions * so that signatures can be handled in frontend via wallet * @extends MarketData */ class TraderInterface extends marketData_1.default { /** * Constructor * @param {NodeSDKConfig} config Configuration object, see * PerpetualDataHandler.readSDKConfig. */ constructor(config) { super(config); this.gasLimit = 1000000; this.digestTool = new traderDigests_1.default(); } /** * Get the fee that is charged to the trader for a given broker (can be ZERO-address), * without broker fee * @param poolSymbolName pool currency (e.g. MATIC) * @param traderAddr address of trader * @param brokerAddr address of broker * @returns fee (in decimals) that is charged by exchange (without broker) * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("cardona"); * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // query exchange fee * let fees = await traderAPI.queryExchangeFee("MATIC"); * console.log(fees); * } * main(); * */ async queryExchangeFee(poolSymbolName, traderAddr, brokerAddr, overrides) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos); let feeTbps = (await this.proxyContract.queryExchangeFee(poolId, traderAddr, brokerAddr, overrides || {})); return Number(feeTbps) / 100000; } /** * * @param poolSymbolName pool symbol, e.g. MATIC * @param traderAddr address of the trader * @returns volume in USD * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("cardona"); * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // query volume * let vol = await traderAPI.getCurrentTraderVolume("MATIC", "0xmyAddress"); * console.log(vol); * } * main(); * */ async getCurrentTraderVolume(poolSymbolName, traderAddr, overrides) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos); let volume = await this.proxyContract.getCurrentTraderVolume(poolId, traderAddr, overrides || {}); return (0, d8XMath_1.ABK64x64ToFloat)(volume); } /** * Get digest to cancel an order. Digest needs to be signed and submitted via * orderBookContract.cancelOrder(orderId, signature); * @param symbol * @param orderId * @returns tuple of digest which the trader needs to sign and address of order book contract * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("x1"); * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // submit order * let resp = await accTrade.order(order, undefined, { gasLimit: 800_000 }); * await resp.tx.wait(); * // cancel what we just submitted * let d = await traderAPI.cancelOrderDigest("ETH-USDC-USDC", resp.orderId); * console.log(d); * } * main(); */ async cancelOrderDigest(symbol, orderId, overrides) { if (this.proxyContract == null) { throw Error("no proxy contract initialized. Use createProxyInstance()."); } let orderBookContract = this.getOrderBookContract(symbol); let scOrder = await orderBookContract.orderOfDigest(orderId, overrides || {}); let digest = this.digestTool.createDigest(scOrder, this.chainId, false, this.proxyAddr); return { digest: digest, OBContractAddr: orderBookContract.target.toString() }; } /** * Get the order book address for a perpetual * @param symbol symbol (e.g. MATIC-USD-MATIC) * @returns order book address for the perpetual * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("cardona"); * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // get order book address * let ob = traderAPI.getOrderBookAddress("BTC-USD-MATIC"); * console.log(ob); * } * main(); */ getOrderBookAddress(symbol) { let orderBookContract = this.getOrderBookContract(symbol); return orderBookContract.target.toString(); } /** * createSmartContractOrder from user-friendly order * @param order order struct * @param traderAddr address of trader * @returns Smart contract type order struct */ createSmartContractOrder(order, traderAddr) { const sInfo = this.symbolToPerpStaticInfo.get(order.symbol); if (!sInfo) { throw new Error(`No perpetual static info found for symbol ${order.symbol}`); } let scOrder = TraderInterface.toSmartContractOrder(order, traderAddr, this.symbolToPerpStaticInfo); return scOrder; } /** * Create smart contract order and digest that the trader signs. * await orderBookContract.postOrder(scOrder, signature, { gasLimit: gasLimit }); * Order must contain broker fee and broker address if there is supposed to be a broker. * @param scOrder smart contract order struct (get from order via createSCOrder) * @returns digest that the trader has to sign */ orderDigest(scOrder) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } let digest = this.digestTool.createDigest(scOrder, this.chainId, true, this.proxyContract.target.toString()); return digest; } /** * Get the ABI of a method in the proxy contract. Throws if non-existent * @param method Name of the method * @returns ABI as a single string */ getProxyABI(method) { if (this.proxyContract == null) { throw new Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } const res = perpetualDataHandler_1.default._getABIFromContract(this.proxyContract, method); if (!res) { throw new Error(`no proxy method found with name ${method}`); } return res; } /** * Get the ABI of a method in the Limit Order Book contract corresponding to a given symbol. * @param symbol Symbol of the form MATIC-USD-MATIC * @param method Name of the method * @returns ABI as a single string */ getOrderBookABI(symbol, method) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } let orderBookContract = this.getOrderBookContract(symbol); const res = perpetualDataHandler_1.default._getABIFromContract(orderBookContract, method); if (!res) { throw new Error(`no proxy method found with name ${method}`); } return res; } /** * Takes up to three orders and designates the first one as "parent" of the others. * E.g. the first order opens a position, and the other two are take-profit and/or stop-loss orders. * @param orders 1, 2 or 3 smart contract orders * @param ids order ids * @returns client orders with dependency info filled in */ static chainOrders(orders, ids) { // add dependency let obOrders = new Array(orders.length); if (orders.length == 1 || orders.length > 3) { // nothing to add obOrders = orders.map((o) => perpetualDataHandler_1.default.fromSmartContratOrderToClientOrder(o)); } else if (orders.length == 2) { // first order is parent, second a child obOrders[0] = perpetualDataHandler_1.default.fromSmartContratOrderToClientOrder(orders[0], [ids[1], constants_1.ZERO_ORDER_ID]); obOrders[1] = perpetualDataHandler_1.default.fromSmartContratOrderToClientOrder(orders[1], [constants_1.ZERO_ORDER_ID, ids[0]]); } else { // first order is parent, other two its children obOrders[0] = perpetualDataHandler_1.default.fromSmartContratOrderToClientOrder(orders[0], [ids[1], ids[2]]); obOrders[1] = perpetualDataHandler_1.default.fromSmartContratOrderToClientOrder(orders[1], [constants_1.ZERO_ORDER_ID, ids[0]]); obOrders[2] = perpetualDataHandler_1.default.fromSmartContratOrderToClientOrder(orders[2], [constants_1.ZERO_ORDER_ID, ids[0]]); } return obOrders; } /** * Add liquidity to the PnL participant fund via signer. The address gets pool shares in return. * @param {Signer} signer Signer that will deposit liquidity * @param {string} poolSymbolName Name of pool symbol (e.g. MATIC) * @param {number} amountCC Amount in pool-collateral currency * @return Transaction object * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("cardona"); * const signer = // ethers Signer, e.g. from Metamask * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // add liquidity * let respAddLiquidity = await traderAPI.addLiquidity(signer, "MATIC", 0.1); * console.log(respAddLiquidity); * } * main(); * */ async addLiquidity(signer, poolSymbolName, amountCC, overrides) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } const poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos); const decimals = this.getSettlementTokenDecimalsFromSymbol(poolSymbolName); const proxy = new ethers_1.Contract(this.proxyAddr, this.proxyABI, signer); return await proxy.addLiquidity(poolId, (0, d8XMath_1.floatToDecN)(amountCC, decimals), overrides || { gasLimit: this.gasLimit }); } /** * Initiates a liquidity withdrawal from the pool * It triggers a time-delayed unlocking of the given number of pool shares. * The amount of pool shares to be unlocked is fixed by this call, but not their value in pool currency. * @param {Signer} signer Signer that will initiate liquidity withdrawal * @param {string} poolSymbolName Name of pool symbol (e.g. MATIC). * @param {string} amountPoolShares Amount in pool-shares, removes everything if > available amount. * * @return Transaction object. * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("cardona"); * const signer = // ethers Signer, e.g. from Metamask * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // submit txn * let tx = await traderAPI.initiateLiquidityWithdrawal(signer, "MATIC", 10.2); * console.log(tx); * } * main(); * */ async initiateLiquidityWithdrawal(signer, poolSymbolName, amountPoolShares, overrides) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos); const proxy = new ethers_1.Contract(this.proxyAddr, this.proxyABI, signer); return await proxy.withdrawLiquidity(poolId, (0, d8XMath_1.floatToDec18)(amountPoolShares), overrides || { gasLimit: this.gasLimit }); } /** * Withdraws as much liquidity as there is available after a call to initiateLiquidityWithdrawal. * The address loses pool shares in return. * @param {Signer} signer Signer that will execute the liquidity withdrawal * @param poolSymbolName * * @returns Transaction object. * @example * import { TraderInterface, PerpetualDataHandler } from '@d8x/perpetuals-sdk'; * async function main() { * console.log(TraderInterface); * const config = PerpetualDataHandler.readSDKConfig("cardona"); * const signer = // ethers Signer, e.g. from Metamask * let traderAPI = new TraderInterface(config); * await traderAPI.createProxyInstance(); * // submit txn * let tx = await traderAPI.executeLiquidityWithdrawal(signer, "MATIC"); * console.log(tx); * } * main(); * */ async executeLiquidityWithdrawal(signer, poolSymbolName, overrides) { if (this.proxyContract == null) { throw Error("no proxy contract or wallet initialized. Use createProxyInstance()."); } let poolId = perpetualDataHandler_1.default._getPoolIdFromSymbol(poolSymbolName, this.poolStaticInfos); const proxy = new ethers_1.Contract(this.proxyAddr, this.proxyABI, signer); return await proxy.executeLiquidityWithdrawal(poolId, await signer.getAddress(), overrides || { gasLimit: this.gasLimit }); } } exports.default = TraderInterface; //# sourceMappingURL=traderInterface.js.map