Snapshots

This commit is contained in:
Luis Fernando Molina committed 2020-05-10 14:17:33 +02:00
1 parent e91125801d
commit 6368221937
75 files changed
+8943 -4332

No files matched your search

+393 -44
View File
@@ -3,7 +3,7 @@
// ---------------------------------------------------------------------------
const Exchange = require ('./base/Exchange');
const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress } = require ('./base/errors');
const { ExchangeError, ExchangeNotAvailable, AuthenticationError, BadRequest, PermissionDenied, InvalidAddress, ArgumentsRequired, InvalidOrder } = require ('./base/errors');
// ---------------------------------------------------------------------------
@@ -16,7 +16,12 @@ module.exports = class bithumb extends Exchange {
'rateLimit': 500,
'has': {
'CORS': true,
'createOrder': true,
'cancelOrder': true,
'createMarketOrder': true,
'fetchTickers': true,
'fetchOpenOrders': true,
'fetchOrder': true,
'withdraw': true,
},
'urls': {
@@ -48,8 +53,8 @@ module.exports = class bithumb extends Exchange {
'info/ticker',
'info/orders',
'info/user_transactions',
'trade/place',
'info/order_detail',
'trade/place',
'trade/cancel',
'trade/btc_withdrawal',
'trade/krw_deposit',
@@ -165,15 +170,53 @@ module.exports = class bithumb extends Exchange {
'currency': market['base'],
};
if (limit !== undefined) {
request['count'] = limit; // max = 50
request['count'] = limit; // default 30, max 30
}
const response = await this.publicGetOrderbookCurrency (this.extend (request, params));
const orderbook = this.safeValue (response, 'data');
const timestamp = this.safeInteger (orderbook, 'timestamp');
return this.parseOrderBook (orderbook, timestamp, 'bids', 'asks', 'price', 'quantity');
//
// {
// "status":"0000",
// "data":{
// "timestamp":"1587621553942",
// "payment_currency":"KRW",
// "order_currency":"BTC",
// "bids":[
// {"price":"8652000","quantity":"0.0043"},
// {"price":"8651000","quantity":"0.0049"},
// {"price":"8650000","quantity":"8.4791"},
// ],
// "asks":[
// {"price":"8654000","quantity":"0.119"},
// {"price":"8655000","quantity":"0.254"},
// {"price":"8658000","quantity":"0.119"},
// ]
// }
// }
//
const data = this.safeValue (response, 'data', {});
const timestamp = this.safeInteger (data, 'timestamp');
return this.parseOrderBook (data, timestamp, 'bids', 'asks', 'price', 'quantity');
}
parseTicker (ticker, market = undefined) {
//
// fetchTicker, fetchTickers
//
// {
// "opening_price":"227100",
// "closing_price":"228400",
// "min_price":"222300",
// "max_price":"230000",
// "units_traded":"82618.56075337",
// "acc_trade_value":"18767376138.6031",
// "prev_closing_price":"227100",
// "units_traded_24H":"151871.13484676",
// "acc_trade_value_24H":"34247610416.8974",
// "fluctate_24H":"8700",
// "fluctate_rate_24H":"3.96",
// "date":"1587710327264", // fetchTickers inject this
// }
//
const timestamp = this.safeInteger (ticker, 'date');
let symbol = undefined;
if (market !== undefined) {
@@ -224,9 +267,31 @@ module.exports = class bithumb extends Exchange {
async fetchTickers (symbols = undefined, params = {}) {
await this.loadMarkets ();
const response = await this.publicGetTickerAll (params);
//
// {
// "status":"0000",
// "data":{
// "BTC":{
// "opening_price":"9045000",
// "closing_price":"9132000",
// "min_price":"8938000",
// "max_price":"9168000",
// "units_traded":"4619.79967497",
// "acc_trade_value":"42021363832.5187",
// "prev_closing_price":"9041000",
// "units_traded_24H":"8793.5045804",
// "acc_trade_value_24H":"78933458515.4962",
// "fluctate_24H":"530000",
// "fluctate_rate_24H":"6.16"
// },
// "date":"1587710878669"
// }
// }
//
const result = {};
const timestamp = this.safeInteger (response['data'], 'date');
const tickers = this.omit (response['data'], 'date');
const data = this.safeValue (response, 'data', {});
const timestamp = this.safeInteger (data, 'date');
const tickers = this.omit (data, 'date');
const ids = Object.keys (tickers);
for (let i = 0; i < ids.length; i++) {
const id = ids[i];
@@ -253,19 +318,72 @@ module.exports = class bithumb extends Exchange {
'currency': market['base'],
};
const response = await this.publicGetTickerCurrency (this.extend (request, params));
return this.parseTicker (response['data'], market);
//
// {
// "status":"0000",
// "data":{
// "opening_price":"227100",
// "closing_price":"228400",
// "min_price":"222300",
// "max_price":"230000",
// "units_traded":"82618.56075337",
// "acc_trade_value":"18767376138.6031",
// "prev_closing_price":"227100",
// "units_traded_24H":"151871.13484676",
// "acc_trade_value_24H":"34247610416.8974",
// "fluctate_24H":"8700",
// "fluctate_rate_24H":"3.96",
// "date":"1587710327264"
// }
// }
//
const data = this.safeValue (response, 'data', {});
return this.parseTicker (data, market);
}
parseTrade (trade, market = undefined) {
//
// fetchTrades (public)
//
// {
// "transaction_date":"2020-04-23 22:21:46",
// "type":"ask",
// "units_traded":"0.0125",
// "price":"8667000",
// "total":"108337"
// }
//
// fetchOrder (private)
//
// {
// "transaction_date": "1572497603902030",
// "price": "8601000",
// "units": "0.005",
// "fee_currency": "KRW",
// "fee": "107.51",
// "total": "43005"
// }
//
// a workaround for their bug in date format, hours are not 0-padded
const parts = trade['transaction_date'].split (' ');
const transaction_date = parts[0];
let transaction_time = parts[1];
if (transaction_time.length < 8) {
transaction_time = '0' + transaction_time;
let timestamp = undefined;
const transactionDatetime = this.safeString (trade, 'transaction_date');
if (transactionDatetime !== undefined) {
const parts = transactionDatetime.split (' ');
const numParts = parts.length;
if (numParts > 1) {
const transactionDate = parts[0];
let transactionTime = parts[1];
if (transactionTime.length < 8) {
transactionTime = '0' + transactionTime;
}
timestamp = this.parse8601 (transactionDate + ' ' + transactionTime);
} else {
timestamp = this.safeIntegerProduct (trade, 'transaction_date', 0.001);
}
}
if (timestamp !== undefined) {
timestamp -= 9 * 3600000; // they report UTC + 9 hours, server in Korean timezone
}
let timestamp = this.parse8601 (transaction_date + ' ' + transaction_time);
timestamp -= 9 * 3600000; // they report UTC + 9 hours (server in Korean timezone)
const type = undefined;
let side = this.safeString (trade, 'type');
side = (side === 'ask') ? 'sell' : 'buy';
@@ -276,12 +394,24 @@ module.exports = class bithumb extends Exchange {
}
const price = this.safeFloat (trade, 'price');
const amount = this.safeFloat (trade, 'units_traded');
let cost = undefined;
if (amount !== undefined) {
if (price !== undefined) {
cost = price * amount;
let cost = this.safeFloat (trade, 'total');
if (cost === undefined) {
if (amount !== undefined) {
if (price !== undefined) {
cost = price * amount;
}
}
}
let fee = undefined;
const feeCost = this.safeFloat (trade, 'fee');
if (feeCost !== undefined) {
const feeCurrencyId = this.safeString (trade, 'fee_currency');
const feeCurrencyCode = this.commonCurrencyCode (feeCurrencyId);
fee = {
'cost': feeCost,
'currency': feeCurrencyCode,
};
}
return {
'id': id,
'info': trade,
@@ -295,7 +425,7 @@ module.exports = class bithumb extends Exchange {
'price': price,
'amount': amount,
'cost': cost,
'fee': undefined,
'fee': fee,
};
}
@@ -309,57 +439,276 @@ module.exports = class bithumb extends Exchange {
request['count'] = limit; // default 20, max 100
}
const response = await this.publicGetTransactionHistoryCurrency (this.extend (request, params));
return this.parseTrades (response['data'], market, since, limit);
//
// {
// "status":"0000",
// "data":[
// {
// "transaction_date":"2020-04-23 22:21:46",
// "type":"ask",
// "units_traded":"0.0125",
// "price":"8667000",
// "total":"108337"
// },
// ]
// }
//
const data = this.safeValue (response, 'data', []);
return this.parseTrades (data, market, since, limit);
}
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
await this.loadMarkets ();
const market = this.market (symbol);
let request = undefined;
let method = 'privatePostTrade';
const request = {
'order_currency': market['id'],
'Payment_currency': market['quote'],
'units': amount,
};
let method = 'privatePostTradePlace';
if (type === 'limit') {
request = {
'order_currency': market['id'],
'Payment_currency': market['quote'],
'units': amount,
'price': price,
'type': (side === 'buy') ? 'bid' : 'ask',
};
method += 'Place';
} else if (type === 'market') {
request = {
'currency': market['id'],
'units': amount,
};
method += 'Market' + this.capitalize (side);
request['price'] = price;
request['type'] = (side === 'buy') ? 'bid' : 'ask';
} else {
method = 'privatePostTradeMarket' + this.capitalize (side);
}
const response = await this[method] (this.extend (request, params));
const id = this.safeString (response, 'order_id');
if (id === undefined) {
throw new InvalidOrder (this.id + ' createOrder did not return an order id');
}
return {
'info': response,
'symbol': symbol,
'type': type,
'side': side,
'id': id,
};
}
async fetchOrder (id, symbol = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' fetchOrder requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
const request = {
'order_id': id,
'count': 1,
'order_currency': market['base'],
'payment_currency': market['quote'],
};
const response = await this.privatePostInfoOrderDetail (this.extend (request, params));
//
// {
// "status": "0000",
// "data": {
// "transaction_date": "1572497603668315",
// "type": "bid",
// "order_status": "Completed",
// "order_currency": "BTC",
// "payment_currency": "KRW",
// "order_price": "8601000",
// "order_qty": "0.007",
// "cancel_date": "",
// "cancel_type": "",
// "contract": [
// {
// "transaction_date": "1572497603902030",
// "price": "8601000",
// "units": "0.005",
// "fee_currency": "KRW",
// "fee": "107.51",
// "total": "43005"
// },
// ]
// }
// }
//
const data = this.safeValue (response, 'data');
return this.parseOrder (this.extend (data, { 'order_id': id }), market);
}
parseOrderStatus (status) {
const statuses = {
'Pending': 'open',
'Completed': 'closed',
'Cancel': 'canceled',
};
return this.safeString (statuses, status, status);
}
parseOrder (order, market = undefined) {
//
// fetchOrder
//
// {
// "transaction_date": "1572497603668315",
// "type": "bid",
// "order_status": "Completed",
// "order_currency": "BTC",
// "payment_currency": "KRW",
// "order_price": "8601000",
// "order_qty": "0.007",
// "cancel_date": "",
// "cancel_type": "",
// "contract": [
// {
// "transaction_date": "1572497603902030",
// "price": "8601000",
// "units": "0.005",
// "fee_currency": "KRW",
// "fee": "107.51",
// "total": "43005"
// },
// ]
// }
//
// fetchOpenOrders
//
// {
// "order_currency": "BTC",
// "payment_currency": "KRW",
// "order_id": "C0101000007408440032",
// "order_date": "1571728739360570",
// "type": "bid",
// "units": "5.0",
// "units_remaining": "5.0",
// "price": "501000",
// }
//
const timestamp = this.safeIntegerProduct (order, 'order_date', 0.001);
const sideProperty = this.safeValue2 (order, 'type', 'side');
const side = (sideProperty === 'bid') ? 'buy' : 'sell';
const status = this.parseOrderStatus (this.safeString (order, 'order_status'));
let price = this.safeFloat2 (order, 'order_price', 'price');
let type = 'limit';
if (price === 0) {
price = undefined;
type = 'market';
}
const amount = this.safeFloat2 (order, 'order_qty', 'units');
let remaining = this.safeFloat (order, 'units_remaining');
if (remaining === undefined) {
if (status === 'closed') {
remaining = 0;
} else {
remaining = amount;
}
}
let filled = undefined;
if ((amount !== undefined) && (remaining !== undefined)) {
filled = amount - remaining;
}
let symbol = undefined;
const baseId = this.safeString (order, 'order_currency');
const quoteId = this.safeString (order, 'payment_currency');
const base = this.safeCurrencyCode (baseId);
const quote = this.safeCurrencyCode (quoteId);
if ((base !== undefined) && (quote !== undefined)) {
symbol = base + '/' + quote;
}
if ((symbol === undefined) && (market !== undefined)) {
symbol = market['symbol'];
}
const rawTrades = this.safeValue (order, 'contract');
let trades = undefined;
const id = this.safeString (order, 'order_id');
if (rawTrades !== undefined) {
trades = this.parseTrades (rawTrades, market, undefined, undefined, {
'side': side,
'symbol': symbol,
'order': id,
});
}
return {
'info': order,
'id': id,
'timestamp': timestamp,
'datetime': this.iso8601 (timestamp),
'lastTradeTimestamp': undefined,
'symbol': symbol,
'type': type,
'side': side,
'price': price,
'amount': amount,
'cost': undefined,
'average': undefined,
'filled': filled,
'remaining': remaining,
'status': status,
'fee': undefined,
'trades': trades,
};
}
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' fetchOpenOrders requires a symbol argument');
}
await this.loadMarkets ();
const market = this.market (symbol);
if (limit === undefined) {
limit = 100;
}
const request = {
'count': limit,
'order_currency': market['base'],
'payment_currency': market['quote'],
};
if (since !== undefined) {
request['after'] = since;
}
const response = await this.privatePostInfoOrders (this.extend (request, params));
//
// {
// "status": "0000",
// "data": [
// {
// "order_currency": "BTC",
// "payment_currency": "KRW",
// "order_id": "C0101000007408440032",
// "order_date": "1571728739360570",
// "type": "bid",
// "units": "5.0",
// "units_remaining": "5.0",
// "price": "501000",
// }
// ]
// }
//
const data = this.safeValue (response, 'data', []);
return this.parseOrders (data, market, since, limit);
}
async cancelOrder (id, symbol = undefined, params = {}) {
const side_in_params = ('side' in params);
if (!side_in_params) {
throw new ExchangeError (this.id + ' cancelOrder requires a `side` parameter (sell or buy) and a `currency` parameter');
throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
}
const currency = this.safeString (params, 'currency');
if (currency === undefined) {
throw new ExchangeError (this.id + ' cancelOrder requires a `currency` parameter (a currency id)');
if (symbol === undefined) {
throw new ArgumentsRequired (this.id + ' cancelOrder requires a `symbol` argument and a `side` parameter (sell or buy)');
}
const market = this.market (symbol);
const side = (params['side'] === 'buy') ? 'bid' : 'ask';
params = this.omit (params, [ 'side', 'currency' ]);
// https://github.com/ccxt/ccxt/issues/6771
const request = {
'order_id': id,
'type': side,
'currency': currency,
'order_currency': market['base'],
'payment_currency': market['quote'],
};
return await this.privatePostTradeCancel (this.extend (request, params));
}
cancelUnifiedOrder (order, params = {}) {
const request = {
'side': order['side'],
};
return this.cancelOrder (order['id'], order['symbol'], this.extend (request, params));
}
async withdraw (code, amount, address, tag = undefined, params = {}) {
this.checkAddress (address);
await this.loadMarkets ();
@@ -372,7 +721,7 @@ module.exports = class bithumb extends Exchange {
if (currency === 'XRP' || currency === 'XMR') {
const destination = this.safeString (params, 'destination');
if ((tag === undefined) && (destination === undefined)) {
throw new ExchangeError (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
throw new ArgumentsRequired (this.id + ' ' + code + ' withdraw() requires a tag argument or an extra destination param');
} else if (tag !== undefined) {
request['destination'] = tag;
}