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/bitrue.js
ADDED
@@ -0,0 +1,1747 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { ExchangeError, ArgumentsRequired, ExchangeNotAvailable, InsufficientFunds, OrderNotFound, InvalidOrder, DDoSProtection, InvalidNonce, AuthenticationError, RateLimitExceeded, PermissionDenied, BadRequest, BadSymbol, AccountSuspended, OrderImmediatelyFillable, OnMaintenance } = require ('./base/errors');
|
7
|
+
const { TRUNCATE } = require ('./base/functions/number');
|
8
|
+
const Precise = require ('./base/Precise');
|
9
|
+
|
10
|
+
// ---------------------------------------------------------------------------
|
11
|
+
|
12
|
+
module.exports = class bitrue extends Exchange {
|
13
|
+
describe () {
|
14
|
+
return this.deepExtend (super.describe (), {
|
15
|
+
'id': 'bitrue',
|
16
|
+
'name': 'Bitrue',
|
17
|
+
'countries': [ 'SG' ], // Singapore, Malta
|
18
|
+
'rateLimit': 1000,
|
19
|
+
'certified': false,
|
20
|
+
'version': 'v1',
|
21
|
+
// new metainfo interface
|
22
|
+
'has': {
|
23
|
+
'CORS': undefined,
|
24
|
+
'spot': true,
|
25
|
+
'margin': false,
|
26
|
+
'swap': undefined, // has but unimplemented
|
27
|
+
'future': undefined,
|
28
|
+
'option': false,
|
29
|
+
'cancelAllOrders': false,
|
30
|
+
'cancelOrder': true,
|
31
|
+
'createOrder': true,
|
32
|
+
'createStopLimitOrder': true,
|
33
|
+
'createStopMarketOrder': true,
|
34
|
+
'createStopOrder': true,
|
35
|
+
'fetchBalance': true,
|
36
|
+
'fetchBidsAsks': true,
|
37
|
+
'fetchBorrowRate': false,
|
38
|
+
'fetchBorrowRateHistories': false,
|
39
|
+
'fetchBorrowRateHistory': false,
|
40
|
+
'fetchBorrowRates': false,
|
41
|
+
'fetchBorrowRatesPerSymbol': false,
|
42
|
+
'fetchClosedOrders': true,
|
43
|
+
'fetchCurrencies': true,
|
44
|
+
'fetchDepositAddress': false,
|
45
|
+
'fetchDeposits': true,
|
46
|
+
'fetchFundingFees': false,
|
47
|
+
'fetchMarkets': true,
|
48
|
+
'fetchMyTrades': true,
|
49
|
+
'fetchOHLCV': 'emulated',
|
50
|
+
'fetchOpenOrders': true,
|
51
|
+
'fetchOrder': true,
|
52
|
+
'fetchOrderBook': true,
|
53
|
+
'fetchOrders': false,
|
54
|
+
'fetchStatus': true,
|
55
|
+
'fetchTicker': true,
|
56
|
+
'fetchTickers': true,
|
57
|
+
'fetchTime': true,
|
58
|
+
'fetchTrades': true,
|
59
|
+
'fetchTradingFee': false,
|
60
|
+
'fetchTradingFees': false,
|
61
|
+
'fetchTransactions': false,
|
62
|
+
'fetchTransfers': false,
|
63
|
+
'fetchWithdrawals': true,
|
64
|
+
'transfer': false,
|
65
|
+
'withdraw': true,
|
66
|
+
},
|
67
|
+
'timeframes': {
|
68
|
+
'1m': '1m',
|
69
|
+
'5m': '5m',
|
70
|
+
'15m': '15m',
|
71
|
+
'30m': '30m',
|
72
|
+
'1h': '1h',
|
73
|
+
'1d': '1d',
|
74
|
+
'1w': '1w',
|
75
|
+
'1M': '1M',
|
76
|
+
},
|
77
|
+
'urls': {
|
78
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/139516488-243a830d-05dd-446b-91c6-c1f18fe30c63.jpg',
|
79
|
+
'api': {
|
80
|
+
'v1': 'https://www.bitrue.com/api/v1',
|
81
|
+
'v2': 'https://www.bitrue.com/api/v2',
|
82
|
+
'kline': 'https://www.bitrue.com/kline-api',
|
83
|
+
},
|
84
|
+
'www': 'https://www.bitrue.com',
|
85
|
+
'referral': 'https://www.bitrue.com/activity/task/task-landing?inviteCode=EZWETQE&cn=900000',
|
86
|
+
'doc': [
|
87
|
+
'https://github.com/Bitrue-exchange/bitrue-official-api-docs',
|
88
|
+
],
|
89
|
+
'fees': 'https://bitrue.zendesk.com/hc/en-001/articles/4405479952537',
|
90
|
+
},
|
91
|
+
'api': {
|
92
|
+
'kline': {
|
93
|
+
'public': {
|
94
|
+
'get': {
|
95
|
+
'public.json': 1,
|
96
|
+
'public{currency}.json': 1,
|
97
|
+
},
|
98
|
+
},
|
99
|
+
},
|
100
|
+
'v1': {
|
101
|
+
'public': {
|
102
|
+
'get': {
|
103
|
+
'ping': 1,
|
104
|
+
'time': 1,
|
105
|
+
'exchangeInfo': 1,
|
106
|
+
'depth': { 'cost': 1, 'byLimit': [ [ 100, 1 ], [ 500, 5 ], [ 1000, 10 ] ] },
|
107
|
+
'trades': 1,
|
108
|
+
'historicalTrades': 5,
|
109
|
+
'aggTrades': 1,
|
110
|
+
'ticker/24hr': { 'cost': 1, 'noSymbol': 40 },
|
111
|
+
'ticker/price': { 'cost': 1, 'noSymbol': 2 },
|
112
|
+
'ticker/bookTicker': { 'cost': 1, 'noSymbol': 2 },
|
113
|
+
},
|
114
|
+
},
|
115
|
+
'private': {
|
116
|
+
'get': {
|
117
|
+
'order': 1,
|
118
|
+
'openOrders': 1,
|
119
|
+
'allOrders': 5,
|
120
|
+
'account': 5,
|
121
|
+
'myTrades': { 'cost': 5, 'noSymbol': 40 },
|
122
|
+
'etf/net-value/{symbol}': 1,
|
123
|
+
'withdraw/history': 1,
|
124
|
+
'deposit/history': 1,
|
125
|
+
},
|
126
|
+
'post': {
|
127
|
+
'order': 4,
|
128
|
+
'withdraw/commit': 1,
|
129
|
+
},
|
130
|
+
'delete': {
|
131
|
+
'order': 1,
|
132
|
+
},
|
133
|
+
},
|
134
|
+
},
|
135
|
+
'v2': {
|
136
|
+
'private': {
|
137
|
+
'get': {
|
138
|
+
'myTrades': 5,
|
139
|
+
},
|
140
|
+
},
|
141
|
+
},
|
142
|
+
},
|
143
|
+
'fees': {
|
144
|
+
'trading': {
|
145
|
+
'feeSide': 'get',
|
146
|
+
'tierBased': false,
|
147
|
+
'percentage': true,
|
148
|
+
'taker': this.parseNumber ('0.00098'),
|
149
|
+
'maker': this.parseNumber ('0.00098'),
|
150
|
+
},
|
151
|
+
'future': {
|
152
|
+
'trading': {
|
153
|
+
'feeSide': 'quote',
|
154
|
+
'tierBased': true,
|
155
|
+
'percentage': true,
|
156
|
+
'taker': this.parseNumber ('0.000400'),
|
157
|
+
'maker': this.parseNumber ('0.000200'),
|
158
|
+
'tiers': {
|
159
|
+
'taker': [
|
160
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.000400') ],
|
161
|
+
[ this.parseNumber ('250'), this.parseNumber ('0.000400') ],
|
162
|
+
[ this.parseNumber ('2500'), this.parseNumber ('0.000350') ],
|
163
|
+
[ this.parseNumber ('7500'), this.parseNumber ('0.000320') ],
|
164
|
+
[ this.parseNumber ('22500'), this.parseNumber ('0.000300') ],
|
165
|
+
[ this.parseNumber ('50000'), this.parseNumber ('0.000270') ],
|
166
|
+
[ this.parseNumber ('100000'), this.parseNumber ('0.000250') ],
|
167
|
+
[ this.parseNumber ('200000'), this.parseNumber ('0.000220') ],
|
168
|
+
[ this.parseNumber ('400000'), this.parseNumber ('0.000200') ],
|
169
|
+
[ this.parseNumber ('750000'), this.parseNumber ('0.000170') ],
|
170
|
+
],
|
171
|
+
'maker': [
|
172
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.000200') ],
|
173
|
+
[ this.parseNumber ('250'), this.parseNumber ('0.000160') ],
|
174
|
+
[ this.parseNumber ('2500'), this.parseNumber ('0.000140') ],
|
175
|
+
[ this.parseNumber ('7500'), this.parseNumber ('0.000120') ],
|
176
|
+
[ this.parseNumber ('22500'), this.parseNumber ('0.000100') ],
|
177
|
+
[ this.parseNumber ('50000'), this.parseNumber ('0.000080') ],
|
178
|
+
[ this.parseNumber ('100000'), this.parseNumber ('0.000060') ],
|
179
|
+
[ this.parseNumber ('200000'), this.parseNumber ('0.000040') ],
|
180
|
+
[ this.parseNumber ('400000'), this.parseNumber ('0.000020') ],
|
181
|
+
[ this.parseNumber ('750000'), this.parseNumber ('0') ],
|
182
|
+
],
|
183
|
+
},
|
184
|
+
},
|
185
|
+
},
|
186
|
+
'delivery': {
|
187
|
+
'trading': {
|
188
|
+
'feeSide': 'base',
|
189
|
+
'tierBased': true,
|
190
|
+
'percentage': true,
|
191
|
+
'taker': this.parseNumber ('0.000500'),
|
192
|
+
'maker': this.parseNumber ('0.000100'),
|
193
|
+
'tiers': {
|
194
|
+
'taker': [
|
195
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.000500') ],
|
196
|
+
[ this.parseNumber ('250'), this.parseNumber ('0.000450') ],
|
197
|
+
[ this.parseNumber ('2500'), this.parseNumber ('0.000400') ],
|
198
|
+
[ this.parseNumber ('7500'), this.parseNumber ('0.000300') ],
|
199
|
+
[ this.parseNumber ('22500'), this.parseNumber ('0.000250') ],
|
200
|
+
[ this.parseNumber ('50000'), this.parseNumber ('0.000240') ],
|
201
|
+
[ this.parseNumber ('100000'), this.parseNumber ('0.000240') ],
|
202
|
+
[ this.parseNumber ('200000'), this.parseNumber ('0.000240') ],
|
203
|
+
[ this.parseNumber ('400000'), this.parseNumber ('0.000240') ],
|
204
|
+
[ this.parseNumber ('750000'), this.parseNumber ('0.000240') ],
|
205
|
+
],
|
206
|
+
'maker': [
|
207
|
+
[ this.parseNumber ('0'), this.parseNumber ('0.000100') ],
|
208
|
+
[ this.parseNumber ('250'), this.parseNumber ('0.000080') ],
|
209
|
+
[ this.parseNumber ('2500'), this.parseNumber ('0.000050') ],
|
210
|
+
[ this.parseNumber ('7500'), this.parseNumber ('0.0000030') ],
|
211
|
+
[ this.parseNumber ('22500'), this.parseNumber ('0') ],
|
212
|
+
[ this.parseNumber ('50000'), this.parseNumber ('-0.000050') ],
|
213
|
+
[ this.parseNumber ('100000'), this.parseNumber ('-0.000060') ],
|
214
|
+
[ this.parseNumber ('200000'), this.parseNumber ('-0.000070') ],
|
215
|
+
[ this.parseNumber ('400000'), this.parseNumber ('-0.000080') ],
|
216
|
+
[ this.parseNumber ('750000'), this.parseNumber ('-0.000090') ],
|
217
|
+
],
|
218
|
+
},
|
219
|
+
},
|
220
|
+
},
|
221
|
+
},
|
222
|
+
// exchange-specific options
|
223
|
+
'options': {
|
224
|
+
// 'fetchTradesMethod': 'publicGetAggTrades', // publicGetTrades, publicGetHistoricalTrades
|
225
|
+
'fetchMyTradesMethod': 'v2PrivateGetMyTrades', // v1PrivateGetMyTrades
|
226
|
+
'hasAlreadyAuthenticatedSuccessfully': false,
|
227
|
+
'recvWindow': 5 * 1000, // 5 sec, binance default
|
228
|
+
'timeDifference': 0, // the difference between system clock and Binance clock
|
229
|
+
'adjustForTimeDifference': false, // controls the adjustment logic upon instantiation
|
230
|
+
'parseOrderToPrecision': false, // force amounts and costs in parseOrder to precision
|
231
|
+
'newOrderRespType': {
|
232
|
+
'market': 'FULL', // 'ACK' for order id, 'RESULT' for full order or 'FULL' for order with fills
|
233
|
+
'limit': 'FULL', // we change it from 'ACK' by default to 'FULL' (returns immediately if limit is not hit)
|
234
|
+
},
|
235
|
+
'networks': {
|
236
|
+
'SPL': 'SOLANA',
|
237
|
+
'SOL': 'SOLANA',
|
238
|
+
'DOGE': 'dogecoin',
|
239
|
+
'ADA': 'Cardano',
|
240
|
+
},
|
241
|
+
},
|
242
|
+
'commonCurrencies': {
|
243
|
+
'MIM': 'MIM Swarm',
|
244
|
+
},
|
245
|
+
// https://binance-docs.github.io/apidocs/spot/en/#error-codes-2
|
246
|
+
'exceptions': {
|
247
|
+
'exact': {
|
248
|
+
'System is under maintenance.': OnMaintenance, // {"code":1,"msg":"System is under maintenance."}
|
249
|
+
'System abnormality': ExchangeError, // {"code":-1000,"msg":"System abnormality"}
|
250
|
+
'You are not authorized to execute this request.': PermissionDenied, // {"msg":"You are not authorized to execute this request."}
|
251
|
+
'API key does not exist': AuthenticationError,
|
252
|
+
'Order would trigger immediately.': OrderImmediatelyFillable,
|
253
|
+
'Stop price would trigger immediately.': OrderImmediatelyFillable, // {"code":-2010,"msg":"Stop price would trigger immediately."}
|
254
|
+
'Order would immediately match and take.': OrderImmediatelyFillable, // {"code":-2010,"msg":"Order would immediately match and take."}
|
255
|
+
'Account has insufficient balance for requested action.': InsufficientFunds,
|
256
|
+
'Rest API trading is not enabled.': ExchangeNotAvailable,
|
257
|
+
"You don't have permission.": PermissionDenied, // {"msg":"You don't have permission.","success":false}
|
258
|
+
'Market is closed.': ExchangeNotAvailable, // {"code":-1013,"msg":"Market is closed."}
|
259
|
+
'Too many requests. Please try again later.': DDoSProtection, // {"msg":"Too many requests. Please try again later.","success":false}
|
260
|
+
'-1000': ExchangeNotAvailable, // {"code":-1000,"msg":"An unknown error occured while processing the request."}
|
261
|
+
'-1001': ExchangeNotAvailable, // 'Internal error; unable to process your request. Please try again.'
|
262
|
+
'-1002': AuthenticationError, // 'You are not authorized to execute this request.'
|
263
|
+
'-1003': RateLimitExceeded, // {"code":-1003,"msg":"Too much request weight used, current limit is 1200 request weight per 1 MINUTE. Please use the websocket for live updates to avoid polling the API."}
|
264
|
+
'-1013': InvalidOrder, // createOrder -> 'invalid quantity'/'invalid price'/MIN_NOTIONAL
|
265
|
+
'-1015': RateLimitExceeded, // 'Too many new orders; current limit is %s orders per %s.'
|
266
|
+
'-1016': ExchangeNotAvailable, // 'This service is no longer available.',
|
267
|
+
'-1020': BadRequest, // 'This operation is not supported.'
|
268
|
+
'-1021': InvalidNonce, // 'your time is ahead of server'
|
269
|
+
'-1022': AuthenticationError, // {"code":-1022,"msg":"Signature for this request is not valid."}
|
270
|
+
'-1100': BadRequest, // createOrder(symbol, 1, asdf) -> 'Illegal characters found in parameter 'price'
|
271
|
+
'-1101': BadRequest, // Too many parameters; expected %s and received %s.
|
272
|
+
'-1102': BadRequest, // Param %s or %s must be sent, but both were empty
|
273
|
+
'-1103': BadRequest, // An unknown parameter was sent.
|
274
|
+
'-1104': BadRequest, // Not all sent parameters were read, read 8 parameters but was sent 9
|
275
|
+
'-1105': BadRequest, // Parameter %s was empty.
|
276
|
+
'-1106': BadRequest, // Parameter %s sent when not required.
|
277
|
+
'-1111': BadRequest, // Precision is over the maximum defined for this asset.
|
278
|
+
'-1112': InvalidOrder, // No orders on book for symbol.
|
279
|
+
'-1114': BadRequest, // TimeInForce parameter sent when not required.
|
280
|
+
'-1115': BadRequest, // Invalid timeInForce.
|
281
|
+
'-1116': BadRequest, // Invalid orderType.
|
282
|
+
'-1117': BadRequest, // Invalid side.
|
283
|
+
'-1118': BadRequest, // New client order ID was empty.
|
284
|
+
'-1119': BadRequest, // Original client order ID was empty.
|
285
|
+
'-1120': BadRequest, // Invalid interval.
|
286
|
+
'-1121': BadSymbol, // Invalid symbol.
|
287
|
+
'-1125': AuthenticationError, // This listenKey does not exist.
|
288
|
+
'-1127': BadRequest, // More than %s hours between startTime and endTime.
|
289
|
+
'-1128': BadRequest, // {"code":-1128,"msg":"Combination of optional parameters invalid."}
|
290
|
+
'-1130': BadRequest, // Data sent for paramter %s is not valid.
|
291
|
+
'-1131': BadRequest, // recvWindow must be less than 60000
|
292
|
+
'-2008': AuthenticationError, // {"code":-2008,"msg":"Invalid Api-Key ID."}
|
293
|
+
'-2010': ExchangeError, // generic error code for createOrder -> 'Account has insufficient balance for requested action.', {"code":-2010,"msg":"Rest API trading is not enabled."}, etc...
|
294
|
+
'-2011': OrderNotFound, // cancelOrder(1, 'BTC/USDT') -> 'UNKNOWN_ORDER'
|
295
|
+
'-2013': OrderNotFound, // fetchOrder (1, 'BTC/USDT') -> 'Order does not exist'
|
296
|
+
'-2014': AuthenticationError, // { "code":-2014, "msg": "API-key format invalid." }
|
297
|
+
'-2015': AuthenticationError, // "Invalid API-key, IP, or permissions for action."
|
298
|
+
'-2019': InsufficientFunds, // {"code":-2019,"msg":"Margin is insufficient."}
|
299
|
+
'-3005': InsufficientFunds, // {"code":-3005,"msg":"Transferring out not allowed. Transfer out amount exceeds max amount."}
|
300
|
+
'-3006': InsufficientFunds, // {"code":-3006,"msg":"Your borrow amount has exceed maximum borrow amount."}
|
301
|
+
'-3008': InsufficientFunds, // {"code":-3008,"msg":"Borrow not allowed. Your borrow amount has exceed maximum borrow amount."}
|
302
|
+
'-3010': ExchangeError, // {"code":-3010,"msg":"Repay not allowed. Repay amount exceeds borrow amount."}
|
303
|
+
'-3015': ExchangeError, // {"code":-3015,"msg":"Repay amount exceeds borrow amount."}
|
304
|
+
'-3022': AccountSuspended, // You account's trading is banned.
|
305
|
+
'-4028': BadRequest, // {"code":-4028,"msg":"Leverage 100 is not valid"}
|
306
|
+
'-3020': InsufficientFunds, // {"code":-3020,"msg":"Transfer out amount exceeds max amount."}
|
307
|
+
'-3041': InsufficientFunds, // {"code":-3041,"msg":"Balance is not enough"}
|
308
|
+
'-5013': InsufficientFunds, // Asset transfer failed: insufficient balance"
|
309
|
+
'-11008': InsufficientFunds, // {"code":-11008,"msg":"Exceeding the account's maximum borrowable limit."}
|
310
|
+
'-4051': InsufficientFunds, // {"code":-4051,"msg":"Isolated balance insufficient."}
|
311
|
+
},
|
312
|
+
'broad': {
|
313
|
+
'has no operation privilege': PermissionDenied,
|
314
|
+
'MAX_POSITION': InvalidOrder, // {"code":-2010,"msg":"Filter failure: MAX_POSITION"}
|
315
|
+
},
|
316
|
+
},
|
317
|
+
});
|
318
|
+
}
|
319
|
+
|
320
|
+
costToPrecision (symbol, cost) {
|
321
|
+
return this.decimalToPrecision (cost, TRUNCATE, this.markets[symbol]['precision']['quote'], this.precisionMode, this.paddingMode);
|
322
|
+
}
|
323
|
+
|
324
|
+
currencyToPrecision (code, fee) {
|
325
|
+
// info is available in currencies only if the user has configured his api keys
|
326
|
+
if (this.safeValue (this.currencies[code], 'precision') !== undefined) {
|
327
|
+
return this.decimalToPrecision (fee, TRUNCATE, this.currencies[code]['precision'], this.precisionMode, this.paddingMode);
|
328
|
+
} else {
|
329
|
+
return this.numberToString (fee);
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
nonce () {
|
334
|
+
return this.milliseconds () - this.options['timeDifference'];
|
335
|
+
}
|
336
|
+
|
337
|
+
async fetchStatus (params = {}) {
|
338
|
+
const response = await this.v1PublicGetPing (params);
|
339
|
+
//
|
340
|
+
// empty means working status.
|
341
|
+
//
|
342
|
+
// {}
|
343
|
+
//
|
344
|
+
const keys = Object.keys (response);
|
345
|
+
const keysLength = keys.length;
|
346
|
+
const formattedStatus = keysLength ? 'maintenance' : 'ok';
|
347
|
+
return {
|
348
|
+
'status': formattedStatus,
|
349
|
+
'updated': this.milliseconds (),
|
350
|
+
'eta': undefined,
|
351
|
+
'url': undefined,
|
352
|
+
'info': response,
|
353
|
+
};
|
354
|
+
}
|
355
|
+
|
356
|
+
async fetchTime (params = {}) {
|
357
|
+
const response = await this.v1PublicGetTime (params);
|
358
|
+
//
|
359
|
+
// {
|
360
|
+
// "serverTime":1635467280514
|
361
|
+
// }
|
362
|
+
//
|
363
|
+
return this.safeInteger (response, 'serverTime');
|
364
|
+
}
|
365
|
+
|
366
|
+
safeNetwork (networkId) {
|
367
|
+
const uppercaseNetworkId = networkId.toUpperCase ();
|
368
|
+
const networksById = {
|
369
|
+
'Aeternity': 'Aeternity',
|
370
|
+
'AION': 'AION',
|
371
|
+
'Algorand': 'Algorand',
|
372
|
+
'ASK': 'ASK',
|
373
|
+
'ATOM': 'ATOM',
|
374
|
+
'AVAX C-Chain': 'AVAX C-Chain',
|
375
|
+
'bch': 'bch',
|
376
|
+
'BCH': 'BCH',
|
377
|
+
'BEP2': 'BEP2',
|
378
|
+
'BEP20': 'BEP20',
|
379
|
+
'Bitcoin': 'Bitcoin',
|
380
|
+
'BRP20': 'BRP20',
|
381
|
+
'Cardano': 'ADA',
|
382
|
+
'CasinoCoin': 'CasinoCoin',
|
383
|
+
'CasinoCoin XRPL': 'CasinoCoin XRPL',
|
384
|
+
'Contentos': 'Contentos',
|
385
|
+
'Dash': 'Dash',
|
386
|
+
'Decoin': 'Decoin',
|
387
|
+
'DeFiChain': 'DeFiChain',
|
388
|
+
'DGB': 'DGB',
|
389
|
+
'Divi': 'Divi',
|
390
|
+
'dogecoin': 'DOGE',
|
391
|
+
'EOS': 'EOS',
|
392
|
+
'ERC20': 'ERC20',
|
393
|
+
'ETC': 'ETC',
|
394
|
+
'Filecoin': 'Filecoin',
|
395
|
+
'FREETON': 'FREETON',
|
396
|
+
'HBAR': 'HBAR',
|
397
|
+
'Hedera Hashgraph': 'Hedera Hashgraph',
|
398
|
+
'HRC20': 'HRC20',
|
399
|
+
'ICON': 'ICON',
|
400
|
+
'ICP': 'ICP',
|
401
|
+
'Ignis': 'Ignis',
|
402
|
+
'Internet Computer': 'Internet Computer',
|
403
|
+
'IOTA': 'IOTA',
|
404
|
+
'KAVA': 'KAVA',
|
405
|
+
'KSM': 'KSM',
|
406
|
+
'LiteCoin': 'LiteCoin',
|
407
|
+
'Luna': 'Luna',
|
408
|
+
'MATIC': 'MATIC',
|
409
|
+
'Mobile Coin': 'Mobile Coin',
|
410
|
+
'MonaCoin': 'MonaCoin',
|
411
|
+
'Monero': 'Monero',
|
412
|
+
'NEM': 'NEM',
|
413
|
+
'NEP5': 'NEP5',
|
414
|
+
'OMNI': 'OMNI',
|
415
|
+
'PAC': 'PAC',
|
416
|
+
'Polkadot': 'Polkadot',
|
417
|
+
'Ravencoin': 'Ravencoin',
|
418
|
+
'Safex': 'Safex',
|
419
|
+
'SOLANA': 'SOL',
|
420
|
+
'Songbird': 'Songbird',
|
421
|
+
'Stellar Lumens': 'Stellar Lumens',
|
422
|
+
'Symbol': 'Symbol',
|
423
|
+
'Tezos': 'XTZ',
|
424
|
+
'theta': 'theta',
|
425
|
+
'THETA': 'THETA',
|
426
|
+
'TRC20': 'TRC20',
|
427
|
+
'VeChain': 'VeChain',
|
428
|
+
'VECHAIN': 'VECHAIN',
|
429
|
+
'Wanchain': 'Wanchain',
|
430
|
+
'XinFin Network': 'XinFin Network',
|
431
|
+
'XRP': 'XRP',
|
432
|
+
'XRPL': 'XRPL',
|
433
|
+
'ZIL': 'ZIL',
|
434
|
+
};
|
435
|
+
return this.safeString2 (networksById, networkId, uppercaseNetworkId, networkId);
|
436
|
+
}
|
437
|
+
|
438
|
+
async fetchCurrencies (params = {}) {
|
439
|
+
const response = await this.v1PublicGetExchangeInfo (params);
|
440
|
+
//
|
441
|
+
// {
|
442
|
+
// "timezone":"CTT",
|
443
|
+
// "serverTime":1635464889117,
|
444
|
+
// "rateLimits":[
|
445
|
+
// {"rateLimitType":"REQUESTS_WEIGHT","interval":"MINUTES","limit":6000},
|
446
|
+
// {"rateLimitType":"ORDERS","interval":"SECONDS","limit":150},
|
447
|
+
// {"rateLimitType":"ORDERS","interval":"DAYS","limit":288000},
|
448
|
+
// ],
|
449
|
+
// "exchangeFilters":[],
|
450
|
+
// "symbols":[
|
451
|
+
// {
|
452
|
+
// "symbol":"SHABTC",
|
453
|
+
// "status":"TRADING",
|
454
|
+
// "baseAsset":"sha",
|
455
|
+
// "baseAssetPrecision":0,
|
456
|
+
// "quoteAsset":"btc",
|
457
|
+
// "quotePrecision":10,
|
458
|
+
// "orderTypes":["MARKET","LIMIT"],
|
459
|
+
// "icebergAllowed":false,
|
460
|
+
// "filters":[
|
461
|
+
// {"filterType":"PRICE_FILTER","minPrice":"0.00000001349","maxPrice":"0.00000017537","priceScale":10},
|
462
|
+
// {"filterType":"LOT_SIZE","minQty":"1.0","minVal":"0.00020","maxQty":"1000000000","volumeScale":0},
|
463
|
+
// ],
|
464
|
+
// "defaultPrice":"0.0000006100",
|
465
|
+
// },
|
466
|
+
// ],
|
467
|
+
// "coins":[
|
468
|
+
// {
|
469
|
+
// "coin":"sbr",
|
470
|
+
// "coinFulName":"Saber",
|
471
|
+
// "enableWithdraw":true,
|
472
|
+
// "enableDeposit":true,
|
473
|
+
// "chains":["SOLANA"],
|
474
|
+
// "withdrawFee":"2.0",
|
475
|
+
// "minWithdraw":"5.0",
|
476
|
+
// "maxWithdraw":"1000000000000000",
|
477
|
+
// },
|
478
|
+
// ],
|
479
|
+
// }
|
480
|
+
//
|
481
|
+
const result = {};
|
482
|
+
const coins = this.safeValue (response, 'coins', []);
|
483
|
+
for (let i = 0; i < coins.length; i++) {
|
484
|
+
const currency = coins[i];
|
485
|
+
const id = this.safeString (currency, 'coin');
|
486
|
+
const name = this.safeString (currency, 'coinFulName');
|
487
|
+
const code = this.safeCurrencyCode (id);
|
488
|
+
const enableDeposit = this.safeValue (currency, 'enableDeposit');
|
489
|
+
const enableWithdraw = this.safeValue (currency, 'enableWithdraw');
|
490
|
+
const precision = undefined;
|
491
|
+
const networkIds = this.safeValue (currency, 'chains', []);
|
492
|
+
const networks = {};
|
493
|
+
for (let j = 0; j < networkIds.length; j++) {
|
494
|
+
const networkId = networkIds[j];
|
495
|
+
const network = this.safeNetwork (networkId);
|
496
|
+
networks[network] = {
|
497
|
+
'info': networkId,
|
498
|
+
'id': networkId,
|
499
|
+
'network': network,
|
500
|
+
'active': undefined,
|
501
|
+
'fee': undefined,
|
502
|
+
'precision': undefined,
|
503
|
+
'limits': {
|
504
|
+
'withdraw': {
|
505
|
+
'min': undefined,
|
506
|
+
'max': undefined,
|
507
|
+
},
|
508
|
+
},
|
509
|
+
};
|
510
|
+
}
|
511
|
+
const active = (enableWithdraw && enableDeposit);
|
512
|
+
result[code] = {
|
513
|
+
'id': id,
|
514
|
+
'name': name,
|
515
|
+
'code': code,
|
516
|
+
'precision': precision,
|
517
|
+
'info': currency,
|
518
|
+
'active': active,
|
519
|
+
'deposit': enableDeposit,
|
520
|
+
'withdraw': enableWithdraw,
|
521
|
+
'networks': networks,
|
522
|
+
'fee': this.safeNumber (currency, 'withdrawFee'),
|
523
|
+
// 'fees': fees,
|
524
|
+
'limits': {
|
525
|
+
'withdraw': {
|
526
|
+
'min': this.safeNumber (currency, 'minWithdraw'),
|
527
|
+
'max': this.safeNumber (currency, 'maxWithdraw'),
|
528
|
+
},
|
529
|
+
},
|
530
|
+
};
|
531
|
+
}
|
532
|
+
return result;
|
533
|
+
}
|
534
|
+
|
535
|
+
async fetchMarkets (params = {}) {
|
536
|
+
const response = await this.v1PublicGetExchangeInfo (params);
|
537
|
+
//
|
538
|
+
// {
|
539
|
+
// "timezone":"CTT",
|
540
|
+
// "serverTime":1635464889117,
|
541
|
+
// "rateLimits":[
|
542
|
+
// {"rateLimitType":"REQUESTS_WEIGHT","interval":"MINUTES","limit":6000},
|
543
|
+
// {"rateLimitType":"ORDERS","interval":"SECONDS","limit":150},
|
544
|
+
// {"rateLimitType":"ORDERS","interval":"DAYS","limit":288000},
|
545
|
+
// ],
|
546
|
+
// "exchangeFilters":[],
|
547
|
+
// "symbols":[
|
548
|
+
// {
|
549
|
+
// "symbol":"SHABTC",
|
550
|
+
// "status":"TRADING",
|
551
|
+
// "baseAsset":"sha",
|
552
|
+
// "baseAssetPrecision":0,
|
553
|
+
// "quoteAsset":"btc",
|
554
|
+
// "quotePrecision":10,
|
555
|
+
// "orderTypes":["MARKET","LIMIT"],
|
556
|
+
// "icebergAllowed":false,
|
557
|
+
// "filters":[
|
558
|
+
// {"filterType":"PRICE_FILTER","minPrice":"0.00000001349","maxPrice":"0.00000017537","priceScale":10},
|
559
|
+
// {"filterType":"LOT_SIZE","minQty":"1.0","minVal":"0.00020","maxQty":"1000000000","volumeScale":0},
|
560
|
+
// ],
|
561
|
+
// "defaultPrice":"0.0000006100",
|
562
|
+
// },
|
563
|
+
// ],
|
564
|
+
// "coins":[
|
565
|
+
// {
|
566
|
+
// "coin":"sbr",
|
567
|
+
// "coinFulName":"Saber",
|
568
|
+
// "enableWithdraw":true,
|
569
|
+
// "enableDeposit":true,
|
570
|
+
// "chains":["SOLANA"],
|
571
|
+
// "withdrawFee":"2.0",
|
572
|
+
// "minWithdraw":"5.0",
|
573
|
+
// "maxWithdraw":"1000000000000000",
|
574
|
+
// },
|
575
|
+
// ],
|
576
|
+
// }
|
577
|
+
//
|
578
|
+
if (this.options['adjustForTimeDifference']) {
|
579
|
+
await this.loadTimeDifference ();
|
580
|
+
}
|
581
|
+
const markets = this.safeValue (response, 'symbols', []);
|
582
|
+
const result = [];
|
583
|
+
for (let i = 0; i < markets.length; i++) {
|
584
|
+
const market = markets[i];
|
585
|
+
const id = this.safeString (market, 'symbol');
|
586
|
+
const lowercaseId = this.safeStringLower (market, 'symbol');
|
587
|
+
const baseId = this.safeString (market, 'baseAsset');
|
588
|
+
const quoteId = this.safeString (market, 'quoteAsset');
|
589
|
+
const base = this.safeCurrencyCode (baseId);
|
590
|
+
const quote = this.safeCurrencyCode (quoteId);
|
591
|
+
const filters = this.safeValue (market, 'filters', []);
|
592
|
+
const filtersByType = this.indexBy (filters, 'filterType');
|
593
|
+
const status = this.safeString (market, 'status');
|
594
|
+
const priceDefault = this.safeInteger (market, 'pricePrecision');
|
595
|
+
const amountDefault = this.safeInteger (market, 'quantityPrecision');
|
596
|
+
const priceFilter = this.safeValue (filtersByType, 'PRICE_FILTER', {});
|
597
|
+
const amountFilter = this.safeValue (filtersByType, 'LOT_SIZE', {});
|
598
|
+
const entry = {
|
599
|
+
'id': id,
|
600
|
+
'lowercaseId': lowercaseId,
|
601
|
+
'symbol': base + '/' + quote,
|
602
|
+
'base': base,
|
603
|
+
'quote': quote,
|
604
|
+
'settle': undefined,
|
605
|
+
'baseId': baseId,
|
606
|
+
'quoteId': quoteId,
|
607
|
+
'settleId': undefined,
|
608
|
+
'type': 'spot',
|
609
|
+
'spot': true,
|
610
|
+
'margin': false,
|
611
|
+
'swap': false,
|
612
|
+
'future': false,
|
613
|
+
'option': false,
|
614
|
+
'active': (status === 'TRADING'),
|
615
|
+
'contract': false,
|
616
|
+
'linear': undefined,
|
617
|
+
'inverse': undefined,
|
618
|
+
'contractSize': undefined,
|
619
|
+
'expiry': undefined,
|
620
|
+
'expiryDatetime': undefined,
|
621
|
+
'strike': undefined,
|
622
|
+
'optionType': undefined,
|
623
|
+
'precision': {
|
624
|
+
'amount': this.safeInteger (amountFilter, 'volumeScale', amountDefault),
|
625
|
+
'price': this.safeInteger (priceFilter, 'priceScale', priceDefault),
|
626
|
+
'base': this.safeInteger (market, 'baseAssetPrecision'),
|
627
|
+
'quote': this.safeInteger (market, 'quotePrecision'),
|
628
|
+
},
|
629
|
+
'limits': {
|
630
|
+
'leverage': {
|
631
|
+
'min': undefined,
|
632
|
+
'max': undefined,
|
633
|
+
},
|
634
|
+
'amount': {
|
635
|
+
'min': this.safeNumber (amountFilter, 'minQty'),
|
636
|
+
'max': this.safeNumber (amountFilter, 'maxQty'),
|
637
|
+
},
|
638
|
+
'price': {
|
639
|
+
'min': this.safeNumber (priceFilter, 'minPrice'),
|
640
|
+
'max': this.safeNumber (priceFilter, 'maxPrice'),
|
641
|
+
},
|
642
|
+
'cost': {
|
643
|
+
'min': this.safeNumber (amountFilter, 'minVal'),
|
644
|
+
'max': undefined,
|
645
|
+
},
|
646
|
+
},
|
647
|
+
'info': market,
|
648
|
+
};
|
649
|
+
result.push (entry);
|
650
|
+
}
|
651
|
+
return result;
|
652
|
+
}
|
653
|
+
|
654
|
+
parseBalance (response) {
|
655
|
+
const result = {
|
656
|
+
'info': response,
|
657
|
+
};
|
658
|
+
const timestamp = this.safeInteger (response, 'updateTime');
|
659
|
+
const balances = this.safeValue2 (response, 'balances', []);
|
660
|
+
for (let i = 0; i < balances.length; i++) {
|
661
|
+
const balance = balances[i];
|
662
|
+
const currencyId = this.safeString (balance, 'asset');
|
663
|
+
const code = this.safeCurrencyCode (currencyId);
|
664
|
+
const account = this.account ();
|
665
|
+
account['free'] = this.safeString (balance, 'free');
|
666
|
+
account['used'] = this.safeString (balance, 'locked');
|
667
|
+
result[code] = account;
|
668
|
+
}
|
669
|
+
result['timestamp'] = timestamp;
|
670
|
+
result['datetime'] = this.iso8601 (timestamp);
|
671
|
+
return this.safeBalance (result);
|
672
|
+
}
|
673
|
+
|
674
|
+
async fetchBalance (params = {}) {
|
675
|
+
await this.loadMarkets ();
|
676
|
+
const response = await this.v1PrivateGetAccount (params);
|
677
|
+
//
|
678
|
+
// {
|
679
|
+
// "makerCommission":0,
|
680
|
+
// "takerCommission":0,
|
681
|
+
// "buyerCommission":0,
|
682
|
+
// "sellerCommission":0,
|
683
|
+
// "updateTime":null,
|
684
|
+
// "balances":[
|
685
|
+
// {"asset":"sbr","free":"0","locked":"0"},
|
686
|
+
// {"asset":"ksm","free":"0","locked":"0"},
|
687
|
+
// {"asset":"neo3s","free":"0","locked":"0"},
|
688
|
+
// ],
|
689
|
+
// "canTrade":false,
|
690
|
+
// "canWithdraw":false,
|
691
|
+
// "canDeposit":false
|
692
|
+
// }
|
693
|
+
//
|
694
|
+
return this.parseBalance (response);
|
695
|
+
}
|
696
|
+
|
697
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
698
|
+
await this.loadMarkets ();
|
699
|
+
const market = this.market (symbol);
|
700
|
+
const request = {
|
701
|
+
'symbol': market['id'],
|
702
|
+
};
|
703
|
+
if (limit !== undefined) {
|
704
|
+
request['limit'] = limit; // default 100, max 1000, see https://github.com/Bitrue-exchange/bitrue-official-api-docs#order-book
|
705
|
+
}
|
706
|
+
const response = await this.v1PublicGetDepth (this.extend (request, params));
|
707
|
+
//
|
708
|
+
// {
|
709
|
+
// "lastUpdateId":1635474910177,
|
710
|
+
// "bids":[
|
711
|
+
// ["61436.84","0.05",[]],
|
712
|
+
// ["61435.77","0.0124",[]],
|
713
|
+
// ["61434.88","0.012",[]],
|
714
|
+
// ],
|
715
|
+
// "asks":[
|
716
|
+
// ["61452.46","0.0001",[]],
|
717
|
+
// ["61452.47","0.0597",[]],
|
718
|
+
// ["61452.76","0.0713",[]],
|
719
|
+
// ]
|
720
|
+
// }
|
721
|
+
//
|
722
|
+
const orderbook = this.parseOrderBook (response, symbol);
|
723
|
+
orderbook['nonce'] = this.safeInteger (response, 'lastUpdateId');
|
724
|
+
return orderbook;
|
725
|
+
}
|
726
|
+
|
727
|
+
parseTicker (ticker, market = undefined) {
|
728
|
+
//
|
729
|
+
// fetchTicker
|
730
|
+
//
|
731
|
+
// {
|
732
|
+
// "id":397945892,
|
733
|
+
// "last":"1.143411",
|
734
|
+
// "lowestAsk":"1.144223",
|
735
|
+
// "highestBid":"1.141696",
|
736
|
+
// "percentChange":"-0.001432",
|
737
|
+
// "baseVolume":"338287",
|
738
|
+
// "quoteVolume":"415013.244366",
|
739
|
+
// "isFrozen":"0",
|
740
|
+
// "high24hr":"1.370087",
|
741
|
+
// "low24hr":"1.370087",
|
742
|
+
// }
|
743
|
+
//
|
744
|
+
const symbol = this.safeSymbol (undefined, market);
|
745
|
+
const last = this.safeString (ticker, 'last');
|
746
|
+
return this.safeTicker ({
|
747
|
+
'symbol': symbol,
|
748
|
+
'timestamp': undefined,
|
749
|
+
'datetime': undefined,
|
750
|
+
'high': this.safeString (ticker, 'high24hr'),
|
751
|
+
'low': this.safeString (ticker, 'low24hr'),
|
752
|
+
'bid': this.safeString (ticker, 'highestBid'),
|
753
|
+
'bidVolume': undefined,
|
754
|
+
'ask': this.safeString (ticker, 'lowestAsk'),
|
755
|
+
'askVolume': undefined,
|
756
|
+
'vwap': undefined,
|
757
|
+
'open': undefined,
|
758
|
+
'close': last,
|
759
|
+
'last': last,
|
760
|
+
'previousClose': undefined,
|
761
|
+
'change': undefined,
|
762
|
+
'percentage': this.safeString (ticker, 'percentChange'),
|
763
|
+
'average': undefined,
|
764
|
+
'baseVolume': this.safeString (ticker, 'baseVolume'),
|
765
|
+
'quoteVolume': this.safeString (ticker, 'quoteVolume'),
|
766
|
+
'info': ticker,
|
767
|
+
}, market, false);
|
768
|
+
}
|
769
|
+
|
770
|
+
async fetchTicker (symbol, params = {}) {
|
771
|
+
await this.loadMarkets ();
|
772
|
+
const market = this.market (symbol);
|
773
|
+
const uppercaseBaseId = this.safeStringUpper (market, 'baseId');
|
774
|
+
const uppercaseQuoteId = this.safeStringUpper (market, 'quoteId');
|
775
|
+
const request = {
|
776
|
+
'currency': uppercaseQuoteId,
|
777
|
+
'command': 'returnTicker',
|
778
|
+
};
|
779
|
+
const response = await this.klinePublicGetPublicCurrencyJson (this.extend (request, params));
|
780
|
+
//
|
781
|
+
// {
|
782
|
+
// "code":"200",
|
783
|
+
// "msg":"success",
|
784
|
+
// "data":{
|
785
|
+
// "DODO3S_USDT":{
|
786
|
+
// "id":397945892,
|
787
|
+
// "last":"1.143411",
|
788
|
+
// "lowestAsk":"1.144223",
|
789
|
+
// "highestBid":"1.141696",
|
790
|
+
// "percentChange":"-0.001432",
|
791
|
+
// "baseVolume":"338287",
|
792
|
+
// "quoteVolume":"415013.244366",
|
793
|
+
// "isFrozen":"0",
|
794
|
+
// "high24hr":"1.370087",
|
795
|
+
// "low24hr":"1.370087"
|
796
|
+
// }
|
797
|
+
// }
|
798
|
+
// }
|
799
|
+
//
|
800
|
+
const data = this.safeValue (response, 'data', {});
|
801
|
+
const id = uppercaseBaseId + '_' + uppercaseQuoteId;
|
802
|
+
const ticker = this.safeValue (data, id);
|
803
|
+
if (ticker === undefined) {
|
804
|
+
throw new ExchangeError (this.id + ' fetchTicker() could not find the ticker for ' + market['symbol']);
|
805
|
+
}
|
806
|
+
return this.parseTicker (ticker, market);
|
807
|
+
}
|
808
|
+
|
809
|
+
async fetchBidsAsks (symbols = undefined, params = {}) {
|
810
|
+
await this.loadMarkets ();
|
811
|
+
const defaultType = this.safeString2 (this.options, 'fetchBidsAsks', 'defaultType', 'spot');
|
812
|
+
const type = this.safeString (params, 'type', defaultType);
|
813
|
+
const query = this.omit (params, 'type');
|
814
|
+
let method = undefined;
|
815
|
+
if (type === 'future') {
|
816
|
+
method = 'fapiPublicGetTickerBookTicker';
|
817
|
+
} else if (type === 'delivery') {
|
818
|
+
method = 'dapiPublicGetTickerBookTicker';
|
819
|
+
} else {
|
820
|
+
method = 'publicGetTickerBookTicker';
|
821
|
+
}
|
822
|
+
const response = await this[method] (query);
|
823
|
+
return this.parseTickers (response, symbols);
|
824
|
+
}
|
825
|
+
|
826
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
827
|
+
await this.loadMarkets ();
|
828
|
+
const request = {
|
829
|
+
'command': 'returnTicker',
|
830
|
+
};
|
831
|
+
const response = await this.klinePublicGetPublicJson (this.extend (request, params));
|
832
|
+
//
|
833
|
+
// {
|
834
|
+
// "code":"200",
|
835
|
+
// "msg":"success",
|
836
|
+
// "data":{
|
837
|
+
// "DODO3S_USDT":{
|
838
|
+
// "id":397945892,
|
839
|
+
// "last":"1.143411",
|
840
|
+
// "lowestAsk":"1.144223",
|
841
|
+
// "highestBid":"1.141696",
|
842
|
+
// "percentChange":"-0.001432",
|
843
|
+
// "baseVolume":"338287",
|
844
|
+
// "quoteVolume":"415013.244366",
|
845
|
+
// "isFrozen":"0",
|
846
|
+
// "high24hr":"1.370087",
|
847
|
+
// "low24hr":"1.370087"
|
848
|
+
// }
|
849
|
+
// }
|
850
|
+
// }
|
851
|
+
//
|
852
|
+
const data = this.safeValue (response, 'data', {});
|
853
|
+
const ids = Object.keys (data);
|
854
|
+
const result = {};
|
855
|
+
for (let i = 0; i < ids.length; i++) {
|
856
|
+
const id = ids[i];
|
857
|
+
const [ baseId, quoteId ] = id.split ('_');
|
858
|
+
const marketId = baseId + quoteId;
|
859
|
+
const market = this.safeMarket (marketId);
|
860
|
+
const rawTicker = this.safeValue (data, id);
|
861
|
+
const ticker = this.parseTicker (rawTicker, market);
|
862
|
+
const symbol = ticker['symbol'];
|
863
|
+
result[symbol] = ticker;
|
864
|
+
}
|
865
|
+
return result;
|
866
|
+
}
|
867
|
+
|
868
|
+
parseTrade (trade, market = undefined) {
|
869
|
+
//
|
870
|
+
// aggregate trades
|
871
|
+
//
|
872
|
+
// {
|
873
|
+
// "a": 26129, // Aggregate tradeId
|
874
|
+
// "p": "0.01633102", // Price
|
875
|
+
// "q": "4.70443515", // Quantity
|
876
|
+
// "f": 27781, // First tradeId
|
877
|
+
// "l": 27781, // Last tradeId
|
878
|
+
// "T": 1498793709153, // Timestamp
|
879
|
+
// "m": true, // Was the buyer the maker?
|
880
|
+
// "M": true // Was the trade the best price match?
|
881
|
+
// }
|
882
|
+
//
|
883
|
+
// recent public trades and old public trades
|
884
|
+
//
|
885
|
+
// {
|
886
|
+
// "id": 28457,
|
887
|
+
// "price": "4.00000100",
|
888
|
+
// "qty": "12.00000000",
|
889
|
+
// "time": 1499865549590,
|
890
|
+
// "isBuyerMaker": true,
|
891
|
+
// "isBestMatch": true
|
892
|
+
// }
|
893
|
+
//
|
894
|
+
// private trades
|
895
|
+
//
|
896
|
+
// {
|
897
|
+
// "symbol":"USDCUSDT",
|
898
|
+
// "id":20725156,
|
899
|
+
// "orderId":2880918576,
|
900
|
+
// "origClientOrderId":null,
|
901
|
+
// "price":"0.9996000000000000",
|
902
|
+
// "qty":"100.0000000000000000",
|
903
|
+
// "commission":null,
|
904
|
+
// "commissionAssert":null,
|
905
|
+
// "time":1635558511000,
|
906
|
+
// "isBuyer":false,
|
907
|
+
// "isMaker":false,
|
908
|
+
// "isBestMatch":true
|
909
|
+
// }
|
910
|
+
//
|
911
|
+
const timestamp = this.safeInteger2 (trade, 'T', 'time');
|
912
|
+
const priceString = this.safeString2 (trade, 'p', 'price');
|
913
|
+
const amountString = this.safeString2 (trade, 'q', 'qty');
|
914
|
+
const marketId = this.safeString (trade, 'symbol');
|
915
|
+
const symbol = this.safeSymbol (marketId, market);
|
916
|
+
let id = this.safeString2 (trade, 't', 'a');
|
917
|
+
id = this.safeString2 (trade, 'id', 'tradeId', id);
|
918
|
+
let side = undefined;
|
919
|
+
const orderId = this.safeString (trade, 'orderId');
|
920
|
+
if ('m' in trade) {
|
921
|
+
side = trade['m'] ? 'sell' : 'buy'; // this is reversed intentionally
|
922
|
+
} else if ('isBuyerMaker' in trade) {
|
923
|
+
side = trade['isBuyerMaker'] ? 'sell' : 'buy';
|
924
|
+
} else if ('side' in trade) {
|
925
|
+
side = this.safeStringLower (trade, 'side');
|
926
|
+
} else {
|
927
|
+
if ('isBuyer' in trade) {
|
928
|
+
side = trade['isBuyer'] ? 'buy' : 'sell'; // this is a true side
|
929
|
+
}
|
930
|
+
}
|
931
|
+
let fee = undefined;
|
932
|
+
if ('commission' in trade) {
|
933
|
+
fee = {
|
934
|
+
'cost': this.safeString (trade, 'commission'),
|
935
|
+
'currency': this.safeCurrencyCode (this.safeString (trade, 'commissionAssert')),
|
936
|
+
};
|
937
|
+
}
|
938
|
+
let takerOrMaker = undefined;
|
939
|
+
if ('isMaker' in trade) {
|
940
|
+
takerOrMaker = trade['isMaker'] ? 'maker' : 'taker';
|
941
|
+
}
|
942
|
+
if ('maker' in trade) {
|
943
|
+
takerOrMaker = trade['maker'] ? 'maker' : 'taker';
|
944
|
+
}
|
945
|
+
return this.safeTrade ({
|
946
|
+
'info': trade,
|
947
|
+
'timestamp': timestamp,
|
948
|
+
'datetime': this.iso8601 (timestamp),
|
949
|
+
'symbol': symbol,
|
950
|
+
'id': id,
|
951
|
+
'order': orderId,
|
952
|
+
'type': undefined,
|
953
|
+
'side': side,
|
954
|
+
'takerOrMaker': takerOrMaker,
|
955
|
+
'price': priceString,
|
956
|
+
'amount': amountString,
|
957
|
+
'cost': undefined,
|
958
|
+
'fee': fee,
|
959
|
+
}, market);
|
960
|
+
}
|
961
|
+
|
962
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
963
|
+
await this.loadMarkets ();
|
964
|
+
const market = this.market (symbol);
|
965
|
+
const request = {
|
966
|
+
'symbol': market['id'],
|
967
|
+
// 'limit': 100, // default 100, max = 1000
|
968
|
+
};
|
969
|
+
const method = this.safeString (this.options, 'fetchTradesMethod', 'v1PublicGetAggTrades');
|
970
|
+
if (limit !== undefined) {
|
971
|
+
request['limit'] = limit; // default 100, max 1000
|
972
|
+
}
|
973
|
+
//
|
974
|
+
// Caveats:
|
975
|
+
// - default limit (500) applies only if no other parameters set, trades up
|
976
|
+
// to the maximum limit may be returned to satisfy other parameters
|
977
|
+
// - if both limit and time window is set and time window contains more
|
978
|
+
// trades than the limit then the last trades from the window are returned
|
979
|
+
// - 'tradeId' accepted and returned by this method is "aggregate" trade id
|
980
|
+
// which is different from actual trade id
|
981
|
+
// - setting both fromId and time window results in error
|
982
|
+
const response = await this[method] (this.extend (request, params));
|
983
|
+
//
|
984
|
+
// aggregate trades
|
985
|
+
//
|
986
|
+
// [
|
987
|
+
// {
|
988
|
+
// "a": 26129, // Aggregate tradeId
|
989
|
+
// "p": "0.01633102", // Price
|
990
|
+
// "q": "4.70443515", // Quantity
|
991
|
+
// "f": 27781, // First tradeId
|
992
|
+
// "l": 27781, // Last tradeId
|
993
|
+
// "T": 1498793709153, // Timestamp
|
994
|
+
// "m": true, // Was the buyer the maker?
|
995
|
+
// "M": true // Was the trade the best price match?
|
996
|
+
// }
|
997
|
+
// ]
|
998
|
+
//
|
999
|
+
// recent public trades and historical public trades
|
1000
|
+
//
|
1001
|
+
// [
|
1002
|
+
// {
|
1003
|
+
// "id": 28457,
|
1004
|
+
// "price": "4.00000100",
|
1005
|
+
// "qty": "12.00000000",
|
1006
|
+
// "time": 1499865549590,
|
1007
|
+
// "isBuyerMaker": true,
|
1008
|
+
// "isBestMatch": true
|
1009
|
+
// }
|
1010
|
+
// ]
|
1011
|
+
//
|
1012
|
+
return this.parseTrades (response, market, since, limit);
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
parseOrderStatus (status) {
|
1016
|
+
const statuses = {
|
1017
|
+
'NEW': 'open',
|
1018
|
+
'PARTIALLY_FILLED': 'open',
|
1019
|
+
'FILLED': 'closed',
|
1020
|
+
'CANCELED': 'canceled',
|
1021
|
+
'PENDING_CANCEL': 'canceling', // currently unused
|
1022
|
+
'REJECTED': 'rejected',
|
1023
|
+
'EXPIRED': 'expired',
|
1024
|
+
};
|
1025
|
+
return this.safeString (statuses, status, status);
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
parseOrder (order, market = undefined) {
|
1029
|
+
//
|
1030
|
+
// createOrder
|
1031
|
+
//
|
1032
|
+
// {
|
1033
|
+
// "symbol":"USDCUSDT",
|
1034
|
+
// "orderId":2878854881,
|
1035
|
+
// "clientOrderId":"",
|
1036
|
+
// "transactTime":1635551031276
|
1037
|
+
// }
|
1038
|
+
//
|
1039
|
+
// fetchOpenOrders
|
1040
|
+
//
|
1041
|
+
// {
|
1042
|
+
// "symbol":"USDCUSDT",
|
1043
|
+
// "orderId":"2878854881",
|
1044
|
+
// "clientOrderId":"",
|
1045
|
+
// "price":"1.1000000000000000",
|
1046
|
+
// "origQty":"100.0000000000000000",
|
1047
|
+
// "executedQty":"0.0000000000000000",
|
1048
|
+
// "cummulativeQuoteQty":"0.0000000000000000",
|
1049
|
+
// "status":"NEW",
|
1050
|
+
// "timeInForce":"",
|
1051
|
+
// "type":"LIMIT",
|
1052
|
+
// "side":"SELL",
|
1053
|
+
// "stopPrice":"",
|
1054
|
+
// "icebergQty":"",
|
1055
|
+
// "time":1635551031000,
|
1056
|
+
// "updateTime":1635551031000,
|
1057
|
+
// "isWorking":false
|
1058
|
+
// }
|
1059
|
+
//
|
1060
|
+
const status = this.parseOrderStatus (this.safeString (order, 'status'));
|
1061
|
+
const marketId = this.safeString (order, 'symbol');
|
1062
|
+
const symbol = this.safeSymbol (marketId, market);
|
1063
|
+
const filled = this.safeString (order, 'executedQty');
|
1064
|
+
let timestamp = undefined;
|
1065
|
+
let lastTradeTimestamp = undefined;
|
1066
|
+
if ('time' in order) {
|
1067
|
+
timestamp = this.safeInteger (order, 'time');
|
1068
|
+
} else if ('transactTime' in order) {
|
1069
|
+
timestamp = this.safeInteger (order, 'transactTime');
|
1070
|
+
} else if ('updateTime' in order) {
|
1071
|
+
if (status === 'open') {
|
1072
|
+
if (Precise.stringGt (filled, '0')) {
|
1073
|
+
lastTradeTimestamp = this.safeInteger (order, 'updateTime');
|
1074
|
+
} else {
|
1075
|
+
timestamp = this.safeInteger (order, 'updateTime');
|
1076
|
+
}
|
1077
|
+
}
|
1078
|
+
}
|
1079
|
+
const average = this.safeString (order, 'avgPrice');
|
1080
|
+
const price = this.safeString (order, 'price');
|
1081
|
+
const amount = this.safeString (order, 'origQty');
|
1082
|
+
// - Spot/Margin market: cummulativeQuoteQty
|
1083
|
+
// - Futures market: cumQuote.
|
1084
|
+
// Note this is not the actual cost, since Binance futures uses leverage to calculate margins.
|
1085
|
+
const cost = this.safeString2 (order, 'cummulativeQuoteQty', 'cumQuote');
|
1086
|
+
const id = this.safeString (order, 'orderId');
|
1087
|
+
let type = this.safeStringLower (order, 'type');
|
1088
|
+
const side = this.safeStringLower (order, 'side');
|
1089
|
+
const fills = this.safeValue (order, 'fills', []);
|
1090
|
+
let clientOrderId = this.safeString (order, 'clientOrderId');
|
1091
|
+
if (clientOrderId === '') {
|
1092
|
+
clientOrderId = undefined;
|
1093
|
+
}
|
1094
|
+
const timeInForce = this.safeString (order, 'timeInForce');
|
1095
|
+
const postOnly = (type === 'limit_maker') || (timeInForce === 'GTX');
|
1096
|
+
if (type === 'limit_maker') {
|
1097
|
+
type = 'limit';
|
1098
|
+
}
|
1099
|
+
const stopPriceString = this.safeString (order, 'stopPrice');
|
1100
|
+
const stopPrice = this.parseNumber (this.omitZero (stopPriceString));
|
1101
|
+
return this.safeOrder ({
|
1102
|
+
'info': order,
|
1103
|
+
'id': id,
|
1104
|
+
'clientOrderId': clientOrderId,
|
1105
|
+
'timestamp': timestamp,
|
1106
|
+
'datetime': this.iso8601 (timestamp),
|
1107
|
+
'lastTradeTimestamp': lastTradeTimestamp,
|
1108
|
+
'symbol': symbol,
|
1109
|
+
'type': type,
|
1110
|
+
'timeInForce': timeInForce,
|
1111
|
+
'postOnly': postOnly,
|
1112
|
+
'side': side,
|
1113
|
+
'price': price,
|
1114
|
+
'stopPrice': stopPrice,
|
1115
|
+
'amount': amount,
|
1116
|
+
'cost': cost,
|
1117
|
+
'average': average,
|
1118
|
+
'filled': filled,
|
1119
|
+
'remaining': undefined,
|
1120
|
+
'status': status,
|
1121
|
+
'fee': undefined,
|
1122
|
+
'trades': fills,
|
1123
|
+
}, market);
|
1124
|
+
}
|
1125
|
+
|
1126
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1127
|
+
await this.loadMarkets ();
|
1128
|
+
const market = this.market (symbol);
|
1129
|
+
const uppercaseType = type.toUpperCase ();
|
1130
|
+
const validOrderTypes = this.safeValue (market['info'], 'orderTypes');
|
1131
|
+
if (!this.inArray (uppercaseType, validOrderTypes)) {
|
1132
|
+
throw new InvalidOrder (this.id + ' ' + type + ' is not a valid order type in market ' + symbol);
|
1133
|
+
}
|
1134
|
+
const request = {
|
1135
|
+
'symbol': market['id'],
|
1136
|
+
'side': side.toUpperCase (),
|
1137
|
+
'type': uppercaseType,
|
1138
|
+
// 'timeInForce': '',
|
1139
|
+
'quantity': this.amountToPrecision (symbol, amount),
|
1140
|
+
// 'price': this.priceToPrecision (symbol, price),
|
1141
|
+
// 'newClientOrderId': clientOrderId, // automatically generated if not sent
|
1142
|
+
// 'stopPrice': this.priceToPrecision (symbol, 'stopPrice'),
|
1143
|
+
// 'icebergQty': this.amountToPrecision (symbol, icebergQty),
|
1144
|
+
};
|
1145
|
+
const clientOrderId = this.safeString2 (params, 'newClientOrderId', 'clientOrderId');
|
1146
|
+
if (clientOrderId !== undefined) {
|
1147
|
+
params = this.omit (params, [ 'newClientOrderId', 'clientOrderId' ]);
|
1148
|
+
request['newClientOrderId'] = clientOrderId;
|
1149
|
+
}
|
1150
|
+
if (uppercaseType === 'LIMIT') {
|
1151
|
+
if (price === undefined) {
|
1152
|
+
throw new InvalidOrder (this.id + ' createOrder() requires a price argument');
|
1153
|
+
}
|
1154
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1155
|
+
}
|
1156
|
+
const stopPrice = this.safeNumber (params, 'stopPrice');
|
1157
|
+
if (stopPrice !== undefined) {
|
1158
|
+
params = this.omit (params, 'stopPrice');
|
1159
|
+
request['stopPrice'] = this.priceToPrecision (symbol, stopPrice);
|
1160
|
+
}
|
1161
|
+
const response = await this.v1PrivatePostOrder (this.extend (request, params));
|
1162
|
+
//
|
1163
|
+
// {
|
1164
|
+
// "symbol":"USDCUSDT",
|
1165
|
+
// "orderId":2878854881,
|
1166
|
+
// "clientOrderId":"",
|
1167
|
+
// "transactTime":1635551031276
|
1168
|
+
// }
|
1169
|
+
//
|
1170
|
+
return this.parseOrder (response, market);
|
1171
|
+
}
|
1172
|
+
|
1173
|
+
async fetchOrder (id, symbol = undefined, params = {}) {
|
1174
|
+
if (symbol === undefined) {
|
1175
|
+
throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument');
|
1176
|
+
}
|
1177
|
+
await this.loadMarkets ();
|
1178
|
+
const market = this.market (symbol);
|
1179
|
+
const request = {
|
1180
|
+
'symbol': market['id'],
|
1181
|
+
};
|
1182
|
+
const clientOrderId = this.safeValue2 (params, 'origClientOrderId', 'clientOrderId');
|
1183
|
+
if (clientOrderId !== undefined) {
|
1184
|
+
request['origClientOrderId'] = clientOrderId;
|
1185
|
+
} else {
|
1186
|
+
request['orderId'] = id;
|
1187
|
+
}
|
1188
|
+
const query = this.omit (params, [ 'type', 'clientOrderId', 'origClientOrderId' ]);
|
1189
|
+
const response = await this.v1PrivateGetOrder (this.extend (request, query));
|
1190
|
+
return this.parseOrder (response, market);
|
1191
|
+
}
|
1192
|
+
|
1193
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1194
|
+
if (symbol === undefined) {
|
1195
|
+
throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
|
1196
|
+
}
|
1197
|
+
await this.loadMarkets ();
|
1198
|
+
const market = this.market (symbol);
|
1199
|
+
const request = {
|
1200
|
+
'symbol': market['id'],
|
1201
|
+
// 'orderId': 123445, // long
|
1202
|
+
// 'startTime': since,
|
1203
|
+
// 'endTime': this.milliseconds (),
|
1204
|
+
// 'limit': limit, // default 100, max 1000
|
1205
|
+
};
|
1206
|
+
if (since !== undefined) {
|
1207
|
+
request['startTime'] = since;
|
1208
|
+
}
|
1209
|
+
if (limit !== undefined) {
|
1210
|
+
request['limit'] = limit; // default 100, max 1000
|
1211
|
+
}
|
1212
|
+
const response = await this.v1PrivateGetAllOrders (this.extend (request, params));
|
1213
|
+
//
|
1214
|
+
// [
|
1215
|
+
// {
|
1216
|
+
// "symbol": "LTCBTC",
|
1217
|
+
// "orderId": 1,
|
1218
|
+
// "clientOrderId": "myOrder1",
|
1219
|
+
// "price": "0.1",
|
1220
|
+
// "origQty": "1.0",
|
1221
|
+
// "executedQty": "0.0",
|
1222
|
+
// "cummulativeQuoteQty": "0.0",
|
1223
|
+
// "status": "NEW",
|
1224
|
+
// "timeInForce": "GTC",
|
1225
|
+
// "type": "LIMIT",
|
1226
|
+
// "side": "BUY",
|
1227
|
+
// "stopPrice": "0.0",
|
1228
|
+
// "icebergQty": "0.0",
|
1229
|
+
// "time": 1499827319559,
|
1230
|
+
// "updateTime": 1499827319559,
|
1231
|
+
// "isWorking": true
|
1232
|
+
// }
|
1233
|
+
// ]
|
1234
|
+
//
|
1235
|
+
return this.parseOrders (response, market, since, limit);
|
1236
|
+
}
|
1237
|
+
|
1238
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1239
|
+
if (symbol === undefined) {
|
1240
|
+
throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument');
|
1241
|
+
}
|
1242
|
+
await this.loadMarkets ();
|
1243
|
+
const market = this.market (symbol);
|
1244
|
+
const request = {
|
1245
|
+
'symbol': market['id'],
|
1246
|
+
};
|
1247
|
+
const response = await this.v1PrivateGetOpenOrders (this.extend (request, params));
|
1248
|
+
//
|
1249
|
+
// [
|
1250
|
+
// {
|
1251
|
+
// "symbol":"USDCUSDT",
|
1252
|
+
// "orderId":"2878854881",
|
1253
|
+
// "clientOrderId":"",
|
1254
|
+
// "price":"1.1000000000000000",
|
1255
|
+
// "origQty":"100.0000000000000000",
|
1256
|
+
// "executedQty":"0.0000000000000000",
|
1257
|
+
// "cummulativeQuoteQty":"0.0000000000000000",
|
1258
|
+
// "status":"NEW",
|
1259
|
+
// "timeInForce":"",
|
1260
|
+
// "type":"LIMIT",
|
1261
|
+
// "side":"SELL",
|
1262
|
+
// "stopPrice":"",
|
1263
|
+
// "icebergQty":"",
|
1264
|
+
// "time":1635551031000,
|
1265
|
+
// "updateTime":1635551031000,
|
1266
|
+
// "isWorking":false
|
1267
|
+
// }
|
1268
|
+
// ]
|
1269
|
+
//
|
1270
|
+
return this.parseOrders (response, market, since, limit);
|
1271
|
+
}
|
1272
|
+
|
1273
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1274
|
+
if (symbol === undefined) {
|
1275
|
+
throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
|
1276
|
+
}
|
1277
|
+
await this.loadMarkets ();
|
1278
|
+
const market = this.market (symbol);
|
1279
|
+
const origClientOrderId = this.safeValue2 (params, 'origClientOrderId', 'clientOrderId');
|
1280
|
+
const request = {
|
1281
|
+
'symbol': market['id'],
|
1282
|
+
// 'orderId': id,
|
1283
|
+
// 'origClientOrderId': id,
|
1284
|
+
// 'newClientOrderId': id,
|
1285
|
+
};
|
1286
|
+
if (origClientOrderId === undefined) {
|
1287
|
+
request['orderId'] = id;
|
1288
|
+
} else {
|
1289
|
+
request['origClientOrderId'] = origClientOrderId;
|
1290
|
+
}
|
1291
|
+
const query = this.omit (params, [ 'type', 'origClientOrderId', 'clientOrderId' ]);
|
1292
|
+
const response = await this.v1PrivateDeleteOrder (this.extend (request, query));
|
1293
|
+
//
|
1294
|
+
// {
|
1295
|
+
// "symbol": "LTCBTC",
|
1296
|
+
// "origClientOrderId": "myOrder1",
|
1297
|
+
// "orderId": 1,
|
1298
|
+
// "clientOrderId": "cancelMyOrder1"
|
1299
|
+
// }
|
1300
|
+
//
|
1301
|
+
return this.parseOrder (response, market);
|
1302
|
+
}
|
1303
|
+
|
1304
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1305
|
+
const method = this.safeString (this.options, 'fetchMyTradesMethod', 'v2PrivateGetMyTrades');
|
1306
|
+
if ((symbol === undefined) && (method === 'v2PrivateGetMyTrades')) {
|
1307
|
+
throw new ArgumentsRequired (this.id + ' v2PrivateGetMyTrades() requires a symbol argument');
|
1308
|
+
}
|
1309
|
+
await this.loadMarkets ();
|
1310
|
+
const request = {
|
1311
|
+
// 'symbol': market['id'],
|
1312
|
+
// 'startTime': since,
|
1313
|
+
// 'endTime': this.milliseconds (),
|
1314
|
+
// 'fromId': 12345, // trade id to fetch from, most recent trades by default
|
1315
|
+
// 'limit': limit, // default 100, max 1000
|
1316
|
+
};
|
1317
|
+
let market = undefined;
|
1318
|
+
if (symbol !== undefined) {
|
1319
|
+
market = this.market (symbol);
|
1320
|
+
request['symbol'] = market['id'];
|
1321
|
+
}
|
1322
|
+
if (since !== undefined) {
|
1323
|
+
request['startTime'] = since;
|
1324
|
+
}
|
1325
|
+
if (limit !== undefined) {
|
1326
|
+
request['limit'] = limit;
|
1327
|
+
}
|
1328
|
+
const response = await this[method] (this.extend (request, params));
|
1329
|
+
//
|
1330
|
+
// [
|
1331
|
+
// {
|
1332
|
+
// "symbol":"USDCUSDT",
|
1333
|
+
// "id":20725156,
|
1334
|
+
// "orderId":2880918576,
|
1335
|
+
// "origClientOrderId":null,
|
1336
|
+
// "price":"0.9996000000000000",
|
1337
|
+
// "qty":"100.0000000000000000",
|
1338
|
+
// "commission":null,
|
1339
|
+
// "commissionAssert":null,
|
1340
|
+
// "time":1635558511000,
|
1341
|
+
// "isBuyer":false,
|
1342
|
+
// "isMaker":false,
|
1343
|
+
// "isBestMatch":true
|
1344
|
+
// }
|
1345
|
+
// ]
|
1346
|
+
//
|
1347
|
+
return this.parseTrades (response, market, since, limit);
|
1348
|
+
}
|
1349
|
+
|
1350
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1351
|
+
if (code === undefined) {
|
1352
|
+
throw new ArgumentsRequired (this.id + ' fetchDeposits() requires a code argument');
|
1353
|
+
}
|
1354
|
+
await this.loadMarkets ();
|
1355
|
+
const currency = this.currency (code);
|
1356
|
+
const request = {
|
1357
|
+
'coin': currency['id'],
|
1358
|
+
'status': 1, // 0 init, 1 finished, default 0
|
1359
|
+
// 'offset': 0,
|
1360
|
+
// 'limit': limit, // default 10, max 1000
|
1361
|
+
// 'startTime': since,
|
1362
|
+
// 'endTime': this.milliseconds (),
|
1363
|
+
};
|
1364
|
+
if (since !== undefined) {
|
1365
|
+
request['startTime'] = since;
|
1366
|
+
// request['endTime'] = this.sum (since, 7776000000);
|
1367
|
+
}
|
1368
|
+
if (limit !== undefined) {
|
1369
|
+
request['limit'] = limit;
|
1370
|
+
}
|
1371
|
+
const response = await this.v1PrivateGetDepositHistory (this.extend (request, params));
|
1372
|
+
//
|
1373
|
+
// {
|
1374
|
+
// "code":200,
|
1375
|
+
// "msg":"succ",
|
1376
|
+
// "data":[
|
1377
|
+
// {
|
1378
|
+
// "id":2659137,
|
1379
|
+
// "symbol":"USDC",
|
1380
|
+
// "amount":"200.0000000000000000",
|
1381
|
+
// "fee":"0.0E-15",
|
1382
|
+
// "createdAt":1635503169000,
|
1383
|
+
// "updatedAt":1635503202000,
|
1384
|
+
// "addressFrom":"0x2faf487a4414fe77e2327f0bf4ae2a264a776ad2",
|
1385
|
+
// "addressTo":"0x190ceccb1f8bfbec1749180f0ba8922b488d865b",
|
1386
|
+
// "txid":"0x9970aec41099ac385568859517308707bc7d716df8dabae7b52f5b17351c3ed0",
|
1387
|
+
// "confirmations":5,
|
1388
|
+
// "status":0,
|
1389
|
+
// "tagType":null,
|
1390
|
+
// },
|
1391
|
+
// {
|
1392
|
+
// "id":2659137,
|
1393
|
+
// "symbol": "XRP",
|
1394
|
+
// "amount": "20.0000000000000000",
|
1395
|
+
// "fee": "0.0E-15",
|
1396
|
+
// "createdAt": 1544669393000,
|
1397
|
+
// "updatedAt": 1544669413000,
|
1398
|
+
// "addressFrom": "",
|
1399
|
+
// "addressTo": "raLPjTYeGezfdb6crXZzcC8RkLBEwbBHJ5_18113641",
|
1400
|
+
// "txid": "515B23E1F9864D3AF7F5B4C4FCBED784BAE861854FAB95F4031922B6AAEFC7AC",
|
1401
|
+
// "confirmations": 7,
|
1402
|
+
// "status": 1,
|
1403
|
+
// "tagType": "Tag"
|
1404
|
+
// }
|
1405
|
+
// ]
|
1406
|
+
// }
|
1407
|
+
//
|
1408
|
+
const data = this.safeValue (response, 'data', []);
|
1409
|
+
return this.parseTransactions (data, currency, since, limit);
|
1410
|
+
}
|
1411
|
+
|
1412
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1413
|
+
if (code === undefined) {
|
1414
|
+
throw new ArgumentsRequired (this.id + ' fetchWithdrawals() requires a code argument');
|
1415
|
+
}
|
1416
|
+
await this.loadMarkets ();
|
1417
|
+
const currency = this.currency (code);
|
1418
|
+
const request = {
|
1419
|
+
'coin': currency['id'],
|
1420
|
+
'status': 5, // 0 init, 5 finished, 6 canceled, default 0
|
1421
|
+
// 'offset': 0,
|
1422
|
+
// 'limit': limit, // default 10, max 1000
|
1423
|
+
// 'startTime': since,
|
1424
|
+
// 'endTime': this.milliseconds (),
|
1425
|
+
};
|
1426
|
+
if (since !== undefined) {
|
1427
|
+
request['startTime'] = since;
|
1428
|
+
// request['endTime'] = this.sum (since, 7776000000);
|
1429
|
+
}
|
1430
|
+
if (limit !== undefined) {
|
1431
|
+
request['limit'] = limit;
|
1432
|
+
}
|
1433
|
+
const response = await this.v1PrivateGetWithdrawHistory (this.extend (request, params));
|
1434
|
+
//
|
1435
|
+
// {
|
1436
|
+
// "code": 200,
|
1437
|
+
// "msg": "succ",
|
1438
|
+
// "data": {
|
1439
|
+
// "msg": null,
|
1440
|
+
// "amount": 1000,
|
1441
|
+
// "fee": 1,
|
1442
|
+
// "ctime": null,
|
1443
|
+
// "coin": "usdt_erc20",
|
1444
|
+
// "addressTo": "0x2edfae3878d7b6db70ce4abed177ab2636f60c83"
|
1445
|
+
// }
|
1446
|
+
// }
|
1447
|
+
//
|
1448
|
+
const data = this.safeValue (response, 'data', {});
|
1449
|
+
return this.parseTransactions (data, currency);
|
1450
|
+
}
|
1451
|
+
|
1452
|
+
parseTransactionStatusByType (status, type = undefined) {
|
1453
|
+
const statusesByType = {
|
1454
|
+
'deposit': {
|
1455
|
+
'0': 'pending',
|
1456
|
+
'1': 'ok',
|
1457
|
+
},
|
1458
|
+
'withdrawal': {
|
1459
|
+
'0': 'pending', // Email Sent
|
1460
|
+
'5': 'ok', // Failure
|
1461
|
+
'6': 'canceled',
|
1462
|
+
},
|
1463
|
+
};
|
1464
|
+
const statuses = this.safeValue (statusesByType, type, {});
|
1465
|
+
return this.safeString (statuses, status, status);
|
1466
|
+
}
|
1467
|
+
|
1468
|
+
parseTransaction (transaction, currency = undefined) {
|
1469
|
+
//
|
1470
|
+
// fetchDeposits
|
1471
|
+
//
|
1472
|
+
// {
|
1473
|
+
// "symbol": "XRP",
|
1474
|
+
// "amount": "261.3361000000000000",
|
1475
|
+
// "fee": "0.0E-15",
|
1476
|
+
// "createdAt": 1548816979000,
|
1477
|
+
// "updatedAt": 1548816999000,
|
1478
|
+
// "addressFrom": "",
|
1479
|
+
// "addressTo": "raLPjTYeGezfdb6crXZzcC8RkLBEwbBHJ5_18113641",
|
1480
|
+
// "txid": "86D6EB68A7A28938BCE06BD348F8C07DEF500C5F7FE92069EF8C0551CE0F2C7D",
|
1481
|
+
// "confirmations": 8,
|
1482
|
+
// "status": 1,
|
1483
|
+
// "tagType": "Tag"
|
1484
|
+
// },
|
1485
|
+
// {
|
1486
|
+
// "symbol": "XRP",
|
1487
|
+
// "amount": "20.0000000000000000",
|
1488
|
+
// "fee": "0.0E-15",
|
1489
|
+
// "createdAt": 1544669393000,
|
1490
|
+
// "updatedAt": 1544669413000,
|
1491
|
+
// "addressFrom": "",
|
1492
|
+
// "addressTo": "raLPjTYeGezfdb6crXZzcC8RkLBEwbBHJ5_18113641",
|
1493
|
+
// "txid": "515B23E1F9864D3AF7F5B4C4FCBED784BAE861854FAB95F4031922B6AAEFC7AC",
|
1494
|
+
// "confirmations": 7,
|
1495
|
+
// "status": 1,
|
1496
|
+
// "tagType": "Tag"
|
1497
|
+
// }
|
1498
|
+
//
|
1499
|
+
// fetchWithdrawals
|
1500
|
+
//
|
1501
|
+
// {
|
1502
|
+
// "id": 183745,
|
1503
|
+
// "symbol": "usdt_erc20",
|
1504
|
+
// "amount": "8.4000000000000000",
|
1505
|
+
// "fee": "1.6000000000000000",
|
1506
|
+
// "payAmount": "0.0000000000000000",
|
1507
|
+
// "createdAt": 1595336441000,
|
1508
|
+
// "updatedAt": 1595336576000,
|
1509
|
+
// "addressFrom": "",
|
1510
|
+
// "addressTo": "0x2edfae3878d7b6db70ce4abed177ab2636f60c83",
|
1511
|
+
// "txid": "",
|
1512
|
+
// "confirmations": 0,
|
1513
|
+
// "status": 6,
|
1514
|
+
// "tagType": null
|
1515
|
+
// }
|
1516
|
+
//
|
1517
|
+
// withdraw
|
1518
|
+
//
|
1519
|
+
// {
|
1520
|
+
// "msg": null,
|
1521
|
+
// "amount": 1000,
|
1522
|
+
// "fee": 1,
|
1523
|
+
// "ctime": null,
|
1524
|
+
// "coin": "usdt_erc20",
|
1525
|
+
// "addressTo": "0x2edfae3878d7b6db70ce4abed177ab2636f60c83"
|
1526
|
+
// }
|
1527
|
+
//
|
1528
|
+
const id = this.safeString (transaction, 'id');
|
1529
|
+
const tagType = this.safeString (transaction, 'tagType');
|
1530
|
+
let addressTo = this.safeString (transaction, 'addressTo');
|
1531
|
+
if (addressTo === '') {
|
1532
|
+
addressTo = undefined;
|
1533
|
+
}
|
1534
|
+
let addressFrom = this.safeString (transaction, 'addressFrom');
|
1535
|
+
if (addressFrom === '') {
|
1536
|
+
addressFrom = undefined;
|
1537
|
+
}
|
1538
|
+
let tagTo = undefined;
|
1539
|
+
let tagFrom = undefined;
|
1540
|
+
if (tagType !== undefined) {
|
1541
|
+
if (addressTo !== undefined) {
|
1542
|
+
const parts = addressTo.split ('_');
|
1543
|
+
addressTo = this.safeString (parts, 0);
|
1544
|
+
tagTo = this.safeString (parts, 1);
|
1545
|
+
}
|
1546
|
+
if (addressFrom !== undefined) {
|
1547
|
+
const parts = addressFrom.split ('_');
|
1548
|
+
addressFrom = this.safeString (parts, 0);
|
1549
|
+
tagFrom = this.safeString (parts, 1);
|
1550
|
+
}
|
1551
|
+
}
|
1552
|
+
let txid = this.safeString (transaction, 'txid');
|
1553
|
+
if (txid === '') {
|
1554
|
+
txid = undefined;
|
1555
|
+
}
|
1556
|
+
const timestamp = this.safeInteger (transaction, 'createdAt');
|
1557
|
+
const updated = this.safeInteger (transaction, 'updatedAt');
|
1558
|
+
const payAmount = ('payAmount' in transaction);
|
1559
|
+
const ctime = ('ctime' in transaction);
|
1560
|
+
const type = (payAmount || ctime) ? 'withdrawal' : 'deposit';
|
1561
|
+
const status = this.parseTransactionStatusByType (this.safeString (transaction, 'status'), type);
|
1562
|
+
const amount = this.safeNumber (transaction, 'amount');
|
1563
|
+
let network = undefined;
|
1564
|
+
let currencyId = this.safeString (transaction, 'symbol');
|
1565
|
+
if (currencyId !== undefined) {
|
1566
|
+
const parts = currencyId.split ('_');
|
1567
|
+
currencyId = this.safeString (parts, 0);
|
1568
|
+
const networkId = this.safeString (parts, 1);
|
1569
|
+
if (networkId !== undefined) {
|
1570
|
+
network = networkId.toUpperCase ();
|
1571
|
+
}
|
1572
|
+
}
|
1573
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
1574
|
+
const feeCost = this.safeNumber (transaction, 'fee');
|
1575
|
+
let fee = undefined;
|
1576
|
+
if (feeCost !== undefined) {
|
1577
|
+
fee = { 'currency': code, 'cost': feeCost };
|
1578
|
+
}
|
1579
|
+
return {
|
1580
|
+
'info': transaction,
|
1581
|
+
'id': id,
|
1582
|
+
'txid': txid,
|
1583
|
+
'timestamp': timestamp,
|
1584
|
+
'datetime': this.iso8601 (timestamp),
|
1585
|
+
'network': network,
|
1586
|
+
'address': addressTo,
|
1587
|
+
'addressTo': addressTo,
|
1588
|
+
'addressFrom': addressFrom,
|
1589
|
+
'tag': tagTo,
|
1590
|
+
'tagTo': tagTo,
|
1591
|
+
'tagFrom': tagFrom,
|
1592
|
+
'type': type,
|
1593
|
+
'amount': amount,
|
1594
|
+
'currency': code,
|
1595
|
+
'status': status,
|
1596
|
+
'updated': updated,
|
1597
|
+
'internal': false,
|
1598
|
+
'fee': fee,
|
1599
|
+
};
|
1600
|
+
}
|
1601
|
+
|
1602
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
1603
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
1604
|
+
this.checkAddress (address);
|
1605
|
+
await this.loadMarkets ();
|
1606
|
+
const currency = this.currency (code);
|
1607
|
+
let chainName = this.safeString (params, 'chainName');
|
1608
|
+
if (chainName === undefined) {
|
1609
|
+
const networks = this.safeValue (currency, 'networks', {});
|
1610
|
+
const network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
|
1611
|
+
const networkEntry = this.safeValue (networks, network, {});
|
1612
|
+
chainName = this.safeString (networkEntry, 'id'); // handle ERC20>ETH alias
|
1613
|
+
if (chainName === undefined) {
|
1614
|
+
throw new ArgumentsRequired (this.id + ' withdraw() requires a network parameter or a chainName parameter');
|
1615
|
+
}
|
1616
|
+
params = this.omit (params, 'network');
|
1617
|
+
}
|
1618
|
+
const request = {
|
1619
|
+
'coin': currency['id'].toUpperCase (),
|
1620
|
+
'amount': amount,
|
1621
|
+
'addressTo': address,
|
1622
|
+
'chainName': chainName, // 'ERC20', 'TRC20', 'SOL'
|
1623
|
+
// 'addressMark': '', // mark of address
|
1624
|
+
// 'addrType': '', // type of address
|
1625
|
+
// 'tag': tag,
|
1626
|
+
};
|
1627
|
+
if (tag !== undefined) {
|
1628
|
+
request['tag'] = tag;
|
1629
|
+
}
|
1630
|
+
const response = await this.v1PrivatePostWithdrawCommit (this.extend (request, params));
|
1631
|
+
// { id: '9a67628b16ba4988ae20d329333f16bc' }
|
1632
|
+
return this.parseTransaction (response, currency);
|
1633
|
+
}
|
1634
|
+
|
1635
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1636
|
+
const [ version, access ] = api;
|
1637
|
+
let url = this.urls['api'][version] + '/' + this.implodeParams (path, params);
|
1638
|
+
params = this.omit (params, this.extractParams (path));
|
1639
|
+
if (access === 'private') {
|
1640
|
+
this.checkRequiredCredentials ();
|
1641
|
+
const recvWindow = this.safeInteger (this.options, 'recvWindow', 5000);
|
1642
|
+
let query = this.urlencode (this.extend ({
|
1643
|
+
'timestamp': this.nonce (),
|
1644
|
+
'recvWindow': recvWindow,
|
1645
|
+
}, params));
|
1646
|
+
const signature = this.hmac (this.encode (query), this.encode (this.secret));
|
1647
|
+
query += '&' + 'signature=' + signature;
|
1648
|
+
headers = {
|
1649
|
+
'X-MBX-APIKEY': this.apiKey,
|
1650
|
+
};
|
1651
|
+
if ((method === 'GET') || (method === 'DELETE')) {
|
1652
|
+
url += '?' + query;
|
1653
|
+
} else {
|
1654
|
+
body = query;
|
1655
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
1656
|
+
}
|
1657
|
+
} else {
|
1658
|
+
if (Object.keys (params).length) {
|
1659
|
+
url += '?' + this.urlencode (params);
|
1660
|
+
}
|
1661
|
+
}
|
1662
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1663
|
+
}
|
1664
|
+
|
1665
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
1666
|
+
if ((code === 418) || (code === 429)) {
|
1667
|
+
throw new DDoSProtection (this.id + ' ' + code.toString () + ' ' + reason + ' ' + body);
|
1668
|
+
}
|
1669
|
+
// error response in a form: { "code": -1013, "msg": "Invalid quantity." }
|
1670
|
+
// following block cointains legacy checks against message patterns in "msg" property
|
1671
|
+
// will switch "code" checks eventually, when we know all of them
|
1672
|
+
if (code >= 400) {
|
1673
|
+
if (body.indexOf ('Price * QTY is zero or less') >= 0) {
|
1674
|
+
throw new InvalidOrder (this.id + ' order cost = amount * price is zero or less ' + body);
|
1675
|
+
}
|
1676
|
+
if (body.indexOf ('LOT_SIZE') >= 0) {
|
1677
|
+
throw new InvalidOrder (this.id + ' order amount should be evenly divisible by lot size ' + body);
|
1678
|
+
}
|
1679
|
+
if (body.indexOf ('PRICE_FILTER') >= 0) {
|
1680
|
+
throw new InvalidOrder (this.id + ' order price is invalid, i.e. exceeds allowed price precision, exceeds min price or max price limits or is invalid float value in general, use this.priceToPrecision (symbol, amount) ' + body);
|
1681
|
+
}
|
1682
|
+
}
|
1683
|
+
if (response === undefined) {
|
1684
|
+
return; // fallback to default error handler
|
1685
|
+
}
|
1686
|
+
// check success value for wapi endpoints
|
1687
|
+
// response in format {'msg': 'The coin does not exist.', 'success': true/false}
|
1688
|
+
const success = this.safeValue (response, 'success', true);
|
1689
|
+
if (!success) {
|
1690
|
+
const message = this.safeString (response, 'msg');
|
1691
|
+
let parsedMessage = undefined;
|
1692
|
+
if (message !== undefined) {
|
1693
|
+
try {
|
1694
|
+
parsedMessage = JSON.parse (message);
|
1695
|
+
} catch (e) {
|
1696
|
+
// do nothing
|
1697
|
+
parsedMessage = undefined;
|
1698
|
+
}
|
1699
|
+
if (parsedMessage !== undefined) {
|
1700
|
+
response = parsedMessage;
|
1701
|
+
}
|
1702
|
+
}
|
1703
|
+
}
|
1704
|
+
const message = this.safeString (response, 'msg');
|
1705
|
+
if (message !== undefined) {
|
1706
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], message, this.id + ' ' + message);
|
1707
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], message, this.id + ' ' + message);
|
1708
|
+
}
|
1709
|
+
// checks against error codes
|
1710
|
+
const error = this.safeString (response, 'code');
|
1711
|
+
if (error !== undefined) {
|
1712
|
+
// https://github.com/ccxt/ccxt/issues/6501
|
1713
|
+
// https://github.com/ccxt/ccxt/issues/7742
|
1714
|
+
if ((error === '200') || Precise.stringEquals (error, '0')) {
|
1715
|
+
return;
|
1716
|
+
}
|
1717
|
+
// a workaround for {"code":-2015,"msg":"Invalid API-key, IP, or permissions for action."}
|
1718
|
+
// despite that their message is very confusing, it is raised by Binance
|
1719
|
+
// on a temporary ban, the API key is valid, but disabled for a while
|
1720
|
+
if ((error === '-2015') && this.options['hasAlreadyAuthenticatedSuccessfully']) {
|
1721
|
+
throw new DDoSProtection (this.id + ' temporary banned: ' + body);
|
1722
|
+
}
|
1723
|
+
const feedback = this.id + ' ' + body;
|
1724
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], error, feedback);
|
1725
|
+
throw new ExchangeError (feedback);
|
1726
|
+
}
|
1727
|
+
if (!success) {
|
1728
|
+
throw new ExchangeError (this.id + ' ' + body);
|
1729
|
+
}
|
1730
|
+
}
|
1731
|
+
|
1732
|
+
calculateRateLimiterCost (api, method, path, params, config = {}, context = {}) {
|
1733
|
+
if (('noSymbol' in config) && !('symbol' in params)) {
|
1734
|
+
return config['noSymbol'];
|
1735
|
+
} else if (('byLimit' in config) && ('limit' in params)) {
|
1736
|
+
const limit = params['limit'];
|
1737
|
+
const byLimit = config['byLimit'];
|
1738
|
+
for (let i = 0; i < byLimit.length; i++) {
|
1739
|
+
const entry = byLimit[i];
|
1740
|
+
if (limit <= entry[0]) {
|
1741
|
+
return entry[1];
|
1742
|
+
}
|
1743
|
+
}
|
1744
|
+
}
|
1745
|
+
return this.safeInteger (config, 'cost', 1);
|
1746
|
+
}
|
1747
|
+
};
|