ccxt
Version:
1,210 lines (1,207 loc) • 136 kB
JavaScript
// ----------------------------------------------------------------------------
// 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