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/woo.js
ADDED
@@ -0,0 +1,1577 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { ArgumentsRequired, AuthenticationError, RateLimitExceeded, BadRequest, ExchangeError, InvalidOrder } = require ('./base/errors');
|
7
|
+
const Precise = require ('./base/Precise');
|
8
|
+
const { TICK_SIZE } = require ('./base/functions/number');
|
9
|
+
|
10
|
+
// ---------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = class woo extends Exchange {
|
13
|
+
describe () {
|
14
|
+
return this.deepExtend (super.describe (), {
|
15
|
+
'id': 'woo',
|
16
|
+
'name': 'WOO X',
|
17
|
+
'countries': [ 'KY' ], // Cayman Islands
|
18
|
+
'rateLimit': 100,
|
19
|
+
'version': 'v1',
|
20
|
+
'certified': false,
|
21
|
+
'hostname': 'woo.org',
|
22
|
+
'has': {
|
23
|
+
'CORS': undefined,
|
24
|
+
'spot': true,
|
25
|
+
'margin': true,
|
26
|
+
'swap': false,
|
27
|
+
'future': false,
|
28
|
+
'option': false,
|
29
|
+
'cancelAllOrders': false,
|
30
|
+
'cancelOrder': true,
|
31
|
+
'cancelOrders': true,
|
32
|
+
'cancelWithdraw': false, // exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://kronosresearch.github.io/wootrade-documents/#cancel-withdraw-request
|
33
|
+
'createMarketOrder': false,
|
34
|
+
'createOrder': true,
|
35
|
+
'fetchBalance': true,
|
36
|
+
'fetchCanceledOrders': false,
|
37
|
+
'fetchClosedOrder': false,
|
38
|
+
'fetchClosedOrders': false,
|
39
|
+
'fetchCurrencies': true,
|
40
|
+
'fetchDepositAddress': false,
|
41
|
+
'fetchDeposits': true,
|
42
|
+
'fetchFundingHistory': false,
|
43
|
+
'fetchFundingRate': false,
|
44
|
+
'fetchFundingRateHistory': false,
|
45
|
+
'fetchFundingRates': false,
|
46
|
+
'fetchIndexOHLCV': false,
|
47
|
+
'fetchLedger': true,
|
48
|
+
'fetchMarkets': true,
|
49
|
+
'fetchMarkOHLCV': false,
|
50
|
+
'fetchMyTrades': true,
|
51
|
+
'fetchOHLCV': true,
|
52
|
+
'fetchOpenOrder': false,
|
53
|
+
'fetchOpenOrders': false,
|
54
|
+
'fetchOrder': true,
|
55
|
+
'fetchOrderBook': true,
|
56
|
+
'fetchOrders': true,
|
57
|
+
'fetchOrderTrades': true,
|
58
|
+
'fetchPremiumIndexOHLCV': false,
|
59
|
+
'fetchStatus': false,
|
60
|
+
'fetchTicker': false,
|
61
|
+
'fetchTickers': false,
|
62
|
+
'fetchTime': false,
|
63
|
+
'fetchTrades': true,
|
64
|
+
'fetchTradingFee': false,
|
65
|
+
'fetchTradingFees': true,
|
66
|
+
'fetchTransactions': true,
|
67
|
+
'fetchTransfers': true,
|
68
|
+
'fetchWithdrawals': true,
|
69
|
+
'transfer': true,
|
70
|
+
'withdraw': false, // exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://kronosresearch.github.io/wootrade-documents/#token-withdraw
|
71
|
+
},
|
72
|
+
'timeframes': {
|
73
|
+
'1m': '1m',
|
74
|
+
'5m': '5m',
|
75
|
+
'15m': '15m',
|
76
|
+
'30m': '30m',
|
77
|
+
'1h': '1h',
|
78
|
+
'4h': '4h',
|
79
|
+
'12h': '12h',
|
80
|
+
'1d': '1d',
|
81
|
+
'1w': '1w',
|
82
|
+
'1M': '1mon',
|
83
|
+
'1y': '1y',
|
84
|
+
},
|
85
|
+
'urls': {
|
86
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/150730761-1a00e5e0-d28c-480f-9e65-089ce3e6ef3b.jpg',
|
87
|
+
'api': {
|
88
|
+
'public': 'https://api.{hostname}',
|
89
|
+
'private': 'https://api.{hostname}',
|
90
|
+
},
|
91
|
+
// TEST (stating) api ( https://support.woo.org/hc/en-001/articles/4406352945305--Institutional-Account-Welcome-Packet-V-2) doesn't work at this moment, even thou
|
92
|
+
// 'test': {
|
93
|
+
// 'public': 'http://api.staging.woo.org',
|
94
|
+
// 'private': 'http://api.staging.woo.org',
|
95
|
+
// },
|
96
|
+
'www': 'https://woo.org/',
|
97
|
+
'doc': [
|
98
|
+
'https://docs.woo.org/',
|
99
|
+
],
|
100
|
+
'fees': [
|
101
|
+
'https://support.woo.org/hc/en-001/articles/4404611795353--Trading-Fees',
|
102
|
+
],
|
103
|
+
'referral': 'https://referral.woo.org/BAJS6oNmZb3vi3RGA',
|
104
|
+
},
|
105
|
+
'api': {
|
106
|
+
'v1': {
|
107
|
+
'public': {
|
108
|
+
'get': {
|
109
|
+
'info': 1,
|
110
|
+
'info/{symbol}': 1,
|
111
|
+
'market_trades': 1,
|
112
|
+
'token': 1,
|
113
|
+
'token_network': 1,
|
114
|
+
},
|
115
|
+
},
|
116
|
+
'private': {
|
117
|
+
'get': {
|
118
|
+
'client/token': 1,
|
119
|
+
'order/{oid}': 1,
|
120
|
+
'client/order/{client_order_id}': 1,
|
121
|
+
'orders': 1,
|
122
|
+
'orderbook/{symbol}': 1,
|
123
|
+
'kline': 1,
|
124
|
+
'client/trade/{tid}': 1,
|
125
|
+
'order/{oid}/trades': 1,
|
126
|
+
'client/trades': 1,
|
127
|
+
'client/info': 60,
|
128
|
+
'asset/deposit': 120,
|
129
|
+
'asset/history': 60,
|
130
|
+
'token_interest': 60,
|
131
|
+
'token_interest/{token}': 60,
|
132
|
+
'interest/history': 60,
|
133
|
+
'interest/repay': 60,
|
134
|
+
},
|
135
|
+
'post': {
|
136
|
+
'order': 5, // 2 requests per 1 second per symbol
|
137
|
+
'asset/main_sub_transfer': 30, // 20 requests per 60 seconds
|
138
|
+
'asset/withdraw': 120, // implemented in ccxt, disabled on the exchange side https://kronosresearch.github.io/wootrade-documents/#token-withdraw
|
139
|
+
},
|
140
|
+
'delete': {
|
141
|
+
'order': 1,
|
142
|
+
'client/order': 1,
|
143
|
+
'orders': 1,
|
144
|
+
'asset/withdraw': 120, // implemented in ccxt, disabled on the exchange side https://kronosresearch.github.io/wootrade-documents/#cancel-withdraw-request
|
145
|
+
},
|
146
|
+
},
|
147
|
+
},
|
148
|
+
'v2': {
|
149
|
+
'private': {
|
150
|
+
'get': {
|
151
|
+
'client/holding': 1,
|
152
|
+
},
|
153
|
+
},
|
154
|
+
},
|
155
|
+
},
|
156
|
+
'fees': {
|
157
|
+
'trading': {
|
158
|
+
'tierBased': true,
|
159
|
+
'percentage': true,
|
160
|
+
'maker': this.parseNumber ('0.0002'),
|
161
|
+
'taker': this.parseNumber ('0.0005'),
|
162
|
+
},
|
163
|
+
},
|
164
|
+
'options': {
|
165
|
+
'createMarketBuyOrderRequiresPrice': true,
|
166
|
+
'network-aliases': {
|
167
|
+
'ALGO': 'ALGO',
|
168
|
+
'ATOM': 'ATOM',
|
169
|
+
'AVAXC': 'AVAXC',
|
170
|
+
'BNB': 'BEP2',
|
171
|
+
'BSC': 'BEP20',
|
172
|
+
'BTC': 'BTC',
|
173
|
+
'BCHSV': 'BSV',
|
174
|
+
'EOS': 'EOS',
|
175
|
+
'ETH': 'ERC20',
|
176
|
+
'HECO': 'HRC20',
|
177
|
+
'MATIC': 'POLYGON',
|
178
|
+
'ONT': 'ONT',
|
179
|
+
'SOL': 'SPL',
|
180
|
+
'TERRA': 'TERRA',
|
181
|
+
'TRON': 'TRC20',
|
182
|
+
},
|
183
|
+
// network-aliases for titles are removed (just in case, if needed: pastebin.com/raw/BvgKViPN )
|
184
|
+
'network-aliases-for-protocol': {
|
185
|
+
'ALGO': 'ALGO',
|
186
|
+
'ATOM': 'ATOM',
|
187
|
+
'C Chain': 'AVAXC',
|
188
|
+
'BEP2': 'BEP2',
|
189
|
+
'BEP20': 'BEP20',
|
190
|
+
'BTC': 'BTC',
|
191
|
+
'BSV': 'BSV',
|
192
|
+
'EOS': 'EOS',
|
193
|
+
'ERC20': 'ERC20',
|
194
|
+
'HECO': 'HRC20',
|
195
|
+
'Polygon': 'POLYGON',
|
196
|
+
'ONT': 'ONT',
|
197
|
+
'SOL': 'SPL',
|
198
|
+
'TERRA': 'TERRA',
|
199
|
+
'TRON': 'TRC20',
|
200
|
+
},
|
201
|
+
// these network aliases require manual mapping here
|
202
|
+
'network-aliases-for-tokens': {
|
203
|
+
'HT': 'ERC20',
|
204
|
+
'OMG': 'ERC20',
|
205
|
+
'UATOM': 'ATOM',
|
206
|
+
'ZRX': 'ZRX',
|
207
|
+
},
|
208
|
+
'defaultNetworkCodePriorities': [
|
209
|
+
'TRC20',
|
210
|
+
'ERC20',
|
211
|
+
'BSC20',
|
212
|
+
],
|
213
|
+
// override defaultNetworkCodePriorities for a specific currency
|
214
|
+
'defaultNetworkCodeForCurrencies': {
|
215
|
+
// 'USDT': 'TRC20',
|
216
|
+
// 'BTC': 'BTC',
|
217
|
+
},
|
218
|
+
'transfer': {
|
219
|
+
'fillResponseFromRequest': true,
|
220
|
+
},
|
221
|
+
},
|
222
|
+
'commonCurrencies': {},
|
223
|
+
'exceptions': {
|
224
|
+
'exact': {
|
225
|
+
'-1000': ExchangeError, // { "code": -1000, "message": "An unknown error occurred while processing the request" }
|
226
|
+
'-1001': AuthenticationError, // { "code": -1001, "message": "The api key or secret is in wrong format" }
|
227
|
+
'-1002': AuthenticationError, // { "code": -1002, "message": "API key or secret is invalid, it may because key have insufficient permission or the key is expired/revoked." }
|
228
|
+
'-1003': RateLimitExceeded, // { "code": -1003, "message": "Rate limit exceed." }
|
229
|
+
'-1004': BadRequest, // { "code": -1004, "message": "An unknown parameter was sent." }
|
230
|
+
'-1005': BadRequest, // { "code": -1005, "message": "Some parameters are in wrong format for api." }
|
231
|
+
'-1006': BadRequest, // { "code": -1006, "message": "The data is not found in server." }
|
232
|
+
'-1007': BadRequest, // { "code": -1007, "message": "The data is already exists or your request is duplicated." }
|
233
|
+
'-1008': InvalidOrder, // { "code": -1008, "message": "The quantity of settlement is too high than you can request." }
|
234
|
+
'-1009': BadRequest, // { "code": -1009, "message": "Can not request withdrawal settlement, you need to deposit other arrears first." }
|
235
|
+
'-1011': ExchangeError, // { "code": -1011, "message": "Can not place/cancel orders, it may because internal network error. Please try again in a few seconds." }
|
236
|
+
'-1012': BadRequest, // { "code": -1012, "message": "Amount is required for buy market orders when margin disabled."} The place/cancel order request is rejected by internal module, it may because the account is in liquidation or other internal errors. Please try again in a few seconds." }
|
237
|
+
'-1101': InvalidOrder, // { "code": -1101, "message": "The risk exposure for client is too high, it may cause by sending too big order or the leverage is too low. please refer to client info to check the current exposure." }
|
238
|
+
'-1102': InvalidOrder, // { "code": -1102, "message": "The order value (price * size) is too small." }
|
239
|
+
'-1103': InvalidOrder, // { "code": -1103, "message": "The order price is not following the tick size rule for the symbol." }
|
240
|
+
'-1104': InvalidOrder, // { "code": -1104, "message": "The order quantity is not following the step size rule for the symbol." }
|
241
|
+
'-1105': InvalidOrder, // { "code": -1105, "message": "Price is X% too high or X% too low from the mid price." }
|
242
|
+
},
|
243
|
+
'broad': {
|
244
|
+
'symbol must not be blank': BadRequest, // when sending 'cancelOrder' without symbol [-1005]
|
245
|
+
'The token is not supported': BadRequest, // when getting incorrect token's deposit address [-1005]
|
246
|
+
'Your order and symbol are not valid or already canceled': BadRequest, // actual response whensending 'cancelOrder' for already canceled id [-1006]
|
247
|
+
'Insufficient WOO. Please enable margin trading for leverage trading': BadRequest, // when selling insufficent token [-1012]
|
248
|
+
},
|
249
|
+
},
|
250
|
+
'precisionMode': TICK_SIZE,
|
251
|
+
});
|
252
|
+
}
|
253
|
+
|
254
|
+
async fetchMarkets (params = {}) {
|
255
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchMarkets', undefined, params);
|
256
|
+
const method = this.getSupportedMapping (marketType, {
|
257
|
+
'spot': 'v1PublicGetInfo',
|
258
|
+
});
|
259
|
+
const response = await this[method] (query);
|
260
|
+
//
|
261
|
+
// {
|
262
|
+
// rows: [
|
263
|
+
// {
|
264
|
+
// symbol: "SPOT_AAVE_USDT",
|
265
|
+
// quote_min: 0,
|
266
|
+
// quote_max: 100000,
|
267
|
+
// quote_tick: 0.01,
|
268
|
+
// base_min: 0.01,
|
269
|
+
// base_max: 7284,
|
270
|
+
// base_tick: 0.0001,
|
271
|
+
// min_notional: 10,
|
272
|
+
// price_range: 0.1,
|
273
|
+
// created_time: "0",
|
274
|
+
// updated_time: "1639107647.988",
|
275
|
+
// is_stable: 0
|
276
|
+
// },
|
277
|
+
// ...
|
278
|
+
// success: true
|
279
|
+
// }
|
280
|
+
//
|
281
|
+
const data = this.safeValue (response, 'rows', []);
|
282
|
+
const result = [];
|
283
|
+
for (let i = 0; i < data.length; i++) {
|
284
|
+
const market = data[i];
|
285
|
+
const marketId = this.safeString (market, 'symbol');
|
286
|
+
const parts = marketId.split ('_');
|
287
|
+
const marketTypeVal = this.safeStringLower (parts, 0);
|
288
|
+
const isSpot = marketTypeVal === 'spot';
|
289
|
+
const isSwap = false;
|
290
|
+
const isFuture = false;
|
291
|
+
const isOption = false;
|
292
|
+
const baseId = this.safeString (parts, 1);
|
293
|
+
const quoteId = this.safeString (parts, 2);
|
294
|
+
const base = this.safeCurrencyCode (baseId);
|
295
|
+
const quote = this.safeCurrencyCode (quoteId);
|
296
|
+
const symbol = base + '/' + quote;
|
297
|
+
const minQuote = this.safeNumber (market, 'quote_min');
|
298
|
+
const maxQuote = this.safeNumber (market, 'quote_max');
|
299
|
+
const minBase = this.safeNumber (market, 'base_min');
|
300
|
+
const maxBase = this.safeNumber (market, 'base_max');
|
301
|
+
const priceScale = this.safeNumber (market, 'quote_tick');
|
302
|
+
const quantityScale = this.safeNumber (market, 'base_tick');
|
303
|
+
const minCost = this.safeNumber (market, 'min_notional');
|
304
|
+
result.push ({
|
305
|
+
'id': marketId,
|
306
|
+
'symbol': symbol,
|
307
|
+
'base': base,
|
308
|
+
'quote': quote,
|
309
|
+
'settle': undefined,
|
310
|
+
'baseId': baseId,
|
311
|
+
'quoteId': quoteId,
|
312
|
+
'settleId': undefined,
|
313
|
+
'type': marketTypeVal,
|
314
|
+
'spot': isSpot,
|
315
|
+
'margin': true,
|
316
|
+
'swap': false,
|
317
|
+
'future': false,
|
318
|
+
'option': false,
|
319
|
+
'active': undefined,
|
320
|
+
'contract': isSwap || isFuture || isOption,
|
321
|
+
'linear': undefined,
|
322
|
+
'inverse': undefined,
|
323
|
+
'contractSize': undefined,
|
324
|
+
'expiry': undefined,
|
325
|
+
'expiryDatetime': undefined,
|
326
|
+
'strike': undefined,
|
327
|
+
'optionType': undefined,
|
328
|
+
'precision': {
|
329
|
+
'amount': quantityScale,
|
330
|
+
'price': priceScale,
|
331
|
+
},
|
332
|
+
'limits': {
|
333
|
+
'leverage': {
|
334
|
+
'min': undefined,
|
335
|
+
'max': undefined,
|
336
|
+
},
|
337
|
+
'amount': {
|
338
|
+
'min': minBase,
|
339
|
+
'max': maxBase,
|
340
|
+
},
|
341
|
+
'price': {
|
342
|
+
'min': minQuote,
|
343
|
+
'max': maxQuote,
|
344
|
+
},
|
345
|
+
'cost': {
|
346
|
+
'min': minCost,
|
347
|
+
'max': undefined,
|
348
|
+
},
|
349
|
+
},
|
350
|
+
'info': market,
|
351
|
+
});
|
352
|
+
}
|
353
|
+
return result;
|
354
|
+
}
|
355
|
+
|
356
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
357
|
+
if (symbol === undefined) {
|
358
|
+
throw new ArgumentsRequired (this.id + ' fetchTrades() requires a symbol argument');
|
359
|
+
}
|
360
|
+
await this.loadMarkets ();
|
361
|
+
const market = this.market (symbol);
|
362
|
+
const request = {
|
363
|
+
'symbol': market['id'],
|
364
|
+
};
|
365
|
+
if (limit !== undefined) {
|
366
|
+
request['limit'] = limit;
|
367
|
+
}
|
368
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchTrades', market, params);
|
369
|
+
const method = this.getSupportedMapping (marketType, {
|
370
|
+
'spot': 'v1PublicGetMarketTrades',
|
371
|
+
});
|
372
|
+
const response = await this[method] (this.extend (request, query));
|
373
|
+
//
|
374
|
+
// {
|
375
|
+
// success: true,
|
376
|
+
// rows: [
|
377
|
+
// {
|
378
|
+
// symbol: "SPOT_BTC_USDT",
|
379
|
+
// side: "SELL",
|
380
|
+
// executed_price: 46222.35,
|
381
|
+
// executed_quantity: 0.0012,
|
382
|
+
// executed_timestamp: "1641241162.329"
|
383
|
+
// },
|
384
|
+
// {
|
385
|
+
// symbol: "SPOT_BTC_USDT",
|
386
|
+
// side: "SELL",
|
387
|
+
// executed_price: 46222.35,
|
388
|
+
// executed_quantity: 0.0012,
|
389
|
+
// executed_timestamp: "1641241162.329"
|
390
|
+
// },
|
391
|
+
// {
|
392
|
+
// symbol: "SPOT_BTC_USDT",
|
393
|
+
// side: "BUY",
|
394
|
+
// executed_price: 46224.32,
|
395
|
+
// executed_quantity: 0.00039,
|
396
|
+
// executed_timestamp: "1641241162.287"
|
397
|
+
// },
|
398
|
+
// ...
|
399
|
+
// ]
|
400
|
+
// }
|
401
|
+
//
|
402
|
+
const resultResponse = this.safeValue (response, 'rows', {});
|
403
|
+
return this.parseTrades (resultResponse, market, since, limit);
|
404
|
+
}
|
405
|
+
|
406
|
+
parseTrade (trade, market = undefined) {
|
407
|
+
//
|
408
|
+
// public/market_trades
|
409
|
+
//
|
410
|
+
// {
|
411
|
+
// symbol: "SPOT_BTC_USDT",
|
412
|
+
// side: "SELL",
|
413
|
+
// executed_price: 46222.35,
|
414
|
+
// executed_quantity: 0.0012,
|
415
|
+
// executed_timestamp: "1641241162.329"
|
416
|
+
// }
|
417
|
+
//
|
418
|
+
// fetchOrderTrades, fetchOrder
|
419
|
+
//
|
420
|
+
// {
|
421
|
+
// id: '99119876',
|
422
|
+
// symbol: 'SPOT_WOO_USDT',
|
423
|
+
// fee: '0.0024',
|
424
|
+
// side: 'BUY',
|
425
|
+
// executed_timestamp: '1641481113.084',
|
426
|
+
// order_id: '87001234',
|
427
|
+
// order_tag: 'default', <-- this param only in "fetchOrderTrades"
|
428
|
+
// executed_price: '1',
|
429
|
+
// executed_quantity: '12',
|
430
|
+
// fee_asset: 'WOO',
|
431
|
+
// is_maker: '1'
|
432
|
+
// }
|
433
|
+
//
|
434
|
+
const isFromFetchOrder = ('id' in trade);
|
435
|
+
const timestamp = this.safeTimestamp (trade, 'executed_timestamp');
|
436
|
+
const marketId = this.safeString (trade, 'symbol');
|
437
|
+
market = this.safeMarket (marketId, market);
|
438
|
+
const symbol = market['symbol'];
|
439
|
+
const price = this.safeString (trade, 'executed_price');
|
440
|
+
const amount = this.safeString (trade, 'executed_quantity');
|
441
|
+
const order_id = this.safeString (trade, 'order_id');
|
442
|
+
const fee = this.parseTokenAndFeeTemp (trade, 'fee_asset', 'fee');
|
443
|
+
const cost = Precise.stringMul (price, amount);
|
444
|
+
const side = this.safeStringLower (trade, 'side');
|
445
|
+
let id = this.safeString (trade, 'id');
|
446
|
+
if (id === undefined) { // reconstruct artificially, if it doesn't exist
|
447
|
+
if (timestamp !== undefined) {
|
448
|
+
const amountStr = (amount === undefined) ? '' : amount;
|
449
|
+
const sideStr = (side === undefined) ? '' : side;
|
450
|
+
const priceStr = (price === undefined) ? '' : price;
|
451
|
+
const marketIdStr = this.safeString (market, 'id', '');
|
452
|
+
id = this.numberToString (timestamp) + '-' + marketIdStr + '-' + sideStr + '-' + amountStr + '-' + priceStr;
|
453
|
+
}
|
454
|
+
}
|
455
|
+
let takerOrMaker = undefined;
|
456
|
+
if (isFromFetchOrder) {
|
457
|
+
const isMaker = this.safeString (trade, 'is_maker') === '1';
|
458
|
+
takerOrMaker = isMaker ? 'maker' : 'taker';
|
459
|
+
}
|
460
|
+
return this.safeTrade ({
|
461
|
+
'id': id,
|
462
|
+
'timestamp': timestamp,
|
463
|
+
'datetime': this.iso8601 (timestamp),
|
464
|
+
'symbol': symbol,
|
465
|
+
'side': side,
|
466
|
+
'price': price,
|
467
|
+
'amount': amount,
|
468
|
+
'cost': cost,
|
469
|
+
'order': order_id,
|
470
|
+
'takerOrMaker': takerOrMaker,
|
471
|
+
'type': undefined,
|
472
|
+
'fee': fee,
|
473
|
+
'info': trade,
|
474
|
+
}, market);
|
475
|
+
}
|
476
|
+
|
477
|
+
parseTokenAndFeeTemp (item, feeTokenKey, feeAmountKey) {
|
478
|
+
const feeCost = this.safeString (item, feeAmountKey);
|
479
|
+
let fee = undefined;
|
480
|
+
if (feeCost !== undefined) {
|
481
|
+
const feeCurrencyId = this.safeString (item, feeTokenKey);
|
482
|
+
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
483
|
+
fee = {
|
484
|
+
'cost': feeCost,
|
485
|
+
'currency': feeCurrencyCode,
|
486
|
+
};
|
487
|
+
}
|
488
|
+
return fee;
|
489
|
+
}
|
490
|
+
|
491
|
+
async fetchTradingFees (params = {}) {
|
492
|
+
await this.loadMarkets ();
|
493
|
+
const response = await this.v1PrivateGetClientInfo (params);
|
494
|
+
//
|
495
|
+
// {
|
496
|
+
// "application":{
|
497
|
+
// "id":45585,
|
498
|
+
// "leverage":3.00,
|
499
|
+
// "otpauth":false,
|
500
|
+
// "alias":"email@address.com",
|
501
|
+
// "application_id":"c2cc4d74-c8cb-4e10-84db-af2089b8c68a",
|
502
|
+
// "account":"email@address.com",
|
503
|
+
// "account_mode":"PURE_SPOT",
|
504
|
+
// "taker_fee_rate":5.00,
|
505
|
+
// "maker_fee_rate":2.00,
|
506
|
+
// "interest_rate":0.00,
|
507
|
+
// "futures_leverage":1.00,
|
508
|
+
// "futures_taker_fee_rate":5.00,
|
509
|
+
// "futures_maker_fee_rate":2.00
|
510
|
+
// },
|
511
|
+
// "margin_rate":1000,
|
512
|
+
// "success":true
|
513
|
+
// }
|
514
|
+
//
|
515
|
+
const application = this.safeValue (response, 'application', {});
|
516
|
+
const maker = this.safeString (application, 'maker_fee_rate');
|
517
|
+
const taker = this.safeString (application, 'taker_fee_rate');
|
518
|
+
const result = {};
|
519
|
+
for (let i = 0; i < this.symbols.length; i++) {
|
520
|
+
const symbol = this.symbols[i];
|
521
|
+
result[symbol] = {
|
522
|
+
'info': response,
|
523
|
+
'symbol': symbol,
|
524
|
+
'maker': this.parseNumber (Precise.stringDiv (maker, '10000')),
|
525
|
+
'taker': this.parseNumber (Precise.stringDiv (taker, '10000')),
|
526
|
+
'percentage': true,
|
527
|
+
'tierBased': true,
|
528
|
+
};
|
529
|
+
}
|
530
|
+
return result;
|
531
|
+
}
|
532
|
+
|
533
|
+
async fetchCurrencies (params = {}) {
|
534
|
+
let method = undefined;
|
535
|
+
const result = {};
|
536
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchCurrencies', undefined, params);
|
537
|
+
method = this.getSupportedMapping (marketType, {
|
538
|
+
'spot': 'v1PublicGetToken',
|
539
|
+
});
|
540
|
+
const tokenResponse = await this[method] (query);
|
541
|
+
//
|
542
|
+
// {
|
543
|
+
// rows: [
|
544
|
+
// {
|
545
|
+
// token: "ETH_USDT",
|
546
|
+
// fullname: "Tether",
|
547
|
+
// decimals: 6,
|
548
|
+
// balance_token: "USDT",
|
549
|
+
// created_time: "0",
|
550
|
+
// updated_time: "0"
|
551
|
+
// },
|
552
|
+
// {
|
553
|
+
// token: "BSC_USDT",
|
554
|
+
// fullname: "Tether",
|
555
|
+
// decimals: 18,
|
556
|
+
// balance_token: "USDT",
|
557
|
+
// created_time: "0",
|
558
|
+
// updated_time: "0"
|
559
|
+
// },
|
560
|
+
// {
|
561
|
+
// token: "ZEC",
|
562
|
+
// fullname: "ZCash",
|
563
|
+
// decimals: 8,
|
564
|
+
// balance_token: "ZEC",
|
565
|
+
// created_time: "0",
|
566
|
+
// updated_time: "0"
|
567
|
+
// },
|
568
|
+
// ...
|
569
|
+
// ],
|
570
|
+
// success: true
|
571
|
+
// }
|
572
|
+
//
|
573
|
+
method = this.getSupportedMapping (marketType, {
|
574
|
+
'spot': 'v1PublicGetTokenNetwork',
|
575
|
+
});
|
576
|
+
const tokenNetworkResponse = await this[method] (query);
|
577
|
+
//
|
578
|
+
// {
|
579
|
+
// rows: [
|
580
|
+
// {
|
581
|
+
// protocol: "ERC20",
|
582
|
+
// token: "USDT",
|
583
|
+
// name: "Ethereum",
|
584
|
+
// minimum_withdrawal: 30,
|
585
|
+
// withdrawal_fee: 25,
|
586
|
+
// allow_deposit: 1,
|
587
|
+
// allow_withdraw: 1
|
588
|
+
// },
|
589
|
+
// {
|
590
|
+
// protocol: "TRC20",
|
591
|
+
// token: "USDT",
|
592
|
+
// name: "Tron",
|
593
|
+
// minimum_withdrawal: 30,
|
594
|
+
// withdrawal_fee: 1,
|
595
|
+
// allow_deposit: 1,
|
596
|
+
// allow_withdraw: 1
|
597
|
+
// },
|
598
|
+
// ...
|
599
|
+
// ],
|
600
|
+
// success: true
|
601
|
+
// }
|
602
|
+
//
|
603
|
+
const tokenRows = this.safeValue (tokenResponse, 'rows', []);
|
604
|
+
const tokenNetworkRows = this.safeValue (tokenNetworkResponse, 'rows', []);
|
605
|
+
const networksByCurrencyId = this.groupBy (tokenNetworkRows, 'token');
|
606
|
+
for (let i = 0; i < tokenRows.length; i++) {
|
607
|
+
const currency = tokenRows[i];
|
608
|
+
const id = this.safeString (currency, 'balance_token');
|
609
|
+
const code = this.safeCurrencyCode (id);
|
610
|
+
const name = this.safeString (currency, 'fullname');
|
611
|
+
const decimals = this.safeInteger (currency, 'decimals');
|
612
|
+
const chainedTokenCode = this.safeString (currency, 'token');
|
613
|
+
const parts = chainedTokenCode.split ('_');
|
614
|
+
const chainNameId = this.safeString (parts, 0, chainedTokenCode);
|
615
|
+
const chainCode = this.safeString (this.options['network-aliases'], chainNameId, chainNameId);
|
616
|
+
if (!(code in result)) {
|
617
|
+
const networks = this.safeValue (networksByCurrencyId, id, []);
|
618
|
+
const resultingNetworks = {};
|
619
|
+
for (let j = 0; j < networks.length; j++) {
|
620
|
+
const networkEntry = networks[j];
|
621
|
+
const networkId = this.safeString (networkEntry, 'protocol');
|
622
|
+
const networkIdManualMatched = this.safeString (this.options['network-aliases-for-tokens'], networkId, networkId);
|
623
|
+
const networkCode = this.safeString2 (this.options['network-aliases-for-protocol'], chainNameId, chainNameId, networkIdManualMatched);
|
624
|
+
const depositEnabled = this.safeInteger (networkEntry, 'allow_deposit', 0);
|
625
|
+
const withdrawEnabled = this.safeInteger (networkEntry, 'allow_withdraw', 0);
|
626
|
+
resultingNetworks[networkCode] = {
|
627
|
+
'id': networkId,
|
628
|
+
'network': networkCode,
|
629
|
+
'limits': {
|
630
|
+
'withdraw': {
|
631
|
+
'min': this.safeNumber (networkEntry, 'minimum_withdrawal'),
|
632
|
+
'max': undefined,
|
633
|
+
},
|
634
|
+
'deposit': {
|
635
|
+
'min': undefined,
|
636
|
+
'max': undefined,
|
637
|
+
},
|
638
|
+
},
|
639
|
+
'active': undefined,
|
640
|
+
'deposit': depositEnabled,
|
641
|
+
'withdraw': withdrawEnabled,
|
642
|
+
'fee': this.safeNumber (networkEntry, 'withdrawal_fee'),
|
643
|
+
'precision': undefined, // will be filled down below
|
644
|
+
'info': networkEntry,
|
645
|
+
};
|
646
|
+
}
|
647
|
+
const networksKeys = Object.keys (resultingNetworks);
|
648
|
+
const firstNetworkKey = networksKeys[0];
|
649
|
+
const networkLength = networksKeys.length;
|
650
|
+
result[code] = {
|
651
|
+
'id': id,
|
652
|
+
'name': name,
|
653
|
+
'code': code,
|
654
|
+
'precision': (networkLength === 1) ? decimals : undefined, // will be filled down below
|
655
|
+
'active': undefined,
|
656
|
+
'fee': (networkLength === 1) ? resultingNetworks[firstNetworkKey]['fee'] : undefined,
|
657
|
+
'networks': resultingNetworks,
|
658
|
+
'limits': {
|
659
|
+
'deposit': {
|
660
|
+
'min': undefined,
|
661
|
+
'max': undefined,
|
662
|
+
},
|
663
|
+
'withdraw': {
|
664
|
+
'min': (networkLength === 1) ? resultingNetworks[firstNetworkKey]['limits']['withdraw']['min'] : undefined,
|
665
|
+
'max': undefined,
|
666
|
+
},
|
667
|
+
},
|
668
|
+
'info': {}, // will be filled down below
|
669
|
+
};
|
670
|
+
}
|
671
|
+
const networkKeys = Object.keys (result[code]['networks']);
|
672
|
+
const firstNetworkKey = this.safeString (networkKeys, 0);
|
673
|
+
// now add the precision info from token-object
|
674
|
+
if (chainCode in result[code]['networks']) {
|
675
|
+
result[code]['networks'][chainCode]['precision'] = decimals;
|
676
|
+
} else {
|
677
|
+
// else chainCode will be the only token slug, which has only 1 supported network
|
678
|
+
result[code]['networks'][firstNetworkKey]['precision'] = decimals;
|
679
|
+
}
|
680
|
+
// now add the info object specifically for the item
|
681
|
+
result[code]['info'][chainedTokenCode] = currency;
|
682
|
+
}
|
683
|
+
return result;
|
684
|
+
}
|
685
|
+
|
686
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
687
|
+
await this.loadMarkets ();
|
688
|
+
const market = this.market (symbol);
|
689
|
+
const request = {
|
690
|
+
'symbol': market['id'],
|
691
|
+
'order_type': type.toUpperCase (),
|
692
|
+
'side': side.toUpperCase (),
|
693
|
+
};
|
694
|
+
if (price !== undefined) {
|
695
|
+
request['order_price'] = this.priceToPrecision (symbol, price);
|
696
|
+
}
|
697
|
+
if (type === 'market') {
|
698
|
+
// for market buy it requires the amount of quote currency to spend
|
699
|
+
if (side === 'buy') {
|
700
|
+
const cost = this.safeNumber (params, 'cost');
|
701
|
+
if (this.safeValue (this.options, 'createMarketBuyOrderRequiresPrice', true)) {
|
702
|
+
if (cost === undefined) {
|
703
|
+
if (price === undefined) {
|
704
|
+
throw new InvalidOrder (this.id + " createOrder() requires the price argument for market buy orders to calculate total order cost. Supply a price argument to createOrder() call if you want the cost to be calculated for you from price and amount, or alternatively, supply the total cost value in the 'order_amount' in exchange-specific parameters");
|
705
|
+
} else {
|
706
|
+
request['order_amount'] = this.costToPrecision (symbol, amount * price);
|
707
|
+
}
|
708
|
+
} else {
|
709
|
+
request['order_amount'] = this.costToPrecision (symbol, cost);
|
710
|
+
}
|
711
|
+
}
|
712
|
+
} else {
|
713
|
+
request['order_quantity'] = this.amountToPrecision (symbol, amount);
|
714
|
+
}
|
715
|
+
} else {
|
716
|
+
request['order_quantity'] = this.amountToPrecision (symbol, amount);
|
717
|
+
}
|
718
|
+
const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
|
719
|
+
if (clientOrderId !== undefined) {
|
720
|
+
request['client_order_id'] = clientOrderId;
|
721
|
+
}
|
722
|
+
params = this.omit (params, [ 'clOrdID', 'clientOrderId' ]);
|
723
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('createOrder', market, params);
|
724
|
+
const method = this.getSupportedMapping (marketType, {
|
725
|
+
'spot': 'v1PrivatePostOrder',
|
726
|
+
});
|
727
|
+
const response = await this[method] (this.extend (request, query));
|
728
|
+
// {
|
729
|
+
// success: true,
|
730
|
+
// timestamp: '1641383206.489',
|
731
|
+
// order_id: '86980774',
|
732
|
+
// order_type: 'LIMIT',
|
733
|
+
// order_price: '1', // null for 'MARKET' order
|
734
|
+
// order_quantity: '12', // null for 'MARKET' order
|
735
|
+
// order_amount: null, // NOT-null for 'MARKET' order
|
736
|
+
// client_order_id: '0'
|
737
|
+
// }
|
738
|
+
return this.extend (
|
739
|
+
this.parseOrder (response, market),
|
740
|
+
{ 'type': type }
|
741
|
+
);
|
742
|
+
}
|
743
|
+
|
744
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
745
|
+
if (symbol === undefined) {
|
746
|
+
throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
|
747
|
+
}
|
748
|
+
await this.loadMarkets ();
|
749
|
+
const request = undefined;
|
750
|
+
const clientOrderIdUnified = this.safeString2 (params, 'clOrdID', 'clientOrderId');
|
751
|
+
const clientOrderIdExchangeSpecific = this.safeString2 (params, 'client_order_id', clientOrderIdUnified);
|
752
|
+
const isByClientOrder = clientOrderIdExchangeSpecific !== undefined;
|
753
|
+
if (isByClientOrder) {
|
754
|
+
request['client_order_id'] = clientOrderIdExchangeSpecific;
|
755
|
+
params = this.omit (params, [ 'clOrdID', 'clientOrderId', 'client_order_id' ]);
|
756
|
+
} else {
|
757
|
+
request['order_id'] = id;
|
758
|
+
}
|
759
|
+
let market = undefined;
|
760
|
+
if (symbol !== undefined) {
|
761
|
+
market = this.market (symbol);
|
762
|
+
}
|
763
|
+
request['symbol'] = market['id'];
|
764
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('cancelOrder', market, params);
|
765
|
+
const method = this.getSupportedMapping (marketType, {
|
766
|
+
'spot': 'v1PrivateDeleteOrder',
|
767
|
+
});
|
768
|
+
const response = await this[method] (this.extend (request, query));
|
769
|
+
//
|
770
|
+
// { success: true, status: 'CANCEL_SENT' }
|
771
|
+
//
|
772
|
+
const extendParams = { 'symbol': symbol };
|
773
|
+
if (isByClientOrder) {
|
774
|
+
extendParams['client_order_id'] = clientOrderIdExchangeSpecific;
|
775
|
+
} else {
|
776
|
+
extendParams['id'] = id;
|
777
|
+
}
|
778
|
+
return this.extend (this.parseOrder (response), extendParams);
|
779
|
+
}
|
780
|
+
|
781
|
+
async cancelOrders (ids, symbol = undefined, params = {}) {
|
782
|
+
if (symbol === undefined) {
|
783
|
+
throw new ArgumentsRequired (this.id + ' canelOrders() requires a symbol argument');
|
784
|
+
}
|
785
|
+
await this.loadMarkets ();
|
786
|
+
const market = this.market (symbol);
|
787
|
+
const request = {
|
788
|
+
'symbol': market['id'],
|
789
|
+
};
|
790
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('cancelOrders', market, params);
|
791
|
+
const method = this.getSupportedMapping (marketType, {
|
792
|
+
'spot': 'v1PrivateDeleteOrders',
|
793
|
+
});
|
794
|
+
const response = await this[method] (this.extend (request, query));
|
795
|
+
return response;
|
796
|
+
}
|
797
|
+
|
798
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
799
|
+
await this.loadMarkets ();
|
800
|
+
const market = (symbol !== undefined) ? this.market (symbol) : undefined;
|
801
|
+
const request = {};
|
802
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrder', market, params);
|
803
|
+
const clientOrderId = this.safeString2 (params, 'clOrdID', 'clientOrderId');
|
804
|
+
let chosenSpotMethod = undefined;
|
805
|
+
if (clientOrderId) {
|
806
|
+
chosenSpotMethod = 'v1PrivateGetClientOrderClientOrderId';
|
807
|
+
request['client_order_id'] = clientOrderId;
|
808
|
+
} else {
|
809
|
+
chosenSpotMethod = 'v1PrivateGetOrderOid';
|
810
|
+
request['oid'] = id;
|
811
|
+
}
|
812
|
+
const method = this.getSupportedMapping (marketType, {
|
813
|
+
'spot': chosenSpotMethod,
|
814
|
+
});
|
815
|
+
const response = await this[method] (this.extend (request, query));
|
816
|
+
//
|
817
|
+
// {
|
818
|
+
// success: true,
|
819
|
+
// symbol: 'SPOT_WOO_USDT',
|
820
|
+
// status: 'FILLED', // FILLED, NEW
|
821
|
+
// side: 'BUY',
|
822
|
+
// created_time: '1641480933.000',
|
823
|
+
// order_id: '87541111',
|
824
|
+
// order_tag: 'default',
|
825
|
+
// price: '1',
|
826
|
+
// type: 'LIMIT',
|
827
|
+
// quantity: '12',
|
828
|
+
// amount: null,
|
829
|
+
// visible: '12',
|
830
|
+
// executed: '12', // or any partial amount
|
831
|
+
// total_fee: '0.0024',
|
832
|
+
// fee_asset: 'WOO',
|
833
|
+
// client_order_id: null,
|
834
|
+
// average_executed_price: '1',
|
835
|
+
// Transactions: [
|
836
|
+
// {
|
837
|
+
// id: '99111647',
|
838
|
+
// symbol: 'SPOT_WOO_USDT',
|
839
|
+
// fee: '0.0024',
|
840
|
+
// side: 'BUY',
|
841
|
+
// executed_timestamp: '1641482113.084',
|
842
|
+
// order_id: '87541111',
|
843
|
+
// executed_price: '1',
|
844
|
+
// executed_quantity: '12',
|
845
|
+
// fee_asset: 'WOO',
|
846
|
+
// is_maker: '1'
|
847
|
+
// }
|
848
|
+
// ]
|
849
|
+
// }
|
850
|
+
//
|
851
|
+
return this.parseOrder (response);
|
852
|
+
}
|
853
|
+
|
854
|
+
async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
855
|
+
await this.loadMarkets ();
|
856
|
+
const request = {};
|
857
|
+
let market = undefined;
|
858
|
+
if (symbol !== undefined) {
|
859
|
+
market = this.market (symbol);
|
860
|
+
request['symbol'] = market['id'];
|
861
|
+
}
|
862
|
+
if (since !== undefined) {
|
863
|
+
request['start_t'] = since;
|
864
|
+
}
|
865
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrders', market, params);
|
866
|
+
const method = this.getSupportedMapping (marketType, {
|
867
|
+
'spot': 'v1PrivateGetOrders',
|
868
|
+
});
|
869
|
+
const response = await this[method] (this.extend (request, query));
|
870
|
+
const data = this.safeValue (response, 'rows');
|
871
|
+
return this.parseOrders (data, market, since, limit, params);
|
872
|
+
}
|
873
|
+
|
874
|
+
parseOrder (order, market = undefined) {
|
875
|
+
//
|
876
|
+
// Possible input functions:
|
877
|
+
// * createOrder
|
878
|
+
// * cancelOrder
|
879
|
+
// * fetchOrder
|
880
|
+
// * fetchOrders
|
881
|
+
// const isFromFetchOrder = ('order_tag' in order); TO_DO
|
882
|
+
const timestamp = this.safeTimestamp2 (order, 'timestamp', 'created_time');
|
883
|
+
const orderId = this.safeInteger (order, 'order_id');
|
884
|
+
const clientOrderId = this.safeTimestamp (order, 'client_order_id'); // Somehow, this always returns 0 for limit order
|
885
|
+
const marketId = this.safeString (order, 'symbol');
|
886
|
+
market = this.safeMarket (marketId, market);
|
887
|
+
const symbol = market['symbol'];
|
888
|
+
const price = this.safeString2 (order, 'order_price', 'price');
|
889
|
+
const amount = this.safeString2 (order, 'order_quantity', 'quantity'); // This is base amount
|
890
|
+
const cost = this.safeString2 (order, 'order_amount', 'amount'); // This is quote amount
|
891
|
+
const orderType = this.safeStringLower2 (order, 'order_type', 'type');
|
892
|
+
const status = this.safeValue (order, 'status');
|
893
|
+
const side = this.safeStringLower2 (order, 'side');
|
894
|
+
const filled = this.safeValue (order, 'executed');
|
895
|
+
const remaining = Precise.stringSub (cost, filled);
|
896
|
+
const fee = this.safeValue (order, 'total_fee');
|
897
|
+
const feeCurrency = this.safeString (order, 'fee_asset');
|
898
|
+
const transactions = this.safeValue (order, 'Transactions');
|
899
|
+
return this.safeOrder ({
|
900
|
+
'id': orderId,
|
901
|
+
'clientOrderId': clientOrderId,
|
902
|
+
'timestamp': timestamp,
|
903
|
+
'datetime': this.iso8601 (timestamp),
|
904
|
+
'lastTradeTimestamp': undefined,
|
905
|
+
'status': this.parseOrderStatus (status),
|
906
|
+
'symbol': symbol,
|
907
|
+
'type': orderType,
|
908
|
+
'timeInForce': undefined,
|
909
|
+
'postOnly': undefined, // TO_DO
|
910
|
+
'side': side,
|
911
|
+
'price': price,
|
912
|
+
'stopPrice': undefined,
|
913
|
+
'average': undefined,
|
914
|
+
'amount': amount,
|
915
|
+
'filled': filled,
|
916
|
+
'remaining': remaining, // TO_DO
|
917
|
+
'cost': cost,
|
918
|
+
'trades': transactions,
|
919
|
+
'fee': {
|
920
|
+
'cost': fee,
|
921
|
+
'currency': feeCurrency,
|
922
|
+
},
|
923
|
+
'info': order,
|
924
|
+
}, market);
|
925
|
+
}
|
926
|
+
|
927
|
+
parseOrderStatus (status) {
|
928
|
+
if (status !== undefined) {
|
929
|
+
const statuses = {
|
930
|
+
'NEW': 'open',
|
931
|
+
'FILLED': 'closed',
|
932
|
+
'CANCEL_SENT': 'canceled',
|
933
|
+
'CANCEL_ALL_SENT': 'canceled',
|
934
|
+
};
|
935
|
+
return this.safeString (statuses, status, status);
|
936
|
+
}
|
937
|
+
return status;
|
938
|
+
}
|
939
|
+
|
940
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
941
|
+
await this.loadMarkets ();
|
942
|
+
const market = this.market (symbol);
|
943
|
+
const request = {
|
944
|
+
'symbol': market['id'],
|
945
|
+
};
|
946
|
+
if (limit !== undefined) {
|
947
|
+
limit = Math.min (limit, 1000);
|
948
|
+
request['max_level'] = limit;
|
949
|
+
}
|
950
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrderBook', market, params);
|
951
|
+
const method = this.getSupportedMapping (marketType, {
|
952
|
+
'spot': 'v1PrivateGetOrderbookSymbol',
|
953
|
+
});
|
954
|
+
const response = await this[method] (this.extend (request, query));
|
955
|
+
//
|
956
|
+
// {
|
957
|
+
// success: true,
|
958
|
+
// timestamp: '1641562961192',
|
959
|
+
// asks: [
|
960
|
+
// { price: '0.921', quantity: '76.01' },
|
961
|
+
// { price: '0.933', quantity: '477.10' },
|
962
|
+
// ...
|
963
|
+
// ],
|
964
|
+
// bids: [
|
965
|
+
// { price: '0.940', quantity: '13502.47' },
|
966
|
+
// { price: '0.932', quantity: '43.91' },
|
967
|
+
// ...
|
968
|
+
// ]
|
969
|
+
// }
|
970
|
+
//
|
971
|
+
const timestamp = this.safeInteger (response, 'timestamp');
|
972
|
+
return this.parseOrderBook (response, symbol, timestamp, 'bids', 'asks', 'price', 'quantity');
|
973
|
+
}
|
974
|
+
|
975
|
+
async fetchOHLCV (symbol, timeframe = '1h', since = undefined, limit = undefined, params = {}) {
|
976
|
+
await this.loadMarkets ();
|
977
|
+
const market = this.market (symbol);
|
978
|
+
const request = {
|
979
|
+
'symbol': market['id'],
|
980
|
+
'type': this.timeframes[timeframe],
|
981
|
+
};
|
982
|
+
if (limit !== undefined) {
|
983
|
+
request['limit'] = Math.min (limit, 1000);
|
984
|
+
}
|
985
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOHLCV', market, params);
|
986
|
+
const method = this.getSupportedMapping (marketType, {
|
987
|
+
'spot': 'v1PrivateGetKline',
|
988
|
+
});
|
989
|
+
const response = await this[method] (this.extend (request, query));
|
990
|
+
// {
|
991
|
+
// success: true,
|
992
|
+
// rows: [
|
993
|
+
// {
|
994
|
+
// open: '0.94238',
|
995
|
+
// close: '0.94271',
|
996
|
+
// low: '0.94238',
|
997
|
+
// high: '0.94296',
|
998
|
+
// volume: '73.55',
|
999
|
+
// amount: '69.32040520',
|
1000
|
+
// symbol: 'SPOT_WOO_USDT',
|
1001
|
+
// type: '1m',
|
1002
|
+
// start_timestamp: '1641584700000',
|
1003
|
+
// end_timestamp: '1641584760000'
|
1004
|
+
// },
|
1005
|
+
// {
|
1006
|
+
// open: '0.94186',
|
1007
|
+
// close: '0.94186',
|
1008
|
+
// low: '0.94186',
|
1009
|
+
// high: '0.94186',
|
1010
|
+
// volume: '64.00',
|
1011
|
+
// amount: '60.27904000',
|
1012
|
+
// symbol: 'SPOT_WOO_USDT',
|
1013
|
+
// type: '1m',
|
1014
|
+
// start_timestamp: '1641584640000',
|
1015
|
+
// end_timestamp: '1641584700000'
|
1016
|
+
// },
|
1017
|
+
// ...
|
1018
|
+
// ]
|
1019
|
+
// }
|
1020
|
+
const data = this.safeValue (response, 'rows', []);
|
1021
|
+
return this.parseOHLCVs (data, market, timeframe, since, limit);
|
1022
|
+
}
|
1023
|
+
|
1024
|
+
parseOHLCV (ohlcv, market = undefined) {
|
1025
|
+
// example response in fetchOHLCV
|
1026
|
+
return [
|
1027
|
+
this.safeInteger (ohlcv, 'start_timestamp'),
|
1028
|
+
this.safeNumber (ohlcv, 'open'),
|
1029
|
+
this.safeNumber (ohlcv, 'high'),
|
1030
|
+
this.safeNumber (ohlcv, 'low'),
|
1031
|
+
this.safeNumber (ohlcv, 'close'),
|
1032
|
+
this.safeNumber (ohlcv, 'volume'),
|
1033
|
+
];
|
1034
|
+
}
|
1035
|
+
|
1036
|
+
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1037
|
+
await this.loadMarkets ();
|
1038
|
+
let market = undefined;
|
1039
|
+
if (symbol !== undefined) {
|
1040
|
+
market = this.market (symbol);
|
1041
|
+
}
|
1042
|
+
const request = {
|
1043
|
+
'oid': id,
|
1044
|
+
};
|
1045
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchOrderTrades', market, params);
|
1046
|
+
const method = this.getSupportedMapping (marketType, {
|
1047
|
+
'spot': 'v1PrivateGetOrderOidTrades',
|
1048
|
+
});
|
1049
|
+
const response = await this[method] (this.extend (request, query));
|
1050
|
+
// {
|
1051
|
+
// success: true,
|
1052
|
+
// rows: [
|
1053
|
+
// {
|
1054
|
+
// id: '99111647',
|
1055
|
+
// symbol: 'SPOT_WOO_USDT',
|
1056
|
+
// fee: '0.0024',
|
1057
|
+
// side: 'BUY',
|
1058
|
+
// executed_timestamp: '1641482113.084',
|
1059
|
+
// order_id: '87541111',
|
1060
|
+
// order_tag: 'default',
|
1061
|
+
// executed_price: '1',
|
1062
|
+
// executed_quantity: '12',
|
1063
|
+
// fee_asset: 'WOO',
|
1064
|
+
// is_maker: '1'
|
1065
|
+
// }
|
1066
|
+
// ]
|
1067
|
+
// }
|
1068
|
+
const trades = this.safeValue (response, 'rows', []);
|
1069
|
+
return this.parseTrades (trades, market, since, limit, params);
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1073
|
+
await this.loadMarkets ();
|
1074
|
+
const request = {};
|
1075
|
+
let market = undefined;
|
1076
|
+
if (symbol !== undefined) {
|
1077
|
+
market = this.market (symbol);
|
1078
|
+
request['symbol'] = market['id'];
|
1079
|
+
}
|
1080
|
+
if (since !== undefined) {
|
1081
|
+
request['start_t'] = since;
|
1082
|
+
}
|
1083
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchMyTrades', market, params);
|
1084
|
+
const method = this.getSupportedMapping (marketType, {
|
1085
|
+
'spot': 'v1PrivateGetClientTrades',
|
1086
|
+
});
|
1087
|
+
const response = await this[method] (this.extend (request, query));
|
1088
|
+
// {
|
1089
|
+
// "success": true,
|
1090
|
+
// "meta": {
|
1091
|
+
// "records_per_page": 25,
|
1092
|
+
// "current_page": 1
|
1093
|
+
// },
|
1094
|
+
// "rows": [
|
1095
|
+
// {
|
1096
|
+
// "id": 5,
|
1097
|
+
// "symbol": "SPOT_BTC_USDT",
|
1098
|
+
// "order_id": 211,
|
1099
|
+
// "order_tag": "default",
|
1100
|
+
// "executed_price": 10892.84,
|
1101
|
+
// "executed_quantity": 0.002,
|
1102
|
+
// "is_maker": 0,
|
1103
|
+
// "side": "SELL",
|
1104
|
+
// "fee": 0,
|
1105
|
+
// "fee_asset": "USDT",
|
1106
|
+
// "executed_timestamp": "1566264290.250"
|
1107
|
+
// },
|
1108
|
+
// ...
|
1109
|
+
// ]
|
1110
|
+
// }
|
1111
|
+
const trades = this.safeValue (response, 'rows', []);
|
1112
|
+
return this.parseTrades (trades, market, since, limit, params);
|
1113
|
+
}
|
1114
|
+
|
1115
|
+
async fetchBalance (params = {}) {
|
1116
|
+
await this.loadMarkets ();
|
1117
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params);
|
1118
|
+
const method = this.getSupportedMapping (marketType, {
|
1119
|
+
'spot': 'v2PrivateGetClientHolding',
|
1120
|
+
});
|
1121
|
+
const response = await this[method] (query);
|
1122
|
+
//
|
1123
|
+
// {
|
1124
|
+
// holding: [
|
1125
|
+
// {
|
1126
|
+
// token: 'USDT',
|
1127
|
+
// holding: '23.56', // free balance
|
1128
|
+
// frozen: '888.0', // i.e. if in processing withdrawal
|
1129
|
+
// interest: '0.0',
|
1130
|
+
// outstanding_holding: '-56.7', // this value is set (negative number) if there is an open limit order, and this is QUOTE currency of order
|
1131
|
+
// pending_exposure: '333.45', // this value is set (positive number) if there is an open limit order, and this is BASE currency of order
|
1132
|
+
// opening_cost: '0.00000000',
|
1133
|
+
// holding_cost: '0.00000000',
|
1134
|
+
// realised_pnl: '0.00000000',
|
1135
|
+
// settled_pnl: '0.00000000',
|
1136
|
+
// fee_24_h: '0',
|
1137
|
+
// settled_pnl_24_h: '0',
|
1138
|
+
// updated_time: '1641370779'
|
1139
|
+
// },
|
1140
|
+
// ...
|
1141
|
+
// ],
|
1142
|
+
// success: true
|
1143
|
+
// }
|
1144
|
+
//
|
1145
|
+
return this.parseBalance (response);
|
1146
|
+
}
|
1147
|
+
|
1148
|
+
parseBalance (response) {
|
1149
|
+
const result = {
|
1150
|
+
'info': response,
|
1151
|
+
};
|
1152
|
+
const balances = this.safeValue (response, 'holding', []);
|
1153
|
+
for (let i = 0; i < balances.length; i++) {
|
1154
|
+
const balance = balances[i];
|
1155
|
+
const code = this.safeCurrencyCode (this.safeString (balance, 'token'));
|
1156
|
+
const account = this.account ();
|
1157
|
+
account['total'] = this.safeString (balance, 'holding');
|
1158
|
+
const used = this.safeString (balance, 'outstanding_holding');
|
1159
|
+
account['used'] = Precise.stringNeg (used);
|
1160
|
+
result[code] = account;
|
1161
|
+
}
|
1162
|
+
return this.safeBalance (result);
|
1163
|
+
}
|
1164
|
+
|
1165
|
+
async fetchDepositAddress (code, params = {}) {
|
1166
|
+
// this method is TODO because of networks unification
|
1167
|
+
await this.loadMarkets ();
|
1168
|
+
const currency = this.currency (code);
|
1169
|
+
const networkCodeDefault = this.defaultNetworkCodeForCurrency (code);
|
1170
|
+
const networkCode = this.safeValue (params, 'network', networkCodeDefault);
|
1171
|
+
params = this.omit (params, 'network');
|
1172
|
+
const networkAliases = this.safeValue (this.options, 'network-aliases', {});
|
1173
|
+
const networkId = this.getKeyByValue (networkAliases, networkCode);
|
1174
|
+
const codeForExchange = networkId + '_' + currency['code'];
|
1175
|
+
const request = {
|
1176
|
+
'token': codeForExchange,
|
1177
|
+
};
|
1178
|
+
const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchDepositAddress', undefined, params);
|
1179
|
+
const method = this.getSupportedMapping (marketType, {
|
1180
|
+
'spot': 'v1PrivateGetAssetDeposit',
|
1181
|
+
});
|
1182
|
+
const response = await this[method] (this.extend (request, query));
|
1183
|
+
// {
|
1184
|
+
// success: true,
|
1185
|
+
// address: '3Jmtjx5544T4smrit9Eroe4PCrRkpDeKjP',
|
1186
|
+
// extra: ''
|
1187
|
+
// }
|
1188
|
+
let tag = this.safeString (response, 'extra');
|
1189
|
+
if (tag === '') {
|
1190
|
+
tag = undefined;
|
1191
|
+
}
|
1192
|
+
const address = this.safeString (response, 'address');
|
1193
|
+
this.checkAddress (address);
|
1194
|
+
return {
|
1195
|
+
'currency': code,
|
1196
|
+
'address': address,
|
1197
|
+
'tag': tag,
|
1198
|
+
'network': networkCode,
|
1199
|
+
'info': response,
|
1200
|
+
};
|
1201
|
+
}
|
1202
|
+
|
1203
|
+
async getAssetHistoryRows (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1204
|
+
await this.loadMarkets ();
|
1205
|
+
const request = { };
|
1206
|
+
let currency = undefined;
|
1207
|
+
if (code !== undefined) {
|
1208
|
+
currency = this.currency (code);
|
1209
|
+
request['balance_token'] = currency['id'];
|
1210
|
+
}
|
1211
|
+
if (since !== undefined) {
|
1212
|
+
request['start_t'] = since;
|
1213
|
+
}
|
1214
|
+
if (limit !== undefined) {
|
1215
|
+
request['pageSize'] = limit;
|
1216
|
+
}
|
1217
|
+
const transactionType = this.safeString (params, 'type');
|
1218
|
+
params = this.omit (params, 'type');
|
1219
|
+
if (transactionType !== undefined) {
|
1220
|
+
request['type'] = transactionType;
|
1221
|
+
}
|
1222
|
+
const response = await this.v1PrivateGetAssetHistory (this.extend (request, params));
|
1223
|
+
// {
|
1224
|
+
// rows: [
|
1225
|
+
// {
|
1226
|
+
// id: '22010508193900165',
|
1227
|
+
// token: 'TRON_USDT',
|
1228
|
+
// extra: '',
|
1229
|
+
// amount: '13.75848500',
|
1230
|
+
// status: 'COMPLETED',
|
1231
|
+
// account: null,
|
1232
|
+
// description: null,
|
1233
|
+
// user_id: '42222',
|
1234
|
+
// application_id: '6ad2b303-f354-45c0-8105-9f5f19d0e335',
|
1235
|
+
// external_id: '220105081900134',
|
1236
|
+
// target_address: 'TXnyFSnAYad3YCaqtwMw9jvXKkeU39NLnK',
|
1237
|
+
// source_address: 'TYDzsYUEpvnYmQk4zGP9sWWcTEd2MiAtW6',
|
1238
|
+
// type: 'BALANCE',
|
1239
|
+
// token_side: 'DEPOSIT',
|
1240
|
+
// tx_id: '35b0004022f6b3ad07f39a0b7af199f6b258c2c3e2c7cdc93c67efa74fd625ee',
|
1241
|
+
// fee_token: '',
|
1242
|
+
// fee_amount: '0.00000000',
|
1243
|
+
// created_time: '1641370779.442',
|
1244
|
+
// updated_time: '1641370779.465',
|
1245
|
+
// is_new_target_address: null,
|
1246
|
+
// confirmed_number: '29',
|
1247
|
+
// confirming_threshold: '27',
|
1248
|
+
// audit_tag: '1',
|
1249
|
+
// audit_result: '0',
|
1250
|
+
// balance_token: null, // TODO -write to support, that this seems broken. here should be the token id
|
1251
|
+
// network_name: null // TODO -write to support, that this seems broken. here should be the network id
|
1252
|
+
// }
|
1253
|
+
// ],
|
1254
|
+
// meta: { total: '1', records_per_page: '25', current_page: '1' },
|
1255
|
+
// success: true
|
1256
|
+
// }
|
1257
|
+
return [ currency, this.safeValue (response, 'rows', {}) ];
|
1258
|
+
}
|
1259
|
+
|
1260
|
+
async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1261
|
+
const [ currency, rows ] = await this.getAssetHistoryRows (code, since, limit, params);
|
1262
|
+
return this.parseLedger (rows, currency, since, limit, params);
|
1263
|
+
}
|
1264
|
+
|
1265
|
+
parseLedgerEntry (item, currency = undefined) {
|
1266
|
+
const networkizedCode = this.safeString (item, 'token');
|
1267
|
+
const currencyDefined = this.getCurrencyFromChaincode (networkizedCode, currency);
|
1268
|
+
const code = currencyDefined['code'];
|
1269
|
+
const amount = this.safeNumber (item, 'amount');
|
1270
|
+
const side = this.safeNumber (item, 'token_side');
|
1271
|
+
const direction = (side === 'DEPOSIT') ? 'in' : 'out';
|
1272
|
+
const timestamp = this.safeTimestamp (item, 'created_time');
|
1273
|
+
const fee = this.parseTokenAndFeeTemp (item, 'fee_token', 'fee_amount');
|
1274
|
+
return {
|
1275
|
+
'id': this.safeString (item, 'id'),
|
1276
|
+
'currency': code,
|
1277
|
+
'account': this.safeString (item, 'account'),
|
1278
|
+
'referenceAccount': undefined,
|
1279
|
+
'referenceId': this.safeString (item, 'tx_id'),
|
1280
|
+
'status': this.parseTransactionStatus (item, 'status'),
|
1281
|
+
'amount': amount,
|
1282
|
+
'before': undefined,
|
1283
|
+
'after': undefined,
|
1284
|
+
'fee': fee,
|
1285
|
+
'direction': direction,
|
1286
|
+
'timestamp': timestamp,
|
1287
|
+
'datetime': this.iso8601 (timestamp),
|
1288
|
+
'type': this.parseLedgerEntryType (this.safeString (item, 'type')),
|
1289
|
+
'info': item,
|
1290
|
+
};
|
1291
|
+
}
|
1292
|
+
|
1293
|
+
parseLedgerEntryType (type) {
|
1294
|
+
const types = {
|
1295
|
+
'BALANCE': 'transaction', // Funds moved in/out wallet
|
1296
|
+
'COLLATERAL': 'transfer', // Funds moved between portfolios
|
1297
|
+
};
|
1298
|
+
return this.safeString (types, type, type);
|
1299
|
+
}
|
1300
|
+
|
1301
|
+
getCurrencyFromChaincode (networkizedCode, currency) {
|
1302
|
+
if (currency !== undefined) {
|
1303
|
+
return currency;
|
1304
|
+
} else {
|
1305
|
+
const parts = networkizedCode.split ('_');
|
1306
|
+
const partsLength = parts.length;
|
1307
|
+
const firstPart = this.safeString (parts, 0);
|
1308
|
+
let currencyId = this.safeString (parts, 1, firstPart);
|
1309
|
+
if (partsLength > 2) {
|
1310
|
+
currencyId += '_' + this.safeString (parts, 2);
|
1311
|
+
}
|
1312
|
+
currency = this.safeCurrency (currencyId);
|
1313
|
+
}
|
1314
|
+
return currency;
|
1315
|
+
}
|
1316
|
+
|
1317
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1318
|
+
const request = {
|
1319
|
+
'token_side': 'DEPOSIT',
|
1320
|
+
};
|
1321
|
+
return await this.fetchTransactions (code, since, limit, this.extend (request, params));
|
1322
|
+
}
|
1323
|
+
|
1324
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1325
|
+
const request = {
|
1326
|
+
'token_side': 'WITHDRAW',
|
1327
|
+
};
|
1328
|
+
return await this.fetchTransactions (code, since, limit, this.extend (request, params));
|
1329
|
+
}
|
1330
|
+
|
1331
|
+
async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1332
|
+
const request = {
|
1333
|
+
'type': 'BALANCE',
|
1334
|
+
};
|
1335
|
+
const [ currency, rows ] = await this.getAssetHistoryRows (code, since, limit, this.extend (request, params));
|
1336
|
+
return this.parseTransactions (rows, currency, since, limit, params);
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
parseTransaction (transaction, currency = undefined) {
|
1340
|
+
// example in fetchLedger
|
1341
|
+
const networkizedCode = this.safeString (transaction, 'token');
|
1342
|
+
const currencyDefined = this.getCurrencyFromChaincode (networkizedCode, currency);
|
1343
|
+
const code = currencyDefined['code'];
|
1344
|
+
let movementDirection = this.safeStringLower (transaction, 'token_side');
|
1345
|
+
if (movementDirection === 'withdraw') {
|
1346
|
+
movementDirection = 'withdrawal';
|
1347
|
+
}
|
1348
|
+
const fee = this.parseTokenAndFeeTemp (transaction, 'fee_token', 'fee_amount');
|
1349
|
+
fee['rate'] = undefined;
|
1350
|
+
const addressTo = this.safeString (transaction, 'target_address');
|
1351
|
+
const addressFrom = this.safeString (transaction, 'source_address');
|
1352
|
+
const timestamp = this.safeTimestamp (transaction, 'created_time');
|
1353
|
+
return {
|
1354
|
+
'id': this.safeString (transaction, 'id'),
|
1355
|
+
'txid': this.safeString (transaction, 'tx_id'),
|
1356
|
+
'timestamp': timestamp,
|
1357
|
+
'datetime': this.iso8601 (timestamp),
|
1358
|
+
'address': undefined,
|
1359
|
+
'addressFrom': addressFrom,
|
1360
|
+
'addressTo': addressTo,
|
1361
|
+
'tag': this.safeString (transaction, 'extra'),
|
1362
|
+
'type': movementDirection,
|
1363
|
+
'amount': this.safeNumber (transaction, 'amount'),
|
1364
|
+
'currency': code,
|
1365
|
+
'status': this.parseTransactionStatus (this.safeString (transaction, 'status')),
|
1366
|
+
'updated': this.safeTimestamp (transaction, 'updated_time'),
|
1367
|
+
'fee': fee,
|
1368
|
+
'info': transaction,
|
1369
|
+
};
|
1370
|
+
}
|
1371
|
+
|
1372
|
+
parseTransactionStatus (status) {
|
1373
|
+
const statuses = {
|
1374
|
+
'NEW': 'pending',
|
1375
|
+
'CONFIRMING': 'pending',
|
1376
|
+
'PROCESSING': 'pending',
|
1377
|
+
'COMPLETED': 'ok',
|
1378
|
+
'CANCELED': 'canceled',
|
1379
|
+
};
|
1380
|
+
return this.safeString (statuses, status, status);
|
1381
|
+
}
|
1382
|
+
|
1383
|
+
async transfer (code, amount, fromAccount, toAccount, params = {}) {
|
1384
|
+
await this.loadMarkets ();
|
1385
|
+
const currency = this.currency (code);
|
1386
|
+
const request = {
|
1387
|
+
'token': currency['id'],
|
1388
|
+
'amount': this.parseNumber (amount),
|
1389
|
+
'from_application_id': fromAccount,
|
1390
|
+
'to_application_id': toAccount,
|
1391
|
+
};
|
1392
|
+
const response = await this.v1PrivatePostAssetMainSubTransfer (this.extend (request, params));
|
1393
|
+
//
|
1394
|
+
// {
|
1395
|
+
// "success": true,
|
1396
|
+
// "id": 200
|
1397
|
+
// }
|
1398
|
+
//
|
1399
|
+
const transfer = this.parseTransfer (response, currency);
|
1400
|
+
const transferOptions = this.safeValue (this.options, 'transfer', {});
|
1401
|
+
const fillResponseFromRequest = this.safeValue (transferOptions, 'fillResponseFromRequest', true);
|
1402
|
+
if (fillResponseFromRequest) {
|
1403
|
+
transfer['amount'] = amount;
|
1404
|
+
transfer['fromAccount'] = fromAccount;
|
1405
|
+
transfer['toAccount'] = toAccount;
|
1406
|
+
}
|
1407
|
+
return transfer;
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
async fetchTransfers (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1411
|
+
const request = {
|
1412
|
+
'type': 'COLLATERAL',
|
1413
|
+
};
|
1414
|
+
const [ currency, rows ] = await this.getAssetHistoryRows (code, since, limit, this.extend (request, params));
|
1415
|
+
return this.parseTransfers (rows, currency, since, limit, params);
|
1416
|
+
}
|
1417
|
+
|
1418
|
+
parseTransfer (transfer, currency = undefined) {
|
1419
|
+
//
|
1420
|
+
// getAssetHistoryRows
|
1421
|
+
// {
|
1422
|
+
// "created_time": "1579399877.041", // Unix epoch time in seconds
|
1423
|
+
// "updated_time": "1579399877.041", // Unix epoch time in seconds
|
1424
|
+
// "id": "202029292829292",
|
1425
|
+
// "external_id": "202029292829292",
|
1426
|
+
// "application_id": null,
|
1427
|
+
// "token": "ETH",
|
1428
|
+
// "target_address": "0x31d64B3230f8baDD91dE1710A65DF536aF8f7cDa",
|
1429
|
+
// "source_address": "0x70fd25717f769c7f9a46b319f0f9103c0d887af0",
|
1430
|
+
// "extra": "",
|
1431
|
+
// "type": "BALANCE",
|
1432
|
+
// "token_side": "DEPOSIT",
|
1433
|
+
// "amount": 1000,
|
1434
|
+
// "tx_id": "0x8a74c517bc104c8ebad0c3c3f64b1f302ed5f8bca598ae4459c63419038106b6",
|
1435
|
+
// "fee_token": null,
|
1436
|
+
// "fee_amount": null,
|
1437
|
+
// "status": "CONFIRMING"
|
1438
|
+
// }
|
1439
|
+
//
|
1440
|
+
// v1PrivatePostAssetMainSubTransfer
|
1441
|
+
// {
|
1442
|
+
// "success": true,
|
1443
|
+
// "id": 200
|
1444
|
+
// }
|
1445
|
+
//
|
1446
|
+
const networkizedCode = this.safeString (transfer, 'token');
|
1447
|
+
const currencyDefined = this.getCurrencyFromChaincode (networkizedCode, currency);
|
1448
|
+
const code = currencyDefined['code'];
|
1449
|
+
let movementDirection = this.safeStringLower (transfer, 'token_side');
|
1450
|
+
if (movementDirection === 'withdraw') {
|
1451
|
+
movementDirection = 'withdrawal';
|
1452
|
+
}
|
1453
|
+
let fromAccount = undefined;
|
1454
|
+
let toAccount = undefined;
|
1455
|
+
if (movementDirection === 'withdraw') {
|
1456
|
+
fromAccount = undefined;
|
1457
|
+
toAccount = 'spot';
|
1458
|
+
} else if (movementDirection === 'deposit') {
|
1459
|
+
fromAccount = 'spot';
|
1460
|
+
toAccount = undefined;
|
1461
|
+
}
|
1462
|
+
const timestamp = this.safeTimestamp (transfer, 'created_time');
|
1463
|
+
const success = this.safeValue (transfer, 'success');
|
1464
|
+
let status = undefined;
|
1465
|
+
if (success !== undefined) {
|
1466
|
+
status = success ? 'ok' : 'failed';
|
1467
|
+
}
|
1468
|
+
return {
|
1469
|
+
'id': this.safeString (transfer, 'id'),
|
1470
|
+
'timestamp': timestamp,
|
1471
|
+
'datetime': this.iso8601 (timestamp),
|
1472
|
+
'currency': code,
|
1473
|
+
'amount': this.safeNumber (transfer, 'amount'),
|
1474
|
+
'fromAccount': fromAccount,
|
1475
|
+
'toAccount': toAccount,
|
1476
|
+
'status': this.parseTransferStatus (this.safeString (transfer, 'status', status)),
|
1477
|
+
'info': transfer,
|
1478
|
+
};
|
1479
|
+
}
|
1480
|
+
|
1481
|
+
parseTransferStatus (status) {
|
1482
|
+
const statuses = {
|
1483
|
+
'NEW': 'pending',
|
1484
|
+
'CONFIRMING': 'pending',
|
1485
|
+
'PROCESSING': 'pending',
|
1486
|
+
'COMPLETED': 'ok',
|
1487
|
+
'CANCELED': 'canceled',
|
1488
|
+
};
|
1489
|
+
return this.safeString (statuses, status, status);
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
nonce () {
|
1493
|
+
return this.milliseconds ();
|
1494
|
+
}
|
1495
|
+
|
1496
|
+
sign (path, section = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1497
|
+
const version = section[0];
|
1498
|
+
const access = section[1];
|
1499
|
+
let url = this.implodeHostname (this.urls['api'][access]);
|
1500
|
+
url += '/' + version + '/';
|
1501
|
+
path = this.implodeParams (path, params);
|
1502
|
+
params = this.omit (params, this.extractParams (path));
|
1503
|
+
params = this.keysort (params);
|
1504
|
+
if (access === 'public') {
|
1505
|
+
url += access + '/' + path;
|
1506
|
+
if (Object.keys (params).length) {
|
1507
|
+
url += '?' + this.urlencode (params);
|
1508
|
+
}
|
1509
|
+
} else {
|
1510
|
+
this.checkRequiredCredentials ();
|
1511
|
+
url += path;
|
1512
|
+
const ts = this.nonce ().toString ();
|
1513
|
+
let auth = this.urlencode (params);
|
1514
|
+
if (method === 'POST' || method === 'DELETE') {
|
1515
|
+
body = auth;
|
1516
|
+
} else {
|
1517
|
+
url += '?' + auth;
|
1518
|
+
}
|
1519
|
+
auth += '|' + ts;
|
1520
|
+
const signature = this.hmac (this.encode (auth), this.encode (this.secret), 'sha256');
|
1521
|
+
headers = {
|
1522
|
+
'x-api-key': this.apiKey,
|
1523
|
+
'x-api-signature': signature,
|
1524
|
+
'x-api-timestamp': ts,
|
1525
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
1526
|
+
};
|
1527
|
+
}
|
1528
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1529
|
+
}
|
1530
|
+
|
1531
|
+
handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
1532
|
+
if (!response) {
|
1533
|
+
return; // fallback to default error handler
|
1534
|
+
}
|
1535
|
+
//
|
1536
|
+
// 400 Bad Request {"success":false,"code":-1012,"message":"Amount is required for buy market orders when margin disabled."}
|
1537
|
+
//
|
1538
|
+
const success = this.safeValue (response, 'success');
|
1539
|
+
const errorCode = this.safeString (response, 'code');
|
1540
|
+
if (!success) {
|
1541
|
+
const feedback = this.id + ' ' + this.json (response);
|
1542
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
|
1543
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], errorCode, feedback);
|
1544
|
+
}
|
1545
|
+
}
|
1546
|
+
|
1547
|
+
defaultNetworkCodeForCurrency (code) { // TODO: can be moved into base as an unified method
|
1548
|
+
// at first, try to find if user or exchange has defined default networks for the specific currency
|
1549
|
+
const defaultNetworkCodeForCurrencies = this.safeValue (this.options, 'defaultNetworkCodeForCurrencies');
|
1550
|
+
if (defaultNetworkCodeForCurrencies !== undefined) {
|
1551
|
+
const defaultNetworkCode = this.safeStringUpper (defaultNetworkCodeForCurrencies, code);
|
1552
|
+
if (defaultNetworkCode !== undefined) {
|
1553
|
+
return defaultNetworkCode;
|
1554
|
+
}
|
1555
|
+
}
|
1556
|
+
// if not found by above 'defaultNetworkCodeForCurrencies' for specific currency, then try with `defaultNetworkCodePriorities`
|
1557
|
+
const currencyItem = this.currency (code);
|
1558
|
+
const networks = currencyItem['networks'];
|
1559
|
+
const defaultNetworkCodePriorities = this.safeValue (this.options, 'defaultNetworkCodePriorities');
|
1560
|
+
if (defaultNetworkCodePriorities !== undefined) {
|
1561
|
+
// itterate according to priority networks
|
1562
|
+
const networksKeys = Object.keys (networks);
|
1563
|
+
const networksKeysLength = networksKeys.length;
|
1564
|
+
if (networksKeysLength > 0) {
|
1565
|
+
for (let i = 0; i < defaultNetworkCodePriorities.length; i++) {
|
1566
|
+
const networkCode = defaultNetworkCodePriorities[i];
|
1567
|
+
if (networkCode in networks) {
|
1568
|
+
return networkCode;
|
1569
|
+
}
|
1570
|
+
}
|
1571
|
+
}
|
1572
|
+
}
|
1573
|
+
// if it was not returned according to above options, then return the first network of currency
|
1574
|
+
const networkKeys = Object.keys (networks);
|
1575
|
+
return this.safeValue (networkKeys, 0);
|
1576
|
+
}
|
1577
|
+
};
|