UNPKG

ccxt

Version:

A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 100+ exchanges

1,210 lines (1,207 loc) • 136 kB
// ---------------------------------------------------------------------------- // PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN: // https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code // EDIT THE CORRESPONDENT .ts FILE INSTEAD // --------------------------------------------------------------------------- import Exchange from './abstract/vertex.js'; import { ExchangeError, RateLimitExceeded, PermissionDenied, InsufficientFunds, AuthenticationError, ArgumentsRequired, NotSupported, InvalidOrder, BadRequest } from './base/errors.js'; import { Precise } from './base/Precise.js'; import { TICK_SIZE } from './base/functions/number.js'; import { keccak_256 as keccak } from './static_dependencies/noble-hashes/sha3.js'; import { secp256k1 } from './static_dependencies/noble-curves/secp256k1.js'; import { ecdsa } from './base/functions/crypto.js'; // --------------------------------------------------------------------------- /** * @class vertex * @augments Exchange */ export default class vertex extends Exchange { describe() { return this.deepExtend(super.describe(), { 'id': 'vertex', 'name': 'Vertex', 'countries': [], 'version': 'v1', 'rateLimit': 50, 'certified': false, 'pro': true, 'dex': true, 'has': { 'CORS': undefined, 'spot': true, 'margin': false, 'swap': true, 'future': true, 'option': false, 'addMargin': false, 'borrowCrossMargin': false, 'borrowIsolatedMargin': false, 'cancelAllOrders': true, 'cancelAllOrdersAfter': false, 'cancelOrder': true, 'cancelOrders': true, 'cancelOrdersForSymbols': false, 'closeAllPositions': false, 'closePosition': false, 'createMarketBuyOrderWithCost': false, 'createMarketOrderWithCost': false, 'createMarketSellOrderWithCost': false, 'createOrder': true, 'createOrders': true, 'createReduceOnlyOrder': true, 'createStopOrder': true, 'createTriggerOrder': true, 'editOrder': false, 'fetchAccounts': false, 'fetchBalance': true, 'fetchBorrowInterest': false, 'fetchBorrowRateHistories': false, 'fetchBorrowRateHistory': false, 'fetchCanceledOrders': false, 'fetchClosedOrders': false, 'fetchCrossBorrowRate': false, 'fetchCrossBorrowRates': false, 'fetchCurrencies': true, 'fetchDepositAddress': false, 'fetchDepositAddresses': false, 'fetchDeposits': false, 'fetchDepositWithdrawFee': false, 'fetchDepositWithdrawFees': false, 'fetchFundingHistory': false, 'fetchFundingRate': true, 'fetchFundingRateHistory': false, 'fetchFundingRates': true, 'fetchIndexOHLCV': false, 'fetchIsolatedBorrowRate': false, 'fetchIsolatedBorrowRates': false, 'fetchLedger': false, 'fetchLeverage': false, 'fetchLeverageTiers': false, 'fetchLiquidations': false, 'fetchMarginMode': undefined, 'fetchMarketLeverageTiers': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyLiquidations': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterest': true, 'fetchOpenInterestHistory': false, 'fetchOpenInterests': true, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchOrderTrades': false, 'fetchPosition': false, 'fetchPositionMode': false, 'fetchPositions': true, 'fetchPositionsRisk': false, 'fetchPremiumIndexOHLCV': false, 'fetchStatus': true, 'fetchTicker': false, 'fetchTickers': true, 'fetchTime': true, 'fetchTrades': true, 'fetchTradingFee': false, 'fetchTradingFees': true, 'fetchTransfer': false, 'fetchTransfers': false, 'fetchWithdrawal': false, 'fetchWithdrawals': false, 'reduceMargin': false, 'repayCrossMargin': false, 'repayIsolatedMargin': false, 'sandbox': true, 'setLeverage': false, 'setMarginMode': false, 'setPositionMode': false, 'transfer': false, 'withdraw': true, }, 'timeframes': { '1m': 60, '5m': 300, '15m': 900, '1h': 3600, '2h': 7200, '4h': 14400, '1d': 86400, '1w': 604800, '1M': 604800, }, 'hostname': 'vertexprotocol.com', 'urls': { 'logo': 'https://github.com/ccxt/ccxt/assets/43336371/bd04a0fa-3b48-47b6-9d8b-124954d520a8', 'api': { 'v1': { 'archive': 'https://archive.prod.{hostname}/v1', 'gateway': 'https://gateway.prod.{hostname}/v1', 'trigger': 'https://trigger.prod.{hostname}/v1', }, 'v2': { 'archive': 'https://archive.prod.{hostname}/v2', 'gateway': 'https://gateway.prod.{hostname}/v2', }, }, 'test': { 'v1': { 'archive': 'https://archive.sepolia-test.{hostname}/v1', 'gateway': 'https://gateway.sepolia-test.{hostname}/v1', 'trigger': 'https://trigger.sepolia-test.{hostname}/v1', }, 'v2': { 'archive': 'https://archive.sepolia-test.{hostname}/v2', 'gateway': 'https://gateway.sepolia-test.{hostname}/v2', }, }, 'www': 'https://vertexprotocol.com/', 'doc': 'https://docs.vertexprotocol.com/', 'fees': 'https://docs.vertexprotocol.com/basics/fees', 'referral': 'https://app.vertexprotocol.com?referrer=0xCfC9BaB96a2eA3d3c3F031c005e82E1D9F295aC1', }, 'api': { 'v1': { 'archive': { 'post': { '': 1, }, }, 'gateway': { 'get': { 'query': 1, 'symbols': 1, 'time': 1, }, 'post': { 'query': 1, 'execute': 1, }, }, 'trigger': { 'post': { 'execute': 1, 'query': 1, }, }, }, 'v2': { 'archive': { 'get': { 'tickers': 1, 'contracts': 1, 'trades': 1, 'vrtx': 1, }, }, 'gateway': { 'get': { 'assets': 0.6667, 'pairs': 1, 'orderbook': 1, }, }, }, }, 'fees': { 'swap': { 'taker': this.parseNumber('0.0002'), 'maker': this.parseNumber('0.0002'), }, 'spot': { 'taker': this.parseNumber('0.0002'), 'maker': this.parseNumber('0.0002'), }, }, 'requiredCredentials': { 'apiKey': false, 'secret': false, 'walletAddress': true, 'privateKey': true, }, 'exceptions': { 'exact': { '1000': RateLimitExceeded, '1015': RateLimitExceeded, '1001': PermissionDenied, '1002': PermissionDenied, '1003': PermissionDenied, '2000': InvalidOrder, '2001': InvalidOrder, '2002': InvalidOrder, '2003': InvalidOrder, '2004': InvalidOrder, '2005': InvalidOrder, '2006': InvalidOrder, '2007': InvalidOrder, '2008': InvalidOrder, '2009': InvalidOrder, '2010': InvalidOrder, '2011': BadRequest, '2012': BadRequest, '2013': InvalidOrder, '2014': PermissionDenied, '2015': InvalidOrder, '2016': InvalidOrder, '2017': InvalidOrder, '2019': InvalidOrder, '2020': InvalidOrder, '2021': InvalidOrder, '2022': InvalidOrder, '2023': InvalidOrder, '2024': InsufficientFunds, '2025': InsufficientFunds, '2026': BadRequest, '2027': AuthenticationError, '2028': AuthenticationError, '2029': AuthenticationError, '2030': BadRequest, '2031': InvalidOrder, '2033': InvalidOrder, '2034': InvalidOrder, '2035': InvalidOrder, '2036': InvalidOrder, '2037': InvalidOrder, '2038': InvalidOrder, '2039': InvalidOrder, '2040': InvalidOrder, '2041': InvalidOrder, '2042': InvalidOrder, '2043': InvalidOrder, '2044': InvalidOrder, '2045': InvalidOrder, '2046': InvalidOrder, '2047': InvalidOrder, '2048': InvalidOrder, '2049': ExchangeError, '2050': PermissionDenied, '2051': InvalidOrder, '2052': InvalidOrder, '2053': InvalidOrder, '2054': InvalidOrder, '2055': InvalidOrder, '2056': InvalidOrder, '2057': InvalidOrder, '2058': InvalidOrder, '2059': InvalidOrder, '2060': InvalidOrder, '2061': InvalidOrder, '2062': InvalidOrder, '2063': InvalidOrder, '2064': InvalidOrder, '2065': InvalidOrder, '2066': InvalidOrder, '2067': InvalidOrder, '2068': InvalidOrder, '2069': InvalidOrder, '2070': InvalidOrder, '2071': InvalidOrder, '2072': InvalidOrder, '2073': InvalidOrder, '2074': InvalidOrder, '2075': InvalidOrder, '2076': InvalidOrder, '3000': BadRequest, '3001': BadRequest, '3002': BadRequest, '3003': BadRequest, '4000': BadRequest, '4001': ExchangeError, '4002': ExchangeError, '4003': ExchangeError, '4004': InvalidOrder, '5000': ExchangeError, }, 'broad': {}, }, 'precisionMode': TICK_SIZE, 'commonCurrencies': {}, 'options': { 'defaultType': 'swap', 'sandboxMode': false, 'timeDifference': 0, 'brokerId': 5930043274845996, }, 'features': { 'default': { 'sandbox': true, 'createOrder': { 'marginMode': false, 'triggerPrice': true, 'triggerDirection': false, 'triggerPriceType': undefined, 'stopLossPrice': true, 'takeProfitPrice': true, 'attachedStopLossTakeProfit': undefined, 'timeInForce': { 'IOC': false, 'FOK': false, 'PO': true, 'GTD': true, }, 'hedged': false, 'trailing': false, 'leverage': false, 'marketBuyByCost': true, 'marketBuyRequiresPrice': true, 'selfTradePrevention': false, 'iceberg': false, }, 'createOrders': undefined, 'fetchMyTrades': { 'marginMode': false, 'limit': 500, 'daysBack': 100000, 'untilDays': undefined, 'symbolRequired': false, }, 'fetchOrder': { 'marginMode': false, 'trigger': false, 'trailing': false, 'symbolRequired': true, }, 'fetchOpenOrders': { 'marginMode': false, 'limit': 500, 'trigger': true, 'trailing': false, 'symbolRequired': false, }, 'fetchOrders': undefined, 'fetchClosedOrders': undefined, 'fetchOHLCV': { 'limit': 1000, }, }, 'spot': { 'extends': 'default', }, 'swap': { 'linear': { 'extends': 'default', }, 'inverse': undefined, }, 'future': { 'linear': undefined, 'inverse': undefined, }, }, }); } setSandboxMode(enabled) { super.setSandboxMode(enabled); this.options['sandboxMode'] = enabled; } convertToX18(num) { if (typeof num === 'string') { return Precise.stringMul(num, '1000000000000000000'); } const numStr = this.numberToString(num); return Precise.stringMul(numStr, '1000000000000000000'); } convertFromX18(num) { if (typeof num === 'string') { return Precise.stringDiv(num, '1000000000000000000'); } const numStr = this.numberToString(num); return Precise.stringDiv(numStr, '1000000000000000000'); } /** * @method * @name vertex#fetchCurrencies * @description fetches all available currencies on an exchange * @see https://docs.vertexprotocol.com/developer-resources/api/v2/assets * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} an associative dictionary of currencies */ async fetchCurrencies(params = {}) { const request = {}; const response = await this.v2GatewayGetAssets(this.extend(request, params)); // // [ // { // "product_id": 2, // "ticker_id": "BTC-PERP_USDC", // "market_type": "perp", // "name": "Bitcoin Perp", // "symbol": "BTC-PERP", // "maker_fee": 0.0002, // "taker_fee": 0, // "can_withdraw": false, // "can_deposit": false // }, // { // "product_id": 1, // "ticker_id": "BTC_USDC", // "market_type": "spot", // "name": "Bitcoin", // "symbol": "BTC", // "taker_fee": 0.0003, // "maker_fee": 0, // "can_withdraw": true, // "can_deposit": true // } // ] // const result = {}; for (let i = 0; i < response.length; i++) { const data = this.safeDict(response, i, {}); const tickerId = this.safeString(data, 'ticker_id'); if ((tickerId !== undefined) && (tickerId.indexOf('PERP') > 0)) { continue; } const name = this.safeString(data, 'symbol'); const code = this.safeCurrencyCode(name); result[code] = this.safeCurrencyStructure({ 'id': this.safeString(data, 'product_id'), 'name': name, 'code': code, 'precision': undefined, 'info': data, 'active': undefined, 'deposit': this.safeBool(data, 'can_deposit'), 'withdraw': this.safeBool(data, 'can_withdraw'), 'networks': undefined, 'fee': undefined, 'limits': { 'amount': { 'min': undefined, 'max': undefined, }, 'withdraw': { 'min': undefined, 'max': undefined, }, }, }); } return result; } parseMarket(market) { // // { // "type": "spot", // "product_id": 3, // "symbol": "WETH", // "price_increment_x18": "100000000000000000", // "size_increment": "10000000000000000", // "min_size": "100000000000000000", // "min_depth_x18": "5000000000000000000000", // "max_spread_rate_x18": "2000000000000000", // "maker_fee_rate_x18": "0", // "taker_fee_rate_x18": "300000000000000", // "long_weight_initial_x18": "900000000000000000", // "long_weight_maintenance_x18": "950000000000000000" // } // const marketType = this.safeString(market, 'type'); const quoteId = 'USDC'; const quote = this.safeCurrencyCode(quoteId); const baseId = this.safeString(market, 'symbol'); const base = this.safeCurrencyCode(baseId); const settleId = quoteId; const settle = this.safeCurrencyCode(settleId); let symbol = base + '/' + quote; const spot = marketType === 'spot'; const contract = !spot; const swap = !spot; if (swap) { const splitSymbol = base.split('-'); symbol = splitSymbol[0] + '/' + quote + ':' + settle; } const priceIncrementX18 = this.safeString(market, 'price_increment_x18'); const sizeIncrementX18 = this.safeString(market, 'size_increment'); const minSizeX18 = this.safeString(market, 'min_size'); const takerX18 = this.safeNumber(market, 'taker_fee_rate_x18'); const makerX18 = this.safeNumber(market, 'maker_fee_rate_x18'); const isInverse = (spot) ? undefined : false; const isLinear = (spot) ? undefined : true; const contractSize = (spot) ? undefined : this.parseNumber('1'); return { 'id': this.safeString(market, 'product_id'), 'symbol': symbol, 'base': base, 'quote': quote, 'settle': (spot) ? undefined : settle, 'baseId': baseId, 'quoteId': quoteId, 'settleId': (spot) ? undefined : settleId, 'type': (spot) ? 'spot' : 'swap', 'spot': spot, 'margin': undefined, 'swap': swap, 'future': false, 'option': false, 'active': true, 'contract': contract, 'linear': isLinear, 'inverse': isInverse, 'taker': this.parseNumber(this.convertFromX18(takerX18)), 'maker': this.parseNumber(this.convertFromX18(makerX18)), 'contractSize': contractSize, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber(this.convertFromX18(sizeIncrementX18)), 'price': this.parseNumber(this.convertFromX18(priceIncrementX18)), }, 'limits': { 'leverage': { 'min': undefined, 'max': undefined, }, 'amount': { 'min': this.parseNumber(this.convertFromX18(minSizeX18)), 'max': undefined, }, 'price': { 'min': undefined, 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'created': undefined, 'info': market, }; } /** * @method * @name vertex#fetchMarkets * @description retrieves data on all markets for vertex * @see https://docs.vertexprotocol.com/developer-resources/api/gateway/queries/symbols * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object[]} an array of objects representing market data */ async fetchMarkets(params = {}) { const request = { 'type': 'symbols', }; const response = await this.v1GatewayGetQuery(this.extend(request, params)); // // { // "status": "success", // "data": { // "symbols": { // "WETH": { // "type": "spot", // "product_id": 3, // "symbol": "WETH", // "price_increment_x18": "100000000000000000", // "size_increment": "10000000000000000", // "min_size": "100000000000000000", // "min_depth_x18": "5000000000000000000000", // "max_spread_rate_x18": "2000000000000000", // "maker_fee_rate_x18": "0", // "taker_fee_rate_x18": "300000000000000", // "long_weight_initial_x18": "900000000000000000", // "long_weight_maintenance_x18": "950000000000000000" // } // } // }, // "request_type": "query_symbols" // } // const data = this.safeDict(response, 'data', {}); const markets = this.safeDict(data, 'symbols', {}); const symbols = Object.keys(markets); const result = []; for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const rawMarket = this.safeDict(markets, symbol, {}); result.push(this.parseMarket(rawMarket)); } return result; } /** * @method * @name vertex#fetchTime * @description fetches the current integer timestamp in milliseconds from the exchange server * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int} the current integer timestamp in milliseconds from the exchange server */ async fetchTime(params = {}) { const response = await this.v1GatewayGetTime(params); // 1717481623452 return this.parseToInt(response); } /** * @method * @name vertex#fetchStatus * @description the latest known information on the availability of the exchange API * @see https://docs.vertexprotocol.com/developer-resources/api/gateway/queries/status * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} a [status structure]{@link https://docs.ccxt.com/#/?id=exchange-status-structure} */ async fetchStatus(params = {}) { const request = { 'type': 'status', }; const response = await this.v1GatewayGetQuery(this.extend(request, params)); // // { // "status": "success", // "data": "active", // "request_type": "query_status", // } // let status = this.safeString(response, 'data'); if (status === 'active') { status = 'ok'; } else { status = 'error'; } return { 'status': status, 'updated': undefined, 'eta': undefined, 'url': undefined, 'info': response, }; } parseTrade(trade, market = undefined) { // // { // "ticker_id": "ARB_USDC", // "trade_id": 999994, // "price": 1.1366122408151016, // "base_filled": 175, // "quote_filled": -198.90714214264278, // "timestamp": 1691068943, // "trade_type": "buy" // } // fetchMytrades // { // "digest": "0x80ce789702b670b7d33f2aa67e12c85f124395c3f9acdb422dde3b4973ccd50c", // "order": { // "sender": "0x12a0b4888021576eb10a67616dd3dd3d9ce206b664656661756c740000000000", // "priceX18": "27544000000000000000000", // "amount": "2000000000000000000", // "expiration": "4611686020107119633", // "nonce": "1761322608857448448" // }, // "base_filled": "736000000000000000", // "quote_filled": "-20276464287857571514302", // "fee": "4055287857571514302", // "sequencer_fee": "0" // "cumulative_fee": "4055287857571514302", // "cumulative_base_filled": "736000000000000000", // "cumulative_quote_filled": "-20276464287857571514302", // "submission_idx": "563012", // "pre_balance": { // "base": { // "perp": { // "product_id": 2, // "lp_balance": { // "amount": "0", // "last_cumulative_funding_x18": "1823351297710837" // }, // "balance": { // "amount": "2686684000000000000000", // "v_quote_balance": "-76348662407149297671587247", // "last_cumulative_funding_x18": "134999841911604906604576" // } // } // }, // "quote": null // }, // "post_balance": { // "base": { // "perp": { // "product_id": 2, // "lp_balance": { // "amount": "0", // "last_cumulative_funding_x18": "1823351297710837" // }, // "balance": { // "amount": "2686013000000000000000", // "v_quote_balance": "-76328351274188497671587247", // "last_cumulative_funding_x18": "134999841911604906604576" // } // } // }, // "quote": null // } // } let price = undefined; let amount = undefined; let side = undefined; let fee = undefined; const feeCost = this.convertFromX18(this.safeString(trade, 'fee')); if (feeCost !== undefined) { fee = { 'cost': feeCost, 'currency': undefined, }; } const id = this.safeString2(trade, 'trade_id', 'submission_idx'); const order = this.safeString(trade, 'digest'); const timestamp = this.safeTimestamp(trade, 'timestamp'); if (timestamp === undefined) { // fetchMyTrades const baseBalance = this.safeDict(this.safeDict(trade, 'pre_balance', {}), 'base', {}); let marketId = undefined; if ('perp' in baseBalance) { marketId = this.safeString(this.safeDict(baseBalance, 'perp', {}), 'product_id'); } else { marketId = this.safeString(this.safeDict(baseBalance, 'spot', {}), 'product_id'); } market = this.safeMarket(marketId); const subOrder = this.safeDict(trade, 'order', {}); price = this.convertFromX18(this.safeString(subOrder, 'priceX18')); amount = this.convertFromX18(this.safeString(trade, 'base_filled')); if (Precise.stringLt(amount, '0')) { side = 'sell'; } else { side = 'buy'; } } else { const tickerId = this.safeString(trade, 'ticker_id'); const splitTickerId = tickerId.split('_'); const splitSymbol = splitTickerId[0].split('-'); const marketId = splitSymbol[0] + splitTickerId[1]; market = this.safeMarket(marketId, market); price = this.safeString(trade, 'price'); amount = this.safeString(trade, 'base_filled'); side = this.safeStringLower(trade, 'trade_type'); } amount = Precise.stringAbs(amount); const symbol = market['symbol']; return this.safeTrade({ 'id': id, 'timestamp': timestamp, 'datetime': this.iso8601(timestamp), 'symbol': symbol, 'side': side, 'price': price, 'amount': amount, 'cost': undefined, 'order': order, 'takerOrMaker': undefined, 'type': undefined, 'fee': fee, 'info': trade, }, market); } /** * @method * @name vertex#fetchTrades * @description get the list of most recent trades for a particular symbol * @see https://docs.vertexprotocol.com/developer-resources/api/v2/trades * @param {string} symbol unified symbol of the market to fetch trades for * @param {int} [since] timestamp in ms of the earliest trade to fetch * @param {int} [limit] the maximum amount of trades to fetch * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=public-trades} */ async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const marketId = market['baseId'] + '_USDC'; const request = { 'ticker_id': marketId, }; if (limit !== undefined) { request['limit'] = limit; } const response = await this.v2ArchiveGetTrades(this.extend(request, params)); // // [ // { // "ticker_id": "ARB_USDC", // "trade_id": 999994, // "price": 1.1366122408151016, // "base_filled": 175, // "quote_filled": -198.90714214264278, // "timestamp": 1691068943, // "trade_type": "buy" // }, // { // "ticker_id": "ARB_USDC", // "trade_id": 999978, // "price": 1.136512210806099, // "base_filled": 175, // "quote_filled": -198.8896368910673, // "timestamp": 1691068882, // "trade_type": "buy" // } // ] // return this.parseTrades(response, market, since, limit); } /** * @method * @name vertex#fetchMyTrades * @description fetch all trades made by the user * @see https://docs.vertexprotocol.com/developer-resources/api/archive-indexer/matches * @param {string} symbol unified market symbol * @param {int} [since] the earliest time in ms to fetch trades for * @param {int} [limit] the maximum number of trades structures to retrieve * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.user] user address, will default to this.walletAddress if not provided * @returns {Trade[]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure} */ async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) { await this.loadMarkets(); let userAddress = undefined; [userAddress, params] = this.handlePublicAddress('fetchMyTrades', params); let market = undefined; const matchesRequest = { 'subaccount': this.convertAddressToSender(userAddress), }; if (symbol !== undefined) { market = this.market(symbol); matchesRequest['product_ids'] = [this.parseToNumeric(market['id'])]; } const until = this.safeInteger(params, 'until'); if (until !== undefined) { params = this.omit(params, 'until'); matchesRequest['max_time'] = until; } if (limit !== undefined) { matchesRequest['limit'] = limit; } const request = { 'matches': matchesRequest, }; const response = await this.v1ArchivePost(this.extend(request, params)); // // { // "matches": [ // { // "digest": "0x80ce789702b670b7d33f2aa67e12c85f124395c3f9acdb422dde3b4973ccd50c", // "order": { // "sender": "0x12a0b4888021576eb10a67616dd3dd3d9ce206b664656661756c740000000000", // "priceX18": "27544000000000000000000", // "amount": "2000000000000000000", // "expiration": "4611686020107119633", // "nonce": "1761322608857448448" // }, // "base_filled": "736000000000000000", // "quote_filled": "-20276464287857571514302", // "fee": "4055287857571514302", // "sequencer_fee": "0" // "cumulative_fee": "4055287857571514302", // "cumulative_base_filled": "736000000000000000", // "cumulative_quote_filled": "-20276464287857571514302", // "submission_idx": "563012", // "pre_balance": { // "base": { // "perp": { // "product_id": 2, // "lp_balance": { // "amount": "0", // "last_cumulative_funding_x18": "1823351297710837" // }, // "balance": { // "amount": "2686684000000000000000", // "v_quote_balance": "-76348662407149297671587247", // "last_cumulative_funding_x18": "134999841911604906604576" // } // } // }, // "quote": null // }, // "post_balance": { // "base": { // "perp": { // "product_id": 2, // "lp_balance": { // "amount": "0", // "last_cumulative_funding_x18": "1823351297710837" // }, // "balance": { // "amount": "2686013000000000000000", // "v_quote_balance": "-76328351274188497671587247", // "last_cumulative_funding_x18": "134999841911604906604576" // } // } // }, // "quote": null // } // }, // { // "digest": "0x0f6e5a0434e36d8e6d4fed950d3624b0d8c91a8a84efd156bb25c1382561c0c2", // "order": { // "sender": "0x12a0b4888021576eb10a67616dd3dd3d9ce206b664656661756c740000000000", // "priceX18": "27540000000000000000000", // "amount": "2000000000000000000", // "expiration": "4611686020107119623", // "nonce": "1761322602510417920" // }, // "base_filled": "723999999999999999", // "quote_filled": "-19944943483044913474043", // "fee": "5983483044913474042", // "cumulative_fee": "11958484645393618085", // "cumulative_base_filled": "1446999999999999998", // "cumulative_quote_filled": "-39861640484645393618087", // "submission_idx": "563011", // "pre_balance": { // "base": { // "perp": { // "product_id": 2, // "lp_balance": { // "amount": "0", // "last_cumulative_funding_x18": "1823351297710837" // }, // "balance": { // "amount": "2686684000000000000000", // "v_quote_balance": "-76348662407149297671587247", // "last_cumulative_funding_x18": "134999841911604906604576" // } // } // }, // "quote": null // }, // "post_balance": { // "base": { // "perp": { // "product_id": 2, // "lp_balance": { // "amount": "0", // "last_cumulative_funding_x18": "1823351297710837" // }, // "balance": { // "amount": "2686013000000000000000", // "v_quote_balance": "-76328351274188497671587247", // "last_cumulative_funding_x18": "134999841911604906604576" // } // } // }, // "quote": null // } // } // ], // "txs": [ // { // "tx": { // "match_orders": { // "product_id": 2, // "amm": true, // "taker": { // "order": { // "sender": "0x12a0b4888021576eb10a67616dd3dd3d9ce206b664656661756c740000000000", // "price_x18": "27544000000000000000000", // "amount": "2000000000000000000", // "expiration": 4611686020107120000, // "nonce": 1761322608857448400 // }, // "signature": "0xe8fa7151bde348afa3b46dc52798046b7c8318f1b0a7f689710debbc094658cc1bf5a7e478ccc8278b625da0b9402c86b580d2e31e13831337dfd6153f4b37811b" // }, // "maker": { // "order": { // "sender": "0xebdbbcdbd2646c5f23a1e0806027eee5f71b074664656661756c740000000000", // "price_x18": "27544000000000000000000", // "amount": "-736000000000000000", // "expiration": 1679731669, // "nonce": 1761322585591644200 // }, // "signature": "0x47f9d47f0777f3ca0b13f07b7682dbeea098c0e377b87dcb025754fe34c900e336b8c7744e021fb9c46a4f8c6a1478bafa28bf0d023ae496aa3efa4d8e81df181c" // } // } // }, // "submission_idx": "563012", // "timestamp": "1679728133" // }, // { // "tx": { // "match_orders": { // "product_id": 1, // "amm": true, // "taker": { // "order": { // "sender": "0x12a0b4888021576eb10a67616dd3dd3d9ce206b664656661756c740000000000", // "price_x18": "27540000000000000000000", // "amount": "2000000000000000000", // "expiration": 4611686020107120000, // "nonce": 1761322602510418000 // }, // "signature": "0x826c68f1a3f76d9ffbe8041f8d45e969d31f1ab6f2ae2f6379d1493e479e56436091d6cf4c72e212dd2f1d2fa17c627c4c21bd6d281c77172b8af030488478b71c" // }, // "maker": { // "order": { // "sender": "0xf8d240d9514c9a4715d66268d7af3b53d619642564656661756c740000000000", // "price_x18": "27540000000000000000000", // "amount": "-724000000000000000", // "expiration": 1679731656, // "nonce": 1761322565506171000 // }, // "signature": "0xd8b6505b8d9b8c3cbfe793080976388035682c02a27893fb26b48a5b2bfe943f4162dea3a42e24e0dff5e2f74fbf77e33d83619140a2a581117c55e6cc236bdb1c" // } // } // }, // "submission_idx": "563011", // "timestamp": "1679728127" // } // ] // } // const trades = this.safeList(response, 'matches', []); return this.parseTrades(trades, market, since, limit, params); } /** * @method * @name vertex#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @see https://docs.vertexprotocol.com/developer-resources/api/v2/orderbook * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int} [limit] the maximum amount of order book entries to return * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/#/?id=order-book-structure} indexed by market symbols */ async fetchOrderBook(symbol, limit = undefined, params = {}) { await this.loadMarkets(); const market = this.market(symbol); const marketId = market['baseId'] + '_USDC'; if (limit === undefined) { limit = 100; } const request = { 'ticker_id': marketId, 'depth': limit, }; const response = await this.v2GatewayGetOrderbook(this.extend(request, params)); // // { // "ticker_id": "ETH-PERP_USDC", // "bids": [ // [ // 1612.3, // 0.31 // ], // [ // 1612.0, // 0.93 // ], // [ // 1611.5, // 1.55 // ], // [ // 1610.8, // 2.17 // ] // ], // "asks": [ // [ // 1612.9, // 0.93 // ], // [ // 1613.4, // 1.55 // ], // [ // 1614.1, // 2.17 // ] // ], // "timestamp": 1694375362016 // } // const timestamp = this.safeInteger(response, 'timestamp'); return this.parseOrderBook(response, symbol, timestamp, 'bids', 'asks'); } /** * @method * @name vertex#fetchTradingFees * @description fetch the trading fees for multiple markets * @see https://docs.vertexprotocol.com/developer-resources/api/gateway/queries/fee-rates * @param {object} [params] extra parameters specific to the exchange API endpoint * @param {string} [params.user] user address, will default to this.walletAddress if not provided * @returns {object} a dictionary of [fee structures]{@link https://docs.ccxt.com/#/?id=fee-structure} indexed by market symbols */ async fetchTradingFees(params = {}) { await this.loadMarkets(); let userAddress = undefined; [userAddress, params] = this.handlePublicAddress('fetchTradingFees', params); const request = { 'type': 'fee_rates', 'sender': this.convertAddressToSender(userAddress), }; const response = await this.v1GatewayGetQuery(this.extend(request, params)); // // { // "status": "success", // "data": { // "taker_fee_rates_x18": [ // "0", // "300000000000000", // "200000000000000", // "300000000000000", // "200000000000000" // ], // "maker_fee_rates_x18": [ // "0", // "0", // "0", // "0", // "0" // ], // "liquidation_sequencer_fee": "250000000000000000", // "health_check_sequencer_fee": "100000000000000000", // "taker_sequencer_fee": "25000000000000000", // "withdraw_sequencer_fees": [ // "10000000000000000", // "40000000000000", // "0", // "600000000000000", // "0" // ] // }, // "request_type": "query_fee_rates", // } // const data = this.safeDict(response, 'data', {}); const maker = this.safeList(data, 'maker_fee_rates_x18', []); const taker = this.safeList(data, 'taker_fee_rates_x18', []); const result = {}; for (let i = 0; i < taker.length; i++) { const market = this.safeMarket(this.numberToString(i)); if (market['id'] === undefined) { continue; } const symbol = market['symbol']; result[symbol] = { 'info': response, 'symbol': symbol, 'maker': this.parseNumber(this.convertFromX18(maker[i])), 'taker': this.parseNumber(this.convertFromX18(taker[i])), 'percentage': true, 'tierBased': false, }; } return result; } parseOHLCV(ohlcv, market = undefined) { // example response in fetchOHLCV return [ this.safeTimestamp(ohlcv, 'timestamp'), this.parseNumber(this.convertFromX18(this.safeString(ohlcv, 'open_x18'))), this.parseNumber(this.convertFromX18(this.safeString(ohlcv, 'high_x18'))), this.parseNumber(this.convertFromX18(this.safeString(ohlcv, 'low_x18'))), this.parseNumber(this.convertFromX18(this.safeString(ohlcv, 'close_x18'))), this.parseNumber(this.convertFromX18(this.safeString(ohlcv, 'volume'))), ]; } /** * @method * @name vertex#fetchOHLCV * @see https://docs.vertexprotocol.com/developer-resources/api/archive-indexer/candlesticks * @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market * @param {string} symbol unified symbol of the market to fetch OHLCV data for * @param {string} timeframe the length of time each candle represents * @param {int} [since] timestamp in ms of the earliest candle to fetch * @param {int} [limit] max=1000, max=100 when since is defined and is less than (now - (999 * (timeframe in ms))) * @param {object} [params] extra parameters specific to the exchange API endpoint * @returns {int[][]} A list of candles ordered as timestamp, open, high, low, close, volume