UNPKG

sfccxt

Version:

A JavaScript / Python / PHP cryptocurrency trading library with support for 130+ exchanges

1,170 lines (1,146 loc) 75.7 kB
'use strict'; // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); const { ExchangeError, ArgumentsRequired, BadRequest, OrderNotFound, InvalidAddress } = require ('./base/errors'); const { TICK_SIZE } = require ('./base/functions/number'); const Precise = require ('./base/Precise'); // --------------------------------------------------------------------------- module.exports = class therock extends Exchange { describe () { return this.deepExtend (super.describe (), { 'id': 'therock', 'name': 'TheRockTrading', 'countries': [ 'MT' ], // 10 requests per second => 1000ms / 10 => 100 ms between requests (all endpoints) 'rateLimit': 100, 'version': 'v1', 'has': { 'CORS': undefined, 'spot': true, 'margin': undefined, // has but unimplemented 'swap': false, 'future': false, 'option': false, 'cancelOrder': true, 'createOrder': true, 'fetchBalance': true, 'fetchClosedOrders': true, 'fetchDeposits': true, 'fetchFundingHistory': false, 'fetchFundingRate': false, 'fetchFundingRateHistory': false, 'fetchFundingRates': false, 'fetchIndexOHLCV': false, 'fetchLedger': true, 'fetchMarginMode': false, 'fetchMarkets': true, 'fetchMarkOHLCV': false, 'fetchMyTrades': true, 'fetchOHLCV': true, 'fetchOpenInterestHistory': false, 'fetchOpenOrders': true, 'fetchOrder': true, 'fetchOrderBook': true, 'fetchOrders': true, 'fetchPositionMode': false, 'fetchPremiumIndexOHLCV': false, 'fetchTicker': true, 'fetchTickers': true, 'fetchTrades': true, 'fetchTradingFee': true, 'fetchTradingFees': true, 'fetchTransactions': 'emulated', 'fetchTransfer': false, 'fetchTransfers': false, 'fetchWithdrawals': true, 'transfer': false, 'withdraw': true, }, 'urls': { 'logo': 'https://user-images.githubusercontent.com/1294454/27766869-75057fa2-5ee9-11e7-9a6f-13e641fa4707.jpg', 'api': { 'rest': 'https://api.therocktrading.com', }, 'www': 'https://therocktrading.com', 'doc': [ 'https://api.therocktrading.com/doc/v1/index.html', 'https://api.therocktrading.com/doc/', ], }, 'api': { 'public': { 'get': { 'funds': 1, 'funds/{id}': 1, 'funds/{id}/orderbook': 1, 'funds/{id}/ticker': 1, 'funds/{id}/trades': 1, 'funds/{id}/ohlc_statistics': 1, 'funds/tickers': 1, }, }, 'private': { 'get': { 'balances': 1, 'balances/{id}': 1, 'discounts': 1, 'discounts/{id}': 1, 'funds': 1, 'funds/{id}': 1, 'funds/{id}/trades': 1, 'funds/{fund_id}/orders': 1, 'funds/{fund_id}/orders/{id}': 1, 'funds/{fund_id}/position_balances': 1, 'funds/{fund_id}/positions': 1, 'funds/{fund_id}/positions/{id}': 1, 'transactions': 1, 'transactions/{id}': 1, 'withdraw_limits/{id}': 1, 'withdraw_limits': 1, }, 'post': { 'atms/withdraw': 1, 'funds/{fund_id}/orders': 1, }, 'delete': { 'funds/{fund_id}/orders/{id}': 1, 'funds/{fund_id}/orders/remove_all': 1, }, }, }, 'fees': { 'trading': { 'maker': this.parseNumber ('0.002'), 'taker': this.parseNumber ('0.002'), }, 'funding': { 'tierBased': false, 'percentage': false, 'withdraw': {}, 'deposit': { 'BTC': 0, 'BCH': 0, 'PPC': 0, 'ETH': 0, 'ZEC': 0, 'LTC': 0, 'EUR': 0, }, }, }, 'precisionMode': TICK_SIZE, 'exceptions': { 'exact': { 'Request already running': BadRequest, 'cannot specify multiple address types': BadRequest, 'Currency is not included in the list': BadRequest, 'Record not found': OrderNotFound, }, 'broad': { 'before must be greater than after param': BadRequest, 'must be shorter than 60 days': BadRequest, 'must be a multiple of (period param) in minutes': BadRequest, 'Address allocation limit reached for currency': InvalidAddress, 'is not a valid value for param currency': BadRequest, ' is invalid': InvalidAddress, }, }, 'options': { 'withdraw': { 'fillResponseFromRequest': true, }, }, }); } async fetchMarkets (params = {}) { /** * @method * @name therock#fetchMarkets * @description retrieves data on all markets for therock * @param {object} params extra parameters specific to the exchange api endpoint * @returns {[object]} an array of objects representing market data */ const response = await this.publicGetFunds (params); // // { // funds: [ // { // id: "BTCEUR", // description: "Trade Bitcoin with Euro", // type: "currency", // base_currency: "EUR", // trade_currency: "BTC", // buy_fee: 0.2, // sell_fee: 0.2, // minimum_price_offer: 0.01, // minimum_quantity_offer: 0.0005, // base_currency_decimals: 2, // trade_currency_decimals: 4, // leverages: [] // }, // ... // ] // } // const markets = this.safeValue (response, 'funds'); const result = []; if (markets === undefined) { throw new ExchangeError (this.id + ' fetchMarkets() got an unexpected response'); } else { for (let i = 0; i < markets.length; i++) { const market = markets[i]; const id = this.safeString (market, 'id'); const baseId = this.safeString (market, 'trade_currency'); const quoteId = this.safeString (market, 'base_currency'); const base = this.safeCurrencyCode (baseId); const quote = this.safeCurrencyCode (quoteId); const buy_fee = this.safeString (market, 'buy_fee'); const sell_fee = this.safeString (market, 'sell_fee'); let taker = Precise.stringMax (buy_fee, sell_fee); taker = this.parseNumber (Precise.stringDiv (taker, '100')); const leverages = this.safeValue (market, 'leverages'); const leveragesLength = leverages.length; result.push ({ 'id': id, 'symbol': base + '/' + quote, 'base': base, 'quote': quote, 'settle': undefined, 'baseId': baseId, 'quoteId': quoteId, 'settleId': undefined, 'type': 'spot', 'spot': true, 'margin': leveragesLength > 0, 'swap': false, 'future': false, 'option': false, 'contract': false, 'linear': undefined, 'inverse': undefined, 'taker': taker, 'maker': taker, 'contractSize': undefined, 'active': true, 'expiry': undefined, 'expiryDatetime': undefined, 'strike': undefined, 'optionType': undefined, 'precision': { 'amount': this.parseNumber (this.parsePrecision (this.safeString (market, 'trade_currency_decimals'))), 'price': this.parseNumber (this.parsePrecision (this.safeString (market, 'base_currency_decimals'))), }, 'limits': { 'leverage': { 'min': 1, 'max': this.safeValue (leverages, leveragesLength - 1, 1), }, 'amount': { 'min': this.safeNumber (market, 'minimum_quantity_offer'), 'max': undefined, }, 'price': { 'min': this.safeNumber (market, 'minimum_price_offer'), 'max': undefined, }, 'cost': { 'min': undefined, 'max': undefined, }, }, 'info': market, }); } } return result; } parseBalance (response) { const balances = this.safeValue (response, 'balances', []); const result = { 'info': response }; for (let i = 0; i < balances.length; i++) { const balance = balances[i]; const currencyId = this.safeString (balance, 'currency'); const code = this.safeCurrencyCode (currencyId); const account = this.account (); account['free'] = this.safeString (balance, 'trading_balance'); account['total'] = this.safeString (balance, 'balance'); result[code] = account; } return this.safeBalance (result); } async fetchBalance (params = {}) { /** * @method * @name therock#fetchBalance * @description query for balance and get the amount of funds available for trading or funds locked in orders * @param {object} params extra parameters specific to the therock api endpoint * @returns {object} a [balance structure]{@link https://docs.ccxt.com/en/latest/manual.html?#balance-structure} */ await this.loadMarkets (); const response = await this.privateGetBalances (params); return this.parseBalance (response); } async fetchOrderBook (symbol, limit = undefined, params = {}) { /** * @method * @name therock#fetchOrderBook * @description fetches information on open orders with bid (buy) and ask (sell) prices, volumes and other data * @param {string} symbol unified symbol of the market to fetch the order book for * @param {int|undefined} limit the maximum amount of order book entries to return * @param {object} params extra parameters specific to the therock api endpoint * @returns {object} A dictionary of [order book structures]{@link https://docs.ccxt.com/en/latest/manual.html#order-book-structure} indexed by market symbols */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'id': market['id'], }; const orderbook = await this.publicGetFundsIdOrderbook (this.extend (request, params)); const timestamp = this.parse8601 (this.safeString (orderbook, 'date')); return this.parseOrderBook (orderbook, market['symbol'], timestamp, 'bids', 'asks', 'price', 'amount'); } parseTicker (ticker, market = undefined) { // // { // "date":"2022-01-16T00:05:08.192Z", // "fund_id":"ETHBTC", // "bid":0.07707802, // "ask":0.07733404, // "last":0.07739053, // "open":0.07628192, // "close":0.07687651, // "low":0.07612047, // "high":0.07703306, // "volume":1.10179665, // "volume_traded":14.273 // } // const timestamp = this.parse8601 (this.safeString (ticker, 'date')); market = this.safeMarket (undefined, market); const last = this.safeString (ticker, 'last'); return this.safeTicker ({ 'symbol': market['symbol'], 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'high': this.safeString (ticker, 'high'), 'low': this.safeString (ticker, 'low'), 'bid': this.safeString (ticker, 'bid'), 'bidVolume': undefined, 'ask': this.safeString (ticker, 'ask'), 'askVolume': undefined, 'vwap': undefined, 'open': this.safeString (ticker, 'open'), 'close': last, 'last': last, 'previousClose': this.safeString (ticker, 'close'), // previous day close, if any 'change': undefined, 'percentage': undefined, 'average': undefined, 'baseVolume': this.safeString (ticker, 'volume_traded'), 'quoteVolume': this.safeString (ticker, 'volume'), 'info': ticker, }, market); } async fetchTickers (symbols = undefined, params = {}) { /** * @method * @name therock#fetchTickers * @description fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market * @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 therock api endpoint * @returns {object} an array of [ticker structures]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); symbols = this.marketSymbols (symbols); const response = await this.publicGetFundsTickers (params); const tickers = this.indexBy (response['tickers'], 'fund_id'); const ids = Object.keys (tickers); const result = {}; for (let i = 0; i < ids.length; i++) { const id = ids[i]; const market = this.safeMarket (id); const symbol = market['symbol']; const ticker = tickers[id]; result[symbol] = this.parseTicker (ticker, market); } return this.filterByArray (result, 'symbol', symbols); } async fetchTicker (symbol, params = {}) { /** * @method * @name therock#fetchTicker * @description fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market * @param {string} symbol unified symbol of the market to fetch the ticker for * @param {object} params extra parameters specific to the therock api endpoint * @returns {object} a [ticker structure]{@link https://docs.ccxt.com/en/latest/manual.html#ticker-structure} */ await this.loadMarkets (); const market = this.market (symbol); const request = { 'id': market['id'], }; const response = await this.publicGetFundsIdTicker (this.extend (request, params)); // // { // "date":"2022-01-16T00:05:08.192Z", // "fund_id":"ETHBTC", // "bid":0.07707802, // "ask":0.07733404, // "last":0.07739053, // "open":0.07628192, // "close":0.07687651, // "low":0.07612047, // "high":0.07703306, // "volume":1.10179665, // "volume_traded":14.273 // } // return this.parseTicker (response, market); } parseTrade (trade, market = undefined) { // // fetchTrades, fetchOrder trades // // { id: 4493548, // fund_id: "ETHBTC", // amount: 0.203, // price: 0.02783576, // side: "buy", // dark: false, // date: "2018-11-30T08:19:18.236Z" } // // fetchMyTrades // // { id: 237338, // fund_id: "BTCEUR", // amount: 0.348, // price: 348, // side: "sell", // dark: false, // order_id: 14920648, // date: "2015-06-03T00:49:49.000Z", // transactions: [ { id: 2770768, // date: "2015-06-03T00:49:49.000Z", // type: "sold_currency_to_fund", // price: 121.1, // currency: "EUR" }, // { id: 2770769, // date: "2015-06-03T00:49:49.000Z", // type: "released_currency_to_fund", // price: 0.348, // currency: "BTC" }, // { id: 2770772, // date: "2015-06-03T00:49:49.000Z", // type: "paid_commission", // price: 0.06, // currency: "EUR", // trade_id: 440492 } ] } // const marketId = this.safeString (trade, 'fund_id'); const symbol = this.safeSymbol (marketId, market); const timestamp = this.parse8601 (this.safeString (trade, 'date')); const id = this.safeString (trade, 'id'); const orderId = this.safeString (trade, 'order_id'); const side = this.safeString (trade, 'side'); const priceString = this.safeString (trade, 'price'); const amountString = this.safeString (trade, 'amount'); let fee = undefined; let feeCostString = undefined; const transactions = this.safeValue (trade, 'transactions', []); const transactionsByType = this.groupBy (transactions, 'type'); const feeTransactions = this.safeValue (transactionsByType, 'paid_commission', []); for (let i = 0; i < feeTransactions.length; i++) { if (feeCostString === undefined) { feeCostString = '0.0'; } feeCostString = Precise.stringAdd (feeCostString, this.safeString (feeTransactions[i], 'price')); } if (feeCostString !== undefined) { fee = { 'cost': feeCostString, 'currency': market['quote'], }; } return this.safeTrade ({ 'info': trade, 'id': id, 'order': orderId, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'symbol': symbol, 'type': undefined, 'side': side, 'takerOrMaker': undefined, 'price': priceString, 'amount': amountString, 'cost': undefined, 'fee': fee, }, market); } parseLedgerEntryDirection (direction) { const directions = { 'affiliate_earnings': 'in', 'atm_payment': 'in', 'bought_currency_from_fund': 'out', 'bought_shares': 'out', 'paid_commission': 'out', 'paypal_payment': 'in', 'pos_payment': 'in', 'released_currency_to_fund': 'out', 'rollover_commission': 'out', 'sold_currency_to_fund': 'in', 'sold_shares': 'in', 'transfer_received': 'in', 'transfer_sent': 'out', 'withdraw': 'out', // commented types will be shown as-is // 'acquired_currency_from_fund': '', // 'acquired_insurance': '', // 'dividend_distributed_to_holders': '', // 'dividend_from_shares': '', // 'exposed_position': '', // 'insurances_reimbursement': '', // 'lent_currency': '', // 'linden_lab_assessment': '', // 'position_transfer_received': '', // 'return_lent_currency': '', // 'returned_lent_currency': '', // 'the_rock_assessment': '', }; return this.safeString (directions, direction, direction); } parseLedgerEntryType (type) { const types = { 'affiliate_earnings': 'referral', 'atm_payment': 'transaction', 'bought_currency_from_fund': 'trade', 'bought_shares': 'trade', 'paid_commission': 'fee', 'paypal_payment': 'transaction', 'pos_payment': 'transaction', 'released_currency_to_fund': 'trade', 'rollover_commission': 'fee', 'sold_currency_to_fund': 'trade', 'sold_shares': 'trade', 'transfer_received': 'transfer', 'transfer_sent': 'transfer', 'withdraw': 'transaction', // commented types will be shown as-is // 'acquired_currency_from_fund': '', // 'acquired_insurance': '', // 'dividend_distributed_to_holders': '', // 'dividend_from_shares': '', // 'exposed_position': '', // 'insurances_reimbursement': '', // 'lent_currency': '', // 'linden_lab_assessment': '', // 'position_transfer_received': '', // 'return_lent_currency': '', // 'returned_lent_currency': '', // 'the_rock_assessment': '', }; return this.safeString (types, type, type); } parseLedgerEntry (item, currency = undefined) { // // withdrawal // // { // "id": 21311223, // "date": "2015-06-30T13:55:11.000Z", // "type": "withdraw", // "price": 103.00, // "currency": "EUR", // "fund_id": null, // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "wire_transfer", // "id": "F112DD3", // "recipient": "IT123456789012", // "confirmations": 0 // } // } // // deposit // // { // "id": 21311222, // "date": "2015-06-30T13:55:11.000Z", // "type": "atm_payment", // "price": 2.01291, // "currency": "BTC", // "fund_id": "null", // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "bitcoin", // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf", // "confirmations": 3 // } // } // // trade fee // // { // "id": 21311221, // "date": "2015-06-30T13:55:11.000Z", // "type": "paid_commission", // "price": 0.0001, // "fund_id": "BTCEUR", // "order_id": 12832371, // "trade_id": 12923212, // "currency": "BTC", // "transfer_detail": null // } // const id = this.safeString (item, 'id'); let referenceId = undefined; let type = this.safeString (item, 'type'); const direction = this.parseLedgerEntryDirection (type); type = this.parseLedgerEntryType (type); if (type === 'trade' || type === 'fee') { referenceId = this.safeString (item, 'trade_id'); } const currencyId = this.safeString (item, 'currency'); const code = this.safeCurrencyCode (currencyId); const amount = this.safeNumber (item, 'price'); const timestamp = this.parse8601 (this.safeString (item, 'date')); const status = 'ok'; return { 'info': item, 'id': id, 'direction': direction, 'account': undefined, 'referenceId': referenceId, 'referenceAccount': undefined, 'type': type, 'currency': code, 'amount': amount, 'before': undefined, 'after': undefined, 'status': status, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'fee': undefined, }; } async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name therock#fetchLedger * @description fetch the history of changes, actions done by the user or operations that altered balance of the user * @param {string|undefined} code unified currency code, default is undefined * @param {int|undefined} since timestamp in ms of the earliest ledger entry, default is undefined * @param {int|undefined} limit max number of ledger entrys to return, default is undefined * @param {object} params extra parameters specific to the therock api endpoint * @returns {object} a [ledger structure]{@link https://docs.ccxt.com/en/latest/manual.html#ledger-structure} */ await this.loadMarkets (); const request = { // 'page': 1, // 'fund_id': 'ETHBTC', // filter by fund symbol // 'currency': 'BTC', // filter by currency // 'after': '2015-02-06T08:47:26Z', // filter after a certain timestamp // 'before': '2015-02-06T08:47:26Z', // 'type': 'withdraw', // 'order_id': '12832371', // filter by a specific order ID // 'trade_id': '12923212', // filter by a specific trade ID // 'transfer_method': 'bitcoin', // wire_transfer, ripple, greenaddress, bitcoin, litecoin, namecoin, peercoin, dogecoin // 'transfer_recipient': '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm', // filter by a specific recipient (e.g. Bitcoin address, IBAN) // 'transfer_id': '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa', // filter by a specific transfer ID (e.g. Bitcoin TX hash) }; let currency = undefined; if (code !== undefined) { currency = this.currency (code); request['currency'] = currency['id']; } if (since !== undefined) { request['after'] = this.iso8601 (since); } const response = await this.privateGetTransactions (this.extend (request, params)); // // { // "transactions": [ // { // "id": 21311223, // "date": "2015-06-30T13:55:11.000Z", // "type": "withdraw", // "price": 103.00, // "currency": "EUR", // "fund_id": null, // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "wire_transfer", // "id": "F112DD3", // "recipient": "IT123456789012", // "confirmations": 0 // } // }, // { // "id": 21311222, // "date": "2015-06-30T13:55:11.000Z", // "type": "atm_payment", // "price": 2.01291, // "currency": "BTC", // "fund_id": "null", // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "bitcoin", // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf", // "confirmations": 3 // } // }, // { // "id": 21311221, // "date": "2015-06-30T13:55:11.000Z", // "type": "paid_commission", // "price": 0.0001, // "fund_id": "BTCEUR", // "order_id": 12832371, // "trade_id": 12923212, // "currency": "BTC", // "transfer_detail": null // } // ], // "meta": { // "total_count": 1221, // "first": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" }, // "previous": null, // "current": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" }, // "next": { "page": 2, "href": "https://api.therocktrading.com/v1/transactions?page=2" }, // "last": { "page": 1221, "href": "https://api.therocktrading.com/v1/transactions?page=1221" } // } // } // const transactions = this.safeValue (response, 'transactions', []); return this.parseLedger (transactions, currency, since, limit); } parseTransactionType (type) { const types = { 'withdraw': 'withdrawal', 'atm_payment': 'deposit', }; return this.safeString (types, type, type); } parseTransaction (transaction, currency = undefined) { // // fetchWithdrawals // // // fiat // // { // "id": 21311223, // "date": "2015-06-30T13:55:11.000Z", // "type": "withdraw", // "price": 103.00, // "currency": "EUR", // "fund_id": null, // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "wire_transfer", // "id": "F112DD3", // "recipient": "IT123456789012", // "confirmations": 0 // } // } // // { // "id": 12564223, // "date": "2017-08-07T08:13:50.023Z", // "note": "GB7IDL401573388", // "type": "withdraw", // "price": 4345.93, // "fund_id": null, // "currency": "EUR", // "order_id": null, // "trade_id": null, // "transfer_detail": { // "id": "EXECUTEDBUTUNCHECKED", // "method": "wire_transfer", // "recipient": "GB7IDL401573388", // "confirmations": 0 // } // } // // // crypto // // { // id: 20914695, // date: '2018-02-24T07:13:23.002Z', // type: 'withdraw', // price: 2.70883607, // currency: 'BCH', // fund_id: null, // order_id: null, // trade_id: null, // note: '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm', // transfer_detail: { // method: 'bitcoin_cash', // id: '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa', // recipient: '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm', // confirmations: 0 // } // } // // // fetchDeposits // // // fiat // // { // id: 16176632, // date: '2017-11-20T21:00:13.355Z', // type: 'atm_payment', // price: 5000, // currency: 'EUR', // fund_id: null, // order_id: null, // trade_id: null, // note: 'Mistral deposit', // transfer_detail: { // method: 'wire_transfer', // id: '972JQ49337DX769T', // recipient: null, // confirmations: 0 // } // } // // // crypto // // { // "id": 21311222, // "date": "2015-06-30T13:55:11.000Z", // "type": "atm_payment", // "price": 2.01291, // "currency": "BTC", // "fund_id": "null", // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "bitcoin", // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf", // "confirmations": 3 // } // } // // privatePostAtmsWithdraw // { "transaction_id": 65088485 } // const id = this.safeString2 (transaction, 'id', 'transaction_id'); const type = this.parseTransactionType (this.safeString (transaction, 'type')); const detail = this.safeValue (transaction, 'transfer_detail', {}); const method = this.safeString (detail, 'method'); let txid = undefined; let address = undefined; if (method !== undefined) { if (method !== 'wire_transfer') { txid = this.safeString (detail, 'id'); address = this.safeString (detail, 'recipient'); } } const currencyId = this.safeString (transaction, 'currency'); const code = this.safeCurrencyCode (currencyId); const amount = this.safeNumber (transaction, 'price'); const timestamp = this.parse8601 (this.safeString (transaction, 'date')); const status = 'ok'; const network = this.safeString (detail, 'method'); // todo parse tags return { 'info': transaction, 'id': id, 'currency': code, 'amount': amount, 'network': network, 'addressFrom': undefined, 'addressTo': address, 'address': address, 'tagFrom': undefined, 'tagTo': undefined, 'tag': undefined, 'status': status, 'type': type, 'updated': undefined, 'txid': txid, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'fee': undefined, }; } async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name therock#fetchWithdrawals * @description fetch all withdrawals made from an account * @param {string|undefined} code unified currency code * @param {int|undefined} since the earliest time in ms to fetch withdrawals for * @param {int|undefined} limit the maximum number of withdrawals structures to retrieve * @param {object} params extra parameters specific to the therock api endpoint * @returns {[object]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure} */ const request = { 'type': 'withdraw', }; return await this.fetchTransactions (code, since, limit, this.extend (request, params)); } async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name therock#fetchDeposits * @description fetch all deposits made to an account * @param {string|undefined} code unified currency code * @param {int|undefined} since the earliest time in ms to fetch deposits for * @param {int|undefined} limit the maximum number of deposits structures to retrieve * @param {object} params extra parameters specific to the therock api endpoint * @returns {[object]} a list of [transaction structures]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure} */ const request = { 'type': 'atm_payment', }; return await this.fetchTransactions (code, since, limit, this.extend (request, params)); } async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) { /** * @method * @name therock#fetchTransactions * @description fetch history of deposits and withdrawals * @param {string|undefined} code unified currency code for the currency of the transactions, default is undefined * @param {int|undefined} since timestamp in ms of the earliest transaction, default is undefined * @param {int|undefined} limit max number of transactions to return, default is undefined * @param {object} params extra parameters specific to the therock api endpoint * @returns {object} a list of [transaction structure]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure} */ await this.loadMarkets (); const request = { // 'page': 1, // 'fund_id': 'ETHBTC', // filter by fund symbol // 'currency': 'BTC', // filter by currency // 'after': '2015-02-06T08:47:26Z', // filter after a certain timestamp // 'before': '2015-02-06T08:47:26Z', // 'type': 'withdraw', // 'order_id': '12832371', // filter by a specific order ID // 'trade_id': '12923212', // filter by a specific trade ID // 'transfer_method': 'bitcoin', // wire_transfer, ripple, greenaddress, bitcoin, litecoin, namecoin, peercoin, dogecoin // 'transfer_recipient': '1MAHLhJoz9W2ydbRf972WSgJYJ3Ui7aotm', // filter by a specific recipient (e.g. Bitcoin address, IBAN) // 'transfer_id': '8261949194985b01985006724dca5d6059989e096fa95608271d00dd902327fa', // filter by a specific transfer ID (e.g. Bitcoin TX hash) }; let currency = undefined; if (code !== undefined) { currency = this.currency (code); request['currency'] = currency['id']; } if (since !== undefined) { request['after'] = this.iso8601 (since); } params = this.extend (request, params); const response = await this.privateGetTransactions (params); // // { // "transactions": [ // { // "id": 21311223, // "date": "2015-06-30T13:55:11.000Z", // "type": "withdraw", // "price": 103.00, // "currency": "EUR", // "fund_id": null, // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "wire_transfer", // "id": "F112DD3", // "recipient": "IT123456789012", // "confirmations": 0 // } // }, // { // "id": 21311222, // "date": "2015-06-30T13:55:11.000Z", // "type": "atm_payment", // "price": 2.01291, // "currency": "BTC", // "fund_id": "null", // "order_id": null, // "trade_id": null, // "transfer_detail": { // "method": "bitcoin", // "id": "0e3e2357e806b6cdb1f70b54c3a3a17b6714ee1f0e68bebb44a74b1efd512098", // "recipient": "mzb3NgX9Dr6jgGAu31L6jsPGB2zkaFxxyf", // "confirmations": 3 // } // }, // { // "id": 21311221, // "date": "2015-06-30T13:55:11.000Z", // "type": "paid_commission", // "price": 0.0001, // "fund_id": "BTCEUR", // "order_id": 12832371, // "trade_id": 12923212, // "currency": "BTC", // "transfer_detail": null // } // ], // "meta": { // "total_count": 1221, // "first": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" }, // "previous": null, // "current": { "page": 1, "href": "https://api.therocktrading.com/v1/transactions?page=1" }, // "next": { "page": 2, "href": "https://api.therocktrading.com/v1/transactions?page=2" }, // "last": { "page": 1221, "href": "https://api.therocktrading.com/v1/transactions?page=1221" } // } // } // const transactions = this.safeValue (response, 'transactions', []); const transactionTypes = [ 'withdraw', 'atm_payment' ]; const depositsAndWithdrawals = this.filterByArray (transactions, 'type', transactionTypes, false); return this.parseTransactions (depositsAndWithdrawals, currency, since, limit); } async withdraw (code, amount, address, tag = undefined, params = {}) { /** * @method * @name therock#withdraw * @description make a withdrawal * @param {string} code unified currency code * @param {float} amount the amount to withdraw * @param {string} address the address to withdraw to * @param {string|undefined} tag * @param {object} params extra parameters specific to the therock api endpoint * @returns {object} a [transaction structure]{@link https://docs.ccxt.com/en/latest/manual.html#transaction-structure} */ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params); await this.loadMarkets (); const currency = this.currency (code); amount = this.currencyToPrecision (code, amount); const request = { 'currency': currency['id'], 'destination_address': address, 'amount': parseFloat (amount), }; if (tag !== undefined) { request['destination_tag'] = tag; } // requires write permission on the wallet const response = await this.privatePostAtmsWithdraw (this.extend (request, params)); // // { "transaction_id": 65088485 } // const transaction = this.parseTransaction (response, currency); const withdrawOptions = this.safeValue (this.options, 'withdraw', {}); const fillResponseFromRequest = this.safeValue (withdrawOptions, 'fillResponseFromRequest', true); if (fillResponseFromRequest) { if (transaction['addressTo'] === address) { transaction['addressTo'] = address; } if (transaction['address'] === undefined) { transaction['address'] = address; } if (transaction['tagTo'] === undefined) { transaction['tagTo'] = tag; } if (transaction['tag'] === undefined) { transaction['tag'] = tag; } if (transaction['amount'] === undefined) { transaction['amount'] = amount; } } return transaction; } parseOrderStatus (status) { const statuses = { 'active': 'open', 'executed': 'closed', 'deleted': 'canceled', // don't know what this status means // 'conditional': '?', }; return this.safeString (statuses, status, status); } parseOrder (order, market = undefined) { // // { // "id": 4325578, // "fund_id":"BTCEUR", // "side":"buy", // "type":"limit", // "status":"executed", // "price":0.0102, // "amount": 50.0, // "amount_unfilled": 0.0, // "conditional_type": null, // "conditional_price": null, // "date":"2015-06-03T00:49:48.000Z", // "close_on": nil, // "leverage": 1.0, // "position_id": null, // "trades": [ // { // "id":237338, // "fund_id":"BTCEUR", // "amount":50, // "price":0.0102, // "side":"buy", // "dark":false, // "date":"2015-06-03T00:49:49.000Z" // } // ] // } // const id = this.safeString (order, 'id'); const marketId = this.safeString (order, 'fund_id'); const symbol = this.safeSymbol (marketId, market); const status = this.parseOrderStatus (this.safeString (order, 'status')); const timestamp = this.parse8601 (this.safeString (order, 'date')); const type = this.safeString (order, 'type'); const side = this.safeString (order, 'side'); const amount = this.safeNumber (order, 'amount'); const remaining = this.safeNumber (order, 'amount_unfilled'); let filled = undefined; if (amount !== undefined) { if (remaining !== undefined) { filled = amount - remaining; } } const price = this.safeNumber (order, 'price'); let trades = this.safeValue (order, 'trades'); let cost = undefined; let average = undefined; let lastTradeTimestamp = undefined; if (trades !== undefined) { const numTrades = trades.length; if (numTrades > 0) { trades = this.parseTrades (trades, market, undefined, undefined, { 'orderId': id, }); // todo: determine the cost and the average price from trades cost = 0; filled = 0; for (let i = 0; i < numTrades; i++) { const trade = trades[i]; cost = this.sum (cost, trade['cost']); filled = this.sum (filled, trade['amount']); } if (filled > 0) { average = cost / filled; } lastTradeTimestamp = trades[numTrades - 1]['timestamp']; } else { cost = 0; } } const stopPrice = this.safeNumber (order, 'conditional_price'); return { 'id': id, 'clientOrderId': undefined, 'info': order, 'timestamp': timestamp, 'datetime': this.iso8601 (timestamp), 'lastTradeTimestamp': lastTradeTimestamp, 'statu