diff --git a/build/ccxt.browser.js b/build/ccxt.browser.js index f0608976f43d3..9a77a1b5a79eb 100644 --- a/build/ccxt.browser.js +++ b/build/ccxt.browser.js @@ -45,7 +45,7 @@ const Exchange = require ('./js/base/Exchange') //----------------------------------------------------------------------------- // this is updated by vss.js when building -const version = '1.17.385' +const version = '1.17.386' Exchange.ccxtVersion = version @@ -2420,8 +2420,8 @@ module.exports = class Exchange { return new Promise ((resolve, reject) => resolve (Object.values (this.markets))) } - async fetchOrderStatus (id, market = undefined) { - let order = await this.fetchOrder (id, market); + async fetchOrderStatus (id, symbol = undefined, params = {}) { + let order = await this.fetchOrder (id, symbol, params); return order['status']; } @@ -12303,7 +12303,7 @@ module.exports = class bitmarket extends Exchange { // --------------------------------------------------------------------------- const Exchange = require ('./base/Exchange'); -const { ExchangeError, DDoSProtection, OrderNotFound, AuthenticationError, PermissionDenied } = require ('./base/errors'); +const { ExchangeError, ExchangeNotAvailable, DDoSProtection, OrderNotFound, AuthenticationError, PermissionDenied } = require ('./base/errors'); // --------------------------------------------------------------------------- @@ -12431,8 +12431,13 @@ module.exports = class bitmex extends Exchange { }, }, 'exceptions': { - 'Invalid API Key.': AuthenticationError, - 'Access Denied': PermissionDenied, + 'exact': { + 'Invalid API Key.': AuthenticationError, + 'Access Denied': PermissionDenied, + }, + 'broad': { + 'overloaded': ExchangeNotAvailable, + }, }, 'options': { 'fetchTickerQuotes': false, @@ -12869,19 +12874,18 @@ module.exports = class bitmex extends Exchange { if (body) { if (body[0] === '{') { let response = JSON.parse (body); - if ('error' in response) { - if ('message' in response['error']) { - let feedback = this.id + ' ' + this.json (response); - let message = this.safeValue (response['error'], 'message'); - let exceptions = this.exceptions; - if (message !== undefined) { - if (message in exceptions) { - throw new exceptions[message] (feedback); - } - } - throw new ExchangeError (feedback); - } + const message = this.safeString (response, 'error'); + const feedback = this.id + ' ' + body; + const exact = this.exceptions['exact']; + if (code in exact) { + throw new exact[code] (feedback); } + const broad = this.exceptions['broad']; + const broadKey = this.findBroadlyMatchedKey (broad, message); + if (broadKey !== undefined) { + throw new broad[broadKey] (feedback); + } + throw new ExchangeError (feedback); // unknown message } } } @@ -14351,6 +14355,7 @@ module.exports = class bitstamp extends Exchange { 'In Queue': 'open', 'Open': 'open', 'Finished': 'closed', + 'Canceled': 'canceled', }; return (status in statuses) ? statuses[status] : status; } @@ -14910,17 +14915,20 @@ module.exports = class bitstamp1 extends Exchange { return await this.privatePostCancelOrder ({ 'id': id }); } - parseOrderStatus (order) { - if ((order['status'] === 'Queue') || (order['status'] === 'Open')) - return 'open'; - if (order['status'] === 'Finished') - return 'closed'; - return order['status']; + parseOrderStatus (status) { + let statuses = { + 'In Queue': 'open', + 'Open': 'open', + 'Finished': 'closed', + 'Canceled': 'canceled', + }; + return (status in statuses) ? statuses[status] : status; } - async fetchOrderStatus (id, symbol = undefined) { + async fetchOrderStatus (id, symbol = undefined, params = {}) { await this.loadMarkets (); - let response = await this.privatePostOrderStatus ({ 'id': id }); + let request = { 'id': id }; + let response = await this.privatePostOrderStatus (this.extend (request, params)); return this.parseOrderStatus (response); } @@ -50894,9 +50902,9 @@ module.exports = class poloniex extends Exchange { return response; } - async fetchOrderStatus (id, symbol = undefined) { + async fetchOrderStatus (id, symbol = undefined, params = {}) { await this.loadMarkets (); - let orders = await this.fetchOpenOrders (symbol); + let orders = await this.fetchOpenOrders (symbol, undefined, undefined, params); let indexed = this.indexBy (orders, 'id'); return (id in indexed) ? 'open' : 'closed'; } diff --git a/ccxt.js b/ccxt.js index 1a937a0024843..7a9b8cc57bb0c 100644 --- a/ccxt.js +++ b/ccxt.js @@ -37,7 +37,7 @@ const Exchange = require ('./js/base/Exchange') //----------------------------------------------------------------------------- // this is updated by vss.js when building -const version = '1.17.385' +const version = '1.17.386' Exchange.ccxtVersion = version diff --git a/package-lock.json b/package-lock.json index 9ae72245f4e03..5011112303742 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "ccxt", - "version": "1.17.385", + "version": "1.17.386", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index ba59d0610c9c8..477265ac4aec3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ccxt", - "version": "1.17.385", + "version": "1.17.386", "description": "A JavaScript / Python / PHP cryptocurrency trading library with support for 100+ exchanges", "main": "./ccxt.js", "unpkg": "build/ccxt.browser.js", diff --git a/php/Exchange.php b/php/Exchange.php index 8dbe1b083552c..49d335607c2ef 100644 --- a/php/Exchange.php +++ b/php/Exchange.php @@ -34,7 +34,7 @@ use kornrunner\Secp256k1; use kornrunner\Solidity; -$version = '1.17.385'; +$version = '1.17.386'; // rounding mode const TRUNCATE = 0; @@ -50,7 +50,7 @@ class Exchange { - const VERSION = '1.17.385'; + const VERSION = '1.17.386'; public static $eth_units = array ( 'wei' => '1', diff --git a/php/bitmex.php b/php/bitmex.php index a302bcc8e75a6..c7f9c08a2f405 100644 --- a/php/bitmex.php +++ b/php/bitmex.php @@ -132,8 +132,13 @@ public function describe () { ), ), 'exceptions' => array ( - 'Invalid API Key.' => '\\ccxt\\AuthenticationError', - 'Access Denied' => '\\ccxt\\PermissionDenied', + 'exact' => array ( + 'Invalid API Key.' => '\\ccxt\\AuthenticationError', + 'Access Denied' => '\\ccxt\\PermissionDenied', + ), + 'broad' => array ( + 'overloaded' => '\\ccxt\\ExchangeNotAvailable', + ), ), 'options' => array ( 'fetchTickerQuotes' => false, @@ -570,19 +575,18 @@ public function handle_errors ($code, $reason, $url, $method, $headers, $body) { if ($body) { if ($body[0] === '{') { $response = json_decode ($body, $as_associative_array = true); - if (is_array ($response) && array_key_exists ('error', $response)) { - if (is_array ($response['error']) && array_key_exists ('message', $response['error'])) { - $feedback = $this->id . ' ' . $this->json ($response); - $message = $this->safe_value($response['error'], 'message'); - $exceptions = $this->exceptions; - if ($message !== null) { - if (is_array ($exceptions) && array_key_exists ($message, $exceptions)) { - throw new $exceptions[$message] ($feedback); - } - } - throw new ExchangeError ($feedback); - } + $message = $this->safe_string($response, 'error'); + $feedback = $this->id . ' ' . $body; + $exact = $this->exceptions['exact']; + if (is_array ($exact) && array_key_exists ($code, $exact)) { + throw new $exact[$code] ($feedback); + } + $broad = $this->exceptions['broad']; + $broadKey = $this->findBroadlyMatchedKey ($broad, $message); + if ($broadKey !== null) { + throw new $broad[$broadKey] ($feedback); } + throw new ExchangeError ($feedback); // unknown $message } } } diff --git a/php/bitstamp.php b/php/bitstamp.php index 062bc7273de36..3f3048aa08516 100644 --- a/php/bitstamp.php +++ b/php/bitstamp.php @@ -450,6 +450,7 @@ public function parse_order_status ($status) { 'In Queue' => 'open', 'Open' => 'open', 'Finished' => 'closed', + 'Canceled' => 'canceled', ); return (is_array ($statuses) && array_key_exists ($status, $statuses)) ? $statuses[$status] : $status; } diff --git a/php/bitstamp1.php b/php/bitstamp1.php index 8d4daadc09bce..3fa954b004c9d 100644 --- a/php/bitstamp1.php +++ b/php/bitstamp1.php @@ -197,17 +197,20 @@ public function cancel_order ($id, $symbol = null, $params = array ()) { return $this->privatePostCancelOrder (array ( 'id' => $id )); } - public function parse_order_status ($order) { - if (($order['status'] === 'Queue') || ($order['status'] === 'Open')) - return 'open'; - if ($order['status'] === 'Finished') - return 'closed'; - return $order['status']; + public function parse_order_status ($status) { + $statuses = array ( + 'In Queue' => 'open', + 'Open' => 'open', + 'Finished' => 'closed', + 'Canceled' => 'canceled', + ); + return (is_array ($statuses) && array_key_exists ($status, $statuses)) ? $statuses[$status] : $status; } - public function fetch_order_status ($id, $symbol = null) { + public function fetch_order_status ($id, $symbol = null, $params = array ()) { $this->load_markets(); - $response = $this->privatePostOrderStatus (array ( 'id' => $id )); + $request = array ( 'id' => $id ); + $response = $this->privatePostOrderStatus (array_merge ($request, $params)); return $this->parse_order_status($response); } diff --git a/php/poloniex.php b/php/poloniex.php index b28c2abe9b531..19619af07326b 100644 --- a/php/poloniex.php +++ b/php/poloniex.php @@ -797,9 +797,9 @@ public function cancel_order ($id, $symbol = null, $params = array ()) { return $response; } - public function fetch_order_status ($id, $symbol = null) { + public function fetch_order_status ($id, $symbol = null, $params = array ()) { $this->load_markets(); - $orders = $this->fetch_open_orders($symbol); + $orders = $this->fetch_open_orders($symbol, null, null, $params); $indexed = $this->index_by($orders, 'id'); return (is_array ($indexed) && array_key_exists ($id, $indexed)) ? 'open' : 'closed'; } diff --git a/python/ccxt/__init__.py b/python/ccxt/__init__.py index 510f52cb18528..8f9300e35a1bf 100644 --- a/python/ccxt/__init__.py +++ b/python/ccxt/__init__.py @@ -22,7 +22,7 @@ # ---------------------------------------------------------------------------- -__version__ = '1.17.385' +__version__ = '1.17.386' # ---------------------------------------------------------------------------- diff --git a/python/ccxt/async_support/__init__.py b/python/ccxt/async_support/__init__.py index c6ae01640aa2a..948d49b02395e 100644 --- a/python/ccxt/async_support/__init__.py +++ b/python/ccxt/async_support/__init__.py @@ -4,7 +4,7 @@ # ----------------------------------------------------------------------------- -__version__ = '1.17.385' +__version__ = '1.17.386' # ----------------------------------------------------------------------------- diff --git a/python/ccxt/async_support/base/exchange.py b/python/ccxt/async_support/base/exchange.py index 144f7824e4d62..e2b18dd8244f0 100644 --- a/python/ccxt/async_support/base/exchange.py +++ b/python/ccxt/async_support/base/exchange.py @@ -2,7 +2,7 @@ # ----------------------------------------------------------------------------- -__version__ = '1.17.385' +__version__ = '1.17.386' # ----------------------------------------------------------------------------- diff --git a/python/ccxt/async_support/bitmex.py b/python/ccxt/async_support/bitmex.py index ba0e38b1a0fdd..1769b72e13170 100644 --- a/python/ccxt/async_support/bitmex.py +++ b/python/ccxt/async_support/bitmex.py @@ -10,6 +10,7 @@ from ccxt.base.errors import PermissionDenied from ccxt.base.errors import OrderNotFound from ccxt.base.errors import DDoSProtection +from ccxt.base.errors import ExchangeNotAvailable class bitmex (Exchange): @@ -137,8 +138,13 @@ def describe(self): }, }, 'exceptions': { - 'Invalid API Key.': AuthenticationError, - 'Access Denied': PermissionDenied, + 'exact': { + 'Invalid API Key.': AuthenticationError, + 'Access Denied': PermissionDenied, + }, + 'broad': { + 'overloaded': ExchangeNotAvailable, + }, }, 'options': { 'fetchTickerQuotes': False, @@ -542,15 +548,16 @@ def handle_errors(self, code, reason, url, method, headers, body): if body: if body[0] == '{': response = json.loads(body) - if 'error' in response: - if 'message' in response['error']: - feedback = self.id + ' ' + self.json(response) - message = self.safe_value(response['error'], 'message') - exceptions = self.exceptions - if message is not None: - if message in exceptions: - raise exceptions[message](feedback) - raise ExchangeError(feedback) + message = self.safe_string(response, 'error') + feedback = self.id + ' ' + body + exact = self.exceptions['exact'] + if code in exact: + raise exact[code](feedback) + broad = self.exceptions['broad'] + broadKey = self.findBroadlyMatchedKey(broad, message) + if broadKey is not None: + raise broad[broadKey](feedback) + raise ExchangeError(feedback) # unknown message def nonce(self): return self.milliseconds() diff --git a/python/ccxt/async_support/bitstamp.py b/python/ccxt/async_support/bitstamp.py index c1559bfbd8863..616631a96b4d5 100644 --- a/python/ccxt/async_support/bitstamp.py +++ b/python/ccxt/async_support/bitstamp.py @@ -430,6 +430,7 @@ def parse_order_status(self, status): 'In Queue': 'open', 'Open': 'open', 'Finished': 'closed', + 'Canceled': 'canceled', } return statuses[status] if (status in list(statuses.keys())) else status diff --git a/python/ccxt/async_support/bitstamp1.py b/python/ccxt/async_support/bitstamp1.py index beecbf49f251d..88e8bcf3ca24e 100644 --- a/python/ccxt/async_support/bitstamp1.py +++ b/python/ccxt/async_support/bitstamp1.py @@ -187,16 +187,19 @@ async def create_order(self, symbol, type, side, amount, price=None, params={}): async def cancel_order(self, id, symbol=None, params={}): return await self.privatePostCancelOrder({'id': id}) - def parse_order_status(self, order): - if (order['status'] == 'Queue') or (order['status'] == 'Open'): - return 'open' - if order['status'] == 'Finished': - return 'closed' - return order['status'] - - async def fetch_order_status(self, id, symbol=None): + def parse_order_status(self, status): + statuses = { + 'In Queue': 'open', + 'Open': 'open', + 'Finished': 'closed', + 'Canceled': 'canceled', + } + return statuses[status] if (status in list(statuses.keys())) else status + + async def fetch_order_status(self, id, symbol=None, params={}): await self.load_markets() - response = await self.privatePostOrderStatus({'id': id}) + request = {'id': id} + response = await self.privatePostOrderStatus(self.extend(request, params)) return self.parse_order_status(response) async def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}): diff --git a/python/ccxt/async_support/poloniex.py b/python/ccxt/async_support/poloniex.py index 0e707fa555b16..e85a8df5d204b 100644 --- a/python/ccxt/async_support/poloniex.py +++ b/python/ccxt/async_support/poloniex.py @@ -747,9 +747,9 @@ async def cancel_order(self, id, symbol=None, params={}): self.orders[id]['status'] = 'canceled' return response - async def fetch_order_status(self, id, symbol=None): + async def fetch_order_status(self, id, symbol=None, params={}): await self.load_markets() - orders = await self.fetch_open_orders(symbol) + orders = await self.fetch_open_orders(symbol, None, None, params) indexed = self.index_by(orders, 'id') return 'open' if (id in list(indexed.keys())) else 'closed' diff --git a/python/ccxt/base/exchange.py b/python/ccxt/base/exchange.py index 609fc8e839d38..141856cebc987 100644 --- a/python/ccxt/base/exchange.py +++ b/python/ccxt/base/exchange.py @@ -4,7 +4,7 @@ # ----------------------------------------------------------------------------- -__version__ = '1.17.385' +__version__ = '1.17.386' # ----------------------------------------------------------------------------- diff --git a/python/ccxt/bitmex.py b/python/ccxt/bitmex.py index f5f78dbac4f55..069ea6acbc04e 100644 --- a/python/ccxt/bitmex.py +++ b/python/ccxt/bitmex.py @@ -10,6 +10,7 @@ from ccxt.base.errors import PermissionDenied from ccxt.base.errors import OrderNotFound from ccxt.base.errors import DDoSProtection +from ccxt.base.errors import ExchangeNotAvailable class bitmex (Exchange): @@ -137,8 +138,13 @@ def describe(self): }, }, 'exceptions': { - 'Invalid API Key.': AuthenticationError, - 'Access Denied': PermissionDenied, + 'exact': { + 'Invalid API Key.': AuthenticationError, + 'Access Denied': PermissionDenied, + }, + 'broad': { + 'overloaded': ExchangeNotAvailable, + }, }, 'options': { 'fetchTickerQuotes': False, @@ -542,15 +548,16 @@ def handle_errors(self, code, reason, url, method, headers, body): if body: if body[0] == '{': response = json.loads(body) - if 'error' in response: - if 'message' in response['error']: - feedback = self.id + ' ' + self.json(response) - message = self.safe_value(response['error'], 'message') - exceptions = self.exceptions - if message is not None: - if message in exceptions: - raise exceptions[message](feedback) - raise ExchangeError(feedback) + message = self.safe_string(response, 'error') + feedback = self.id + ' ' + body + exact = self.exceptions['exact'] + if code in exact: + raise exact[code](feedback) + broad = self.exceptions['broad'] + broadKey = self.findBroadlyMatchedKey(broad, message) + if broadKey is not None: + raise broad[broadKey](feedback) + raise ExchangeError(feedback) # unknown message def nonce(self): return self.milliseconds() diff --git a/python/ccxt/bitstamp.py b/python/ccxt/bitstamp.py index 1607fae0a8e8d..d7cc3c4b17d2d 100644 --- a/python/ccxt/bitstamp.py +++ b/python/ccxt/bitstamp.py @@ -430,6 +430,7 @@ def parse_order_status(self, status): 'In Queue': 'open', 'Open': 'open', 'Finished': 'closed', + 'Canceled': 'canceled', } return statuses[status] if (status in list(statuses.keys())) else status diff --git a/python/ccxt/bitstamp1.py b/python/ccxt/bitstamp1.py index ed4cbd6220000..514f5a26d1c38 100644 --- a/python/ccxt/bitstamp1.py +++ b/python/ccxt/bitstamp1.py @@ -187,16 +187,19 @@ def create_order(self, symbol, type, side, amount, price=None, params={}): def cancel_order(self, id, symbol=None, params={}): return self.privatePostCancelOrder({'id': id}) - def parse_order_status(self, order): - if (order['status'] == 'Queue') or (order['status'] == 'Open'): - return 'open' - if order['status'] == 'Finished': - return 'closed' - return order['status'] - - def fetch_order_status(self, id, symbol=None): + def parse_order_status(self, status): + statuses = { + 'In Queue': 'open', + 'Open': 'open', + 'Finished': 'closed', + 'Canceled': 'canceled', + } + return statuses[status] if (status in list(statuses.keys())) else status + + def fetch_order_status(self, id, symbol=None, params={}): self.load_markets() - response = self.privatePostOrderStatus({'id': id}) + request = {'id': id} + response = self.privatePostOrderStatus(self.extend(request, params)) return self.parse_order_status(response) def fetch_my_trades(self, symbol=None, since=None, limit=None, params={}): diff --git a/python/ccxt/poloniex.py b/python/ccxt/poloniex.py index f07e8d6d536cb..8514000224fc0 100644 --- a/python/ccxt/poloniex.py +++ b/python/ccxt/poloniex.py @@ -747,9 +747,9 @@ def cancel_order(self, id, symbol=None, params={}): self.orders[id]['status'] = 'canceled' return response - def fetch_order_status(self, id, symbol=None): + def fetch_order_status(self, id, symbol=None, params={}): self.load_markets() - orders = self.fetch_open_orders(symbol) + orders = self.fetch_open_orders(symbol, None, None, params) indexed = self.index_by(orders, 'id') return 'open' if (id in list(indexed.keys())) else 'closed'