UNPKG

@algodex/algodex-sdk

Version:

API calls for interacting with the Algorand blockchain

124 lines (113 loc) 5.33 kB
/* * Copyright (C) 2021-2022 Algodex VASP (BVI) Corp. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ const getTakerOrders = require('./getTakerOrders'); const withMakerTxns = require('./maker/withMakerTxns'); const fromBaseUnits = require('../../utils/units/fromBaseUnits'); const compile = require('../compile'); const logger = require('../../logger'); /** * # 🏃 getMakerTakerTxns * This method represents the synthesis of two execution types: [Maker]{@tutorial Maker} and [Taker]{@tutorial Taker} and is represented as "Both". * * It first fetches TakerTxns using [getTakerOrders]{@link module:order/structure.getTakerOrders} . If there is a remainder, it concats the return of getTakerOrders * and the return of [withMakerTxns]{@link module:order/structure.withMakerTxns}. * * ### Scenarios: * 1. There are no Taker orders that meet the criteria. * * The return of [getTakerOrders]{@link module:order/structure.getTakerOrders} is empty. The entire order is [compiled]{@link module:order/compile} as a maker using [withMakerTxns]{@link module:order/structure.withMakerTxns}. * 2. There are taker orders and no remainder. * * The return of [getTakerOrders]{@link module:order/structure.getTakerOrders} is not empty, maker leg is skipped. * 3. There are taker orders with a remainder * * The return of [getTakerOrders]{@link module:order/structure.getTakerOrders} is not empty, the remainder is [compiled]{@link module:order/compile} as a maker using [withMakerTxns]{@link module:order/structure.withMakerTxns}. * * ### When is it used? * This execution type is mainly used with our frontend. Since getMakerTakerTxns is robust enough to * handle both order types, it acts as a catch all method for placing orders with a UI. * * If you are planning on integrating Algodex's service into your own UI this is a good method to facillate placing of orders. * The more granular methods are beneficial for algorithmic trading strategies. * * * * * @example * const [AlgodexAPI]{@link AlgodexApi} = require(@algodex/algodex-sdk) * const api = new [AlgodexAPI]{@link AlgodexApi}(require('../config.json')) * const order = { * "client": api.algod, * "indexer": api.indexer, * "asset": { * "id": 15322902, * "decimals": 6, * }, * "address": "TJFFNUYWHPPIYDE4DGGYPGHWKGAPJEWP3DGE5THZS3B2M2XIAPQ2WY3X4I", * "price": 2.22, * "amount": 1, * "total": 2, * "execution": "both", * "type": "buy", * "appId": 22045503, * "version": 6 * } * * let res = await getTakerOrders(api, order) * console.log(res.contract.txns) * //Outputs an array with items being some combination of the below : * [withExecuteAssetTxns]{@link module:txns/sell.withExecuteAssetTxns} || [withExecuteAlgoTxns]{@link module:txns/buy.withExecuteAlgoTxns} || [withPlaceAssetTxns]{@link module:txns/sell.withPlaceAssetTxns} || [withPlaceAlgoTxns]{@link module:txns/buy.withPlaceAlgoTxns} * @param {AlgodexApi} api The Algodex API * @param {Order} order The Order from the User * @return {Promise<Array<Order>>} A promise of all compiled and structured Orders * @memberOf module:order/structure * @throws ValidationError * @see [withExecuteAssetTxns]{@link module:txns/sell.withExecuteAssetTxns} || [withExecuteAlgoTxns]{@link module:txns/buy.withExecuteAlgoTxns} || [withPlaceAssetTxns]{@link module:txns/sell.withPlaceAssetTxns} || [withPlaceAlgoTxns]{@link module:txns/buy.withPlaceAlgoTxns} * */ async function getMakerTakerOrders(api, order) { if (order.execution !== 'both') { throw new TypeError(`Unsupported execution of ${order.execution}, use both for automated orderbook matching`); } /** * All Orders * * Starts with available Taker Transactions * @type {Array<Order>} */ const originalPrice = order.price; const roundedTakerPrice = order.type === 'buy'? order.price+= 0.0000009999999 : order. price-= 0.0000009999999; const orders = [...await getTakerOrders(api, {...order, price: roundedTakerPrice, execution: 'taker'})]; logger.debug( `getMakerTakerOrders: Created ${orders.length} Taker Order(s)`); /** * Remainder of the current order * @type {Number} */ const remainder = orders.reduce((result, o) => result -= fromBaseUnits(o.contract.amount, order.asset.decimals), order.amount); const assetPrecision = 1/(10 ** order.asset.decimals); if (orders.length > 0 && orders[0].type === 'sell') { if (remainder * order.price < 0.500001) { return orders; // This is to prevent placing a maker buy order with a total amount less than 0.5 algo } } // Add Maker Order to response if overflow if (remainder >= assetPrecision) { orders.push( await withMakerTxns(api, await compile({ ...order, price: originalPrice, execution: 'maker', amount: remainder, total: remainder * order.price, appId: await api.getAppId(order), indexer: api.indexer, })), ); logger.debug(`getMakerTakerOrders: Created 1 Maker Order`); } logger.debug(`getMakerTakerOrders: Created ${orders.length} Order(s)`); return orders; } module.exports = getMakerTakerOrders;