ccxt-look 1.81.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cache/eslintcache +1 -0
- package/.dockerignore +6 -0
- package/.eslintignore +1 -0
- package/.gitattributes +5 -0
- package/.readthedocs.yaml +16 -0
- package/CONTRIBUTING.md +1049 -0
- package/LICENSE.txt +21 -0
- package/README.md +537 -0
- package/SECURITY.md +5 -0
- package/build/cleanup-old-tags.js +94 -0
- package/build/countries.js +256 -0
- package/build/export-exchanges.js +520 -0
- package/build/fs.js +51 -0
- package/build/transpile.js +1772 -0
- package/build/vss.js +78 -0
- package/ccxt.browser.js +7 -0
- package/ccxt.d.ts +692 -0
- package/ccxt.js +171 -0
- package/cleanup.sh +2 -0
- package/composer-install.sh +20 -0
- package/dist/ccxt.browser.js +208383 -0
- package/gource.sh +3 -0
- package/index.html +7 -0
- package/js/.eslintrc +87 -0
- package/js/aax.js +2686 -0
- package/js/ascendex.js +2584 -0
- package/js/base/.eslintrc.js +43 -0
- package/js/base/Exchange.js +2371 -0
- package/js/base/Precise.js +283 -0
- package/js/base/errorHierarchy.js +47 -0
- package/js/base/errors.js +55 -0
- package/js/base/functions/crypto.js +158 -0
- package/js/base/functions/encode.js +118 -0
- package/js/base/functions/generic.js +270 -0
- package/js/base/functions/misc.js +138 -0
- package/js/base/functions/number.js +329 -0
- package/js/base/functions/platform.js +38 -0
- package/js/base/functions/string.js +21 -0
- package/js/base/functions/throttle.js +79 -0
- package/js/base/functions/time.js +210 -0
- package/js/base/functions/type.js +66 -0
- package/js/base/functions.js +28 -0
- package/js/bequant.js +32 -0
- package/js/bibox.js +1407 -0
- package/js/bigone.js +1366 -0
- package/js/binance.js +5652 -0
- package/js/binancecoinm.js +46 -0
- package/js/binanceus.js +46 -0
- package/js/binanceusdm.js +49 -0
- package/js/bit2c.js +535 -0
- package/js/bitbank.js +842 -0
- package/js/bitbay.js +16 -0
- package/js/bitbns.js +1073 -0
- package/js/bitcoincom.js +15 -0
- package/js/bitfinex.js +1433 -0
- package/js/bitfinex2.js +2025 -0
- package/js/bitflyer.js +840 -0
- package/js/bitforex.js +614 -0
- package/js/bitget.js +2397 -0
- package/js/bithumb.js +980 -0
- package/js/bitmart.js +2516 -0
- package/js/bitmex.js +1809 -0
- package/js/bitopro.js +1443 -0
- package/js/bitpanda.js +1782 -0
- package/js/bitrue.js +1747 -0
- package/js/bitso.js +1062 -0
- package/js/bitstamp.js +1757 -0
- package/js/bitstamp1.js +343 -0
- package/js/bittrex.js +1876 -0
- package/js/bitvavo.js +1579 -0
- package/js/bkex.js +1233 -0
- package/js/bl3p.js +346 -0
- package/js/blockchaincom.js +969 -0
- package/js/btcalpha.js +680 -0
- package/js/btcbox.js +477 -0
- package/js/btcmarkets.js +1022 -0
- package/js/btctradeua.js +466 -0
- package/js/btcturk.js +734 -0
- package/js/buda.js +946 -0
- package/js/bw.js +1265 -0
- package/js/bybit.js +3372 -0
- package/js/bytetrade.js +1336 -0
- package/js/cdax.js +1646 -0
- package/js/cex.js +1410 -0
- package/js/coinbase.js +1342 -0
- package/js/coinbaseprime.js +31 -0
- package/js/coinbasepro.js +1466 -0
- package/js/coincheck.js +755 -0
- package/js/coinex.js +3400 -0
- package/js/coinfalcon.js +880 -0
- package/js/coinmate.js +794 -0
- package/js/coinone.js +816 -0
- package/js/coinspot.js +345 -0
- package/js/crex24.js +1636 -0
- package/js/cryptocom.js +1832 -0
- package/js/currencycom.js +1748 -0
- package/js/delta.js +1547 -0
- package/js/deribit.js +2148 -0
- package/js/digifinex.js +1585 -0
- package/js/eqonex.js +1660 -0
- package/js/exmo.js +1670 -0
- package/js/fairdesk.js +1231 -0
- package/js/flowbtc.js +35 -0
- package/js/fmfwio.js +34 -0
- package/js/ftx.js +2751 -0
- package/js/ftxus.js +38 -0
- package/js/gateio.js +4174 -0
- package/js/gemini.js +1397 -0
- package/js/hitbtc.js +1343 -0
- package/js/hitbtc3.js +2329 -0
- package/js/hollaex.js +1486 -0
- package/js/huobi.js +5706 -0
- package/js/huobijp.js +1710 -0
- package/js/huobipro.js +18 -0
- package/js/idex.js +1439 -0
- package/js/independentreserve.js +649 -0
- package/js/indodax.js +742 -0
- package/js/itbit.js +722 -0
- package/js/kraken.js +2179 -0
- package/js/kucoin.js +2571 -0
- package/js/kucoinfutures.js +1771 -0
- package/js/kuna.js +809 -0
- package/js/latoken.js +1445 -0
- package/js/lbank.js +760 -0
- package/js/liquid.js +1432 -0
- package/js/luno.js +873 -0
- package/js/lykke.js +1147 -0
- package/js/mercado.js +771 -0
- package/js/mexc.js +3151 -0
- package/js/ndax.js +2233 -0
- package/js/novadax.js +1318 -0
- package/js/oceanex.js +816 -0
- package/js/okcoin.js +3841 -0
- package/js/okex.js +16 -0
- package/js/okex5.js +16 -0
- package/js/okx.js +4795 -0
- package/js/paymium.js +498 -0
- package/js/phemex.js +2957 -0
- package/js/poloniex.js +1674 -0
- package/js/probit.js +1346 -0
- package/js/qtrade.js +1588 -0
- package/js/ripio.js +1061 -0
- package/js/static_dependencies/BN/bn.js +3526 -0
- package/js/static_dependencies/README.md +1 -0
- package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
- package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
- package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
- package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
- package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
- package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
- package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
- package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
- package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
- package/js/static_dependencies/node-fetch/index.js +1564 -0
- package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
- package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
- package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
- package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
- package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
- package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
- package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
- package/js/static_dependencies/node-rsa/formats/components.js +71 -0
- package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
- package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
- package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
- package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
- package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
- package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
- package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
- package/js/static_dependencies/node-rsa/utils.js +98 -0
- package/js/static_dependencies/qs/formats.js +18 -0
- package/js/static_dependencies/qs/index.js +11 -0
- package/js/static_dependencies/qs/parse.js +242 -0
- package/js/static_dependencies/qs/stringify.js +269 -0
- package/js/static_dependencies/qs/utils.js +230 -0
- package/js/stex.js +1925 -0
- package/js/test/.eslintrc.js +42 -0
- package/js/test/Exchange/test.balance.js +61 -0
- package/js/test/Exchange/test.borrowRate.js +32 -0
- package/js/test/Exchange/test.currency.js +52 -0
- package/js/test/Exchange/test.fetchBalance.js +23 -0
- package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
- package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
- package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
- package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
- package/js/test/Exchange/test.fetchCurrencies.js +35 -0
- package/js/test/Exchange/test.fetchDeposits.js +31 -0
- package/js/test/Exchange/test.fetchFundingFees.js +19 -0
- package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
- package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
- package/js/test/Exchange/test.fetchLedger.js +42 -0
- package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
- package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
- package/js/test/Exchange/test.fetchMarkets.js +33 -0
- package/js/test/Exchange/test.fetchMyTrades.js +42 -0
- package/js/test/Exchange/test.fetchOHLCV.js +46 -0
- package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
- package/js/test/Exchange/test.fetchOrderBook.js +25 -0
- package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
- package/js/test/Exchange/test.fetchOrders.js +41 -0
- package/js/test/Exchange/test.fetchPositions.js +47 -0
- package/js/test/Exchange/test.fetchStatus.js +35 -0
- package/js/test/Exchange/test.fetchTicker.js +38 -0
- package/js/test/Exchange/test.fetchTickers.js +49 -0
- package/js/test/Exchange/test.fetchTrades.js +39 -0
- package/js/test/Exchange/test.fetchTradingFee.js +18 -0
- package/js/test/Exchange/test.fetchTradingFees.js +22 -0
- package/js/test/Exchange/test.fetchTransactions.js +31 -0
- package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
- package/js/test/Exchange/test.ledgerItem.js +46 -0
- package/js/test/Exchange/test.leverageTier.js +33 -0
- package/js/test/Exchange/test.loadMarkets.js +35 -0
- package/js/test/Exchange/test.market.js +129 -0
- package/js/test/Exchange/test.ohlcv.js +33 -0
- package/js/test/Exchange/test.order.js +62 -0
- package/js/test/Exchange/test.orderbook.js +61 -0
- package/js/test/Exchange/test.position.js +21 -0
- package/js/test/Exchange/test.throttle.js +94 -0
- package/js/test/Exchange/test.ticker.js +95 -0
- package/js/test/Exchange/test.trade.js +68 -0
- package/js/test/Exchange/test.tradingFee.js +34 -0
- package/js/test/Exchange/test.transaction.js +35 -0
- package/js/test/base/.eslintrc +38 -0
- package/js/test/base/functions/test.crypto.js +110 -0
- package/js/test/base/functions/test.datetime.js +62 -0
- package/js/test/base/functions/test.generic.js +152 -0
- package/js/test/base/functions/test.number.js +362 -0
- package/js/test/base/functions/test.time.js +56 -0
- package/js/test/base/functions/test.type.js +53 -0
- package/js/test/base/test.base.js +193 -0
- package/js/test/errors/test.InsufficientFunds.js +86 -0
- package/js/test/errors/test.InvalidNonce.js +64 -0
- package/js/test/errors/test.InvalidOrder.js +35 -0
- package/js/test/errors/test.OrderNotFound.js +39 -0
- package/js/test/test.js +426 -0
- package/js/test/test.timeout_hang.js +12 -0
- package/js/therock.js +1431 -0
- package/js/tidebit.js +632 -0
- package/js/tidex.js +939 -0
- package/js/timex.js +1283 -0
- package/js/upbit.js +1622 -0
- package/js/vcc.js +1353 -0
- package/js/wavesexchange.js +2185 -0
- package/js/wazirx.js +732 -0
- package/js/whitebit.js +1352 -0
- package/js/woo.js +1577 -0
- package/js/xena.js +1948 -0
- package/js/yobit.js +1129 -0
- package/js/zaif.js +647 -0
- package/js/zb.js +4088 -0
- package/js/zipmex.js +40 -0
- package/js/zonda.js +1497 -0
- package/multilang.sh +159 -0
- package/package.json +591 -0
- package/postinstall.js +103 -0
package/js/hitbtc.js
ADDED
@@ -0,0 +1,1343 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { BadSymbol, PermissionDenied, ExchangeError, ExchangeNotAvailable, OrderNotFound, InsufficientFunds, InvalidOrder, RequestTimeout, AuthenticationError } = require ('./base/errors');
|
7
|
+
const { TRUNCATE, DECIMAL_PLACES, TICK_SIZE } = require ('./base/functions/number');
|
8
|
+
const Precise = require ('./base/Precise');
|
9
|
+
|
10
|
+
// ---------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = class hitbtc extends Exchange {
|
13
|
+
describe () {
|
14
|
+
return this.deepExtend (super.describe (), {
|
15
|
+
'id': 'hitbtc',
|
16
|
+
'name': 'HitBTC',
|
17
|
+
'countries': [ 'HK' ],
|
18
|
+
// 300 requests per second => 1000ms / 300 = 3.333ms between requests on average (Trading)
|
19
|
+
// 100 requests per second => ( 1000ms / rateLimit ) / 100 => cost = 3.0003 (Market Data)
|
20
|
+
// 10 requests per second => ( 1000ms / rateLimit ) / 10 => cost = 30.003 (Other Requests)
|
21
|
+
'rateLimit': 3.333,
|
22
|
+
'version': '2',
|
23
|
+
'pro': true,
|
24
|
+
'has': {
|
25
|
+
'CORS': undefined,
|
26
|
+
'spot': true,
|
27
|
+
'margin': false,
|
28
|
+
'swap': false,
|
29
|
+
'future': false,
|
30
|
+
'option': false,
|
31
|
+
'addMargin': false,
|
32
|
+
'cancelOrder': true,
|
33
|
+
'createDepositAddress': true,
|
34
|
+
'createOrder': true,
|
35
|
+
'createReduceOnlyOrder': false,
|
36
|
+
'editOrder': true,
|
37
|
+
'fetchBalance': true,
|
38
|
+
'fetchBorrowRate': false,
|
39
|
+
'fetchBorrowRateHistories': false,
|
40
|
+
'fetchBorrowRateHistory': false,
|
41
|
+
'fetchBorrowRates': false,
|
42
|
+
'fetchBorrowRatesPerSymbol': false,
|
43
|
+
'fetchClosedOrders': true,
|
44
|
+
'fetchCurrencies': true,
|
45
|
+
'fetchDepositAddress': true,
|
46
|
+
'fetchDeposits': undefined,
|
47
|
+
'fetchFundingHistory': false,
|
48
|
+
'fetchFundingRate': false,
|
49
|
+
'fetchFundingRateHistory': false,
|
50
|
+
'fetchFundingRates': false,
|
51
|
+
'fetchIndexOHLCV': false,
|
52
|
+
'fetchLeverage': false,
|
53
|
+
'fetchLeverageTiers': false,
|
54
|
+
'fetchMarkets': true,
|
55
|
+
'fetchMarkOHLCV': false,
|
56
|
+
'fetchMyTrades': true,
|
57
|
+
'fetchOHLCV': true,
|
58
|
+
'fetchOpenOrder': true,
|
59
|
+
'fetchOpenOrders': true,
|
60
|
+
'fetchOrder': true,
|
61
|
+
'fetchOrderBook': true,
|
62
|
+
'fetchOrders': undefined,
|
63
|
+
'fetchOrderTrades': true,
|
64
|
+
'fetchPosition': false,
|
65
|
+
'fetchPositions': false,
|
66
|
+
'fetchPositionsRisk': false,
|
67
|
+
'fetchPremiumIndexOHLCV': false,
|
68
|
+
'fetchTicker': true,
|
69
|
+
'fetchTickers': true,
|
70
|
+
'fetchTrades': true,
|
71
|
+
'fetchTradingFee': true,
|
72
|
+
'fetchTradingFees': false,
|
73
|
+
'fetchTransactions': true,
|
74
|
+
'fetchWithdrawals': undefined,
|
75
|
+
'reduceMargin': false,
|
76
|
+
'setLeverage': false,
|
77
|
+
'setMarginMode': false,
|
78
|
+
'setPositionMode': false,
|
79
|
+
'transfer': true,
|
80
|
+
'withdraw': true,
|
81
|
+
},
|
82
|
+
'timeframes': {
|
83
|
+
'1m': 'M1',
|
84
|
+
'3m': 'M3',
|
85
|
+
'5m': 'M5',
|
86
|
+
'15m': 'M15',
|
87
|
+
'30m': 'M30', // default
|
88
|
+
'1h': 'H1',
|
89
|
+
'4h': 'H4',
|
90
|
+
'1d': 'D1',
|
91
|
+
'1w': 'D7',
|
92
|
+
'1M': '1M',
|
93
|
+
},
|
94
|
+
'urls': {
|
95
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/27766555-8eaec20e-5edc-11e7-9c5b-6dc69fc42f5e.jpg',
|
96
|
+
'test': {
|
97
|
+
'public': 'https://api.demo.hitbtc.com',
|
98
|
+
'private': 'https://api.demo.hitbtc.com',
|
99
|
+
},
|
100
|
+
'api': {
|
101
|
+
'public': 'https://api.hitbtc.com',
|
102
|
+
'private': 'https://api.hitbtc.com',
|
103
|
+
},
|
104
|
+
'www': 'https://hitbtc.com',
|
105
|
+
'referral': 'https://hitbtc.com/?ref_id=5a5d39a65d466',
|
106
|
+
'doc': [
|
107
|
+
'https://api.hitbtc.com/v2',
|
108
|
+
],
|
109
|
+
'fees': [
|
110
|
+
'https://hitbtc.com/fees-and-limits',
|
111
|
+
'https://support.hitbtc.com/hc/en-us/articles/115005148605-Fees-and-limits',
|
112
|
+
],
|
113
|
+
},
|
114
|
+
'api': {
|
115
|
+
'public': {
|
116
|
+
'get': {
|
117
|
+
'currency': 3, // Available Currencies
|
118
|
+
'currency/{currency}': 3, // Get currency info
|
119
|
+
'symbol': 3, // Available Currency Symbols
|
120
|
+
'symbol/{symbol}': 3, // Get symbol info
|
121
|
+
'ticker': 3, // Ticker list for all symbols
|
122
|
+
'ticker/{symbol}': 3, // Ticker for symbol
|
123
|
+
'trades': 3,
|
124
|
+
'trades/{symbol}': 3, // Trades
|
125
|
+
'orderbook': 3,
|
126
|
+
'orderbook/{symbol}': 3, // Orderbook
|
127
|
+
'candles': 3,
|
128
|
+
'candles/{symbol}': 3, // Candles
|
129
|
+
},
|
130
|
+
},
|
131
|
+
'private': {
|
132
|
+
'get': {
|
133
|
+
'trading/balance': 30, // Get trading balance
|
134
|
+
'order': 30, // List your current open orders
|
135
|
+
'order/{clientOrderId}': 30, // Get a single order by clientOrderId
|
136
|
+
'trading/fee/all': 30, // Get trading fee rate
|
137
|
+
'trading/fee/{symbol}': 30, // Get trading fee rate
|
138
|
+
'margin/account': 30,
|
139
|
+
'margin/account/{symbol}': 30,
|
140
|
+
'margin/position': 30,
|
141
|
+
'margin/position/{symbol}': 30,
|
142
|
+
'margin/order': 30,
|
143
|
+
'margin/order/{clientOrderId}': 30,
|
144
|
+
'history/order': 30, // Get historical orders
|
145
|
+
'history/trades': 30, // Get historical trades
|
146
|
+
'history/order/{orderId}/trades': 30, // Get historical trades by specified order
|
147
|
+
'account/balance': 30, // Get main acccount balance
|
148
|
+
'account/crypto/address/{currency}': 30, // Get current address
|
149
|
+
'account/crypto/addresses/{currency}': 30, // Get last 10 deposit addresses for currency
|
150
|
+
'account/crypto/used-addresses/{currency}': 30, // Get last 10 unique addresses used for withdraw by currency
|
151
|
+
'account/crypto/estimate-withdraw': 30,
|
152
|
+
'account/crypto/is-mine/{address}': 30,
|
153
|
+
'account/transactions': 30, // Get account transactions
|
154
|
+
'account/transactions/{id}': 30, // Get account transaction by id
|
155
|
+
'sub-acc': 30,
|
156
|
+
'sub-acc/acl': 30,
|
157
|
+
'sub-acc/balance/{subAccountUserID}': 30,
|
158
|
+
'sub-acc/deposit-address/{subAccountUserId}/{currency}': 30,
|
159
|
+
},
|
160
|
+
'post': {
|
161
|
+
'order': 1, // Create new order
|
162
|
+
'margin/order': 1,
|
163
|
+
'account/crypto/address/{currency}': 1, // Create new crypto deposit address
|
164
|
+
'account/crypto/withdraw': 1, // Withdraw crypto
|
165
|
+
'account/crypto/transfer-convert': 1,
|
166
|
+
'account/transfer': 1, // Transfer amount to trading account or to main account
|
167
|
+
'account/transfer/internal': 1,
|
168
|
+
'sub-acc/freeze': 1,
|
169
|
+
'sub-acc/activate': 1,
|
170
|
+
'sub-acc/transfer': 1,
|
171
|
+
},
|
172
|
+
'put': {
|
173
|
+
'order/{clientOrderId}': 1, // Create new order
|
174
|
+
'margin/account/{symbol}': 1,
|
175
|
+
'margin/order/{clientOrderId}': 1,
|
176
|
+
'account/crypto/withdraw/{id}': 1, // Commit crypto withdrawal
|
177
|
+
'sub-acc/acl/{subAccountUserId}': 1,
|
178
|
+
},
|
179
|
+
'delete': {
|
180
|
+
'order': 1, // Cancel all open orders
|
181
|
+
'order/{clientOrderId}': 1, // Cancel order
|
182
|
+
'margin/account': 1,
|
183
|
+
'margin/account/{symbol}': 1,
|
184
|
+
'margin/position': 1,
|
185
|
+
'margin/position/{symbol}': 1,
|
186
|
+
'margin/order': 1,
|
187
|
+
'margin/order/{clientOrderId}': 1,
|
188
|
+
'account/crypto/withdraw/{id}': 1, // Rollback crypto withdrawal
|
189
|
+
},
|
190
|
+
// outdated?
|
191
|
+
'patch': {
|
192
|
+
'order/{clientOrderId}': 1, // Cancel Replace order
|
193
|
+
},
|
194
|
+
},
|
195
|
+
},
|
196
|
+
'precisionMode': TICK_SIZE,
|
197
|
+
'fees': {
|
198
|
+
'trading': {
|
199
|
+
'tierBased': false,
|
200
|
+
'percentage': true,
|
201
|
+
'maker': 0.1 / 100,
|
202
|
+
'taker': 0.2 / 100,
|
203
|
+
},
|
204
|
+
},
|
205
|
+
'options': {
|
206
|
+
'networks': {
|
207
|
+
'ETH': 'T20',
|
208
|
+
'ERC20': 'T20',
|
209
|
+
'TRX': 'TTRX',
|
210
|
+
'TRC20': 'TTRX',
|
211
|
+
'OMNI': '',
|
212
|
+
},
|
213
|
+
'defaultTimeInForce': 'FOK',
|
214
|
+
'accountsByType': {
|
215
|
+
'funding': 'bank',
|
216
|
+
'spot': 'exchange',
|
217
|
+
},
|
218
|
+
'fetchBalanceMethod': {
|
219
|
+
'account': 'account',
|
220
|
+
'bank': 'account',
|
221
|
+
'main': 'account',
|
222
|
+
'funding': 'account',
|
223
|
+
'exchange': 'trading',
|
224
|
+
'spot': 'trading',
|
225
|
+
'trade': 'trading',
|
226
|
+
'trading': 'trading',
|
227
|
+
},
|
228
|
+
},
|
229
|
+
'commonCurrencies': {
|
230
|
+
'AUTO': 'Cube',
|
231
|
+
'BCC': 'BCC', // initial symbol for Bitcoin Cash, now inactive
|
232
|
+
'BDP': 'BidiPass',
|
233
|
+
'BET': 'DAO.Casino',
|
234
|
+
'BIT': 'BitRewards',
|
235
|
+
'BOX': 'BOX Token',
|
236
|
+
'CPT': 'Cryptaur', // conflict with CPT = Contents Protocol https://github.com/ccxt/ccxt/issues/4920 and https://github.com/ccxt/ccxt/issues/6081
|
237
|
+
'GET': 'Themis',
|
238
|
+
'GMT': 'GMT Token',
|
239
|
+
'HSR': 'HC',
|
240
|
+
'IQ': 'IQ.Cash',
|
241
|
+
'LNC': 'LinkerCoin',
|
242
|
+
'PLA': 'PlayChip',
|
243
|
+
'PNT': 'Penta',
|
244
|
+
'SBTC': 'Super Bitcoin',
|
245
|
+
'STEPN': 'GMT',
|
246
|
+
'STX': 'STOX',
|
247
|
+
'TV': 'Tokenville',
|
248
|
+
'USD': 'USDT',
|
249
|
+
'XMT': 'MTL',
|
250
|
+
'XPNT': 'PNT',
|
251
|
+
},
|
252
|
+
'exceptions': {
|
253
|
+
'504': RequestTimeout, // {"error":{"code":504,"message":"Gateway Timeout"}}
|
254
|
+
'1002': AuthenticationError, // {"error":{"code":1002,"message":"Authorization failed","description":""}}
|
255
|
+
'1003': PermissionDenied, // "Action is forbidden for this API key"
|
256
|
+
'2010': InvalidOrder, // "Quantity not a valid number"
|
257
|
+
'2001': BadSymbol, // "Symbol not found"
|
258
|
+
'2011': InvalidOrder, // "Quantity too low"
|
259
|
+
'2020': InvalidOrder, // "Price not a valid number"
|
260
|
+
'20002': OrderNotFound, // canceling non-existent order
|
261
|
+
'20001': InsufficientFunds, // {"error":{"code":20001,"message":"Insufficient funds","description":"Check that the funds are sufficient, given commissions"}}
|
262
|
+
'20010': BadSymbol, // {"error":{"code":20010,"message":"Exchange temporary closed","description":"Exchange market for this symbol is temporary closed"}}
|
263
|
+
'20045': InvalidOrder, // {"error":{"code":20045,"message":"Fat finger limit exceeded"}}
|
264
|
+
},
|
265
|
+
});
|
266
|
+
}
|
267
|
+
|
268
|
+
feeToPrecision (symbol, fee) {
|
269
|
+
return this.decimalToPrecision (fee, TRUNCATE, 8, DECIMAL_PLACES);
|
270
|
+
}
|
271
|
+
|
272
|
+
async fetchMarkets (params = {}) {
|
273
|
+
const response = await this.publicGetSymbol (params);
|
274
|
+
//
|
275
|
+
// [
|
276
|
+
// {
|
277
|
+
// "id":"BCNBTC",
|
278
|
+
// "baseCurrency":"BCN",
|
279
|
+
// "quoteCurrency":"BTC",
|
280
|
+
// "quantityIncrement":"100",
|
281
|
+
// "tickSize":"0.00000000001",
|
282
|
+
// "takeLiquidityRate":"0.002",
|
283
|
+
// "provideLiquidityRate":"0.001",
|
284
|
+
// "feeCurrency":"BTC"
|
285
|
+
// }
|
286
|
+
// ]
|
287
|
+
//
|
288
|
+
const result = [];
|
289
|
+
for (let i = 0; i < response.length; i++) {
|
290
|
+
const market = response[i];
|
291
|
+
const id = this.safeString (market, 'id');
|
292
|
+
const baseId = this.safeString (market, 'baseCurrency');
|
293
|
+
const quoteId = this.safeString (market, 'quoteCurrency');
|
294
|
+
const base = this.safeCurrencyCode (baseId);
|
295
|
+
const quote = this.safeCurrencyCode (quoteId);
|
296
|
+
// bequant fix
|
297
|
+
let symbol = base + '/' + quote;
|
298
|
+
if (id.indexOf ('_') >= 0) {
|
299
|
+
symbol = id;
|
300
|
+
}
|
301
|
+
const lotString = this.safeString (market, 'quantityIncrement');
|
302
|
+
const stepString = this.safeString (market, 'tickSize');
|
303
|
+
const lot = this.parseNumber (lotString);
|
304
|
+
const step = this.parseNumber (stepString);
|
305
|
+
const feeCurrencyId = this.safeString (market, 'feeCurrency');
|
306
|
+
result.push (this.extend (this.fees['trading'], {
|
307
|
+
'id': id,
|
308
|
+
'symbol': symbol,
|
309
|
+
'base': base,
|
310
|
+
'quote': quote,
|
311
|
+
'settle': undefined,
|
312
|
+
'baseId': baseId,
|
313
|
+
'quoteId': quoteId,
|
314
|
+
'settleId': undefined,
|
315
|
+
'type': 'spot',
|
316
|
+
'spot': true,
|
317
|
+
'margin': false,
|
318
|
+
'swap': false,
|
319
|
+
'future': false,
|
320
|
+
'option': false,
|
321
|
+
'active': true,
|
322
|
+
'contract': false,
|
323
|
+
'linear': undefined,
|
324
|
+
'inverse': undefined,
|
325
|
+
'taker': this.safeNumber (market, 'takeLiquidityRate'),
|
326
|
+
'maker': this.safeNumber (market, 'provideLiquidityRate'),
|
327
|
+
'contractSize': undefined,
|
328
|
+
'expiry': undefined,
|
329
|
+
'expiryDatetime': undefined,
|
330
|
+
'strike': undefined,
|
331
|
+
'optionType': undefined,
|
332
|
+
'feeCurrency': this.safeCurrencyCode (feeCurrencyId),
|
333
|
+
'precision': {
|
334
|
+
'amount': lot,
|
335
|
+
'price': step,
|
336
|
+
},
|
337
|
+
'limits': {
|
338
|
+
'leverage': {
|
339
|
+
'min': undefined,
|
340
|
+
'max': undefined,
|
341
|
+
},
|
342
|
+
'amount': {
|
343
|
+
'min': lot,
|
344
|
+
'max': undefined,
|
345
|
+
},
|
346
|
+
'price': {
|
347
|
+
'min': step,
|
348
|
+
'max': undefined,
|
349
|
+
},
|
350
|
+
'cost': {
|
351
|
+
'min': this.parseNumber (Precise.stringMul (lotString, stepString)),
|
352
|
+
'max': undefined,
|
353
|
+
},
|
354
|
+
},
|
355
|
+
'info': market,
|
356
|
+
}));
|
357
|
+
}
|
358
|
+
return result;
|
359
|
+
}
|
360
|
+
|
361
|
+
async transfer (code, amount, fromAccount, toAccount, params = {}) {
|
362
|
+
// account can be "exchange" or "bank", with aliases "main" or "trading" respectively
|
363
|
+
await this.loadMarkets ();
|
364
|
+
const currency = this.currency (code);
|
365
|
+
const requestAmount = this.currencyToPrecision (code, amount);
|
366
|
+
const request = {
|
367
|
+
'currency': currency['id'],
|
368
|
+
'amount': requestAmount,
|
369
|
+
};
|
370
|
+
let type = this.safeString (params, 'type');
|
371
|
+
if (type === undefined) {
|
372
|
+
const accountsByType = this.safeValue (this.options, 'accountsByType', {});
|
373
|
+
const fromId = this.safeString (accountsByType, fromAccount, fromAccount);
|
374
|
+
const toId = this.safeString (accountsByType, toAccount, toAccount);
|
375
|
+
if (fromId === toId) {
|
376
|
+
throw new ExchangeError (this.id + ' transfer() from and to cannot be the same account');
|
377
|
+
}
|
378
|
+
type = fromId + 'To' + this.capitalize (toId);
|
379
|
+
}
|
380
|
+
request['type'] = type;
|
381
|
+
const response = await this.privatePostAccountTransfer (this.extend (request, params));
|
382
|
+
//
|
383
|
+
// {
|
384
|
+
// 'id': '2db6ebab-fb26-4537-9ef8-1a689472d236'
|
385
|
+
// }
|
386
|
+
//
|
387
|
+
const transfer = this.parseTransfer (response, currency);
|
388
|
+
return this.extend (transfer, {
|
389
|
+
'fromAccount': fromAccount,
|
390
|
+
'toAccount': toAccount,
|
391
|
+
'amount': this.parseNumber (requestAmount),
|
392
|
+
});
|
393
|
+
}
|
394
|
+
|
395
|
+
parseTransfer (transfer, currency = undefined) {
|
396
|
+
//
|
397
|
+
// {
|
398
|
+
// 'id': '2db6ebab-fb26-4537-9ef8-1a689472d236'
|
399
|
+
// }
|
400
|
+
//
|
401
|
+
const timestamp = this.milliseconds ();
|
402
|
+
return {
|
403
|
+
'id': this.safeString (transfer, 'id'),
|
404
|
+
'timestamp': timestamp,
|
405
|
+
'datetime': this.iso8601 (timestamp),
|
406
|
+
'currency': this.safeCurrencyCode (undefined, currency),
|
407
|
+
'amount': undefined,
|
408
|
+
'fromAccount': undefined,
|
409
|
+
'toAccount': undefined,
|
410
|
+
'status': undefined,
|
411
|
+
'info': transfer,
|
412
|
+
};
|
413
|
+
}
|
414
|
+
|
415
|
+
async fetchCurrencies (params = {}) {
|
416
|
+
const response = await this.publicGetCurrency (params);
|
417
|
+
//
|
418
|
+
// [
|
419
|
+
// {
|
420
|
+
// "id":"XPNT",
|
421
|
+
// "fullName":"pToken",
|
422
|
+
// "crypto":true,
|
423
|
+
// "payinEnabled":true,
|
424
|
+
// "payinPaymentId":false,
|
425
|
+
// "payinConfirmations":9,
|
426
|
+
// "payoutEnabled":true,
|
427
|
+
// "payoutIsPaymentId":false,
|
428
|
+
// "transferEnabled":true,
|
429
|
+
// "delisted":false,
|
430
|
+
// "payoutFee":"26.510000000000",
|
431
|
+
// "precisionPayout":18,
|
432
|
+
// "precisionTransfer":8
|
433
|
+
// }
|
434
|
+
// ]
|
435
|
+
//
|
436
|
+
const result = {};
|
437
|
+
for (let i = 0; i < response.length; i++) {
|
438
|
+
const currency = response[i];
|
439
|
+
const id = this.safeString (currency, 'id');
|
440
|
+
// todo: will need to rethink the fees
|
441
|
+
// to add support for multiple withdrawal/deposit methods and
|
442
|
+
// differentiated fees for each particular method
|
443
|
+
const decimals = this.safeInteger (currency, 'precisionTransfer', 8);
|
444
|
+
const precision = 1 / Math.pow (10, decimals);
|
445
|
+
const code = this.safeCurrencyCode (id);
|
446
|
+
const payin = this.safeValue (currency, 'payinEnabled');
|
447
|
+
const payout = this.safeValue (currency, 'payoutEnabled');
|
448
|
+
const transfer = this.safeValue (currency, 'transferEnabled');
|
449
|
+
let active = payin && payout && transfer;
|
450
|
+
if ('disabled' in currency) {
|
451
|
+
if (currency['disabled']) {
|
452
|
+
active = false;
|
453
|
+
}
|
454
|
+
}
|
455
|
+
let type = 'fiat';
|
456
|
+
if (('crypto' in currency) && currency['crypto']) {
|
457
|
+
type = 'crypto';
|
458
|
+
}
|
459
|
+
const name = this.safeString (currency, 'fullName');
|
460
|
+
result[code] = {
|
461
|
+
'id': id,
|
462
|
+
'code': code,
|
463
|
+
'type': type,
|
464
|
+
'payin': payin,
|
465
|
+
'payout': payout,
|
466
|
+
'transfer': transfer,
|
467
|
+
'info': currency,
|
468
|
+
'name': name,
|
469
|
+
'active': active,
|
470
|
+
'deposit': payin,
|
471
|
+
'withdraw': payout,
|
472
|
+
'fee': this.safeNumber (currency, 'payoutFee'), // todo: redesign
|
473
|
+
'precision': precision,
|
474
|
+
'limits': {
|
475
|
+
'amount': {
|
476
|
+
'min': 1 / Math.pow (10, decimals),
|
477
|
+
'max': Math.pow (10, decimals),
|
478
|
+
},
|
479
|
+
'withdraw': {
|
480
|
+
'min': undefined,
|
481
|
+
'max': Math.pow (10, precision),
|
482
|
+
},
|
483
|
+
},
|
484
|
+
};
|
485
|
+
}
|
486
|
+
return result;
|
487
|
+
}
|
488
|
+
|
489
|
+
parseTradingFee (fee, market = undefined) {
|
490
|
+
//
|
491
|
+
//
|
492
|
+
// {
|
493
|
+
// takeLiquidityRate: '0.001',
|
494
|
+
// provideLiquidityRate: '-0.0001'
|
495
|
+
// }
|
496
|
+
//
|
497
|
+
return {
|
498
|
+
'info': fee,
|
499
|
+
'symbol': this.safeSymbol (undefined, market),
|
500
|
+
'maker': this.safeNumber (fee, 'provideLiquidityRate'),
|
501
|
+
'taker': this.safeNumber (fee, 'takeLiquidityRate'),
|
502
|
+
'percentage': true,
|
503
|
+
'tierBased': true,
|
504
|
+
};
|
505
|
+
}
|
506
|
+
|
507
|
+
async fetchTradingFee (symbol, params = {}) {
|
508
|
+
await this.loadMarkets ();
|
509
|
+
const market = this.market (symbol);
|
510
|
+
const request = {
|
511
|
+
'symbol': market['id'],
|
512
|
+
};
|
513
|
+
const response = await this.privateGetTradingFeeSymbol (request);
|
514
|
+
//
|
515
|
+
// {
|
516
|
+
// takeLiquidityRate: '0.001',
|
517
|
+
// provideLiquidityRate: '-0.0001'
|
518
|
+
// }
|
519
|
+
//
|
520
|
+
return this.parseTradingFee (response, market);
|
521
|
+
}
|
522
|
+
|
523
|
+
parseBalance (response) {
|
524
|
+
const result = {
|
525
|
+
'info': response,
|
526
|
+
'timestamp': undefined,
|
527
|
+
'datetime': undefined,
|
528
|
+
};
|
529
|
+
for (let i = 0; i < response.length; i++) {
|
530
|
+
const balance = response[i];
|
531
|
+
const currencyId = this.safeString (balance, 'currency');
|
532
|
+
const code = this.safeCurrencyCode (currencyId);
|
533
|
+
const account = this.account ();
|
534
|
+
account['free'] = this.safeString (balance, 'available');
|
535
|
+
account['used'] = this.safeString (balance, 'reserved');
|
536
|
+
result[code] = account;
|
537
|
+
}
|
538
|
+
return this.safeBalance (result);
|
539
|
+
}
|
540
|
+
|
541
|
+
async fetchBalance (params = {}) {
|
542
|
+
await this.loadMarkets ();
|
543
|
+
const type = this.safeString (params, 'type', 'trading');
|
544
|
+
const fetchBalanceAccounts = this.safeValue (this.options, 'fetchBalanceMethod', {});
|
545
|
+
const typeId = this.safeString (fetchBalanceAccounts, type);
|
546
|
+
if (typeId === undefined) {
|
547
|
+
throw new ExchangeError (this.id + ' fetchBalance() account type must be either main or trading');
|
548
|
+
}
|
549
|
+
const method = 'privateGet' + this.capitalize (typeId) + 'Balance';
|
550
|
+
const query = this.omit (params, 'type');
|
551
|
+
const response = await this[method] (query);
|
552
|
+
//
|
553
|
+
// [
|
554
|
+
// {"currency":"SPI","available":"0","reserved":"0"},
|
555
|
+
// {"currency":"GRPH","available":"0","reserved":"0"},
|
556
|
+
// {"currency":"DGTX","available":"0","reserved":"0"},
|
557
|
+
// ]
|
558
|
+
//
|
559
|
+
return this.parseBalance (response);
|
560
|
+
}
|
561
|
+
|
562
|
+
parseOHLCV (ohlcv, market = undefined) {
|
563
|
+
//
|
564
|
+
// {
|
565
|
+
// "timestamp":"2015-08-20T19:01:00.000Z",
|
566
|
+
// "open":"0.006",
|
567
|
+
// "close":"0.006",
|
568
|
+
// "min":"0.006",
|
569
|
+
// "max":"0.006",
|
570
|
+
// "volume":"0.003",
|
571
|
+
// "volumeQuote":"0.000018"
|
572
|
+
// }
|
573
|
+
//
|
574
|
+
return [
|
575
|
+
this.parse8601 (this.safeString (ohlcv, 'timestamp')),
|
576
|
+
this.safeNumber (ohlcv, 'open'),
|
577
|
+
this.safeNumber (ohlcv, 'max'),
|
578
|
+
this.safeNumber (ohlcv, 'min'),
|
579
|
+
this.safeNumber (ohlcv, 'close'),
|
580
|
+
this.safeNumber (ohlcv, 'volume'),
|
581
|
+
];
|
582
|
+
}
|
583
|
+
|
584
|
+
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
585
|
+
await this.loadMarkets ();
|
586
|
+
const market = this.market (symbol);
|
587
|
+
const request = {
|
588
|
+
'symbol': market['id'],
|
589
|
+
'period': this.timeframes[timeframe],
|
590
|
+
};
|
591
|
+
if (since !== undefined) {
|
592
|
+
request['from'] = this.iso8601 (since);
|
593
|
+
}
|
594
|
+
if (limit !== undefined) {
|
595
|
+
request['limit'] = limit;
|
596
|
+
}
|
597
|
+
const response = await this.publicGetCandlesSymbol (this.extend (request, params));
|
598
|
+
//
|
599
|
+
// [
|
600
|
+
// {"timestamp":"2015-08-20T19:01:00.000Z","open":"0.006","close":"0.006","min":"0.006","max":"0.006","volume":"0.003","volumeQuote":"0.000018"},
|
601
|
+
// {"timestamp":"2015-08-20T19:03:00.000Z","open":"0.006","close":"0.006","min":"0.006","max":"0.006","volume":"0.013","volumeQuote":"0.000078"},
|
602
|
+
// {"timestamp":"2015-08-20T19:06:00.000Z","open":"0.0055","close":"0.005","min":"0.005","max":"0.0055","volume":"0.003","volumeQuote":"0.0000155"},
|
603
|
+
// ]
|
604
|
+
//
|
605
|
+
return this.parseOHLCVs (response, market, timeframe, since, limit);
|
606
|
+
}
|
607
|
+
|
608
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
609
|
+
await this.loadMarkets ();
|
610
|
+
const request = {
|
611
|
+
'symbol': this.marketId (symbol),
|
612
|
+
};
|
613
|
+
if (limit !== undefined) {
|
614
|
+
request['limit'] = limit; // default = 100, 0 = unlimited
|
615
|
+
}
|
616
|
+
const response = await this.publicGetOrderbookSymbol (this.extend (request, params));
|
617
|
+
return this.parseOrderBook (response, symbol, undefined, 'bid', 'ask', 'price', 'size');
|
618
|
+
}
|
619
|
+
|
620
|
+
parseTicker (ticker, market = undefined) {
|
621
|
+
const timestamp = this.parse8601 (ticker['timestamp']);
|
622
|
+
const symbol = this.safeSymbol (undefined, market);
|
623
|
+
const baseVolume = this.safeString (ticker, 'volume');
|
624
|
+
const quoteVolume = this.safeString (ticker, 'volumeQuote');
|
625
|
+
const open = this.safeString (ticker, 'open');
|
626
|
+
const last = this.safeString (ticker, 'last');
|
627
|
+
return this.safeTicker ({
|
628
|
+
'symbol': symbol,
|
629
|
+
'timestamp': timestamp,
|
630
|
+
'datetime': this.iso8601 (timestamp),
|
631
|
+
'high': this.safeString (ticker, 'high'),
|
632
|
+
'low': this.safeString (ticker, 'low'),
|
633
|
+
'bid': this.safeString (ticker, 'bid'),
|
634
|
+
'bidVolume': undefined,
|
635
|
+
'ask': this.safeString (ticker, 'ask'),
|
636
|
+
'askVolume': undefined,
|
637
|
+
'vwap': undefined,
|
638
|
+
'open': open,
|
639
|
+
'close': last,
|
640
|
+
'last': last,
|
641
|
+
'previousClose': undefined,
|
642
|
+
'change': undefined,
|
643
|
+
'percentage': undefined,
|
644
|
+
'average': undefined,
|
645
|
+
'baseVolume': baseVolume,
|
646
|
+
'quoteVolume': quoteVolume,
|
647
|
+
'info': ticker,
|
648
|
+
}, market, false);
|
649
|
+
}
|
650
|
+
|
651
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
652
|
+
await this.loadMarkets ();
|
653
|
+
const response = await this.publicGetTicker (params);
|
654
|
+
const result = {};
|
655
|
+
for (let i = 0; i < response.length; i++) {
|
656
|
+
const ticker = response[i];
|
657
|
+
const marketId = this.safeString (ticker, 'symbol');
|
658
|
+
const market = this.safeMarket (marketId);
|
659
|
+
const symbol = market['symbol'];
|
660
|
+
result[symbol] = this.parseTicker (ticker, market);
|
661
|
+
}
|
662
|
+
return this.filterByArray (result, 'symbol', symbols);
|
663
|
+
}
|
664
|
+
|
665
|
+
async fetchTicker (symbol, params = {}) {
|
666
|
+
await this.loadMarkets ();
|
667
|
+
const market = this.market (symbol);
|
668
|
+
const request = {
|
669
|
+
'symbol': market['id'],
|
670
|
+
};
|
671
|
+
const response = await this.publicGetTickerSymbol (this.extend (request, params));
|
672
|
+
if ('message' in response) {
|
673
|
+
throw new ExchangeError (this.id + ' ' + response['message']);
|
674
|
+
}
|
675
|
+
return this.parseTicker (response, market);
|
676
|
+
}
|
677
|
+
|
678
|
+
parseTrade (trade, market = undefined) {
|
679
|
+
// createMarketOrder
|
680
|
+
//
|
681
|
+
// { fee: "0.0004644",
|
682
|
+
// id: 386394956,
|
683
|
+
// price: "0.4644",
|
684
|
+
// quantity: "1",
|
685
|
+
// timestamp: "2018-10-25T16:41:44.780Z" }
|
686
|
+
//
|
687
|
+
// fetchTrades
|
688
|
+
//
|
689
|
+
// { id: 974786185,
|
690
|
+
// price: '0.032462',
|
691
|
+
// quantity: '0.3673',
|
692
|
+
// side: 'buy',
|
693
|
+
// timestamp: '2020-10-16T12:57:39.846Z' }
|
694
|
+
//
|
695
|
+
// fetchMyTrades
|
696
|
+
//
|
697
|
+
// { id: 277210397,
|
698
|
+
// clientOrderId: '6e102f3e7f3f4e04aeeb1cdc95592f1a',
|
699
|
+
// orderId: 28102855393,
|
700
|
+
// symbol: 'ETHBTC',
|
701
|
+
// side: 'sell',
|
702
|
+
// quantity: '0.002',
|
703
|
+
// price: '0.073365',
|
704
|
+
// fee: '0.000000147',
|
705
|
+
// timestamp: '2018-04-28T18:39:55.345Z' }
|
706
|
+
//
|
707
|
+
// {
|
708
|
+
// "id":1568938909,
|
709
|
+
// "orderId":793293348428,
|
710
|
+
// "clientOrderId":"fbc5c5b753e8476cb14697458cb928ef",
|
711
|
+
// "symbol":"DOGEUSD",
|
712
|
+
// "side":"sell",
|
713
|
+
// "quantity":"100",
|
714
|
+
// "price":"0.03904191",
|
715
|
+
// "fee":"0.009760477500",
|
716
|
+
// "timestamp":"2022-01-25T15:15:41.353Z",
|
717
|
+
// "taker":true
|
718
|
+
// }
|
719
|
+
//
|
720
|
+
const timestamp = this.parse8601 (trade['timestamp']);
|
721
|
+
const marketId = this.safeString (trade, 'symbol');
|
722
|
+
market = this.safeMarket (marketId, market);
|
723
|
+
const symbol = market['symbol'];
|
724
|
+
let fee = undefined;
|
725
|
+
const feeCostString = this.safeString (trade, 'fee');
|
726
|
+
if (feeCostString !== undefined) {
|
727
|
+
const feeCurrencyCode = market ? market['feeCurrency'] : undefined;
|
728
|
+
fee = {
|
729
|
+
'cost': feeCostString,
|
730
|
+
'currency': feeCurrencyCode,
|
731
|
+
};
|
732
|
+
}
|
733
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
734
|
+
// because most of their endpoints will require clientOrderId
|
735
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
736
|
+
const orderId = this.safeString (trade, 'clientOrderId');
|
737
|
+
const priceString = this.safeString (trade, 'price');
|
738
|
+
const amountString = this.safeString (trade, 'quantity');
|
739
|
+
const side = this.safeString (trade, 'side');
|
740
|
+
const id = this.safeString (trade, 'id');
|
741
|
+
return this.safeTrade ({
|
742
|
+
'info': trade,
|
743
|
+
'id': id,
|
744
|
+
'order': orderId,
|
745
|
+
'timestamp': timestamp,
|
746
|
+
'datetime': this.iso8601 (timestamp),
|
747
|
+
'symbol': symbol,
|
748
|
+
'type': undefined,
|
749
|
+
'side': side,
|
750
|
+
'takerOrMaker': undefined,
|
751
|
+
'price': priceString,
|
752
|
+
'amount': amountString,
|
753
|
+
'cost': undefined,
|
754
|
+
'fee': fee,
|
755
|
+
}, market);
|
756
|
+
}
|
757
|
+
|
758
|
+
async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
|
759
|
+
await this.loadMarkets ();
|
760
|
+
let currency = undefined;
|
761
|
+
const request = {};
|
762
|
+
if (code !== undefined) {
|
763
|
+
currency = this.currency (code);
|
764
|
+
request['asset'] = currency['id'];
|
765
|
+
}
|
766
|
+
if (since !== undefined) {
|
767
|
+
request['startTime'] = since;
|
768
|
+
}
|
769
|
+
const response = await this.privateGetAccountTransactions (this.extend (request, params));
|
770
|
+
return this.parseTransactions (response, currency, since, limit);
|
771
|
+
}
|
772
|
+
|
773
|
+
parseTransaction (transaction, currency = undefined) {
|
774
|
+
//
|
775
|
+
// transactions
|
776
|
+
//
|
777
|
+
// {
|
778
|
+
// id: 'd53ee9df-89bf-4d09-886e-849f8be64647',
|
779
|
+
// index: 1044718371,
|
780
|
+
// type: 'payout', // payout, payin
|
781
|
+
// status: 'success',
|
782
|
+
// currency: 'ETH',
|
783
|
+
// amount: '4.522683200000000000000000',
|
784
|
+
// createdAt: '2018-06-07T00:43:32.426Z',
|
785
|
+
// updatedAt: '2018-06-07T00:45:36.447Z',
|
786
|
+
// hash: '0x973e5683dfdf80a1fb1e0b96e19085b6489221d2ddf864daa46903c5ec283a0f',
|
787
|
+
// address: '0xC5a59b21948C1d230c8C54f05590000Eb3e1252c',
|
788
|
+
// fee: '0.00958',
|
789
|
+
// },
|
790
|
+
// {
|
791
|
+
// id: 'e6c63331-467e-4922-9edc-019e75d20ba3',
|
792
|
+
// index: 1044714672,
|
793
|
+
// type: 'exchangeToBank', // exchangeToBank, bankToExchange, withdraw
|
794
|
+
// status: 'success',
|
795
|
+
// currency: 'ETH',
|
796
|
+
// amount: '4.532263200000000000',
|
797
|
+
// createdAt: '2018-06-07T00:42:39.543Z',
|
798
|
+
// updatedAt: '2018-06-07T00:42:39.683Z',
|
799
|
+
// },
|
800
|
+
//
|
801
|
+
// withdraw
|
802
|
+
//
|
803
|
+
// {
|
804
|
+
// "id": "d2ce578f-647d-4fa0-b1aa-4a27e5ee597b"
|
805
|
+
// }
|
806
|
+
//
|
807
|
+
const id = this.safeString (transaction, 'id');
|
808
|
+
const timestamp = this.parse8601 (this.safeString (transaction, 'createdAt'));
|
809
|
+
const updated = this.parse8601 (this.safeString (transaction, 'updatedAt'));
|
810
|
+
const currencyId = this.safeString (transaction, 'currency');
|
811
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
812
|
+
const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
|
813
|
+
const amount = this.safeNumber (transaction, 'amount');
|
814
|
+
const address = this.safeString (transaction, 'address');
|
815
|
+
const txid = this.safeString (transaction, 'hash');
|
816
|
+
let fee = undefined;
|
817
|
+
const feeCost = this.safeNumber (transaction, 'fee');
|
818
|
+
if (feeCost !== undefined) {
|
819
|
+
fee = {
|
820
|
+
'cost': feeCost,
|
821
|
+
'currency': code,
|
822
|
+
};
|
823
|
+
}
|
824
|
+
const type = this.parseTransactionType (this.safeString (transaction, 'type'));
|
825
|
+
return {
|
826
|
+
'info': transaction,
|
827
|
+
'id': id,
|
828
|
+
'txid': txid,
|
829
|
+
'timestamp': timestamp,
|
830
|
+
'datetime': this.iso8601 (timestamp),
|
831
|
+
'network': undefined,
|
832
|
+
'address': address,
|
833
|
+
'addressTo': undefined,
|
834
|
+
'addressFrom': undefined,
|
835
|
+
'tag': undefined,
|
836
|
+
'tagTo': undefined,
|
837
|
+
'tagFrom': undefined,
|
838
|
+
'type': type,
|
839
|
+
'amount': amount,
|
840
|
+
'currency': code,
|
841
|
+
'status': status,
|
842
|
+
'updated': updated,
|
843
|
+
'fee': fee,
|
844
|
+
};
|
845
|
+
}
|
846
|
+
|
847
|
+
parseTransactionStatus (status) {
|
848
|
+
const statuses = {
|
849
|
+
'pending': 'pending',
|
850
|
+
'failed': 'failed',
|
851
|
+
'success': 'ok',
|
852
|
+
};
|
853
|
+
return this.safeString (statuses, status, status);
|
854
|
+
}
|
855
|
+
|
856
|
+
parseTransactionType (type) {
|
857
|
+
const types = {
|
858
|
+
'payin': 'deposit',
|
859
|
+
'payout': 'withdrawal',
|
860
|
+
'withdraw': 'withdrawal',
|
861
|
+
};
|
862
|
+
return this.safeString (types, type, type);
|
863
|
+
}
|
864
|
+
|
865
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
866
|
+
await this.loadMarkets ();
|
867
|
+
const market = this.market (symbol);
|
868
|
+
const request = {
|
869
|
+
'symbol': market['id'],
|
870
|
+
};
|
871
|
+
if (limit !== undefined) {
|
872
|
+
request['limit'] = limit;
|
873
|
+
}
|
874
|
+
if (since !== undefined) {
|
875
|
+
request['sort'] = 'ASC';
|
876
|
+
request['from'] = this.iso8601 (since);
|
877
|
+
}
|
878
|
+
const response = await this.publicGetTradesSymbol (this.extend (request, params));
|
879
|
+
return this.parseTrades (response, market, since, limit);
|
880
|
+
}
|
881
|
+
|
882
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
883
|
+
await this.loadMarkets ();
|
884
|
+
const market = this.market (symbol);
|
885
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
886
|
+
// because most of their endpoints will require clientOrderId
|
887
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
888
|
+
// their max accepted length is 32 characters
|
889
|
+
const uuid = this.uuid ();
|
890
|
+
const parts = uuid.split ('-');
|
891
|
+
let clientOrderId = parts.join ('');
|
892
|
+
clientOrderId = clientOrderId.slice (0, 32);
|
893
|
+
amount = parseFloat (amount);
|
894
|
+
const request = {
|
895
|
+
'clientOrderId': clientOrderId,
|
896
|
+
'symbol': market['id'],
|
897
|
+
'side': side,
|
898
|
+
'quantity': this.amountToPrecision (symbol, amount),
|
899
|
+
'type': type,
|
900
|
+
};
|
901
|
+
if (type === 'limit') {
|
902
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
903
|
+
} else {
|
904
|
+
request['timeInForce'] = this.options['defaultTimeInForce'];
|
905
|
+
}
|
906
|
+
const response = await this.privatePostOrder (this.extend (request, params));
|
907
|
+
const order = this.parseOrder (response);
|
908
|
+
if (order['status'] === 'rejected') {
|
909
|
+
throw new InvalidOrder (this.id + ' order was rejected by the exchange ' + this.json (order));
|
910
|
+
}
|
911
|
+
return order;
|
912
|
+
}
|
913
|
+
|
914
|
+
async editOrder (id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
|
915
|
+
await this.loadMarkets ();
|
916
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
917
|
+
// because most of their endpoints will require clientOrderId
|
918
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
919
|
+
// their max accepted length is 32 characters
|
920
|
+
const uuid = this.uuid ();
|
921
|
+
const parts = uuid.split ('-');
|
922
|
+
let requestClientId = parts.join ('');
|
923
|
+
requestClientId = requestClientId.slice (0, 32);
|
924
|
+
const request = {
|
925
|
+
'clientOrderId': id,
|
926
|
+
'requestClientId': requestClientId,
|
927
|
+
};
|
928
|
+
if (amount !== undefined) {
|
929
|
+
request['quantity'] = this.amountToPrecision (symbol, amount);
|
930
|
+
}
|
931
|
+
if (price !== undefined) {
|
932
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
933
|
+
}
|
934
|
+
const response = await this.privatePatchOrderClientOrderId (this.extend (request, params));
|
935
|
+
return this.parseOrder (response);
|
936
|
+
}
|
937
|
+
|
938
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
939
|
+
await this.loadMarkets ();
|
940
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
941
|
+
// because most of their endpoints will require clientOrderId
|
942
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
943
|
+
const request = {
|
944
|
+
'clientOrderId': id,
|
945
|
+
};
|
946
|
+
const response = await this.privateDeleteOrderClientOrderId (this.extend (request, params));
|
947
|
+
return this.parseOrder (response);
|
948
|
+
}
|
949
|
+
|
950
|
+
parseOrderStatus (status) {
|
951
|
+
const statuses = {
|
952
|
+
'new': 'open',
|
953
|
+
'suspended': 'open',
|
954
|
+
'partiallyFilled': 'open',
|
955
|
+
'filled': 'closed',
|
956
|
+
'canceled': 'canceled',
|
957
|
+
'expired': 'failed',
|
958
|
+
};
|
959
|
+
return this.safeString (statuses, status, status);
|
960
|
+
}
|
961
|
+
|
962
|
+
parseOrder (order, market = undefined) {
|
963
|
+
//
|
964
|
+
// createMarketOrder
|
965
|
+
//
|
966
|
+
// {
|
967
|
+
// clientOrderId: "fe36aa5e190149bf9985fb673bbb2ea0",
|
968
|
+
// createdAt: "2018-10-25T16:41:44.780Z",
|
969
|
+
// cumQuantity: "1",
|
970
|
+
// id: "66799540063",
|
971
|
+
// quantity: "1",
|
972
|
+
// side: "sell",
|
973
|
+
// status: "filled",
|
974
|
+
// symbol: "XRPUSDT",
|
975
|
+
// timeInForce: "FOK",
|
976
|
+
// tradesReport: [
|
977
|
+
// {
|
978
|
+
// fee: "0.0004644",
|
979
|
+
// id: 386394956,
|
980
|
+
// price: "0.4644",
|
981
|
+
// quantity: "1",
|
982
|
+
// timestamp: "2018-10-25T16:41:44.780Z"
|
983
|
+
// }
|
984
|
+
// ],
|
985
|
+
// type: "market",
|
986
|
+
// updatedAt: "2018-10-25T16:41:44.780Z"
|
987
|
+
// }
|
988
|
+
//
|
989
|
+
// {
|
990
|
+
// "id": 119499457455,
|
991
|
+
// "clientOrderId": "87baab109d58401b9202fa0749cb8288",
|
992
|
+
// "symbol": "ETHUSD",
|
993
|
+
// "side": "buy",
|
994
|
+
// "status": "filled",
|
995
|
+
// "type": "market",
|
996
|
+
// "timeInForce": "FOK",
|
997
|
+
// "quantity": "0.0007",
|
998
|
+
// "price": "181.487",
|
999
|
+
// "avgPrice": "164.989",
|
1000
|
+
// "cumQuantity": "0.0007",
|
1001
|
+
// "createdAt": "2019-04-17T13:27:38.062Z",
|
1002
|
+
// "updatedAt": "2019-04-17T13:27:38.062Z"
|
1003
|
+
// }
|
1004
|
+
//
|
1005
|
+
const created = this.parse8601 (this.safeString (order, 'createdAt'));
|
1006
|
+
const updated = this.parse8601 (this.safeString (order, 'updatedAt'));
|
1007
|
+
const marketId = this.safeString (order, 'symbol');
|
1008
|
+
market = this.safeMarket (marketId, market);
|
1009
|
+
const symbol = market['symbol'];
|
1010
|
+
const amount = this.safeString (order, 'quantity');
|
1011
|
+
const filled = this.safeString (order, 'cumQuantity');
|
1012
|
+
const status = this.parseOrderStatus (this.safeString (order, 'status'));
|
1013
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
1014
|
+
// because most of their endpoints will require clientOrderId
|
1015
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
1016
|
+
const id = this.safeString (order, 'clientOrderId');
|
1017
|
+
const clientOrderId = id;
|
1018
|
+
const price = this.safeString (order, 'price');
|
1019
|
+
const type = this.safeString (order, 'type');
|
1020
|
+
const side = this.safeString (order, 'side');
|
1021
|
+
const trades = this.safeValue (order, 'tradesReport');
|
1022
|
+
const fee = undefined;
|
1023
|
+
const average = this.safeString (order, 'avgPrice');
|
1024
|
+
const timeInForce = this.safeString (order, 'timeInForce');
|
1025
|
+
return this.safeOrder ({
|
1026
|
+
'id': id,
|
1027
|
+
'clientOrderId': clientOrderId, // https://github.com/ccxt/ccxt/issues/5674
|
1028
|
+
'timestamp': created,
|
1029
|
+
'datetime': this.iso8601 (created),
|
1030
|
+
'lastTradeTimestamp': updated,
|
1031
|
+
'status': status,
|
1032
|
+
'symbol': symbol,
|
1033
|
+
'type': type,
|
1034
|
+
'timeInForce': timeInForce,
|
1035
|
+
'side': side,
|
1036
|
+
'price': price,
|
1037
|
+
'stopPrice': undefined,
|
1038
|
+
'average': average,
|
1039
|
+
'amount': amount,
|
1040
|
+
'cost': undefined,
|
1041
|
+
'filled': filled,
|
1042
|
+
'remaining': undefined,
|
1043
|
+
'fee': fee,
|
1044
|
+
'trades': trades,
|
1045
|
+
'info': order,
|
1046
|
+
}, market);
|
1047
|
+
}
|
1048
|
+
|
1049
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
1050
|
+
await this.loadMarkets ();
|
1051
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
1052
|
+
// because most of their endpoints will require clientOrderId
|
1053
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
1054
|
+
const request = {
|
1055
|
+
'clientOrderId': id,
|
1056
|
+
};
|
1057
|
+
const response = await this.privateGetHistoryOrder (this.extend (request, params));
|
1058
|
+
const numOrders = response.length;
|
1059
|
+
if (numOrders > 0) {
|
1060
|
+
return this.parseOrder (response[0]);
|
1061
|
+
}
|
1062
|
+
throw new OrderNotFound (this.id + ' order ' + id + ' not found');
|
1063
|
+
}
|
1064
|
+
|
1065
|
+
async fetchOpenOrder (id, symbol = undefined, params = {}) {
|
1066
|
+
await this.loadMarkets ();
|
1067
|
+
// we use clientOrderId as the order id with this exchange intentionally
|
1068
|
+
// because most of their endpoints will require clientOrderId
|
1069
|
+
// explained here: https://github.com/ccxt/ccxt/issues/5674
|
1070
|
+
const request = {
|
1071
|
+
'clientOrderId': id,
|
1072
|
+
};
|
1073
|
+
const response = await this.privateGetOrderClientOrderId (this.extend (request, params));
|
1074
|
+
return this.parseOrder (response);
|
1075
|
+
}
|
1076
|
+
|
1077
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1078
|
+
await this.loadMarkets ();
|
1079
|
+
let market = undefined;
|
1080
|
+
const request = {};
|
1081
|
+
if (symbol !== undefined) {
|
1082
|
+
market = this.market (symbol);
|
1083
|
+
request['symbol'] = market['id'];
|
1084
|
+
}
|
1085
|
+
const response = await this.privateGetOrder (this.extend (request, params));
|
1086
|
+
return this.parseOrders (response, market, since, limit);
|
1087
|
+
}
|
1088
|
+
|
1089
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1090
|
+
await this.loadMarkets ();
|
1091
|
+
let market = undefined;
|
1092
|
+
const request = {};
|
1093
|
+
if (symbol !== undefined) {
|
1094
|
+
market = this.market (symbol);
|
1095
|
+
request['symbol'] = market['id'];
|
1096
|
+
}
|
1097
|
+
if (limit !== undefined) {
|
1098
|
+
request['limit'] = limit;
|
1099
|
+
}
|
1100
|
+
if (since !== undefined) {
|
1101
|
+
request['from'] = this.iso8601 (since);
|
1102
|
+
}
|
1103
|
+
const response = await this.privateGetHistoryOrder (this.extend (request, params));
|
1104
|
+
const parsedOrders = this.parseOrders (response, market);
|
1105
|
+
const orders = [];
|
1106
|
+
for (let i = 0; i < parsedOrders.length; i++) {
|
1107
|
+
const order = parsedOrders[i];
|
1108
|
+
const status = order['status'];
|
1109
|
+
if ((status === 'closed') || (status === 'canceled')) {
|
1110
|
+
orders.push (order);
|
1111
|
+
}
|
1112
|
+
}
|
1113
|
+
return this.filterBySinceLimit (orders, since, limit);
|
1114
|
+
}
|
1115
|
+
|
1116
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1117
|
+
await this.loadMarkets ();
|
1118
|
+
const request = {
|
1119
|
+
// 'symbol': 'BTC/USD', // optional
|
1120
|
+
// 'sort': 'DESC', // or 'ASC'
|
1121
|
+
// 'by': 'timestamp', // or 'id' String timestamp by default, or id
|
1122
|
+
// 'from': 'Datetime or Number', // ISO 8601
|
1123
|
+
// 'till': 'Datetime or Number',
|
1124
|
+
// 'limit': 100,
|
1125
|
+
// 'offset': 0,
|
1126
|
+
};
|
1127
|
+
let market = undefined;
|
1128
|
+
if (symbol !== undefined) {
|
1129
|
+
market = this.market (symbol);
|
1130
|
+
request['symbol'] = market['id'];
|
1131
|
+
}
|
1132
|
+
if (since !== undefined) {
|
1133
|
+
request['from'] = this.iso8601 (since);
|
1134
|
+
}
|
1135
|
+
if (limit !== undefined) {
|
1136
|
+
request['limit'] = limit;
|
1137
|
+
}
|
1138
|
+
const response = await this.privateGetHistoryTrades (this.extend (request, params));
|
1139
|
+
//
|
1140
|
+
// [
|
1141
|
+
// {
|
1142
|
+
// "id": 9535486,
|
1143
|
+
// "clientOrderId": "f8dbaab336d44d5ba3ff578098a68454",
|
1144
|
+
// "orderId": 816088377,
|
1145
|
+
// "symbol": "ETHBTC",
|
1146
|
+
// "side": "sell",
|
1147
|
+
// "quantity": "0.061",
|
1148
|
+
// "price": "0.045487",
|
1149
|
+
// "fee": "0.000002775",
|
1150
|
+
// "timestamp": "2017-05-17T12:32:57.848Z"
|
1151
|
+
// },
|
1152
|
+
// {
|
1153
|
+
// "id": 9535437,
|
1154
|
+
// "clientOrderId": "27b9bfc068b44194b1f453c7af511ed6",
|
1155
|
+
// "orderId": 816088021,
|
1156
|
+
// "symbol": "ETHBTC",
|
1157
|
+
// "side": "buy",
|
1158
|
+
// "quantity": "0.038",
|
1159
|
+
// "price": "0.046000",
|
1160
|
+
// "fee": "-0.000000174",
|
1161
|
+
// "timestamp": "2017-05-17T12:30:57.848Z"
|
1162
|
+
// }
|
1163
|
+
// ]
|
1164
|
+
//
|
1165
|
+
return this.parseTrades (response, market, since, limit);
|
1166
|
+
}
|
1167
|
+
|
1168
|
+
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1169
|
+
// The id needed here is the exchange's id, and not the clientOrderID,
|
1170
|
+
// which is the id that is stored in the unified order id
|
1171
|
+
// To get the exchange's id you need to grab it from order['info']['id']
|
1172
|
+
await this.loadMarkets ();
|
1173
|
+
let market = undefined;
|
1174
|
+
if (symbol !== undefined) {
|
1175
|
+
market = this.market (symbol);
|
1176
|
+
}
|
1177
|
+
const request = {
|
1178
|
+
'orderId': id,
|
1179
|
+
};
|
1180
|
+
const response = await this.privateGetHistoryOrderOrderIdTrades (this.extend (request, params));
|
1181
|
+
const numOrders = response.length;
|
1182
|
+
if (numOrders > 0) {
|
1183
|
+
return this.parseTrades (response, market, since, limit);
|
1184
|
+
}
|
1185
|
+
throw new OrderNotFound (this.id + ' order ' + id + ' not found, ' + this.id + '.fetchOrderTrades() requires an exchange-specific order id, you need to grab it from order["info"]["id"]');
|
1186
|
+
}
|
1187
|
+
|
1188
|
+
async createDepositAddress (code, params = {}) {
|
1189
|
+
await this.loadMarkets ();
|
1190
|
+
const currency = this.currency (code);
|
1191
|
+
const request = {
|
1192
|
+
'currency': currency['id'],
|
1193
|
+
};
|
1194
|
+
const response = await this.privatePostAccountCryptoAddressCurrency (this.extend (request, params));
|
1195
|
+
const address = this.safeString (response, 'address');
|
1196
|
+
this.checkAddress (address);
|
1197
|
+
const tag = this.safeString (response, 'paymentId');
|
1198
|
+
return {
|
1199
|
+
'currency': currency,
|
1200
|
+
'address': address,
|
1201
|
+
'tag': tag,
|
1202
|
+
'info': response,
|
1203
|
+
};
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
async fetchDepositAddress (code, params = {}) {
|
1207
|
+
await this.loadMarkets ();
|
1208
|
+
const currency = this.currency (code);
|
1209
|
+
const request = {
|
1210
|
+
'currency': currency['id'],
|
1211
|
+
};
|
1212
|
+
const network = this.safeString (params, 'network');
|
1213
|
+
if (network !== undefined) {
|
1214
|
+
params = this.omit (params, 'network');
|
1215
|
+
const networks = this.safeValue (this.options, 'networks');
|
1216
|
+
const endpart = this.safeString (networks, network, network);
|
1217
|
+
request['currency'] += endpart;
|
1218
|
+
}
|
1219
|
+
const response = await this.privateGetAccountCryptoAddressCurrency (this.extend (request, params));
|
1220
|
+
const address = this.safeString (response, 'address');
|
1221
|
+
this.checkAddress (address);
|
1222
|
+
const tag = this.safeString (response, 'paymentId');
|
1223
|
+
return {
|
1224
|
+
'currency': currency['code'],
|
1225
|
+
'address': address,
|
1226
|
+
'tag': tag,
|
1227
|
+
'network': undefined,
|
1228
|
+
'info': response,
|
1229
|
+
};
|
1230
|
+
}
|
1231
|
+
|
1232
|
+
async convertCurrencyNetwork (code, amount, fromNetwork, toNetwork, params) {
|
1233
|
+
await this.loadMarkets ();
|
1234
|
+
const currency = this.currency (code);
|
1235
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
1236
|
+
fromNetwork = this.safeString (networks, fromNetwork, fromNetwork); // handle ETH>ERC20 alias
|
1237
|
+
toNetwork = this.safeString (networks, toNetwork, toNetwork); // handle ETH>ERC20 alias
|
1238
|
+
if (fromNetwork === toNetwork) {
|
1239
|
+
throw new ExchangeError (this.id + ' convertCurrencyNetwork() fromNetwork cannot be the same as toNetwork');
|
1240
|
+
}
|
1241
|
+
const request = {
|
1242
|
+
'fromCurrency': currency['id'] + fromNetwork,
|
1243
|
+
'toCurrency': currency['id'] + toNetwork,
|
1244
|
+
'amount': parseFloat (this.currencyToPrecision (code, amount)),
|
1245
|
+
};
|
1246
|
+
const response = await this.privatePostAccountCryptoTransferConvert (this.extend (request, params));
|
1247
|
+
return {
|
1248
|
+
'info': response,
|
1249
|
+
};
|
1250
|
+
}
|
1251
|
+
|
1252
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
1253
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
1254
|
+
await this.loadMarkets ();
|
1255
|
+
this.checkAddress (address);
|
1256
|
+
const currency = this.currency (code);
|
1257
|
+
const request = {
|
1258
|
+
'currency': currency['id'],
|
1259
|
+
'amount': parseFloat (amount),
|
1260
|
+
'address': address,
|
1261
|
+
};
|
1262
|
+
if (tag) {
|
1263
|
+
request['paymentId'] = tag;
|
1264
|
+
}
|
1265
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
1266
|
+
let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
|
1267
|
+
network = this.safeString (networks, network, network); // handle ERC20>ETH alias
|
1268
|
+
if (network !== undefined) {
|
1269
|
+
request['currency'] += network; // when network the currency need to be changed to currency + network
|
1270
|
+
params = this.omit (params, 'network');
|
1271
|
+
}
|
1272
|
+
const response = await this.privatePostAccountCryptoWithdraw (this.extend (request, params));
|
1273
|
+
//
|
1274
|
+
// {
|
1275
|
+
// "id": "d2ce578f-647d-4fa0-b1aa-4a27e5ee597b"
|
1276
|
+
// }
|
1277
|
+
//
|
1278
|
+
return this.parseTransaction (response, currency);
|
1279
|
+
}
|
1280
|
+
|
1281
|
+
nonce () {
|
1282
|
+
return this.milliseconds ();
|
1283
|
+
}
|
1284
|
+
|
1285
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1286
|
+
let url = '/api/' + this.version + '/';
|
1287
|
+
const query = this.omit (params, this.extractParams (path));
|
1288
|
+
if (api === 'public') {
|
1289
|
+
url += api + '/' + this.implodeParams (path, params);
|
1290
|
+
if (Object.keys (query).length) {
|
1291
|
+
url += '?' + this.urlencode (query);
|
1292
|
+
}
|
1293
|
+
} else {
|
1294
|
+
this.checkRequiredCredentials ();
|
1295
|
+
url += this.implodeParams (path, params);
|
1296
|
+
if (method === 'GET') {
|
1297
|
+
if (Object.keys (query).length) {
|
1298
|
+
url += '?' + this.urlencode (query);
|
1299
|
+
}
|
1300
|
+
} else if (Object.keys (query).length) {
|
1301
|
+
body = this.json (query);
|
1302
|
+
}
|
1303
|
+
const payload = this.encode (this.apiKey + ':' + this.secret);
|
1304
|
+
const auth = this.stringToBase64 (payload);
|
1305
|
+
headers = {
|
1306
|
+
'Authorization': 'Basic ' + this.decode (auth),
|
1307
|
+
'Content-Type': 'application/json',
|
1308
|
+
};
|
1309
|
+
}
|
1310
|
+
url = this.urls['api'][api] + url;
|
1311
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1312
|
+
}
|
1313
|
+
|
1314
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
1315
|
+
if (response === undefined) {
|
1316
|
+
return;
|
1317
|
+
}
|
1318
|
+
if (code >= 400) {
|
1319
|
+
const feedback = this.id + ' ' + body;
|
1320
|
+
// {"code":504,"message":"Gateway Timeout","description":""}
|
1321
|
+
if ((code === 503) || (code === 504)) {
|
1322
|
+
throw new ExchangeNotAvailable (feedback);
|
1323
|
+
}
|
1324
|
+
// fallback to default error handler on rate limit errors
|
1325
|
+
// {"code":429,"message":"Too many requests","description":"Too many requests"}
|
1326
|
+
if (code === 429) {
|
1327
|
+
return;
|
1328
|
+
}
|
1329
|
+
// {"error":{"code":20002,"message":"Order not found","description":""}}
|
1330
|
+
if (body[0] === '{') {
|
1331
|
+
if ('error' in response) {
|
1332
|
+
const errorCode = this.safeString (response['error'], 'code');
|
1333
|
+
this.throwExactlyMatchedException (this.exceptions, errorCode, feedback);
|
1334
|
+
const message = this.safeString (response['error'], 'message');
|
1335
|
+
if (message === 'Duplicate clientOrderId') {
|
1336
|
+
throw new InvalidOrder (feedback);
|
1337
|
+
}
|
1338
|
+
}
|
1339
|
+
}
|
1340
|
+
throw new ExchangeError (feedback);
|
1341
|
+
}
|
1342
|
+
}
|
1343
|
+
};
|