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.
Files changed (264) hide show
  1. package/.cache/eslintcache +1 -0
  2. package/.dockerignore +6 -0
  3. package/.eslintignore +1 -0
  4. package/.gitattributes +5 -0
  5. package/.readthedocs.yaml +16 -0
  6. package/CONTRIBUTING.md +1049 -0
  7. package/LICENSE.txt +21 -0
  8. package/README.md +537 -0
  9. package/SECURITY.md +5 -0
  10. package/build/cleanup-old-tags.js +94 -0
  11. package/build/countries.js +256 -0
  12. package/build/export-exchanges.js +520 -0
  13. package/build/fs.js +51 -0
  14. package/build/transpile.js +1772 -0
  15. package/build/vss.js +78 -0
  16. package/ccxt.browser.js +7 -0
  17. package/ccxt.d.ts +692 -0
  18. package/ccxt.js +171 -0
  19. package/cleanup.sh +2 -0
  20. package/composer-install.sh +20 -0
  21. package/dist/ccxt.browser.js +208383 -0
  22. package/gource.sh +3 -0
  23. package/index.html +7 -0
  24. package/js/.eslintrc +87 -0
  25. package/js/aax.js +2686 -0
  26. package/js/ascendex.js +2584 -0
  27. package/js/base/.eslintrc.js +43 -0
  28. package/js/base/Exchange.js +2371 -0
  29. package/js/base/Precise.js +283 -0
  30. package/js/base/errorHierarchy.js +47 -0
  31. package/js/base/errors.js +55 -0
  32. package/js/base/functions/crypto.js +158 -0
  33. package/js/base/functions/encode.js +118 -0
  34. package/js/base/functions/generic.js +270 -0
  35. package/js/base/functions/misc.js +138 -0
  36. package/js/base/functions/number.js +329 -0
  37. package/js/base/functions/platform.js +38 -0
  38. package/js/base/functions/string.js +21 -0
  39. package/js/base/functions/throttle.js +79 -0
  40. package/js/base/functions/time.js +210 -0
  41. package/js/base/functions/type.js +66 -0
  42. package/js/base/functions.js +28 -0
  43. package/js/bequant.js +32 -0
  44. package/js/bibox.js +1407 -0
  45. package/js/bigone.js +1366 -0
  46. package/js/binance.js +5652 -0
  47. package/js/binancecoinm.js +46 -0
  48. package/js/binanceus.js +46 -0
  49. package/js/binanceusdm.js +49 -0
  50. package/js/bit2c.js +535 -0
  51. package/js/bitbank.js +842 -0
  52. package/js/bitbay.js +16 -0
  53. package/js/bitbns.js +1073 -0
  54. package/js/bitcoincom.js +15 -0
  55. package/js/bitfinex.js +1433 -0
  56. package/js/bitfinex2.js +2025 -0
  57. package/js/bitflyer.js +840 -0
  58. package/js/bitforex.js +614 -0
  59. package/js/bitget.js +2397 -0
  60. package/js/bithumb.js +980 -0
  61. package/js/bitmart.js +2516 -0
  62. package/js/bitmex.js +1809 -0
  63. package/js/bitopro.js +1443 -0
  64. package/js/bitpanda.js +1782 -0
  65. package/js/bitrue.js +1747 -0
  66. package/js/bitso.js +1062 -0
  67. package/js/bitstamp.js +1757 -0
  68. package/js/bitstamp1.js +343 -0
  69. package/js/bittrex.js +1876 -0
  70. package/js/bitvavo.js +1579 -0
  71. package/js/bkex.js +1233 -0
  72. package/js/bl3p.js +346 -0
  73. package/js/blockchaincom.js +969 -0
  74. package/js/btcalpha.js +680 -0
  75. package/js/btcbox.js +477 -0
  76. package/js/btcmarkets.js +1022 -0
  77. package/js/btctradeua.js +466 -0
  78. package/js/btcturk.js +734 -0
  79. package/js/buda.js +946 -0
  80. package/js/bw.js +1265 -0
  81. package/js/bybit.js +3372 -0
  82. package/js/bytetrade.js +1336 -0
  83. package/js/cdax.js +1646 -0
  84. package/js/cex.js +1410 -0
  85. package/js/coinbase.js +1342 -0
  86. package/js/coinbaseprime.js +31 -0
  87. package/js/coinbasepro.js +1466 -0
  88. package/js/coincheck.js +755 -0
  89. package/js/coinex.js +3400 -0
  90. package/js/coinfalcon.js +880 -0
  91. package/js/coinmate.js +794 -0
  92. package/js/coinone.js +816 -0
  93. package/js/coinspot.js +345 -0
  94. package/js/crex24.js +1636 -0
  95. package/js/cryptocom.js +1832 -0
  96. package/js/currencycom.js +1748 -0
  97. package/js/delta.js +1547 -0
  98. package/js/deribit.js +2148 -0
  99. package/js/digifinex.js +1585 -0
  100. package/js/eqonex.js +1660 -0
  101. package/js/exmo.js +1670 -0
  102. package/js/fairdesk.js +1231 -0
  103. package/js/flowbtc.js +35 -0
  104. package/js/fmfwio.js +34 -0
  105. package/js/ftx.js +2751 -0
  106. package/js/ftxus.js +38 -0
  107. package/js/gateio.js +4174 -0
  108. package/js/gemini.js +1397 -0
  109. package/js/hitbtc.js +1343 -0
  110. package/js/hitbtc3.js +2329 -0
  111. package/js/hollaex.js +1486 -0
  112. package/js/huobi.js +5706 -0
  113. package/js/huobijp.js +1710 -0
  114. package/js/huobipro.js +18 -0
  115. package/js/idex.js +1439 -0
  116. package/js/independentreserve.js +649 -0
  117. package/js/indodax.js +742 -0
  118. package/js/itbit.js +722 -0
  119. package/js/kraken.js +2179 -0
  120. package/js/kucoin.js +2571 -0
  121. package/js/kucoinfutures.js +1771 -0
  122. package/js/kuna.js +809 -0
  123. package/js/latoken.js +1445 -0
  124. package/js/lbank.js +760 -0
  125. package/js/liquid.js +1432 -0
  126. package/js/luno.js +873 -0
  127. package/js/lykke.js +1147 -0
  128. package/js/mercado.js +771 -0
  129. package/js/mexc.js +3151 -0
  130. package/js/ndax.js +2233 -0
  131. package/js/novadax.js +1318 -0
  132. package/js/oceanex.js +816 -0
  133. package/js/okcoin.js +3841 -0
  134. package/js/okex.js +16 -0
  135. package/js/okex5.js +16 -0
  136. package/js/okx.js +4795 -0
  137. package/js/paymium.js +498 -0
  138. package/js/phemex.js +2957 -0
  139. package/js/poloniex.js +1674 -0
  140. package/js/probit.js +1346 -0
  141. package/js/qtrade.js +1588 -0
  142. package/js/ripio.js +1061 -0
  143. package/js/static_dependencies/BN/bn.js +3526 -0
  144. package/js/static_dependencies/README.md +1 -0
  145. package/js/static_dependencies/crypto-js/crypto-js.js +5988 -0
  146. package/js/static_dependencies/elliptic/lib/elliptic/curve/base.js +375 -0
  147. package/js/static_dependencies/elliptic/lib/elliptic/curve/edwards.js +433 -0
  148. package/js/static_dependencies/elliptic/lib/elliptic/curve/index.js +8 -0
  149. package/js/static_dependencies/elliptic/lib/elliptic/curve/mont.js +180 -0
  150. package/js/static_dependencies/elliptic/lib/elliptic/curve/short.js +938 -0
  151. package/js/static_dependencies/elliptic/lib/elliptic/curves.js +204 -0
  152. package/js/static_dependencies/elliptic/lib/elliptic/ec/index.js +240 -0
  153. package/js/static_dependencies/elliptic/lib/elliptic/ec/key.js +119 -0
  154. package/js/static_dependencies/elliptic/lib/elliptic/ec/signature.js +24 -0
  155. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/index.js +145 -0
  156. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/key.js +100 -0
  157. package/js/static_dependencies/elliptic/lib/elliptic/eddsa/signature.js +65 -0
  158. package/js/static_dependencies/elliptic/lib/elliptic/precomputed/secp256k1.js +780 -0
  159. package/js/static_dependencies/elliptic/lib/elliptic/utils.js +214 -0
  160. package/js/static_dependencies/elliptic/lib/elliptic.js +22 -0
  161. package/js/static_dependencies/elliptic/lib/hmac-drbg/hmac-drbg.js +114 -0
  162. package/js/static_dependencies/fetch-ponyfill/fetch-node.js +39 -0
  163. package/js/static_dependencies/node-fetch/index.js +1564 -0
  164. package/js/static_dependencies/node-rsa/NodeRSA.js +223 -0
  165. package/js/static_dependencies/node-rsa/asn1/ber/errors.js +13 -0
  166. package/js/static_dependencies/node-rsa/asn1/ber/index.js +21 -0
  167. package/js/static_dependencies/node-rsa/asn1/ber/reader.js +262 -0
  168. package/js/static_dependencies/node-rsa/asn1/ber/types.js +36 -0
  169. package/js/static_dependencies/node-rsa/asn1/index.js +17 -0
  170. package/js/static_dependencies/node-rsa/encryptEngines/js.js +34 -0
  171. package/js/static_dependencies/node-rsa/formats/components.js +71 -0
  172. package/js/static_dependencies/node-rsa/formats/formats.js +31 -0
  173. package/js/static_dependencies/node-rsa/formats/pkcs1.js +148 -0
  174. package/js/static_dependencies/node-rsa/formats/pkcs8.js +187 -0
  175. package/js/static_dependencies/node-rsa/libs/jsbn.js +1252 -0
  176. package/js/static_dependencies/node-rsa/libs/rsa.js +147 -0
  177. package/js/static_dependencies/node-rsa/schemes/pkcs1.js +176 -0
  178. package/js/static_dependencies/node-rsa/schemes/schemes.js +21 -0
  179. package/js/static_dependencies/node-rsa/utils.js +98 -0
  180. package/js/static_dependencies/qs/formats.js +18 -0
  181. package/js/static_dependencies/qs/index.js +11 -0
  182. package/js/static_dependencies/qs/parse.js +242 -0
  183. package/js/static_dependencies/qs/stringify.js +269 -0
  184. package/js/static_dependencies/qs/utils.js +230 -0
  185. package/js/stex.js +1925 -0
  186. package/js/test/.eslintrc.js +42 -0
  187. package/js/test/Exchange/test.balance.js +61 -0
  188. package/js/test/Exchange/test.borrowRate.js +32 -0
  189. package/js/test/Exchange/test.currency.js +52 -0
  190. package/js/test/Exchange/test.fetchBalance.js +23 -0
  191. package/js/test/Exchange/test.fetchBorrowInterest.js +59 -0
  192. package/js/test/Exchange/test.fetchBorrowRate.js +32 -0
  193. package/js/test/Exchange/test.fetchBorrowRates.js +28 -0
  194. package/js/test/Exchange/test.fetchClosedOrders.js +32 -0
  195. package/js/test/Exchange/test.fetchCurrencies.js +35 -0
  196. package/js/test/Exchange/test.fetchDeposits.js +31 -0
  197. package/js/test/Exchange/test.fetchFundingFees.js +19 -0
  198. package/js/test/Exchange/test.fetchFundingRateHistory.js +40 -0
  199. package/js/test/Exchange/test.fetchL2OrderBook.js +23 -0
  200. package/js/test/Exchange/test.fetchLedger.js +42 -0
  201. package/js/test/Exchange/test.fetchLeverageTiers.js +33 -0
  202. package/js/test/Exchange/test.fetchMarketLeverageTiers.js +22 -0
  203. package/js/test/Exchange/test.fetchMarkets.js +33 -0
  204. package/js/test/Exchange/test.fetchMyTrades.js +42 -0
  205. package/js/test/Exchange/test.fetchOHLCV.js +46 -0
  206. package/js/test/Exchange/test.fetchOpenOrders.js +36 -0
  207. package/js/test/Exchange/test.fetchOrderBook.js +25 -0
  208. package/js/test/Exchange/test.fetchOrderBooks.js +35 -0
  209. package/js/test/Exchange/test.fetchOrders.js +41 -0
  210. package/js/test/Exchange/test.fetchPositions.js +47 -0
  211. package/js/test/Exchange/test.fetchStatus.js +35 -0
  212. package/js/test/Exchange/test.fetchTicker.js +38 -0
  213. package/js/test/Exchange/test.fetchTickers.js +49 -0
  214. package/js/test/Exchange/test.fetchTrades.js +39 -0
  215. package/js/test/Exchange/test.fetchTradingFee.js +18 -0
  216. package/js/test/Exchange/test.fetchTradingFees.js +22 -0
  217. package/js/test/Exchange/test.fetchTransactions.js +31 -0
  218. package/js/test/Exchange/test.fetchWithdrawals.js +31 -0
  219. package/js/test/Exchange/test.ledgerItem.js +46 -0
  220. package/js/test/Exchange/test.leverageTier.js +33 -0
  221. package/js/test/Exchange/test.loadMarkets.js +35 -0
  222. package/js/test/Exchange/test.market.js +129 -0
  223. package/js/test/Exchange/test.ohlcv.js +33 -0
  224. package/js/test/Exchange/test.order.js +62 -0
  225. package/js/test/Exchange/test.orderbook.js +61 -0
  226. package/js/test/Exchange/test.position.js +21 -0
  227. package/js/test/Exchange/test.throttle.js +94 -0
  228. package/js/test/Exchange/test.ticker.js +95 -0
  229. package/js/test/Exchange/test.trade.js +68 -0
  230. package/js/test/Exchange/test.tradingFee.js +34 -0
  231. package/js/test/Exchange/test.transaction.js +35 -0
  232. package/js/test/base/.eslintrc +38 -0
  233. package/js/test/base/functions/test.crypto.js +110 -0
  234. package/js/test/base/functions/test.datetime.js +62 -0
  235. package/js/test/base/functions/test.generic.js +152 -0
  236. package/js/test/base/functions/test.number.js +362 -0
  237. package/js/test/base/functions/test.time.js +56 -0
  238. package/js/test/base/functions/test.type.js +53 -0
  239. package/js/test/base/test.base.js +193 -0
  240. package/js/test/errors/test.InsufficientFunds.js +86 -0
  241. package/js/test/errors/test.InvalidNonce.js +64 -0
  242. package/js/test/errors/test.InvalidOrder.js +35 -0
  243. package/js/test/errors/test.OrderNotFound.js +39 -0
  244. package/js/test/test.js +426 -0
  245. package/js/test/test.timeout_hang.js +12 -0
  246. package/js/therock.js +1431 -0
  247. package/js/tidebit.js +632 -0
  248. package/js/tidex.js +939 -0
  249. package/js/timex.js +1283 -0
  250. package/js/upbit.js +1622 -0
  251. package/js/vcc.js +1353 -0
  252. package/js/wavesexchange.js +2185 -0
  253. package/js/wazirx.js +732 -0
  254. package/js/whitebit.js +1352 -0
  255. package/js/woo.js +1577 -0
  256. package/js/xena.js +1948 -0
  257. package/js/yobit.js +1129 -0
  258. package/js/zaif.js +647 -0
  259. package/js/zb.js +4088 -0
  260. package/js/zipmex.js +40 -0
  261. package/js/zonda.js +1497 -0
  262. package/multilang.sh +159 -0
  263. package/package.json +591 -0
  264. package/postinstall.js +103 -0
package/js/gateio.js ADDED
@@ -0,0 +1,4174 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const Precise = require ('./base/Precise');
7
+ const { TICK_SIZE } = require ('./base/functions/number');
8
+ const { ExchangeError, BadRequest, ArgumentsRequired, AuthenticationError, PermissionDenied, AccountSuspended, InsufficientFunds, RateLimitExceeded, ExchangeNotAvailable, BadSymbol, InvalidOrder, OrderNotFound, NotSupported, AccountNotEnabled } = require ('./base/errors');
9
+
10
+ module.exports = class gateio extends Exchange {
11
+ describe () {
12
+ return this.deepExtend (super.describe (), {
13
+ 'id': 'gateio',
14
+ 'name': 'Gate.io',
15
+ 'countries': [ 'KR' ],
16
+ 'rateLimit': 10 / 3, // 300 requests per second or 3.33ms
17
+ 'version': 'v4',
18
+ 'certified': true,
19
+ 'pro': true,
20
+ 'urls': {
21
+ 'logo': 'https://user-images.githubusercontent.com/1294454/31784029-0313c702-b509-11e7-9ccc-bc0da6a0e435.jpg',
22
+ 'doc': 'https://www.gate.io/docs/apiv4/en/index.html',
23
+ 'www': 'https://gate.io/',
24
+ 'api': {
25
+ 'public': {
26
+ 'wallet': 'https://api.gateio.ws/api/v4',
27
+ 'futures': 'https://api.gateio.ws/api/v4',
28
+ 'margin': 'https://api.gateio.ws/api/v4',
29
+ 'delivery': 'https://api.gateio.ws/api/v4',
30
+ 'spot': 'https://api.gateio.ws/api/v4',
31
+ 'options': 'https://api.gateio.ws/api/v4',
32
+ },
33
+ 'private': {
34
+ 'withdrawals': 'https://api.gateio.ws/api/v4',
35
+ 'wallet': 'https://api.gateio.ws/api/v4',
36
+ 'futures': 'https://api.gateio.ws/api/v4',
37
+ 'margin': 'https://api.gateio.ws/api/v4',
38
+ 'delivery': 'https://api.gateio.ws/api/v4',
39
+ 'spot': 'https://api.gateio.ws/api/v4',
40
+ 'options': 'https://api.gateio.ws/api/v4',
41
+ },
42
+ },
43
+ 'test': {
44
+ 'public': {
45
+ 'futures': 'https://fx-api-testnet.gateio.ws/api/v4',
46
+ 'delivery': 'https://fx-api-testnet.gateio.ws/api/v4',
47
+ },
48
+ 'private': {
49
+ 'futures': 'https://fx-api-testnet.gateio.ws/api/v4',
50
+ 'delivery': 'https://fx-api-testnet.gateio.ws/api/v4',
51
+ },
52
+ },
53
+ 'referral': {
54
+ 'url': 'https://www.gate.io/ref/2436035',
55
+ 'discount': 0.2,
56
+ },
57
+ },
58
+ 'has': {
59
+ 'CORS': undefined,
60
+ 'spot': true,
61
+ 'margin': true,
62
+ 'swap': true,
63
+ 'future': true,
64
+ 'option': undefined,
65
+ 'cancelAllOrders': true,
66
+ 'cancelOrder': true,
67
+ 'createMarketOrder': false,
68
+ 'createOrder': true,
69
+ 'createPostOnlyOrder': true,
70
+ 'createStopLimitOrder': true,
71
+ 'createStopMarketOrder': false,
72
+ 'createStopOrder': true,
73
+ 'fetchBalance': true,
74
+ 'fetchBorrowRate': false,
75
+ 'fetchBorrowRateHistories': false,
76
+ 'fetchBorrowRateHistory': false,
77
+ 'fetchBorrowRates': false,
78
+ 'fetchClosedOrders': true,
79
+ 'fetchCurrencies': true,
80
+ 'fetchDepositAddress': true,
81
+ 'fetchDeposits': true,
82
+ 'fetchFundingFees': true,
83
+ 'fetchFundingHistory': true,
84
+ 'fetchFundingRate': true,
85
+ 'fetchFundingRateHistory': true,
86
+ 'fetchFundingRates': true,
87
+ 'fetchIndexOHLCV': true,
88
+ 'fetchLeverage': false,
89
+ 'fetchLeverageTiers': true,
90
+ 'fetchMarketLeverageTiers': 'emulated',
91
+ 'fetchMarkets': true,
92
+ 'fetchMarkOHLCV': true,
93
+ 'fetchMyTrades': true,
94
+ 'fetchNetworkDepositAddress': true,
95
+ 'fetchOHLCV': true,
96
+ 'fetchOpenOrders': true,
97
+ 'fetchOrder': true,
98
+ 'fetchOrderBook': true,
99
+ 'fetchPositions': true,
100
+ 'fetchPremiumIndexOHLCV': false,
101
+ 'fetchTicker': true,
102
+ 'fetchTickers': true,
103
+ 'fetchTime': false,
104
+ 'fetchTrades': true,
105
+ 'fetchTradingFee': true,
106
+ 'fetchTradingFees': true,
107
+ 'fetchWithdrawals': true,
108
+ 'setLeverage': true,
109
+ 'setMarginMode': false,
110
+ 'transfer': true,
111
+ 'withdraw': true,
112
+ },
113
+ 'api': {
114
+ 'public': {
115
+ 'wallet': {
116
+ 'get': {
117
+ 'wallet/currency_chains': 1.5,
118
+ },
119
+ },
120
+ 'spot': {
121
+ 'get': {
122
+ 'currencies': 1,
123
+ 'currencies/{currency}': 1,
124
+ 'currency_pairs': 1,
125
+ 'currency_pairs/{currency_pair}': 1,
126
+ 'tickers': 1,
127
+ 'order_book': 1,
128
+ 'trades': 1,
129
+ 'candlesticks': 1,
130
+ },
131
+ },
132
+ 'margin': {
133
+ 'get': {
134
+ 'currency_pairs': 1,
135
+ 'currency_pairs/{currency_pair}': 1,
136
+ 'cross/currencies': 1,
137
+ 'cross/currencies/{currency}': 1,
138
+ 'funding_book': 1,
139
+ },
140
+ },
141
+ 'futures': {
142
+ 'get': {
143
+ '{settle}/contracts': 1.5,
144
+ '{settle}/contracts/{contract}': 1.5,
145
+ '{settle}/order_book': 1.5,
146
+ '{settle}/trades': 1.5,
147
+ '{settle}/candlesticks': 1.5,
148
+ '{settle}/tickers': 1.5,
149
+ '{settle}/funding_rate': 1.5,
150
+ '{settle}/insurance': 1.5,
151
+ '{settle}/contract_stats': 1.5,
152
+ '{settle}/liq_orders': 1.5,
153
+ },
154
+ },
155
+ 'delivery': {
156
+ 'get': {
157
+ '{settle}/contracts': 1.5,
158
+ '{settle}/contracts/{contract}': 1.5,
159
+ '{settle}/order_book': 1.5,
160
+ '{settle}/trades': 1.5,
161
+ '{settle}/candlesticks': 1.5,
162
+ '{settle}/tickers': 1.5,
163
+ '{settle}/insurance': 1.5,
164
+ },
165
+ },
166
+ 'options': {
167
+ 'get': {
168
+ 'underlyings': 1.5,
169
+ 'expirations': 1.5,
170
+ 'contracts': 1.5,
171
+ 'contracts/{contract}': 1.5,
172
+ 'settlements': 1.5,
173
+ 'settlements/{contract}': 1.5,
174
+ 'order_book': 1.5,
175
+ 'tickers': 1.5,
176
+ 'underlying/tickers/{underlying}': 1.5,
177
+ 'candlesticks': 1.5,
178
+ 'underlying/candlesticks': 1.5,
179
+ 'trades': 1.5,
180
+ },
181
+ },
182
+ },
183
+ 'private': {
184
+ 'withdrawals': {
185
+ 'post': {
186
+ '': 3000, // 3000 = 10 seconds
187
+ },
188
+ 'delete': {
189
+ '{withdrawal_id}': 300,
190
+ },
191
+ },
192
+ 'wallet': {
193
+ 'get': {
194
+ 'deposit_address': 300,
195
+ 'withdrawals': 300,
196
+ 'deposits': 300,
197
+ 'sub_account_transfers': 300,
198
+ 'withdraw_status': 300,
199
+ 'sub_account_balances': 300,
200
+ 'fee': 300,
201
+ 'total_balance': 300,
202
+ },
203
+ 'post': {
204
+ 'transfers': 300,
205
+ 'sub_account_transfers': 300,
206
+ },
207
+ },
208
+ 'spot': {
209
+ 'get': {
210
+ 'accounts': 1,
211
+ 'open_orders': 1,
212
+ 'orders': 1,
213
+ 'orders/{order_id}': 1,
214
+ 'my_trades': 1,
215
+ 'price_orders': 1,
216
+ 'price_orders/{order_id}': 1,
217
+ },
218
+ 'post': {
219
+ 'batch_orders': 1,
220
+ 'orders': 1,
221
+ 'cancel_batch_orders': 1,
222
+ 'price_orders': 1,
223
+ },
224
+ 'delete': {
225
+ 'orders': 1,
226
+ 'orders/{order_id}': 1,
227
+ 'price_orders': 1,
228
+ 'price_orders/{order_id}': 1,
229
+ },
230
+ },
231
+ 'margin': {
232
+ 'get': {
233
+ 'accounts': 1.5,
234
+ 'account_book': 1.5,
235
+ 'funding_accounts': 1.5,
236
+ 'loans': 1.5,
237
+ 'loans/{loan_id}': 1.5,
238
+ 'loans/{loan_id}/repayment': 1.5,
239
+ 'loan_records': 1.5,
240
+ 'loan_records/{load_record_id}': 1.5,
241
+ 'auto_repay': 1.5,
242
+ 'transferable': 1.5,
243
+ 'cross/accounts': 1.5,
244
+ 'cross/account_book': 1.5,
245
+ 'cross/loans': 1.5,
246
+ 'cross/loans/{loan_id}': 1.5,
247
+ 'cross/loans/repayments': 1.5,
248
+ 'cross/transferable': 1.5,
249
+ 'loan_records/{loan_record_id}': 1.5,
250
+ 'borrowable': 1.5,
251
+ 'cross/repayments': 1.5,
252
+ 'cross/borrowable': 1.5,
253
+ },
254
+ 'post': {
255
+ 'loans': 1.5,
256
+ 'merged_loans': 1.5,
257
+ 'loans/{loan_id}/repayment': 1.5,
258
+ 'auto_repay': 1.5,
259
+ 'cross/loans': 1.5,
260
+ 'cross/loans/repayments': 1.5,
261
+ 'cross/repayments': 1.5,
262
+ },
263
+ 'patch': {
264
+ 'loans/{loan_id}': 1.5,
265
+ 'loan_records/{loan_record_id}': 1.5,
266
+ },
267
+ 'delete': {
268
+ 'loans/{loan_id}': 1.5,
269
+ },
270
+ },
271
+ 'futures': {
272
+ 'get': {
273
+ '{settle}/accounts': 1.5,
274
+ '{settle}/account_book': 1.5,
275
+ '{settle}/positions': 1.5,
276
+ '{settle}/positions/{contract}': 1.5,
277
+ '{settle}/orders': 1.5,
278
+ '{settle}/orders/{order_id}': 1.5,
279
+ '{settle}/my_trades': 1.5,
280
+ '{settle}/position_close': 1.5,
281
+ '{settle}/liquidates': 1.5,
282
+ '{settle}/price_orders': 1.5,
283
+ '{settle}/price_orders/{order_id}': 1.5,
284
+ '{settle}/dual_comp/positions/{contract}': 1.5,
285
+ },
286
+ 'post': {
287
+ '{settle}/positions/{contract}/margin': 1.5,
288
+ '{settle}/positions/{contract}/leverage': 1.5,
289
+ '{settle}/positions/{contract}/risk_limit': 1.5,
290
+ '{settle}/dual_mode': 1.5,
291
+ '{settle}/dual_comp/positions/{contract}': 1.5,
292
+ '{settle}/dual_comp/positions/{contract}/margin': 1.5,
293
+ '{settle}/dual_comp/positions/{contract}/leverage': 1.5,
294
+ '{settle}/dual_comp/positions/{contract}/risk_limit': 1.5,
295
+ '{settle}/orders': 1.5,
296
+ '{settle}/price_orders': 1.5,
297
+ },
298
+ 'delete': {
299
+ '{settle}/orders': 1.5,
300
+ '{settle}/orders/{order_id}': 1.5,
301
+ '{settle}/price_orders': 1.5,
302
+ '{settle}/price_orders/{order_id}': 1.5,
303
+ },
304
+ },
305
+ 'delivery': {
306
+ 'get': {
307
+ '{settle}/accounts': 1.5,
308
+ '{settle}/account_book': 1.5,
309
+ '{settle}/positions': 1.5,
310
+ '{settle}/positions/{contract}': 1.5,
311
+ '{settle}/orders': 1.5,
312
+ '{settle}/orders/{order_id}': 1.5,
313
+ '{settle}/my_trades': 1.5,
314
+ '{settle}/position_close': 1.5,
315
+ '{settle}/liquidates': 1.5,
316
+ '{settle}/price_orders': 1.5,
317
+ '{settle}/price_orders/{order_id}': 1.5,
318
+ '{settle}/settlements': 1.5,
319
+ },
320
+ 'post': {
321
+ '{settle}/positions/{contract}/margin': 1.5,
322
+ '{settle}/positions/{contract}/leverage': 1.5,
323
+ '{settle}/positions/{contract}/risk_limit': 1.5,
324
+ '{settle}/orders': 1.5,
325
+ '{settle}/price_orders': 1.5,
326
+ },
327
+ 'delete': {
328
+ '{settle}/orders': 1.5,
329
+ '{settle}/orders/{order_id}': 1.5,
330
+ '{settle}/price_orders': 1.5,
331
+ '{settle}/price_orders/{order_id}': 1.5,
332
+ },
333
+ },
334
+ 'options': {
335
+ 'get': {
336
+ 'accounts': 1.5,
337
+ 'account_book': 1.5,
338
+ 'positions': 1.5,
339
+ 'positions/{contract}': 1.5,
340
+ 'position_close': 1.5,
341
+ 'orders': 1.5,
342
+ 'orders/{order_id}': 1.5,
343
+ 'my_trades': 1.5,
344
+ },
345
+ 'post': {
346
+ 'orders': 1.5,
347
+ },
348
+ 'delete': {
349
+ 'orders': 1.5,
350
+ 'orders/{order_id}': 1.5,
351
+ },
352
+ },
353
+ },
354
+ },
355
+ 'timeframes': {
356
+ '10s': '10s',
357
+ '1m': '1m',
358
+ '5m': '5m',
359
+ '15m': '15m',
360
+ '30m': '30m',
361
+ '1h': '1h',
362
+ '4h': '4h',
363
+ '8h': '8h',
364
+ '1d': '1d',
365
+ '7d': '7d',
366
+ '1w': '7d',
367
+ },
368
+ // copied from gateiov2
369
+ 'commonCurrencies': {
370
+ '88MPH': 'MPH',
371
+ 'AXIS': 'Axis DeFi',
372
+ 'BIFI': 'Bitcoin File',
373
+ 'BOX': 'DefiBox',
374
+ 'BTCBEAR': 'BEAR',
375
+ 'BTCBULL': 'BULL',
376
+ 'BYN': 'BeyondFi',
377
+ 'EGG': 'Goose Finance',
378
+ 'GTC': 'Game.com', // conflict with Gitcoin and Gastrocoin
379
+ 'GTC_HT': 'Game.com HT',
380
+ 'GTC_BSC': 'Game.com BSC',
381
+ 'HIT': 'HitChain',
382
+ 'MM': 'Million', // conflict with MilliMeter
383
+ 'MPH': 'Morpher', // conflict with 88MPH
384
+ 'RAI': 'Rai Reflex Index', // conflict with RAI Finance
385
+ 'SBTC': 'Super Bitcoin',
386
+ 'TNC': 'Trinity Network Credit',
387
+ 'TON': 'TONToken',
388
+ 'VAI': 'VAIOT',
389
+ },
390
+ 'requiredCredentials': {
391
+ 'apiKey': true,
392
+ 'secret': true,
393
+ },
394
+ 'headers': {
395
+ 'X-Gate-Channel-Id': 'ccxt',
396
+ },
397
+ 'options': {
398
+ 'createOrder': {
399
+ 'expiration': 86400, // for conditional orders
400
+ },
401
+ 'networks': {
402
+ 'TRC20': 'TRX',
403
+ 'ERC20': 'ETH',
404
+ 'BEP20': 'BSC',
405
+ },
406
+ 'accountsByType': {
407
+ 'funding': 'spot',
408
+ 'spot': 'spot',
409
+ 'margin': 'margin',
410
+ 'cross_margin': 'cross_margin',
411
+ 'cross': 'cross_margin',
412
+ 'isolated': 'margin',
413
+ 'swap': 'futures',
414
+ 'future': 'delivery',
415
+ 'futures': 'futures',
416
+ 'delivery': 'delivery',
417
+ },
418
+ 'defaultType': 'spot',
419
+ 'swap': {
420
+ 'fetchMarkets': {
421
+ 'settlementCurrencies': [ 'usdt', 'btc' ],
422
+ },
423
+ },
424
+ 'future': {
425
+ 'fetchMarkets': {
426
+ 'settlementCurrencies': [ 'usdt', 'btc' ],
427
+ },
428
+ },
429
+ },
430
+ 'precisionMode': TICK_SIZE,
431
+ 'fees': {
432
+ 'trading': {
433
+ 'tierBased': true,
434
+ 'feeSide': 'get',
435
+ 'percentage': true,
436
+ 'maker': this.parseNumber ('0.002'),
437
+ 'taker': this.parseNumber ('0.002'),
438
+ 'tiers': {
439
+ // volume is in BTC
440
+ 'maker': [
441
+ [ this.parseNumber ('0'), this.parseNumber ('0.002') ],
442
+ [ this.parseNumber ('1.5'), this.parseNumber ('0.00185') ],
443
+ [ this.parseNumber ('3'), this.parseNumber ('0.00175') ],
444
+ [ this.parseNumber ('6'), this.parseNumber ('0.00165') ],
445
+ [ this.parseNumber ('12.5'), this.parseNumber ('0.00155') ],
446
+ [ this.parseNumber ('25'), this.parseNumber ('0.00145') ],
447
+ [ this.parseNumber ('75'), this.parseNumber ('0.00135') ],
448
+ [ this.parseNumber ('200'), this.parseNumber ('0.00125') ],
449
+ [ this.parseNumber ('500'), this.parseNumber ('0.00115') ],
450
+ [ this.parseNumber ('1250'), this.parseNumber ('0.00105') ],
451
+ [ this.parseNumber ('2500'), this.parseNumber ('0.00095') ],
452
+ [ this.parseNumber ('3000'), this.parseNumber ('0.00085') ],
453
+ [ this.parseNumber ('6000'), this.parseNumber ('0.00075') ],
454
+ [ this.parseNumber ('11000'), this.parseNumber ('0.00065') ],
455
+ [ this.parseNumber ('20000'), this.parseNumber ('0.00055') ],
456
+ [ this.parseNumber ('40000'), this.parseNumber ('0.00055') ],
457
+ [ this.parseNumber ('75000'), this.parseNumber ('0.00055') ],
458
+ ],
459
+ 'taker': [
460
+ [ this.parseNumber ('0'), this.parseNumber ('0.002') ],
461
+ [ this.parseNumber ('1.5'), this.parseNumber ('0.00195') ],
462
+ [ this.parseNumber ('3'), this.parseNumber ('0.00185') ],
463
+ [ this.parseNumber ('6'), this.parseNumber ('0.00175') ],
464
+ [ this.parseNumber ('12.5'), this.parseNumber ('0.00165') ],
465
+ [ this.parseNumber ('25'), this.parseNumber ('0.00155') ],
466
+ [ this.parseNumber ('75'), this.parseNumber ('0.00145') ],
467
+ [ this.parseNumber ('200'), this.parseNumber ('0.00135') ],
468
+ [ this.parseNumber ('500'), this.parseNumber ('0.00125') ],
469
+ [ this.parseNumber ('1250'), this.parseNumber ('0.00115') ],
470
+ [ this.parseNumber ('2500'), this.parseNumber ('0.00105') ],
471
+ [ this.parseNumber ('3000'), this.parseNumber ('0.00095') ],
472
+ [ this.parseNumber ('6000'), this.parseNumber ('0.00085') ],
473
+ [ this.parseNumber ('11000'), this.parseNumber ('0.00075') ],
474
+ [ this.parseNumber ('20000'), this.parseNumber ('0.00065') ],
475
+ [ this.parseNumber ('40000'), this.parseNumber ('0.00065') ],
476
+ [ this.parseNumber ('75000'), this.parseNumber ('0.00065') ],
477
+ ],
478
+ },
479
+ },
480
+ 'swap': {
481
+ 'tierBased': true,
482
+ 'feeSide': 'base',
483
+ 'percentage': true,
484
+ 'maker': this.parseNumber ('0.0'),
485
+ 'taker': this.parseNumber ('0.0005'),
486
+ 'tiers': {
487
+ 'maker': [
488
+ [ this.parseNumber ('0'), this.parseNumber ('0.0000') ],
489
+ [ this.parseNumber ('1.5'), this.parseNumber ('-0.00005') ],
490
+ [ this.parseNumber ('3'), this.parseNumber ('-0.00005') ],
491
+ [ this.parseNumber ('6'), this.parseNumber ('-0.00005') ],
492
+ [ this.parseNumber ('12.5'), this.parseNumber ('-0.00005') ],
493
+ [ this.parseNumber ('25'), this.parseNumber ('-0.00005') ],
494
+ [ this.parseNumber ('75'), this.parseNumber ('-0.00005') ],
495
+ [ this.parseNumber ('200'), this.parseNumber ('-0.00005') ],
496
+ [ this.parseNumber ('500'), this.parseNumber ('-0.00005') ],
497
+ [ this.parseNumber ('1250'), this.parseNumber ('-0.00005') ],
498
+ [ this.parseNumber ('2500'), this.parseNumber ('-0.00005') ],
499
+ [ this.parseNumber ('3000'), this.parseNumber ('-0.00008') ],
500
+ [ this.parseNumber ('6000'), this.parseNumber ('-0.01000') ],
501
+ [ this.parseNumber ('11000'), this.parseNumber ('-0.01002') ],
502
+ [ this.parseNumber ('20000'), this.parseNumber ('-0.01005') ],
503
+ [ this.parseNumber ('40000'), this.parseNumber ('-0.02000') ],
504
+ [ this.parseNumber ('75000'), this.parseNumber ('-0.02005') ],
505
+ ],
506
+ 'taker': [
507
+ [ this.parseNumber ('0'), this.parseNumber ('0.00050') ],
508
+ [ this.parseNumber ('1.5'), this.parseNumber ('0.00048') ],
509
+ [ this.parseNumber ('3'), this.parseNumber ('0.00046') ],
510
+ [ this.parseNumber ('6'), this.parseNumber ('0.00044') ],
511
+ [ this.parseNumber ('12.5'), this.parseNumber ('0.00042') ],
512
+ [ this.parseNumber ('25'), this.parseNumber ('0.00040') ],
513
+ [ this.parseNumber ('75'), this.parseNumber ('0.00038') ],
514
+ [ this.parseNumber ('200'), this.parseNumber ('0.00036') ],
515
+ [ this.parseNumber ('500'), this.parseNumber ('0.00034') ],
516
+ [ this.parseNumber ('1250'), this.parseNumber ('0.00032') ],
517
+ [ this.parseNumber ('2500'), this.parseNumber ('0.00030') ],
518
+ [ this.parseNumber ('3000'), this.parseNumber ('0.00030') ],
519
+ [ this.parseNumber ('6000'), this.parseNumber ('0.00030') ],
520
+ [ this.parseNumber ('11000'), this.parseNumber ('0.00030') ],
521
+ [ this.parseNumber ('20000'), this.parseNumber ('0.00030') ],
522
+ [ this.parseNumber ('40000'), this.parseNumber ('0.00030') ],
523
+ [ this.parseNumber ('75000'), this.parseNumber ('0.00030') ],
524
+ ],
525
+ },
526
+ },
527
+ },
528
+ // https://www.gate.io/docs/apiv4/en/index.html#label-list
529
+ 'exceptions': {
530
+ 'exact': {
531
+ 'INVALID_PARAM_VALUE': BadRequest,
532
+ 'INVALID_PROTOCOL': BadRequest,
533
+ 'INVALID_ARGUMENT': BadRequest,
534
+ 'INVALID_REQUEST_BODY': BadRequest,
535
+ 'MISSING_REQUIRED_PARAM': ArgumentsRequired,
536
+ 'BAD_REQUEST': BadRequest,
537
+ 'INVALID_CONTENT_TYPE': BadRequest,
538
+ 'NOT_ACCEPTABLE': BadRequest,
539
+ 'METHOD_NOT_ALLOWED': BadRequest,
540
+ 'NOT_FOUND': ExchangeError,
541
+ 'INVALID_CREDENTIALS': AuthenticationError,
542
+ 'INVALID_KEY': AuthenticationError,
543
+ 'IP_FORBIDDEN': AuthenticationError,
544
+ 'READ_ONLY': PermissionDenied,
545
+ 'INVALID_SIGNATURE': AuthenticationError,
546
+ 'MISSING_REQUIRED_HEADER': AuthenticationError,
547
+ 'REQUEST_EXPIRED': AuthenticationError,
548
+ 'ACCOUNT_LOCKED': AccountSuspended,
549
+ 'FORBIDDEN': PermissionDenied,
550
+ 'SUB_ACCOUNT_NOT_FOUND': ExchangeError,
551
+ 'SUB_ACCOUNT_LOCKED': AccountSuspended,
552
+ 'MARGIN_BALANCE_EXCEPTION': ExchangeError,
553
+ 'MARGIN_TRANSFER_FAILED': ExchangeError,
554
+ 'TOO_MUCH_FUTURES_AVAILABLE': ExchangeError,
555
+ 'FUTURES_BALANCE_NOT_ENOUGH': InsufficientFunds,
556
+ 'ACCOUNT_EXCEPTION': ExchangeError,
557
+ 'SUB_ACCOUNT_TRANSFER_FAILED': ExchangeError,
558
+ 'ADDRESS_NOT_USED': ExchangeError,
559
+ 'TOO_FAST': RateLimitExceeded,
560
+ 'WITHDRAWAL_OVER_LIMIT': ExchangeError,
561
+ 'API_WITHDRAW_DISABLED': ExchangeNotAvailable,
562
+ 'INVALID_WITHDRAW_ID': ExchangeError,
563
+ 'INVALID_WITHDRAW_CANCEL_STATUS': ExchangeError,
564
+ 'INVALID_PRECISION': InvalidOrder,
565
+ 'INVALID_CURRENCY': BadSymbol,
566
+ 'INVALID_CURRENCY_PAIR': BadSymbol,
567
+ 'POC_FILL_IMMEDIATELY': ExchangeError,
568
+ 'ORDER_NOT_FOUND': OrderNotFound,
569
+ 'CLIENT_ID_NOT_FOUND': OrderNotFound,
570
+ 'ORDER_CLOSED': InvalidOrder,
571
+ 'ORDER_CANCELLED': InvalidOrder,
572
+ 'QUANTITY_NOT_ENOUGH': InvalidOrder,
573
+ 'BALANCE_NOT_ENOUGH': InsufficientFunds,
574
+ 'MARGIN_NOT_SUPPORTED': InvalidOrder,
575
+ 'MARGIN_BALANCE_NOT_ENOUGH': InsufficientFunds,
576
+ 'AMOUNT_TOO_LITTLE': InvalidOrder,
577
+ 'AMOUNT_TOO_MUCH': InvalidOrder,
578
+ 'REPEATED_CREATION': InvalidOrder,
579
+ 'LOAN_NOT_FOUND': OrderNotFound,
580
+ 'LOAN_RECORD_NOT_FOUND': OrderNotFound,
581
+ 'NO_MATCHED_LOAN': ExchangeError,
582
+ 'NOT_MERGEABLE': ExchangeError,
583
+ 'NO_CHANGE': ExchangeError,
584
+ 'REPAY_TOO_MUCH': ExchangeError,
585
+ 'TOO_MANY_CURRENCY_PAIRS': InvalidOrder,
586
+ 'TOO_MANY_ORDERS': InvalidOrder,
587
+ 'MIXED_ACCOUNT_TYPE': InvalidOrder,
588
+ 'AUTO_BORROW_TOO_MUCH': ExchangeError,
589
+ 'TRADE_RESTRICTED': InsufficientFunds,
590
+ 'USER_NOT_FOUND': AccountNotEnabled,
591
+ 'CONTRACT_NO_COUNTER': ExchangeError,
592
+ 'CONTRACT_NOT_FOUND': BadSymbol,
593
+ 'RISK_LIMIT_EXCEEDED': ExchangeError,
594
+ 'INSUFFICIENT_AVAILABLE': InsufficientFunds,
595
+ 'LIQUIDATE_IMMEDIATELY': InvalidOrder,
596
+ 'LEVERAGE_TOO_HIGH': InvalidOrder,
597
+ 'LEVERAGE_TOO_LOW': InvalidOrder,
598
+ 'ORDER_NOT_OWNED': ExchangeError,
599
+ 'ORDER_FINISHED': ExchangeError,
600
+ 'POSITION_CROSS_MARGIN': ExchangeError,
601
+ 'POSITION_IN_LIQUIDATION': ExchangeError,
602
+ 'POSITION_IN_CLOSE': ExchangeError,
603
+ 'POSITION_EMPTY': InvalidOrder,
604
+ 'REMOVE_TOO_MUCH': ExchangeError,
605
+ 'RISK_LIMIT_NOT_MULTIPLE': ExchangeError,
606
+ 'RISK_LIMIT_TOO_HIGH': ExchangeError,
607
+ 'RISK_LIMIT_TOO_lOW': ExchangeError,
608
+ 'PRICE_TOO_DEVIATED': InvalidOrder,
609
+ 'SIZE_TOO_LARGE': InvalidOrder,
610
+ 'SIZE_TOO_SMALL': InvalidOrder,
611
+ 'PRICE_OVER_LIQUIDATION': InvalidOrder,
612
+ 'PRICE_OVER_BANKRUPT': InvalidOrder,
613
+ 'ORDER_POC_IMMEDIATE': InvalidOrder,
614
+ 'INCREASE_POSITION': InvalidOrder,
615
+ 'CONTRACT_IN_DELISTING': ExchangeError,
616
+ 'INTERNAL': ExchangeNotAvailable,
617
+ 'SERVER_ERROR': ExchangeNotAvailable,
618
+ 'TOO_BUSY': ExchangeNotAvailable,
619
+ 'CROSS_ACCOUNT_NOT_FOUND': ExchangeError,
620
+ },
621
+ },
622
+ 'broad': {},
623
+ });
624
+ }
625
+
626
+ async fetchMarkets (params = {}) {
627
+ let result = [];
628
+ const [ type, query ] = this.handleMarketTypeAndParams ('fetchMarkets', undefined, params);
629
+ if (type === 'spot' || type === 'margin') {
630
+ result = await this.fetchSpotMarkets (query);
631
+ }
632
+ if (type === 'swap' || type === 'future') {
633
+ result = await this.fetchContractMarkets (query); // futures and swaps
634
+ }
635
+ if (type === 'option') {
636
+ result = await this.fetchOptionMarkets (query);
637
+ }
638
+ const resultLength = result.length;
639
+ if (resultLength === 0) {
640
+ throw new ExchangeError (this.id + " does not support '" + type + "' type, set exchange.options['defaultType'] to " + "'spot', 'margin', 'swap', 'future' or 'option'"); // eslint-disable-line quotes
641
+ }
642
+ return result;
643
+ }
644
+
645
+ async fetchSpotMarkets (params) {
646
+ const marginResponse = await this.publicMarginGetCurrencyPairs (params);
647
+ const spotMarketsResponse = await this.publicSpotGetCurrencyPairs (params);
648
+ const marginMarkets = this.indexBy (marginResponse, 'id');
649
+ //
650
+ // Spot
651
+ //
652
+ // [
653
+ // {
654
+ // "id": "QTUM_ETH",
655
+ // "base": "QTUM",
656
+ // "quote": "ETH",
657
+ // "fee": "0.2",
658
+ // "min_base_amount": "0.01",
659
+ // "min_quote_amount": "0.001",
660
+ // "amount_precision": 3,
661
+ // "precision": 6,
662
+ // "trade_status": "tradable",
663
+ // "sell_start": 0,
664
+ // "buy_start": 0
665
+ // }
666
+ // ]
667
+ //
668
+ // Margin
669
+ //
670
+ // [
671
+ // {
672
+ // "id": "ETH_USDT",
673
+ // "base": "ETH",
674
+ // "quote": "USDT",
675
+ // "leverage": 3,
676
+ // "min_base_amount": "0.01",
677
+ // "min_quote_amount": "100",
678
+ // "max_quote_amount": "1000000"
679
+ // }
680
+ // ]
681
+ //
682
+ const result = [];
683
+ for (let i = 0; i < spotMarketsResponse.length; i++) {
684
+ const spotMarket = spotMarketsResponse[i];
685
+ const id = this.safeString (spotMarket, 'id');
686
+ const marginMarket = this.safeValue (marginMarkets, id);
687
+ const market = this.deepExtend (marginMarket, spotMarket);
688
+ const [ baseId, quoteId ] = id.split ('_');
689
+ const base = this.safeCurrencyCode (baseId);
690
+ const quote = this.safeCurrencyCode (quoteId);
691
+ const takerPercent = this.safeString (market, 'fee');
692
+ const makerPercent = this.safeString (market, 'maker_fee_rate', takerPercent);
693
+ const amountPrecisionString = this.safeString (market, 'amount_precision');
694
+ const pricePrecisionString = this.safeString (market, 'precision');
695
+ const tradeStatus = this.safeString (market, 'trade_status');
696
+ const leverage = this.safeNumber (market, 'leverage');
697
+ const defaultMinAmountLimit = this.parseNumber (this.parsePrecision (amountPrecisionString));
698
+ const margin = leverage !== undefined;
699
+ result.push ({
700
+ 'id': id,
701
+ 'symbol': base + '/' + quote,
702
+ 'base': base,
703
+ 'quote': quote,
704
+ 'settle': undefined,
705
+ 'baseId': baseId,
706
+ 'quoteId': quoteId,
707
+ 'settleId': undefined,
708
+ 'type': 'spot',
709
+ 'spot': true,
710
+ 'margin': margin,
711
+ 'swap': false,
712
+ 'future': false,
713
+ 'option': false,
714
+ 'active': (tradeStatus === 'tradable'),
715
+ 'contract': false,
716
+ 'linear': undefined,
717
+ 'inverse': undefined,
718
+ // Fee is in %, so divide by 100
719
+ 'taker': this.parseNumber (Precise.stringDiv (takerPercent, '100')),
720
+ 'maker': this.parseNumber (Precise.stringDiv (makerPercent, '100')),
721
+ 'contractSize': undefined,
722
+ 'expiry': undefined,
723
+ 'expiryDatetime': undefined,
724
+ 'strike': undefined,
725
+ 'optionType': undefined,
726
+ 'precision': {
727
+ 'amount': this.parseNumber (this.parsePrecision (amountPrecisionString)),
728
+ 'price': this.parseNumber (this.parsePrecision (pricePrecisionString)),
729
+ },
730
+ 'limits': {
731
+ 'leverage': {
732
+ 'min': this.parseNumber ('1'),
733
+ 'max': this.safeNumber (market, 'leverage', 1),
734
+ },
735
+ 'amount': {
736
+ 'min': this.safeNumber (spotMarket, 'min_base_amount', defaultMinAmountLimit),
737
+ 'max': undefined,
738
+ },
739
+ 'price': {
740
+ 'min': undefined,
741
+ 'max': undefined,
742
+ },
743
+ 'cost': {
744
+ 'min': this.safeNumber (market, 'min_quote_amount'),
745
+ 'max': this.safeNumber (market, 'max_quote_amount'),
746
+ },
747
+ },
748
+ 'info': market,
749
+ });
750
+ }
751
+ return result;
752
+ }
753
+
754
+ async fetchContractMarkets (params) {
755
+ const result = [];
756
+ const swapSettlementCurrencies = this.getSettlementCurrencies ('swap', 'fetchMarkets');
757
+ const futureSettlementCurrencies = this.getSettlementCurrencies ('future', 'fetchMarkets');
758
+ for (let c = 0; c < swapSettlementCurrencies.length; c++) {
759
+ const settleId = swapSettlementCurrencies[c];
760
+ const query = params;
761
+ query['settle'] = settleId;
762
+ const response = await this.publicFuturesGetSettleContracts (query);
763
+ for (let i = 0; i < response.length; i++) {
764
+ const parsedMarket = this.parseContractMarket (response[i], settleId);
765
+ result.push (parsedMarket);
766
+ }
767
+ }
768
+ for (let c = 0; c < futureSettlementCurrencies.length; c++) {
769
+ const settleId = futureSettlementCurrencies[c];
770
+ const query = params;
771
+ query['settle'] = settleId;
772
+ const response = await this.publicDeliveryGetSettleContracts (query);
773
+ for (let i = 0; i < response.length; i++) {
774
+ const parsedMarket = this.parseContractMarket (response[i], settleId);
775
+ result.push (parsedMarket);
776
+ }
777
+ }
778
+ return result;
779
+ }
780
+
781
+ parseContractMarket (market, settleId) {
782
+ //
783
+ // Perpetual swap
784
+ //
785
+ // {
786
+ // "name": "BTC_USDT",
787
+ // "type": "direct",
788
+ // "quanto_multiplier": "0.0001",
789
+ // "ref_discount_rate": "0",
790
+ // "order_price_deviate": "0.5",
791
+ // "maintenance_rate": "0.005",
792
+ // "mark_type": "index",
793
+ // "last_price": "38026",
794
+ // "mark_price": "37985.6",
795
+ // "index_price": "37954.92",
796
+ // "funding_rate_indicative": "0.000219",
797
+ // "mark_price_round": "0.01",
798
+ // "funding_offset": 0,
799
+ // "in_delisting": false,
800
+ // "risk_limit_base": "1000000",
801
+ // "interest_rate": "0.0003",
802
+ // "order_price_round": "0.1",
803
+ // "order_size_min": 1,
804
+ // "ref_rebate_rate": "0.2",
805
+ // "funding_interval": 28800,
806
+ // "risk_limit_step": "1000000",
807
+ // "leverage_min": "1",
808
+ // "leverage_max": "100",
809
+ // "risk_limit_max": "8000000",
810
+ // "maker_fee_rate": "-0.00025",
811
+ // "taker_fee_rate": "0.00075",
812
+ // "funding_rate": "0.002053",
813
+ // "order_size_max": 1000000,
814
+ // "funding_next_apply": 1610035200,
815
+ // "short_users": 977,
816
+ // "config_change_time": 1609899548,
817
+ // "trade_size": 28530850594,
818
+ // "position_size": 5223816,
819
+ // "long_users": 455,
820
+ // "funding_impact_value": "60000",
821
+ // "orders_limit": 50,
822
+ // "trade_id": 10851092,
823
+ // "orderbook_id": 2129638396
824
+ // }
825
+ //
826
+ // Delivery Futures
827
+ //
828
+ // {
829
+ // "name": "BTC_USDT_20200814",
830
+ // "underlying": "BTC_USDT",
831
+ // "cycle": "WEEKLY",
832
+ // "type": "direct",
833
+ // "quanto_multiplier": "0.0001",
834
+ // "mark_type": "index",
835
+ // "last_price": "9017",
836
+ // "mark_price": "9019",
837
+ // "index_price": "9005.3",
838
+ // "basis_rate": "0.185095",
839
+ // "basis_value": "13.7",
840
+ // "basis_impact_value": "100000",
841
+ // "settle_price": "0",
842
+ // "settle_price_interval": 60,
843
+ // "settle_price_duration": 1800,
844
+ // "settle_fee_rate": "0.0015",
845
+ // "expire_time": 1593763200,
846
+ // "order_price_round": "0.1",
847
+ // "mark_price_round": "0.1",
848
+ // "leverage_min": "1",
849
+ // "leverage_max": "100",
850
+ // "maintenance_rate": "1000000",
851
+ // "risk_limit_base": "140.726652109199",
852
+ // "risk_limit_step": "1000000",
853
+ // "risk_limit_max": "8000000",
854
+ // "maker_fee_rate": "-0.00025",
855
+ // "taker_fee_rate": "0.00075",
856
+ // "ref_discount_rate": "0",
857
+ // "ref_rebate_rate": "0.2",
858
+ // "order_price_deviate": "0.5",
859
+ // "order_size_min": 1,
860
+ // "order_size_max": 1000000,
861
+ // "orders_limit": 50,
862
+ // "orderbook_id": 63,
863
+ // "trade_id": 26,
864
+ // "trade_size": 435,
865
+ // "position_size": 130,
866
+ // "config_change_time": 1593158867,
867
+ // "in_delisting": false
868
+ // }
869
+ //
870
+ const id = this.safeString (market, 'name');
871
+ const parts = id.split ('_');
872
+ const baseId = this.safeString (parts, 0);
873
+ const quoteId = this.safeString (parts, 1);
874
+ const date = this.safeString (parts, 2);
875
+ const base = this.safeCurrencyCode (baseId);
876
+ const quote = this.safeCurrencyCode (quoteId);
877
+ const settle = this.safeCurrencyCode (settleId);
878
+ const expiry = this.safeTimestamp (market, 'expire_time');
879
+ let symbol = '';
880
+ let marketType = 'swap';
881
+ if (date !== undefined) {
882
+ symbol = base + '/' + quote + ':' + settle + '-' + this.yymmdd (expiry, '');
883
+ marketType = 'future';
884
+ } else {
885
+ symbol = base + '/' + quote + ':' + settle;
886
+ }
887
+ const priceDeviate = this.safeString (market, 'order_price_deviate');
888
+ const markPrice = this.safeString (market, 'mark_price');
889
+ const minMultiplier = Precise.stringSub ('1', priceDeviate);
890
+ const maxMultiplier = Precise.stringAdd ('1', priceDeviate);
891
+ const minPrice = Precise.stringMul (minMultiplier, markPrice);
892
+ const maxPrice = Precise.stringMul (maxMultiplier, markPrice);
893
+ const takerPercent = this.safeString (market, 'taker_fee_rate');
894
+ const makerPercent = this.safeString (market, 'maker_fee_rate', takerPercent);
895
+ const isLinear = quote === settle;
896
+ return {
897
+ 'id': id,
898
+ 'symbol': symbol,
899
+ 'base': base,
900
+ 'quote': quote,
901
+ 'settle': settle,
902
+ 'baseId': baseId,
903
+ 'quoteId': quoteId,
904
+ 'settleId': settleId,
905
+ 'type': marketType,
906
+ 'spot': false,
907
+ 'margin': false,
908
+ 'swap': marketType === 'swap',
909
+ 'future': marketType === 'future',
910
+ 'option': marketType === 'option',
911
+ 'active': true,
912
+ 'contract': true,
913
+ 'linear': isLinear,
914
+ 'inverse': !isLinear,
915
+ 'taker': this.parseNumber (Precise.stringDiv (takerPercent, '100')), // Fee is in %, so divide by 100
916
+ 'maker': this.parseNumber (Precise.stringDiv (makerPercent, '100')),
917
+ 'contractSize': this.safeNumber (market, 'quanto_multiplier'),
918
+ 'expiry': expiry,
919
+ 'expiryDatetime': this.iso8601 (expiry),
920
+ 'strike': undefined,
921
+ 'optionType': undefined,
922
+ 'precision': {
923
+ 'amount': this.parseNumber ('1'),
924
+ 'price': this.safeNumber (market, 'order_price_round'),
925
+ },
926
+ 'limits': {
927
+ 'leverage': {
928
+ 'min': this.safeNumber (market, 'leverage_min'),
929
+ 'max': this.safeNumber (market, 'leverage_max'),
930
+ },
931
+ 'amount': {
932
+ 'min': this.safeNumber (market, 'order_size_min'),
933
+ 'max': this.safeNumber (market, 'order_size_max'),
934
+ },
935
+ 'price': {
936
+ 'min': this.parseNumber (minPrice),
937
+ 'max': this.parseNumber (maxPrice),
938
+ },
939
+ 'cost': {
940
+ 'min': undefined,
941
+ 'max': undefined,
942
+ },
943
+ },
944
+ 'info': market,
945
+ };
946
+ }
947
+
948
+ async fetchOptionMarkets (params = {}) {
949
+ const result = [];
950
+ const underlyings = await this.fetchOptionUnderlyings ();
951
+ for (let i = 0; i < underlyings.length; i++) {
952
+ const underlying = underlyings[i];
953
+ const query = params;
954
+ query['underlying'] = underlying;
955
+ const response = await this.publicOptionsGetContracts (query);
956
+ //
957
+ // [
958
+ // {
959
+ // "orders_limit": "50",
960
+ // "order_size_max": "100000",
961
+ // "mark_price_round": "0.1",
962
+ // "order_size_min": "1",
963
+ // "position_limit": "1000000",
964
+ // "orderbook_id": "575967",
965
+ // "order_price_deviate": "0.9",
966
+ // "is_call": true, // true means Call false means Put
967
+ // "last_price": "93.9",
968
+ // "bid1_size": "0",
969
+ // "bid1_price": "0",
970
+ // "taker_fee_rate": "0.0004",
971
+ // "underlying": "BTC_USDT",
972
+ // "create_time": "1646381188",
973
+ // "price_limit_fee_rate": "0.1",
974
+ // "maker_fee_rate": "0.0004",
975
+ // "trade_id": "727",
976
+ // "order_price_round": "0.1",
977
+ // "settle_fee_rate": "0.0001",
978
+ // "trade_size": "1982",
979
+ // "ref_rebate_rate": "0",
980
+ // "name": "BTC_USDT-20220311-44000-C",
981
+ // "underlying_price": "39194.26",
982
+ // "strike_price": "44000",
983
+ // "multiplier": "0.0001",
984
+ // "ask1_price": "0",
985
+ // "ref_discount_rate": "0",
986
+ // "expiration_time": "1646985600",
987
+ // "mark_price": "12.15",
988
+ // "position_size": "4",
989
+ // "ask1_size": "0",
990
+ // "tag": "WEEK"
991
+ // }
992
+ // ]
993
+ //
994
+ for (let i = 0; i < response.length; i++) {
995
+ const market = response[i];
996
+ const id = this.safeString (market, 'name');
997
+ const parts = underlying.split ('_');
998
+ const baseId = this.safeString (parts, 0);
999
+ const quoteId = this.safeString (parts, 1);
1000
+ const base = this.safeCurrencyCode (baseId);
1001
+ const quote = this.safeCurrencyCode (quoteId);
1002
+ let symbol = base + '/' + quote;
1003
+ const expiry = this.safeTimestamp (market, 'expiration_time');
1004
+ const strike = this.safeString (market, 'strike_price');
1005
+ const isCall = this.safeValue (market, 'is_call');
1006
+ const optionLetter = isCall ? 'C' : 'P';
1007
+ const optionType = isCall ? 'call' : 'put';
1008
+ symbol = symbol + ':' + quote + '-' + this.yymmdd (expiry) + ':' + strike + ':' + optionLetter;
1009
+ const priceDeviate = this.safeString (market, 'order_price_deviate');
1010
+ const markPrice = this.safeString (market, 'mark_price');
1011
+ const minMultiplier = Precise.stringSub ('1', priceDeviate);
1012
+ const maxMultiplier = Precise.stringAdd ('1', priceDeviate);
1013
+ const minPrice = Precise.stringMul (minMultiplier, markPrice);
1014
+ const maxPrice = Precise.stringMul (maxMultiplier, markPrice);
1015
+ const takerPercent = this.safeString (market, 'taker_fee_rate');
1016
+ const makerPercent = this.safeString (market, 'maker_fee_rate', takerPercent);
1017
+ result.push ({
1018
+ 'id': id,
1019
+ 'symbol': symbol,
1020
+ 'base': base,
1021
+ 'quote': quote,
1022
+ 'settle': quote,
1023
+ 'baseId': baseId,
1024
+ 'quoteId': quoteId,
1025
+ 'settleId': quoteId,
1026
+ 'type': 'option',
1027
+ 'spot': false,
1028
+ 'margin': false,
1029
+ 'swap': false,
1030
+ 'future': false,
1031
+ 'option': true,
1032
+ 'active': true,
1033
+ 'contract': true,
1034
+ 'linear': true,
1035
+ 'inverse': false,
1036
+ 'taker': this.parseNumber (Precise.stringDiv (takerPercent, '100')), // Fee is in %, so divide by 100
1037
+ 'maker': this.parseNumber (Precise.stringDiv (makerPercent, '100')),
1038
+ 'contractSize': this.parseNumber ('1'),
1039
+ 'expiry': expiry,
1040
+ 'expiryDatetime': this.iso8601 (expiry),
1041
+ 'strike': strike,
1042
+ 'optionType': optionType,
1043
+ 'precision': {
1044
+ 'amount': this.parseNumber ('1'),
1045
+ 'price': this.safeNumber (market, 'order_price_round'),
1046
+ },
1047
+ 'limits': {
1048
+ 'leverage': {
1049
+ 'min': undefined,
1050
+ 'max': undefined,
1051
+ },
1052
+ 'amount': {
1053
+ 'min': this.safeNumber (market, 'order_size_min'),
1054
+ 'max': this.safeNumber (market, 'order_size_max'),
1055
+ },
1056
+ 'price': {
1057
+ 'min': this.parseNumber (minPrice),
1058
+ 'max': this.parseNumber (maxPrice),
1059
+ },
1060
+ 'cost': {
1061
+ 'min': undefined,
1062
+ 'max': undefined,
1063
+ },
1064
+ },
1065
+ 'info': market,
1066
+ });
1067
+ }
1068
+ }
1069
+ return result;
1070
+ }
1071
+
1072
+ async fetchOptionUnderlyings () {
1073
+ const underlyingsResponse = await this.publicOptionsGetUnderlyings ();
1074
+ //
1075
+ // [
1076
+ // {
1077
+ // "index_time": "1646915796",
1078
+ // "name": "BTC_USDT",
1079
+ // "index_price": "39142.73"
1080
+ // }
1081
+ // ]
1082
+ //
1083
+ const underlyings = [];
1084
+ for (let i = 0; i < underlyingsResponse.length; i++) {
1085
+ const underlying = underlyingsResponse[i];
1086
+ const name = this.safeString (underlying, 'name');
1087
+ if (name !== undefined) {
1088
+ underlyings.push (name);
1089
+ }
1090
+ }
1091
+ return underlyings;
1092
+ }
1093
+
1094
+ prepareRequest (market) {
1095
+ if (market !== undefined) {
1096
+ if (market['contract']) {
1097
+ return {
1098
+ 'contract': market['id'],
1099
+ 'settle': market['settleId'],
1100
+ };
1101
+ } else {
1102
+ return {
1103
+ 'currency_pair': market['id'],
1104
+ };
1105
+ }
1106
+ }
1107
+ }
1108
+
1109
+ getMarginType (stop, params) {
1110
+ /**
1111
+ * @ignore
1112
+ * @method
1113
+ * @name gateio#getMarginType
1114
+ * @description Gets the margin type for this api call
1115
+ * @param {bool} stop True if for a stop order
1116
+ * @param {dict} params Request params
1117
+ * @returns The marginType and the updated request params with marginType removed, marginType value is the value that can be read by the "account" property specified in gateios api docs
1118
+ */
1119
+ const defaultMarginType = this.safeStringLower2 (this.options, 'defaultMarginType', 'marginType', 'spot'); // 'margin' is isolated margin on gateio's api
1120
+ let marginType = this.safeStringLower2 (params, 'marginType', 'account', defaultMarginType);
1121
+ params = this.omit (params, [ 'marginType' ]);
1122
+ if (marginType === 'cross') {
1123
+ marginType = 'cross_margin';
1124
+ } else if (marginType === 'isolated') {
1125
+ marginType = 'margin';
1126
+ } else if (marginType === '') {
1127
+ marginType = 'spot';
1128
+ }
1129
+ if (stop) {
1130
+ if (marginType === 'spot') {
1131
+ marginType = 'normal';
1132
+ // gateio spot and margin stop orders use the term normal instead of spot
1133
+ }
1134
+ if (marginType === 'cross_margin') {
1135
+ throw new BadRequest (this.id + ' getMarginType() does not support stop orders for cross margin');
1136
+ }
1137
+ }
1138
+ return [ marginType, params ];
1139
+ }
1140
+
1141
+ getSettlementCurrencies (type, method) {
1142
+ const options = this.safeValue (this.options, type, {}); // [ 'BTC', 'USDT' ] unified codes
1143
+ const fetchMarketsContractOptions = this.safeValue (options, method, {});
1144
+ const defaultSettle = (type === 'swap') ? [ 'usdt' ] : [ 'btc' ];
1145
+ return this.safeValue (fetchMarketsContractOptions, 'settlementCurrencies', defaultSettle);
1146
+ }
1147
+
1148
+ async fetchCurrencies (params = {}) {
1149
+ // sandbox/testnet only supports future markets
1150
+ const apiBackup = this.safeValue (this.urls, 'apiBackup');
1151
+ if (apiBackup !== undefined) {
1152
+ return undefined;
1153
+ }
1154
+ const response = await this.publicSpotGetCurrencies (params);
1155
+ //
1156
+ // {
1157
+ // "currency": "BCN",
1158
+ // "delisted": false,
1159
+ // "withdraw_disabled": true,
1160
+ // "withdraw_delayed": false,
1161
+ // "deposit_disabled": true,
1162
+ // "trade_disabled": false
1163
+ // }
1164
+ //
1165
+ const result = {};
1166
+ // TODO: remove magic constants
1167
+ const amountPrecision = this.parseNumber ('1e-6');
1168
+ for (let i = 0; i < response.length; i++) {
1169
+ const entry = response[i];
1170
+ const currencyId = this.safeString (entry, 'currency');
1171
+ const currencyIdLower = this.safeStringLower (entry, 'currency');
1172
+ const code = this.safeCurrencyCode (currencyId);
1173
+ const delisted = this.safeValue (entry, 'delisted');
1174
+ const withdrawDisabled = this.safeValue (entry, 'withdraw_disabled', false);
1175
+ const depositDisabled = this.safeValue (entry, 'deposit_disabled', false);
1176
+ const tradeDisabled = this.safeValue (entry, 'trade_disabled', false);
1177
+ const withdrawEnabled = !withdrawDisabled;
1178
+ const depositEnabled = !depositDisabled;
1179
+ const tradeEnabled = !tradeDisabled;
1180
+ const listed = !delisted;
1181
+ const active = listed && tradeEnabled && withdrawEnabled && depositEnabled;
1182
+ result[code] = {
1183
+ 'id': currencyId,
1184
+ 'lowerCaseId': currencyIdLower,
1185
+ 'name': undefined,
1186
+ 'code': code,
1187
+ 'precision': amountPrecision,
1188
+ 'info': entry,
1189
+ 'active': active,
1190
+ 'deposit': depositEnabled,
1191
+ 'withdraw': withdrawEnabled,
1192
+ 'fee': undefined,
1193
+ 'fees': [],
1194
+ 'limits': this.limits,
1195
+ };
1196
+ }
1197
+ return result;
1198
+ }
1199
+
1200
+ async fetchFundingRate (symbol, params = {}) {
1201
+ await this.loadMarkets ();
1202
+ const market = this.market (symbol);
1203
+ if (!market['swap']) {
1204
+ throw new BadRequest ('Funding rates only exist for swap contracts');
1205
+ }
1206
+ const request = this.prepareRequest (market);
1207
+ const response = await this.publicFuturesGetSettleContractsContract (this.extend (request, params));
1208
+ //
1209
+ // [
1210
+ // {
1211
+ // "name": "BTC_USDT",
1212
+ // "type": "direct",
1213
+ // "quanto_multiplier": "0.0001",
1214
+ // "ref_discount_rate": "0",
1215
+ // "order_price_deviate": "0.5",
1216
+ // "maintenance_rate": "0.005",
1217
+ // "mark_type": "index",
1218
+ // "last_price": "38026",
1219
+ // "mark_price": "37985.6",
1220
+ // "index_price": "37954.92",
1221
+ // "funding_rate_indicative": "0.000219",
1222
+ // "mark_price_round": "0.01",
1223
+ // "funding_offset": 0,
1224
+ // "in_delisting": false,
1225
+ // "risk_limit_base": "1000000",
1226
+ // "interest_rate": "0.0003",
1227
+ // "order_price_round": "0.1",
1228
+ // "order_size_min": 1,
1229
+ // "ref_rebate_rate": "0.2",
1230
+ // "funding_interval": 28800,
1231
+ // "risk_limit_step": "1000000",
1232
+ // "leverage_min": "1",
1233
+ // "leverage_max": "100",
1234
+ // "risk_limit_max": "8000000",
1235
+ // "maker_fee_rate": "-0.00025",
1236
+ // "taker_fee_rate": "0.00075",
1237
+ // "funding_rate": "0.002053",
1238
+ // "order_size_max": 1000000,
1239
+ // "funding_next_apply": 1610035200,
1240
+ // "short_users": 977,
1241
+ // "config_change_time": 1609899548,
1242
+ // "trade_size": 28530850594,
1243
+ // "position_size": 5223816,
1244
+ // "long_users": 455,
1245
+ // "funding_impact_value": "60000",
1246
+ // "orders_limit": 50,
1247
+ // "trade_id": 10851092,
1248
+ // "orderbook_id": 2129638396
1249
+ // }
1250
+ // ]
1251
+ //
1252
+ return this.parseFundingRate (response);
1253
+ }
1254
+
1255
+ async fetchFundingRates (symbols = undefined, params = {}) {
1256
+ await this.loadMarkets ();
1257
+ const settle = this.safeStringLower (params, 'settle');
1258
+ const request = {
1259
+ 'settle': settle,
1260
+ };
1261
+ const response = await this.publicFuturesGetSettleContracts (this.extend (request, params));
1262
+ //
1263
+ // [
1264
+ // {
1265
+ // "name": "BTC_USDT",
1266
+ // "type": "direct",
1267
+ // "quanto_multiplier": "0.0001",
1268
+ // "ref_discount_rate": "0",
1269
+ // "order_price_deviate": "0.5",
1270
+ // "maintenance_rate": "0.005",
1271
+ // "mark_type": "index",
1272
+ // "last_price": "38026",
1273
+ // "mark_price": "37985.6",
1274
+ // "index_price": "37954.92",
1275
+ // "funding_rate_indicative": "0.000219",
1276
+ // "mark_price_round": "0.01",
1277
+ // "funding_offset": 0,
1278
+ // "in_delisting": false,
1279
+ // "risk_limit_base": "1000000",
1280
+ // "interest_rate": "0.0003",
1281
+ // "order_price_round": "0.1",
1282
+ // "order_size_min": 1,
1283
+ // "ref_rebate_rate": "0.2",
1284
+ // "funding_interval": 28800,
1285
+ // "risk_limit_step": "1000000",
1286
+ // "leverage_min": "1",
1287
+ // "leverage_max": "100",
1288
+ // "risk_limit_max": "8000000",
1289
+ // "maker_fee_rate": "-0.00025",
1290
+ // "taker_fee_rate": "0.00075",
1291
+ // "funding_rate": "0.002053",
1292
+ // "order_size_max": 1000000,
1293
+ // "funding_next_apply": 1610035200,
1294
+ // "short_users": 977,
1295
+ // "config_change_time": 1609899548,
1296
+ // "trade_size": 28530850594,
1297
+ // "position_size": 5223816,
1298
+ // "long_users": 455,
1299
+ // "funding_impact_value": "60000",
1300
+ // "orders_limit": 50,
1301
+ // "trade_id": 10851092,
1302
+ // "orderbook_id": 2129638396
1303
+ // }
1304
+ // ]
1305
+ //
1306
+ const result = this.parseFundingRates (response);
1307
+ return this.filterByArray (result, 'symbol', symbols);
1308
+ }
1309
+
1310
+ parseFundingRate (contract, market = undefined) {
1311
+ //
1312
+ // {
1313
+ // "name": "BTC_USDT",
1314
+ // "type": "direct",
1315
+ // "quanto_multiplier": "0.0001",
1316
+ // "ref_discount_rate": "0",
1317
+ // "order_price_deviate": "0.5",
1318
+ // "maintenance_rate": "0.005",
1319
+ // "mark_type": "index",
1320
+ // "last_price": "38026",
1321
+ // "mark_price": "37985.6",
1322
+ // "index_price": "37954.92",
1323
+ // "funding_rate_indicative": "0.000219",
1324
+ // "mark_price_round": "0.01",
1325
+ // "funding_offset": 0,
1326
+ // "in_delisting": false,
1327
+ // "risk_limit_base": "1000000",
1328
+ // "interest_rate": "0.0003",
1329
+ // "order_price_round": "0.1",
1330
+ // "order_size_min": 1,
1331
+ // "ref_rebate_rate": "0.2",
1332
+ // "funding_interval": 28800,
1333
+ // "risk_limit_step": "1000000",
1334
+ // "leverage_min": "1",
1335
+ // "leverage_max": "100",
1336
+ // "risk_limit_max": "8000000",
1337
+ // "maker_fee_rate": "-0.00025",
1338
+ // "taker_fee_rate": "0.00075",
1339
+ // "funding_rate": "0.002053",
1340
+ // "order_size_max": 1000000,
1341
+ // "funding_next_apply": 1610035200,
1342
+ // "short_users": 977,
1343
+ // "config_change_time": 1609899548,
1344
+ // "trade_size": 28530850594,
1345
+ // "position_size": 5223816,
1346
+ // "long_users": 455,
1347
+ // "funding_impact_value": "60000",
1348
+ // "orders_limit": 50,
1349
+ // "trade_id": 10851092,
1350
+ // "orderbook_id": 2129638396
1351
+ // }
1352
+ //
1353
+ const marketId = this.safeString (contract, 'name');
1354
+ const symbol = this.safeSymbol (marketId, market);
1355
+ const markPrice = this.safeNumber (contract, 'mark_price');
1356
+ const indexPrice = this.safeNumber (contract, 'index_price');
1357
+ const interestRate = this.safeNumber (contract, 'interest_rate');
1358
+ const fundingRate = this.safeNumber (contract, 'funding_rate');
1359
+ const fundingTime = this.safeInteger (contract, 'funding_next_apply') * 1000;
1360
+ const fundingRateIndicative = this.safeNumber (contract, 'funding_rate_indicative');
1361
+ return {
1362
+ 'info': contract,
1363
+ 'symbol': symbol,
1364
+ 'markPrice': markPrice,
1365
+ 'indexPrice': indexPrice,
1366
+ 'interestRate': interestRate,
1367
+ 'estimatedSettlePrice': undefined,
1368
+ 'timestamp': undefined,
1369
+ 'datetime': undefined,
1370
+ 'fundingRate': fundingRate,
1371
+ 'fundingTimestamp': fundingTime,
1372
+ 'fundingDatetime': this.iso8601 (fundingTime),
1373
+ 'nextFundingRate': fundingRateIndicative,
1374
+ 'nextFundingTimestamp': undefined,
1375
+ 'nextFundingDatetime': undefined,
1376
+ 'previousFundingRate': undefined,
1377
+ 'previousFundingTimestamp': undefined,
1378
+ 'previousFundingDatetime': undefined,
1379
+ };
1380
+ }
1381
+
1382
+ async fetchNetworkDepositAddress (code, params = {}) {
1383
+ await this.loadMarkets ();
1384
+ const currency = this.currency (code);
1385
+ const request = {
1386
+ 'currency': currency['id'],
1387
+ };
1388
+ const response = await this.privateWalletGetDepositAddress (this.extend (request, params));
1389
+ const addresses = this.safeValue (response, 'multichain_addresses');
1390
+ const currencyId = this.safeString (response, 'currency');
1391
+ code = this.safeCurrencyCode (currencyId);
1392
+ const result = {};
1393
+ for (let i = 0; i < addresses.length; i++) {
1394
+ const entry = addresses[i];
1395
+ //
1396
+ // {
1397
+ // "chain": "ETH",
1398
+ // "address": "0x359a697945E79C7e17b634675BD73B33324E9408",
1399
+ // "payment_id": "",
1400
+ // "payment_name": "",
1401
+ // "obtain_failed": "0"
1402
+ // }
1403
+ //
1404
+ const obtainFailed = this.safeInteger (entry, 'obtain_failed');
1405
+ if (obtainFailed) {
1406
+ continue;
1407
+ }
1408
+ const network = this.safeString (entry, 'chain');
1409
+ const address = this.safeString (entry, 'address');
1410
+ let tag = this.safeString (entry, 'payment_id');
1411
+ const tagLength = tag.length;
1412
+ tag = tagLength ? tag : undefined;
1413
+ result[network] = {
1414
+ 'info': entry,
1415
+ 'code': code,
1416
+ 'address': address,
1417
+ 'tag': tag,
1418
+ };
1419
+ }
1420
+ return result;
1421
+ }
1422
+
1423
+ async fetchDepositAddress (code, params = {}) {
1424
+ await this.loadMarkets ();
1425
+ const currency = this.currency (code);
1426
+ const request = {
1427
+ 'currency': currency['id'],
1428
+ };
1429
+ const response = await this.privateWalletGetDepositAddress (this.extend (request, params));
1430
+ //
1431
+ // {
1432
+ // "currency": "XRP",
1433
+ // "address": "rHcFoo6a9qT5NHiVn1THQRhsEGcxtYCV4d 391331007",
1434
+ // "multichain_addresses": [
1435
+ // {
1436
+ // "chain": "XRP",
1437
+ // "address": "rHcFoo6a9qT5NHiVn1THQRhsEGcxtYCV4d",
1438
+ // "payment_id": "391331007",
1439
+ // "payment_name": "Tag",
1440
+ // "obtain_failed": 0
1441
+ // }
1442
+ // ]
1443
+ // }
1444
+ //
1445
+ const currencyId = this.safeString (response, 'currency');
1446
+ code = this.safeCurrencyCode (currencyId);
1447
+ const addressField = this.safeString (response, 'address');
1448
+ let tag = undefined;
1449
+ let address = undefined;
1450
+ if (addressField.indexOf (' ') >= 0) {
1451
+ const splitted = addressField.split (' ');
1452
+ address = splitted[0];
1453
+ tag = splitted[1];
1454
+ } else {
1455
+ address = addressField;
1456
+ }
1457
+ return {
1458
+ 'info': response,
1459
+ 'code': code,
1460
+ 'address': address,
1461
+ 'tag': tag,
1462
+ 'network': undefined,
1463
+ };
1464
+ }
1465
+
1466
+ async fetchTradingFee (symbol, params = {}) {
1467
+ await this.loadMarkets ();
1468
+ const market = this.market (symbol);
1469
+ const request = {
1470
+ 'currency_pair': market['id'],
1471
+ };
1472
+ const response = await this.privateWalletGetFee (this.extend (request, params));
1473
+ //
1474
+ // {
1475
+ // "user_id": 1486602,
1476
+ // "taker_fee": "0.002",
1477
+ // "maker_fee": "0.002",
1478
+ // "gt_discount": true,
1479
+ // "gt_taker_fee": "0.0015",
1480
+ // "gt_maker_fee": "0.0015",
1481
+ // "loan_fee": "0.18",
1482
+ // "point_type": "0",
1483
+ // "futures_taker_fee": "0.0005",
1484
+ // "futures_maker_fee": "0"
1485
+ // }
1486
+ //
1487
+ return this.parseTradingFee (response, market);
1488
+ }
1489
+
1490
+ async fetchTradingFees (params = {}) {
1491
+ await this.loadMarkets ();
1492
+ const response = await this.privateWalletGetFee (params);
1493
+ //
1494
+ // {
1495
+ // "user_id": 1486602,
1496
+ // "taker_fee": "0.002",
1497
+ // "maker_fee": "0.002",
1498
+ // "gt_discount": true,
1499
+ // "gt_taker_fee": "0.0015",
1500
+ // "gt_maker_fee": "0.0015",
1501
+ // "loan_fee": "0.18",
1502
+ // "point_type": "0",
1503
+ // "futures_taker_fee": "0.0005",
1504
+ // "futures_maker_fee": "0"
1505
+ // }
1506
+ //
1507
+ return this.parseTradingFees (response);
1508
+ }
1509
+
1510
+ parseTradingFees (response) {
1511
+ const result = {};
1512
+ for (let i = 0; i < this.symbols.length; i++) {
1513
+ const symbol = this.symbols[i];
1514
+ const market = this.market (symbol);
1515
+ result[symbol] = this.parseTradingFee (response, market);
1516
+ }
1517
+ return result;
1518
+ }
1519
+
1520
+ parseTradingFee (info, market = undefined) {
1521
+ //
1522
+ // {
1523
+ // "user_id": 1486602,
1524
+ // "taker_fee": "0.002",
1525
+ // "maker_fee": "0.002",
1526
+ // "gt_discount": true,
1527
+ // "gt_taker_fee": "0.0015",
1528
+ // "gt_maker_fee": "0.0015",
1529
+ // "loan_fee": "0.18",
1530
+ // "point_type": "0",
1531
+ // "futures_taker_fee": "0.0005",
1532
+ // "futures_maker_fee": "0"
1533
+ // }
1534
+ //
1535
+ const contract = this.safeValue (market, 'contract');
1536
+ const takerKey = contract ? 'futures_taker_fee' : 'taker_fee';
1537
+ const makerKey = contract ? 'futures_maker_fee' : 'maker_fee';
1538
+ return {
1539
+ 'info': info,
1540
+ 'symbol': this.safeString (market, 'symbol'),
1541
+ 'maker': this.safeNumber (info, makerKey),
1542
+ 'taker': this.safeNumber (info, takerKey),
1543
+ };
1544
+ }
1545
+
1546
+ async fetchFundingFees (params = {}) {
1547
+ await this.loadMarkets ();
1548
+ const response = await this.privateWalletGetWithdrawStatus (params);
1549
+ //
1550
+ // {
1551
+ // "currency": "MTN",
1552
+ // "name": "Medicalchain",
1553
+ // "name_cn": "Medicalchain",
1554
+ // "deposit": "0",
1555
+ // "withdraw_percent": "0%",
1556
+ // "withdraw_fix": "900",
1557
+ // "withdraw_day_limit": "500000",
1558
+ // "withdraw_day_limit_remain": "500000",
1559
+ // "withdraw_amount_mini": "900.1",
1560
+ // "withdraw_eachtime_limit": "90000000000",
1561
+ // "withdraw_fix_on_chains": {
1562
+ // "ETH": "900"
1563
+ // }
1564
+ // }
1565
+ //
1566
+ const withdrawFees = {};
1567
+ for (let i = 0; i < response.length; i++) {
1568
+ const entry = response[i];
1569
+ const currencyId = this.safeString (entry, 'currency');
1570
+ const code = this.safeCurrencyCode (currencyId);
1571
+ withdrawFees[code] = {};
1572
+ let withdrawFix = this.safeValue (entry, 'withdraw_fix_on_chains');
1573
+ if (withdrawFix === undefined) {
1574
+ withdrawFix = {};
1575
+ withdrawFix[code] = this.safeNumber (entry, 'withdraw_fix');
1576
+ }
1577
+ const keys = Object.keys (withdrawFix);
1578
+ for (let i = 0; i < keys.length; i++) {
1579
+ const key = keys[i];
1580
+ withdrawFees[code][key] = this.parseNumber (withdrawFix[key]);
1581
+ }
1582
+ }
1583
+ return {
1584
+ 'info': response,
1585
+ 'withdraw': withdrawFees,
1586
+ 'deposit': {},
1587
+ };
1588
+ }
1589
+
1590
+ async fetchFundingHistory (symbol = undefined, since = undefined, limit = undefined, params = {}) {
1591
+ await this.loadMarkets ();
1592
+ // let defaultType = 'future';
1593
+ let market = undefined;
1594
+ let request = {};
1595
+ if (symbol !== undefined) {
1596
+ market = this.market (symbol);
1597
+ symbol = market['symbol'];
1598
+ request = this.prepareRequest (market);
1599
+ }
1600
+ let type = undefined;
1601
+ [ type, params ] = this.handleMarketTypeAndParams ('fetchFundingHistory', market, params);
1602
+ if (market === undefined) {
1603
+ const defaultSettle = (type === 'swap') ? 'usdt' : 'btc';
1604
+ const settle = this.safeString (params, 'settle', defaultSettle);
1605
+ request['settle'] = settle;
1606
+ params = this.omit (params, 'settle');
1607
+ }
1608
+ request['type'] = 'fund'; // 'dnw' 'pnl' 'fee' 'refr' 'fund' 'point_dnw' 'point_fee' 'point_refr'
1609
+ if (since !== undefined) {
1610
+ request['from'] = since / 1000;
1611
+ }
1612
+ if (limit !== undefined) {
1613
+ request['limit'] = limit;
1614
+ }
1615
+ const method = this.getSupportedMapping (type, {
1616
+ 'swap': 'privateFuturesGetSettleAccountBook',
1617
+ 'future': 'privateDeliveryGetSettleAccountBook',
1618
+ });
1619
+ const response = await this[method] (this.extend (request, params));
1620
+ //
1621
+ // [
1622
+ // {
1623
+ // "time": 1646899200,
1624
+ // "change": "-0.027722",
1625
+ // "balance": "11.653120591841",
1626
+ // "text": "XRP_USDT",
1627
+ // "type": "fund"
1628
+ // },
1629
+ // ...
1630
+ // ]
1631
+ //
1632
+ return this.parseFundingHistories (response, symbol, since, limit);
1633
+ }
1634
+
1635
+ parseFundingHistories (response, symbol, since, limit) {
1636
+ const result = [];
1637
+ for (let i = 0; i < response.length; i++) {
1638
+ const entry = response[i];
1639
+ const funding = this.parseFundingHistory (entry);
1640
+ result.push (funding);
1641
+ }
1642
+ const sorted = this.sortBy (result, 'timestamp');
1643
+ return this.filterBySymbolSinceLimit (sorted, symbol, since, limit);
1644
+ }
1645
+
1646
+ parseFundingHistory (info, market = undefined) {
1647
+ //
1648
+ // {
1649
+ // "time": 1646899200,
1650
+ // "change": "-0.027722",
1651
+ // "balance": "11.653120591841",
1652
+ // "text": "XRP_USDT",
1653
+ // "type": "fund"
1654
+ // }
1655
+ //
1656
+ const timestamp = this.safeTimestamp (info, 'time');
1657
+ const marketId = this.safeString (info, 'text');
1658
+ market = this.safeMarket (marketId, market);
1659
+ return {
1660
+ 'info': info,
1661
+ 'symbol': this.safeString (market, 'symbol'),
1662
+ 'code': this.safeString (market, 'settle'),
1663
+ 'timestamp': timestamp,
1664
+ 'datetime': this.iso8601 (timestamp),
1665
+ 'id': undefined,
1666
+ 'amount': this.safeNumber (info, 'change'),
1667
+ };
1668
+ }
1669
+
1670
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
1671
+ await this.loadMarkets ();
1672
+ const market = this.market (symbol);
1673
+ //
1674
+ // const request = {
1675
+ // 'currency_pair': market['id'],
1676
+ // 'interval': '0', // depth, 0 means no aggregation is applied, default to 0
1677
+ // 'limit': limit, // maximum number of order depth data in asks or bids
1678
+ // 'with_id': true, // return order book ID
1679
+ // };
1680
+ //
1681
+ const request = this.prepareRequest (market);
1682
+ const spotOrMargin = market['spot'] || market['margin'];
1683
+ const method = this.getSupportedMapping (market['type'], {
1684
+ 'spot': 'publicSpotGetOrderBook',
1685
+ 'margin': 'publicSpotGetOrderBook',
1686
+ 'swap': 'publicFuturesGetSettleOrderBook',
1687
+ 'future': 'publicDeliveryGetSettleOrderBook',
1688
+ });
1689
+ if (limit !== undefined) {
1690
+ request['limit'] = limit; // default 10, max 100
1691
+ }
1692
+ request['with_id'] = true;
1693
+ const response = await this[method] (this.extend (request, params));
1694
+ //
1695
+ // SPOT
1696
+ //
1697
+ // {
1698
+ // "id": 6358770031
1699
+ // "current": 1634345973275,
1700
+ // "update": 1634345973271,
1701
+ // "asks": [
1702
+ // ["2.2241","12449.827"],
1703
+ // ["2.2242","200"],
1704
+ // ["2.2244","826.931"],
1705
+ // ["2.2248","3876.107"],
1706
+ // ["2.225","2377.252"],
1707
+ // ["2.22509","439.484"],
1708
+ // ["2.2251","1489.313"],
1709
+ // ["2.2253","714.582"],
1710
+ // ["2.2254","1349.784"],
1711
+ // ["2.2256","234.701"]],
1712
+ // "bids": [
1713
+ // ["2.2236","32.465"],
1714
+ // ["2.2232","243.983"],
1715
+ // ["2.2231","32.207"],
1716
+ // ["2.223","449.827"],
1717
+ // ["2.2228","7.918"],
1718
+ // ["2.2227","12703.482"],
1719
+ // ["2.2226","143.033"],
1720
+ // ["2.2225","143.027"],
1721
+ // ["2.2224","1369.352"],
1722
+ // ["2.2223","756.063"]
1723
+ // ]
1724
+ // }
1725
+ //
1726
+ // Perpetual Swap
1727
+ //
1728
+ // {
1729
+ // "id": 6358770031
1730
+ // "current": 1634350208.745,
1731
+ // "asks": [
1732
+ // {"s": 24909, "p": "61264.8"},
1733
+ // {"s": 81, "p": "61266.6"},
1734
+ // {"s": 2000, "p": "61267.6"},
1735
+ // {"s": 490, "p": "61270.2"},
1736
+ // {"s": 12, "p": "61270.4"},
1737
+ // {"s": 11782, "p": "61273.2"},
1738
+ // {"s": 14666, "p": "61273.3"},
1739
+ // {"s": 22541, "p": "61273.4"},
1740
+ // {"s": 33, "p": "61273.6"},
1741
+ // {"s": 11980, "p": "61274.5"}
1742
+ // ],
1743
+ // "bids": [
1744
+ // {"s": 41844, "p": "61264.7"},
1745
+ // {"s": 13783, "p": "61263.3"},
1746
+ // {"s": 1143, "p": "61259.8"},
1747
+ // {"s": 81, "p": "61258.7"},
1748
+ // {"s": 2471, "p": "61257.8"},
1749
+ // {"s": 2471, "p": "61257.7"},
1750
+ // {"s": 2471, "p": "61256.5"},
1751
+ // {"s": 3, "p": "61254.2"},
1752
+ // {"s": 114, "p": "61252.4"},
1753
+ // {"s": 14372, "p": "61248.6"}
1754
+ // ],
1755
+ // "update": 1634350208.724
1756
+ // }
1757
+ //
1758
+ let timestamp = this.safeInteger (response, 'current');
1759
+ if (!spotOrMargin) {
1760
+ timestamp = timestamp * 1000;
1761
+ }
1762
+ const priceKey = spotOrMargin ? 0 : 'p';
1763
+ const amountKey = spotOrMargin ? 1 : 's';
1764
+ const nonce = this.safeInteger (response, 'id');
1765
+ const result = this.parseOrderBook (response, symbol, timestamp, 'bids', 'asks', priceKey, amountKey);
1766
+ result['nonce'] = nonce;
1767
+ return result;
1768
+ }
1769
+
1770
+ async fetchTicker (symbol, params = {}) {
1771
+ await this.loadMarkets ();
1772
+ const market = this.market (symbol);
1773
+ const request = this.prepareRequest (market);
1774
+ const method = this.getSupportedMapping (market['type'], {
1775
+ 'spot': 'publicSpotGetTickers',
1776
+ 'margin': 'publicSpotGetTickers',
1777
+ 'swap': 'publicFuturesGetSettleTickers',
1778
+ 'future': 'publicDeliveryGetSettleTickers',
1779
+ });
1780
+ const response = await this[method] (this.extend (request, params));
1781
+ const ticker = this.safeValue (response, 0);
1782
+ return this.parseTicker (ticker, market);
1783
+ }
1784
+
1785
+ parseTicker (ticker, market = undefined) {
1786
+ //
1787
+ // SPOT
1788
+ //
1789
+ // {
1790
+ // "currency_pair": "KFC_USDT",
1791
+ // "last": "7.255",
1792
+ // "lowest_ask": "7.298",
1793
+ // "highest_bid": "7.218",
1794
+ // "change_percentage": "-1.18",
1795
+ // "base_volume": "1219.053687865",
1796
+ // "quote_volume": "8807.40299875455",
1797
+ // "high_24h": "7.262",
1798
+ // "low_24h": "7.095"
1799
+ // }
1800
+ //
1801
+ // LINEAR/DELIVERY
1802
+ //
1803
+ // {
1804
+ // "contract": "BTC_USDT",
1805
+ // "last": "6432",
1806
+ // "low_24h": "6278",
1807
+ // "high_24h": "6790",
1808
+ // "change_percentage": "4.43",
1809
+ // "total_size": "32323904",
1810
+ // "volume_24h": "184040233284",
1811
+ // "volume_24h_btc": "28613220",
1812
+ // "volume_24h_usd": "184040233284",
1813
+ // "volume_24h_base": "28613220",
1814
+ // "volume_24h_quote": "184040233284",
1815
+ // "volume_24h_settle": "28613220",
1816
+ // "mark_price": "6534",
1817
+ // "funding_rate": "0.0001",
1818
+ // "funding_rate_indicative": "0.0001",
1819
+ // "index_price": "6531"
1820
+ // }
1821
+ //
1822
+ const marketId = this.safeString2 (ticker, 'currency_pair', 'contract');
1823
+ const symbol = this.safeSymbol (marketId, market);
1824
+ const last = this.safeString (ticker, 'last');
1825
+ const ask = this.safeString (ticker, 'lowest_ask');
1826
+ const bid = this.safeString (ticker, 'highest_bid');
1827
+ const high = this.safeString (ticker, 'high_24h');
1828
+ const low = this.safeString (ticker, 'low_24h');
1829
+ const baseVolume = this.safeString2 (ticker, 'base_volume', 'volume_24h_base');
1830
+ const quoteVolume = this.safeString2 (ticker, 'quote_volume', 'volume_24h_quote');
1831
+ const percentage = this.safeString (ticker, 'change_percentage');
1832
+ return this.safeTicker ({
1833
+ 'symbol': symbol,
1834
+ 'timestamp': undefined,
1835
+ 'datetime': undefined,
1836
+ 'high': high,
1837
+ 'low': low,
1838
+ 'bid': bid,
1839
+ 'bidVolume': undefined,
1840
+ 'ask': ask,
1841
+ 'askVolume': undefined,
1842
+ 'vwap': undefined,
1843
+ 'open': undefined,
1844
+ 'close': last,
1845
+ 'last': last,
1846
+ 'previousClose': undefined,
1847
+ 'change': undefined,
1848
+ 'percentage': percentage,
1849
+ 'average': undefined,
1850
+ 'baseVolume': baseVolume,
1851
+ 'quoteVolume': quoteVolume,
1852
+ 'info': ticker,
1853
+ }, market, false);
1854
+ }
1855
+
1856
+ async fetchTickers (symbols = undefined, params = {}) {
1857
+ await this.loadMarkets ();
1858
+ let type = undefined;
1859
+ [ type, params ] = this.handleMarketTypeAndParams ('fetchTickers', undefined, params);
1860
+ const method = this.getSupportedMapping (type, {
1861
+ 'spot': 'publicSpotGetTickers',
1862
+ 'margin': 'publicSpotGetTickers',
1863
+ 'swap': 'publicFuturesGetSettleTickers',
1864
+ 'future': 'publicDeliveryGetSettleTickers',
1865
+ });
1866
+ const request = {};
1867
+ const future = type === 'future';
1868
+ const swap = type === 'swap';
1869
+ const defaultSettle = swap ? 'usdt' : 'btc';
1870
+ const settle = this.safeStringLower (params, 'settle', defaultSettle);
1871
+ if (swap || future) {
1872
+ request['settle'] = settle;
1873
+ }
1874
+ const response = await this[method] (this.extend (request, params));
1875
+ return this.parseTickers (response, symbols);
1876
+ }
1877
+
1878
+ fetchBalanceHelper (entry) {
1879
+ const account = this.account ();
1880
+ account['used'] = this.safeString2 (entry, 'freeze', 'locked');
1881
+ account['free'] = this.safeString (entry, 'available');
1882
+ account['total'] = this.safeString (entry, 'total');
1883
+ return account;
1884
+ }
1885
+
1886
+ async fetchBalance (params = {}) {
1887
+ /**
1888
+ * @param {dict} params exchange specific parameters
1889
+ * @param {str} params.type spot, margin, swap or future, if not provided this.options['defaultType'] is used
1890
+ * @param {str} params.settle 'btc' or 'usdt' - settle currency for perpetual swap and future - default="usdt" for swap and "btc" for future
1891
+ * @param {str} params.marginType 'cross' or 'isolated' - marginType for margin trading if not provided this.options['defaultMarginType'] is used
1892
+ * @param {str} params.symbol margin only - unified ccxt symbol
1893
+ */
1894
+ await this.loadMarkets ();
1895
+ let type = undefined;
1896
+ let marginType = undefined;
1897
+ [ type, params ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params);
1898
+ const spot = type === 'spot';
1899
+ const swap = type === 'swap';
1900
+ const future = type === 'future';
1901
+ const contract = swap || future;
1902
+ const request = {};
1903
+ if (contract) {
1904
+ const defaultSettle = swap ? 'usdt' : 'btc';
1905
+ const settle = this.safeStringLower (params, 'settle', defaultSettle);
1906
+ params = this.omit (params, 'settle');
1907
+ request['settle'] = settle;
1908
+ } else {
1909
+ [ marginType, params ] = this.getMarginType (false, params);
1910
+ const symbol = this.safeString (params, 'symbol');
1911
+ if (symbol !== undefined) {
1912
+ const market = this.market (symbol);
1913
+ request['currency_pair'] = market['id'];
1914
+ }
1915
+ }
1916
+ const crossMargin = marginType === 'cross_margin';
1917
+ const margin = marginType === 'margin';
1918
+ let spotMethod = 'privateSpotGetAccounts';
1919
+ if (spot) {
1920
+ spotMethod = this.getSupportedMapping (marginType, {
1921
+ 'spot': 'privateSpotGetAccounts',
1922
+ 'margin': 'privateMarginGetAccounts',
1923
+ 'cross_margin': 'privateMarginGetCrossAccounts',
1924
+ });
1925
+ }
1926
+ const method = this.getSupportedMapping (type, {
1927
+ 'spot': spotMethod,
1928
+ 'funding': 'privateMarginGetFundingAccounts',
1929
+ 'swap': 'privateFuturesGetSettleAccounts',
1930
+ 'future': 'privateDeliveryGetSettleAccounts',
1931
+ });
1932
+ let response = await this[method] (this.extend (request, params));
1933
+ if (contract) {
1934
+ response = [ response ];
1935
+ }
1936
+ //
1937
+ // Spot / margin funding
1938
+ //
1939
+ // [
1940
+ // {
1941
+ // "currency": "DBC",
1942
+ // "available": "0",
1943
+ // "locked": "0"
1944
+ // "lent": "0", // margin funding only
1945
+ // "total_lent": "0" // margin funding only
1946
+ // },
1947
+ // ...
1948
+ // ]
1949
+ //
1950
+ // Margin
1951
+ //
1952
+ // [
1953
+ // {
1954
+ // "currency_pair": "DOGE_USDT",
1955
+ // "locked": false,
1956
+ // "risk": "9999.99",
1957
+ // "base": {
1958
+ // "currency": "DOGE",
1959
+ // "available": "0",
1960
+ // "locked": "0",
1961
+ // "borrowed": "0",
1962
+ // "interest": "0"
1963
+ // },
1964
+ // "quote": {
1965
+ // "currency": "USDT",
1966
+ // "available": "0.73402",
1967
+ // "locked": "0",
1968
+ // "borrowed": "0",
1969
+ // "interest": "0"
1970
+ // }
1971
+ // },
1972
+ // ...
1973
+ // ]
1974
+ //
1975
+ // Cross margin
1976
+ //
1977
+ // {
1978
+ // "user_id": 10406147,
1979
+ // "locked": false,
1980
+ // "balances": {
1981
+ // "USDT": {
1982
+ // "available": "1",
1983
+ // "freeze": "0",
1984
+ // "borrowed": "0",
1985
+ // "interest": "0"
1986
+ // }
1987
+ // },
1988
+ // "total": "1",
1989
+ // "borrowed": "0",
1990
+ // "interest": "0",
1991
+ // "risk": "9999.99"
1992
+ // }
1993
+ //
1994
+ // Perpetual Swap
1995
+ //
1996
+ // {
1997
+ // order_margin: "0",
1998
+ // point: "0",
1999
+ // bonus: "0",
2000
+ // history: {
2001
+ // dnw: "2.1321",
2002
+ // pnl: "11.5351",
2003
+ // refr: "0",
2004
+ // point_fee: "0",
2005
+ // fund: "-0.32340576684",
2006
+ // bonus_dnw: "0",
2007
+ // point_refr: "0",
2008
+ // bonus_offset: "0",
2009
+ // fee: "-0.20132775",
2010
+ // point_dnw: "0",
2011
+ // },
2012
+ // unrealised_pnl: "13.315100000006",
2013
+ // total: "12.51345151332",
2014
+ // available: "0",
2015
+ // in_dual_mode: false,
2016
+ // currency: "USDT",
2017
+ // position_margin: "12.51345151332",
2018
+ // user: "6333333",
2019
+ // }
2020
+ //
2021
+ // Delivery Future
2022
+ //
2023
+ // {
2024
+ // order_margin: "0",
2025
+ // point: "0",
2026
+ // history: {
2027
+ // dnw: "1",
2028
+ // pnl: "0",
2029
+ // refr: "0",
2030
+ // point_fee: "0",
2031
+ // point_dnw: "0",
2032
+ // settle: "0",
2033
+ // settle_fee: "0",
2034
+ // point_refr: "0",
2035
+ // fee: "0",
2036
+ // },
2037
+ // unrealised_pnl: "0",
2038
+ // total: "1",
2039
+ // available: "1",
2040
+ // currency: "USDT",
2041
+ // position_margin: "0",
2042
+ // user: "6333333",
2043
+ // }
2044
+ //
2045
+ const result = {
2046
+ 'info': response,
2047
+ };
2048
+ let data = response;
2049
+ if ('balances' in data) { // True for cross_margin
2050
+ const flatBalances = [];
2051
+ const balances = this.safeValue (data, 'balances', []);
2052
+ // inject currency and create an artificial balance object
2053
+ // so it can follow the existent flow
2054
+ const keys = Object.keys (balances);
2055
+ for (let i = 0; i < keys.length; i++) {
2056
+ const currencyId = keys[i];
2057
+ const content = balances[currencyId];
2058
+ content['currency'] = currencyId;
2059
+ flatBalances.push (content);
2060
+ }
2061
+ data = flatBalances;
2062
+ }
2063
+ for (let i = 0; i < data.length; i++) {
2064
+ const entry = data[i];
2065
+ if (margin && !crossMargin) {
2066
+ const marketId = this.safeString (entry, 'currency_pair');
2067
+ const symbol = this.safeSymbol (marketId, undefined, '_');
2068
+ const base = this.safeValue (entry, 'base', {});
2069
+ const quote = this.safeValue (entry, 'quote', {});
2070
+ const baseCode = this.safeCurrencyCode (this.safeString (base, 'currency', {}));
2071
+ const quoteCode = this.safeCurrencyCode (this.safeString (quote, 'currency', {}));
2072
+ const subResult = {};
2073
+ subResult[baseCode] = this.fetchBalanceHelper (base);
2074
+ subResult[quoteCode] = this.fetchBalanceHelper (quote);
2075
+ result[symbol] = this.safeBalance (subResult);
2076
+ } else {
2077
+ const code = this.safeCurrencyCode (this.safeString (entry, 'currency', {}));
2078
+ result[code] = this.fetchBalanceHelper (entry);
2079
+ }
2080
+ }
2081
+ return (margin && !crossMargin) ? result : this.safeBalance (result);
2082
+ }
2083
+
2084
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
2085
+ await this.loadMarkets ();
2086
+ const market = this.market (symbol);
2087
+ const price = this.safeString (params, 'price');
2088
+ const request = this.prepareRequest (market);
2089
+ request['interval'] = this.timeframes[timeframe];
2090
+ let method = 'publicSpotGetCandlesticks';
2091
+ if (market['contract']) {
2092
+ const maxLimit = 1999;
2093
+ limit = (limit === undefined) ? maxLimit : Math.min (limit, maxLimit);
2094
+ if (market['future']) {
2095
+ method = 'publicDeliveryGetSettleCandlesticks';
2096
+ } else if (market['swap']) {
2097
+ method = 'publicFuturesGetSettleCandlesticks';
2098
+ }
2099
+ const isMark = (price === 'mark');
2100
+ const isIndex = (price === 'index');
2101
+ if (isMark || isIndex) {
2102
+ request['contract'] = price + '_' + market['id'];
2103
+ params = this.omit (params, 'price');
2104
+ }
2105
+ } else {
2106
+ const maxLimit = 1000;
2107
+ limit = (limit === undefined) ? maxLimit : Math.min (limit, maxLimit);
2108
+ request['limit'] = limit;
2109
+ }
2110
+ if (since !== undefined) {
2111
+ const duration = this.parseTimeframe (timeframe);
2112
+ request['from'] = parseInt (since / 1000);
2113
+ const toTimestamp = this.sum (request['from'], limit * duration - 1);
2114
+ const currentTimestamp = this.seconds ();
2115
+ request['to'] = Math.min (toTimestamp, currentTimestamp);
2116
+ }
2117
+ const response = await this[method] (this.extend (request, params));
2118
+ return this.parseOHLCVs (response, market, timeframe, since, limit);
2119
+ }
2120
+
2121
+ async fetchMarkOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
2122
+ const request = {
2123
+ 'price': 'mark',
2124
+ };
2125
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
2126
+ }
2127
+
2128
+ async fetchFundingRateHistory (symbol = undefined, since = undefined, limit = undefined, params = {}) {
2129
+ if (symbol === undefined) {
2130
+ throw new ArgumentsRequired (this.id + ' fetchFundingRateHistory() requires a symbol argument');
2131
+ }
2132
+ await this.loadMarkets ();
2133
+ const market = this.market (symbol);
2134
+ if (!market['swap']) {
2135
+ throw new BadRequest ('Funding rates only exist for swap contracts');
2136
+ }
2137
+ const request = {
2138
+ 'contract': market['id'],
2139
+ 'settle': market['settleId'],
2140
+ };
2141
+ if (limit !== undefined) {
2142
+ request['limit'] = limit;
2143
+ }
2144
+ const method = 'publicFuturesGetSettleFundingRate';
2145
+ const response = await this[method] (this.extend (request, params));
2146
+ //
2147
+ // {
2148
+ // "r": "0.00063521",
2149
+ // "t": "1621267200000",
2150
+ // }
2151
+ //
2152
+ const rates = [];
2153
+ for (let i = 0; i < response.length; i++) {
2154
+ const entry = response[i];
2155
+ const timestamp = this.safeTimestamp (entry, 't');
2156
+ rates.push ({
2157
+ 'info': entry,
2158
+ 'symbol': symbol,
2159
+ 'fundingRate': this.safeNumber (entry, 'r'),
2160
+ 'timestamp': timestamp,
2161
+ 'datetime': this.iso8601 (timestamp),
2162
+ });
2163
+ }
2164
+ const sorted = this.sortBy (rates, 'timestamp');
2165
+ return this.filterBySymbolSinceLimit (sorted, market['symbol'], since, limit);
2166
+ }
2167
+
2168
+ async fetchIndexOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
2169
+ const request = {
2170
+ 'price': 'index',
2171
+ };
2172
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
2173
+ }
2174
+
2175
+ parseOHLCV (ohlcv, market = undefined) {
2176
+ //
2177
+ // Spot market candles
2178
+ //
2179
+ // [
2180
+ // "1626163200", // Unix timestamp in seconds
2181
+ // "346711.933138181617", // Trading volume
2182
+ // "33165.23", // Close price
2183
+ // "33260", // Highest price
2184
+ // "33117.6", // Lowest price
2185
+ // "33184.47" // Open price
2186
+ // ]
2187
+ //
2188
+ // Mark and Index price candles
2189
+ //
2190
+ // {
2191
+ // "t":1632873600, // Unix timestamp in seconds
2192
+ // "o": "41025", // Open price
2193
+ // "h": "41882.17", // Highest price
2194
+ // "c": "41776.92", // Close price
2195
+ // "l": "40783.94" // Lowest price
2196
+ // }
2197
+ //
2198
+ if (Array.isArray (ohlcv)) {
2199
+ return [
2200
+ this.safeTimestamp (ohlcv, 0), // unix timestamp in seconds
2201
+ this.safeNumber (ohlcv, 5), // open price
2202
+ this.safeNumber (ohlcv, 3), // highest price
2203
+ this.safeNumber (ohlcv, 4), // lowest price
2204
+ this.safeNumber (ohlcv, 2), // close price
2205
+ this.safeNumber (ohlcv, 1), // trading volume
2206
+ ];
2207
+ } else {
2208
+ // Mark and Index price candles
2209
+ return [
2210
+ this.safeTimestamp (ohlcv, 't'), // unix timestamp in seconds
2211
+ this.safeNumber (ohlcv, 'o'), // open price
2212
+ this.safeNumber (ohlcv, 'h'), // highest price
2213
+ this.safeNumber (ohlcv, 'l'), // lowest price
2214
+ this.safeNumber (ohlcv, 'c'), // close price
2215
+ this.safeNumber (ohlcv, 'v'), // trading volume, undefined for mark or index price
2216
+ ];
2217
+ }
2218
+ }
2219
+
2220
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
2221
+ await this.loadMarkets ();
2222
+ const market = this.market (symbol);
2223
+ //
2224
+ // spot
2225
+ //
2226
+ // const request = {
2227
+ // 'currency_pair': market['id'],
2228
+ // 'limit': limit, // maximum number of records to be returned in a single list
2229
+ // 'last_id': 'id', // specify list staring point using the id of last record in previous list-query results
2230
+ // 'reverse': false, // true to retrieve records where id is smaller than the specified last_id, false to retrieve records where id is larger than the specified last_id
2231
+ // };
2232
+ //
2233
+ // swap, future
2234
+ //
2235
+ // const request = {
2236
+ // 'settle': market['settleId'],
2237
+ // 'contract': market['id'],
2238
+ // 'limit': limit, // maximum number of records to be returned in a single list
2239
+ // 'last_id': 'id', // specify list staring point using the id of last record in previous list-query results
2240
+ // 'from': since / 1000), // starting time in seconds, if not specified, to and limit will be used to limit response items
2241
+ // 'to': this.seconds (), // end time in seconds, default to current time
2242
+ // };
2243
+ //
2244
+ const request = this.prepareRequest (market);
2245
+ const method = this.getSupportedMapping (market['type'], {
2246
+ 'spot': 'publicSpotGetTrades',
2247
+ 'margin': 'publicSpotGetTrades',
2248
+ 'swap': 'publicFuturesGetSettleTrades',
2249
+ 'future': 'publicDeliveryGetSettleTrades',
2250
+ });
2251
+ if (limit !== undefined) {
2252
+ request['limit'] = limit; // default 100, max 1000
2253
+ }
2254
+ if (since !== undefined && (market['contract'])) {
2255
+ request['from'] = parseInt (since / 1000);
2256
+ }
2257
+ const response = await this[method] (this.extend (request, params));
2258
+ //
2259
+ // spot
2260
+ //
2261
+ // [
2262
+ // {
2263
+ // id: "1852958144",
2264
+ // create_time: "1634673259",
2265
+ // create_time_ms: "1634673259378.105000",
2266
+ // currency_pair: "ADA_USDT",
2267
+ // side: "sell",
2268
+ // amount: "307.078",
2269
+ // price: "2.104",
2270
+ // }
2271
+ // ]
2272
+ //
2273
+ // perpetual swap
2274
+ //
2275
+ // [
2276
+ // {
2277
+ // size: "2",
2278
+ // id: "2522911",
2279
+ // create_time_ms: "1634673380.182",
2280
+ // create_time: "1634673380.182",
2281
+ // contract: "ADA_USDT",
2282
+ // price: "2.10486",
2283
+ // }
2284
+ // ]
2285
+ //
2286
+ return this.parseTrades (response, market, since, limit);
2287
+ }
2288
+
2289
+ async fetchMyTrades (symbol = undefined, since = undefined, limit = undefined, params = {}) {
2290
+ await this.loadMarkets ();
2291
+ let market = undefined;
2292
+ let request = {};
2293
+ let type = undefined;
2294
+ [ type, params ] = this.handleMarketTypeAndParams ('fetchMyTrades', undefined, params);
2295
+ if (symbol) {
2296
+ market = this.market (symbol);
2297
+ request = this.prepareRequest (market);
2298
+ type = market['type'];
2299
+ } else {
2300
+ if (type === 'swap' || type === 'future') {
2301
+ const settle = this.safeStringLower (params, 'settle');
2302
+ if (!settle) {
2303
+ throw new ArgumentsRequired (this.id + ' fetchMyTrades() requires a symbol argument or a settle parameter for ' + type + ' markets');
2304
+ }
2305
+ request['settle'] = settle;
2306
+ }
2307
+ }
2308
+ //
2309
+ // const request = {
2310
+ // 'currency_pair': market['id'],
2311
+ // // 'limit': limit,
2312
+ // // 'page': 0,
2313
+ // // 'order_id': 'Order ID',
2314
+ // // 'account': 'spot', // default to spot and margin account if not specified, set to cross_margin to operate against margin account
2315
+ // // 'from': since, // default to 7 days before current time
2316
+ // // 'to': this.milliseconds (), // default to current time
2317
+ // };
2318
+ //
2319
+ if (limit !== undefined) {
2320
+ request['limit'] = limit; // default 100, max 1000
2321
+ }
2322
+ if (since !== undefined) {
2323
+ request['from'] = parseInt (since / 1000);
2324
+ // request['to'] = since + 7 * 24 * 60 * 60;
2325
+ }
2326
+ const method = this.getSupportedMapping (type, {
2327
+ 'spot': 'privateSpotGetMyTrades',
2328
+ 'margin': 'privateSpotGetMyTrades',
2329
+ 'swap': 'privateFuturesGetSettleMyTrades',
2330
+ 'future': 'privateDeliveryGetSettleMyTrades',
2331
+ });
2332
+ const response = await this[method] (this.extend (request, params));
2333
+ //
2334
+ // spot
2335
+ //
2336
+ // [
2337
+ // {
2338
+ // "id": "2876130500",
2339
+ // "create_time": "1645464610",
2340
+ // "create_time_ms": "1645464610777.399200",
2341
+ // "currency_pair": "DOGE_USDT",
2342
+ // "side": "sell",
2343
+ // "role": "taker",
2344
+ // "amount": "10.97",
2345
+ // "price": "0.137384",
2346
+ // "order_id": "125924049993",
2347
+ // "fee": "0.00301420496",
2348
+ // "fee_currency": "USDT",
2349
+ // "point_fee": "0",
2350
+ // "gt_fee": "0"
2351
+ // }
2352
+ // ]
2353
+ //
2354
+ // perpetual swap
2355
+ //
2356
+ // [
2357
+ // {
2358
+ // "size": -5,
2359
+ // "order_id": "130264979823",
2360
+ // "id": 26884791,
2361
+ // "role": "taker",
2362
+ // "create_time": 1645465199.5472,
2363
+ // "contract": "DOGE_USDT",
2364
+ // "price": "0.136888"
2365
+ // }
2366
+ // ]
2367
+ //
2368
+ // future
2369
+ //
2370
+ // [
2371
+ // {
2372
+ // "id": 121234231,
2373
+ // "create_time": 1514764800.123,
2374
+ // "contract": "BTC_USDT",
2375
+ // "order_id": "21893289839",
2376
+ // "size": 100,
2377
+ // "price": "100.123",
2378
+ // "role": "taker"
2379
+ // }
2380
+ // ]
2381
+ //
2382
+ return this.parseTrades (response, market, since, limit);
2383
+ }
2384
+
2385
+ parseTrade (trade, market = undefined) {
2386
+ //
2387
+ // public
2388
+ //
2389
+ // {
2390
+ // "id": "1334253759",
2391
+ // "create_time": "1626342738",
2392
+ // "create_time_ms": "1626342738331.497000",
2393
+ // "currency_pair": "BTC_USDT",
2394
+ // "side": "sell",
2395
+ // "amount": "0.0022",
2396
+ // "price": "32452.16"
2397
+ // }
2398
+ //
2399
+ // public ws
2400
+ //
2401
+ // {
2402
+ // id: 221994511,
2403
+ // time: 1580311438.618647,
2404
+ // price: '9309',
2405
+ // amount: '0.0019',
2406
+ // type: 'sell'
2407
+ // }
2408
+ //
2409
+ // spot rest
2410
+ //
2411
+ // {
2412
+ // "id": "2876130500",
2413
+ // "create_time": "1645464610",
2414
+ // "create_time_ms": "1645464610777.399200",
2415
+ // "currency_pair": "DOGE_USDT",
2416
+ // "side": "sell",
2417
+ // "role": "taker",
2418
+ // "amount": "10.97",
2419
+ // "price": "0.137384",
2420
+ // "order_id": "125924049993",
2421
+ // "fee": "0.00301420496",
2422
+ // "fee_currency": "USDT",
2423
+ // "point_fee": "0","gt_fee":"0"
2424
+ // }
2425
+ //
2426
+ // perpetual swap rest
2427
+ //
2428
+ // {
2429
+ // "size": -5,
2430
+ // "order_id": "130264979823",
2431
+ // "id": 26884791,
2432
+ // "role": "taker",
2433
+ // "create_time": 1645465199.5472,
2434
+ // "contract": "DOGE_USDT",
2435
+ // "price": "0.136888"
2436
+ // }
2437
+ //
2438
+ // future rest
2439
+ //
2440
+ // {
2441
+ // "id": 121234231,
2442
+ // "create_time": 1514764800.123,
2443
+ // "contract": "BTC_USDT",
2444
+ // "order_id": "21893289839",
2445
+ // "size": 100,
2446
+ // "price": "100.123",
2447
+ // "role": "taker"
2448
+ // }
2449
+ //
2450
+ const id = this.safeString (trade, 'id');
2451
+ let timestamp = this.safeTimestamp2 (trade, 'time', 'create_time');
2452
+ timestamp = this.safeInteger (trade, 'create_time_ms', timestamp);
2453
+ const marketId = this.safeString2 (trade, 'currency_pair', 'contract');
2454
+ const symbol = this.safeSymbol (marketId, market);
2455
+ let amountString = this.safeString2 (trade, 'amount', 'size');
2456
+ const priceString = this.safeString (trade, 'price');
2457
+ const contractSide = Precise.stringLt (amountString, '0') ? 'sell' : 'buy';
2458
+ amountString = Precise.stringAbs (amountString);
2459
+ const side = this.safeString2 (trade, 'side', 'type', contractSide);
2460
+ const orderId = this.safeString (trade, 'order_id');
2461
+ const gtFee = this.safeString (trade, 'gt_fee');
2462
+ let feeCurrency = undefined;
2463
+ let feeCostString = undefined;
2464
+ if (gtFee === '0') {
2465
+ feeCurrency = this.safeString (trade, 'fee_currency');
2466
+ feeCostString = this.safeString (trade, 'fee');
2467
+ } else {
2468
+ feeCurrency = 'GT';
2469
+ feeCostString = gtFee;
2470
+ }
2471
+ const fee = {
2472
+ 'cost': feeCostString,
2473
+ 'currency': feeCurrency,
2474
+ };
2475
+ const takerOrMaker = this.safeString (trade, 'role');
2476
+ return this.safeTrade ({
2477
+ 'info': trade,
2478
+ 'id': id,
2479
+ 'timestamp': timestamp,
2480
+ 'datetime': this.iso8601 (timestamp),
2481
+ 'symbol': symbol,
2482
+ 'order': orderId,
2483
+ 'type': undefined,
2484
+ 'side': side,
2485
+ 'takerOrMaker': takerOrMaker,
2486
+ 'price': priceString,
2487
+ 'amount': amountString,
2488
+ 'cost': undefined,
2489
+ 'fee': fee,
2490
+ }, market);
2491
+ }
2492
+
2493
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
2494
+ await this.loadMarkets ();
2495
+ const request = {};
2496
+ let currency = undefined;
2497
+ if (code !== undefined) {
2498
+ currency = this.currency (code);
2499
+ request['currency'] = currency['id'];
2500
+ }
2501
+ if (limit !== undefined) {
2502
+ request['limit'] = limit;
2503
+ }
2504
+ if (since !== undefined) {
2505
+ const start = parseInt (since / 1000);
2506
+ request['from'] = start;
2507
+ request['to'] = this.sum (start, 30 * 24 * 60 * 60);
2508
+ }
2509
+ const response = await this.privateWalletGetDeposits (this.extend (request, params));
2510
+ return this.parseTransactions (response, currency);
2511
+ }
2512
+
2513
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
2514
+ await this.loadMarkets ();
2515
+ const request = {};
2516
+ let currency = undefined;
2517
+ if (code !== undefined) {
2518
+ currency = this.currency (code);
2519
+ request['currency'] = currency['id'];
2520
+ }
2521
+ if (limit !== undefined) {
2522
+ request['limit'] = limit;
2523
+ }
2524
+ if (since !== undefined) {
2525
+ const start = parseInt (since / 1000);
2526
+ request['from'] = start;
2527
+ request['to'] = this.sum (start, 30 * 24 * 60 * 60);
2528
+ }
2529
+ const response = await this.privateWalletGetWithdrawals (this.extend (request, params));
2530
+ return this.parseTransactions (response, currency);
2531
+ }
2532
+
2533
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
2534
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
2535
+ this.checkAddress (address);
2536
+ await this.loadMarkets ();
2537
+ const currency = this.currency (code);
2538
+ const request = {
2539
+ 'currency': currency['id'],
2540
+ 'address': address,
2541
+ 'amount': this.currencyToPrecision (code, amount),
2542
+ };
2543
+ if (tag !== undefined) {
2544
+ request['memo'] = tag;
2545
+ }
2546
+ const networks = this.safeValue (this.options, 'networks', {});
2547
+ let network = this.safeStringUpper (params, 'network'); // this line allows the user to specify either ERC20 or ETH
2548
+ network = this.safeStringLower (networks, network, network); // handle ETH>ERC20 alias
2549
+ if (network !== undefined) {
2550
+ request['chain'] = network;
2551
+ params = this.omit (params, 'network');
2552
+ }
2553
+ const response = await this.privateWithdrawalsPost (this.extend (request, params));
2554
+ //
2555
+ // {
2556
+ // "id": "w13389675",
2557
+ // "currency": "USDT",
2558
+ // "amount": "50",
2559
+ // "address": "TUu2rLFrmzUodiWfYki7QCNtv1akL682p1",
2560
+ // "memo": null
2561
+ // }
2562
+ //
2563
+ return this.parseTransaction (response, currency);
2564
+ }
2565
+
2566
+ parseTransactionStatus (status) {
2567
+ const statuses = {
2568
+ 'PEND': 'pending',
2569
+ 'REQUEST': 'pending',
2570
+ 'DMOVE': 'pending',
2571
+ 'CANCEL': 'failed',
2572
+ 'DONE': 'ok',
2573
+ 'BCODE': 'ok', // GateCode withdrawal
2574
+ };
2575
+ return this.safeString (statuses, status, status);
2576
+ }
2577
+
2578
+ parseTransactionType (type) {
2579
+ const types = {
2580
+ 'd': 'deposit',
2581
+ 'w': 'withdrawal',
2582
+ };
2583
+ return this.safeString (types, type, type);
2584
+ }
2585
+
2586
+ parseTransaction (transaction, currency = undefined) {
2587
+ //
2588
+ // deposits
2589
+ //
2590
+ // {
2591
+ // "id": "d33361395",
2592
+ // "currency": "USDT_TRX",
2593
+ // "address": "TErdnxenuLtXfnMafLbfappYdHtnXQ5U4z",
2594
+ // "amount": "100",
2595
+ // "txid": "ae9374de34e558562fe18cbb1bf9ab4d9eb8aa7669d65541c9fa2a532c1474a0",
2596
+ // "timestamp": "1626345819",
2597
+ // "status": "DONE",
2598
+ // "memo": ""
2599
+ // }
2600
+ //
2601
+ // withdraw
2602
+ //
2603
+ // {
2604
+ // "id": "w13389675",
2605
+ // "currency": "USDT",
2606
+ // "amount": "50",
2607
+ // "address": "TUu2rLFrmzUodiWfYki7QCNtv1akL682p1",
2608
+ // "memo": null
2609
+ // }
2610
+ //
2611
+ const id = this.safeString (transaction, 'id');
2612
+ let type = undefined;
2613
+ let amount = this.safeString (transaction, 'amount');
2614
+ if (id[0] === 'b') {
2615
+ // GateCode handling
2616
+ type = Precise.stringGt (amount, '0') ? 'deposit' : 'withdrawal';
2617
+ amount = Precise.stringAbs (amount);
2618
+ } else if (id !== undefined) {
2619
+ type = this.parseTransactionType (id[0]);
2620
+ }
2621
+ const currencyId = this.safeString (transaction, 'currency');
2622
+ const code = this.safeCurrencyCode (currencyId);
2623
+ const txid = this.safeString (transaction, 'txid');
2624
+ const rawStatus = this.safeString (transaction, 'status');
2625
+ const status = this.parseTransactionStatus (rawStatus);
2626
+ const address = this.safeString (transaction, 'address');
2627
+ const fee = this.safeNumber (transaction, 'fee');
2628
+ let tag = this.safeString (transaction, 'memo');
2629
+ if (tag === '') {
2630
+ tag = undefined;
2631
+ }
2632
+ const timestamp = this.safeTimestamp (transaction, 'timestamp');
2633
+ return {
2634
+ 'info': transaction,
2635
+ 'id': id,
2636
+ 'txid': txid,
2637
+ 'currency': code,
2638
+ 'amount': this.parseNumber (amount),
2639
+ 'network': undefined,
2640
+ 'address': address,
2641
+ 'addressTo': undefined,
2642
+ 'addressFrom': undefined,
2643
+ 'tag': tag,
2644
+ 'tagTo': undefined,
2645
+ 'tagFrom': undefined,
2646
+ 'status': status,
2647
+ 'type': type,
2648
+ 'timestamp': timestamp,
2649
+ 'datetime': this.iso8601 (timestamp),
2650
+ 'updated': undefined,
2651
+ 'fee': fee,
2652
+ };
2653
+ }
2654
+
2655
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
2656
+ /**
2657
+ * @method
2658
+ * @name gateio#createOrder
2659
+ * @description Create an order on the exchange
2660
+ * @param {str} symbol Unified CCXT market symbol
2661
+ * @param {str} type "limit" or "market" *"market" is contract only*
2662
+ * @param {str} side "buy" or "sell"
2663
+ * @param {float} amount the amount of currency to trade
2664
+ * @param {float} price *ignored in "market" orders* the price at which the order is to be fullfilled at in units of the quote currency
2665
+ * @param {dict} params Extra parameters specific to the exchange API endpoint
2666
+ * @param {float} params.stopPrice The price at which a trigger order is triggered at
2667
+ * @param {str} params.timeInForce "GTC", "IOC", or "PO"
2668
+ * @param {str} params.marginType 'cross' or 'isolated' - marginType for margin trading if not provided this.options['defaultMarginType'] is used
2669
+ * @param {int} params.iceberg Amount to display for the iceberg order, Null or 0 for normal orders, Set to -1 to hide the order completely
2670
+ * @param {str} params.text User defined information
2671
+ * @param {str} params.account *spot and margin only* "spot", "margin" or "cross_margin"
2672
+ * @param {bool} params.auto_borrow *margin only* Used in margin or cross margin trading to allow automatic loan of insufficient amount if balance is not enough
2673
+ * @param {str} params.settle *contract only* Unified Currency Code for settle currency
2674
+ * @param {bool} params.reduceOnly *contract only* Indicates if this order is to reduce the size of a position
2675
+ * @param {bool} params.close *contract only* Set as true to close the position, with size set to 0
2676
+ * @param {bool} params.auto_size *contract only* Set side to close dual-mode position, close_long closes the long side, while close_short the short one, size also needs to be set to 0
2677
+ * @returns [An order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
2678
+ */
2679
+ await this.loadMarkets ();
2680
+ const market = this.market (symbol);
2681
+ const contract = market['contract'];
2682
+ const stopPrice = this.safeNumber (params, 'stopPrice');
2683
+ let methodTail = 'Orders';
2684
+ const reduceOnly = this.safeValue2 (params, 'reduce_only', 'reduceOnly');
2685
+ const defaultTimeInForce = this.safeValue2 (params, 'tif', 'time_in_force', 'gtc');
2686
+ let timeInForce = this.safeValue (params, 'timeInForce', defaultTimeInForce);
2687
+ let postOnly = false;
2688
+ [ type, postOnly, timeInForce, params ] = this.isPostOnly (type, timeInForce, undefined, params);
2689
+ params = this.omit (params, [ 'stopPrice', 'reduce_only', 'reduceOnly', 'tif', 'time_in_force', 'timeInForce' ]);
2690
+ if (postOnly) {
2691
+ timeInForce = 'poc';
2692
+ }
2693
+ const isLimitOrder = (type === 'limit');
2694
+ const isMarketOrder = (type === 'market');
2695
+ if (isLimitOrder && price === undefined) {
2696
+ throw new ArgumentsRequired (this.id + ' createOrder() requires a price argument for ' + type + ' orders');
2697
+ }
2698
+ if (contract) {
2699
+ const amountToPrecision = this.amountToPrecision (symbol, amount);
2700
+ const signedAmount = (side === 'sell') ? Precise.stringNeg (amountToPrecision) : amountToPrecision;
2701
+ amount = parseInt (signedAmount);
2702
+ if (isMarketOrder) {
2703
+ timeInForce = 'ioc';
2704
+ price = 0;
2705
+ }
2706
+ } else if (!isLimitOrder) {
2707
+ // Gateio doesn't have market orders for spot
2708
+ throw new InvalidOrder (this.id + ' createOrder() does not support ' + type + ' orders for ' + market['type'] + ' markets');
2709
+ }
2710
+ let request = undefined;
2711
+ const trigger = this.safeValue (params, 'trigger');
2712
+ if (stopPrice === undefined && trigger === undefined) {
2713
+ if (contract) {
2714
+ // contract order
2715
+ request = {
2716
+ 'contract': market['id'], // filled in prepareRequest above
2717
+ 'size': amount, // int64, positive = bid, negative = ask
2718
+ // 'iceberg': 0, // int64, display size for iceberg order, 0 for non-iceberg, note that you will have to pay the taker fee for the hidden size
2719
+ 'price': this.priceToPrecision (symbol, price), // 0 for market order with tif set as ioc
2720
+ // 'close': false, // true to close the position, with size set to 0
2721
+ // 'reduce_only': false, // St as true to be reduce-only order
2722
+ // 'tif': 'gtc', // gtc, ioc, poc PendingOrCancelled == postOnly order
2723
+ // 'text': clientOrderId, // 't-abcdef1234567890',
2724
+ // 'auto_size': '', // close_long, close_short, note size also needs to be set to 0
2725
+ 'settle': market['settleId'], // filled in prepareRequest above
2726
+ };
2727
+ if (reduceOnly !== undefined) {
2728
+ request['reduce_only'] = reduceOnly;
2729
+ }
2730
+ if (timeInForce !== undefined) {
2731
+ request['tif'] = timeInForce;
2732
+ }
2733
+ } else {
2734
+ let marginType = undefined;
2735
+ [ marginType, params ] = this.getMarginType (false, params);
2736
+ params = this.omit (params, 'account');
2737
+ // spot order
2738
+ request = {
2739
+ // 'text': clientOrderId, // 't-abcdef1234567890',
2740
+ 'currency_pair': market['id'], // filled in prepareRequest above
2741
+ 'type': type,
2742
+ 'account': marginType, // 'spot', 'margin', 'cross_margin'
2743
+ 'side': side,
2744
+ 'amount': this.amountToPrecision (symbol, amount),
2745
+ 'price': this.priceToPrecision (symbol, price),
2746
+ // 'time_in_force': 'gtc', // gtc, ioc, poc PendingOrCancelled == postOnly order
2747
+ // 'iceberg': 0, // amount to display for the iceberg order, null or 0 for normal orders, set to -1 to hide the order completely
2748
+ // 'auto_borrow': false, // used in margin or cross margin trading to allow automatic loan of insufficient amount if balance is not enough
2749
+ // 'auto_repay': false, // automatic repayment for automatic borrow loan generated by cross margin order, diabled by default
2750
+ };
2751
+ if (timeInForce !== undefined) {
2752
+ request['time_in_force'] = timeInForce;
2753
+ }
2754
+ }
2755
+ let clientOrderId = this.safeString2 (params, 'text', 'clientOrderId');
2756
+ if (clientOrderId !== undefined) {
2757
+ // user-defined, must follow the rules if not empty
2758
+ // prefixed with t-
2759
+ // no longer than 28 bytes without t- prefix
2760
+ // can only include 0-9, A-Z, a-z, underscores (_), hyphens (-) or dots (.)
2761
+ if (clientOrderId.length > 28) {
2762
+ throw new BadRequest (this.id + ' createOrder() clientOrderId or text param must be up to 28 characters');
2763
+ }
2764
+ params = this.omit (params, [ 'text', 'clientOrderId' ]);
2765
+ if (clientOrderId[0] !== 't') {
2766
+ clientOrderId = 't-' + clientOrderId;
2767
+ }
2768
+ request['text'] = clientOrderId;
2769
+ }
2770
+ } else {
2771
+ if (contract) {
2772
+ // contract conditional order
2773
+ const rule = (side === 'buy') ? 1 : 2;
2774
+ request = {
2775
+ 'initial': {
2776
+ 'contract': market['id'],
2777
+ 'size': amount, // positive = buy, negative = sell, set to 0 to close the position
2778
+ 'price': this.priceToPrecision (symbol, price), // set to 0 to use market price
2779
+ // 'close': false, // set to true if trying to close the position
2780
+ // 'tif': 'gtc', // gtc, ioc, if using market price, only ioc is supported
2781
+ // 'text': clientOrderId, // web, api, app
2782
+ // 'reduce_only': false,
2783
+ },
2784
+ 'trigger': {
2785
+ // 'strategy_type': 0, // 0 = by price, 1 = by price gap, only 0 is supported currently
2786
+ // 'price_type': 0, // 0 latest deal price, 1 mark price, 2 index price
2787
+ 'price': this.priceToPrecision (symbol, stopPrice), // price or gap
2788
+ 'rule': rule, // 1 means price_type >= price, 2 means price_type <= price
2789
+ // 'expiration': expiration, how many seconds to wait for the condition to be triggered before cancelling the order
2790
+ },
2791
+ 'settle': market['settleId'],
2792
+ };
2793
+ const expiration = this.safeInteger (params, 'expiration');
2794
+ if (expiration !== undefined) {
2795
+ request['trigger']['expiration'] = expiration;
2796
+ params = this.omit (params, 'expiration');
2797
+ }
2798
+ if (reduceOnly !== undefined) {
2799
+ request['initial']['reduce_only'] = reduceOnly;
2800
+ }
2801
+ if (timeInForce !== undefined) {
2802
+ request['initial']['tif'] = timeInForce;
2803
+ }
2804
+ } else {
2805
+ // spot conditional order
2806
+ const options = this.safeValue (this.options, 'createOrder', {});
2807
+ let marginType = undefined;
2808
+ [ marginType, params ] = this.getMarginType (true, params);
2809
+ const defaultExpiration = this.safeInteger (options, 'expiration');
2810
+ const expiration = this.safeInteger (params, 'expiration', defaultExpiration);
2811
+ const rule = (side === 'buy') ? '>=' : '<=';
2812
+ const triggerPrice = this.safeValue (trigger, 'price', stopPrice);
2813
+ request = {
2814
+ 'trigger': {
2815
+ 'price': this.priceToPrecision (symbol, triggerPrice),
2816
+ 'rule': rule, // >= triggered when market price larger than or equal to price field, <= triggered when market price less than or equal to price field
2817
+ 'expiration': expiration, // required, how long (in seconds) to wait for the condition to be triggered before cancelling the order
2818
+ },
2819
+ 'put': {
2820
+ 'type': type,
2821
+ 'side': side,
2822
+ 'price': this.priceToPrecision (symbol, price),
2823
+ 'amount': this.amountToPrecision (symbol, amount),
2824
+ 'account': marginType,
2825
+ 'time_in_force': timeInForce, // gtc, ioc for taker only
2826
+ },
2827
+ 'market': market['id'],
2828
+ };
2829
+ }
2830
+ methodTail = 'PriceOrders';
2831
+ }
2832
+ const method = this.getSupportedMapping (market['type'], {
2833
+ 'spot': 'privateSpotPost' + methodTail,
2834
+ 'margin': 'privateSpotPost' + methodTail,
2835
+ 'swap': 'privateFuturesPostSettle' + methodTail,
2836
+ 'future': 'privateDeliveryPostSettle' + methodTail,
2837
+ });
2838
+ const response = await this[method] (this.deepExtend (request, params));
2839
+ //
2840
+ // spot
2841
+ //
2842
+ // {
2843
+ // "id": "95282841887",
2844
+ // "text": "apiv4",
2845
+ // "create_time": "1637383156",
2846
+ // "update_time": "1637383156",
2847
+ // "create_time_ms": 1637383156017,
2848
+ // "update_time_ms": 1637383156017,
2849
+ // "status": "open",
2850
+ // "currency_pair": "ETH_USDT",
2851
+ // "type": "limit",
2852
+ // "account": "spot",
2853
+ // "side": "buy",
2854
+ // "amount": "0.01",
2855
+ // "price": "3500",
2856
+ // "time_in_force": "gtc",
2857
+ // "iceberg": "0",
2858
+ // "left": "0.01",
2859
+ // "fill_price": "0",
2860
+ // "filled_total": "0",
2861
+ // "fee": "0",
2862
+ // "fee_currency": "ETH",
2863
+ // "point_fee": "0",
2864
+ // "gt_fee": "0",
2865
+ // "gt_discount": false,
2866
+ // "rebated_fee": "0",
2867
+ // "rebated_fee_currency": "USDT"
2868
+ // }
2869
+ //
2870
+ // spot conditional
2871
+ //
2872
+ // {"id": 5891843}
2873
+ //
2874
+ // future and perpetual swaps
2875
+ //
2876
+ // {
2877
+ // "id": 95938572327,
2878
+ // "contract": "ETH_USDT",
2879
+ // "mkfr": "0",
2880
+ // "tkfr": "0.0005",
2881
+ // "tif": "gtc",
2882
+ // "is_reduce_only": false,
2883
+ // "create_time": 1637384600.08,
2884
+ // "price": "3000",
2885
+ // "size": 1,
2886
+ // "refr": "0",
2887
+ // "left": 1,
2888
+ // "text": "api",
2889
+ // "fill_price": "0",
2890
+ // "user": 2436035,
2891
+ // "status": "open",
2892
+ // "is_liq": false,
2893
+ // "refu": 0,
2894
+ // "is_close": false,
2895
+ // "iceberg": 0
2896
+ // }
2897
+ //
2898
+ // futures and perpetual swaps conditionals
2899
+ //
2900
+ // {"id": 7615567}
2901
+ //
2902
+ return this.parseOrder (response, market);
2903
+ }
2904
+
2905
+ parseOrderStatus (status) {
2906
+ const statuses = {
2907
+ '_new': 'open',
2908
+ 'filled': 'closed',
2909
+ 'cancelled': 'canceled',
2910
+ 'liquidated': 'closed',
2911
+ };
2912
+ return this.safeString (statuses, status, status);
2913
+ }
2914
+
2915
+ parseOrder (order, market = undefined) {
2916
+ //
2917
+ // SPOT
2918
+ // createOrder/cancelOrder/fetchOrder
2919
+ //
2920
+ // {
2921
+ // "id": "62364648575",
2922
+ // "text": "apiv4",
2923
+ // "create_time": "1626354834",
2924
+ // "update_time": "1626354834",
2925
+ // "create_time_ms": "1626354833544",
2926
+ // "update_time_ms": "1626354833544",
2927
+ // "status": "open",
2928
+ // "currency_pair": "BTC_USDT",
2929
+ // "type": "limit",
2930
+ // "account": "spot",
2931
+ // "side": "buy",
2932
+ // "amount": "0.0001",
2933
+ // "price": "30000",
2934
+ // "time_in_force": "gtc",
2935
+ // "iceberg": "0",
2936
+ // "left": "0.0001",
2937
+ // "fill_price": "0",
2938
+ // "filled_total": "0",
2939
+ // "fee": "0",
2940
+ // "fee_currency": "BTC",
2941
+ // "point_fee": "0",
2942
+ // "gt_fee": "0",
2943
+ // "gt_discount": true,
2944
+ // "rebated_fee": "0",
2945
+ // "rebated_fee_currency": "USDT"
2946
+ // }
2947
+ //
2948
+ // SPOT TRIGGER ORDERS
2949
+ // createOrder
2950
+ //
2951
+ // {
2952
+ // "id": 12604556
2953
+ // }
2954
+ //
2955
+ // fetchOrder/cancelOrder
2956
+ //
2957
+ // {
2958
+ // "market": "ADA_USDT",
2959
+ // "user": 6392049,
2960
+ // "trigger": {
2961
+ // "price": "1.08", // stopPrice
2962
+ // "rule": "\u003e=",
2963
+ // "expiration": 86400
2964
+ // },
2965
+ // "put": {
2966
+ // "type": "limit",
2967
+ // "side": "buy",
2968
+ // "price": "1.08", // order price
2969
+ // "amount": "1.00000000000000000000",
2970
+ // "account": "normal",
2971
+ // "time_in_force": "gtc"
2972
+ // },
2973
+ // "id": 71639298,
2974
+ // "ctime": 1643945985,
2975
+ // "status": "open"
2976
+ // }
2977
+ //
2978
+ // FUTURE AND SWAP
2979
+ // createOrder/cancelOrder/fetchOrder
2980
+ //
2981
+ // {
2982
+ // "id": 123028481731,
2983
+ // "contract": "ADA_USDT",
2984
+ // "mkfr": "-0.00005",
2985
+ // "tkfr": "0.00048",
2986
+ // "tif": "ioc",
2987
+ // "is_reduce_only": false,
2988
+ // "create_time": 1643950262.68,
2989
+ // "finish_time": 1643950262.68,
2990
+ // "price": "0",
2991
+ // "size": 1,
2992
+ // "refr": "0",
2993
+ // "left":0,
2994
+ // "text": "api",
2995
+ // "fill_price": "1.05273",
2996
+ // "user":6329238,
2997
+ // "finish_as": "filled",
2998
+ // "status": "finished",
2999
+ // "is_liq": false,
3000
+ // "refu":0,
3001
+ // "is_close": false,
3002
+ // "iceberg": 0
3003
+ // }
3004
+ //
3005
+ // TRIGGER ORDERS (FUTURE AND SWAP)
3006
+ // createOrder
3007
+ //
3008
+ // {
3009
+ // "id": 12604556
3010
+ // }
3011
+ //
3012
+ // fetchOrder/cancelOrder
3013
+ //
3014
+ // {
3015
+ // "user": 6320300,
3016
+ // "trigger": {
3017
+ // "strategy_type": 0,
3018
+ // "price_type": 0,
3019
+ // "price": "1.03", // stopPrice
3020
+ // "rule": 2,
3021
+ // "expiration": 0
3022
+ // },
3023
+ // "initial": {
3024
+ // "contract": "ADA_USDT",
3025
+ // "size": -1,
3026
+ // "price": "1.02",
3027
+ // "tif": "gtc",
3028
+ // "text": "",
3029
+ // "iceberg": 0,
3030
+ // "is_close": false,
3031
+ // "is_reduce_only": false,
3032
+ // "auto_size": ""
3033
+ // },
3034
+ // "id": 126393906,
3035
+ // "trade_id": 0,
3036
+ // "status": "open",
3037
+ // "reason": "",
3038
+ // "create_time": 1643953482,
3039
+ // "finish_time": 1643953482,
3040
+ // "is_stop_order": false,
3041
+ // "stop_trigger": {
3042
+ // "rule": 0,
3043
+ // "trigger_price": "",
3044
+ // "order_price": ""
3045
+ // },
3046
+ // "me_order_id": 0,
3047
+ // "order_type": ""
3048
+ // }
3049
+ //
3050
+ const put = this.safeValue2 (order, 'put', 'initial');
3051
+ const trigger = this.safeValue (order, 'trigger');
3052
+ let contract = this.safeString (put, 'contract');
3053
+ let type = this.safeString (put, 'type');
3054
+ let timeInForce = this.safeStringUpper2 (put, 'time_in_force', 'tif');
3055
+ let amount = this.safeString2 (put, 'amount', 'size');
3056
+ let side = this.safeString (put, 'side');
3057
+ let price = this.safeString (put, 'price');
3058
+ contract = this.safeString (order, 'contract', contract);
3059
+ type = this.safeString (order, 'type', type);
3060
+ timeInForce = this.safeStringUpper2 (order, 'time_in_force', 'tif', timeInForce);
3061
+ if (timeInForce === 'POC') {
3062
+ timeInForce = 'PO';
3063
+ }
3064
+ const postOnly = (timeInForce === 'PO');
3065
+ amount = this.safeString2 (order, 'amount', 'size', amount);
3066
+ side = this.safeString (order, 'side', side);
3067
+ price = this.safeString (order, 'price', price);
3068
+ let remaining = this.safeString (order, 'left');
3069
+ let filled = Precise.stringSub (amount, remaining);
3070
+ let cost = this.safeString (order, 'filled_total');
3071
+ let rawStatus = undefined;
3072
+ let average = undefined;
3073
+ if (put) {
3074
+ remaining = amount;
3075
+ filled = '0';
3076
+ cost = '0';
3077
+ }
3078
+ if (contract) {
3079
+ const isMarketOrder = Precise.stringEquals (price, '0') && (timeInForce === 'IOC');
3080
+ type = isMarketOrder ? 'market' : 'limit';
3081
+ side = Precise.stringGt (amount, '0') ? 'buy' : 'sell';
3082
+ rawStatus = this.safeString (order, 'finish_as', 'open');
3083
+ average = this.safeNumber (order, 'fill_price');
3084
+ } else {
3085
+ rawStatus = this.safeString (order, 'status');
3086
+ }
3087
+ let timestamp = this.safeInteger (order, 'create_time_ms');
3088
+ if (timestamp === undefined) {
3089
+ timestamp = this.safeTimestamp2 (order, 'create_time', 'ctime');
3090
+ }
3091
+ let lastTradeTimestamp = this.safeInteger (order, 'update_time_ms');
3092
+ if (lastTradeTimestamp === undefined) {
3093
+ lastTradeTimestamp = this.safeTimestamp2 (order, 'update_time', 'finish_time');
3094
+ }
3095
+ const exchangeSymbol = this.safeString2 (order, 'currency_pair', 'market', contract);
3096
+ // Everything below this(above return) is related to fees
3097
+ const fees = [];
3098
+ const gtFee = this.safeString (order, 'gt_fee');
3099
+ if (gtFee) {
3100
+ fees.push ({
3101
+ 'currency': 'GT',
3102
+ 'cost': gtFee,
3103
+ });
3104
+ }
3105
+ const fee = this.safeString (order, 'fee');
3106
+ if (fee) {
3107
+ fees.push ({
3108
+ 'currency': this.safeCurrencyCode (this.safeString (order, 'fee_currency')),
3109
+ 'cost': fee,
3110
+ });
3111
+ }
3112
+ const rebate = this.safeString (order, 'rebated_fee');
3113
+ if (rebate) {
3114
+ fees.push ({
3115
+ 'currency': this.safeCurrencyCode (this.safeString (order, 'rebated_fee_currency')),
3116
+ 'cost': Precise.stringNeg (rebate),
3117
+ });
3118
+ }
3119
+ const numFeeCurrencies = fees.length;
3120
+ const multipleFeeCurrencies = numFeeCurrencies > 1;
3121
+ const status = this.parseOrderStatus (rawStatus);
3122
+ return this.safeOrder ({
3123
+ 'id': this.safeString (order, 'id'),
3124
+ 'clientOrderId': this.safeString (order, 'text'),
3125
+ 'timestamp': timestamp,
3126
+ 'datetime': this.iso8601 (timestamp),
3127
+ 'lastTradeTimestamp': lastTradeTimestamp,
3128
+ 'status': status,
3129
+ 'symbol': this.safeSymbol (exchangeSymbol),
3130
+ 'type': type,
3131
+ 'timeInForce': timeInForce,
3132
+ 'postOnly': postOnly,
3133
+ 'side': side,
3134
+ 'price': this.parseNumber (price),
3135
+ 'stopPrice': this.safeNumber (trigger, 'price'),
3136
+ 'average': average,
3137
+ 'amount': this.parseNumber (Precise.stringAbs (amount)),
3138
+ 'cost': Precise.stringAbs (cost),
3139
+ 'filled': this.parseNumber (Precise.stringAbs (filled)),
3140
+ 'remaining': this.parseNumber (Precise.stringAbs (remaining)),
3141
+ 'fee': multipleFeeCurrencies ? undefined : this.safeValue (fees, 0),
3142
+ 'fees': multipleFeeCurrencies ? fees : [],
3143
+ 'trades': undefined,
3144
+ 'info': order,
3145
+ }, market);
3146
+ }
3147
+
3148
+ async createReduceOnlyOrder (symbol, type, side, amount, price = undefined, params = {}) {
3149
+ const request = {
3150
+ 'reduceOnly': true,
3151
+ };
3152
+ return await this.createOrder (symbol, type, side, amount, price, this.extend (request, params));
3153
+ }
3154
+
3155
+ async fetchOrder (id, symbol = undefined, params = {}) {
3156
+ /**
3157
+ * @method
3158
+ * @name gateio#fetchOrder
3159
+ * @description Retrieves information on an order
3160
+ * @param {str} id Order id
3161
+ * @param {str} symbol Unified market symbol
3162
+ * @param {dict} params Parameters specified by the exchange api
3163
+ * @param {bool} params.stop True if the order being fetched is a trigger order
3164
+ * @param {str} params.marginType 'cross' or 'isolated' - marginType for margin trading if not provided this.options['defaultMarginType'] is used
3165
+ * @param {str} params.type 'spot', 'swap', or 'future', if not provided this.options['defaultMarginType'] is used
3166
+ * @param {str} params.settle 'btc' or 'usdt' - settle currency for perpetual swap and future - market settle currency is used if symbol !== undefined, default="usdt" for swap and "btc" for future
3167
+ * @returns An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3168
+ */
3169
+ await this.loadMarkets ();
3170
+ const stop = this.safeValue2 (params, 'is_stop_order', 'stop', false);
3171
+ params = this.omit (params, [ 'is_stop_order', 'stop' ]);
3172
+ let clientOrderId = this.safeString2 (params, 'text', 'clientOrderId');
3173
+ let orderId = id;
3174
+ if (clientOrderId !== undefined) {
3175
+ params = this.omit (params, [ 'text', 'clientOrderId' ]);
3176
+ if (clientOrderId[0] !== 't') {
3177
+ clientOrderId = 't-' + clientOrderId;
3178
+ }
3179
+ orderId = clientOrderId;
3180
+ }
3181
+ const request = {
3182
+ 'order_id': orderId,
3183
+ };
3184
+ let market = undefined;
3185
+ let settle = undefined;
3186
+ let type = undefined;
3187
+ if (symbol !== undefined) {
3188
+ market = this.market (symbol);
3189
+ if (market['spot']) {
3190
+ request['currency_pair'] = market['id'];
3191
+ } else {
3192
+ settle = market['settle'];
3193
+ }
3194
+ }
3195
+ [ type, params ] = this.handleMarketTypeAndParams ('fetchOrder', market, params);
3196
+ if (!stop && type === 'spot' && symbol === undefined) {
3197
+ // Symbol not required for stop orders
3198
+ throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument for spot orders');
3199
+ }
3200
+ const swap = type === 'swap';
3201
+ if (swap || type === 'future') {
3202
+ if (settle === undefined) {
3203
+ const defaultSettle = swap ? 'usdt' : 'btc';
3204
+ settle = this.safeStringLower (params, 'settle', defaultSettle);
3205
+ params = this.omit (params, 'settle');
3206
+ }
3207
+ request['settle'] = settle;
3208
+ } else {
3209
+ let marginType = undefined;
3210
+ [ marginType, params ] = this.getMarginType (stop, params);
3211
+ request['account'] = marginType;
3212
+ }
3213
+ let method = undefined;
3214
+ if (stop) {
3215
+ method = this.getSupportedMapping (type, {
3216
+ 'spot': 'privateSpotGetPriceOrdersOrderId',
3217
+ 'margin': 'privateSpotGetPriceOrdersOrderId',
3218
+ 'swap': 'privateFuturesGetSettlePriceOrdersOrderId',
3219
+ 'future': 'privateDeliveryGetSettlePriceOrdersOrderId',
3220
+ });
3221
+ } else {
3222
+ method = this.getSupportedMapping (type, {
3223
+ 'spot': 'privateSpotGetOrdersOrderId',
3224
+ 'margin': 'privateSpotGetOrdersOrderId',
3225
+ 'swap': 'privateFuturesGetSettleOrdersOrderId',
3226
+ 'future': 'privateDeliveryGetSettleOrdersOrderId',
3227
+ });
3228
+ }
3229
+ const response = await this[method] (this.extend (request, params));
3230
+ return this.parseOrder (response, market);
3231
+ }
3232
+
3233
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
3234
+ /**
3235
+ * @description fetches all open orders
3236
+ * @param {str} symbol Unified market symbol
3237
+ * @param {int} since earliest time in ms for orders in the response
3238
+ * @param {int} limit max number of order structures to return
3239
+ * @param {dict} params exchange specific params
3240
+ * @param {str} params.type spot, margin, swap or future, if not provided this.options['defaultType'] is used
3241
+ * @param {str} params.marginType 'cross' or 'isolated' - marginType for type='margin', if not provided this.options['defaultMarginType'] is used
3242
+ * @returns An array of order structures
3243
+ */
3244
+ await this.loadMarkets ();
3245
+ let type = undefined;
3246
+ [ type, params ] = this.handleMarketTypeAndParams ('fetchOpenOrders', undefined, params);
3247
+ if (symbol === undefined && (type === 'spot') || type === 'margin' || type === 'cross_margin') {
3248
+ const request = {
3249
+ // 'page': 1,
3250
+ // 'limit': limit,
3251
+ 'account': type, // spot/margin (default), cross_margin
3252
+ };
3253
+ if (limit !== undefined) {
3254
+ request['limit'] = limit;
3255
+ }
3256
+ const response = await this.privateSpotGetOpenOrders (this.extend (request, params));
3257
+ //
3258
+ // [
3259
+ // {
3260
+ // "currency_pair": "ETH_BTC",
3261
+ // "total": 1,
3262
+ // "orders": [
3263
+ // {
3264
+ // "id": "12332324",
3265
+ // "text": "t-123456",
3266
+ // "create_time": "1548000000",
3267
+ // "update_time": "1548000100",
3268
+ // "currency_pair": "ETH_BTC",
3269
+ // "status": "open",
3270
+ // "type": "limit",
3271
+ // "account": "spot",
3272
+ // "side": "buy",
3273
+ // "amount": "1",
3274
+ // "price": "5.00032",
3275
+ // "time_in_force": "gtc",
3276
+ // "left": "0.5",
3277
+ // "filled_total": "2.50016",
3278
+ // "fee": "0.005",
3279
+ // "fee_currency": "ETH",
3280
+ // "point_fee": "0",
3281
+ // "gt_fee": "0",
3282
+ // "gt_discount": false,
3283
+ // "rebated_fee": "0",
3284
+ // "rebated_fee_currency": "BTC"
3285
+ // }
3286
+ // ]
3287
+ // },
3288
+ // ...
3289
+ // ]
3290
+ //
3291
+ // price_orders
3292
+ //
3293
+ // [
3294
+ // {
3295
+ // "market": "ADA_USDT",
3296
+ // "user": 6693577,
3297
+ // "trigger": {
3298
+ // "price": "0.9",
3299
+ // "rule": "\u003c=",
3300
+ // "expiration": 86400
3301
+ // },
3302
+ // "put": {
3303
+ // "type": "limit",
3304
+ // "side": "sell",
3305
+ // "price": "0.9",
3306
+ // "amount": "2.00000000000000000000",
3307
+ // "account": "margin",
3308
+ // "time_in_force": "gtc"
3309
+ // },
3310
+ // "id": 8308730,
3311
+ // "ctime": 1650434238,
3312
+ // "status": "open"
3313
+ // }
3314
+ // ]
3315
+ //
3316
+ let allOrders = [];
3317
+ for (let i = 0; i < response.length; i++) {
3318
+ const entry = response[i];
3319
+ const orders = this.safeValue (entry, 'orders', []);
3320
+ const parsed = this.parseOrders (orders, undefined, since, limit);
3321
+ allOrders = this.arrayConcat (allOrders, parsed);
3322
+ }
3323
+ return this.filterBySinceLimit (allOrders, since, limit);
3324
+ }
3325
+ return await this.fetchOrdersByStatus ('open', symbol, since, limit, params);
3326
+ }
3327
+
3328
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
3329
+ return await this.fetchOrdersByStatus ('finished', symbol, since, limit, params);
3330
+ }
3331
+
3332
+ async fetchOrdersByStatus (status, symbol = undefined, since = undefined, limit = undefined, params = {}) {
3333
+ if (symbol === undefined) {
3334
+ throw new ArgumentsRequired (this.id + ' fetchOrdersByStatus() requires a symbol argument');
3335
+ }
3336
+ await this.loadMarkets ();
3337
+ const market = this.market (symbol);
3338
+ const request = this.prepareRequest (market);
3339
+ request['status'] = status;
3340
+ if (limit !== undefined) {
3341
+ request['limit'] = limit;
3342
+ }
3343
+ if (since !== undefined && (market['spot'] || market['margin'])) {
3344
+ request['from'] = parseInt (since / 1000);
3345
+ }
3346
+ const method = this.getSupportedMapping (market['type'], {
3347
+ 'spot': 'privateSpotGetOrders',
3348
+ 'margin': 'privateSpotGetOrders',
3349
+ 'swap': 'privateFuturesGetSettleOrders',
3350
+ 'future': 'privateDeliveryGetSettleOrders',
3351
+ });
3352
+ if (market['type'] === 'margin' || market['type'] === 'cross_margin') {
3353
+ request['account'] = market['type'];
3354
+ }
3355
+ const response = await this[method] (this.extend (request, params));
3356
+ //
3357
+ // SPOT
3358
+ //
3359
+ // {
3360
+ // "id": "8834234273",
3361
+ // "text": "3",
3362
+ // "create_time": "1635406193",
3363
+ // "update_time": "1635406193",
3364
+ // "create_time_ms": 1635406193361,
3365
+ // "update_time_ms": 1635406193361,
3366
+ // "status": "closed",
3367
+ // "currency_pair": "BTC_USDT",
3368
+ // "type": "limit",
3369
+ // "account": "spot",
3370
+ // "side": "sell",
3371
+ // "amount": "0.0002",
3372
+ // "price": "58904.01",
3373
+ // "time_in_force": "gtc",
3374
+ // "iceberg": "0",
3375
+ // "left": "0.0000",
3376
+ // "fill_price": "11.790516",
3377
+ // "filled_total": "11.790516",
3378
+ // "fee": "0.023581032",
3379
+ // "fee_currency": "USDT",
3380
+ // "point_fee": "0",
3381
+ // "gt_fee": "0",
3382
+ // "gt_discount": false,
3383
+ // "rebated_fee_currency": "BTC"
3384
+ // }
3385
+ //
3386
+ // Perpetual Swap
3387
+ //
3388
+ // {
3389
+ // "status": "finished",
3390
+ // "size": -1,
3391
+ // "left": 0,
3392
+ // "id": 82750739203,
3393
+ // "is_liq": false,
3394
+ // "is_close": false,
3395
+ // "contract": "BTC_USDT",
3396
+ // "text": "web",
3397
+ // "fill_price": "60721.3",
3398
+ // "finish_as": "filled",
3399
+ // "iceberg": 0,
3400
+ // "tif": "ioc",
3401
+ // "is_reduce_only": true,
3402
+ // "create_time": 1635403475.412,
3403
+ // "finish_time": 1635403475.4127,
3404
+ // "price": "0"
3405
+ // }
3406
+ //
3407
+ return this.parseOrders (response, market, since, limit);
3408
+ }
3409
+
3410
+ async cancelOrder (id, symbol = undefined, params = {}) {
3411
+ /**
3412
+ * @method
3413
+ * @name gateio#cancelOrder
3414
+ * @description Cancels an open order
3415
+ * @param {str} id Order id
3416
+ * @param {str} symbol Unified market symbol
3417
+ * @param {dict} params Parameters specified by the exchange api
3418
+ * @param {bool} params.stop True if the order to be cancelled is a trigger order
3419
+ * @returns An [order structure]{@link https://docs.ccxt.com/en/latest/manual.html#order-structure}
3420
+ */
3421
+ if (symbol === undefined) {
3422
+ throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
3423
+ }
3424
+ await this.loadMarkets ();
3425
+ const market = this.market (symbol);
3426
+ const request = {
3427
+ 'order_id': id,
3428
+ };
3429
+ if (market['contract']) {
3430
+ request['settle'] = market['settleId'];
3431
+ } else {
3432
+ request['currency_pair'] = market['id'];
3433
+ }
3434
+ const stop = this.safeValue2 (params, 'is_stop_order', 'stop', false);
3435
+ params = this.omit (params, [ 'is_stop_order', 'stop' ]);
3436
+ const pathMiddle = stop ? 'Price' : '';
3437
+ const method = this.getSupportedMapping (market['type'], {
3438
+ 'spot': 'privateSpotDelete' + pathMiddle + 'OrdersOrderId',
3439
+ 'margin': 'privateSpotDelete' + pathMiddle + 'OrdersOrderId',
3440
+ 'swap': 'privateFuturesDeleteSettle' + pathMiddle + 'OrdersOrderId',
3441
+ 'future': 'privateDeliveryDeleteSettle' + pathMiddle + 'OrdersOrderId',
3442
+ });
3443
+ const response = await this[method] (this.extend (request, params));
3444
+ //
3445
+ // spot
3446
+ //
3447
+ // {
3448
+ // "id": "95282841887",
3449
+ // "text": "apiv4",
3450
+ // "create_time": "1637383156",
3451
+ // "update_time": "1637383235",
3452
+ // "create_time_ms": 1637383156017,
3453
+ // "update_time_ms": 1637383235085,
3454
+ // "status": "cancelled",
3455
+ // "currency_pair": "ETH_USDT",
3456
+ // "type": "limit",
3457
+ // "account": "spot",
3458
+ // "side": "buy",
3459
+ // "amount": "0.01",
3460
+ // "price": "3500",
3461
+ // "time_in_force": "gtc",
3462
+ // "iceberg": "0",
3463
+ // "left": "0.01",
3464
+ // "fill_price": "0",
3465
+ // "filled_total": "0",
3466
+ // "fee": "0",
3467
+ // "fee_currency": "ETH",
3468
+ // "point_fee": "0",
3469
+ // "gt_fee": "0",
3470
+ // "gt_discount": false,
3471
+ // "rebated_fee": "0",
3472
+ // "rebated_fee_currency": "USDT"
3473
+ // }
3474
+ //
3475
+ // spot conditional
3476
+ //
3477
+ // {
3478
+ // "market": "ETH_USDT",
3479
+ // "user": 2436035,
3480
+ // "trigger": {
3481
+ // "price": "3500",
3482
+ // "rule": "\u003c=",
3483
+ // "expiration": 86400
3484
+ // },
3485
+ // "put": {
3486
+ // "type": "limit",
3487
+ // "side": "buy",
3488
+ // "price": "3500",
3489
+ // "amount": "0.01000000000000000000",
3490
+ // "account": "normal",
3491
+ // "time_in_force": "gtc"
3492
+ // },
3493
+ // "id": 5891843,
3494
+ // "ctime": 1637382379,
3495
+ // "ftime": 1637382673,
3496
+ // "status": "canceled"
3497
+ // }
3498
+ //
3499
+ // perpetual swaps
3500
+ //
3501
+ // {
3502
+ // id: "82241928192",
3503
+ // contract: "BTC_USDT",
3504
+ // mkfr: "0",
3505
+ // tkfr: "0.0005",
3506
+ // tif: "gtc",
3507
+ // is_reduce_only: false,
3508
+ // create_time: "1635196145.06",
3509
+ // finish_time: "1635196233.396",
3510
+ // price: "61000",
3511
+ // size: "4",
3512
+ // refr: "0",
3513
+ // left: "4",
3514
+ // text: "web",
3515
+ // fill_price: "0",
3516
+ // user: "6693577",
3517
+ // finish_as: "cancelled",
3518
+ // status: "finished",
3519
+ // is_liq: false,
3520
+ // refu: "0",
3521
+ // is_close: false,
3522
+ // iceberg: "0",
3523
+ // }
3524
+ //
3525
+ return this.parseOrder (response, market);
3526
+ }
3527
+
3528
+ async cancelAllOrders (symbol = undefined, params = {}) {
3529
+ await this.loadMarkets ();
3530
+ let request = {};
3531
+ let market = undefined;
3532
+ if (symbol !== undefined) {
3533
+ market = this.market (symbol);
3534
+ request = this.prepareRequest (market);
3535
+ }
3536
+ const [ type, query ] = this.handleMarketTypeAndParams ('cancelAllOrders', market, params);
3537
+ const swap = type === 'swap';
3538
+ const future = type === 'future';
3539
+ if (symbol === undefined && (swap || future)) {
3540
+ const defaultSettle = swap ? 'usdt' : 'btc';
3541
+ const settle = this.safeStringLower (params, 'settle', defaultSettle);
3542
+ request['settle'] = settle;
3543
+ }
3544
+ const method = this.getSupportedMapping (type, {
3545
+ 'spot': 'privateSpotDeleteOrders',
3546
+ 'margin': 'privateSpotDeleteOrders',
3547
+ 'swap': 'privateFuturesDeleteSettleOrders',
3548
+ 'future': 'privateDeliveryDeleteSettleOrders',
3549
+ });
3550
+ const response = await this[method] (this.extend (request, query));
3551
+ //
3552
+ // [
3553
+ // {
3554
+ // "id": 139797004085,
3555
+ // "contract": "ADA_USDT",
3556
+ // "mkfr": "0",
3557
+ // "tkfr": "0.0005",
3558
+ // "tif": "gtc",
3559
+ // "is_reduce_only": false,
3560
+ // "create_time": 1647911169.343,
3561
+ // "finish_time": 1647911226.849,
3562
+ // "price": "0.8",
3563
+ // "size": 1,
3564
+ // "refr": "0.3",
3565
+ // "left": 1,
3566
+ // "text": "api",
3567
+ // "fill_price": "0",
3568
+ // "user": 6693577,
3569
+ // "finish_as": "cancelled",
3570
+ // "status": "finished",
3571
+ // "is_liq": false,
3572
+ // "refu": 2436035,
3573
+ // "is_close": false,
3574
+ // "iceberg": 0
3575
+ // }
3576
+ // ...
3577
+ // ]
3578
+ //
3579
+ return this.parseOrders (response, market);
3580
+ }
3581
+
3582
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
3583
+ /**
3584
+ * @method
3585
+ * @name gateio#transfer
3586
+ * @description makes internal transfers of funds between accounts on the same exchange
3587
+ * @param {str} code unified currency code for currency being transferred
3588
+ * @param {float} amount the amount of currency to transfer
3589
+ * @param {str} fromAccount the account to transfer currency from
3590
+ * @param {str} toAccount the account to transfer currency to
3591
+ * @param {dict} params Exchange specific parameters
3592
+ * @param {dict} params.symbol Unified market symbol *required for type == margin*
3593
+ * @returns A [transfer structure]{@link https://docs.ccxt.com/en/latest/manual.html#transfer-structure}
3594
+ */
3595
+ await this.loadMarkets ();
3596
+ const currency = this.currency (code);
3597
+ const accountsByType = this.safeValue (this.options, 'accountsByType', {});
3598
+ const fromId = this.safeString (accountsByType, fromAccount, fromAccount);
3599
+ const toId = this.safeString (accountsByType, toAccount, toAccount);
3600
+ if (fromId === undefined) {
3601
+ const keys = Object.keys (accountsByType);
3602
+ throw new ExchangeError (this.id + ' transfer() fromAccount must be one of ' + keys.join (', '));
3603
+ }
3604
+ if (toId === undefined) {
3605
+ const keys = Object.keys (accountsByType);
3606
+ throw new ExchangeError (this.id + ' transfer() toAccount must be one of ' + keys.join (', '));
3607
+ }
3608
+ const truncated = this.currencyToPrecision (code, amount);
3609
+ const request = {
3610
+ 'currency': currency['id'],
3611
+ 'from': fromId,
3612
+ 'to': toId,
3613
+ 'amount': truncated,
3614
+ };
3615
+ if (fromAccount === 'margin' || toAccount === 'margin') {
3616
+ const symbol = this.safeString2 (params, 'symbol', 'currency_pair');
3617
+ if (symbol === undefined) {
3618
+ throw new ArgumentsRequired (this.id + ' transfer() requires params.symbol for isolated margin transfers');
3619
+ }
3620
+ const market = this.market (symbol);
3621
+ request['currency_pair'] = market['id'];
3622
+ params = this.omit (params, 'symbol');
3623
+ }
3624
+ if ((toId === 'futures') || (toId === 'delivery') || (fromId === 'futures') || (fromId === 'delivery')) {
3625
+ request['settle'] = currency['lowerCaseId'];
3626
+ }
3627
+ const response = await this.privateWalletPostTransfers (this.extend (request, params));
3628
+ //
3629
+ // according to the docs (however actual response seems to be an empty string '')
3630
+ //
3631
+ // {
3632
+ // "currency": "BTC",
3633
+ // "from": "spot",
3634
+ // "to": "margin",
3635
+ // "amount": "1",
3636
+ // "currency_pair": "BTC_USDT"
3637
+ // }
3638
+ //
3639
+ const transfer = this.parseTransfer (response, currency);
3640
+ return this.extend (transfer, {
3641
+ 'fromAccount': fromAccount,
3642
+ 'toAccount': toAccount,
3643
+ 'amount': this.parseNumber (truncated),
3644
+ });
3645
+ }
3646
+
3647
+ parseTransfer (transfer, currency = undefined) {
3648
+ const timestamp = this.milliseconds ();
3649
+ return {
3650
+ 'id': undefined,
3651
+ 'timestamp': timestamp,
3652
+ 'datetime': this.iso8601 (timestamp),
3653
+ 'currency': this.safeCurrencyCode (undefined, currency),
3654
+ 'amount': undefined,
3655
+ 'fromAccount': undefined,
3656
+ 'toAccount': undefined,
3657
+ 'status': undefined,
3658
+ 'info': transfer,
3659
+ };
3660
+ }
3661
+
3662
+ async setLeverage (leverage, symbol = undefined, params = {}) {
3663
+ if (symbol === undefined) {
3664
+ throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
3665
+ }
3666
+ // WARNING: THIS WILL INCREASE LIQUIDATION PRICE FOR OPEN ISOLATED LONG POSITIONS
3667
+ // AND DECREASE LIQUIDATION PRICE FOR OPEN ISOLATED SHORT POSITIONS
3668
+ if ((leverage < 0) || (leverage > 100)) {
3669
+ throw new BadRequest (this.id + ' setLeverage() leverage should be between 1 and 100');
3670
+ }
3671
+ await this.loadMarkets ();
3672
+ const market = this.market (symbol);
3673
+ const method = this.getSupportedMapping (market['type'], {
3674
+ 'swap': 'privateFuturesPostSettlePositionsContractLeverage',
3675
+ 'future': 'privateDeliveryPostSettlePositionsContractLeverage',
3676
+ });
3677
+ const request = this.prepareRequest (market);
3678
+ const defaultMarginType = this.safeString2 (this.options, 'marginType', 'defaultMarginType');
3679
+ const crossLeverageLimit = this.safeString (params, 'cross_leverage_limit');
3680
+ let marginType = this.safeString (params, 'marginType', defaultMarginType);
3681
+ if (crossLeverageLimit !== undefined) {
3682
+ marginType = 'cross';
3683
+ leverage = crossLeverageLimit;
3684
+ }
3685
+ if (marginType === 'cross') {
3686
+ request['query'] = {
3687
+ 'cross_leverage_limit': leverage.toString (),
3688
+ 'leverage': '0',
3689
+ };
3690
+ } else {
3691
+ request['query'] = {
3692
+ 'leverage': leverage.toString (),
3693
+ };
3694
+ }
3695
+ const response = await this[method] (this.extend (request, params));
3696
+ //
3697
+ // {
3698
+ // "value": "0",
3699
+ // "leverage": "5",
3700
+ // "mode": "single",
3701
+ // "realised_point": "0",
3702
+ // "contract": "BTC_USDT",
3703
+ // "entry_price": "0",
3704
+ // "mark_price": "62035.86",
3705
+ // "history_point": "0",
3706
+ // "realised_pnl": "0",
3707
+ // "close_order": null,
3708
+ // "size": 0,
3709
+ // "cross_leverage_limit": "0",
3710
+ // "pending_orders": 0,
3711
+ // "adl_ranking": 6,
3712
+ // "maintenance_rate": "0.005",
3713
+ // "unrealised_pnl": "0",
3714
+ // "user": 2436035,
3715
+ // "leverage_max": "100",
3716
+ // "history_pnl": "0",
3717
+ // "risk_limit": "1000000",
3718
+ // "margin": "0",
3719
+ // "last_close_pnl": "0",
3720
+ // "liq_price": "0"
3721
+ // }
3722
+ //
3723
+ return response;
3724
+ }
3725
+
3726
+ parsePosition (position, market = undefined) {
3727
+ //
3728
+ // {
3729
+ // value: "12.475572",
3730
+ // leverage: "0",
3731
+ // mode: "single",
3732
+ // realised_point: "0",
3733
+ // contract: "BTC_USDT",
3734
+ // entry_price: "62422.6",
3735
+ // mark_price: "62377.86",
3736
+ // history_point: "0",
3737
+ // realised_pnl: "-0.00624226",
3738
+ // close_order: null,
3739
+ // size: "2",
3740
+ // cross_leverage_limit: "25",
3741
+ // pending_orders: "0",
3742
+ // adl_ranking: "5",
3743
+ // maintenance_rate: "0.005",
3744
+ // unrealised_pnl: "-0.008948",
3745
+ // user: "663337",
3746
+ // leverage_max: "100",
3747
+ // history_pnl: "14.98868396636",
3748
+ // risk_limit: "1000000",
3749
+ // margin: "0.740721495056",
3750
+ // last_close_pnl: "-0.041996015",
3751
+ // liq_price: "59058.58"
3752
+ // }
3753
+ //
3754
+ const contract = this.safeString (position, 'contract');
3755
+ market = this.safeMarket (contract, market);
3756
+ const size = this.safeString (position, 'size');
3757
+ let side = undefined;
3758
+ if (Precise.stringGt (size, '0')) {
3759
+ side = 'long';
3760
+ } else if (Precise.stringLt (size, '0')) {
3761
+ side = 'short';
3762
+ }
3763
+ const maintenanceRate = this.safeString (position, 'maintenance_rate');
3764
+ const notional = this.safeString (position, 'value');
3765
+ const leverage = this.safeString (position, 'leverage');
3766
+ let marginType = undefined;
3767
+ if (leverage === '0') {
3768
+ marginType = 'cross';
3769
+ } else {
3770
+ marginType = 'isolated';
3771
+ }
3772
+ const unrealisedPnl = this.safeString (position, 'unrealised_pnl');
3773
+ // Initial Position Margin = ( Position Value / Leverage ) + Close Position Fee
3774
+ // *The default leverage under the full position is the highest leverage in the market.
3775
+ // *Trading fee is charged as Taker Fee Rate (0.075%).
3776
+ const takerFee = '0.00075';
3777
+ const feePaid = Precise.stringMul (takerFee, notional);
3778
+ const initialMarginString = Precise.stringAdd (Precise.stringDiv (notional, leverage), feePaid);
3779
+ const percentage = Precise.stringMul (Precise.stringDiv (unrealisedPnl, initialMarginString), '100');
3780
+ return {
3781
+ 'info': position,
3782
+ 'symbol': this.safeString (market, 'symbol'),
3783
+ 'timestamp': undefined,
3784
+ 'datetime': undefined,
3785
+ 'initialMargin': this.parseNumber (initialMarginString),
3786
+ 'initialMarginPercentage': this.parseNumber (Precise.stringDiv (initialMarginString, notional)),
3787
+ 'maintenanceMargin': this.parseNumber (Precise.stringMul (maintenanceRate, notional)),
3788
+ 'maintenanceMarginPercentage': this.parseNumber (maintenanceRate),
3789
+ 'entryPrice': this.safeNumber (position, 'entry_price'),
3790
+ 'notional': this.parseNumber (notional),
3791
+ 'leverage': this.safeNumber (position, 'leverage'),
3792
+ 'unrealizedPnl': this.parseNumber (unrealisedPnl),
3793
+ 'contracts': this.parseNumber (Precise.stringAbs (size)),
3794
+ 'contractSize': this.safeValue (market, 'contractSize'),
3795
+ // realisedPnl: position['realised_pnl'],
3796
+ 'marginRatio': undefined,
3797
+ 'liquidationPrice': this.safeNumber (position, 'liq_price'),
3798
+ 'markPrice': this.safeNumber (position, 'mark_price'),
3799
+ 'collateral': this.safeNumber (position, 'margin'),
3800
+ 'marginType': marginType,
3801
+ 'side': side,
3802
+ 'percentage': this.parseNumber (percentage),
3803
+ };
3804
+ }
3805
+
3806
+ parsePositions (positions) {
3807
+ const result = [];
3808
+ for (let i = 0; i < positions.length; i++) {
3809
+ result.push (this.parsePosition (positions[i]));
3810
+ }
3811
+ return result;
3812
+ }
3813
+
3814
+ async fetchPositions (symbols = undefined, params = {}) {
3815
+ /**
3816
+ * @method
3817
+ * @name gateio#fetchPositions
3818
+ * @description Fetch trades positions
3819
+ * @param {[str]} symbols Not used by Gateio, but parsed internally by CCXT
3820
+ * @param {dict} params exchange specific parameters
3821
+ * @param {str} params.settle 'btc' or 'usdt' - settle currency for perpetual swap and future - default="usdt" for swap and "btc" for future
3822
+ * @param {str} params.type swap or future, if not provided this.options['defaultType'] is used
3823
+ * @returns An array of [position structures]{@link https://docs.ccxt.com/en/latest/manual.html#position-structure}
3824
+ */
3825
+ await this.loadMarkets ();
3826
+ const defaultType = this.safeString2 (this.options, 'fetchPositions', 'defaultType', 'swap');
3827
+ const type = this.safeString (params, 'type', defaultType);
3828
+ const method = this.getSupportedMapping (type, {
3829
+ 'swap': 'privateFuturesGetSettlePositions',
3830
+ 'future': 'privateDeliveryGetSettlePositions',
3831
+ });
3832
+ const defaultSettle = (type === 'swap') ? 'usdt' : 'btc';
3833
+ const settle = this.safeStringLower (params, 'settle', defaultSettle);
3834
+ const request = {
3835
+ 'settle': settle,
3836
+ };
3837
+ const response = await this[method] (request);
3838
+ //
3839
+ // [
3840
+ // {
3841
+ // value: "12.475572",
3842
+ // leverage: "0",
3843
+ // mode: "single",
3844
+ // realised_point: "0",
3845
+ // contract: "BTC_USDT",
3846
+ // entry_price: "62422.6",
3847
+ // mark_price: "62377.86",
3848
+ // history_point: "0",
3849
+ // realised_pnl: "-0.00624226",
3850
+ // close_order: null,
3851
+ // size: "2",
3852
+ // cross_leverage_limit: "25",
3853
+ // pending_orders: "0",
3854
+ // adl_ranking: "5",
3855
+ // maintenance_rate: "0.005",
3856
+ // unrealised_pnl: "-0.008948",
3857
+ // user: "6693577",
3858
+ // leverage_max: "100",
3859
+ // history_pnl: "14.98868396636",
3860
+ // risk_limit: "1000000",
3861
+ // margin: "0.740721495056",
3862
+ // last_close_pnl: "-0.041996015",
3863
+ // liq_price: "59058.58"
3864
+ // }
3865
+ // ]
3866
+ //
3867
+ const result = this.parsePositions (response);
3868
+ return this.filterByArray (result, 'symbol', symbols, false);
3869
+ }
3870
+
3871
+ async fetchLeverageTiers (symbols = undefined, params = {}) {
3872
+ await this.loadMarkets ();
3873
+ const methodName = 'fetchLeverageTiers';
3874
+ const [ type, query ] = this.handleMarketTypeAndParams (methodName, undefined, params);
3875
+ const swap = type === 'swap';
3876
+ const defaultSettle = swap ? 'usdt' : 'btc';
3877
+ const settle = this.safeStringLower (query, 'settle', defaultSettle);
3878
+ query['settle'] = settle;
3879
+ if (type !== 'future' && type !== 'swap') {
3880
+ throw new BadRequest (this.id + ' ' + methodName + '() only supports swap and future');
3881
+ }
3882
+ const method = this.getSupportedMapping (type, {
3883
+ 'swap': 'publicFuturesGetSettleContracts',
3884
+ 'future': 'publicDeliveryGetSettleContracts',
3885
+ });
3886
+ const response = await this[method] (query);
3887
+ //
3888
+ // Perpetual swap
3889
+ //
3890
+ // [
3891
+ // {
3892
+ // "name": "BTC_USDT",
3893
+ // "type": "direct",
3894
+ // "quanto_multiplier": "0.0001",
3895
+ // "ref_discount_rate": "0",
3896
+ // "order_price_deviate": "0.5",
3897
+ // "maintenance_rate": "0.005",
3898
+ // "mark_type": "index",
3899
+ // "last_price": "38026",
3900
+ // "mark_price": "37985.6",
3901
+ // "index_price": "37954.92",
3902
+ // "funding_rate_indicative": "0.000219",
3903
+ // "mark_price_round": "0.01",
3904
+ // "funding_offset": 0,
3905
+ // "in_delisting": false,
3906
+ // "risk_limit_base": "1000000",
3907
+ // "interest_rate": "0.0003",
3908
+ // "order_price_round": "0.1",
3909
+ // "order_size_min": 1,
3910
+ // "ref_rebate_rate": "0.2",
3911
+ // "funding_interval": 28800,
3912
+ // "risk_limit_step": "1000000",
3913
+ // "leverage_min": "1",
3914
+ // "leverage_max": "100",
3915
+ // "risk_limit_max": "8000000",
3916
+ // "maker_fee_rate": "-0.00025",
3917
+ // "taker_fee_rate": "0.00075",
3918
+ // "funding_rate": "0.002053",
3919
+ // "order_size_max": 1000000,
3920
+ // "funding_next_apply": 1610035200,
3921
+ // "short_users": 977,
3922
+ // "config_change_time": 1609899548,
3923
+ // "trade_size": 28530850594,
3924
+ // "position_size": 5223816,
3925
+ // "long_users": 455,
3926
+ // "funding_impact_value": "60000",
3927
+ // "orders_limit": 50,
3928
+ // "trade_id": 10851092,
3929
+ // "orderbook_id": 2129638396
3930
+ // }
3931
+ // ]
3932
+ //
3933
+ // Delivery Futures
3934
+ //
3935
+ // [
3936
+ // {
3937
+ // "name": "BTC_USDT_20200814",
3938
+ // "underlying": "BTC_USDT",
3939
+ // "cycle": "WEEKLY",
3940
+ // "type": "direct",
3941
+ // "quanto_multiplier": "0.0001",
3942
+ // "mark_type": "index",
3943
+ // "last_price": "9017",
3944
+ // "mark_price": "9019",
3945
+ // "index_price": "9005.3",
3946
+ // "basis_rate": "0.185095",
3947
+ // "basis_value": "13.7",
3948
+ // "basis_impact_value": "100000",
3949
+ // "settle_price": "0",
3950
+ // "settle_price_interval": 60,
3951
+ // "settle_price_duration": 1800,
3952
+ // "settle_fee_rate": "0.0015",
3953
+ // "expire_time": 1593763200,
3954
+ // "order_price_round": "0.1",
3955
+ // "mark_price_round": "0.1",
3956
+ // "leverage_min": "1",
3957
+ // "leverage_max": "100",
3958
+ // "maintenance_rate": "1000000",
3959
+ // "risk_limit_base": "140.726652109199",
3960
+ // "risk_limit_step": "1000000",
3961
+ // "risk_limit_max": "8000000",
3962
+ // "maker_fee_rate": "-0.00025",
3963
+ // "taker_fee_rate": "0.00075",
3964
+ // "ref_discount_rate": "0",
3965
+ // "ref_rebate_rate": "0.2",
3966
+ // "order_price_deviate": "0.5",
3967
+ // "order_size_min": 1,
3968
+ // "order_size_max": 1000000,
3969
+ // "orders_limit": 50,
3970
+ // "orderbook_id": 63,
3971
+ // "trade_id": 26,
3972
+ // "trade_size": 435,
3973
+ // "position_size": 130,
3974
+ // "config_change_time": 1593158867,
3975
+ // "in_delisting": false
3976
+ // }
3977
+ // ]
3978
+ //
3979
+ return this.parseLeverageTiers (response, symbols, 'name');
3980
+ }
3981
+
3982
+ parseMarketLeverageTiers (info, market = undefined) {
3983
+ /**
3984
+ * @ignore
3985
+ * @method
3986
+ * @description https://www.gate.io/help/futures/perpetual/22162/instrctions-of-risk-limit
3987
+ * @param {dict} info Exchange market response for 1 market
3988
+ * @param {dict} market CCXT market
3989
+ */
3990
+ //
3991
+ // Perpetual swap
3992
+ //
3993
+ // {
3994
+ // "name": "BTC_USDT",
3995
+ // "type": "direct",
3996
+ // "quanto_multiplier": "0.0001",
3997
+ // "ref_discount_rate": "0",
3998
+ // "order_price_deviate": "0.5",
3999
+ // "maintenance_rate": "0.005",
4000
+ // "mark_type": "index",
4001
+ // "last_price": "38026",
4002
+ // "mark_price": "37985.6",
4003
+ // "index_price": "37954.92",
4004
+ // "funding_rate_indicative": "0.000219",
4005
+ // "mark_price_round": "0.01",
4006
+ // "funding_offset": 0,
4007
+ // "in_delisting": false,
4008
+ // "risk_limit_base": "1000000",
4009
+ // "interest_rate": "0.0003",
4010
+ // "order_price_round": "0.1",
4011
+ // "order_size_min": 1,
4012
+ // "ref_rebate_rate": "0.2",
4013
+ // "funding_interval": 28800,
4014
+ // "risk_limit_step": "1000000",
4015
+ // "leverage_min": "1",
4016
+ // "leverage_max": "100",
4017
+ // "risk_limit_max": "8000000",
4018
+ // "maker_fee_rate": "-0.00025",
4019
+ // "taker_fee_rate": "0.00075",
4020
+ // "funding_rate": "0.002053",
4021
+ // "order_size_max": 1000000,
4022
+ // "funding_next_apply": 1610035200,
4023
+ // "short_users": 977,
4024
+ // "config_change_time": 1609899548,
4025
+ // "trade_size": 28530850594,
4026
+ // "position_size": 5223816,
4027
+ // "long_users": 455,
4028
+ // "funding_impact_value": "60000",
4029
+ // "orders_limit": 50,
4030
+ // "trade_id": 10851092,
4031
+ // "orderbook_id": 2129638396
4032
+ // }
4033
+ //
4034
+ // Delivery Futures
4035
+ //
4036
+ // {
4037
+ // "name": "BTC_USDT_20200814",
4038
+ // "underlying": "BTC_USDT",
4039
+ // "cycle": "WEEKLY",
4040
+ // "type": "direct",
4041
+ // "quanto_multiplier": "0.0001",
4042
+ // "mark_type": "index",
4043
+ // "last_price": "9017",
4044
+ // "mark_price": "9019",
4045
+ // "index_price": "9005.3",
4046
+ // "basis_rate": "0.185095",
4047
+ // "basis_value": "13.7",
4048
+ // "basis_impact_value": "100000",
4049
+ // "settle_price": "0",
4050
+ // "settle_price_interval": 60,
4051
+ // "settle_price_duration": 1800,
4052
+ // "settle_fee_rate": "0.0015",
4053
+ // "expire_time": 1593763200,
4054
+ // "order_price_round": "0.1",
4055
+ // "mark_price_round": "0.1",
4056
+ // "leverage_min": "1",
4057
+ // "leverage_max": "100",
4058
+ // "maintenance_rate": "1000000",
4059
+ // "risk_limit_base": "140.726652109199",
4060
+ // "risk_limit_step": "1000000",
4061
+ // "risk_limit_max": "8000000",
4062
+ // "maker_fee_rate": "-0.00025",
4063
+ // "taker_fee_rate": "0.00075",
4064
+ // "ref_discount_rate": "0",
4065
+ // "ref_rebate_rate": "0.2",
4066
+ // "order_price_deviate": "0.5",
4067
+ // "order_size_min": 1,
4068
+ // "order_size_max": 1000000,
4069
+ // "orders_limit": 50,
4070
+ // "orderbook_id": 63,
4071
+ // "trade_id": 26,
4072
+ // "trade_size": 435,
4073
+ // "position_size": 130,
4074
+ // "config_change_time": 1593158867,
4075
+ // "in_delisting": false
4076
+ // }
4077
+ //
4078
+ const maintenanceMarginUnit = this.safeString (info, 'maintenance_rate'); // '0.005',
4079
+ const leverageMax = this.safeString (info, 'leverage_max'); // '100',
4080
+ const riskLimitStep = this.safeString (info, 'risk_limit_step'); // '1000000',
4081
+ const riskLimitMax = this.safeString (info, 'risk_limit_max'); // '16000000',
4082
+ const initialMarginUnit = Precise.stringDiv ('1', leverageMax);
4083
+ let maintenanceMarginRate = maintenanceMarginUnit;
4084
+ let initialMarginRatio = initialMarginUnit;
4085
+ let floor = '0';
4086
+ const tiers = [];
4087
+ while (Precise.stringLt (floor, riskLimitMax)) {
4088
+ const cap = Precise.stringAdd (floor, riskLimitStep);
4089
+ tiers.push ({
4090
+ 'tier': this.parseNumber (Precise.stringDiv (cap, riskLimitStep)),
4091
+ 'currency': this.safeString (market, 'settle'),
4092
+ 'minNotional': this.parseNumber (floor),
4093
+ 'maxNotional': this.parseNumber (cap),
4094
+ 'maintenanceMarginRate': this.parseNumber (maintenanceMarginRate),
4095
+ 'maxLeverage': this.parseNumber (Precise.stringDiv ('1', initialMarginRatio)),
4096
+ 'info': info,
4097
+ });
4098
+ maintenanceMarginRate = Precise.stringAdd (maintenanceMarginRate, maintenanceMarginUnit);
4099
+ initialMarginRatio = Precise.stringAdd (initialMarginRatio, initialMarginUnit);
4100
+ floor = cap;
4101
+ }
4102
+ return tiers;
4103
+ }
4104
+
4105
+ sign (path, api = [], method = 'GET', params = {}, headers = undefined, body = undefined) {
4106
+ const authentication = api[0]; // public, private
4107
+ const type = api[1]; // spot, margin, future, delivery
4108
+ let query = this.omit (params, this.extractParams (path));
4109
+ path = this.implodeParams (path, params);
4110
+ const endPart = (path === '') ? '' : ('/' + path);
4111
+ const entirePath = '/' + type + endPart;
4112
+ let url = this.urls['api'][authentication][type];
4113
+ if (url === undefined) {
4114
+ throw new NotSupported (this.id + ' does not have a testnet for the ' + type + ' market type.');
4115
+ }
4116
+ url += entirePath;
4117
+ if (authentication === 'public') {
4118
+ if (Object.keys (query).length) {
4119
+ url += '?' + this.urlencode (query);
4120
+ }
4121
+ } else {
4122
+ let queryString = '';
4123
+ if ((method === 'GET') || (method === 'DELETE')) {
4124
+ if (Object.keys (query).length) {
4125
+ queryString = this.urlencode (query);
4126
+ url += '?' + queryString;
4127
+ }
4128
+ } else {
4129
+ const urlQueryParams = this.safeValue (query, 'query', {});
4130
+ if (Object.keys (urlQueryParams).length) {
4131
+ queryString = this.urlencode (urlQueryParams);
4132
+ url += '?' + queryString;
4133
+ }
4134
+ query = this.omit (query, 'query');
4135
+ body = this.json (query);
4136
+ }
4137
+ const bodyPayload = (body === undefined) ? '' : body;
4138
+ const bodySignature = this.hash (this.encode (bodyPayload), 'sha512');
4139
+ const timestamp = this.seconds ();
4140
+ const timestampString = timestamp.toString ();
4141
+ const signaturePath = '/api/' + this.version + entirePath;
4142
+ const payloadArray = [ method.toUpperCase (), signaturePath, queryString, bodySignature, timestampString ];
4143
+ // eslint-disable-next-line quotes
4144
+ const payload = payloadArray.join ("\n");
4145
+ const signature = this.hmac (this.encode (payload), this.encode (this.secret), 'sha512');
4146
+ headers = {
4147
+ 'KEY': this.apiKey,
4148
+ 'Timestamp': timestampString,
4149
+ 'SIGN': signature,
4150
+ 'Content-Type': 'application/json',
4151
+ };
4152
+ }
4153
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
4154
+ }
4155
+
4156
+ handleErrors (code, reason, url, method, headers, body, response, requestHeaders, requestBody) {
4157
+ if (response === undefined) {
4158
+ return;
4159
+ }
4160
+ //
4161
+ // {"label": "ORDER_NOT_FOUND", "message": "Order not found"}
4162
+ // {"label": "INVALID_PARAM_VALUE", "message": "invalid argument: status"}
4163
+ // {"label": "INVALID_PARAM_VALUE", "message": "invalid argument: Trigger.rule"}
4164
+ // {"label": "INVALID_PARAM_VALUE", "message": "invalid argument: trigger.expiration invalid range"}
4165
+ // {"label": "INVALID_ARGUMENT", "detail": "invalid size"}
4166
+ //
4167
+ const label = this.safeString (response, 'label');
4168
+ if (label !== undefined) {
4169
+ const feedback = this.id + ' ' + body;
4170
+ this.throwExactlyMatchedException (this.exceptions['exact'], label, feedback);
4171
+ throw new ExchangeError (feedback);
4172
+ }
4173
+ }
4174
+ };