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/xena.js
ADDED
@@ -0,0 +1,1948 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
const Exchange = require ('./base/Exchange');
|
4
|
+
const { ExchangeError, ArgumentsRequired, BadRequest, InsufficientFunds, InvalidAddress, BadSymbol, InvalidOrder } = require ('./base/errors');
|
5
|
+
const Precise = require ('./base/Precise');
|
6
|
+
|
7
|
+
module.exports = class xena extends Exchange {
|
8
|
+
describe () {
|
9
|
+
return this.deepExtend (super.describe (), {
|
10
|
+
'id': 'xena',
|
11
|
+
'name': 'Xena Exchange',
|
12
|
+
'countries': [ 'VC', 'UK' ],
|
13
|
+
// per second rate limits are far lower than the equivalent hourly
|
14
|
+
// requests per second rounded down (3dp)
|
15
|
+
// relative weight costs rounded up (3dp)
|
16
|
+
// 1 hour = 3600 seconds
|
17
|
+
// Order Cancellations: 100k per hour => 100 000 / 3600 = 27.777 requests per second => rateLimit = 1000ms / 27.777 = 36.001008 ms between requests => 36.1 (safety)
|
18
|
+
// New Orders: 30k per hour => 30 000 / 3600 = 8.333 requests per second => cost = 27.777 / 8.333 = 3.333373335 => 3.334
|
19
|
+
// Heartbeat: 30k per hour => 30 000 / 3600 = 8.333 requests per second => cost = 27.777 / 8.333 = 3.333373335 => 3.334
|
20
|
+
// Candles: 5000 per hour => 5000 / 3600 = 1.388 requests per second => cost = 27.777 / 1.388 = 20.01224784 => 20.013
|
21
|
+
// Dom (market data): 5000 per hour => 5000 / 3600 = 1.388 requests per second => cost = 27.777 / 1.388 = 20.01224784 => 20.013
|
22
|
+
// All snapshot requests (balances, active orders and trade history, positions): 500 per hour => 0.138 requests per second => cost = 27.777 / 0.138 = 201.2826087 => 201.283
|
23
|
+
'rateLimit': 36.1,
|
24
|
+
'has': {
|
25
|
+
'CORS': undefined,
|
26
|
+
'spot': false,
|
27
|
+
'margin': false,
|
28
|
+
'swap': undefined, // has but not fully implemented
|
29
|
+
'future': undefined, // has but not fully implemented
|
30
|
+
'option': false,
|
31
|
+
'cancelAllOrders': true,
|
32
|
+
'cancelOrder': true,
|
33
|
+
'createDepositAddress': true,
|
34
|
+
'createOrder': true,
|
35
|
+
'editOrder': true,
|
36
|
+
'fetchAccounts': true,
|
37
|
+
'fetchBalance': true,
|
38
|
+
'fetchBorrowRate': false,
|
39
|
+
'fetchBorrowRateHistories': false,
|
40
|
+
'fetchBorrowRateHistory': false,
|
41
|
+
'fetchBorrowRates': false,
|
42
|
+
'fetchBorrowRatesPerSymbol': false,
|
43
|
+
'fetchClosedOrders': true,
|
44
|
+
'fetchCurrencies': true,
|
45
|
+
'fetchDepositAddress': true,
|
46
|
+
'fetchDeposits': true,
|
47
|
+
'fetchLedger': true,
|
48
|
+
'fetchLeverageTiers': true,
|
49
|
+
'fetchMarketLeverageTiers': 'emulated',
|
50
|
+
'fetchMarkets': true,
|
51
|
+
'fetchMyTrades': true,
|
52
|
+
'fetchOHLCV': true,
|
53
|
+
'fetchOpenOrders': true,
|
54
|
+
'fetchOrderBook': true,
|
55
|
+
'fetchTicker': true,
|
56
|
+
'fetchTickers': true,
|
57
|
+
'fetchTime': true,
|
58
|
+
'fetchTrades': true,
|
59
|
+
'fetchTradingFee': false,
|
60
|
+
'fetchTradingFees': false,
|
61
|
+
'fetchWithdrawals': true,
|
62
|
+
'withdraw': true,
|
63
|
+
},
|
64
|
+
'urls': {
|
65
|
+
'logo': 'https://user-images.githubusercontent.com/51840849/87489843-bb469280-c64c-11ea-91aa-69c6326506af.jpg',
|
66
|
+
'test': {
|
67
|
+
'public': 'https://trading.demo.xena.io/api',
|
68
|
+
'private': 'https://api.demo.xena.io',
|
69
|
+
},
|
70
|
+
'api': {
|
71
|
+
'public': 'https://trading.xena.exchange/api',
|
72
|
+
'private': 'https://api.xena.exchange',
|
73
|
+
},
|
74
|
+
'www': 'https://xena.exchange',
|
75
|
+
'doc': 'https://support.xena.exchange/support/solutions/44000808700',
|
76
|
+
'fees': 'https://trading.xena.exchange/en/contracts/terms-and-condition',
|
77
|
+
},
|
78
|
+
'timeframes': {
|
79
|
+
'1m': '1m',
|
80
|
+
'5m': '5m',
|
81
|
+
'15m': '15m',
|
82
|
+
'30m': '30m',
|
83
|
+
'1h': '1h',
|
84
|
+
'4h': '4h',
|
85
|
+
'12h': '12h',
|
86
|
+
'1d': '1d',
|
87
|
+
'1w': '1w',
|
88
|
+
},
|
89
|
+
'api': {
|
90
|
+
'public': {
|
91
|
+
'get': {
|
92
|
+
'common/currencies': 20.013,
|
93
|
+
'common/instruments': 20.013,
|
94
|
+
'common/features': 20.013,
|
95
|
+
'common/commissions': 20.013,
|
96
|
+
'common/news': 20.013,
|
97
|
+
'market-data/candles/{marketId}/{timeframe}': 20.013,
|
98
|
+
'market-data/market-watch': 20.013,
|
99
|
+
'market-data/dom/{symbol}': 20.013,
|
100
|
+
'market-data/candles/{symbol}/{timeframe}': 20.013,
|
101
|
+
'market-data/trades/{symbol}': 20.013,
|
102
|
+
'market-data/server-time': 20.013,
|
103
|
+
'market-data/v2/candles/{symbol}/{timeframe}': 20.013,
|
104
|
+
'market-data/v2/trades/{symbol}': 20.013,
|
105
|
+
'market-data/v2/dom/{symbol}/': 20.013,
|
106
|
+
'market-data/v2/server-time': 20.013,
|
107
|
+
},
|
108
|
+
},
|
109
|
+
'private': {
|
110
|
+
'get': {
|
111
|
+
'trading/accounts/{accountId}/order': 50,
|
112
|
+
'trading/accounts/{accountId}/active-orders': 50,
|
113
|
+
'trading/accounts/{accountId}/last-order-statuses': 50,
|
114
|
+
'trading/accounts/{accountId}/positions': 50,
|
115
|
+
'trading/accounts/{accountId}/positions-history': 50,
|
116
|
+
'trading/accounts/{accountId}/margin-requirements': 50,
|
117
|
+
'trading/accounts': 50,
|
118
|
+
'trading/accounts/{accountId}/balance': 50, // TESTING (50 works)
|
119
|
+
'trading/accounts/{accountId}/trade-history': 50,
|
120
|
+
// 'trading/accounts/{accountId}/trade-history?symbol=BTC/USDT&client_order_id=EMBB8Veke&trade_id=2205043254': 50,
|
121
|
+
'transfers/accounts': 50,
|
122
|
+
'transfers/accounts/{accountId}': 50,
|
123
|
+
'transfers/accounts/{accountId}/deposit-address/{currency}': 50,
|
124
|
+
'transfers/accounts/{accountId}/deposits': 100, // TESTING
|
125
|
+
'transfers/accounts/{accountId}/trusted-addresses': 50,
|
126
|
+
'transfers/accounts/{accountId}/withdrawals': 50,
|
127
|
+
'transfers/accounts/{accountId}/balance-history': 50,
|
128
|
+
// 'transfers/accounts/{accountId}/balance-history?currency={currency}&from={time}&to={time}&kind={kind}&kind={kind}': 50,
|
129
|
+
// 'transfers/accounts/{accountId}/balance-history?page={page}&limit={limit}': 50,
|
130
|
+
// 'transfers/accounts/{accountId}/balance-history?txid=3e50db982c4eed2d6355e276c5bae01a52a27c9cef61574b0e8c67ee05fc26ccf': 50,
|
131
|
+
},
|
132
|
+
'post': {
|
133
|
+
'trading/order/new': 3.334,
|
134
|
+
'trading/order/heartbeat': 3.334,
|
135
|
+
'trading/order/cancel': 1,
|
136
|
+
'trading/order/mass-cancel': 1,
|
137
|
+
'trading/order/replace': 3.334,
|
138
|
+
'trading/position/maintenance': 3.334,
|
139
|
+
'transfers/accounts/{accountId}/withdrawals': 3.334,
|
140
|
+
'transfers/accounts/{accountId}/deposit-address/{currency}': 3.334,
|
141
|
+
},
|
142
|
+
},
|
143
|
+
},
|
144
|
+
'fees': {
|
145
|
+
'trading': {
|
146
|
+
'maker': 0.0005,
|
147
|
+
'taker': 0.001,
|
148
|
+
'tierBased': true,
|
149
|
+
'percentage': true,
|
150
|
+
},
|
151
|
+
'funding': {
|
152
|
+
'tierBased': false,
|
153
|
+
'percentage': false,
|
154
|
+
'withdraw': {},
|
155
|
+
'deposit': {},
|
156
|
+
},
|
157
|
+
},
|
158
|
+
'exceptions': {
|
159
|
+
'exact': {
|
160
|
+
'Validation failed': BadRequest,
|
161
|
+
'Unknown derivative symbol': BadSymbol, // {"error":"Unknown derivative symbol"}
|
162
|
+
'Unknown account': BadRequest, // {"error":"Unknown account"}
|
163
|
+
'Wrong TransactTime': BadRequest, // {"error":"Wrong TransactTime"}
|
164
|
+
'ClOrdId is empty': BadRequest, // {"error":"ClOrdId is empty"}
|
165
|
+
},
|
166
|
+
'broad': {
|
167
|
+
'Invalid aggregation ratio or depth': BadRequest,
|
168
|
+
'address': InvalidAddress,
|
169
|
+
'Money not enough': InsufficientFunds,
|
170
|
+
'parse error': BadRequest,
|
171
|
+
'Not enough': InsufficientFunds, // {"error":"Not enough free margin"}
|
172
|
+
},
|
173
|
+
},
|
174
|
+
'options': {
|
175
|
+
'defaultType': 'margin', // 'margin',
|
176
|
+
'accountId': undefined, // '1012838157',
|
177
|
+
},
|
178
|
+
});
|
179
|
+
}
|
180
|
+
|
181
|
+
async fetchTime (params = {}) {
|
182
|
+
const response = await this.publicGetMarketDataV2ServerTime (params);
|
183
|
+
//
|
184
|
+
// {
|
185
|
+
// "msgType":"0",
|
186
|
+
// "transactTime":1594774454112817637
|
187
|
+
// }
|
188
|
+
//
|
189
|
+
const transactTime = this.safeInteger (response, 'transactTime');
|
190
|
+
return parseInt (transactTime / 1000000);
|
191
|
+
}
|
192
|
+
|
193
|
+
async fetchMarkets (params = {}) {
|
194
|
+
const response = await this.publicGetCommonInstruments (params);
|
195
|
+
//
|
196
|
+
// [
|
197
|
+
// {
|
198
|
+
// "type": "Index",
|
199
|
+
// "symbol": ".ADAUSD",
|
200
|
+
// "tickSize": 4,
|
201
|
+
// "enabled": true
|
202
|
+
// },
|
203
|
+
// {
|
204
|
+
// "id":"ETHUSD_3M_250920",
|
205
|
+
// "type":"Margin",
|
206
|
+
// "marginType":"XenaFuture",
|
207
|
+
// "symbol":"ETHUSD_3M_250920",
|
208
|
+
// "baseCurrency":"ETH",
|
209
|
+
// "quoteCurrency":"USD",
|
210
|
+
// "settlCurrency":"BTC",
|
211
|
+
// "tickSize":2,
|
212
|
+
// "minOrderQuantity":"1",
|
213
|
+
// "orderQtyStep":"1",
|
214
|
+
// "limitOrderMaxDistance":"10",
|
215
|
+
// "priceInputMask":"0000.00",
|
216
|
+
// "enabled":true,
|
217
|
+
// "liquidationMaxDistance":"0.01",
|
218
|
+
// "contractValue":"1",
|
219
|
+
// "contractCurrency":"BTC",
|
220
|
+
// "lotSize":"1",
|
221
|
+
// "tickValue":"0.00000001", // linear contracts only
|
222
|
+
// "maxOrderQty":"175000",
|
223
|
+
// "maxPosVolume":"1750000",
|
224
|
+
// "mark":".ETHUSD_3M_250920",
|
225
|
+
// "underlying":".ETHUSD_TWAP",
|
226
|
+
// "openInterest":".ETHUSD_3M_250920_OpenInterest",
|
227
|
+
// "floatingPL":"BidAsk", // perpetual contracts only
|
228
|
+
// "addUvmToFreeMargin":"ProfitAndLoss",
|
229
|
+
// "margin":{
|
230
|
+
// "netting":"PositionsAndOrders",
|
231
|
+
// "rates":[
|
232
|
+
// {"maxVolume":"175000","initialRate":"0.05","maintenanceRate":"0.0125"},
|
233
|
+
// {"maxVolume":"350000","initialRate":"0.1","maintenanceRate":"0.025"},
|
234
|
+
// {"maxVolume":"500000","initialRate":"0.2","maintenanceRate":"0.05"},
|
235
|
+
// {"maxVolume":"750000","initialRate":"0.3","maintenanceRate":"0.075"},
|
236
|
+
// {"maxVolume":"1050000","initialRate":"0.4","maintenanceRate":"0.1"},
|
237
|
+
// {"maxVolume":"1400000","initialRate":"0.5","maintenanceRate":"0.125"},
|
238
|
+
// {"maxVolume":"1750000","initialRate":"1","maintenanceRate":"0.25"}
|
239
|
+
// ],
|
240
|
+
// "rateMultipliers":{
|
241
|
+
// "LimitBuy":"1",
|
242
|
+
// "LimitSell":"1",
|
243
|
+
// "Long":"1",
|
244
|
+
// "MarketBuy":"1",
|
245
|
+
// "MarketSell":"1",
|
246
|
+
// "Short":"1",
|
247
|
+
// "StopBuy":"0",
|
248
|
+
// "StopSell":"0"
|
249
|
+
// }
|
250
|
+
// },
|
251
|
+
// "clearing":{"enabled":true,"index":".ETHUSD_3M_250920"},
|
252
|
+
// "premium":{"enabled":true,"index":".XBTUSD_Premium_IR_Corrected"}, // perpetual contracts only
|
253
|
+
// "riskAdjustment":{"enabled":true,"index":".RiskAdjustment_IR"},
|
254
|
+
// "expiration":{"enabled":true,"index":".ETHUSD_TWAP"}, // futures only
|
255
|
+
// "pricePrecision":3,
|
256
|
+
// "priceRange":{
|
257
|
+
// "enabled":true,
|
258
|
+
// "distance":"0.03",
|
259
|
+
// "movingBoundary":"0",
|
260
|
+
// "lowIndex":".ETHUSD_3M_250920_LOWRANGE",
|
261
|
+
// "highIndex":".ETHUSD_3M_250920_HIGHRANGE"
|
262
|
+
// },
|
263
|
+
// "priceLimits":{
|
264
|
+
// "enabled":true,
|
265
|
+
// "distance":"0.5",
|
266
|
+
// "movingBoundary":"0",
|
267
|
+
// "lowIndex":".ETHUSD_3M_250920_LOWLIMIT",
|
268
|
+
// "highIndex":".ETHUSD_3M_250920_HIGHLIMIT"
|
269
|
+
// },
|
270
|
+
// "inverse":true, // inverse contracts only
|
271
|
+
// "serie":"ETHUSD", // futures only
|
272
|
+
// "tradingStartDate":"2020-03-27 07:00:00",
|
273
|
+
// "expiryDate":"2020-09-25 08:00:00" // futures only
|
274
|
+
// },
|
275
|
+
// {
|
276
|
+
// "type":"Index",
|
277
|
+
// "symbol":".ETHUSD_Premium_IR_Corrected",
|
278
|
+
// "tickSize":6,
|
279
|
+
// "enabled":true,
|
280
|
+
// "basis":365
|
281
|
+
// },
|
282
|
+
// ]
|
283
|
+
//
|
284
|
+
const result = [];
|
285
|
+
for (let i = 0; i < response.length; i++) {
|
286
|
+
const market = response[i];
|
287
|
+
let type = this.safeStringLower (market, 'type');
|
288
|
+
const id = this.safeString (market, 'symbol');
|
289
|
+
const numericId = this.safeString (market, 'id');
|
290
|
+
const marginType = this.safeString (market, 'marginType');
|
291
|
+
const baseId = this.safeString (market, 'baseCurrency');
|
292
|
+
const quoteId = this.safeString (market, 'quoteCurrency');
|
293
|
+
const settleId = this.safeString (market, 'settlCurrency');
|
294
|
+
const base = this.safeCurrencyCode (baseId);
|
295
|
+
const quote = this.safeCurrencyCode (quoteId);
|
296
|
+
const settle = this.safeCurrencyCode (settleId);
|
297
|
+
const expiryDate = this.safeString (market, 'expiryDate');
|
298
|
+
const expiryTimestamp = this.parse8601 (expiryDate);
|
299
|
+
let symbol = id;
|
300
|
+
let future = false;
|
301
|
+
let swap = false;
|
302
|
+
if (type === 'margin') {
|
303
|
+
symbol = base + '/' + quote + ':' + settle;
|
304
|
+
if (marginType === 'XenaFuture') {
|
305
|
+
symbol = symbol + '-' + this.yymmdd (expiryTimestamp);
|
306
|
+
type = 'future';
|
307
|
+
future = true;
|
308
|
+
} else if (marginType === 'XenaListedPerpetual') {
|
309
|
+
type = 'swap';
|
310
|
+
swap = true;
|
311
|
+
}
|
312
|
+
}
|
313
|
+
const inverse = this.safeValue (market, 'inverse', false);
|
314
|
+
const contract = swap || future;
|
315
|
+
result.push ({
|
316
|
+
'id': id,
|
317
|
+
'symbol': symbol,
|
318
|
+
'base': base,
|
319
|
+
'quote': quote,
|
320
|
+
'settle': settle,
|
321
|
+
'baseId': baseId,
|
322
|
+
'quoteId': quoteId,
|
323
|
+
'settleId': settleId,
|
324
|
+
'numericId': numericId,
|
325
|
+
'type': type,
|
326
|
+
'spot': false,
|
327
|
+
'margin': false,
|
328
|
+
'swap': swap,
|
329
|
+
'future': future,
|
330
|
+
'option': false,
|
331
|
+
'active': this.safeValue (market, 'enabled', false),
|
332
|
+
'contract': contract,
|
333
|
+
'linear': contract ? !inverse : undefined,
|
334
|
+
'inverse': contract ? inverse : undefined,
|
335
|
+
'contractSize': this.safeNumber (market, 'contractValue'),
|
336
|
+
'expiry': expiryTimestamp,
|
337
|
+
'expiryDatetime': this.iso8601 (expiryTimestamp),
|
338
|
+
'strike': undefined,
|
339
|
+
'optionType': undefined,
|
340
|
+
'precision': {
|
341
|
+
'amount': parseInt ('0'),
|
342
|
+
'price': this.safeInteger2 (market, 'tickSize', 'pricePrecision'),
|
343
|
+
},
|
344
|
+
'limits': {
|
345
|
+
'leverage': {
|
346
|
+
'min': undefined,
|
347
|
+
'max': undefined,
|
348
|
+
},
|
349
|
+
'amount': {
|
350
|
+
'min': undefined,
|
351
|
+
'max': undefined,
|
352
|
+
},
|
353
|
+
'price': {
|
354
|
+
'min': undefined,
|
355
|
+
'max': undefined,
|
356
|
+
},
|
357
|
+
'cost': {
|
358
|
+
'min': this.safeNumber (market, 'minOrderQuantity'),
|
359
|
+
'max': this.safeNumber (market, 'maxOrderQty'),
|
360
|
+
},
|
361
|
+
},
|
362
|
+
'info': market,
|
363
|
+
});
|
364
|
+
}
|
365
|
+
return result;
|
366
|
+
}
|
367
|
+
|
368
|
+
async fetchCurrencies (params = {}) {
|
369
|
+
const response = await this.publicGetCommonCurrencies (params);
|
370
|
+
//
|
371
|
+
// {
|
372
|
+
// "BAB": {
|
373
|
+
// "name":"BAB",
|
374
|
+
// "title":"Bitcoin ABC",
|
375
|
+
// "blockchain":{
|
376
|
+
// "name":"BAB",
|
377
|
+
// "title":"Bitcoin ABC",
|
378
|
+
// "deposit":{"confirmations":6},
|
379
|
+
// "withdraw":{"confirmations":1},
|
380
|
+
// "addressReuseAllowed":false,
|
381
|
+
// "view":{
|
382
|
+
// "uriTemplate":"bitcoinabc:%s?message=Xena Exchange",
|
383
|
+
// "recommendedFee":"0.00001",
|
384
|
+
// "transactionUrl":"https://blockchair.com/bitcoin-cash/transaction/${txId}",
|
385
|
+
// "walletUrl":"https://blockchair.com/bitcoin-cash/address/${walletId}"
|
386
|
+
// }
|
387
|
+
// },
|
388
|
+
// "precision":5,
|
389
|
+
// "withdraw":{"minAmount":"0.01","commission":"0.001"},
|
390
|
+
// "view":{
|
391
|
+
// "color":"#DC7C08",
|
392
|
+
// "site":"https://www.bitcoinabc.org"
|
393
|
+
// },
|
394
|
+
// "enabled":true
|
395
|
+
// },
|
396
|
+
// }
|
397
|
+
const ids = Object.keys (response);
|
398
|
+
const result = {};
|
399
|
+
for (let i = 0; i < ids.length; i++) {
|
400
|
+
const id = ids[i];
|
401
|
+
const currency = response[id];
|
402
|
+
const code = this.safeCurrencyCode (id);
|
403
|
+
const name = this.safeString (currency, 'title');
|
404
|
+
const precision = this.safeInteger (currency, 'precision');
|
405
|
+
const enabled = this.safeValue (currency, 'enabled');
|
406
|
+
const active = (enabled === true);
|
407
|
+
const withdraw = this.safeValue (currency, 'withdraw', {});
|
408
|
+
result[code] = {
|
409
|
+
'id': id,
|
410
|
+
'code': code,
|
411
|
+
'info': currency,
|
412
|
+
'name': name,
|
413
|
+
'active': active,
|
414
|
+
'deposit': undefined,
|
415
|
+
'withdraw': undefined,
|
416
|
+
'fee': this.safeNumber (withdraw, 'commission'),
|
417
|
+
'precision': precision,
|
418
|
+
'limits': {
|
419
|
+
'amount': {
|
420
|
+
'min': undefined,
|
421
|
+
'max': undefined,
|
422
|
+
},
|
423
|
+
'withdraw': {
|
424
|
+
'min': this.safeNumber (withdraw, 'minAmount'),
|
425
|
+
'max': undefined,
|
426
|
+
},
|
427
|
+
},
|
428
|
+
};
|
429
|
+
}
|
430
|
+
return result;
|
431
|
+
}
|
432
|
+
|
433
|
+
parseTicker (ticker, market = undefined) {
|
434
|
+
//
|
435
|
+
// fetchTicker, fetchTickers
|
436
|
+
//
|
437
|
+
// {
|
438
|
+
// "symbol":".XBTUSD_3M_250920_MID",
|
439
|
+
// "firstPx":"9337.49",
|
440
|
+
// "lastPx":"9355.81",
|
441
|
+
// "highPx":"9579.42",
|
442
|
+
// "lowPx":"9157.63",
|
443
|
+
// "buyVolume":"0",
|
444
|
+
// "sellVolume":"0",
|
445
|
+
// "bid":"0",
|
446
|
+
// "ask":"0"
|
447
|
+
// }
|
448
|
+
//
|
449
|
+
const timestamp = this.milliseconds ();
|
450
|
+
const marketId = this.safeString (ticker, 'symbol');
|
451
|
+
const symbol = this.safeSymbol (marketId, market);
|
452
|
+
const last = this.safeString (ticker, 'lastPx');
|
453
|
+
const open = this.safeString (ticker, 'firstPx');
|
454
|
+
const buyVolume = this.safeString (ticker, 'buyVolume');
|
455
|
+
const sellVolume = this.safeString (ticker, 'sellVolume');
|
456
|
+
const baseVolume = this.sum (buyVolume, sellVolume);
|
457
|
+
return this.safeTicker ({
|
458
|
+
'symbol': symbol,
|
459
|
+
'timestamp': timestamp,
|
460
|
+
'datetime': this.iso8601 (timestamp),
|
461
|
+
'high': this.safeString (ticker, 'highPx'),
|
462
|
+
'low': this.safeString (ticker, 'lowPx'),
|
463
|
+
'bid': this.safeString (ticker, 'bid'),
|
464
|
+
'bidVolume': undefined,
|
465
|
+
'ask': this.safeString (ticker, 'ask'),
|
466
|
+
'askVolume': undefined,
|
467
|
+
'vwap': undefined,
|
468
|
+
'open': open,
|
469
|
+
'close': last,
|
470
|
+
'last': last,
|
471
|
+
'previousClose': undefined,
|
472
|
+
'change': undefined,
|
473
|
+
'percentage': undefined,
|
474
|
+
'average': undefined,
|
475
|
+
'baseVolume': baseVolume,
|
476
|
+
'quoteVolume': undefined,
|
477
|
+
'info': ticker,
|
478
|
+
}, market, false);
|
479
|
+
}
|
480
|
+
|
481
|
+
async fetchTicker (symbol, params = {}) {
|
482
|
+
await this.loadMarkets ();
|
483
|
+
const tickers = await this.fetchTickers (undefined, params);
|
484
|
+
if (symbol in tickers) {
|
485
|
+
return tickers[symbol];
|
486
|
+
}
|
487
|
+
throw new BadSymbol (this.id + ' fetchTicker() could not find a ticker with symbol ' + symbol);
|
488
|
+
}
|
489
|
+
|
490
|
+
async fetchTickers (symbols = undefined, params = {}) {
|
491
|
+
await this.loadMarkets ();
|
492
|
+
const tickers = await this.publicGetMarketDataMarketWatch (params);
|
493
|
+
//
|
494
|
+
// [
|
495
|
+
// {
|
496
|
+
// "symbol":".XBTUSD_3M_250920_MID",
|
497
|
+
// "firstPx":"9337.49",
|
498
|
+
// "lastPx":"9355.81",
|
499
|
+
// "highPx":"9579.42",
|
500
|
+
// "lowPx":"9157.63",
|
501
|
+
// "buyVolume":"0",
|
502
|
+
// "sellVolume":"0",
|
503
|
+
// "bid":"0",
|
504
|
+
// "ask":"0"
|
505
|
+
// }
|
506
|
+
// ]
|
507
|
+
//
|
508
|
+
const result = {};
|
509
|
+
for (let i = 0; i < tickers.length; i++) {
|
510
|
+
const ticker = this.parseTicker (tickers[i]);
|
511
|
+
const symbol = ticker['symbol'];
|
512
|
+
result[symbol] = ticker;
|
513
|
+
}
|
514
|
+
return this.filterByArray (result, 'symbol', symbols);
|
515
|
+
}
|
516
|
+
|
517
|
+
async fetchOrderBook (symbol, limit = undefined, params = {}) {
|
518
|
+
await this.loadMarkets ();
|
519
|
+
const request = {
|
520
|
+
'symbol': this.marketId (symbol),
|
521
|
+
};
|
522
|
+
if (limit !== undefined) {
|
523
|
+
request['depth'] = limit;
|
524
|
+
}
|
525
|
+
const response = await this.publicGetMarketDataV2DomSymbol (this.extend (request, params));
|
526
|
+
//
|
527
|
+
// {
|
528
|
+
// "msgType":"W",
|
529
|
+
// "mdStreamId":"DOM:XBTUSD:aggregated",
|
530
|
+
// "lastUpdateTime":1594772683037691997,
|
531
|
+
// "mdBookType":"2",
|
532
|
+
// "symbol":"XBTUSD",
|
533
|
+
// "lowRangePx":"9132.24",
|
534
|
+
// "highRangePx":"9410.36",
|
535
|
+
// "lowLimitPx":"9132.24",
|
536
|
+
// "highLimitPx":"9410.36",
|
537
|
+
// "clearingPx":"9253.4",
|
538
|
+
// "bestBid":"9269.8",
|
539
|
+
// "bestAsk":"9275.9",
|
540
|
+
// "mdEntry":[
|
541
|
+
// {"mdEntryType":"1","mdEntryPx":"9275.9","mdEntrySize":"3000","numberOfOrders":1},
|
542
|
+
// {"mdEntryType":"1","mdEntryPx":"9277.7","mdEntrySize":"50000","numberOfOrders":1},
|
543
|
+
// {"mdEntryType":"1","mdEntryPx":"9277.8","mdEntrySize":"2000","numberOfOrders":1},
|
544
|
+
// {"mdEntryType":"0","mdEntryPx":"9269.8","mdEntrySize":"2000","numberOfOrders":1},
|
545
|
+
// {"mdEntryType":"0","mdEntryPx":"9267.9","mdEntrySize":"3000","numberOfOrders":1},
|
546
|
+
// {"mdEntryType":"0","mdEntryPx":"9267.8","mdEntrySize":"50000","numberOfOrders":1},
|
547
|
+
// ]
|
548
|
+
// }
|
549
|
+
//
|
550
|
+
const mdEntry = this.safeValue (response, 'mdEntry', []);
|
551
|
+
const mdEntriesByType = this.groupBy (mdEntry, 'mdEntryType');
|
552
|
+
const lastUpdateTime = this.safeInteger (response, 'lastUpdateTime');
|
553
|
+
let timestamp = undefined;
|
554
|
+
if (lastUpdateTime !== undefined) {
|
555
|
+
timestamp = parseInt (lastUpdateTime / 1000000);
|
556
|
+
}
|
557
|
+
return this.parseOrderBook (mdEntriesByType, symbol, timestamp, '0', '1', 'mdEntryPx', 'mdEntrySize');
|
558
|
+
}
|
559
|
+
|
560
|
+
async fetchAccounts (params = {}) {
|
561
|
+
const response = await this.privateGetTradingAccounts (params);
|
562
|
+
//
|
563
|
+
// {
|
564
|
+
// "accounts": [
|
565
|
+
// { "id":8273231, "kind": "Spot" },
|
566
|
+
// { "id":10012833469, "kind": "Margin", "currency": "BTC" }
|
567
|
+
// ]
|
568
|
+
// }
|
569
|
+
//
|
570
|
+
const accounts = this.safeValue (response, 'accounts');
|
571
|
+
const result = [];
|
572
|
+
for (let i = 0; i < accounts.length; i++) {
|
573
|
+
const account = accounts[i];
|
574
|
+
const accountId = this.safeString (account, 'id');
|
575
|
+
const currencyId = this.safeString (account, 'currency');
|
576
|
+
const code = this.safeCurrencyCode (currencyId);
|
577
|
+
const type = this.safeStringLower (account, 'kind');
|
578
|
+
result.push ({
|
579
|
+
'id': accountId,
|
580
|
+
'type': type,
|
581
|
+
'currency': code,
|
582
|
+
'info': account,
|
583
|
+
});
|
584
|
+
}
|
585
|
+
return result;
|
586
|
+
}
|
587
|
+
|
588
|
+
async findAccountByType (type) {
|
589
|
+
await this.loadMarkets ();
|
590
|
+
await this.loadAccounts ();
|
591
|
+
const accountsByType = this.groupBy (this.accounts, 'type');
|
592
|
+
const accounts = this.safeValue (accountsByType, type);
|
593
|
+
if (accounts === undefined) {
|
594
|
+
throw new ExchangeError (this.id + " findAccountByType() could not find an accountId with type '" + type + "', specify the 'accountId' parameter instead"); // eslint-disable-line quotes
|
595
|
+
}
|
596
|
+
const numAccounts = accounts.length;
|
597
|
+
if (numAccounts > 1) {
|
598
|
+
throw new ExchangeError (this.id + " findAccountByType() found more than one accountId with type '" + type + "', specify the 'accountId' parameter instead"); // eslint-disable-line quotes
|
599
|
+
}
|
600
|
+
return accounts[0];
|
601
|
+
}
|
602
|
+
|
603
|
+
async getAccountId (params) {
|
604
|
+
await this.loadMarkets ();
|
605
|
+
await this.loadAccounts ();
|
606
|
+
const defaultAccountId = this.safeString (this.options, 'accountId');
|
607
|
+
const accountId = this.safeString (params, 'accountId', defaultAccountId);
|
608
|
+
if (accountId !== undefined) {
|
609
|
+
return accountId;
|
610
|
+
}
|
611
|
+
const defaultType = this.safeString (this.options, 'defaultType', 'margin');
|
612
|
+
const type = this.safeString (params, 'type', defaultType);
|
613
|
+
params = this.omit (params, 'type');
|
614
|
+
if (type === undefined) {
|
615
|
+
throw new ArgumentsRequired (this.id + " requires an 'accountId' parameter or a 'type' parameter ('spot' or 'margin')");
|
616
|
+
}
|
617
|
+
const account = await this.findAccountByType (type);
|
618
|
+
return account['id'];
|
619
|
+
}
|
620
|
+
|
621
|
+
parseBalance (response) {
|
622
|
+
const result = { 'info': response };
|
623
|
+
let timestamp = undefined;
|
624
|
+
const balances = this.safeValue (response, 'balances', []);
|
625
|
+
for (let i = 0; i < balances.length; i++) {
|
626
|
+
const balance = balances[i];
|
627
|
+
const lastUpdateTime = this.safeString (balance, 'lastUpdateTime');
|
628
|
+
const lastUpdated = lastUpdateTime.slice (0, 13);
|
629
|
+
const currentTimestamp = parseInt (lastUpdated);
|
630
|
+
timestamp = (timestamp === undefined) ? currentTimestamp : Math.max (timestamp, currentTimestamp);
|
631
|
+
const currencyId = this.safeString (balance, 'currency');
|
632
|
+
const code = this.safeCurrencyCode (currencyId);
|
633
|
+
const account = this.account ();
|
634
|
+
account['free'] = this.safeString (balance, 'available');
|
635
|
+
account['used'] = this.safeString (balance, 'onHold');
|
636
|
+
result[code] = account;
|
637
|
+
}
|
638
|
+
result['timestamp'] = timestamp;
|
639
|
+
result['datetime'] = this.iso8601 (timestamp);
|
640
|
+
return this.safeBalance (result);
|
641
|
+
}
|
642
|
+
|
643
|
+
async fetchBalance (params = {}) {
|
644
|
+
await this.loadMarkets ();
|
645
|
+
await this.loadAccounts ();
|
646
|
+
const accountId = await this.getAccountId (params);
|
647
|
+
const request = {
|
648
|
+
'accountId': accountId,
|
649
|
+
};
|
650
|
+
const response = await this.privateGetTradingAccountsAccountIdBalance (this.extend (request, params));
|
651
|
+
//
|
652
|
+
// {
|
653
|
+
// "msgType":"XAR",
|
654
|
+
// "balances":[
|
655
|
+
// {
|
656
|
+
// "currency":"BTC",
|
657
|
+
// "lastUpdateTime":1619384111905916598,
|
658
|
+
// "available":"0.00549964",
|
659
|
+
// "onHold":"0",
|
660
|
+
// "settled":"0.00549964",
|
661
|
+
// "equity":"0.00549964"
|
662
|
+
// }
|
663
|
+
// ]
|
664
|
+
// }
|
665
|
+
//
|
666
|
+
return this.parseBalance (response);
|
667
|
+
}
|
668
|
+
|
669
|
+
parseTrade (trade, market = undefined) {
|
670
|
+
//
|
671
|
+
// fetchTrades (public)
|
672
|
+
//
|
673
|
+
// {
|
674
|
+
// "mdUpdateAction":"0",
|
675
|
+
// "mdEntryType":"2",
|
676
|
+
// "mdEntryPx":"9225.16",
|
677
|
+
// "mdEntrySize":"10000",
|
678
|
+
// "transactTime":1594728504524977655,
|
679
|
+
// "tradeId":"6ac51bb7-7505-4f35-85ef-61eb738cb4d9",
|
680
|
+
// "aggressorSide":"1"
|
681
|
+
// }
|
682
|
+
//
|
683
|
+
// fetchMyTrades (private)
|
684
|
+
//
|
685
|
+
// {
|
686
|
+
// "msgType":"8",
|
687
|
+
// "account":1012838158,
|
688
|
+
// "clOrdId":"xXWKLQVl3",
|
689
|
+
// "orderId":"89eee8bd-98ae-4d06-97dc-ee2d12997fe7",
|
690
|
+
// "symbol":"ETHUSD",
|
691
|
+
// "transactTime":1595143349089739000,
|
692
|
+
// "execId":"c4bd0ee2330930924e0f6fdde4630e56751692a4",
|
693
|
+
// "tradeId":"30a394b2-6d53-4bc4-b276-d8e19f470ba1",
|
694
|
+
// "side":"2",
|
695
|
+
// "lastQty":"1",
|
696
|
+
// "lastPx":"234.58",
|
697
|
+
// "avgPx":"234.58",
|
698
|
+
// "calculatedCcyLastQty":"0",
|
699
|
+
// "netMoney":"0",
|
700
|
+
// "lastLiquidityInd":"2",
|
701
|
+
// "commission":"0.00000011",
|
702
|
+
// "commRate":"0.00045",
|
703
|
+
// "commCurrency":"BTC",
|
704
|
+
// "positionId":132162662,
|
705
|
+
// "positionEffect":"C"
|
706
|
+
// }
|
707
|
+
//
|
708
|
+
const id = this.safeString (trade, 'tradeId');
|
709
|
+
let timestamp = this.safeInteger (trade, 'transactTime');
|
710
|
+
if (timestamp !== undefined) {
|
711
|
+
timestamp = parseInt (timestamp / 1000000);
|
712
|
+
}
|
713
|
+
let side = this.safeStringLower2 (trade, 'side', 'aggressorSide');
|
714
|
+
if (side === '1') {
|
715
|
+
side = 'buy';
|
716
|
+
} else if (side === '2') {
|
717
|
+
side = 'sell';
|
718
|
+
}
|
719
|
+
const orderId = this.safeString (trade, 'orderId');
|
720
|
+
const marketId = this.safeString (trade, 'symbol');
|
721
|
+
const symbol = this.safeSymbol (marketId, market);
|
722
|
+
const priceString = this.safeString2 (trade, 'lastPx', 'mdEntryPx');
|
723
|
+
const amountString = this.safeString2 (trade, 'lastQty', 'mdEntrySize');
|
724
|
+
let fee = undefined;
|
725
|
+
const feeCostString = this.safeString (trade, 'commission');
|
726
|
+
if (feeCostString !== undefined) {
|
727
|
+
const feeCurrencyId = this.safeString (trade, 'commCurrency');
|
728
|
+
const feeCurrencyCode = this.safeCurrencyCode (feeCurrencyId);
|
729
|
+
const feeRateString = this.safeString (trade, 'commRate');
|
730
|
+
fee = {
|
731
|
+
'cost': feeCostString,
|
732
|
+
'rate': feeRateString,
|
733
|
+
'currency': feeCurrencyCode,
|
734
|
+
};
|
735
|
+
}
|
736
|
+
return this.safeTrade ({
|
737
|
+
'id': id,
|
738
|
+
'info': trade,
|
739
|
+
'timestamp': timestamp,
|
740
|
+
'datetime': this.iso8601 (timestamp),
|
741
|
+
'symbol': symbol,
|
742
|
+
'type': undefined,
|
743
|
+
'order': orderId,
|
744
|
+
'side': side,
|
745
|
+
'takerOrMaker': undefined,
|
746
|
+
'price': priceString,
|
747
|
+
'amount': amountString,
|
748
|
+
'cost': undefined,
|
749
|
+
'fee': fee,
|
750
|
+
}, market);
|
751
|
+
}
|
752
|
+
|
753
|
+
async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
754
|
+
await this.loadMarkets ();
|
755
|
+
await this.loadAccounts ();
|
756
|
+
const accountId = await this.getAccountId (params);
|
757
|
+
const request = {
|
758
|
+
'accountId': accountId,
|
759
|
+
// 'page': 1,
|
760
|
+
// 'limit': integer,
|
761
|
+
// 'from': time,
|
762
|
+
// 'to': time,
|
763
|
+
// 'symbol': currency['id'],
|
764
|
+
// 'trade_id': id,
|
765
|
+
// 'client_order_id': id,
|
766
|
+
};
|
767
|
+
let market = undefined;
|
768
|
+
if (symbol !== undefined) {
|
769
|
+
market = this.market (symbol);
|
770
|
+
request['symbol'] = market['id'];
|
771
|
+
}
|
772
|
+
if (since !== undefined) {
|
773
|
+
request['from'] = since * 1000000;
|
774
|
+
}
|
775
|
+
if (limit !== undefined) {
|
776
|
+
request['limit'] = limit;
|
777
|
+
}
|
778
|
+
const response = await this.privateGetTradingAccountsAccountIdTradeHistory (this.extend (request, params));
|
779
|
+
//
|
780
|
+
// [
|
781
|
+
// {
|
782
|
+
// "msgType":"8",
|
783
|
+
// "account":1012838158,
|
784
|
+
// "clOrdId":"xXWKLQVl3",
|
785
|
+
// "orderId":"89eee8bd-98ae-4d06-97dc-ee2d12997fe7",
|
786
|
+
// "symbol":"ETHUSD",
|
787
|
+
// "transactTime":1595143349089739000,
|
788
|
+
// "execId":"c4bd0ee2330930924e0f6fdde4630e56751692a4",
|
789
|
+
// "tradeId":"30a394b2-6d53-4bc4-b276-d8e19f470ba1",
|
790
|
+
// "side":"2",
|
791
|
+
// "lastQty":"1",
|
792
|
+
// "lastPx":"234.58",
|
793
|
+
// "avgPx":"234.58",
|
794
|
+
// "calculatedCcyLastQty":"0",
|
795
|
+
// "netMoney":"0",
|
796
|
+
// "lastLiquidityInd":"2",
|
797
|
+
// "commission":"0.00000011",
|
798
|
+
// "commRate":"0.00045",
|
799
|
+
// "commCurrency":"BTC",
|
800
|
+
// "positionId":132162662,
|
801
|
+
// "positionEffect":"C"
|
802
|
+
// },
|
803
|
+
// {
|
804
|
+
// "msgType":"8",
|
805
|
+
// "account":1012838158,
|
806
|
+
// "clOrdId":"3ce8c305-9936-4e97-9206-71ae3ff40305",
|
807
|
+
// "orderId":"a93c686d-990e-44d9-9cbe-61107744b990",
|
808
|
+
// "symbol":"ETHUSD",
|
809
|
+
// "transactTime":1595143315369226000,
|
810
|
+
// "execId":"1c745881722ad966a4ce71600cd058d59da0d1c3",
|
811
|
+
// "tradeId":"77f75bd8-27c4-4b1a-a5e8-0d59239ce216",
|
812
|
+
// "side":"1",
|
813
|
+
// "lastQty":"1",
|
814
|
+
// "lastPx":"234.72",
|
815
|
+
// "avgPx":"234.72",
|
816
|
+
// "calculatedCcyLastQty":"0",
|
817
|
+
// "netMoney":"0",
|
818
|
+
// "lastLiquidityInd":"2",
|
819
|
+
// "commission":"0.00000011",
|
820
|
+
// "commRate":"0.00045",
|
821
|
+
// "commCurrency":"BTC",
|
822
|
+
// "positionId":132162662,
|
823
|
+
// "positionEffect":"O"
|
824
|
+
// }
|
825
|
+
// ]
|
826
|
+
//
|
827
|
+
return this.parseTrades (response, market, since, limit);
|
828
|
+
}
|
829
|
+
|
830
|
+
parseOHLCV (ohlcv, market = undefined) {
|
831
|
+
//
|
832
|
+
// {
|
833
|
+
// "transactTime":1594784700000000000,
|
834
|
+
// "firstPx":"9246.3",
|
835
|
+
// "lastPx":"9232.8",
|
836
|
+
// "highPx":"9246.3",
|
837
|
+
// "lowPx":"9232.8",
|
838
|
+
// "buyVolume":"0",
|
839
|
+
// "sellVolume":"0"
|
840
|
+
// }
|
841
|
+
//
|
842
|
+
const transactTime = this.safeInteger (ohlcv, 'transactTime');
|
843
|
+
const timestamp = parseInt (transactTime / 1000000);
|
844
|
+
const buyVolume = this.safeNumber (ohlcv, 'buyVolume');
|
845
|
+
const sellVolume = this.safeNumber (ohlcv, 'sellVolume');
|
846
|
+
const volume = this.sum (buyVolume, sellVolume);
|
847
|
+
return [
|
848
|
+
timestamp,
|
849
|
+
this.safeNumber (ohlcv, 'firstPx'),
|
850
|
+
this.safeNumber (ohlcv, 'highPx'),
|
851
|
+
this.safeNumber (ohlcv, 'lowPx'),
|
852
|
+
this.safeNumber (ohlcv, 'lastPx'),
|
853
|
+
volume,
|
854
|
+
];
|
855
|
+
}
|
856
|
+
|
857
|
+
async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
|
858
|
+
await this.loadMarkets ();
|
859
|
+
const market = this.market (symbol);
|
860
|
+
const request = {
|
861
|
+
'symbol': market['id'],
|
862
|
+
'timeframe': this.timeframes[timeframe],
|
863
|
+
};
|
864
|
+
const durationInSeconds = this.parseTimeframe (timeframe);
|
865
|
+
const duration = durationInSeconds * 1000;
|
866
|
+
if (since !== undefined) {
|
867
|
+
request['from'] = since * 1000000;
|
868
|
+
if (limit !== undefined) {
|
869
|
+
request['to'] = this.sum (since, limit * duration) * 1000000;
|
870
|
+
}
|
871
|
+
} else {
|
872
|
+
const now = this.milliseconds ();
|
873
|
+
// max limit is 1000
|
874
|
+
if (limit !== undefined) {
|
875
|
+
request['from'] = (now - limit * duration) * 1000000;
|
876
|
+
}
|
877
|
+
}
|
878
|
+
const response = await this.publicGetMarketDataV2CandlesSymbolTimeframe (this.extend (request, params));
|
879
|
+
//
|
880
|
+
// {
|
881
|
+
// "mdEntry":[
|
882
|
+
// {"transactTime":1594784700000000000,"firstPx":"9246.3","lastPx":"9232.8","highPx":"9246.3","lowPx":"9232.8","buyVolume":"0","sellVolume":"0"},
|
883
|
+
// {"transactTime":1594785600000000000,"firstPx":"9231.8","lastPx":"9227.3","highPx":"9232.8","lowPx":"9227.3","buyVolume":"0","sellVolume":"0"},
|
884
|
+
// {"transactTime":1594786500000000000,"firstPx":"9226.3","lastPx":"9230.3","highPx":"9230.3","lowPx":"9220.6","buyVolume":"0","sellVolume":"0"}
|
885
|
+
// ]
|
886
|
+
// }
|
887
|
+
//
|
888
|
+
const mdEntry = this.safeValue (response, 'mdEntry', []);
|
889
|
+
return this.parseOHLCVs (mdEntry, market, timeframe, since, limit);
|
890
|
+
}
|
891
|
+
|
892
|
+
async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
|
893
|
+
await this.loadMarkets ();
|
894
|
+
const market = this.market (symbol);
|
895
|
+
const request = {
|
896
|
+
'symbol': market['id'],
|
897
|
+
// 'from': this.iso8601 (since),
|
898
|
+
// 'to': this.iso8601 (this.milliseconds ()),
|
899
|
+
// 'page': 1,
|
900
|
+
// 'limit': limit,
|
901
|
+
};
|
902
|
+
if (since !== undefined) {
|
903
|
+
request['from'] = this.iso8601 (since);
|
904
|
+
}
|
905
|
+
if (limit !== undefined) {
|
906
|
+
request['limit'] = limit;
|
907
|
+
}
|
908
|
+
const response = await this.publicGetMarketDataV2TradesSymbol (this.extend (request, params));
|
909
|
+
//
|
910
|
+
// {
|
911
|
+
// "msgType":"W",
|
912
|
+
// "lastUpdateTime":1594737830902223803,
|
913
|
+
// "symbol":"XBTUSD",
|
914
|
+
// "mdEntry":[
|
915
|
+
// {
|
916
|
+
// "mdUpdateAction":"0",
|
917
|
+
// "mdEntryType":"2",
|
918
|
+
// "mdEntryPx":"9225.16",
|
919
|
+
// "mdEntrySize":"10000",
|
920
|
+
// "transactTime":1594728504524977655,
|
921
|
+
// "tradeId":"6ac51bb7-7505-4f35-85ef-61eb738cb4d9",
|
922
|
+
// "aggressorSide":"1"
|
923
|
+
// },
|
924
|
+
// ]
|
925
|
+
// }
|
926
|
+
//
|
927
|
+
const mdEntry = this.safeValue (response, 'mdEntry', []);
|
928
|
+
return this.parseTrades (mdEntry, market, since, limit);
|
929
|
+
}
|
930
|
+
|
931
|
+
parseOrderStatus (status) {
|
932
|
+
const statuses = {
|
933
|
+
'A': 'open', // PendingNew
|
934
|
+
'0': 'open', // New
|
935
|
+
'1': 'open', // PartiallyFilled
|
936
|
+
'2': 'closed', // Filled
|
937
|
+
'6': 'canceled', // PendingCancel
|
938
|
+
'4': 'canceled', // Cancelled
|
939
|
+
'E': 'open', // PendingReplace
|
940
|
+
'8': 'rejected', // Rejected
|
941
|
+
};
|
942
|
+
return this.safeString (statuses, status, status);
|
943
|
+
}
|
944
|
+
|
945
|
+
parseOrder (order, market = undefined) {
|
946
|
+
//
|
947
|
+
// createOrder
|
948
|
+
//
|
949
|
+
// {
|
950
|
+
// "msgType":"8",
|
951
|
+
// "account":1012838720,
|
952
|
+
// "clOrdId":"XAq0pRQ1g",
|
953
|
+
// "orderId":"64d7a06a-27e5-422e-99d9-3cadc04f5a35",
|
954
|
+
// "symbol":"XBTUSD",
|
955
|
+
// "ordType":"2",
|
956
|
+
// "price":"9000",
|
957
|
+
// "transactTime":1593778763271127920,
|
958
|
+
// "execId":"ff5fb8153652f0516bf07b6979255bed053c84b9",
|
959
|
+
// "execType":"I",
|
960
|
+
// "ordStatus":"0",
|
961
|
+
// "side":"1",
|
962
|
+
// "orderQty":"1",
|
963
|
+
// "leavesQty":"1",
|
964
|
+
// "cumQty":"0",
|
965
|
+
// "positionEffect":"O",
|
966
|
+
// "marginAmt":"0.00000556",
|
967
|
+
// "marginAmtType":"11"
|
968
|
+
// }
|
969
|
+
//
|
970
|
+
const id = this.safeString (order, 'orderId');
|
971
|
+
const clientOrderId = this.safeString (order, 'clOrdId');
|
972
|
+
const transactTime = this.safeInteger (order, 'transactTime');
|
973
|
+
const timestamp = parseInt (transactTime / 1000000);
|
974
|
+
const status = this.parseOrderStatus (this.safeString (order, 'ordStatus'));
|
975
|
+
const marketId = this.safeString (order, 'symbol');
|
976
|
+
const symbol = this.safeSymbol (marketId, market);
|
977
|
+
const price = this.safeString (order, 'price');
|
978
|
+
const amount = this.safeString (order, 'orderQty');
|
979
|
+
const filled = this.safeString (order, 'cumQty');
|
980
|
+
const remaining = this.safeString (order, 'leavesQty');
|
981
|
+
let side = this.safeString (order, 'side');
|
982
|
+
if (side === '1') {
|
983
|
+
side = 'buy';
|
984
|
+
} else if (side === '2') {
|
985
|
+
side = 'sell';
|
986
|
+
}
|
987
|
+
let type = this.safeString (order, 'ordType');
|
988
|
+
if (type === '1') {
|
989
|
+
type = 'market';
|
990
|
+
} else if (type === '2') {
|
991
|
+
type = 'limit';
|
992
|
+
} else if (type === '3') {
|
993
|
+
type = 'stop';
|
994
|
+
} else if (type === '4') {
|
995
|
+
type = 'stop-limit';
|
996
|
+
}
|
997
|
+
return this.safeOrder ({
|
998
|
+
'id': id,
|
999
|
+
'clientOrderId': clientOrderId,
|
1000
|
+
'info': order,
|
1001
|
+
'timestamp': timestamp,
|
1002
|
+
'datetime': this.iso8601 (timestamp),
|
1003
|
+
'lastTradeTimestamp': undefined,
|
1004
|
+
'symbol': symbol,
|
1005
|
+
'type': type,
|
1006
|
+
'timeInForce': undefined,
|
1007
|
+
'postOnly': undefined,
|
1008
|
+
'side': side,
|
1009
|
+
'price': price,
|
1010
|
+
'stopPrice': undefined,
|
1011
|
+
'amount': amount,
|
1012
|
+
'cost': undefined,
|
1013
|
+
'average': undefined,
|
1014
|
+
'filled': filled,
|
1015
|
+
'remaining': remaining,
|
1016
|
+
'status': status,
|
1017
|
+
'fee': undefined,
|
1018
|
+
'trades': undefined,
|
1019
|
+
}, market);
|
1020
|
+
}
|
1021
|
+
|
1022
|
+
async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
|
1023
|
+
await this.loadMarkets ();
|
1024
|
+
await this.loadAccounts ();
|
1025
|
+
const accountId = await this.getAccountId (params);
|
1026
|
+
const orderTypes = {
|
1027
|
+
'market': '1',
|
1028
|
+
'limit': '2',
|
1029
|
+
'stop': '3',
|
1030
|
+
'stop-limit': '4',
|
1031
|
+
};
|
1032
|
+
const orderType = this.safeString (orderTypes, type);
|
1033
|
+
if (orderType === undefined) {
|
1034
|
+
throw new InvalidOrder (this.id + ' createOrder() does not support order type ' + type + ', supported order types are market, limit, stop, stop-limit');
|
1035
|
+
}
|
1036
|
+
const orderSides = {
|
1037
|
+
'buy': '1',
|
1038
|
+
'sell': '2',
|
1039
|
+
};
|
1040
|
+
const orderSide = this.safeString (orderSides, side);
|
1041
|
+
if (orderSide === undefined) {
|
1042
|
+
throw new InvalidOrder (this.id + ' createOrder() does not support order side ' + side + ', supported order sides are buy, sell');
|
1043
|
+
}
|
1044
|
+
const market = this.market (symbol);
|
1045
|
+
const request = {
|
1046
|
+
'account': parseInt (accountId),
|
1047
|
+
'symbol': market['id'],
|
1048
|
+
'ordType': orderType,
|
1049
|
+
'side': orderSide,
|
1050
|
+
'orderQty': this.amountToPrecision (symbol, amount),
|
1051
|
+
'transactTime': this.milliseconds () * 1000000,
|
1052
|
+
// 'clOrdId': this.uuid (), // required
|
1053
|
+
// 'price': this.priceToPrecision (symbol, price), // required for limit and stop-limit orders
|
1054
|
+
// 'stopPx': this.priceToPrecision (symbol, stopPx), // required for stop and stop-limit orders
|
1055
|
+
// 'timeInForce': '1', // default '1' = GoodTillCancelled, '3' = ImmediateOrCancel, '4' = FillOrKill
|
1056
|
+
// 'execInst': '0',
|
1057
|
+
// '0' = StayOnOfferSide, maker only, reject instead of aggressive execution
|
1058
|
+
// '9' = PegToOfferSide, maker only, best available level instead of aggressive execution
|
1059
|
+
// 'o' = CancelOnConnectionLoss
|
1060
|
+
// 'positionID': 1013838923, // required when positionEffect == 'C' with hedged accounting
|
1061
|
+
// 'positionEffect': 'O', // 'C' = Close, 'O' = Open, send C along with the positionID if the order must close a position with hedged accounting mode
|
1062
|
+
// 'text': 'comment', // optional
|
1063
|
+
// 'grpID': 'group-identifier', // group identifier for cancel on disconnect orders
|
1064
|
+
};
|
1065
|
+
if ((type === 'limit') || (type === 'stop-limit')) {
|
1066
|
+
if (price === undefined) {
|
1067
|
+
throw new InvalidOrder (this.id + ' createOrder() requires a price argument for order type ' + type);
|
1068
|
+
}
|
1069
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1070
|
+
}
|
1071
|
+
if ((type === 'stop') || (type === 'stop-limit')) {
|
1072
|
+
const stopPx = this.safeNumber (params, 'stopPx');
|
1073
|
+
if (stopPx === undefined) {
|
1074
|
+
throw new InvalidOrder (this.id + ' createOrder() requires a stopPx param for order type ' + type);
|
1075
|
+
}
|
1076
|
+
request['stopPx'] = this.priceToPrecision (symbol, stopPx);
|
1077
|
+
params = this.omit (params, 'stopPx');
|
1078
|
+
}
|
1079
|
+
const clientOrderId = this.safeString2 (params, 'clientOrderId', 'clOrdId', this.uuid ());
|
1080
|
+
if (clientOrderId !== undefined) {
|
1081
|
+
request['clOrdId'] = clientOrderId;
|
1082
|
+
params = this.omit (params, [ 'clientOrderId', 'clOrdId' ]);
|
1083
|
+
}
|
1084
|
+
const response = await this.privatePostTradingOrderNew (this.extend (request, params));
|
1085
|
+
//
|
1086
|
+
// {
|
1087
|
+
// "msgType":"8",
|
1088
|
+
// "account":1012838720,
|
1089
|
+
// "clOrdId":"XAq0pRQ1g",
|
1090
|
+
// "orderId":"64d7a06a-27e5-422e-99d9-3cadc04f5a35",
|
1091
|
+
// "symbol":"XBTUSD",
|
1092
|
+
// "ordType":"2",
|
1093
|
+
// "price":"9000",
|
1094
|
+
// "transactTime":1593778763271127920,
|
1095
|
+
// "execId":"ff5fb8153652f0516bf07b6979255bed053c84b9",
|
1096
|
+
// "execType":"I",
|
1097
|
+
// "ordStatus":"0",
|
1098
|
+
// "side":"1",
|
1099
|
+
// "orderQty":"1",
|
1100
|
+
// "leavesQty":"1",
|
1101
|
+
// "cumQty":"0",
|
1102
|
+
// "positionEffect":"O",
|
1103
|
+
// "marginAmt":"0.00000556",
|
1104
|
+
// "marginAmtType":"11"
|
1105
|
+
// }
|
1106
|
+
//
|
1107
|
+
return this.parseOrder (response, market);
|
1108
|
+
}
|
1109
|
+
|
1110
|
+
async editOrder (id, symbol, type, side, amount = undefined, price = undefined, params = {}) {
|
1111
|
+
if (symbol === undefined) {
|
1112
|
+
throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
|
1113
|
+
}
|
1114
|
+
await this.loadMarkets ();
|
1115
|
+
await this.loadAccounts ();
|
1116
|
+
const accountId = await this.getAccountId (params);
|
1117
|
+
const market = this.market (symbol);
|
1118
|
+
const request = {
|
1119
|
+
'account': parseInt (accountId),
|
1120
|
+
'clOrdId': this.uuid (),
|
1121
|
+
'symbol': market['id'],
|
1122
|
+
'transactTime': this.milliseconds () * 1000000,
|
1123
|
+
// 'origClOrdId': this.uuid (), // one of orderId or origClOrdId is required
|
1124
|
+
// 'orderId': id,
|
1125
|
+
// 'side': '1', // 1 = buy, 2 = sell
|
1126
|
+
// 'execInst': '0',
|
1127
|
+
// '0' = StayOnOfferSide, maker only, reject instead of aggressive execution
|
1128
|
+
// '9' = PegToOfferSide, maker only, best available level instead of aggressive execution
|
1129
|
+
// 'o' = CancelOnConnectionLoss
|
1130
|
+
// 'orderQty': 38 M decimal
|
1131
|
+
// 'price': this.priceToPrecision (symbol, price), // required for limit and stop-limit orders
|
1132
|
+
// 'stopPx': this.priceToPrecision (symbol, stopPx), // required for stop and stop-limit orders
|
1133
|
+
// 'capPrice': this.priceToPrecision (symbol, capPrice), // the price beyond which the order will not move for trailing stop and attempt-zero-loss
|
1134
|
+
// 'pegPriceType': '8', // '8' = TrailingStopPeg, identifies a trailing stop or an attempt-zero-loss order
|
1135
|
+
// 'pegOffsetType': '2', // '2' = BasisPoints, the unit of the distance to the stop price for a trailing stop or an attempt-zero-loss order
|
1136
|
+
// 'pegOffsetValue': 123, // distance to the trailing stop or attempt-zero-loss
|
1137
|
+
};
|
1138
|
+
const clientOrderId = this.safeString2 (params, 'clientOrderId', 'origClOrdId');
|
1139
|
+
if (clientOrderId !== undefined) {
|
1140
|
+
request['origClOrdId'] = clientOrderId;
|
1141
|
+
params = this.omit (params, [ 'clientOrderId', 'origClOrdId' ]);
|
1142
|
+
} else {
|
1143
|
+
request['orderId'] = id;
|
1144
|
+
}
|
1145
|
+
if (amount !== undefined) {
|
1146
|
+
request['orderQty'] = this.amountToPrecision (symbol, amount);
|
1147
|
+
}
|
1148
|
+
if (price !== undefined) {
|
1149
|
+
request['price'] = this.priceToPrecision (symbol, price);
|
1150
|
+
}
|
1151
|
+
const stopPx = this.safeNumber (params, 'stopPx');
|
1152
|
+
if (stopPx !== undefined) {
|
1153
|
+
request['stopPx'] = this.priceToPrecision (symbol, stopPx);
|
1154
|
+
params = this.omit (params, 'stopPx');
|
1155
|
+
}
|
1156
|
+
const capPrice = this.safeNumber (params, 'capPrice');
|
1157
|
+
if (capPrice !== undefined) {
|
1158
|
+
request['capPrice'] = this.priceToPrecision (symbol, capPrice);
|
1159
|
+
params = this.omit (params, 'capPrice');
|
1160
|
+
}
|
1161
|
+
const response = await this.privatePostTradingOrderReplace (this.extend (request, params));
|
1162
|
+
return this.parseOrder (response, market);
|
1163
|
+
}
|
1164
|
+
|
1165
|
+
async cancelOrder (id, symbol = undefined, params = {}) {
|
1166
|
+
if (symbol === undefined) {
|
1167
|
+
throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
|
1168
|
+
}
|
1169
|
+
await this.loadMarkets ();
|
1170
|
+
await this.loadAccounts ();
|
1171
|
+
const accountId = await this.getAccountId (params);
|
1172
|
+
const clientOrderId = this.safeString2 (params, 'clientOrderId', 'origClOrdId');
|
1173
|
+
params = this.omit (params, [ 'clientOrderId', 'origClOrdId' ]);
|
1174
|
+
const market = this.market (symbol);
|
1175
|
+
const request = {
|
1176
|
+
'account': parseInt (accountId),
|
1177
|
+
'symbol': market['id'],
|
1178
|
+
'clOrdId': this.uuid (),
|
1179
|
+
'transactTime': this.milliseconds () * 1000000,
|
1180
|
+
};
|
1181
|
+
if (clientOrderId !== undefined) {
|
1182
|
+
request['origClOrdId'] = clientOrderId;
|
1183
|
+
} else {
|
1184
|
+
request['orderId'] = id;
|
1185
|
+
}
|
1186
|
+
const response = await this.privatePostTradingOrderCancel (this.extend (request, params));
|
1187
|
+
//
|
1188
|
+
// {
|
1189
|
+
// "msgType":"8",
|
1190
|
+
// "account":1012838158,
|
1191
|
+
// "clOrdId":"0fa3fb55-9dc0-4cfc-a1db-6aa8b7dd2d98",
|
1192
|
+
// "origClOrdId":"3b2878bb-24d8-4922-9d2a-5b8009416677",
|
1193
|
+
// "orderId":"665b418e-9d09-4461-b733-d317f6bff43f",
|
1194
|
+
// "symbol":"ETHUSD",
|
1195
|
+
// "ordType":"2",
|
1196
|
+
// "price":"640",
|
1197
|
+
// "transactTime":1595060080941618739,
|
1198
|
+
// "execId":"c541c0ca437c0e6501c3a50a9d4dc8f575f49972",
|
1199
|
+
// "execType":"6",
|
1200
|
+
// "ordStatus":"6",
|
1201
|
+
// "side":"2",
|
1202
|
+
// "orderQty":"1",
|
1203
|
+
// "leavesQty":"0",
|
1204
|
+
// "cumQty":"0",
|
1205
|
+
// "positionEffect":"O",
|
1206
|
+
// "marginAmt":"0.000032",
|
1207
|
+
// "marginAmtType":"11"
|
1208
|
+
// }
|
1209
|
+
//
|
1210
|
+
return this.parseOrder (response, market);
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
async cancelAllOrders (symbol = undefined, params = {}) {
|
1214
|
+
await this.loadMarkets ();
|
1215
|
+
await this.loadAccounts ();
|
1216
|
+
const accountId = await this.getAccountId (params);
|
1217
|
+
const request = {
|
1218
|
+
'account': parseInt (accountId),
|
1219
|
+
'clOrdId': this.uuid (),
|
1220
|
+
// 'side': '1', // 1 = buy, 2 = sell, optional filter, cancel only orders with the given side
|
1221
|
+
// 'positionEffect': 'C', // C = Close, O = Open, optional filter, cancel only orders with the given positionEffect, applicable only for accounts with hedged accounting
|
1222
|
+
};
|
1223
|
+
if (symbol !== undefined) {
|
1224
|
+
const market = this.market (symbol);
|
1225
|
+
request['symbol'] = market['id'];
|
1226
|
+
request['massCancelRequestType'] = '1'; // CancelOrdersForASecurity
|
1227
|
+
} else {
|
1228
|
+
request['massCancelRequestType'] = '7'; // CancelAllOrders
|
1229
|
+
}
|
1230
|
+
const response = await this.privatePostTradingOrderMassCancel (this.extend (request, params));
|
1231
|
+
//
|
1232
|
+
// {
|
1233
|
+
// "msgType":"r",
|
1234
|
+
// "clOrdId":"b3e95759-e43e-4b3a-b664-a4d213e281a7",
|
1235
|
+
// "massActionReportID":"e915b6f4-a7ca-4c5c-b8d6-e39862530248",
|
1236
|
+
// "massCancelResponse":"1",
|
1237
|
+
// "symbol":"ETHUSD",
|
1238
|
+
// "transactTime":1595065630133756426,
|
1239
|
+
// "totalAffectedOrders":2,
|
1240
|
+
// "account":1012838158
|
1241
|
+
// }
|
1242
|
+
//
|
1243
|
+
return response;
|
1244
|
+
}
|
1245
|
+
|
1246
|
+
async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1247
|
+
await this.loadMarkets ();
|
1248
|
+
await this.loadAccounts ();
|
1249
|
+
const accountId = await this.getAccountId (params);
|
1250
|
+
const request = {
|
1251
|
+
'accountId': accountId,
|
1252
|
+
// 'symbol': market['id'],
|
1253
|
+
};
|
1254
|
+
let market = undefined;
|
1255
|
+
if (symbol !== undefined) {
|
1256
|
+
market = this.market (symbol);
|
1257
|
+
request['symbol'] = market['id'];
|
1258
|
+
}
|
1259
|
+
const response = await this.privateGetTradingAccountsAccountIdActiveOrders (this.extend (request, params));
|
1260
|
+
//
|
1261
|
+
// [
|
1262
|
+
// {
|
1263
|
+
// "msgType":"8",
|
1264
|
+
// "account":1012838720,
|
1265
|
+
// "clOrdId":"XAq0pRQ1g",
|
1266
|
+
// "orderId":"64d7a06a-27e5-422e-99d9-3cadc04f5a35",
|
1267
|
+
// "symbol":"XBTUSD",
|
1268
|
+
// "ordType":"2",
|
1269
|
+
// "price":"9000",
|
1270
|
+
// "transactTime":1593778763271127920,
|
1271
|
+
// "execId":"ff5fb8153652f0516bf07b6979255bed053c84b9",
|
1272
|
+
// "execType":"I",
|
1273
|
+
// "ordStatus":"0",
|
1274
|
+
// "side":"1",
|
1275
|
+
// "orderQty":"1",
|
1276
|
+
// "leavesQty":"1",
|
1277
|
+
// "cumQty":"0",
|
1278
|
+
// "positionEffect":"O",
|
1279
|
+
// "marginAmt":"0.00000556",
|
1280
|
+
// "marginAmtType":"11"
|
1281
|
+
// }
|
1282
|
+
// ]
|
1283
|
+
//
|
1284
|
+
return this.parseOrders (response, market, since, limit);
|
1285
|
+
}
|
1286
|
+
|
1287
|
+
async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
|
1288
|
+
await this.loadMarkets ();
|
1289
|
+
await this.loadAccounts ();
|
1290
|
+
const accountId = await this.getAccountId (params);
|
1291
|
+
const request = {
|
1292
|
+
'accountId': accountId,
|
1293
|
+
// 'from': this.iso8601 (since) * 1000000,
|
1294
|
+
// 'to': this.iso8601 (this.milliseconds ()) * 1000000, // max range is 7 days
|
1295
|
+
// 'symbol': market['id'],
|
1296
|
+
// 'limit': 100,
|
1297
|
+
};
|
1298
|
+
let market = undefined;
|
1299
|
+
if (symbol !== undefined) {
|
1300
|
+
market = this.market (symbol);
|
1301
|
+
request['symbol'] = market['id'];
|
1302
|
+
}
|
1303
|
+
if (since !== undefined) {
|
1304
|
+
request['from'] = this.iso8601 (since) * 1000000;
|
1305
|
+
}
|
1306
|
+
if (limit !== undefined) {
|
1307
|
+
request['limit'] = limit;
|
1308
|
+
}
|
1309
|
+
const response = await this.privateGetTradingAccountsAccountIdLastOrderStatuses (this.extend (request, params));
|
1310
|
+
//
|
1311
|
+
// [
|
1312
|
+
// {
|
1313
|
+
// "msgType":"8",
|
1314
|
+
// "account":1012838720,
|
1315
|
+
// "clOrdId":"XAq0pRQ1g",
|
1316
|
+
// "orderId":"64d7a06a-27e5-422e-99d9-3cadc04f5a35",
|
1317
|
+
// "symbol":"XBTUSD",
|
1318
|
+
// "ordType":"2",
|
1319
|
+
// "price":"9000",
|
1320
|
+
// "transactTime":1593778763271127920,
|
1321
|
+
// "execId":"ff5fb8153652f0516bf07b6979255bed053c84b9",
|
1322
|
+
// "execType":"I",
|
1323
|
+
// "ordStatus":"0",
|
1324
|
+
// "side":"1",
|
1325
|
+
// "orderQty":"1",
|
1326
|
+
// "leavesQty":"1",
|
1327
|
+
// "cumQty":"0",
|
1328
|
+
// "positionEffect":"O",
|
1329
|
+
// "marginAmt":"0.00000556",
|
1330
|
+
// "marginAmtType":"11"
|
1331
|
+
// }
|
1332
|
+
// ]
|
1333
|
+
//
|
1334
|
+
return this.parseOrders (response, market, since, limit);
|
1335
|
+
}
|
1336
|
+
|
1337
|
+
async createDepositAddress (code, params = {}) {
|
1338
|
+
await this.loadMarkets ();
|
1339
|
+
await this.loadAccounts ();
|
1340
|
+
const accountId = await this.getAccountId (params);
|
1341
|
+
const currency = this.currency (code);
|
1342
|
+
const request = {
|
1343
|
+
'accountId': accountId,
|
1344
|
+
'currency': currency['id'],
|
1345
|
+
};
|
1346
|
+
const response = await this.privatePostTransfersAccountsAccountIdDepositAddressCurrency (this.extend (request, params));
|
1347
|
+
//
|
1348
|
+
// {
|
1349
|
+
// "address": "mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",
|
1350
|
+
// "uri": "bitcoin:mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9?message=Xena Exchange",
|
1351
|
+
// "allowsRenewal": true
|
1352
|
+
// }
|
1353
|
+
//
|
1354
|
+
const address = this.safeValue (response, 'address');
|
1355
|
+
const tag = undefined;
|
1356
|
+
this.checkAddress (address);
|
1357
|
+
return {
|
1358
|
+
'currency': code,
|
1359
|
+
'address': address,
|
1360
|
+
'tag': tag,
|
1361
|
+
'info': response,
|
1362
|
+
};
|
1363
|
+
}
|
1364
|
+
|
1365
|
+
async fetchDepositAddress (code, params = {}) {
|
1366
|
+
await this.loadMarkets ();
|
1367
|
+
await this.loadAccounts ();
|
1368
|
+
const accountId = await this.getAccountId (params);
|
1369
|
+
const currency = this.currency (code);
|
1370
|
+
const request = {
|
1371
|
+
'accountId': accountId,
|
1372
|
+
'currency': currency['id'],
|
1373
|
+
};
|
1374
|
+
const response = await this.privateGetTransfersAccountsAccountIdDepositAddressCurrency (this.extend (request, params));
|
1375
|
+
//
|
1376
|
+
// {
|
1377
|
+
// "address": "mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",
|
1378
|
+
// "uri": "bitcoin:mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9?message=Xena Exchange",
|
1379
|
+
// "allowsRenewal": true
|
1380
|
+
// }
|
1381
|
+
//
|
1382
|
+
const address = this.safeValue (response, 'address');
|
1383
|
+
const tag = undefined;
|
1384
|
+
this.checkAddress (address);
|
1385
|
+
return {
|
1386
|
+
'currency': code,
|
1387
|
+
'address': address,
|
1388
|
+
'tag': tag,
|
1389
|
+
'network': undefined,
|
1390
|
+
'info': response,
|
1391
|
+
};
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
async fetchTransactionsByType (type, code = undefined, since = undefined, limit = undefined, params = {}) {
|
1395
|
+
if (code === undefined) {
|
1396
|
+
throw new ArgumentsRequired (this.id + ' fetchTransactions() requires a currency `code` argument');
|
1397
|
+
}
|
1398
|
+
await this.loadMarkets ();
|
1399
|
+
await this.loadAccounts ();
|
1400
|
+
const accountId = await this.getAccountId (params);
|
1401
|
+
const currency = this.currency (code);
|
1402
|
+
const request = {
|
1403
|
+
'currency': currency['id'],
|
1404
|
+
'accountId': accountId,
|
1405
|
+
};
|
1406
|
+
if (since !== undefined) {
|
1407
|
+
request['since'] = parseInt (since / 1000);
|
1408
|
+
}
|
1409
|
+
const method = 'privateGetTransfersAccountsAccountId' + this.capitalize (type);
|
1410
|
+
const response = await this[method] (this.extend (request, params));
|
1411
|
+
//
|
1412
|
+
// {
|
1413
|
+
// "withdrawals": [
|
1414
|
+
// {
|
1415
|
+
// "withdrawalRequestId": 47383243,
|
1416
|
+
// "externalId": "...", // external ID submitted by the client when creating the request
|
1417
|
+
// "status": 1,
|
1418
|
+
// "statusMessage": "Pending confirmation",
|
1419
|
+
// "amount": "10.2",
|
1420
|
+
// "currency": "BTC",
|
1421
|
+
// "lastUpdated": <UNIX nanoseconds>,
|
1422
|
+
// "blockchain": "Bitcoin",
|
1423
|
+
// "address": "mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",
|
1424
|
+
// "txId": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98"
|
1425
|
+
// }
|
1426
|
+
// ]
|
1427
|
+
// }
|
1428
|
+
//
|
1429
|
+
// {
|
1430
|
+
// "deposits": [
|
1431
|
+
// {
|
1432
|
+
// "currency": "BTC",
|
1433
|
+
// "amount": "1.2",
|
1434
|
+
// "status": 1,
|
1435
|
+
// "statusMessage": "Processing",
|
1436
|
+
// "blockchain": "Bitcoin",
|
1437
|
+
// "txId": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
|
1438
|
+
// "address": "mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",
|
1439
|
+
// "lastUpdated": <UNIX nanoseconds>
|
1440
|
+
// "confirmations": 2,
|
1441
|
+
// "requiredConfirmations": 6
|
1442
|
+
// }
|
1443
|
+
// ]
|
1444
|
+
// }
|
1445
|
+
//
|
1446
|
+
//
|
1447
|
+
const transactions = this.safeValue (response, type, []);
|
1448
|
+
return this.parseTransactions (transactions, currency, since, limit);
|
1449
|
+
}
|
1450
|
+
|
1451
|
+
async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1452
|
+
return await this.fetchTransactionsByType ('withdrawals', code, since, limit, params);
|
1453
|
+
}
|
1454
|
+
|
1455
|
+
async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1456
|
+
return await this.fetchTransactionsByType ('deposits', code, since, limit, params);
|
1457
|
+
}
|
1458
|
+
|
1459
|
+
parseTransaction (transaction, currency = undefined) {
|
1460
|
+
//
|
1461
|
+
// withdraw()
|
1462
|
+
//
|
1463
|
+
// {
|
1464
|
+
// "withdrawalRequestId": 47383243,
|
1465
|
+
// "status": 1,
|
1466
|
+
// "statusMessage": "Pending confirmation"
|
1467
|
+
// }
|
1468
|
+
//
|
1469
|
+
// fetchWithdrawals
|
1470
|
+
//
|
1471
|
+
// {
|
1472
|
+
// "withdrawalRequestId": 47383243,
|
1473
|
+
// "externalId": "...", // external ID submitted by the client when creating the request
|
1474
|
+
// "status": 1,
|
1475
|
+
// "statusMessage": "Pending confirmation",
|
1476
|
+
// "amount": "10.2",
|
1477
|
+
// "currency": "BTC",
|
1478
|
+
// "lastUpdated": <UNIX nanoseconds>,
|
1479
|
+
// "blockchain": "Bitcoin",
|
1480
|
+
// "address": "mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",
|
1481
|
+
// "txId": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98"
|
1482
|
+
// }
|
1483
|
+
//
|
1484
|
+
// fetchDeposits
|
1485
|
+
//
|
1486
|
+
// {
|
1487
|
+
// "currency": "BTC",
|
1488
|
+
// "amount": "1.2",
|
1489
|
+
// "status": 1,
|
1490
|
+
// "statusMessage": "Processing",
|
1491
|
+
// "blockchain": "Bitcoin",
|
1492
|
+
// "txId": "0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98",
|
1493
|
+
// "address": "mu5GceHFAG38mGRYCFqafe5ZiNKLX3rKk9",
|
1494
|
+
// "lastUpdated": <UNIX nanoseconds>
|
1495
|
+
// "confirmations": 2,
|
1496
|
+
// "requiredConfirmations": 6
|
1497
|
+
// }
|
1498
|
+
//
|
1499
|
+
const id = this.safeString (transaction, 'withdrawalRequestId');
|
1500
|
+
const type = (id === undefined) ? 'deposit' : 'withdrawal';
|
1501
|
+
let updated = this.safeInteger (transaction, 'lastUpdated');
|
1502
|
+
if (updated !== undefined) {
|
1503
|
+
updated = parseInt (updated / 1000000);
|
1504
|
+
}
|
1505
|
+
const timestamp = undefined;
|
1506
|
+
const txid = this.safeString (transaction, 'txId');
|
1507
|
+
const currencyId = this.safeString (transaction, 'currency');
|
1508
|
+
const code = this.safeCurrencyCode (currencyId, currency);
|
1509
|
+
const address = this.safeString (transaction, 'address');
|
1510
|
+
const addressFrom = undefined;
|
1511
|
+
const addressTo = address;
|
1512
|
+
const amount = this.safeNumber (transaction, 'amount');
|
1513
|
+
const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
|
1514
|
+
const fee = undefined;
|
1515
|
+
const network = this.safeString (transaction, 'blockchain');
|
1516
|
+
return {
|
1517
|
+
'info': transaction,
|
1518
|
+
'id': id,
|
1519
|
+
'txid': txid,
|
1520
|
+
'timestamp': timestamp,
|
1521
|
+
'datetime': this.iso8601 (timestamp),
|
1522
|
+
'network': network,
|
1523
|
+
'addressFrom': addressFrom,
|
1524
|
+
'addressTo': addressTo,
|
1525
|
+
'address': address,
|
1526
|
+
'tagFrom': undefined,
|
1527
|
+
'tagTo': undefined,
|
1528
|
+
'tag': undefined,
|
1529
|
+
'type': type,
|
1530
|
+
'amount': amount,
|
1531
|
+
'currency': code,
|
1532
|
+
'status': status,
|
1533
|
+
'updated': updated,
|
1534
|
+
'fee': fee,
|
1535
|
+
};
|
1536
|
+
}
|
1537
|
+
|
1538
|
+
parseTransactionStatus (status) {
|
1539
|
+
const statuses = {
|
1540
|
+
'1': 'pending', // new
|
1541
|
+
'2': 'ok', // completed
|
1542
|
+
'3': 'failed', // duplicate
|
1543
|
+
'4': 'failed', // not enough money
|
1544
|
+
'5': 'pending', // waiting for manual approval from XENA
|
1545
|
+
'100': 'pending', // request is being processed
|
1546
|
+
'101': 'pending', // request is being processed
|
1547
|
+
'102': 'pending', // request is being processed
|
1548
|
+
'103': 'pending', // request is being processed
|
1549
|
+
};
|
1550
|
+
return this.safeString (statuses, status, status);
|
1551
|
+
}
|
1552
|
+
|
1553
|
+
async withdraw (code, amount, address, tag = undefined, params = {}) {
|
1554
|
+
[ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
|
1555
|
+
this.checkAddress (address);
|
1556
|
+
await this.loadMarkets ();
|
1557
|
+
await this.loadAccounts ();
|
1558
|
+
const accountId = await this.getAccountId (params);
|
1559
|
+
const currency = this.currency (code);
|
1560
|
+
let uuid = this.uuid ();
|
1561
|
+
uuid = uuid.split ('-');
|
1562
|
+
uuid = uuid.join ('');
|
1563
|
+
const request = {
|
1564
|
+
'currency': currency['id'],
|
1565
|
+
'accountId': accountId,
|
1566
|
+
'amount': this.currencyToPrecision (code, amount),
|
1567
|
+
'address': address,
|
1568
|
+
'id': uuid, // mandatory external ID (string), used by the client to identify his request
|
1569
|
+
};
|
1570
|
+
const response = await this.privatePostTransfersAccountsAccountIdWithdrawals (this.extend (request, params));
|
1571
|
+
//
|
1572
|
+
// {
|
1573
|
+
// "withdrawalRequestId": 47383243,
|
1574
|
+
// "status": 1,
|
1575
|
+
// "statusMessage": "Pending confirmation"
|
1576
|
+
// }
|
1577
|
+
//
|
1578
|
+
return this.parseTransaction (response, currency);
|
1579
|
+
}
|
1580
|
+
|
1581
|
+
parseLedgerEntryType (type) {
|
1582
|
+
const types = {
|
1583
|
+
'deposit': 'transaction',
|
1584
|
+
'withdrawal': 'transaction',
|
1585
|
+
'internal deposit': 'transfer',
|
1586
|
+
'internal withdrawal': 'transfer',
|
1587
|
+
'rebate': 'rebate',
|
1588
|
+
'reward': 'reward',
|
1589
|
+
};
|
1590
|
+
return this.safeString (types, type, type);
|
1591
|
+
}
|
1592
|
+
|
1593
|
+
parseLedgerEntry (item, currency = undefined) {
|
1594
|
+
//
|
1595
|
+
// {
|
1596
|
+
// "accountId":8263118,
|
1597
|
+
// "ts":1551974415000000000,
|
1598
|
+
// "amount":"-1",
|
1599
|
+
// "currency":"BTC",
|
1600
|
+
// "kind":"internal withdrawal",
|
1601
|
+
// "commission":"0",
|
1602
|
+
// "id":96
|
1603
|
+
// }
|
1604
|
+
//
|
1605
|
+
const id = this.safeString (item, 'id');
|
1606
|
+
let direction = undefined;
|
1607
|
+
const account = this.safeString (item, 'accountId');
|
1608
|
+
const referenceId = undefined;
|
1609
|
+
const referenceAccount = undefined;
|
1610
|
+
const type = this.parseLedgerEntryType (this.safeString (item, 'kind'));
|
1611
|
+
const code = this.safeCurrencyCode (this.safeString (item, 'currency'), currency);
|
1612
|
+
let amount = this.safeNumber (item, 'amount');
|
1613
|
+
if (amount < 0) {
|
1614
|
+
direction = 'out';
|
1615
|
+
amount = Math.abs (amount);
|
1616
|
+
} else {
|
1617
|
+
direction = 'in';
|
1618
|
+
}
|
1619
|
+
let timestamp = this.safeInteger (item, 'ts');
|
1620
|
+
if (timestamp !== undefined) {
|
1621
|
+
timestamp = parseInt (timestamp / 1000000);
|
1622
|
+
}
|
1623
|
+
const fee = {
|
1624
|
+
'cost': this.safeNumber (item, 'commission'),
|
1625
|
+
'currency': code,
|
1626
|
+
};
|
1627
|
+
const before = undefined;
|
1628
|
+
const after = this.safeNumber (item, 'balance');
|
1629
|
+
const status = 'ok';
|
1630
|
+
return {
|
1631
|
+
'info': item,
|
1632
|
+
'id': id,
|
1633
|
+
'direction': direction,
|
1634
|
+
'account': account,
|
1635
|
+
'referenceId': referenceId,
|
1636
|
+
'referenceAccount': referenceAccount,
|
1637
|
+
'type': type,
|
1638
|
+
'currency': code,
|
1639
|
+
'amount': amount,
|
1640
|
+
'before': before,
|
1641
|
+
'after': after,
|
1642
|
+
'status': status,
|
1643
|
+
'timestamp': timestamp,
|
1644
|
+
'datetime': this.iso8601 (timestamp),
|
1645
|
+
'fee': fee,
|
1646
|
+
};
|
1647
|
+
}
|
1648
|
+
|
1649
|
+
async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
|
1650
|
+
await this.loadMarkets ();
|
1651
|
+
await this.loadAccounts ();
|
1652
|
+
const accountId = await this.getAccountId (params);
|
1653
|
+
const request = {
|
1654
|
+
'accountId': accountId,
|
1655
|
+
// 'page': 1,
|
1656
|
+
// 'limit': 5000, // max 5000
|
1657
|
+
// 'from': time,
|
1658
|
+
// 'to': time,
|
1659
|
+
// 'symbol': currency['id'],
|
1660
|
+
// 'trade_id': id,
|
1661
|
+
// 'client_order_id': id,
|
1662
|
+
// 'txid': txid,
|
1663
|
+
// 'kind': 'deposit', // 'withdrawal, 'internal deposit', 'internal withdrawal', 'rebate', 'reward'
|
1664
|
+
};
|
1665
|
+
let currency = undefined;
|
1666
|
+
if (code !== undefined) {
|
1667
|
+
currency = this.currency (code);
|
1668
|
+
request['symbol'] = currency['id'];
|
1669
|
+
}
|
1670
|
+
if (since !== undefined) {
|
1671
|
+
request['from'] = since * 1000000;
|
1672
|
+
}
|
1673
|
+
if (limit !== undefined) {
|
1674
|
+
request['limit'] = limit; // max 5000
|
1675
|
+
}
|
1676
|
+
const response = await this.privateGetTransfersAccountsAccountIdBalanceHistory (this.extend (request, params));
|
1677
|
+
//
|
1678
|
+
// [
|
1679
|
+
// {
|
1680
|
+
// "accountId":8263118,
|
1681
|
+
// "ts":1551974415000000000,
|
1682
|
+
// "amount":"-1",
|
1683
|
+
// "currency":"BTC",
|
1684
|
+
// "kind":"internal withdrawal",
|
1685
|
+
// "commission":"0",
|
1686
|
+
// "id":96
|
1687
|
+
// },
|
1688
|
+
// {
|
1689
|
+
// "accountId":8263118,
|
1690
|
+
// "ts":1551964677000000000,
|
1691
|
+
// "amount":"-1",
|
1692
|
+
// "currency":"BTC",
|
1693
|
+
// "kind":"internal deposit",
|
1694
|
+
// "commission":"0",
|
1695
|
+
// "id":95
|
1696
|
+
// }
|
1697
|
+
// ]
|
1698
|
+
//
|
1699
|
+
return this.parseLedger (response, currency, since, limit);
|
1700
|
+
}
|
1701
|
+
|
1702
|
+
async fetchLeverageTiers (symbols = undefined, params = {}) {
|
1703
|
+
await this.loadMarkets ();
|
1704
|
+
const response = await this.publicGetCommonInstruments (params);
|
1705
|
+
//
|
1706
|
+
// [
|
1707
|
+
// {
|
1708
|
+
// "id": "XBTUSD_3M_240622",
|
1709
|
+
// "type": "Margin",
|
1710
|
+
// "marginType": "XenaFuture",
|
1711
|
+
// "symbol": "XBTUSD_3M_240622",
|
1712
|
+
// "baseCurrency": "BTC",
|
1713
|
+
// "quoteCurrency": "USD",
|
1714
|
+
// "settlCurrency": "USDC",
|
1715
|
+
// "tickSize": 0,
|
1716
|
+
// "minOrderQuantity": "0.0001",
|
1717
|
+
// "orderQtyStep": "0.0001",
|
1718
|
+
// "limitOrderMaxDistance": "10",
|
1719
|
+
// "priceInputMask": "00000.0",
|
1720
|
+
// "enabled": true,
|
1721
|
+
// "liquidationMaxDistance": "0.01",
|
1722
|
+
// "contractValue": "1",
|
1723
|
+
// "contractCurrency": "BTC",
|
1724
|
+
// "lotSize": "1",
|
1725
|
+
// "maxOrderQty": "10",
|
1726
|
+
// "maxPosVolume": "200",
|
1727
|
+
// "mark": ".XBTUSD_3M_240622",
|
1728
|
+
// "underlying": ".BTC3_TWAP",
|
1729
|
+
// "openInterest": ".XBTUSD_3M_240622_OpenInterest",
|
1730
|
+
// "addUvmToFreeMargin": "ProfitAndLoss",
|
1731
|
+
// "margin": {
|
1732
|
+
// "netting": "PositionsAndOrders",
|
1733
|
+
// "rates": [
|
1734
|
+
// { "maxVolume": "10", "initialRate": "0.05", "maintenanceRate": "0.025" },
|
1735
|
+
// { "maxVolume": "20", "initialRate": "0.1", "maintenanceRate": "0.05" },
|
1736
|
+
// { "maxVolume": "30", "initialRate": "0.2", "maintenanceRate": "0.1" },
|
1737
|
+
// { "maxVolume": "40", "initialRate": "0.3", "maintenanceRate": "0.15" },
|
1738
|
+
// { "maxVolume": "60", "initialRate": "0.4", "maintenanceRate": "0.2" },
|
1739
|
+
// { "maxVolume": "150", "initialRate": "0.5", "maintenanceRate": "0.25" },
|
1740
|
+
// { "maxVolume": "200", "initialRate": "1", "maintenanceRate": "0.5" }
|
1741
|
+
// ],
|
1742
|
+
// "rateMultipliers": {
|
1743
|
+
// "LimitBuy": "1",
|
1744
|
+
// "LimitSell": "1",
|
1745
|
+
// "Long": "1",
|
1746
|
+
// "MarketBuy": "1",
|
1747
|
+
// "MarketSell": "1",
|
1748
|
+
// "Short": "1",
|
1749
|
+
// "StopBuy": "0",
|
1750
|
+
// "StopSell": "0"
|
1751
|
+
// }
|
1752
|
+
// },
|
1753
|
+
// "clearing": { "enabled": true, "index": ".XBTUSD_3M_240622" },
|
1754
|
+
// "riskAdjustment": { "enabled": true, "index": ".RiskAdjustment_IR" },
|
1755
|
+
// "expiration": { "enabled": true, "index": ".BTC3_TWAP" },
|
1756
|
+
// "pricePrecision": 1,
|
1757
|
+
// "priceRange": {
|
1758
|
+
// "enabled": true,
|
1759
|
+
// "distance": "0.2",
|
1760
|
+
// "movingBoundary": "0",
|
1761
|
+
// "lowIndex": ".XBTUSD_3M_240622_LOWRANGE",
|
1762
|
+
// "highIndex": ".XBTUSD_3M_240622_HIGHRANGE"
|
1763
|
+
// },
|
1764
|
+
// "priceLimits": {
|
1765
|
+
// "enabled": true,
|
1766
|
+
// "distance": "0.5",
|
1767
|
+
// "movingBoundary": "0",
|
1768
|
+
// "lowIndex": ".XBTUSD_3M_240622_LOWLIMIT",
|
1769
|
+
// "highIndex": ".XBTUSD_3M_240622_HIGHLIMIT"
|
1770
|
+
// },
|
1771
|
+
// "serie": "XBTUSD",
|
1772
|
+
// "tradingStartDate": "2021-12-31 07:00:00",
|
1773
|
+
// "expiryDate": "2022-06-24 08:00:00"
|
1774
|
+
// },
|
1775
|
+
// ...
|
1776
|
+
// ]
|
1777
|
+
//
|
1778
|
+
return this.parseLeverageTiers (response, symbols, 'symbol');
|
1779
|
+
}
|
1780
|
+
|
1781
|
+
parseMarketLeverageTiers (info, market) {
|
1782
|
+
/**
|
1783
|
+
* @ignore
|
1784
|
+
* @method
|
1785
|
+
* @param {dict} info Exchange market response for 1 market
|
1786
|
+
* @param {dict} market CCXT market
|
1787
|
+
*/
|
1788
|
+
//
|
1789
|
+
// {
|
1790
|
+
// "id": "XBTUSD_3M_240622",
|
1791
|
+
// "type": "Margin",
|
1792
|
+
// "marginType": "XenaFuture",
|
1793
|
+
// "symbol": "XBTUSD_3M_240622",
|
1794
|
+
// "baseCurrency": "BTC",
|
1795
|
+
// "quoteCurrency": "USD",
|
1796
|
+
// "settlCurrency": "USDC",
|
1797
|
+
// "tickSize": 0,
|
1798
|
+
// "minOrderQuantity": "0.0001",
|
1799
|
+
// "orderQtyStep": "0.0001",
|
1800
|
+
// "limitOrderMaxDistance": "10",
|
1801
|
+
// "priceInputMask": "00000.0",
|
1802
|
+
// "enabled": true,
|
1803
|
+
// "liquidationMaxDistance": "0.01",
|
1804
|
+
// "contractValue": "1",
|
1805
|
+
// "contractCurrency": "BTC",
|
1806
|
+
// "lotSize": "1",
|
1807
|
+
// "maxOrderQty": "10",
|
1808
|
+
// "maxPosVolume": "200",
|
1809
|
+
// "mark": ".XBTUSD_3M_240622",
|
1810
|
+
// "underlying": ".BTC3_TWAP",
|
1811
|
+
// "openInterest": ".XBTUSD_3M_240622_OpenInterest",
|
1812
|
+
// "addUvmToFreeMargin": "ProfitAndLoss",
|
1813
|
+
// "margin": {
|
1814
|
+
// "netting": "PositionsAndOrders",
|
1815
|
+
// "rates": [
|
1816
|
+
// { "maxVolume": "10", "initialRate": "0.05", "maintenanceRate": "0.025" },
|
1817
|
+
// { "maxVolume": "20", "initialRate": "0.1", "maintenanceRate": "0.05" },
|
1818
|
+
// { "maxVolume": "30", "initialRate": "0.2", "maintenanceRate": "0.1" },
|
1819
|
+
// { "maxVolume": "40", "initialRate": "0.3", "maintenanceRate": "0.15" },
|
1820
|
+
// { "maxVolume": "60", "initialRate": "0.4", "maintenanceRate": "0.2" },
|
1821
|
+
// { "maxVolume": "150", "initialRate": "0.5", "maintenanceRate": "0.25" },
|
1822
|
+
// { "maxVolume": "200", "initialRate": "1", "maintenanceRate": "0.5" }
|
1823
|
+
// ],
|
1824
|
+
// "rateMultipliers": {
|
1825
|
+
// "LimitBuy": "1",
|
1826
|
+
// "LimitSell": "1",
|
1827
|
+
// "Long": "1",
|
1828
|
+
// "MarketBuy": "1",
|
1829
|
+
// "MarketSell": "1",
|
1830
|
+
// "Short": "1",
|
1831
|
+
// "StopBuy": "0",
|
1832
|
+
// "StopSell": "0"
|
1833
|
+
// }
|
1834
|
+
// },
|
1835
|
+
// "clearing": { "enabled": true, "index": ".XBTUSD_3M_240622" },
|
1836
|
+
// "riskAdjustment": { "enabled": true, "index": ".RiskAdjustment_IR" },
|
1837
|
+
// "expiration": { "enabled": true, "index": ".BTC3_TWAP" },
|
1838
|
+
// "pricePrecision": 1,
|
1839
|
+
// "priceRange": {
|
1840
|
+
// "enabled": true,
|
1841
|
+
// "distance": "0.2",
|
1842
|
+
// "movingBoundary": "0",
|
1843
|
+
// "lowIndex": ".XBTUSD_3M_240622_LOWRANGE",
|
1844
|
+
// "highIndex": ".XBTUSD_3M_240622_HIGHRANGE"
|
1845
|
+
// },
|
1846
|
+
// "priceLimits": {
|
1847
|
+
// "enabled": true,
|
1848
|
+
// "distance": "0.5",
|
1849
|
+
// "movingBoundary": "0",
|
1850
|
+
// "lowIndex": ".XBTUSD_3M_240622_LOWLIMIT",
|
1851
|
+
// "highIndex": ".XBTUSD_3M_240622_HIGHLIMIT"
|
1852
|
+
// },
|
1853
|
+
// "serie": "XBTUSD",
|
1854
|
+
// "tradingStartDate": "2021-12-31 07:00:00",
|
1855
|
+
// "expiryDate": "2022-06-24 08:00:00"
|
1856
|
+
// }
|
1857
|
+
//
|
1858
|
+
const margin = this.safeValue (info, 'margin');
|
1859
|
+
const rates = this.safeValue (margin, 'rates');
|
1860
|
+
let floor = 0;
|
1861
|
+
const id = this.safeString (info, 'symbol');
|
1862
|
+
market = this.safeMarket (id, market);
|
1863
|
+
const tiers = [];
|
1864
|
+
if (rates !== undefined) {
|
1865
|
+
for (let j = 0; j < rates.length; j++) {
|
1866
|
+
const tier = rates[j];
|
1867
|
+
const cap = this.safeNumber (tier, 'maxVolume');
|
1868
|
+
const initialRate = this.safeString (tier, 'initialRate');
|
1869
|
+
tiers.push ({
|
1870
|
+
'tier': this.sum (j, 1),
|
1871
|
+
'currency': market['base'],
|
1872
|
+
'minNotional': floor,
|
1873
|
+
'maxNotional': cap,
|
1874
|
+
'maintenanceMarginRate': this.safeNumber (tier, 'maintenanceRate'),
|
1875
|
+
'maxLeverage': this.parseNumber (Precise.stringDiv ('1', initialRate)),
|
1876
|
+
'info': tier,
|
1877
|
+
});
|
1878
|
+
floor = cap;
|
1879
|
+
}
|
1880
|
+
}
|
1881
|
+
return tiers;
|
1882
|
+
}
|
1883
|
+
|
1884
|
+
nonce () {
|
1885
|
+
return this.milliseconds ();
|
1886
|
+
}
|
1887
|
+
|
1888
|
+
sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
|
1889
|
+
let url = this.urls['api'][api] + '/' + this.implodeParams (path, params);
|
1890
|
+
const query = this.omit (params, this.extractParams (path));
|
1891
|
+
if (api === 'public') {
|
1892
|
+
if (Object.keys (query).length) {
|
1893
|
+
url += '?' + this.urlencode (query);
|
1894
|
+
}
|
1895
|
+
} else if (api === 'private') {
|
1896
|
+
this.checkRequiredCredentials ();
|
1897
|
+
let nonce = this.nonce ();
|
1898
|
+
// php does not format it properly
|
1899
|
+
// therefore we use string concatenation here
|
1900
|
+
// nonce *= 1000000;
|
1901
|
+
nonce = nonce.toString ();
|
1902
|
+
nonce = nonce + '000000'; // see the comment a few lines above
|
1903
|
+
const payload = 'AUTH' + nonce;
|
1904
|
+
const secret = this.secret.slice (14, 78);
|
1905
|
+
const ecdsa = this.ecdsa (payload, secret, 'p256', 'sha256');
|
1906
|
+
const signature = ecdsa['r'] + ecdsa['s'];
|
1907
|
+
headers = {
|
1908
|
+
'X-AUTH-API-KEY': this.apiKey,
|
1909
|
+
'X-AUTH-API-PAYLOAD': payload,
|
1910
|
+
'X-AUTH-API-SIGNATURE': signature,
|
1911
|
+
'X-AUTH-API-NONCE': nonce,
|
1912
|
+
};
|
1913
|
+
if (method === 'GET') {
|
1914
|
+
if (Object.keys (query).length) {
|
1915
|
+
url += '?' + this.urlencode (query);
|
1916
|
+
}
|
1917
|
+
} else if (method === 'POST') {
|
1918
|
+
body = this.json (query);
|
1919
|
+
headers['Content-Type'] = 'application/json';
|
1920
|
+
}
|
1921
|
+
}
|
1922
|
+
return { 'url': url, 'method': method, 'body': body, 'headers': headers };
|
1923
|
+
}
|
1924
|
+
|
1925
|
+
handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
|
1926
|
+
if (response === undefined) {
|
1927
|
+
return;
|
1928
|
+
}
|
1929
|
+
//
|
1930
|
+
// {"error":"Validation failed","fields":["address"]}
|
1931
|
+
// {"error":"Money not enough. You have only: 0 ETH","fields":["amount"]}
|
1932
|
+
//
|
1933
|
+
if (code >= 400) {
|
1934
|
+
const feedback = this.id + ' ' + this.json (response);
|
1935
|
+
const message = this.safeString (response, 'error');
|
1936
|
+
const exact = this.exceptions['exact'];
|
1937
|
+
if (message in exact) {
|
1938
|
+
throw new exact[message] (feedback);
|
1939
|
+
}
|
1940
|
+
const broad = this.exceptions['broad'];
|
1941
|
+
const broadKey = this.findBroadlyMatchedKey (broad, body);
|
1942
|
+
if (broadKey !== undefined) {
|
1943
|
+
throw new broad[broadKey] (feedback);
|
1944
|
+
}
|
1945
|
+
throw new ExchangeError (feedback); // unknown message
|
1946
|
+
}
|
1947
|
+
}
|
1948
|
+
};
|