@proton/ccxt
Version:
A JavaScript / TypeScript / Python / C# / PHP cryptocurrency trading library with support for 130+ exchanges
1,193 lines (1,191 loc) • 96.4 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/poloniex.js';
import { ArgumentsRequired, ExchangeError, ExchangeNotAvailable, NotSupported, RequestTimeout, AuthenticationError, PermissionDenied, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, OnMaintenance, BadSymbol, BadRequest, CancelPending } from './base/errors.js';
import { Precise } from './base/Precise.js';
import { TICK_SIZE } from './base/functions/number.js';
import { sha256 } from './static_dependencies/noble-hashes/sha256.js';
// ---------------------------------------------------------------------------
export default class poloniex extends Exchange {
describe() {
return this.deepExtend(super.describe(), {
'id': 'poloniex',
'name': 'Poloniex',
'countries': ['US'],
// 200 requests per second for some unauthenticated market endpoints => 1000ms / 200 = 5ms between requests
'rateLimit': 5,
'certified': false,
'pro': true,
'has': {
'CORS': undefined,
'spot': true,
'margin': undefined,
'swap': undefined,
'future': undefined,
'option': undefined,
'cancelAllOrders': true,
'cancelOrder': true,
'createDepositAddress': true,
'createOrder': true,
'editOrder': true,
'fetchBalance': true,
'fetchClosedOrder': false,
'fetchCurrencies': true,
'fetchDepositAddress': true,
'fetchDeposits': true,
'fetchDepositsWithdrawals': true,
'fetchDepositWithdrawFee': 'emulated',
'fetchDepositWithdrawFees': true,
'fetchMarginMode': false,
'fetchMarkets': true,
'fetchMyTrades': true,
'fetchOHLCV': true,
'fetchOpenInterestHistory': false,
'fetchOpenOrder': false,
'fetchOpenOrders': true,
'fetchOrder': true,
'fetchOrderBook': true,
'fetchOrderBooks': false,
'fetchOrderTrades': true,
'fetchPosition': false,
'fetchPositionMode': false,
'fetchTicker': true,
'fetchTickers': true,
'fetchTime': true,
'fetchTrades': true,
'fetchTradingFee': false,
'fetchTradingFees': true,
'fetchTransactions': true,
'fetchTransfer': false,
'fetchTransfers': false,
'fetchWithdrawals': true,
'transfer': true,
'withdraw': true,
},
'timeframes': {
'1m': 'MINUTE_1',
'5m': 'MINUTE_5',
'10m': 'MINUTE_10',
'15m': 'MINUTE_15',
'30m': 'MINUTE_30',
'1h': 'HOUR_1',
'2h': 'HOUR_2',
'4h': 'HOUR_4',
'6h': 'HOUR_6',
'12h': 'HOUR_12',
'1d': 'DAY_1',
'3d': 'DAY_3',
'1w': 'WEEK_1',
'1M': 'MONTH_1',
},
'urls': {
'logo': 'https://user-images.githubusercontent.com/1294454/27766817-e9456312-5ee6-11e7-9b3c-b628ca5626a5.jpg',
'api': {
'rest': 'https://api.poloniex.com',
},
'test': {
'rest': 'https://sand-spot-api-gateway.poloniex.com',
},
'www': 'https://www.poloniex.com',
'doc': 'https://docs.poloniex.com',
'fees': 'https://poloniex.com/fees',
'referral': 'https://poloniex.com/signup?c=UBFZJRPJ',
},
'api': {
'public': {
'get': {
'markets': 20,
'markets/{symbol}': 1,
'currencies': 20,
'currencies/{currency}': 20,
'timestamp': 1,
'markets/price': 1,
'markets/{symbol}/price': 1,
'markets/{symbol}/orderBook': 1,
'markets/{symbol}/candles': 1,
'markets/{symbol}/trades': 20,
'markets/ticker24h': 20,
'markets/{symbol}/ticker24h': 20,
},
},
'private': {
'get': {
'accounts': 4,
'accounts/activity': 4,
'accounts/balances': 4,
'accounts/{id}/balances': 4,
'accounts/transfer': 20,
'accounts/transfer/{id}': 4,
'subaccounts': 4,
'subaccounts/balances': 20,
'subaccounts/{id}/balances': 4,
'subaccounts/transfer': 20,
'subaccounts/transfer/{id}': 4,
'feeinfo': 20,
'wallets/addresses': 20,
'wallets/activity': 20,
'wallets/addresses/{currency}': 20,
'orders': 20,
'orders/{id}': 4,
'orders/history': 20,
'orders/killSwitchStatus': 4,
'smartorders': 20,
'smartorders/{id}': 4,
'smartorders/history': 20,
'trades': 20,
'orders/{id}/trades': 4,
},
'post': {
'accounts/transfer': 4,
'subaccounts/transfer': 20,
'wallets/address': 20,
'wallets/withdraw': 20,
'orders': 4,
'orders/killSwitch': 4,
'orders/batch': 20,
'smartorders': 4,
},
'delete': {
'orders/{id}': 4,
'orders/cancelByIds': 20,
'orders': 20,
'smartorders/{id}': 4,
'smartorders/cancelByIds': 20,
'smartorders': 20,
},
'put': {
'orders/{id}': 4,
'smartorders/{id}': 4,
},
},
},
'fees': {
'trading': {
'feeSide': 'get',
// starting from Jan 8 2020
'maker': this.parseNumber('0.0009'),
'taker': this.parseNumber('0.0009'),
},
'funding': {},
},
'commonCurrencies': {
'AIR': 'AirCoin',
'APH': 'AphroditeCoin',
'BCC': 'BTCtalkcoin',
'BCHABC': 'BCHABC',
'BDG': 'Badgercoin',
'BTM': 'Bitmark',
'CON': 'Coino',
'ETHTRON': 'ETH',
'GOLD': 'GoldEagles',
'GPUC': 'GPU',
'HOT': 'Hotcoin',
'ITC': 'Information Coin',
'KEY': 'KEYCoin',
'MASK': 'NFTX Hashmasks Index',
'MEME': 'Degenerator Meme',
'PLX': 'ParallaxCoin',
'REPV2': 'REP',
'STR': 'XLM',
'SOC': 'SOCC',
'TRADE': 'Unitrade',
'TRXETH': 'TRX',
'XAP': 'API Coin',
// this is not documented in the API docs for Poloniex
// https://github.com/ccxt/ccxt/issues/7084
// when the user calls withdraw ('USDT', amount, address, tag, params)
// with params = { 'currencyToWithdrawAs': 'USDTTRON' }
// or params = { 'currencyToWithdrawAs': 'USDTETH' }
// fetchWithdrawals ('USDT') returns the corresponding withdrawals
// with a USDTTRON or a USDTETH currency id, respectfully
// therefore we have map them back to the original code USDT
// otherwise the returned withdrawals are filtered out
'USDTBSC': 'USDT',
'USDTTRON': 'USDT',
'USDTETH': 'USDT',
'UST': 'USTC',
},
'options': {
'networks': {
'BEP20': 'BSC',
'ERC20': 'ETH',
'TRC20': 'TRON',
},
'networksById': {
'BSC': 'BEP20',
'ETH': 'ERC20',
'TRON': 'TRC20',
'TRX': 'TRC20',
},
'limits': {
'cost': {
'min': {
'BTC': 0.0001,
'ETH': 0.0001,
'USDT': 1.0,
'TRX': 100,
'BNB': 0.06,
'USDC': 1.0,
'USDJ': 1.0,
'TUSD': 0.0001,
'DAI': 1.0,
'PAX': 1.0,
'BUSD': 1.0,
},
},
},
'accountsByType': {
'spot': 'spot',
'future': 'futures',
},
'accountsById': {
'exchange': 'spot',
'futures': 'future',
},
},
'precisionMode': TICK_SIZE,
'exceptions': {
'exact': {
// General
'200': CancelPending,
'500': ExchangeNotAvailable,
'603': RequestTimeout,
'601': BadRequest,
'415': ExchangeError,
'602': ArgumentsRequired,
// Accounts
'21604': BadRequest,
'21600': AuthenticationError,
'21605': AuthenticationError,
'21102': ExchangeError,
'21100': AuthenticationError,
'21704': AuthenticationError,
'21700': BadRequest,
'21705': BadRequest,
'21707': ExchangeError,
'21708': BadRequest,
'21601': AccountSuspended,
'21711': ExchangeError,
'21709': InsufficientFunds,
'250000': ExchangeError,
'250001': BadRequest,
'250002': BadRequest,
'250003': BadRequest,
'250004': BadRequest,
'250005': InsufficientFunds,
'250008': BadRequest,
'250012': ExchangeError,
// Trading
'21110': BadRequest,
'10040': BadSymbol,
'10060': ExchangeError,
'10020': BadSymbol,
'10041': BadSymbol,
'21340': OnMaintenance,
'21341': InvalidOrder,
'21342': InvalidOrder,
'21343': InvalidOrder,
'21351': AccountSuspended,
'21352': BadSymbol,
'21353': PermissionDenied,
'21354': PermissionDenied,
'21360': InvalidOrder,
'24106': BadRequest,
'24201': ExchangeNotAvailable,
// Orders
'21301': OrderNotFound,
'21302': ExchangeError,
'21304': ExchangeError,
'21305': OrderNotFound,
'21307': ExchangeError,
'21309': InvalidOrder,
'21310': InvalidOrder,
'21311': InvalidOrder,
'21312': InvalidOrder,
'21314': InvalidOrder,
'21315': InvalidOrder,
'21317': InvalidOrder,
'21319': InvalidOrder,
'21320': InvalidOrder,
'21321': InvalidOrder,
'21322': InvalidOrder,
'21324': BadRequest,
'21327': InvalidOrder,
'21328': InvalidOrder,
'21330': InvalidOrder,
'21335': InvalidOrder,
'21336': InvalidOrder,
'21337': InvalidOrder,
'21344': InvalidOrder,
'21345': InvalidOrder,
'21346': InvalidOrder,
'21348': InvalidOrder,
'21347': InvalidOrder,
'21349': InvalidOrder,
'21350': InvalidOrder,
'21355': ExchangeError,
'21356': BadRequest,
'24101': BadSymbol,
'24102': InvalidOrder,
'24103': InvalidOrder,
'24104': InvalidOrder,
'24105': InvalidOrder,
'25020': InvalidOrder,
// Smartorders
'25000': InvalidOrder,
'25001': InvalidOrder,
'25002': InvalidOrder,
'25003': ExchangeError,
'25004': InvalidOrder,
'25005': ExchangeError,
'25006': InvalidOrder,
'25007': InvalidOrder,
'25008': InvalidOrder,
'25009': ExchangeError,
'25010': PermissionDenied,
'25011': InvalidOrder,
'25012': ExchangeError,
'25013': OrderNotFound,
'25014': OrderNotFound,
'25015': OrderNotFound,
'25016': ExchangeError,
'25017': ExchangeError,
'25018': BadRequest,
'25019': BadSymbol, // Invalid symbol
},
'broad': {},
},
});
}
parseOHLCV(ohlcv, market = undefined) {
//
// [
// [
// "22814.01",
// "22937.42",
// "22832.57",
// "22937.42",
// "3916.58764051",
// "0.171199",
// "2982.64647063",
// "0.130295",
// 33,
// 0,
// "22877.449915304470460711",
// "MINUTE_5",
// 1659664800000,
// 1659665099999
// ]
// ]
//
return [
this.safeInteger(ohlcv, 12),
this.safeNumber(ohlcv, 2),
this.safeNumber(ohlcv, 1),
this.safeNumber(ohlcv, 0),
this.safeNumber(ohlcv, 3),
this.safeNumber(ohlcv, 5),
];
}
async fetchOHLCV(symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name poloniex#fetchOHLCV
* @description fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
* @see https://docs.poloniex.com/#public-endpoints-market-data-candles
* @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|undefined} since timestamp in ms of the earliest candle to fetch
* @param {int|undefined} limit the maximum amount of candles to fetch
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {[[int]]} A list of candles ordered as timestamp, open, high, low, close, volume
*/
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
'interval': this.safeString(this.timeframes, timeframe, timeframe),
};
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
// limit should in between 100 and 500
request['limit'] = limit;
}
const response = await this.publicGetMarketsSymbolCandles(this.extend(request, params));
//
// [
// [
// "22814.01",
// "22937.42",
// "22832.57",
// "22937.42",
// "3916.58764051",
// "0.171199",
// "2982.64647063",
// "0.130295",
// 33,
// 0,
// "22877.449915304470460711",
// "MINUTE_5",
// 1659664800000,
// 1659665099999
// ]
// ]
//
return this.parseOHLCVs(response, market, timeframe, since, limit);
}
async loadMarkets(reload = false, params = {}) {
const markets = await super.loadMarkets(reload, params);
const currenciesByNumericId = this.safeValue(this.options, 'currenciesByNumericId');
if ((currenciesByNumericId === undefined) || reload) {
this.options['currenciesByNumericId'] = this.indexBy(this.currencies, 'numericId');
}
return markets;
}
async fetchMarkets(params = {}) {
/**
* @method
* @name poloniex#fetchMarkets
* @description retrieves data on all markets for poloniex
* @see https://docs.poloniex.com/#public-endpoints-reference-data-symbol-information
* @param {object} params extra parameters specific to the exchange api endpoint
* @returns {[object]} an array of objects representing market data
*/
const markets = await this.publicGetMarkets(params);
//
// [
// {
// "symbol" : "BTS_BTC",
// "baseCurrencyName" : "BTS",
// "quoteCurrencyName" : "BTC",
// "displayName" : "BTS/BTC",
// "state" : "NORMAL",
// "visibleStartTime" : 1659018816626,
// "tradableStartTime" : 1659018816626,
// "symbolTradeLimit" : {
// "symbol" : "BTS_BTC",
// "priceScale" : 10,
// "quantityScale" : 0,
// "amountScale" : 8,
// "minQuantity" : "100",
// "minAmount" : "0.00001",
// "highestBid" : "0",
// "lowestAsk" : "0"
// }
// }
// ]
//
const result = [];
for (let i = 0; i < markets.length; i++) {
const market = this.safeValue(markets, i);
const id = this.safeString(market, 'symbol');
const baseId = this.safeString(market, 'baseCurrencyName');
const quoteId = this.safeString(market, 'quoteCurrencyName');
const base = this.safeCurrencyCode(baseId);
const quote = this.safeCurrencyCode(quoteId);
const state = this.safeString(market, 'state');
const active = state === 'NORMAL';
const symbolTradeLimit = this.safeValue(market, 'symbolTradeLimit');
// these are known defaults
result.push({
'id': id,
'symbol': base + '/' + quote,
'base': base,
'quote': quote,
'settle': undefined,
'baseId': baseId,
'quoteId': quoteId,
'settleId': undefined,
'type': 'spot',
'spot': true,
'margin': false,
'swap': false,
'future': false,
'option': false,
'active': active,
'contract': false,
'linear': undefined,
'inverse': undefined,
'contractSize': undefined,
'expiry': undefined,
'expiryDatetime': undefined,
'strike': undefined,
'optionType': undefined,
'precision': {
'amount': this.parseNumber(this.parsePrecision(this.safeString(symbolTradeLimit, 'quantityScale'))),
'price': this.parseNumber(this.parsePrecision(this.safeString(symbolTradeLimit, 'priceScale'))),
},
'limits': {
'amount': {
'min': this.safeNumber(symbolTradeLimit, 'minQuantity'),
'max': undefined,
},
'price': {
'min': undefined,
'max': undefined,
},
'cost': {
'min': this.safeNumber(symbolTradeLimit, 'minAmount'),
'max': undefined,
},
},
'info': market,
});
}
return result;
}
async fetchTime(params = {}) {
/**
* @method
* @name poloniex#fetchTime
* @description fetches the current integer timestamp in milliseconds from the exchange server
* @see https://docs.poloniex.com/#public-endpoints-reference-data-system-timestamp
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {int} the current integer timestamp in milliseconds from the exchange server
*/
const response = await this.publicGetTimestamp(params);
return this.safeInteger(response, 'serverTime');
}
parseTicker(ticker, market = undefined) {
//
// {
// "symbol" : "BTC_USDT",
// "open" : "22814.93",
// "low" : "22441.90",
// "high" : "23413.00",
// "close" : "23148.66",
// "quantity" : "71.743706",
// "amount" : "1638994.52683452",
// "tradeCount" : 3893,
// "startTime" : 1659605760000,
// "closeTime" : 1659692161077,
// "displayName" : "BTC/USDT",
// "dailyChange" : "0.0152",
// "ts" : 1659692169838
// }
//
const timestamp = this.safeInteger(ticker, 'ts');
const marketId = this.safeString(ticker, 'symbol');
market = this.safeMarket(marketId);
const close = this.safeString(ticker, 'close');
const relativeChange = this.safeString(ticker, 'percentChange');
const percentage = Precise.stringMul(relativeChange, '100');
return this.safeTicker({
'id': marketId,
'symbol': market['symbol'],
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'high': this.safeString(ticker, 'high'),
'low': this.safeString(ticker, 'low'),
'bid': undefined,
'bidVolume': undefined,
'ask': undefined,
'askVolume': undefined,
'vwap': undefined,
'open': this.safeString(ticker, 'open'),
'close': close,
'last': close,
'previousClose': undefined,
'change': undefined,
'percentage': percentage,
'average': undefined,
'baseVolume': this.safeString(ticker, 'quantity'),
'quoteVolume': this.safeString(ticker, 'amount'),
'info': ticker,
}, market);
}
async fetchTickers(symbols = undefined, params = {}) {
/**
* @method
* @name poloniex#fetchTickers
* @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
* @see https://docs.poloniex.com/#public-endpoints-market-data-ticker
* @param {[string]|undefined} symbols unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {object} a dictionary of [ticker structures]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
await this.loadMarkets();
symbols = this.marketSymbols(symbols);
const response = await this.publicGetMarketsTicker24h(params);
//
// [
// {
// "symbol" : "KUB_USDD",
// "open" : "0",
// "low" : "0",
// "high" : "0",
// "close" : "0",
// "quantity" : "0",
// "amount" : "0",
// "tradeCount" : 0,
// "startTime" : 1659606240000,
// "closeTime" : 1659692648742,
// "displayName" : "KUB/USDD",
// "dailyChange" : "0.00",
// "ts" : 1659692648742
// }
// ]
//
return this.parseTickers(response, symbols);
}
async fetchCurrencies(params = {}) {
/**
* @method
* @name poloniex#fetchCurrencies
* @description fetches all available currencies on an exchange
* @see https://docs.poloniex.com/#public-endpoints-reference-data-currency-information
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {object} an associative dictionary of currencies
*/
const response = await this.publicGetCurrencies(this.extend(params, { 'includeMultiChainCurrencies': true }));
//
// [
// {
// "1CR": {
// "id": 1,
// "name": "1CRedit",
// "description": "BTC Clone",
// "type": "address",
// "withdrawalFee": "0.01000000",
// "minConf": 10000,
// "depositAddress": null,
// "blockchain": "1CR",
// "delisted": false,
// "tradingState": "NORMAL",
// "walletState": "DISABLED",
// "walletDepositState": 'DISABLED',
// "walletWithdrawalState": 'DISABLED',
// "parentChain": null,
// "isMultiChain": false,
// "isChildChain": false,
// "childChains": []
// }
// }
// ]
//
const result = {};
for (let i = 0; i < response.length; i++) {
const item = this.safeValue(response, i);
const ids = Object.keys(item);
const id = this.safeValue(ids, 0);
const currency = this.safeValue(item, id);
const code = this.safeCurrencyCode(id);
const name = this.safeString(currency, 'name');
const networkId = this.safeString(currency, 'blockchain');
const networkCode = this.networkIdToCode(networkId, code);
const delisted = this.safeValue(currency, 'delisted');
const walletEnabled = this.safeString(currency, 'walletState') === 'ENABLED';
const depositEnabled = this.safeString(currency, 'walletDepositState') === 'ENABLED';
const withdrawEnabled = this.safeString(currency, 'walletWithdrawalState') === 'ENABLED';
const active = !delisted && walletEnabled && depositEnabled && withdrawEnabled;
const numericId = this.safeInteger(currency, 'id');
const feeString = this.safeString(currency, 'withdrawalFee');
const parentChain = this.safeValue(currency, 'parentChain');
const noParentChain = parentChain === undefined;
if (this.safeValue(result, code) === undefined) {
result[code] = {
'id': id,
'code': code,
'info': undefined,
'name': name,
'active': active,
'deposit': depositEnabled,
'withdraw': withdrawEnabled,
'fee': this.parseNumber(feeString),
'precision': undefined,
'limits': {
'amount': {
'min': undefined,
'max': undefined,
},
'deposit': {
'min': undefined,
'max': undefined,
},
'withdraw': {
'min': undefined,
'max': undefined,
},
},
};
}
let minFeeString = this.safeString(result[code], 'fee');
if (feeString !== undefined) {
minFeeString = (minFeeString === undefined) ? feeString : Precise.stringMin(feeString, minFeeString);
}
let depositAvailable = this.safeValue(result[code], 'deposit');
depositAvailable = (depositEnabled) ? depositEnabled : depositAvailable;
let withdrawAvailable = this.safeValue(result[code], 'withdraw');
withdrawAvailable = (withdrawEnabled) ? withdrawEnabled : withdrawAvailable;
const networks = this.safeValue(result[code], 'networks', {});
networks[networkCode] = {
'info': currency,
'id': networkId,
'network': networkCode,
'currencyId': id,
'numericId': numericId,
'deposit': depositEnabled,
'withdraw': withdrawEnabled,
'active': active,
'fee': this.parseNumber(feeString),
'precision': undefined,
'limits': {
'amount': {
'min': undefined,
'max': undefined,
},
'withdraw': {
'min': undefined,
'max': undefined,
},
'deposit': {
'min': undefined,
'max': undefined,
},
},
};
result[code]['networks'] = networks;
const info = this.safeValue(result[code], 'info', []);
const rawInfo = {};
rawInfo[id] = currency;
info.push(rawInfo);
result[code]['info'] = info;
if (noParentChain) {
result[code]['id'] = id;
result[code]['name'] = name;
}
result[code]['active'] = depositAvailable && withdrawAvailable;
result[code]['deposit'] = depositAvailable;
result[code]['withdraw'] = withdrawAvailable;
result[code]['fee'] = this.parseNumber(minFeeString);
}
return result;
}
async fetchTicker(symbol, params = {}) {
/**
* @method
* @name poloniex#fetchTicker
* @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
* @see https://docs.poloniex.com/#public-endpoints-market-data-ticker
* @param {string} symbol unified symbol of the market to fetch the ticker for
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {object} a [ticker structure]{@link https://docs.ccxt.com/#/?id=ticker-structure}
*/
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
const response = await this.publicGetMarketsSymbolTicker24h(this.extend(request, params));
//
// {
// "symbol" : "BTC_USDT",
// "open" : "22814.93",
// "low" : "22441.90",
// "high" : "23413.00",
// "close" : "23148.66",
// "quantity" : "71.743706",
// "amount" : "1638994.52683452",
// "tradeCount" : 3893,
// "startTime" : 1659605760000,
// "closeTime" : 1659692161077,
// "displayName" : "BTC/USDT",
// "dailyChange" : "0.0152",
// "ts" : 1659692169838
// }
//
return this.parseTicker(response, market);
}
parseTrade(trade, market = undefined) {
//
// fetchTrades
//
// {
// "id" : "60014521",
// "price" : "23162.94",
// "quantity" : "0.00009",
// "amount" : "2.0846646",
// "takerSide" : "SELL",
// "ts" : 1659684602042,
// "createTime" : 1659684602036
// }
//
// fetchMyTrades
//
// {
// "id": "32164924331503616",
// "symbol": "LINK_USDT",
// "accountType": "SPOT",
// "orderId": "32164923987566592",
// "side": "SELL",
// "type": "MARKET",
// "matchRole": "TAKER",
// "createTime": 1648635115525,
// "price": "11",
// "quantity": "0.5",
// "amount": "5.5",
// "feeCurrency": "USDT",
// "feeAmount": "0.007975",
// "pageId": "32164924331503616",
// "clientOrderId": "myOwnId-321"
// }
//
// fetchOrderTrades (taker trades)
//
// {
// "id": "30341456333942784",
// "symbol": "LINK_USDT",
// "accountType": "SPOT",
// "orderId": "30249408733945856",
// "side": "BUY",
// "type": "LIMIT",
// "matchRole": "MAKER",
// "createTime": 1648200366864,
// "price": "3.1",
// "quantity": "1",
// "amount": "3.1",
// "feeCurrency": "LINK",
// "feeAmount": "0.00145",
// "pageId": "30341456333942784",
// "clientOrderId": ""
// }
//
//
const id = this.safeString2(trade, 'id', 'tradeID');
const orderId = this.safeString(trade, 'orderId');
const timestamp = this.safeInteger2(trade, 'ts', 'createTime');
const marketId = this.safeString(trade, 'symbol');
market = this.safeMarket(marketId, market, '_');
const symbol = market['symbol'];
const side = this.safeStringLower2(trade, 'side', 'takerSide');
let fee = undefined;
const priceString = this.safeString(trade, 'price');
const amountString = this.safeString(trade, 'quantity');
const costString = this.safeString(trade, 'amount');
const feeCurrencyId = this.safeString(trade, 'feeCurrency');
const feeCostString = this.safeString(trade, 'feeAmount');
if (feeCostString !== undefined) {
const feeCurrencyCode = this.safeCurrencyCode(feeCurrencyId);
fee = {
'cost': feeCostString,
'currency': feeCurrencyCode,
};
}
return this.safeTrade({
'id': id,
'info': trade,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'symbol': symbol,
'order': orderId,
'type': this.safeStringLower(trade, 'type'),
'side': side,
'takerOrMaker': this.safeStringLower(trade, 'matchRole'),
'price': priceString,
'amount': amountString,
'cost': costString,
'fee': fee,
}, market);
}
async fetchTrades(symbol, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name poloniex#fetchTrades
* @description get the list of most recent trades for a particular symbol
* @see https://docs.poloniex.com/#public-endpoints-market-data-trades
* @param {string} symbol unified symbol of the market to fetch trades for
* @param {int|undefined} since timestamp in ms of the earliest trade to fetch
* @param {int|undefined} limit the maximum amount of trades to fetch
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/en/latest/manual.html?#public-trades}
*/
await this.loadMarkets();
const market = this.market(symbol);
const request = {
'symbol': market['id'],
};
if (limit !== undefined) {
request['limit'] = limit;
}
const trades = await this.publicGetMarketsSymbolTrades(this.extend(request, params));
//
// [
// {
// "id" : "60014521",
// "price" : "23162.94",
// "quantity" : "0.00009",
// "amount" : "2.0846646",
// "takerSide" : "SELL",
// "ts" : 1659684602042,
// "createTime" : 1659684602036
// }
// ]
//
return this.parseTrades(trades, market, since, limit);
}
async fetchMyTrades(symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name poloniex#fetchMyTrades
* @description fetch all trades made by the user
* @see https://docs.poloniex.com/#authenticated-endpoints-trades-trade-history
* @param {string|undefined} symbol unified market symbol
* @param {int|undefined} since the earliest time in ms to fetch trades for
* @param {int|undefined} limit the maximum number of trades structures to retrieve
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {[object]} a list of [trade structures]{@link https://docs.ccxt.com/#/?id=trade-structure}
*/
await this.loadMarkets();
let market = undefined;
if (symbol !== undefined) {
market = this.market(symbol);
}
const request = {
// 'from': 12345678, // A 'trade Id'. The query begins at ‘from'.
// 'direction': 'PRE', // PRE, NEXT The direction before or after ‘from'.
};
if (since !== undefined) {
request['startTime'] = since;
}
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.privateGetTrades(this.extend(request, params));
//
// [
// {
// "id": "32164924331503616",
// "symbol": "LINK_USDT",
// "accountType": "SPOT",
// "orderId": "32164923987566592",
// "side": "SELL",
// "type": "MARKET",
// "matchRole": "TAKER",
// "createTime": 1648635115525,
// "price": "11",
// "quantity": "0.5",
// "amount": "5.5",
// "feeCurrency": "USDT",
// "feeAmount": "0.007975",
// "pageId": "32164924331503616",
// "clientOrderId": "myOwnId-321"
// }
// ]
//
const result = this.parseTrades(response, market);
return this.filterBySinceLimit(result, since, limit);
}
parseOrderStatus(status) {
const statuses = {
'NEW': 'open',
'PARTIALLY_FILLED': 'open',
'FILLED': 'closed',
'PENDING_CANCEL': 'canceled',
'PARTIALLY_CANCELED': 'canceled',
'CANCELED': 'canceled',
'FAILED': 'canceled',
};
return this.safeString(statuses, status, status);
}
parseOrder(order, market = undefined) {
//
// fetchOpenOrder
//
// {
// "id" : "7xxxxxxxxxxxxxxx6",
// "clientOrderId" : "",
// "symbol" : "ETH_USDT",
// "state" : "NEW",
// "accountType" : "SPOT",
// "side" : "BUY",
// "type" : "LIMIT",
// "timeInForce" : "GTC",
// "quantity" : "0.001",
// "price" : "1600",
// "avgPrice" : "0",
// "amount" : "0",
// "filledQuantity" : "0",
// "filledAmount" : "0",
// "createTime" : 16xxxxxxxxx26,
// "updateTime" : 16xxxxxxxxx36
// }
//
// fetchOpenOrders
//
// {
// "id": "24993088082542592",
// "clientOrderId": "",
// "symbol": "ELON_USDC",
// "state": "NEW",
// "accountType": "SPOT",
// "side": "SELL",
// "type": "MARKET",
// "timeInForce": "GTC",
// "quantity": "1.00",
// "price": "0.00",
// "avgPrice": "0.00",
// "amount": "0.00",
// "filledQuantity": "0.00",
// "filledAmount": "0.00",
// "createTime": 1646925216548,
// "updateTime": 1646925216548
// }
//
// createOrder, editOrder
//
// {
// "id": "29772698821328896",
// "clientOrderId": "1234Abc"
// }
//
let timestamp = this.safeInteger2(order, 'timestamp', 'createTime');
if (timestamp === undefined) {
timestamp = this.parse8601(this.safeString(order, 'date'));
}
const marketId = this.safeString(order, 'symbol');
market = this.safeMarket(marketId, market, '_');
const symbol = market['symbol'];
let resultingTrades = this.safeValue(order, 'resultingTrades');
if (!Array.isArray(resultingTrades)) {
resultingTrades = this.safeValue(resultingTrades, this.safeString(market, 'id', marketId));
}
const price = this.safeString2(order, 'price', 'rate');
const amount = this.safeString(order, 'quantity');
const filled = this.safeString(order, 'filledQuantity');
const status = this.parseOrderStatus(this.safeString(order, 'state'));
const side = this.safeStringLower(order, 'side');
const rawType = this.safeString(order, 'type');
const type = this.parseOrderType(rawType);
const id = this.safeString2(order, 'orderNumber', 'id');
let fee = undefined;
const feeCurrency = this.safeString(order, 'tokenFeeCurrency');
let feeCost = undefined;
let feeCurrencyCode = undefined;
const rate = this.safeString(order, 'fee');
if (feeCurrency === undefined) {
feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
}
else {
// poloniex accepts a 30% discount to pay fees in TRX
feeCurrencyCode = this.safeCurrencyCode(feeCurrency);
feeCost = this.safeString(order, 'tokenFee');
}
if (feeCost !== undefined) {
fee = {
'rate': rate,
'cost': feeCost,
'currency': feeCurrencyCode,
};
}
const clientOrderId = this.safeString(order, 'clientOrderId');
return this.safeOrder({
'info': order,
'id': id,
'clientOrderId': clientOrderId,
'timestamp': timestamp,
'datetime': this.iso8601(timestamp),
'lastTradeTimestamp': this.safeInteger(order, 'updateTime'),
'status': status,
'symbol': symbol,
'type': type,
'timeInForce': this.safeString(order, 'timeInForce'),
'postOnly': undefined,
'side': side,
'price': price,
'stopPrice': undefined,
'triggerPrice': undefined,
'cost': undefined,
'average': this.safeString(order, 'avgPrice'),
'amount': amount,
'filled': filled,
'remaining': undefined,
'trades': resultingTrades,
'fee': fee,
}, market);
}
parseOrderType(status) {
const statuses = {
'MARKET': 'market',
'LIMIT': 'limit',
'STOP-LIMIT': 'limit',
'STOP-MARKET': 'market',
};
return this.safeString(statuses, status, status);
}
parseOpenOrders(orders, market, result) {
for (let i = 0; i < orders.length; i++) {
const order = orders[i];
const extended = this.extend(order, {
'status': 'open',
'type': 'limit',
'side': order['type'],
'price': order['rate'],
});
result.push(this.parseOrder(extended, market));
}
return result;
}
async fetchOpenOrders(symbol = undefined, since = undefined, limit = undefined, params = {}) {
/**
* @method
* @name poloniex#fetchOpenOrders
* @description fetch all unfilled currently open orders
* @see https://docs.poloniex.com/#authenticated-endpoints-orders-open-orders
* @param {string|undefined} symbol unified market symbol
* @param {int|undefined} since the earliest time in ms to fetch open orders for
* @param {int|undefined} limit the maximum number of open orders structures to retrieve
* @param {object} params extra parameters specific to the poloniex api endpoint
* @returns {[object]} a list of [order structures]{@link https://docs.ccxt.com/#/?id=order-structure}
*/
await this.loadMarkets();
let market = undefined;
const request = {};
if (symbol !== undefined) {
market = this.market(symbol);
request['symbol'] = market['id'];
}
if (limit !== undefined) {
request['limit'] = limit;
}
const response = await this.privateGetOrders(this.extend(request, params));
//
// [
// {
// "id" : "7xxxxxxxxxxxxxxx6",
// "clientOrderId" : "",
// "symbol" : "ETH_USDT",
// "state" : "NEW",
// "accountType" : "SPOT",
// "side" : "BUY",
// "type" : "LIMIT",
// "timeInForce" : "GTC",
// "quantity" : "0.001",
// "price" : "1600",
// "avgPrice" : "0",
// "amount" : "0",
// "filledQuantity" : "0",
// "filledAmount" : "0",
// "createTime" : 16xxxxxxxxx26,
// "updateTime" : 16xxxxxxxxx36
// }
// ]
//
const extension = { 'status': 'open' };
return this.parseOrders(response, market, since, limit, extension);
}
async createOrder(symbol, type, side, amount, price = undefined, params = {}) {
/**
* @method
* @name poloniex#createOrder
* @description create a trade order
* @see https://docs.poloniex.com/#authenticated-endpoints-orders-create-order
* @param {string} symbol unified symbol of the market to create an order in
* @param {string} type 'market' or 'limit'
* @param {string} side 'buy' or 'sell'
* @param {float} amount how much of currency you want to trade in units of base currency
* @param {float|undefined} price the price at which the order is to be fullfilled, in units of th