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/poloniex.js
ADDED
@@ -0,0 +1,1674 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
// ---------------------------------------------------------------------------
|
4
|
+
|
5
|
+
const Exchange = require ('./base/Exchange');
|
6
|
+
const { ExchangeError, ExchangeNotAvailable, RequestTimeout, AuthenticationError, PermissionDenied, RateLimitExceeded, InsufficientFunds, OrderNotFound, InvalidOrder, AccountSuspended, CancelPending, InvalidNonce, OnMaintenance, BadSymbol } = require ('./base/errors');
|
7
|
+
const Precise = require ('./base/Precise');
|
8
|
+
|
9
|
+
// ---------------------------------------------------------------------------
|
10
|
+
|
11
|
+
module.exports = class poloniex extends Exchange {
|
12
|
+
describe () {
|
13
|
+
return this.deepExtend (super.describe (), {
|
14
|
+
'id': 'poloniex',
|
15
|
+
'name': 'Poloniex',
|
16
|
+
'countries': [ 'US' ],
|
17
|
+
'rateLimit': 166.667, // 6 calls per second, 1000ms / 6 = 166.667ms between requests
|
18
|
+
'certified': false,
|
19
|
+
'pro': true,
|
20
|
+
'has': {
|
21
|
+
'CORS': undefined,
|
22
|
+
'spot': true,
|
23
|
+
'margin': undefined, // has but not fully implemented
|
24
|
+
'swap': undefined, // has but not fully implemented
|
25
|
+
'future': undefined, // has but not fully implemented
|
26
|
+
'option': undefined,
|
27
|
+
'cancelAllOrders': true,
|
28
|
+
'cancelOrder': true,
|
29
|
+
'createDepositAddress': true,
|
30
|
+
'createMarketOrder': undefined,
|
31
|
+
'createOrder': true,
|
32
|
+
'editOrder': true,
|
33
|
+
'fetchBalance': true,
|
34
|
+
'fetchClosedOrder': 'emulated',
|
35
|
+
'fetchCurrencies': true,
|
36
|
+
'fetchDepositAddress': true,
|
37
|
+
'fetchDeposits': true,
|
38
|
+
'fetchMarkets': true,
|
39
|
+
'fetchMyTrades': true,
|
40
|
+
'fetchOHLCV': true,
|
41
|
+
'fetchOpenOrder': true, // true endpoint for a single open order
|
42
|
+
'fetchOpenOrders': true, // true endpoint for open orders
|
43
|
+
'fetchOrderBook': true,
|
44
|
+
'fetchOrderBooks': true,
|
45
|
+
'fetchOrderTrades': true, // true endpoint for trades of a single open or closed order
|
46
|
+
'fetchPosition': true,
|
47
|
+
'fetchTicker': true,
|
48
|
+
'fetchTickers': true,
|
49
|
+
'fetchTrades': true,
|
50
|
+
'fetchTradingFee': false,
|
51
|
+
'fetchTradingFees': true,
|
52
|
+
'fetchTransactions': true,
|
53
|
+
'fetchTransfer': false,
|
54
|
+
'fetchTransfers': false,
|
55
|
+
'fetchWithdrawals': true,
|
56
|
+
'transfer': true,
|
57
|
+
'withdraw': true,
|
58
|
+
},
|
59
|
+
'timeframes': {
|
60
|
+
'5m': 300,
|
61
|
+
'15m': 900,
|
62
|
+
'30m': 1800,
|
63
|
+
'2h': 7200,
|
64
|
+
'4h': 14400,
|
65
|
+
'1d': 86400,
|
66
|
+
},
|
67
|
+
'urls': {
|
68
|
+
'logo': 'https://user-images.githubusercontent.com/1294454/27766817-e9456312-5ee6-11e7-9b3c-b628ca5626a5.jpg',
|
69
|
+
'api': {
|
70
|
+
'public': 'https://poloniex.com/public',
|
71
|
+
'private': 'https://poloniex.com/tradingApi',
|
72
|
+
},
|
73
|
+
'www': 'https://www.poloniex.com',
|
74
|
+
'doc': 'https://docs.poloniex.com',
|
75
|
+
'fees': 'https://poloniex.com/fees',
|
76
|
+
'referral': 'https://poloniex.com/signup?c=UBFZJRPJ',
|
77
|
+
},
|
78
|
+
'api': {
|
79
|
+
'public': {
|
80
|
+
'get': {
|
81
|
+
'return24hVolume': 1,
|
82
|
+
'returnChartData': 1,
|
83
|
+
'returnCurrencies': 1,
|
84
|
+
'returnLoanOrders': 1,
|
85
|
+
'returnOrderBook': 1,
|
86
|
+
'returnTicker': 1,
|
87
|
+
'returnTradeHistory': 1,
|
88
|
+
},
|
89
|
+
},
|
90
|
+
'private': {
|
91
|
+
'post': {
|
92
|
+
'buy': 1,
|
93
|
+
'cancelLoanOffer': 1,
|
94
|
+
'cancelOrder': 1,
|
95
|
+
'cancelAllOrders': 1,
|
96
|
+
'closeMarginPosition': 1,
|
97
|
+
'createLoanOffer': 1,
|
98
|
+
'generateNewAddress': 1,
|
99
|
+
'getMarginPosition': 1,
|
100
|
+
'marginBuy': 1,
|
101
|
+
'marginSell': 1,
|
102
|
+
'moveOrder': 1,
|
103
|
+
'returnActiveLoans': 1,
|
104
|
+
'returnAvailableAccountBalances': 1,
|
105
|
+
'returnBalances': 1,
|
106
|
+
'returnCompleteBalances': 1,
|
107
|
+
'returnDepositAddresses': 1,
|
108
|
+
'returnDepositsWithdrawals': 1,
|
109
|
+
'returnFeeInfo': 1,
|
110
|
+
'returnLendingHistory': 1,
|
111
|
+
'returnMarginAccountSummary': 1,
|
112
|
+
'returnOpenLoanOffers': 1,
|
113
|
+
'returnOpenOrders': 1,
|
114
|
+
'returnOrderTrades': 1,
|
115
|
+
'returnOrderStatus': 1,
|
116
|
+
'returnTradableBalances': 1,
|
117
|
+
'returnTradeHistory': 1,
|
118
|
+
'sell': 1,
|
119
|
+
'toggleAutoRenew': 1,
|
120
|
+
'transferBalance': 1,
|
121
|
+
'withdraw': 1,
|
122
|
+
},
|
123
|
+
},
|
124
|
+
},
|
125
|
+
'fees': {
|
126
|
+
'trading': {
|
127
|
+
'feeSide': 'get',
|
128
|
+
// starting from Jan 8 2020
|
129
|
+
'maker': this.parseNumber ('0.0009'),
|
130
|
+
'taker': this.parseNumber ('0.0009'),
|
131
|
+
},
|
132
|
+
'funding': {},
|
133
|
+
},
|
134
|
+
'limits': {
|
135
|
+
'amount': {
|
136
|
+
'min': 0.000001,
|
137
|
+
'max': undefined,
|
138
|
+
},
|
139
|
+
'price': {
|
140
|
+
'min': 0.00000001,
|
141
|
+
'max': 1000000000,
|
142
|
+
},
|
143
|
+
'cost': {
|
144
|
+
'min': 0.00000000,
|
145
|
+
'max': 1000000000,
|
146
|
+
},
|
147
|
+
},
|
148
|
+
'precision': {
|
149
|
+
'amount': 8,
|
150
|
+
'price': 8,
|
151
|
+
},
|
152
|
+
'commonCurrencies': {
|
153
|
+
'AIR': 'AirCoin',
|
154
|
+
'APH': 'AphroditeCoin',
|
155
|
+
'BCC': 'BTCtalkcoin',
|
156
|
+
'BCHABC': 'BCHABC',
|
157
|
+
'BDG': 'Badgercoin',
|
158
|
+
'BTM': 'Bitmark',
|
159
|
+
'CON': 'Coino',
|
160
|
+
'GOLD': 'GoldEagles',
|
161
|
+
'GPUC': 'GPU',
|
162
|
+
'HOT': 'Hotcoin',
|
163
|
+
'ITC': 'Information Coin',
|
164
|
+
'KEY': 'KEYCoin',
|
165
|
+
'MASK': 'NFTX Hashmasks Index', // conflict with Mask Network
|
166
|
+
'MEME': 'Degenerator Meme', // Degenerator Meme migrated to Meme Inu, this exchange still has the old price
|
167
|
+
'PLX': 'ParallaxCoin',
|
168
|
+
'REPV2': 'REP',
|
169
|
+
'STR': 'XLM',
|
170
|
+
'SOC': 'SOCC',
|
171
|
+
'TRADE': 'Unitrade',
|
172
|
+
'XAP': 'API Coin',
|
173
|
+
// this is not documented in the API docs for Poloniex
|
174
|
+
// https://github.com/ccxt/ccxt/issues/7084
|
175
|
+
// when the user calls withdraw ('USDT', amount, address, tag, params)
|
176
|
+
// with params = { 'currencyToWithdrawAs': 'USDTTRON' }
|
177
|
+
// or params = { 'currencyToWithdrawAs': 'USDTETH' }
|
178
|
+
// fetchWithdrawals ('USDT') returns the corresponding withdrawals
|
179
|
+
// with a USDTTRON or a USDTETH currency id, respectfully
|
180
|
+
// therefore we have map them back to the original code USDT
|
181
|
+
// otherwise the returned withdrawals are filtered out
|
182
|
+
'USDTTRON': 'USDT',
|
183
|
+
'USDTETH': 'USDT',
|
184
|
+
},
|
185
|
+
'options': {
|
186
|
+
'networks': {
|
187
|
+
'ERC20': 'ETH',
|
188
|
+
'TRX': 'TRON',
|
189
|
+
'TRC20': 'TRON',
|
190
|
+
},
|
191
|
+
'limits': {
|
192
|
+
'cost': {
|
193
|
+
'min': {
|
194
|
+
'BTC': 0.0001,
|
195
|
+
'ETH': 0.0001,
|
196
|
+
'USDT': 1.0,
|
197
|
+
'TRX': 100,
|
198
|
+
'BNB': 0.06,
|
199
|
+
'USDC': 1.0,
|
200
|
+
'USDJ': 1.0,
|
201
|
+
'TUSD': 0.0001,
|
202
|
+
'DAI': 1.0,
|
203
|
+
'PAX': 1.0,
|
204
|
+
'BUSD': 1.0,
|
205
|
+
},
|
206
|
+
},
|
207
|
+
},
|
208
|
+
'accountsByType': {
|
209
|
+
'spot': 'exchange',
|
210
|
+
'margin': 'margin',
|
211
|
+
'future': 'futures',
|
212
|
+
'lending': 'lending',
|
213
|
+
},
|
214
|
+
'accountsById': {
|
215
|
+
'exchange': 'spot',
|
216
|
+
'margin': 'margin',
|
217
|
+
'futures': 'future',
|
218
|
+
'lending': 'lending',
|
219
|
+
},
|
220
|
+
},
|
221
|
+
'exceptions': {
|
222
|
+
'exact': {
|
223
|
+
'You may only place orders that reduce your position.': InvalidOrder,
|
224
|
+
'Invalid order number, or you are not the person who placed the order.': OrderNotFound,
|
225
|
+
'Permission denied': PermissionDenied,
|
226
|
+
'Permission denied.': PermissionDenied,
|
227
|
+
'Connection timed out. Please try again.': RequestTimeout,
|
228
|
+
'Internal error. Please try again.': ExchangeNotAvailable,
|
229
|
+
'Currently in maintenance mode.': OnMaintenance,
|
230
|
+
'Order not found, or you are not the person who placed it.': OrderNotFound,
|
231
|
+
'Invalid API key/secret pair.': AuthenticationError,
|
232
|
+
'Please do not make more than 8 API calls per second.': RateLimitExceeded,
|
233
|
+
'This IP has been temporarily throttled. Please ensure your requests are valid and try again in one minute.': RateLimitExceeded,
|
234
|
+
'Rate must be greater than zero.': InvalidOrder, // {"error":"Rate must be greater than zero."}
|
235
|
+
'Invalid currency pair.': BadSymbol, // {"error":"Invalid currency pair."}
|
236
|
+
'Invalid currencyPair parameter.': BadSymbol, // {"error":"Invalid currencyPair parameter."}
|
237
|
+
'Trading is disabled in this market.': BadSymbol, // {"error":"Trading is disabled in this market."}
|
238
|
+
'Invalid orderNumber parameter.': OrderNotFound,
|
239
|
+
'Order is beyond acceptable bounds.': InvalidOrder, // {"error":"Order is beyond acceptable bounds.","fee":"0.00155000","currencyPair":"USDT_BOBA"}
|
240
|
+
'This account is closed.': AccountSuspended, // {"error":"This account is closed."}
|
241
|
+
},
|
242
|
+
'broad': {
|
243
|
+
'Total must be at least': InvalidOrder, // {"error":"Total must be at least 0.0001."}
|
244
|
+
'This account is frozen': AccountSuspended, // {"error":"This account is frozen for trading."} || {"error":"This account is frozen."}
|
245
|
+
'This account is locked.': AccountSuspended, // {"error":"This account is locked."}
|
246
|
+
'Not enough': InsufficientFunds,
|
247
|
+
'Nonce must be greater': InvalidNonce,
|
248
|
+
'You have already called cancelOrder or moveOrder on this order.': CancelPending,
|
249
|
+
'Amount must be at least': InvalidOrder, // {"error":"Amount must be at least 0.000001."}
|
250
|
+
'is either completed or does not exist': OrderNotFound, // {"error":"Order 587957810791 is either completed or does not exist."}
|
251
|
+
'Error pulling ': ExchangeError, // {"error":"Error pulling order book"}
|
252
|
+
},
|
253
|
+
},
|
254
|
+
});
|
255
|
+
}
|
256
|
+
|
257
|
+
parseOHLCV (ohlcv, market = undefined) {
|
258
|
+
//
|
259
|
+
// {
|
260
|
+
// "date":1590913773,
|
261
|
+
// "high":0.02491611,
|
262
|
+
// "low":0.02491611,
|
263
|
+
// "open":0.02491611,
|
264
|
+
// "close":0.02491611,
|
265
|
+
// "volume":0,
|
266
|
+
// "quoteVolume":0,
|
267
|
+
// "weightedAverage":0.02491611
|
268
|
+
// }
|
269
|
+
//
|
270
|
+
return [
|
271
|
+
this.safeTimestamp (ohlcv, 'date'),
|
272
|
+
this.safeNumber (ohlcv, 'open'),
|
273
|
+
this.safeNumber (ohlcv, 'high'),
|
274
|
+
this.safeNumber (ohlcv, 'low'),
|
275
|
+
this.safeNumber (ohlcv, 'close'),
|
276
|
+
this.safeNumber (ohlcv, 'quoteVolume'),
|
277
|
+
];
|
278
|
+
}
|
279
|
+
|
280
|
+
async fetchOHLCV (symbol, timeframe = '5m', since = undefined, limit = undefined, params = {}) {
|
281
|
+
await this.loadMarkets ();
|
282
|
+
const market = this.market (symbol);
|
283
|
+
const request = {
|
284
|
+
'currencyPair': market['id'],
|
285
|
+
'period': this.timeframes[timeframe],
|
286
|
+
};
|
287
|
+
if (since === undefined) {
|
288
|
+
request['end'] = this.seconds ();
|
289
|
+
if (limit === undefined) {
|
290
|
+
request['start'] = request['end'] - this.parseTimeframe ('1w'); // max range = 1 week
|
291
|
+
} else {
|
292
|
+
request['start'] = request['end'] - limit * this.parseTimeframe (timeframe);
|
293
|
+
}
|
294
|
+
} else {
|
295
|
+
request['start'] = parseInt (since / 1000);
|
296
|
+
if (limit !== undefined) {
|
297
|
+
const end = this.sum (request['start'], limit * this.parseTimeframe (timeframe));
|
298
|
+
request['end'] = end;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
const response = await this.publicGetReturnChartData (this.extend (request, params));
|
302
|
+
//
|
303
|
+
// [
|
304
|
+
// {"date":1590913773,"high":0.02491611,"low":0.02491611,"open":0.02491611,"close":0.02491611,"volume":0,"quoteVolume":0,"weightedAverage":0.02491611},
|
305
|
+
// {"date":1590913800,"high":0.02495324,"low":0.02489501,"open":0.02491797,"close":0.02493693,"volume":0.0927415,"quoteVolume":3.7227869,"weightedAverage":0.02491185},
|
306
|
+
// {"date":1590914100,"high":0.02498596,"low":0.02488503,"open":0.02493033,"close":0.02497896,"volume":0.21196348,"quoteVolume":8.50291888,"weightedAverage":0.02492832},
|
307
|
+
// ]
|
308
|
+
//
|
309
|
+
return this.parseOHLCVs (response, market, timeframe, since, limit);
|
310
|
+
}
|
311
|
+
|
312
|
+
async loadMarkets (reload = false, params = {}) {
|
313
|
+
const markets = await super.loadMarkets (reload, params);
|
314
|
+
const currenciesByNumericId = this.safeValue (this.options, 'currenciesByNumericId');
|
315
|
+
if ((currenciesByNumericId === undefined) || reload) {
|
316
|
+
this.options['currenciesByNumericId'] = this.indexBy (this.currencies, 'numericId');
|
317
|
+
}
|
318
|
+
return markets;
|
319
|
+
}
|
320
|
+
|
321
|
+
async fetchMarkets (params = {}) {
|
322
|
+
const markets = await this.publicGetReturnTicker (params);
|
323
|
+
const keys = Object.keys (markets);
|
324
|
+
const result = [];
|
325
|
+
for (let i = 0; i < keys.length; i++) {
|
326
|
+
const id = keys[i];
|
327
|
+
const market = markets[id];
|
328
|
+
const [ quoteId, baseId ] = id.split ('_');
|
329
|
+
const base = this.safeCurrencyCode (baseId);
|
330
|
+
const quote = this.safeCurrencyCode (quoteId);
|
331
|
+
const isFrozen = this.safeString (market, 'isFrozen');
|
332
|
+
const marginEnabled = this.safeInteger (market, 'marginTradingEnabled');
|
333
|
+
// these are known defaults
|
334
|
+
result.push ({
|
335
|
+
'id': id,
|
336
|
+
'numericId': this.safeInteger (market, 'id'),
|
337
|
+
'symbol': base + '/' + quote,
|
338
|
+
'base': base,
|
339
|
+
'quote': quote,
|
340
|
+
'settle': undefined,
|
341
|
+
'baseId': baseId,
|
342
|
+
'quoteId': quoteId,
|
343
|
+
'settleId': undefined,
|
344
|
+
'type': 'spot',
|
345
|
+
'spot': true,
|
346
|
+
'margin': (marginEnabled === 1),
|
347
|
+
'swap': false,
|
348
|
+
'future': false,
|
349
|
+
'option': false,
|
350
|
+
'active': (isFrozen !== '1'),
|
351
|
+
'contract': false,
|
352
|
+
'linear': undefined,
|
353
|
+
'inverse': undefined,
|
354
|
+
'contractSize': undefined,
|
355
|
+
'expiry': undefined,
|
356
|
+
'expiryDatetime': undefined,
|
357
|
+
'strike': undefined,
|
358
|
+
'optionType': undefined,
|
359
|
+
'precision': {
|
360
|
+
'amount': parseInt ('8'),
|
361
|
+
'price': parseInt ('8'),
|
362
|
+
},
|
363
|
+
'limits': this.extend (this.limits, {
|
364
|
+
'leverage': {
|
365
|
+
'min': undefined,
|
366
|
+
'max': undefined,
|
367
|
+
},
|
368
|
+
'cost': {
|
369
|
+
'min': this.safeValue (this.options['limits']['cost']['min'], quote),
|
370
|
+
'max': undefined,
|
371
|
+
},
|
372
|
+
}),
|
373
|
+
'info': market,
|
374
|
+
});
|
375
|
+
}
|
376
|
+
return result;
|
377
|
+
}
|
378
|
+
|
379
|
+
parseBalance (response) {
|
380
|
+
const result = {
|
381
|
+
'info': response,
|
382
|
+
'timestamp': undefined,
|
383
|
+
'datetime': undefined,
|
384
|
+
};
|
385
|
+
const currencyIds = Object.keys (response);
|
386
|
+
for (let i = 0; i < currencyIds.length; i++) {
|
387
|
+
const currencyId = currencyIds[i];
|
388
|
+
const balance = this.safeValue (response, currencyId, {});
|
389
|
+
const code = this.safeCurrencyCode (currencyId);
|
390
|
+
const account = this.account ();
|
391
|
+
account['free'] = this.safeString (balance, 'available');
|
392
|
+
account['used'] = this.safeString (balance, 'onOrders');
|
393
|
+
result[code] = account;
|
394
|
+
}
|
395
|
+
return this.safeBalance (result);
|
396
|
+
}
|
397
|
+
|
398
|
+
async fetchBalance (params = {}) {
|
399
|
+
await this.loadMarkets ();
|
400
|
+
const request = {
|
401
|
+
'account': 'all',
|
402
|
+
};
|
403
|
+
const response = await this.privatePostReturnCompleteBalances (this.extend (request, params));
|
404
|
+
//
|
405
|
+
// {
|
406
|
+
// "1CR":{"available":"0.00000000","onOrders":"0.00000000","btcValue":"0.00000000"},
|
407
|
+
// "ABY":{"available":"0.00000000","onOrders":"0.00000000","btcValue":"0.00000000"},
|
408
|
+
// "AC":{"available":"0.00000000","onOrders":"0.00000000","btcValue":"0.00000000"},
|
409
|
+
// }
|
410
|
+
//
|
411
|
+
return this.parseBalance (response);
|
412
|
+
}
|
413
|
+
|
414
|
+
async fetchTradingFees (params = {}) {
|
415
|
+
await this.loadMarkets ();
|
416
|
+
const response = await this.privatePostReturnFeeInfo (params);
|
417
|
+
//
|
418
|
+
// {
|
419
|
+
// makerFee: '0.00100000',
|
420
|
+
// takerFee: '0.00200000',
|
421
|
+
// marginMakerFee: '0.00100000',
|
422
|
+
// marginTakerFee: '0.00200000',
|
423
|
+
// thirtyDayVolume: '106.08463302',
|
424
|
+
// nextTier: 500000,
|
425
|
+
// }
|
426
|
+
//
|
427
|
+
const result = {};
|
428
|
+
for (let i = 0; i < this.symbols.length; i++) {
|
429
|
+
const symbol = this.symbols[i];
|
430
|
+
result[symbol] = {
|
431
|
+
'info': response,
|
432
|
+
'symbol': symbol,
|
433
|
+
'maker': this.safeNumber (response, 'makerFee'),
|
434
|
+
'taker': this.safeNumber (response, 'takerFee'),
|
435
|
+
'percentage': true,
|
436
|
+
'tierBased': true,
|
437
|
+
};
|
438
|
+
}
|
439
|
+
return result;
|
440
|
+
}
|
441
|
+
|
442
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
443
|
+
await this.loadMarkets ();
|
444
|
+
const request = {
|
445
|
+
'currencyPair': this.marketId (symbol),
|
446
|
+
};
|
447
|
+
if (limit !== undefined) {
|
448
|
+
request['depth'] = limit; // 100
|
449
|
+
}
|
450
|
+
const response = await this.publicGetReturnOrderBook (this.extend (request, params));
|
451
|
+
const orderbook = this.parseOrderBook (response, symbol);
|
452
|
+
orderbook['nonce'] = this.safeInteger (response, 'seq');
|
453
|
+
return orderbook;
|
454
|
+
}
|
455
|
+
|
456
|
+
async fetchOrderBooks (symbols = undefined, limit = undefined, params = {}) {
|
457
|
+
await this.loadMarkets ();
|
458
|
+
const request = {
|
459
|
+
'currencyPair': 'all',
|
460
|
+
};
|
461
|
+
if (limit !== undefined) {
|
462
|
+
request['depth'] = limit; // 100
|
463
|
+
}
|
464
|
+
const response = await this.publicGetReturnOrderBook (this.extend (request, params));
|
465
|
+
const marketIds = Object.keys (response);
|
466
|
+
const result = {};
|
467
|
+
for (let i = 0; i < marketIds.length; i++) {
|
468
|
+
const marketId = marketIds[i];
|
469
|
+
let symbol = undefined;
|
470
|
+
if (marketId in this.markets_by_id) {
|
471
|
+
symbol = this.markets_by_id[marketId]['symbol'];
|
472
|
+
} else {
|
473
|
+
const [ quoteId, baseId ] = marketId.split ('_');
|
474
|
+
const base = this.safeCurrencyCode (baseId);
|
475
|
+
const quote = this.safeCurrencyCode (quoteId);
|
476
|
+
symbol = base + '/' + quote;
|
477
|
+
}
|
478
|
+
const orderbook = this.parseOrderBook (response[marketId], symbol);
|
479
|
+
orderbook['nonce'] = this.safeInteger (response[marketId], 'seq');
|
480
|
+
result[symbol] = orderbook;
|
481
|
+
}
|
482
|
+
return result;
|
483
|
+
}
|
484
|
+
|
485
|
+
parseTicker (ticker, market = undefined) {
|
486
|
+
// {
|
487
|
+
// id: '121',
|
488
|
+
// last: '43196.31469670',
|
489
|
+
// lowestAsk: '43209.61843169',
|
490
|
+
// highestBid: '43162.41965234',
|
491
|
+
// percentChange: '0.00963340',
|
492
|
+
// baseVolume: '13444643.33799658',
|
493
|
+
// quoteVolume: '315.84780115',
|
494
|
+
// isFrozen: '0',
|
495
|
+
// postOnly: '0',
|
496
|
+
// marginTradingEnabled: '1',
|
497
|
+
// high24hr: '43451.84481934',
|
498
|
+
// low24hr: '41749.89529736'
|
499
|
+
// }
|
500
|
+
const timestamp = this.milliseconds ();
|
501
|
+
const symbol = this.safeSymbol (undefined, market);
|
502
|
+
const last = this.safeString (ticker, 'last');
|
503
|
+
const relativeChange = this.safeString (ticker, 'percentChange');
|
504
|
+
const percentage = Precise.stringMul (relativeChange, '100');
|
505
|
+
return this.safeTicker ({
|
506
|
+
'symbol': symbol,
|
507
|
+
'timestamp': timestamp,
|
508
|
+
'datetime': this.iso8601 (timestamp),
|
509
|
+
'high': this.safeString (ticker, 'high24hr'),
|
510
|
+
'low': this.safeString (ticker, 'low24hr'),
|
511
|
+
'bid': this.safeString (ticker, 'highestBid'),
|
512
|
+
'bidVolume': undefined,
|
513
|
+
'ask': this.safeString (ticker, 'lowestAsk'),
|
514
|
+
'askVolume': undefined,
|
515
|
+
'vwap': undefined,
|
516
|
+
'open': undefined,
|
517
|
+
'close': last,
|
518
|
+
'last': last,
|
519
|
+
'previousClose': undefined,
|
520
|
+
'change': undefined,
|
521
|
+
'percentage': percentage,
|
522
|
+
'average': undefined,
|
523
|
+
'baseVolume': this.safeString (ticker, 'quoteVolume'),
|
524
|
+
'quoteVolume': this.safeString (ticker, 'baseVolume'),
|
525
|
+
'info': ticker,
|
526
|
+
}, market, false);
|
527
|
+
}
|
528
|
+
|
529
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
530
|
+
await this.loadMarkets ();
|
531
|
+
const response = await this.publicGetReturnTicker (params);
|
532
|
+
const ids = Object.keys (response);
|
533
|
+
const result = {};
|
534
|
+
for (let i = 0; i < ids.length; i++) {
|
535
|
+
const id = ids[i];
|
536
|
+
let symbol = undefined;
|
537
|
+
let market = undefined;
|
538
|
+
if (id in this.markets_by_id) {
|
539
|
+
market = this.markets_by_id[id];
|
540
|
+
symbol = market['symbol'];
|
541
|
+
} else {
|
542
|
+
const [ quoteId, baseId ] = id.split ('_');
|
543
|
+
const base = this.safeCurrencyCode (baseId);
|
544
|
+
const quote = this.safeCurrencyCode (quoteId);
|
545
|
+
symbol = base + '/' + quote;
|
546
|
+
market = { 'symbol': symbol };
|
547
|
+
}
|
548
|
+
const ticker = response[id];
|
549
|
+
result[symbol] = this.parseTicker (ticker, market);
|
550
|
+
}
|
551
|
+
return this.filterByArray (result, 'symbol', symbols);
|
552
|
+
}
|
553
|
+
|
554
|
+
async fetchCurrencies (params = {}) {
|
555
|
+
const response = await this.publicGetReturnCurrencies (params);
|
556
|
+
//
|
557
|
+
// {
|
558
|
+
// "id": "293",
|
559
|
+
// "name": "0x",
|
560
|
+
// "humanType": "Sweep to Main Account",
|
561
|
+
// "currencyType": "address",
|
562
|
+
// "txFee": "17.21877546",
|
563
|
+
// "minConf": "12",
|
564
|
+
// "depositAddress": null,
|
565
|
+
// "disabled": "0",
|
566
|
+
// "frozen": "0",
|
567
|
+
// "hexColor": "003831",
|
568
|
+
// "blockchain": "ETH",
|
569
|
+
// "delisted": "0",
|
570
|
+
// "isGeofenced": 0
|
571
|
+
// }
|
572
|
+
//
|
573
|
+
const ids = Object.keys (response);
|
574
|
+
const result = {};
|
575
|
+
for (let i = 0; i < ids.length; i++) {
|
576
|
+
const id = ids[i];
|
577
|
+
const currency = response[id];
|
578
|
+
const precision = 8; // default precision, todo: fix "magic constants"
|
579
|
+
const amountLimit = '1e-8';
|
580
|
+
const code = this.safeCurrencyCode (id);
|
581
|
+
const delisted = this.safeInteger (currency, 'delisted', 0);
|
582
|
+
const disabled = this.safeInteger (currency, 'disabled', 0);
|
583
|
+
const listed = !delisted;
|
584
|
+
const enabled = !disabled;
|
585
|
+
const active = enabled && listed;
|
586
|
+
const numericId = this.safeInteger (currency, 'id');
|
587
|
+
const fee = this.safeNumber (currency, 'txFee');
|
588
|
+
result[code] = {
|
589
|
+
'id': id,
|
590
|
+
'numericId': numericId,
|
591
|
+
'code': code,
|
592
|
+
'info': currency,
|
593
|
+
'name': currency['name'],
|
594
|
+
'active': active,
|
595
|
+
'deposit': undefined,
|
596
|
+
'withdraw': undefined,
|
597
|
+
'fee': fee,
|
598
|
+
'precision': precision,
|
599
|
+
'limits': {
|
600
|
+
'amount': {
|
601
|
+
'min': this.parseNumber (amountLimit),
|
602
|
+
'max': undefined,
|
603
|
+
},
|
604
|
+
'withdraw': {
|
605
|
+
'min': fee,
|
606
|
+
'max': undefined,
|
607
|
+
},
|
608
|
+
},
|
609
|
+
};
|
610
|
+
}
|
611
|
+
return result;
|
612
|
+
}
|
613
|
+
|
614
|
+
async fetchTicker (symbol, params = {}) {
|
615
|
+
await this.loadMarkets ();
|
616
|
+
const market = this.market (symbol);
|
617
|
+
const response = await this.publicGetReturnTicker (params);
|
618
|
+
// {
|
619
|
+
// "BTC_BTS":{
|
620
|
+
// "id":14,
|
621
|
+
// "last":"0.00000073",
|
622
|
+
// "lowestAsk":"0.00000075",
|
623
|
+
// "highestBid":"0.00000073",
|
624
|
+
// "percentChange":"0.01388888",
|
625
|
+
// "baseVolume":"0.01413528",
|
626
|
+
// "quoteVolume":"19431.16872167",
|
627
|
+
// "isFrozen":"0",
|
628
|
+
// "postOnly":"0",
|
629
|
+
// "marginTradingEnabled":"0",
|
630
|
+
// "high24hr":"0.00000074",
|
631
|
+
// "low24hr":"0.00000071"
|
632
|
+
// },
|
633
|
+
// ...
|
634
|
+
// }
|
635
|
+
const ticker = response[market['id']];
|
636
|
+
return this.parseTicker (ticker, market);
|
637
|
+
}
|
638
|
+
|
639
|
+
parseTrade (trade, market = undefined) {
|
640
|
+
//
|
641
|
+
// fetchTrades
|
642
|
+
//
|
643
|
+
// {
|
644
|
+
// globalTradeID: "667563407",
|
645
|
+
// tradeID: "1984256",
|
646
|
+
// date: "2022-03-01 20:06:06",
|
647
|
+
// type: "buy",
|
648
|
+
// rate: "0.13361871",
|
649
|
+
// amount: "28.40841257",
|
650
|
+
// total: "3.79589544",
|
651
|
+
// orderNumber: "159992152911"
|
652
|
+
// }
|
653
|
+
//
|
654
|
+
// fetchMyTrades
|
655
|
+
//
|
656
|
+
// {
|
657
|
+
// globalTradeID: 471030550,
|
658
|
+
// tradeID: '42582',
|
659
|
+
// date: '2020-06-16 09:47:50',
|
660
|
+
// rate: '0.000079980000',
|
661
|
+
// amount: '75215.00000000',
|
662
|
+
// total: '6.01569570',
|
663
|
+
// fee: '0.00095000',
|
664
|
+
// feeDisplay: '0.26636100 TRX (0.07125%)',
|
665
|
+
// orderNumber: '5963454848',
|
666
|
+
// type: 'sell',
|
667
|
+
// category: 'exchange'
|
668
|
+
// }
|
669
|
+
//
|
670
|
+
// createOrder (taker trades)
|
671
|
+
//
|
672
|
+
// {
|
673
|
+
// 'amount': '200.00000000',
|
674
|
+
// 'date': '2019-12-15 16:04:10',
|
675
|
+
// 'rate': '0.00000355',
|
676
|
+
// 'total': '0.00071000',
|
677
|
+
// 'tradeID': '119871',
|
678
|
+
// 'type': 'buy',
|
679
|
+
// 'takerAdjustment': '200.00000000'
|
680
|
+
// }
|
681
|
+
//
|
682
|
+
const id = this.safeString2 (trade, 'globalTradeID', 'tradeID');
|
683
|
+
const orderId = this.safeString (trade, 'orderNumber');
|
684
|
+
const timestamp = this.parse8601 (this.safeString (trade, 'date'));
|
685
|
+
const marketId = this.safeString (trade, 'currencyPair');
|
686
|
+
market = this.safeMarket (marketId, market, '_');
|
687
|
+
const symbol = market['symbol'];
|
688
|
+
const side = this.safeString (trade, 'type');
|
689
|
+
let fee = undefined;
|
690
|
+
const priceString = this.safeString (trade, 'rate');
|
691
|
+
const amountString = this.safeString (trade, 'amount');
|
692
|
+
const costString = this.safeString (trade, 'total');
|
693
|
+
const feeDisplay = this.safeString (trade, 'feeDisplay');
|
694
|
+
if (feeDisplay !== undefined) {
|
695
|
+
const parts = feeDisplay.split (' ');
|
696
|
+
const feeCostString = this.safeString (parts, 0);
|
697
|
+
if (feeCostString !== undefined) {
|
698
|
+
const feeCurrencyId = this.safeString (parts, 1);
|
699
|
+
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
700
|
+
let feeRateString = this.safeString (parts, 2);
|
701
|
+
if (feeRateString !== undefined) {
|
702
|
+
feeRateString = feeRateString.replace ('(', '');
|
703
|
+
const feeRateParts = feeRateString.split ('%');
|
704
|
+
feeRateString = this.safeString (feeRateParts, 0);
|
705
|
+
feeRateString = Precise.stringDiv (feeRateString, '100');
|
706
|
+
}
|
707
|
+
fee = {
|
708
|
+
'cost': feeCostString,
|
709
|
+
'currency': feeCurrencyCode,
|
710
|
+
'rate': feeRateString,
|
711
|
+
};
|
712
|
+
}
|
713
|
+
} else {
|
714
|
+
const feeCostString = this.safeString (trade, 'fee');
|
715
|
+
if (feeCostString !== undefined && market !== undefined) {
|
716
|
+
const feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
|
717
|
+
const feeBase = (side === 'buy') ? amountString : costString;
|
718
|
+
const feeRateString = Precise.stringDiv (feeCostString, feeBase);
|
719
|
+
fee = {
|
720
|
+
'cost': feeCostString,
|
721
|
+
'currency': feeCurrencyCode,
|
722
|
+
'rate': feeRateString,
|
723
|
+
};
|
724
|
+
}
|
725
|
+
}
|
726
|
+
let takerOrMaker = undefined;
|
727
|
+
const takerAdjustment = this.safeNumber (trade, 'takerAdjustment');
|
728
|
+
if (takerAdjustment !== undefined) {
|
729
|
+
takerOrMaker = 'taker';
|
730
|
+
}
|
731
|
+
return this.safeTrade ({
|
732
|
+
'id': id,
|
733
|
+
'info': trade,
|
734
|
+
'timestamp': timestamp,
|
735
|
+
'datetime': this.iso8601 (timestamp),
|
736
|
+
'symbol': symbol,
|
737
|
+
'order': orderId,
|
738
|
+
'type': 'limit',
|
739
|
+
'side': side,
|
740
|
+
'takerOrMaker': takerOrMaker,
|
741
|
+
'price': priceString,
|
742
|
+
'amount': amountString,
|
743
|
+
'cost': costString,
|
744
|
+
'fee': fee,
|
745
|
+
}, market);
|
746
|
+
}
|
747
|
+
|
748
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
749
|
+
await this.loadMarkets ();
|
750
|
+
const market = this.market (symbol);
|
751
|
+
const request = {
|
752
|
+
'currencyPair': market['id'],
|
753
|
+
};
|
754
|
+
if (since !== undefined) {
|
755
|
+
request['start'] = parseInt (since / 1000);
|
756
|
+
request['end'] = this.seconds (); // last 50000 trades by default
|
757
|
+
}
|
758
|
+
const trades = await this.publicGetReturnTradeHistory (this.extend (request, params));
|
759
|
+
return this.parseTrades (trades, market, since, limit);
|
760
|
+
}
|
761
|
+
|
762
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
763
|
+
await this.loadMarkets ();
|
764
|
+
let market = undefined;
|
765
|
+
if (symbol !== undefined) {
|
766
|
+
market = this.market (symbol);
|
767
|
+
}
|
768
|
+
const pair = market ? market['id'] : 'all';
|
769
|
+
const request = { 'currencyPair': pair };
|
770
|
+
if (since !== undefined) {
|
771
|
+
request['start'] = parseInt (since / 1000);
|
772
|
+
request['end'] = this.sum (this.seconds (), 1); // adding 1 is a fix for #3411
|
773
|
+
}
|
774
|
+
// limit is disabled (does not really work as expected)
|
775
|
+
if (limit !== undefined) {
|
776
|
+
request['limit'] = parseInt (limit);
|
777
|
+
}
|
778
|
+
const response = await this.privatePostReturnTradeHistory (this.extend (request, params));
|
779
|
+
//
|
780
|
+
// specific market (symbol defined)
|
781
|
+
//
|
782
|
+
// [
|
783
|
+
// {
|
784
|
+
// globalTradeID: 470912587,
|
785
|
+
// tradeID: '42543',
|
786
|
+
// date: '2020-06-15 17:31:22',
|
787
|
+
// rate: '0.000083840000',
|
788
|
+
// amount: '95237.60321429',
|
789
|
+
// total: '7.98472065',
|
790
|
+
// fee: '0.00095000',
|
791
|
+
// feeDisplay: '0.36137761 TRX (0.07125%)',
|
792
|
+
// orderNumber: '5926344995',
|
793
|
+
// type: 'sell',
|
794
|
+
// category: 'exchange'
|
795
|
+
// },
|
796
|
+
// {
|
797
|
+
// globalTradeID: 470974497,
|
798
|
+
// tradeID: '42560',
|
799
|
+
// date: '2020-06-16 00:41:23',
|
800
|
+
// rate: '0.000078220000',
|
801
|
+
// amount: '1000000.00000000',
|
802
|
+
// total: '78.22000000',
|
803
|
+
// fee: '0.00095000',
|
804
|
+
// feeDisplay: '3.48189819 TRX (0.07125%)',
|
805
|
+
// orderNumber: '5945490830',
|
806
|
+
// type: 'sell',
|
807
|
+
// category: 'exchange'
|
808
|
+
// }
|
809
|
+
// ]
|
810
|
+
//
|
811
|
+
// all markets (symbol undefined)
|
812
|
+
//
|
813
|
+
// {
|
814
|
+
// BTC_GNT: [{
|
815
|
+
// globalTradeID: 470839947,
|
816
|
+
// tradeID: '4322347',
|
817
|
+
// date: '2020-06-15 12:25:24',
|
818
|
+
// rate: '0.000005810000',
|
819
|
+
// amount: '1702.04429303',
|
820
|
+
// total: '0.00988887',
|
821
|
+
// fee: '0.00095000',
|
822
|
+
// feeDisplay: '4.18235294 TRX (0.07125%)',
|
823
|
+
// orderNumber: '102290272520',
|
824
|
+
// type: 'buy',
|
825
|
+
// category: 'exchange'
|
826
|
+
// }, {
|
827
|
+
// globalTradeID: 470895902,
|
828
|
+
// tradeID: '4322413',
|
829
|
+
// date: '2020-06-15 16:19:00',
|
830
|
+
// rate: '0.000005980000',
|
831
|
+
// amount: '18.66879219',
|
832
|
+
// total: '0.00011163',
|
833
|
+
// fee: '0.00095000',
|
834
|
+
// feeDisplay: '0.04733727 TRX (0.07125%)',
|
835
|
+
// orderNumber: '102298304480',
|
836
|
+
// type: 'buy',
|
837
|
+
// category: 'exchange'
|
838
|
+
// }],
|
839
|
+
// }
|
840
|
+
//
|
841
|
+
let result = [];
|
842
|
+
if (market !== undefined) {
|
843
|
+
result = this.parseTrades (response, market);
|
844
|
+
} else {
|
845
|
+
if (response) {
|
846
|
+
const ids = Object.keys (response);
|
847
|
+
for (let i = 0; i < ids.length; i++) {
|
848
|
+
const id = ids[i];
|
849
|
+
let market = undefined;
|
850
|
+
if (id in this.markets_by_id) {
|
851
|
+
market = this.markets_by_id[id];
|
852
|
+
const trades = this.parseTrades (response[id], market);
|
853
|
+
for (let j = 0; j < trades.length; j++) {
|
854
|
+
result.push (trades[j]);
|
855
|
+
}
|
856
|
+
} else {
|
857
|
+
const [ quoteId, baseId ] = id.split ('_');
|
858
|
+
const base = this.safeCurrencyCode (baseId);
|
859
|
+
const quote = this.safeCurrencyCode (quoteId);
|
860
|
+
const symbol = base + '/' + quote;
|
861
|
+
const trades = response[id];
|
862
|
+
for (let j = 0; j < trades.length; j++) {
|
863
|
+
const market = {
|
864
|
+
'symbol': symbol,
|
865
|
+
'base': base,
|
866
|
+
'quote': quote,
|
867
|
+
};
|
868
|
+
result.push (this.parseTrade (trades[j], market));
|
869
|
+
}
|
870
|
+
}
|
871
|
+
}
|
872
|
+
}
|
873
|
+
}
|
874
|
+
return this.filterBySinceLimit (result, since, limit);
|
875
|
+
}
|
876
|
+
|
877
|
+
parseOrderStatus (status) {
|
878
|
+
const statuses = {
|
879
|
+
'Open': 'open',
|
880
|
+
'Partially filled': 'open',
|
881
|
+
};
|
882
|
+
return this.safeString (statuses, status, status);
|
883
|
+
}
|
884
|
+
|
885
|
+
parseOrder (order, market = undefined) {
|
886
|
+
//
|
887
|
+
// fetchOpenOrder
|
888
|
+
//
|
889
|
+
// {
|
890
|
+
// status: 'Open',
|
891
|
+
// rate: '0.40000000',
|
892
|
+
// amount: '1.00000000',
|
893
|
+
// currencyPair: 'BTC_ETH',
|
894
|
+
// date: '2018-10-17 17:04:50',
|
895
|
+
// total: '0.40000000',
|
896
|
+
// type: 'buy',
|
897
|
+
// startingAmount: '1.00000',
|
898
|
+
// }
|
899
|
+
//
|
900
|
+
// fetchOpenOrders
|
901
|
+
//
|
902
|
+
// {
|
903
|
+
// orderNumber: '514514894224',
|
904
|
+
// type: 'buy',
|
905
|
+
// rate: '0.00001000',
|
906
|
+
// startingAmount: '100.00000000',
|
907
|
+
// amount: '100.00000000',
|
908
|
+
// total: '0.00100000',
|
909
|
+
// date: '2018-10-23 17:38:53',
|
910
|
+
// margin: 0,
|
911
|
+
// }
|
912
|
+
//
|
913
|
+
// createOrder
|
914
|
+
//
|
915
|
+
// {
|
916
|
+
// 'orderNumber': '9805453960',
|
917
|
+
// 'resultingTrades': [
|
918
|
+
// {
|
919
|
+
// 'amount': '200.00000000',
|
920
|
+
// 'date': '2019-12-15 16:04:10',
|
921
|
+
// 'rate': '0.00000355',
|
922
|
+
// 'total': '0.00071000',
|
923
|
+
// 'tradeID': '119871',
|
924
|
+
// 'type': 'buy',
|
925
|
+
// 'takerAdjustment': '200.00000000',
|
926
|
+
// },
|
927
|
+
// ],
|
928
|
+
// 'fee': '0.00000000',
|
929
|
+
// 'clientOrderId': '12345',
|
930
|
+
// 'currencyPair': 'BTC_MANA',
|
931
|
+
// // 'resultingTrades' in editOrder
|
932
|
+
// 'resultingTrades': {
|
933
|
+
// 'BTC_MANA': [],
|
934
|
+
// }
|
935
|
+
// }
|
936
|
+
//
|
937
|
+
let timestamp = this.safeInteger (order, 'timestamp');
|
938
|
+
if (timestamp === undefined) {
|
939
|
+
timestamp = this.parse8601 (this.safeString (order, 'date'));
|
940
|
+
}
|
941
|
+
const marketId = this.safeString (order, 'currencyPair');
|
942
|
+
market = this.safeMarket (marketId, market, '_');
|
943
|
+
const symbol = market['symbol'];
|
944
|
+
let resultingTrades = this.safeValue (order, 'resultingTrades');
|
945
|
+
if (!Array.isArray (resultingTrades)) {
|
946
|
+
resultingTrades = this.safeValue (resultingTrades, this.safeString (market, 'id', marketId));
|
947
|
+
}
|
948
|
+
const price = this.safeString2 (order, 'price', 'rate');
|
949
|
+
const remaining = this.safeString (order, 'amount');
|
950
|
+
const amount = this.safeString (order, 'startingAmount');
|
951
|
+
const status = this.parseOrderStatus (this.safeString (order, 'status'));
|
952
|
+
const side = this.safeString (order, 'type');
|
953
|
+
const id = this.safeString (order, 'orderNumber');
|
954
|
+
let fee = undefined;
|
955
|
+
const feeCurrency = this.safeString (order, 'tokenFeeCurrency');
|
956
|
+
let feeCost = undefined;
|
957
|
+
let feeCurrencyCode = undefined;
|
958
|
+
const rate = this.safeString (order, 'fee');
|
959
|
+
if (feeCurrency === undefined) {
|
960
|
+
feeCurrencyCode = (side === 'buy') ? market['base'] : market['quote'];
|
961
|
+
} else {
|
962
|
+
// poloniex accepts a 30% discount to pay fees in TRX
|
963
|
+
feeCurrencyCode = this.safeCurrencyCode (feeCurrency);
|
964
|
+
feeCost = this.safeString (order, 'tokenFee');
|
965
|
+
}
|
966
|
+
if (feeCost !== undefined) {
|
967
|
+
fee = {
|
968
|
+
'rate': rate,
|
969
|
+
'cost': feeCost,
|
970
|
+
'currency': feeCurrencyCode,
|
971
|
+
};
|
972
|
+
}
|
973
|
+
const clientOrderId = this.safeString (order, 'clientOrderId');
|
974
|
+
return this.safeOrder ({
|
975
|
+
'info': order,
|
976
|
+
'id': id,
|
977
|
+
'clientOrderId': clientOrderId,
|
978
|
+
'timestamp': timestamp,
|
979
|
+
'datetime': this.iso8601 (timestamp),
|
980
|
+
'lastTradeTimestamp': undefined,
|
981
|
+
'status': status,
|
982
|
+
'symbol': symbol,
|
983
|
+
'type': 'limit',
|
984
|
+
'timeInForce': undefined,
|
985
|
+
'postOnly': undefined,
|
986
|
+
'side': side,
|
987
|
+
'price': price,
|
988
|
+
'stopPrice': undefined,
|
989
|
+
'cost': undefined,
|
990
|
+
'average': undefined,
|
991
|
+
'amount': amount,
|
992
|
+
'filled': undefined,
|
993
|
+
'remaining': remaining,
|
994
|
+
'trades': resultingTrades,
|
995
|
+
'fee': fee,
|
996
|
+
}, market);
|
997
|
+
}
|
998
|
+
|
999
|
+
parseOpenOrders (orders, market, result) {
|
1000
|
+
for (let i = 0; i < orders.length; i++) {
|
1001
|
+
const order = orders[i];
|
1002
|
+
const extended = this.extend (order, {
|
1003
|
+
'status': 'open',
|
1004
|
+
'type': 'limit',
|
1005
|
+
'side': order['type'],
|
1006
|
+
'price': order['rate'],
|
1007
|
+
});
|
1008
|
+
result.push (this.parseOrder (extended, market));
|
1009
|
+
}
|
1010
|
+
return result;
|
1011
|
+
}
|
1012
|
+
|
1013
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1014
|
+
await this.loadMarkets ();
|
1015
|
+
let market = undefined;
|
1016
|
+
if (symbol !== undefined) {
|
1017
|
+
market = this.market (symbol);
|
1018
|
+
}
|
1019
|
+
const pair = market ? market['id'] : 'all';
|
1020
|
+
const request = {
|
1021
|
+
'currencyPair': pair,
|
1022
|
+
};
|
1023
|
+
const response = await this.privatePostReturnOpenOrders (this.extend (request, params));
|
1024
|
+
const extension = { 'status': 'open' };
|
1025
|
+
if (market === undefined) {
|
1026
|
+
const marketIds = Object.keys (response);
|
1027
|
+
let openOrders = [];
|
1028
|
+
for (let i = 0; i < marketIds.length; i++) {
|
1029
|
+
const marketId = marketIds[i];
|
1030
|
+
const orders = response[marketId];
|
1031
|
+
const m = this.markets_by_id[marketId];
|
1032
|
+
openOrders = this.arrayConcat (openOrders, this.parseOrders (orders, m, undefined, undefined, extension));
|
1033
|
+
}
|
1034
|
+
return this.filterBySinceLimit (openOrders, since, limit);
|
1035
|
+
} else {
|
1036
|
+
return this.parseOrders (response, market, since, limit, extension);
|
1037
|
+
}
|
1038
|
+
}
|
1039
|
+
|
1040
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1041
|
+
if (type === 'market') {
|
1042
|
+
throw new ExchangeError (this.id + ' createOrder() does not accept market orders');
|
1043
|
+
}
|
1044
|
+
await this.loadMarkets ();
|
1045
|
+
const method = 'privatePost' + this.capitalize (side);
|
1046
|
+
const market = this.market (symbol);
|
1047
|
+
amount = this.amountToPrecision (symbol, amount);
|
1048
|
+
const request = {
|
1049
|
+
'currencyPair': market['id'],
|
1050
|
+
'rate': this.priceToPrecision (symbol, price),
|
1051
|
+
'amount': amount,
|
1052
|
+
};
|
1053
|
+
const clientOrderId = this.safeString (params, 'clientOrderId');
|
1054
|
+
if (clientOrderId !== undefined) {
|
1055
|
+
request['clientOrderId'] = clientOrderId;
|
1056
|
+
params = this.omit (params, 'clientOrderId');
|
1057
|
+
}
|
1058
|
+
// remember the timestamp before issuing the request
|
1059
|
+
let response = await this[method] (this.extend (request, params));
|
1060
|
+
//
|
1061
|
+
// {
|
1062
|
+
// 'orderNumber': '9805453960',
|
1063
|
+
// 'resultingTrades': [
|
1064
|
+
// {
|
1065
|
+
// 'amount': '200.00000000',
|
1066
|
+
// 'date': '2019-12-15 16:04:10',
|
1067
|
+
// 'rate': '0.00000355',
|
1068
|
+
// 'total': '0.00071000',
|
1069
|
+
// 'tradeID': '119871',
|
1070
|
+
// 'type': 'buy',
|
1071
|
+
// 'takerAdjustment': '200.00000000',
|
1072
|
+
// },
|
1073
|
+
// ],
|
1074
|
+
// 'fee': '0.00000000',
|
1075
|
+
// 'currencyPair': 'BTC_MANA',
|
1076
|
+
// }
|
1077
|
+
//
|
1078
|
+
response = this.extend (response, {
|
1079
|
+
'type': side,
|
1080
|
+
});
|
1081
|
+
return this.parseOrder (response, market);
|
1082
|
+
}
|
1083
|
+
|
1084
|
+
async editOrder (id, symbol, type, side, amount, price = undefined, params = {}) {
|
1085
|
+
await this.loadMarkets ();
|
1086
|
+
price = parseFloat (price);
|
1087
|
+
const request = {
|
1088
|
+
'orderNumber': id,
|
1089
|
+
'rate': this.priceToPrecision (symbol, price),
|
1090
|
+
};
|
1091
|
+
if (amount !== undefined) {
|
1092
|
+
request['amount'] = this.amountToPrecision (symbol, amount);
|
1093
|
+
}
|
1094
|
+
const response = await this.privatePostMoveOrder (this.extend (request, params));
|
1095
|
+
return this.parseOrder (response);
|
1096
|
+
}
|
1097
|
+
|
1098
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1099
|
+
await this.loadMarkets ();
|
1100
|
+
const request = {};
|
1101
|
+
const clientOrderId = this.safeValue (params, 'clientOrderId');
|
1102
|
+
if (clientOrderId === undefined) {
|
1103
|
+
request['orderNumber'] = id;
|
1104
|
+
} else {
|
1105
|
+
request['clientOrderId'] = clientOrderId;
|
1106
|
+
}
|
1107
|
+
params = this.omit (params, 'clientOrderId');
|
1108
|
+
return await this.privatePostCancelOrder (this.extend (request, params));
|
1109
|
+
}
|
1110
|
+
|
1111
|
+
async cancelAllOrders (symbol = undefined, params = {}) {
|
1112
|
+
const request = {};
|
1113
|
+
let market = undefined;
|
1114
|
+
if (symbol !== undefined) {
|
1115
|
+
market = this.market (symbol);
|
1116
|
+
request['currencyPair'] = market['id'];
|
1117
|
+
}
|
1118
|
+
const response = await this.privatePostCancelAllOrders (this.extend (request, params));
|
1119
|
+
//
|
1120
|
+
// {
|
1121
|
+
// "success": 1,
|
1122
|
+
// "message": "Orders canceled",
|
1123
|
+
// "orderNumbers": [
|
1124
|
+
// 503749,
|
1125
|
+
// 888321,
|
1126
|
+
// 7315825,
|
1127
|
+
// 7316824
|
1128
|
+
// ]
|
1129
|
+
// }
|
1130
|
+
//
|
1131
|
+
return response;
|
1132
|
+
}
|
1133
|
+
|
1134
|
+
async fetchOpenOrder (id, symbol = undefined, params = {}) {
|
1135
|
+
await this.loadMarkets ();
|
1136
|
+
id = id.toString ();
|
1137
|
+
const request = {
|
1138
|
+
'orderNumber': id,
|
1139
|
+
};
|
1140
|
+
const response = await this.privatePostReturnOrderStatus (this.extend (request, params));
|
1141
|
+
//
|
1142
|
+
// {
|
1143
|
+
// success: 1,
|
1144
|
+
// result: {
|
1145
|
+
// '6071071': {
|
1146
|
+
// status: 'Open',
|
1147
|
+
// rate: '0.40000000',
|
1148
|
+
// amount: '1.00000000',
|
1149
|
+
// currencyPair: 'BTC_ETH',
|
1150
|
+
// date: '2018-10-17 17:04:50',
|
1151
|
+
// total: '0.40000000',
|
1152
|
+
// type: 'buy',
|
1153
|
+
// startingAmount: '1.00000',
|
1154
|
+
// },
|
1155
|
+
// },
|
1156
|
+
// }
|
1157
|
+
//
|
1158
|
+
const result = this.safeValue (response['result'], id);
|
1159
|
+
if (result === undefined) {
|
1160
|
+
throw new OrderNotFound (this.id + ' order id ' + id + ' not found');
|
1161
|
+
}
|
1162
|
+
return this.extend (this.parseOrder (result), {
|
1163
|
+
'id': id,
|
1164
|
+
});
|
1165
|
+
}
|
1166
|
+
|
1167
|
+
async fetchClosedOrder (id, symbol = undefined, params = {}) {
|
1168
|
+
await this.loadMarkets ();
|
1169
|
+
const request = {
|
1170
|
+
'orderNumber': id,
|
1171
|
+
};
|
1172
|
+
const response = await this.privatePostReturnOrderTrades (this.extend (request, params));
|
1173
|
+
//
|
1174
|
+
// [
|
1175
|
+
// {
|
1176
|
+
// "globalTradeID":570264000,
|
1177
|
+
// "tradeID":8026283,
|
1178
|
+
// "currencyPair":"USDT_LTC",
|
1179
|
+
// "type":"sell",
|
1180
|
+
// "rate":"144.73833409",
|
1181
|
+
// "amount":"0.18334460",
|
1182
|
+
// "total":"26.53699196",
|
1183
|
+
// "fee":"0.00155000",
|
1184
|
+
// "date":"2021-07-04 15:16:20"
|
1185
|
+
// }
|
1186
|
+
// ]
|
1187
|
+
//
|
1188
|
+
const firstTrade = this.safeValue (response, 0);
|
1189
|
+
if (firstTrade === undefined) {
|
1190
|
+
throw new OrderNotFound (this.id + ' order id ' + id + ' not found');
|
1191
|
+
}
|
1192
|
+
id = this.safeValue (firstTrade, 'globalTradeID', id);
|
1193
|
+
return this.safeOrder ({
|
1194
|
+
'info': response,
|
1195
|
+
'id': id,
|
1196
|
+
'clientOrderId': this.safeValue (firstTrade, 'clientOrderId'),
|
1197
|
+
'timestamp': undefined,
|
1198
|
+
'datetime': undefined,
|
1199
|
+
'lastTradeTimestamp': undefined,
|
1200
|
+
'status': 'closed',
|
1201
|
+
'symbol': undefined,
|
1202
|
+
'type': undefined,
|
1203
|
+
'timeInForce': undefined,
|
1204
|
+
'postOnly': undefined,
|
1205
|
+
'side': undefined,
|
1206
|
+
'price': undefined,
|
1207
|
+
'stopPrice': undefined,
|
1208
|
+
'cost': undefined,
|
1209
|
+
'average': undefined,
|
1210
|
+
'amount': undefined,
|
1211
|
+
'filled': undefined,
|
1212
|
+
'remaining': undefined,
|
1213
|
+
'trades': response,
|
1214
|
+
'fee': undefined,
|
1215
|
+
});
|
1216
|
+
}
|
1217
|
+
|
1218
|
+
async fetchOrderStatus (id, symbol = undefined, params = {}) {
|
1219
|
+
await this.loadMarkets ();
|
1220
|
+
const orders = await this.fetchOpenOrders (symbol, undefined, undefined, params);
|
1221
|
+
const indexed = this.indexBy (orders, 'id');
|
1222
|
+
return (id in indexed) ? 'open' : 'closed';
|
1223
|
+
}
|
1224
|
+
|
1225
|
+
async fetchOrderTrades (id, symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1226
|
+
await this.loadMarkets ();
|
1227
|
+
const request = {
|
1228
|
+
'orderNumber': id,
|
1229
|
+
};
|
1230
|
+
const trades = await this.privatePostReturnOrderTrades (this.extend (request, params));
|
1231
|
+
return this.parseTrades (trades);
|
1232
|
+
}
|
1233
|
+
|
1234
|
+
async createDepositAddress (code, params = {}) {
|
1235
|
+
await this.loadMarkets ();
|
1236
|
+
// USDT, USDTETH, USDTTRON
|
1237
|
+
let currencyId = undefined;
|
1238
|
+
let currency = undefined;
|
1239
|
+
if (code in this.currencies) {
|
1240
|
+
currency = this.currency (code);
|
1241
|
+
currencyId = currency['id'];
|
1242
|
+
} else {
|
1243
|
+
currencyId = code;
|
1244
|
+
}
|
1245
|
+
const request = {
|
1246
|
+
'currency': currencyId,
|
1247
|
+
};
|
1248
|
+
const response = await this.privatePostGenerateNewAddress (this.extend (request, params));
|
1249
|
+
let address = undefined;
|
1250
|
+
let tag = undefined;
|
1251
|
+
const success = this.safeString (response, 'success');
|
1252
|
+
if (success === '1') {
|
1253
|
+
address = this.safeString (response, 'response');
|
1254
|
+
}
|
1255
|
+
this.checkAddress (address);
|
1256
|
+
if (currency !== undefined) {
|
1257
|
+
const depositAddress = this.safeString (currency['info'], 'depositAddress');
|
1258
|
+
if (depositAddress !== undefined) {
|
1259
|
+
tag = address;
|
1260
|
+
address = depositAddress;
|
1261
|
+
}
|
1262
|
+
}
|
1263
|
+
return {
|
1264
|
+
'currency': code,
|
1265
|
+
'address': address,
|
1266
|
+
'tag': tag,
|
1267
|
+
'info': response,
|
1268
|
+
};
|
1269
|
+
}
|
1270
|
+
|
1271
|
+
async fetchDepositAddress (code, params = {}) {
|
1272
|
+
await this.loadMarkets ();
|
1273
|
+
const response = await this.privatePostReturnDepositAddresses (params);
|
1274
|
+
// USDT, USDTETH, USDTTRON
|
1275
|
+
let currencyId = undefined;
|
1276
|
+
let currency = undefined;
|
1277
|
+
if (code in this.currencies) {
|
1278
|
+
currency = this.currency (code);
|
1279
|
+
currencyId = currency['id'];
|
1280
|
+
} else {
|
1281
|
+
currencyId = code;
|
1282
|
+
}
|
1283
|
+
let address = this.safeString (response, currencyId);
|
1284
|
+
let tag = undefined;
|
1285
|
+
this.checkAddress (address);
|
1286
|
+
if (currency !== undefined) {
|
1287
|
+
const depositAddress = this.safeString (currency['info'], 'depositAddress');
|
1288
|
+
if (depositAddress !== undefined) {
|
1289
|
+
tag = address;
|
1290
|
+
address = depositAddress;
|
1291
|
+
}
|
1292
|
+
}
|
1293
|
+
return {
|
1294
|
+
'currency': code,
|
1295
|
+
'address': address,
|
1296
|
+
'tag': tag,
|
1297
|
+
'network': undefined,
|
1298
|
+
'info': response,
|
1299
|
+
};
|
1300
|
+
}
|
1301
|
+
|
1302
|
+
async transfer (code, amount, fromAccount, toAccount, params = {}) {
|
1303
|
+
await this.loadMarkets ();
|
1304
|
+
const currency = this.currency (code);
|
1305
|
+
amount = this.currencyToPrecision (code, amount);
|
1306
|
+
const accountsByType = this.safeValue (this.options, 'accountsByType', {});
|
1307
|
+
const fromId = this.safeString (accountsByType, fromAccount, fromAccount);
|
1308
|
+
const toId = this.safeString (accountsByType, toAccount, fromAccount);
|
1309
|
+
const request = {
|
1310
|
+
'amount': amount,
|
1311
|
+
'currency': currency['id'],
|
1312
|
+
'fromAccount': fromId,
|
1313
|
+
'toAccount': toId,
|
1314
|
+
};
|
1315
|
+
const response = await this.privatePostTransferBalance (this.extend (request, params));
|
1316
|
+
//
|
1317
|
+
// {
|
1318
|
+
// success: '1',
|
1319
|
+
// message: 'Transferred 1.00000000 USDT from exchange to lending account.'
|
1320
|
+
// }
|
1321
|
+
//
|
1322
|
+
return this.parseTransfer (response, currency);
|
1323
|
+
}
|
1324
|
+
|
1325
|
+
parseTransferStatus (status) {
|
1326
|
+
const statuses = {
|
1327
|
+
'1': 'ok',
|
1328
|
+
};
|
1329
|
+
return this.safeString (statuses, status, status);
|
1330
|
+
}
|
1331
|
+
|
1332
|
+
parseTransfer (transfer, currency = undefined) {
|
1333
|
+
//
|
1334
|
+
// {
|
1335
|
+
// success: '1',
|
1336
|
+
// message: 'Transferred 1.00000000 USDT from exchange to lending account.'
|
1337
|
+
// }
|
1338
|
+
//
|
1339
|
+
const message = this.safeString (transfer, 'message');
|
1340
|
+
const words = message.split (' ');
|
1341
|
+
const amount = this.safeNumber (words, 1);
|
1342
|
+
const currencyId = this.safeString (words, 2);
|
1343
|
+
const fromAccountId = this.safeString (words, 4);
|
1344
|
+
const toAccountId = this.safeString (words, 6);
|
1345
|
+
const accountsById = this.safeValue (this.options, 'accountsById', {});
|
1346
|
+
return {
|
1347
|
+
'info': transfer,
|
1348
|
+
'id': undefined,
|
1349
|
+
'timestamp': undefined,
|
1350
|
+
'datetime': undefined,
|
1351
|
+
'currency': this.safeCurrencyCode (currencyId, currency),
|
1352
|
+
'amount': amount,
|
1353
|
+
'fromAccount': this.safeString (accountsById, fromAccountId),
|
1354
|
+
'toAccount': this.safeString (accountsById, toAccountId),
|
1355
|
+
'status': this.parseOrderStatus (this.safeString (transfer, 'success', 'failed')),
|
1356
|
+
};
|
1357
|
+
}
|
1358
|
+
|
1359
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
1360
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
1361
|
+
this.checkAddress (address);
|
1362
|
+
await this.loadMarkets ();
|
1363
|
+
const currency = this.currency (code);
|
1364
|
+
const request = {
|
1365
|
+
'currency': currency['id'],
|
1366
|
+
'amount': amount,
|
1367
|
+
'address': address,
|
1368
|
+
};
|
1369
|
+
if (tag !== undefined) {
|
1370
|
+
request['paymentId'] = tag;
|
1371
|
+
}
|
1372
|
+
const networks = this.safeValue (this.options, 'networks', {});
|
1373
|
+
let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
|
1374
|
+
network = this.safeString (networks, network, network); // handle ERC20>ETH alias
|
1375
|
+
if (network !== undefined) {
|
1376
|
+
request['currency'] += network; // when network the currency need to be changed to currency+network https://docs.poloniex.com/#withdraw on MultiChain Currencies section
|
1377
|
+
params = this.omit (params, 'network');
|
1378
|
+
}
|
1379
|
+
const response = await this.privatePostWithdraw (this.extend (request, params));
|
1380
|
+
//
|
1381
|
+
// {
|
1382
|
+
// response: 'Withdrew 1.00000000 USDT.',
|
1383
|
+
// email2FA: false,
|
1384
|
+
// withdrawalNumber: 13449869
|
1385
|
+
// }
|
1386
|
+
//
|
1387
|
+
return this.parseTransaction (response, currency);
|
1388
|
+
}
|
1389
|
+
|
1390
|
+
async fetchTransactionsHelper (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1391
|
+
await this.loadMarkets ();
|
1392
|
+
const year = 31104000; // 60 * 60 * 24 * 30 * 12 = one year of history, why not
|
1393
|
+
const now = this.seconds ();
|
1394
|
+
const start = (since !== undefined) ? parseInt (since / 1000) : now - 10 * year;
|
1395
|
+
const request = {
|
1396
|
+
'start': start, // UNIX timestamp, required
|
1397
|
+
'end': now, // UNIX timestamp, required
|
1398
|
+
};
|
1399
|
+
if (limit !== undefined) {
|
1400
|
+
request['limit'] = limit;
|
1401
|
+
}
|
1402
|
+
const response = await this.privatePostReturnDepositsWithdrawals (this.extend (request, params));
|
1403
|
+
//
|
1404
|
+
// {
|
1405
|
+
// "adjustments":[],
|
1406
|
+
// "deposits":[
|
1407
|
+
// {
|
1408
|
+
// currency: "BTC",
|
1409
|
+
// address: "1MEtiqJWru53FhhHrfJPPvd2tC3TPDVcmW",
|
1410
|
+
// amount: "0.01063000",
|
1411
|
+
// confirmations: 1,
|
1412
|
+
// txid: "952b0e1888d6d491591facc0d37b5ebec540ac1efb241fdbc22bcc20d1822fb6",
|
1413
|
+
// timestamp: 1507916888,
|
1414
|
+
// status: "COMPLETE"
|
1415
|
+
// },
|
1416
|
+
// {
|
1417
|
+
// currency: "ETH",
|
1418
|
+
// address: "0x20108ba20b65c04d82909e91df06618107460197",
|
1419
|
+
// amount: "4.00000000",
|
1420
|
+
// confirmations: 38,
|
1421
|
+
// txid: "0x4be260073491fe63935e9e0da42bd71138fdeb803732f41501015a2d46eb479d",
|
1422
|
+
// timestamp: 1525060430,
|
1423
|
+
// status: "COMPLETE"
|
1424
|
+
// }
|
1425
|
+
// ],
|
1426
|
+
// "withdrawals":[
|
1427
|
+
// {
|
1428
|
+
// "withdrawalNumber":13449869,
|
1429
|
+
// "currency":"USDTTRON", // not documented in API docs, see commonCurrencies in describe()
|
1430
|
+
// "address":"TXGaqPW23JdRWhsVwS2mRsGsegbdnAd3Rw",
|
1431
|
+
// "amount":"1.00000000",
|
1432
|
+
// "fee":"0.00000000",
|
1433
|
+
// "timestamp":1591573420,
|
1434
|
+
// "status":"COMPLETE: dadf427224b3d44b38a2c13caa4395e4666152556ca0b2f67dbd86a95655150f",
|
1435
|
+
// "ipAddress":"x.x.x.x",
|
1436
|
+
// "canCancel":0,
|
1437
|
+
// "canResendEmail":0,
|
1438
|
+
// "paymentID":null,
|
1439
|
+
// "scope":"crypto"
|
1440
|
+
// },
|
1441
|
+
// {
|
1442
|
+
// withdrawalNumber: 8224394,
|
1443
|
+
// currency: "EMC2",
|
1444
|
+
// address: "EYEKyCrqTNmVCpdDV8w49XvSKRP9N3EUyF",
|
1445
|
+
// amount: "63.10796020",
|
1446
|
+
// fee: "0.01000000",
|
1447
|
+
// timestamp: 1510819838,
|
1448
|
+
// status: "COMPLETE: d37354f9d02cb24d98c8c4fc17aa42f475530b5727effdf668ee5a43ce667fd6",
|
1449
|
+
// ipAddress: "x.x.x.x"
|
1450
|
+
// },
|
1451
|
+
// {
|
1452
|
+
// withdrawalNumber: 9290444,
|
1453
|
+
// currency: "ETH",
|
1454
|
+
// address: "0x191015ff2e75261d50433fbd05bd57e942336149",
|
1455
|
+
// amount: "0.15500000",
|
1456
|
+
// fee: "0.00500000",
|
1457
|
+
// timestamp: 1514099289,
|
1458
|
+
// status: "COMPLETE: 0x12d444493b4bca668992021fd9e54b5292b8e71d9927af1f076f554e4bea5b2d",
|
1459
|
+
// ipAddress: "x.x.x.x"
|
1460
|
+
// },
|
1461
|
+
// {
|
1462
|
+
// withdrawalNumber: 11518260,
|
1463
|
+
// currency: "BTC",
|
1464
|
+
// address: "8JoDXAmE1GY2LRK8jD1gmAmgRPq54kXJ4t",
|
1465
|
+
// amount: "0.20000000",
|
1466
|
+
// fee: "0.00050000",
|
1467
|
+
// timestamp: 1527918155,
|
1468
|
+
// status: "COMPLETE: 1864f4ebb277d90b0b1ff53259b36b97fa1990edc7ad2be47c5e0ab41916b5ff",
|
1469
|
+
// ipAddress: "x.x.x.x"
|
1470
|
+
// }
|
1471
|
+
// ]
|
1472
|
+
// }
|
1473
|
+
//
|
1474
|
+
return response;
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
async fetchTransactions (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1478
|
+
await this.loadMarkets ();
|
1479
|
+
const response = await this.fetchTransactionsHelper (code, since, limit, params);
|
1480
|
+
let currency = undefined;
|
1481
|
+
if (code !== undefined) {
|
1482
|
+
currency = this.currency (code);
|
1483
|
+
}
|
1484
|
+
const withdrawals = this.safeValue (response, 'withdrawals', []);
|
1485
|
+
const deposits = this.safeValue (response, 'deposits', []);
|
1486
|
+
const withdrawalTransactions = this.parseTransactions (withdrawals, currency, since, limit);
|
1487
|
+
const depositTransactions = this.parseTransactions (deposits, currency, since, limit);
|
1488
|
+
const transactions = this.arrayConcat (depositTransactions, withdrawalTransactions);
|
1489
|
+
return this.filterByCurrencySinceLimit (this.sortBy (transactions, 'timestamp'), code, since, limit);
|
1490
|
+
}
|
1491
|
+
|
1492
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1493
|
+
const response = await this.fetchTransactionsHelper (code, since, limit, params);
|
1494
|
+
let currency = undefined;
|
1495
|
+
if (code !== undefined) {
|
1496
|
+
currency = this.currency (code);
|
1497
|
+
}
|
1498
|
+
const withdrawals = this.safeValue (response, 'withdrawals', []);
|
1499
|
+
const transactions = this.parseTransactions (withdrawals, currency, since, limit);
|
1500
|
+
return this.filterByCurrencySinceLimit (transactions, code, since, limit);
|
1501
|
+
}
|
1502
|
+
|
1503
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1504
|
+
const response = await this.fetchTransactionsHelper (code, since, limit, params);
|
1505
|
+
let currency = undefined;
|
1506
|
+
if (code !== undefined) {
|
1507
|
+
currency = this.currency (code);
|
1508
|
+
}
|
1509
|
+
const deposits = this.safeValue (response, 'deposits', []);
|
1510
|
+
const transactions = this.parseTransactions (deposits, currency, since, limit);
|
1511
|
+
return this.filterByCurrencySinceLimit (transactions, code, since, limit);
|
1512
|
+
}
|
1513
|
+
|
1514
|
+
parseTransactionStatus (status) {
|
1515
|
+
const statuses = {
|
1516
|
+
'COMPLETE': 'ok',
|
1517
|
+
'AWAITING APPROVAL': 'pending',
|
1518
|
+
'PENDING': 'pending',
|
1519
|
+
'PROCESSING': 'pending',
|
1520
|
+
'COMPLETE ERROR': 'failed',
|
1521
|
+
};
|
1522
|
+
return this.safeString (statuses, status, status);
|
1523
|
+
}
|
1524
|
+
|
1525
|
+
parseTransaction (transaction, currency = undefined) {
|
1526
|
+
//
|
1527
|
+
// deposits
|
1528
|
+
//
|
1529
|
+
// {
|
1530
|
+
// "txid": "f49d489616911db44b740612d19464521179c76ebe9021af85b6de1e2f8d68cd",
|
1531
|
+
// "type": "deposit",
|
1532
|
+
// "amount": "49798.01987021",
|
1533
|
+
// "status": "COMPLETE",
|
1534
|
+
// "address": "DJVJZ58tJC8UeUv9Tqcdtn6uhWobouxFLT",
|
1535
|
+
// "currency": "DOGE",
|
1536
|
+
// "timestamp": 1524321838,
|
1537
|
+
// "confirmations": 3371,
|
1538
|
+
// "depositNumber": 134587098
|
1539
|
+
// }
|
1540
|
+
//
|
1541
|
+
// withdrawals
|
1542
|
+
//
|
1543
|
+
// {
|
1544
|
+
// "fee": "0.00050000",
|
1545
|
+
// "type": "withdrawal",
|
1546
|
+
// "amount": "0.40234387",
|
1547
|
+
// "status": "COMPLETE: fbabb2bf7d81c076f396f3441166d5f60f6cea5fdfe69e02adcc3b27af8c2746",
|
1548
|
+
// "address": "1EdAqY4cqHoJGAgNfUFER7yZpg1Jc9DUa3",
|
1549
|
+
// "currency": "BTC",
|
1550
|
+
// "canCancel": 0,
|
1551
|
+
// "ipAddress": "x.x.x.x",
|
1552
|
+
// "paymentID": null,
|
1553
|
+
// "timestamp": 1523834337,
|
1554
|
+
// "canResendEmail": 0,
|
1555
|
+
// "withdrawalNumber": 11162900
|
1556
|
+
// }
|
1557
|
+
//
|
1558
|
+
// withdraw
|
1559
|
+
//
|
1560
|
+
// {
|
1561
|
+
// response: 'Withdrew 1.00000000 USDT.',
|
1562
|
+
// email2FA: false,
|
1563
|
+
// withdrawalNumber: 13449869
|
1564
|
+
// }
|
1565
|
+
//
|
1566
|
+
const timestamp = this.safeTimestamp (transaction, 'timestamp');
|
1567
|
+
const currencyId = this.safeString (transaction, 'currency');
|
1568
|
+
const code = this.safeCurrencyCode (currencyId);
|
1569
|
+
let status = this.safeString (transaction, 'status', 'pending');
|
1570
|
+
let txid = this.safeString (transaction, 'txid');
|
1571
|
+
if (status !== undefined) {
|
1572
|
+
const parts = status.split (': ');
|
1573
|
+
const numParts = parts.length;
|
1574
|
+
status = parts[0];
|
1575
|
+
if ((numParts > 1) && (txid === undefined)) {
|
1576
|
+
txid = parts[1];
|
1577
|
+
}
|
1578
|
+
status = this.parseTransactionStatus (status);
|
1579
|
+
}
|
1580
|
+
const defaultType = ('withdrawalNumber' in transaction) ? 'withdrawal' : 'deposit';
|
1581
|
+
const type = this.safeString (transaction, 'type', defaultType);
|
1582
|
+
const id = this.safeString2 (transaction, 'withdrawalNumber', 'depositNumber');
|
1583
|
+
let amount = this.safeNumber (transaction, 'amount');
|
1584
|
+
const address = this.safeString (transaction, 'address');
|
1585
|
+
const tag = this.safeString (transaction, 'paymentID');
|
1586
|
+
// according to https://poloniex.com/fees/
|
1587
|
+
const feeCost = this.safeNumber (transaction, 'fee', 0);
|
1588
|
+
if (type === 'withdrawal') {
|
1589
|
+
// poloniex withdrawal amount includes the fee
|
1590
|
+
amount = amount - feeCost;
|
1591
|
+
}
|
1592
|
+
return {
|
1593
|
+
'info': transaction,
|
1594
|
+
'id': id,
|
1595
|
+
'currency': code,
|
1596
|
+
'amount': amount,
|
1597
|
+
'network': undefined,
|
1598
|
+
'address': address,
|
1599
|
+
'addressTo': undefined,
|
1600
|
+
'addressFrom': undefined,
|
1601
|
+
'tag': tag,
|
1602
|
+
'tagTo': undefined,
|
1603
|
+
'tagFrom': undefined,
|
1604
|
+
'status': status,
|
1605
|
+
'type': type,
|
1606
|
+
'updated': undefined,
|
1607
|
+
'txid': txid,
|
1608
|
+
'timestamp': timestamp,
|
1609
|
+
'datetime': this.iso8601 (timestamp),
|
1610
|
+
'fee': {
|
1611
|
+
'currency': code,
|
1612
|
+
'cost': feeCost,
|
1613
|
+
},
|
1614
|
+
};
|
1615
|
+
}
|
1616
|
+
|
1617
|
+
async fetchPosition (symbol, params = {}) {
|
1618
|
+
await this.loadMarkets ();
|
1619
|
+
const market = this.market (symbol);
|
1620
|
+
const request = {
|
1621
|
+
'currencyPair': market['id'],
|
1622
|
+
};
|
1623
|
+
const response = await this.privatePostGetMarginPosition (this.extend (request, params));
|
1624
|
+
//
|
1625
|
+
// {
|
1626
|
+
// type: "none",
|
1627
|
+
// amount: "0.00000000",
|
1628
|
+
// total: "0.00000000",
|
1629
|
+
// basePrice: "0.00000000",
|
1630
|
+
// liquidationPrice: -1,
|
1631
|
+
// pl: "0.00000000",
|
1632
|
+
// lendingFees: "0.00000000"
|
1633
|
+
// }
|
1634
|
+
//
|
1635
|
+
// todo unify parsePosition/parsePositions
|
1636
|
+
return response;
|
1637
|
+
}
|
1638
|
+
|
1639
|
+
nonce () {
|
1640
|
+
return this.milliseconds ();
|
1641
|
+
}
|
1642
|
+
|
1643
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1644
|
+
let url = this.urls['api'][api];
|
1645
|
+
const query = this.extend ({ 'command': path }, params);
|
1646
|
+
if (api === 'public') {
|
1647
|
+
url += '?' + this.urlencode (query);
|
1648
|
+
} else {
|
1649
|
+
this.checkRequiredCredentials ();
|
1650
|
+
query['nonce'] = this.nonce ();
|
1651
|
+
body = this.urlencode (query);
|
1652
|
+
headers = {
|
1653
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
1654
|
+
'Key': this.apiKey,
|
1655
|
+
'Sign': this.hmac (this.encode (body), this.encode (this.secret), 'sha512'),
|
1656
|
+
};
|
1657
|
+
}
|
1658
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1659
|
+
}
|
1660
|
+
|
1661
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
1662
|
+
if (response === undefined) {
|
1663
|
+
return;
|
1664
|
+
}
|
1665
|
+
// {"error":"Permission denied."}
|
1666
|
+
if ('error' in response) {
|
1667
|
+
const message = response['error'];
|
1668
|
+
const feedback = this.id + ' ' + body;
|
1669
|
+
this.throwExactlyMatchedException (this.exceptions['exact'], message, feedback);
|
1670
|
+
this.throwBroadlyMatchedException (this.exceptions['broad'], message, feedback);
|
1671
|
+
throw new ExchangeError (feedback); // unknown message
|
1672
|
+
}
|
1673
|
+
}
|
1674
|
+
};
|