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/zb.js ADDED
@@ -0,0 +1,4088 @@
1
+ 'use strict';
2
+
3
+ // ---------------------------------------------------------------------------
4
+
5
+ const Exchange = require ('./base/Exchange');
6
+ const { BadRequest, BadSymbol, ExchangeError, ArgumentsRequired, AuthenticationError, InsufficientFunds, NotSupported, OrderNotFound, ExchangeNotAvailable, RateLimitExceeded, PermissionDenied, InvalidOrder, InvalidAddress, OnMaintenance, RequestTimeout, AccountSuspended, NetworkError, DDoSProtection, DuplicateOrderId, BadResponse } = require ('./base/errors');
7
+ const Precise = require ('./base/Precise');
8
+
9
+ // ---------------------------------------------------------------------------
10
+
11
+ module.exports = class zb extends Exchange {
12
+ describe () {
13
+ return this.deepExtend (super.describe (), {
14
+ 'id': 'zb',
15
+ 'name': 'ZB',
16
+ 'countries': [ 'CN' ],
17
+ 'rateLimit': 100,
18
+ 'version': 'v1',
19
+ 'certified': true,
20
+ 'pro': true,
21
+ 'has': {
22
+ 'CORS': undefined,
23
+ 'spot': true,
24
+ 'margin': true,
25
+ 'swap': true,
26
+ 'future': undefined,
27
+ 'option': undefined,
28
+ 'addMargin': true,
29
+ 'cancelAllOrders': true,
30
+ 'cancelOrder': true,
31
+ 'createMarketOrder': undefined,
32
+ 'createOrder': true,
33
+ 'createReduceOnlyOrder': false,
34
+ 'createStopLimitOrder': true,
35
+ 'createStopMarketOrder': true,
36
+ 'createStopOrder': true,
37
+ 'fetchBalance': true,
38
+ 'fetchBorrowRate': true,
39
+ 'fetchBorrowRateHistories': false,
40
+ 'fetchBorrowRateHistory': false,
41
+ 'fetchBorrowRates': true,
42
+ 'fetchCanceledOrders': true,
43
+ 'fetchClosedOrders': true,
44
+ 'fetchCurrencies': true,
45
+ 'fetchDepositAddress': true,
46
+ 'fetchDepositAddresses': true,
47
+ 'fetchDeposits': true,
48
+ 'fetchFundingHistory': false,
49
+ 'fetchFundingRate': true,
50
+ 'fetchFundingRateHistory': true,
51
+ 'fetchFundingRates': true,
52
+ 'fetchLedger': true,
53
+ 'fetchLeverage': false,
54
+ 'fetchLeverageTiers': false,
55
+ 'fetchMarketLeverageTiers': false,
56
+ 'fetchMarkets': true,
57
+ 'fetchOHLCV': true,
58
+ 'fetchOpenOrders': true,
59
+ 'fetchOrder': true,
60
+ 'fetchOrderBook': true,
61
+ 'fetchOrders': true,
62
+ 'fetchPosition': true,
63
+ 'fetchPositions': true,
64
+ 'fetchPositionsRisk': false,
65
+ 'fetchPremiumIndexOHLCV': false,
66
+ 'fetchTicker': true,
67
+ 'fetchTickers': true,
68
+ 'fetchTrades': true,
69
+ 'fetchTradingFee': false,
70
+ 'fetchTradingFees': false,
71
+ 'fetchWithdrawals': true,
72
+ 'reduceMargin': true,
73
+ 'setLeverage': true,
74
+ 'setMarginMode': false,
75
+ 'setPositionMode': false,
76
+ 'transfer': true,
77
+ 'withdraw': true,
78
+ },
79
+ 'timeframes': {
80
+ '1m': '1m',
81
+ '3m': '3m',
82
+ '5m': '5m',
83
+ '15m': '15m',
84
+ '30m': '30m',
85
+ '1h': '1h',
86
+ '2h': '2h',
87
+ '4h': '4h',
88
+ '6h': '6h',
89
+ '12h': '12h',
90
+ '1d': '1d',
91
+ '3d': '3d',
92
+ '5d': '5d',
93
+ '1w': '1w',
94
+ },
95
+ 'hostname': 'zb.com', // zb.cafe for users in China
96
+ 'urls': {
97
+ 'logo': 'https://user-images.githubusercontent.com/1294454/32859187-cd5214f0-ca5e-11e7-967d-96568e2e2bd1.jpg',
98
+ 'api': {
99
+ 'spot': {
100
+ 'v1': {
101
+ 'public': 'https://api.{hostname}/data',
102
+ 'private': 'https://trade.{hostname}/api',
103
+ },
104
+ },
105
+ 'contract': {
106
+ 'v1': {
107
+ 'public': 'https://fapi.{hostname}/api/public',
108
+ },
109
+ 'v2': {
110
+ 'public': 'https://fapi.{hostname}/Server/api',
111
+ 'private': 'https://fapi.{hostname}/Server/api',
112
+ },
113
+ },
114
+ },
115
+ 'www': 'https://www.zb.com',
116
+ 'doc': 'https://www.zb.com/i/developer',
117
+ 'fees': 'https://www.zb.com/i/rate',
118
+ 'referral': {
119
+ 'url': 'https://www.zbex.club/en/register?ref=4301lera',
120
+ 'discount': 0.16,
121
+ },
122
+ },
123
+ 'api': {
124
+ 'spot': {
125
+ 'v1': {
126
+ 'public': {
127
+ 'get': [
128
+ 'markets',
129
+ 'ticker',
130
+ 'allTicker',
131
+ 'depth',
132
+ 'trades',
133
+ 'kline',
134
+ 'getGroupMarkets',
135
+ 'getFeeInfo',
136
+ ],
137
+ },
138
+ 'private': {
139
+ 'get': [
140
+ // spot API
141
+ 'order',
142
+ 'orderMoreV2',
143
+ 'cancelOrder',
144
+ 'getOrder',
145
+ 'getOrders',
146
+ 'getOrdersNew',
147
+ 'getOrdersIgnoreTradeType',
148
+ 'getUnfinishedOrdersIgnoreTradeType',
149
+ 'getFinishedAndPartialOrders',
150
+ 'getAccountInfo',
151
+ 'getUserAddress',
152
+ 'getPayinAddress',
153
+ 'getWithdrawAddress',
154
+ 'getWithdrawRecord',
155
+ 'getChargeRecord',
156
+ 'getCnyWithdrawRecord',
157
+ 'getCnyChargeRecord',
158
+ 'withdraw',
159
+ // sub accounts
160
+ 'addSubUser',
161
+ 'getSubUserList',
162
+ 'doTransferFunds',
163
+ 'createSubUserKey', // removed on 2021-03-16 according to the update log in the API doc
164
+ // leverage API
165
+ 'getLeverAssetsInfo',
166
+ 'getLeverBills',
167
+ 'transferInLever',
168
+ 'transferOutLever',
169
+ 'loan',
170
+ 'cancelLoan',
171
+ 'getLoans',
172
+ 'getLoanRecords',
173
+ 'borrow',
174
+ 'autoBorrow',
175
+ 'repay',
176
+ 'doAllRepay',
177
+ 'getRepayments',
178
+ 'getFinanceRecords',
179
+ 'changeInvestMark',
180
+ 'changeLoop',
181
+ // cross API
182
+ 'getCrossAssets',
183
+ 'getCrossBills',
184
+ 'transferInCross',
185
+ 'transferOutCross',
186
+ 'doCrossLoan',
187
+ 'doCrossRepay',
188
+ 'getCrossRepayRecords',
189
+ ],
190
+ },
191
+ },
192
+ },
193
+ 'contract': {
194
+ 'v1': {
195
+ 'public': {
196
+ 'get': [
197
+ 'depth',
198
+ 'fundingRate',
199
+ 'indexKline',
200
+ 'indexPrice',
201
+ 'kline',
202
+ 'markKline',
203
+ 'markPrice',
204
+ 'ticker',
205
+ 'trade',
206
+ ],
207
+ },
208
+ },
209
+ 'v2': {
210
+ 'public': {
211
+ 'get': [
212
+ 'allForceOrders',
213
+ 'config/marketList',
214
+ 'topLongShortAccountRatio',
215
+ 'topLongShortPositionRatio',
216
+ 'fundingRate',
217
+ 'premiumIndex',
218
+ ],
219
+ },
220
+ 'private': {
221
+ 'get': [
222
+ 'Fund/balance',
223
+ 'Fund/getAccount',
224
+ 'Fund/getBill',
225
+ 'Fund/getBillTypeList',
226
+ 'Fund/marginHistory',
227
+ 'Positions/getPositions',
228
+ 'Positions/getNominalValue',
229
+ 'Positions/marginInfo',
230
+ 'setting/get',
231
+ 'trade/getAllOrders',
232
+ 'trade/getOrder',
233
+ 'trade/getOrderAlgos',
234
+ 'trade/getTradeList',
235
+ 'trade/getUndoneOrders',
236
+ 'trade/tradeHistory',
237
+ ],
238
+ 'post': [
239
+ 'activity/buyTicket',
240
+ 'Fund/transferFund',
241
+ 'Positions/setMarginCoins',
242
+ 'Positions/updateAppendUSDValue',
243
+ 'Positions/updateMargin',
244
+ 'setting/setLeverage',
245
+ 'trade/batchOrder',
246
+ 'trade/batchCancelOrder',
247
+ 'trade/cancelAlgos',
248
+ 'trade/cancelAllOrders',
249
+ 'trade/cancelOrder',
250
+ 'trade/order',
251
+ 'trade/orderAlgo',
252
+ 'trade/updateOrderAlgo',
253
+ ],
254
+ },
255
+ },
256
+ },
257
+ },
258
+ 'fees': {
259
+ 'funding': {
260
+ 'withdraw': {},
261
+ },
262
+ 'trading': {
263
+ 'maker': this.parseNumber ('0.002'),
264
+ 'taker': this.parseNumber ('0.002'),
265
+ },
266
+ },
267
+ 'commonCurrencies': {
268
+ 'ANG': 'Anagram',
269
+ 'ENT': 'ENTCash',
270
+ 'BCHABC': 'BCHABC', // conflict with BCH / BCHA
271
+ 'BCHSV': 'BCHSV', // conflict with BCH / BSV
272
+ },
273
+ 'options': {
274
+ 'timeframes': {
275
+ 'spot': {
276
+ '1m': '1min',
277
+ '3m': '3min',
278
+ '5m': '5min',
279
+ '15m': '15min',
280
+ '30m': '30min',
281
+ '1h': '1hour',
282
+ '2h': '2hour',
283
+ '4h': '4hour',
284
+ '6h': '6hour',
285
+ '12h': '12hour',
286
+ '1d': '1day',
287
+ '3d': '3day',
288
+ '1w': '1week',
289
+ },
290
+ 'swap': {
291
+ '1m': '1M',
292
+ '5m': '5M',
293
+ '15m': '15M',
294
+ '30m': '30M',
295
+ '1h': '1H',
296
+ '6h': '6H',
297
+ '1d': '1D',
298
+ '5d': '5D',
299
+ },
300
+ },
301
+ },
302
+ 'exceptions': {
303
+ 'ws': {
304
+ // '1000': ExchangeError, // The call is successful.
305
+ '1001': ExchangeError, // General error prompt
306
+ '1002': ExchangeError, // Internal Error
307
+ '1003': AuthenticationError, // Fail to verify
308
+ '1004': AuthenticationError, // The transaction password is locked
309
+ '1005': AuthenticationError, // Wrong transaction password, please check it and re-enter。
310
+ '1006': PermissionDenied, // Real-name authentication is pending approval or unapproved
311
+ '1007': ExchangeError, // Channel does not exist
312
+ '1009': OnMaintenance, // This interface is under maintenance
313
+ '1010': ExchangeNotAvailable, // Not available now
314
+ '1012': PermissionDenied, // Insufficient permissions
315
+ '1013': ExchangeError, // Cannot trade, please contact email: support@zb.cn for support.
316
+ '1014': ExchangeError, // Cannot sell during the pre-sale period
317
+ '2001': InsufficientFunds, // Insufficient CNY account balance
318
+ '2002': InsufficientFunds, // Insufficient BTC account balance
319
+ '2003': InsufficientFunds, // Insufficient LTC account balance
320
+ '2005': InsufficientFunds, // Insufficient ETH account balance
321
+ '2006': InsufficientFunds, // ETCInsufficient account balance
322
+ '2007': InsufficientFunds, // BTSInsufficient account balance
323
+ '2008': InsufficientFunds, // EOSInsufficient account balance
324
+ '2009': InsufficientFunds, // BCCInsufficient account balance
325
+ '3001': OrderNotFound, // Order not found or is completed
326
+ '3002': InvalidOrder, // Invalid amount
327
+ '3003': InvalidOrder, // Invalid quantity
328
+ '3004': AuthenticationError, // User does not exist
329
+ '3005': BadRequest, // Invalid parameter
330
+ '3006': PermissionDenied, // Invalid IP or not consistent with the bound IP
331
+ '3007': RequestTimeout, // The request time has expired
332
+ '3008': ExchangeError, // Transaction not found
333
+ '3009': InvalidOrder, // The price exceeds the limit
334
+ '3010': PermissionDenied, // It fails to place an order, due to you have set up to prohibit trading of this market.
335
+ '3011': InvalidOrder, // The entrusted price is abnormal, please modify it and place order again
336
+ '3012': InvalidOrder, // Duplicate custom customerOrderId
337
+ '4001': AccountSuspended, // APIThe interface is locked for one hour
338
+ '4002': RateLimitExceeded, // Request too frequently
339
+ },
340
+ 'exact': {
341
+ // '1000': 'Successful operation',
342
+ '10001': ExchangeError, // Operation failed
343
+ '10002': PermissionDenied, // Operation is forbidden
344
+ '10003': BadResponse, // Data existed
345
+ '10004': BadResponse, // Date not exist
346
+ '10005': PermissionDenied, // Forbidden to access the interface
347
+ '10006': BadRequest, // Currency invalid or expired
348
+ '10007': ExchangeError, // {0}
349
+ '10008': ExchangeError, // Operation failed: {0}
350
+ '10009': ExchangeError, // URL error
351
+ '1001': ExchangeError, // 'General error message',
352
+ '10010': AuthenticationError, // API KEY not exist
353
+ '10011': AuthenticationError, // API KEY CLOSED
354
+ '10012': AccountSuspended, // User API has been frozen, please contact customer service for processing
355
+ '10013': AuthenticationError, // API verification failed
356
+ '10014': AuthenticationError, // Invalid signature(1001)
357
+ '10015': AuthenticationError, // Invalid signature(1002)
358
+ '10016': AuthenticationError, // Invalid ip
359
+ '10017': PermissionDenied, // Permission denied
360
+ '10018': AccountSuspended, // User has been frozen, please contact customer service
361
+ '10019': RequestTimeout, // Request time has expired
362
+ '1002': ExchangeError, // 'Internal error',
363
+ '10020': BadRequest, // {0}Parameter cannot be empty
364
+ '10021': BadRequest, // {0}Invalid parameter
365
+ '10022': BadRequest, // Request method error
366
+ '10023': RateLimitExceeded, // Request frequency is too fast, exceeding the limit allowed by the interface
367
+ '10024': AuthenticationError, // Login failed
368
+ '10025': ExchangeError, // Non-personal operation
369
+ '10026': NetworkError, // Failed to request interface, please try again
370
+ '10027': RequestTimeout, // Timed out, please try again later
371
+ '10028': ExchangeNotAvailable, // System busy, please try again later
372
+ '10029': DDoSProtection, // Frequent operation, please try again later
373
+ '1003': AuthenticationError, // 'Verification does not pass',
374
+ '10030': BadRequest, // Currency already exist
375
+ '10031': BadRequest, // Currency does not exist
376
+ '10032': BadRequest, // Market existed
377
+ '10033': BadRequest, // Market not exist
378
+ '10034': BadRequest, // Currency error
379
+ '10035': BadRequest, // Market not open
380
+ '10036': BadRequest, // Ineffective market type
381
+ '10037': ArgumentsRequired, // User id cannot be empty
382
+ '10038': BadRequest, // Market id cannot be empty
383
+ '10039': BadResponse, // Failed to get mark price
384
+ '1004': AuthenticationError, // 'Funding security password lock',
385
+ '10040': BadResponse, // Failed to obtain the opening margin configuration
386
+ '10041': BadResponse, // Failed to obtain maintenance margin allocation
387
+ '10042': ExchangeError, // Avg. price error
388
+ '10043': ExchangeError, // Abnormal acquisition of liquidation price
389
+ '10044': ExchangeError, // Unrealized profit and loss acquisition exception
390
+ '10045': ExchangeError, // jdbcData source acquisition failed
391
+ '10046': ExchangeError, // Invalid position opening direction
392
+ '10047': ExchangeError, // The maximum position allowed by the current leverage multiple has been exceeded
393
+ '10048': ExchangeError, // The maximum allowable order quantity has been exceeded
394
+ '10049': NetworkError, // Failed to get the latest price
395
+ '1005': AuthenticationError, // 'Funds security password is incorrect, please confirm and re-enter.',
396
+ '1006': AuthenticationError, // 'Real-name certification pending approval or audit does not pass',
397
+ '1009': ExchangeNotAvailable, // 'This interface is under maintenance',
398
+ '1010': ExchangeNotAvailable, // Not available now
399
+ '10100': OnMaintenance, // Sorry! System maintenance, stop operation
400
+ '1012': PermissionDenied, // Insufficient permissions
401
+ '1013': ExchangeError, // Cannot trade, please contact email: support@zb.cn for support.
402
+ '1014': ExchangeError, // Cannot sell during the pre-sale period
403
+ '11000': ExchangeError, // Funding change failed
404
+ '11001': ExchangeError, // Position change failed
405
+ '110011': ExchangeError, // Exceeds the maximum leverage allowed by the position
406
+ '11002': ExchangeError, // Funding not exist
407
+ '11003': ExchangeError, // Freeze records not exist
408
+ '11004': InsufficientFunds, // Insufficient frozen funds
409
+ '11005': InvalidOrder, // Insufficient positions
410
+ '11006': InsufficientFunds, // Insufficient frozen positions
411
+ '11007': OrderNotFound, // Position not exist
412
+ '11008': ExchangeError, // The contract have positions, cannot be modified
413
+ '11009': ExchangeError, // Failed to query data
414
+ '110110': ExchangeError, // Exceed the market's maximum leverage
415
+ '11012': InsufficientFunds, // Insufficient margin
416
+ '11013': ExchangeError, // Exceeding accuracy limit
417
+ '11014': ExchangeError, // Invalid bill type
418
+ '11015': AuthenticationError, // Failed to add default account
419
+ '11016': AuthenticationError, // Account not exist
420
+ '11017': ExchangeError, // Funds are not frozen or unfrozen
421
+ '11018': InsufficientFunds, // Insufficient funds
422
+ '11019': ExchangeError, // Bill does not exist
423
+ '11021': InsufficientFunds, // Inconsistent currency for funds transfer
424
+ '11023': ExchangeError, // Same transaction currency
425
+ '11030': PermissionDenied, // Position is locked, the operation is prohibited
426
+ '11031': ExchangeError, // The number of bill changes is zero
427
+ '11032': ExchangeError, // The same request is being processed, please do not submit it repeatedly
428
+ '11033': ArgumentsRequired, // Position configuration data is empty
429
+ '11034': ExchangeError, // Funding fee is being settled, please do not operate
430
+ '12000': InvalidOrder, // Invalid order price
431
+ '12001': InvalidOrder, // Invalid order amount
432
+ '12002': InvalidOrder, // Invalid order type
433
+ '12003': InvalidOrder, // Invalid price accuracy
434
+ '12004': InvalidOrder, // Invalid quantity precision
435
+ '12005': InvalidOrder, // order value less than the minimum or greater than the maximum
436
+ '12006': InvalidOrder, // Customize's order number format is wrong
437
+ '12007': InvalidOrder, // Direction error
438
+ '12008': InvalidOrder, // Order type error
439
+ '12009': InvalidOrder, // Commission type error
440
+ '12010': InvalidOrder, // Failed to place the order, the loss of the order placed at this price will exceed margin
441
+ '12011': InvalidOrder, // it's not a buz order
442
+ '12012': OrderNotFound, // order not exist
443
+ '12013': InvalidOrder, // Order user does not match
444
+ '12014': InvalidOrder, // Order is still in transaction
445
+ '12015': InvalidOrder, // Order preprocessing failed
446
+ '12016': InvalidOrder, // Order cannot be canceled
447
+ '12017': InvalidOrder, // Transaction Record not exist
448
+ '12018': InvalidOrder, // Order failed
449
+ '12019': ArgumentsRequired, // extend parameter cannot be empty
450
+ '12020': ExchangeError, // extend Parameter error
451
+ '12021': InvalidOrder, // The order price is not within the price limit rules!
452
+ '12022': InvalidOrder, // Stop placing an order while the system is calculating the fund fee
453
+ '12023': OrderNotFound, // There are no positions to close
454
+ '12024': InvalidOrder, // Orders are prohibited, stay tuned!
455
+ '12025': InvalidOrder, // Order cancellation is prohibited, so stay tuned!
456
+ '12026': DuplicateOrderId, // Order failed, customize order number exists
457
+ '12027': ExchangeNotAvailable, // System busy, please try again later
458
+ '12028': InvalidOrder, // The market has banned trading
459
+ '12029': InvalidOrder, // Forbidden place order, stay tuned
460
+ '12201': InvalidOrder, // Delegation strategy does not exist or the status has changed
461
+ '12202': InvalidOrder, // Delegation strategy has been changed, cannot be canceled
462
+ '12203': InvalidOrder, // Wrong order type
463
+ '12204': InvalidOrder, // Invalid trigger price
464
+ '12205': InvalidOrder, // The trigger price must be greater than the market’s selling price or lower than the buying price.
465
+ '12206': InvalidOrder, // Direction and order type do not match
466
+ '12207': RateLimitExceeded, // Submission failed, exceeding the allowed limit
467
+ '13001': AuthenticationError, // User not exist
468
+ '13002': PermissionDenied, // User did not activate futures
469
+ // '13003': AuthenticationError, // User is locked
470
+ '13003': InvalidOrder, // Margin gear is not continuous
471
+ '13004': InvalidOrder, // The margin quick calculation amount is less than 0
472
+ '13005': RateLimitExceeded, // You have exceeded the number of exports that day
473
+ '13006': ExchangeError, // No markets are bookmarked
474
+ '13007': ExchangeError, // Market not favorited
475
+ '13008': ExchangeError, // Not in any market user whitelist
476
+ '13009': ExchangeError, // Not in the whitelist of users in this market
477
+ '14000': ExchangeError, // {0}not support
478
+ '14001': AuthenticationError, // Already logged in, no need to log in multiple times
479
+ '14002': AuthenticationError, // Not logged in yet, please log in before subscribing
480
+ '14003': ExchangeError, // This is a channel for one-time queries, no need to unsubscribe
481
+ '14100': ExchangeError, // Accuracy does not support
482
+ '14101': RateLimitExceeded, // Request exceeded frequency limit
483
+ '14200': ArgumentsRequired, // id empty
484
+ '14300': ExchangeError, // activity not exist
485
+ '14301': ExchangeError, // The event has been opened and cannot be admitted
486
+ '14302': ExchangeError, // The purchase time has passed and cannot be admitted
487
+ '14303': ExchangeError, // Not yet open for the purchase
488
+ '14305': ExchangeError, // Cannot enter, the maximum number of returns has been exceeded
489
+ '14306': ExchangeError, // Cannot repeat admission
490
+ '14307': InvalidOrder, // Unable to cancel, status has been changed
491
+ '14308': InvalidOrder, // Unable to cancel, the amount does not match
492
+ '14309': ExchangeError, // Activity has not started
493
+ '14310': NotSupported, // Activity is over
494
+ '14311': NotSupported, // The activity does not support orders placed in this market
495
+ '14312': ExchangeError, // You have not participated in this activity
496
+ '14313': PermissionDenied, // Sorry! The purchase failed, the maximum number of participants has been reached
497
+ '14314': ExchangeError, // Active period id error
498
+ '2001': InsufficientFunds, // 'Insufficient CNY Balance',
499
+ '2002': InsufficientFunds, // 'Insufficient BTC Balance',
500
+ '2003': InsufficientFunds, // 'Insufficient LTC Balance',
501
+ '2005': InsufficientFunds, // 'Insufficient ETH Balance',
502
+ '2006': InsufficientFunds, // 'Insufficient ETC Balance',
503
+ '2007': InsufficientFunds, // 'Insufficient BTS Balance',
504
+ '2008': InsufficientFunds, // EOSInsufficient account balance
505
+ '2009': InsufficientFunds, // 'Account balance is not enough',
506
+ '3001': OrderNotFound, // 'Pending orders not found',
507
+ '3002': InvalidOrder, // 'Invalid price',
508
+ '3003': InvalidOrder, // 'Invalid amount',
509
+ '3004': AuthenticationError, // 'User does not exist',
510
+ '3005': BadRequest, // 'Invalid parameter',
511
+ '3006': AuthenticationError, // 'Invalid IP or inconsistent with the bound IP',
512
+ '3007': AuthenticationError, // 'The request time has expired',
513
+ '3008': OrderNotFound, // 'Transaction records not found',
514
+ '3009': InvalidOrder, // 'The price exceeds the limit',
515
+ '3010': PermissionDenied, // It fails to place an order, due to you have set up to prohibit trading of this market.
516
+ '3011': InvalidOrder, // 'The entrusted price is abnormal, please modify it and place order again',
517
+ '3012': InvalidOrder, // Duplicate custom customerOrderId
518
+ '4001': ExchangeNotAvailable, // 'API interface is locked or not enabled',
519
+ '4002': RateLimitExceeded, // 'Request too often',
520
+ '9999': ExchangeError, // Unknown error
521
+ },
522
+ 'broad': {
523
+ '提币地址有误, 请先添加提币地址。': InvalidAddress, // {"code":1001,"message":"提币地址有误,请先添加提币地址。"}
524
+ '资金不足,无法划账': InsufficientFunds, // {"code":1001,"message":"资金不足,无法划账"}
525
+ '响应超时': RequestTimeout, // {"code":1001,"message":"响应超时"}
526
+ },
527
+ },
528
+ });
529
+ }
530
+
531
+ async fetchMarkets (params = {}) {
532
+ const markets = await this.spotV1PublicGetMarkets (params);
533
+ //
534
+ // {
535
+ // "zb_qc":{
536
+ // "amountScale":2,
537
+ // "minAmount":0.01,
538
+ // "minSize":5,
539
+ // "priceScale":4,
540
+ // },
541
+ // }
542
+ //
543
+ let contracts = undefined;
544
+ try {
545
+ // https://github.com/ZBFuture/docs_en/blob/main/API%20V2%20_en.md#7-public-markethttp
546
+ // https://fapi.zb.com/Server/api/v2/config/marketList 502 Bad Gateway
547
+ contracts = await this.contractV2PublicGetConfigMarketList (params);
548
+ } catch (e) {
549
+ contracts = {};
550
+ }
551
+ //
552
+ // {
553
+ // BTC_USDT: {
554
+ // symbol: 'BTC_USDT',
555
+ // buyerCurrencyId: '6',
556
+ // contractType: '1',
557
+ // defaultMarginMode: '1',
558
+ // marketType: '2',
559
+ // historyDBName: 'trade_history_readonly.dbc',
560
+ // defaultLeverage: '20',
561
+ // id: '100',
562
+ // canCancelOrder: true,
563
+ // area: '1',
564
+ // mixMarginCoinName: 'usdt',
565
+ // fundingRateRatio: '0.25',
566
+ // marginCurrencyName: 'usdt',
567
+ // minTradeMoney: '0.0001',
568
+ // enableTime: '1638954000000',
569
+ // maxTradeMoney: '10000000',
570
+ // canTrade: true,
571
+ // maxLeverage: '125',
572
+ // defaultPositionsMode: '2',
573
+ // onlyWhitelistVisible: false,
574
+ // riskWarnRatio: '0.8',
575
+ // marginDecimal: '8',
576
+ // spot: false,
577
+ // status: '1',
578
+ // amountDecimal: '3',
579
+ // leverage: false,
580
+ // minAmount: '0.001',
581
+ // canOrder: true,
582
+ // duration: '1',
583
+ // feeDecimal: '8',
584
+ // sellerCurrencyId: '1',
585
+ // maxAmount: '1000',
586
+ // canOpenPosition: true,
587
+ // isSupportMixMargin: false,
588
+ // markPriceLimitRate: '0.05',
589
+ // marginCurrencyId: '6',
590
+ // stopFundingFee: false,
591
+ // priceDecimal: '2',
592
+ // lightenUpFeeRate: '0',
593
+ // futures: true,
594
+ // sellerCurrencyName: 'btc',
595
+ // marketPriceLimitRate: '0.05',
596
+ // canRebate: true,
597
+ // marketName: 'BTC_USDT',
598
+ // depth: [ 0.01, 0.1, 1 ],
599
+ // createTime: '1607590430094',
600
+ // mixMarginCoinIds: [ 6 ],
601
+ // buyerCurrencyName: 'usdt',
602
+ // stopService: false
603
+ // },
604
+ // }
605
+ //
606
+ const contractsData = this.safeValue (contracts, 'data', []);
607
+ const contractsById = this.indexBy (contractsData, 'marketName');
608
+ const dataById = this.deepExtend (contractsById, markets);
609
+ const keys = Object.keys (dataById);
610
+ const result = [];
611
+ for (let i = 0; i < keys.length; i++) {
612
+ const id = keys[i];
613
+ const market = dataById[id];
614
+ const [ baseId, quoteId ] = id.split ('_');
615
+ const base = this.safeCurrencyCode (baseId);
616
+ const quote = this.safeCurrencyCode (quoteId);
617
+ const settleId = this.safeValue (market, 'marginCurrencyName');
618
+ const settle = this.safeCurrencyCode (settleId);
619
+ const spot = settle === undefined;
620
+ const swap = this.safeValue (market, 'futures', false);
621
+ const linear = swap ? true : undefined;
622
+ let active = true;
623
+ let symbol = base + '/' + quote;
624
+ const amountPrecisionString = this.safeString2 (market, 'amountScale', 'amountDecimal');
625
+ const pricePrecisionString = this.safeString2 (market, 'priceScale', 'priceDecimal');
626
+ if (swap) {
627
+ const status = this.safeString (market, 'status');
628
+ active = (status === '1');
629
+ symbol = base + '/' + quote + ':' + settle;
630
+ }
631
+ result.push ({
632
+ 'id': id,
633
+ 'symbol': symbol,
634
+ 'base': base,
635
+ 'quote': quote,
636
+ 'settle': settle,
637
+ 'baseId': baseId,
638
+ 'quoteId': quoteId,
639
+ 'settleId': settleId,
640
+ 'type': swap ? 'swap' : 'spot',
641
+ 'spot': spot,
642
+ 'margin': false,
643
+ 'swap': swap,
644
+ 'future': false,
645
+ 'option': false,
646
+ 'active': active,
647
+ 'contract': swap,
648
+ 'linear': linear,
649
+ 'inverse': swap ? !linear : undefined,
650
+ 'contractSize': undefined,
651
+ 'expiry': undefined,
652
+ 'expiryDatetime': undefined,
653
+ 'strike': undefined,
654
+ 'optionType': undefined,
655
+ 'precision': {
656
+ 'amount': parseInt (amountPrecisionString),
657
+ 'price': parseInt (pricePrecisionString),
658
+ },
659
+ 'limits': {
660
+ 'leverage': {
661
+ 'min': undefined,
662
+ 'max': this.safeNumber (market, 'maxLeverage'),
663
+ },
664
+ 'amount': {
665
+ 'min': this.safeNumber (market, 'minAmount'),
666
+ 'max': this.safeNumber (market, 'maxAmount'),
667
+ },
668
+ 'price': {
669
+ 'min': undefined,
670
+ 'max': undefined,
671
+ },
672
+ 'cost': {
673
+ 'min': this.safeNumber2 (market, 'minSize', 'minTradeMoney'),
674
+ 'max': this.safeNumber (market, 'maxTradeMoney'),
675
+ },
676
+ },
677
+ 'info': market,
678
+ });
679
+ }
680
+ return result;
681
+ }
682
+
683
+ async fetchCurrencies (params = {}) {
684
+ const response = await this.spotV1PublicGetGetFeeInfo (params);
685
+ //
686
+ // {
687
+ // "code":1000,
688
+ // "message":"success",
689
+ // "result":{
690
+ // "USDT":[
691
+ // {
692
+ // "chainName":"TRC20",
693
+ // "canWithdraw":true,
694
+ // "fee":1.0,
695
+ // "mainChainName":"TRX",
696
+ // "canDeposit":true
697
+ // },
698
+ // {
699
+ // "chainName":"OMNI",
700
+ // "canWithdraw":true,
701
+ // "fee":5.0,
702
+ // "mainChainName":"BTC",
703
+ // "canDeposit":true
704
+ // },
705
+ // {
706
+ // "chainName":"ERC20",
707
+ // "canWithdraw":true,
708
+ // "fee":15.0,
709
+ // "mainChainName":"ETH",
710
+ // "canDeposit":true
711
+ // }
712
+ // ],
713
+ // }
714
+ // }
715
+ //
716
+ const currencies = this.safeValue (response, 'result', {});
717
+ const ids = Object.keys (currencies);
718
+ const result = {};
719
+ for (let i = 0; i < ids.length; i++) {
720
+ const id = ids[i];
721
+ const currency = currencies[id];
722
+ const code = this.safeCurrencyCode (id);
723
+ const precision = undefined;
724
+ let isWithdrawEnabled = true;
725
+ let isDepositEnabled = true;
726
+ const fees = {};
727
+ for (let j = 0; j < currency.length; j++) {
728
+ const networkItem = currency[j];
729
+ const network = this.safeString (networkItem, 'chainName');
730
+ // const name = this.safeString (networkItem, 'name');
731
+ const withdrawFee = this.safeNumber (networkItem, 'fee');
732
+ const depositEnable = this.safeValue (networkItem, 'canDeposit');
733
+ const withdrawEnable = this.safeValue (networkItem, 'canWithdraw');
734
+ isDepositEnabled = isDepositEnabled || depositEnable;
735
+ isWithdrawEnabled = isWithdrawEnabled || withdrawEnable;
736
+ fees[network] = withdrawFee;
737
+ }
738
+ const active = (isWithdrawEnabled && isDepositEnabled);
739
+ result[code] = {
740
+ 'id': id,
741
+ 'name': undefined,
742
+ 'code': code,
743
+ 'precision': precision,
744
+ 'info': currency,
745
+ 'active': active,
746
+ 'deposit': isDepositEnabled,
747
+ 'withdraw': isWithdrawEnabled,
748
+ 'fee': undefined,
749
+ 'fees': fees,
750
+ 'limits': this.limits,
751
+ };
752
+ }
753
+ return result;
754
+ }
755
+
756
+ parseBalance (response) {
757
+ const balances = this.safeValue (response['result'], 'coins');
758
+ const result = {
759
+ 'info': response,
760
+ };
761
+ for (let i = 0; i < balances.length; i++) {
762
+ const balance = balances[i];
763
+ // { enName: "BTC",
764
+ // freez: "0.00000000",
765
+ // unitDecimal: 8, // always 8
766
+ // cnName: "BTC",
767
+ // isCanRecharge: true, // TODO: should use this
768
+ // unitTag: "฿",
769
+ // isCanWithdraw: true, // TODO: should use this
770
+ // available: "0.00000000",
771
+ // key: "btc" }
772
+ const account = this.account ();
773
+ const currencyId = this.safeString (balance, 'key');
774
+ const code = this.safeCurrencyCode (currencyId);
775
+ account['free'] = this.safeString (balance, 'available');
776
+ account['used'] = this.safeString (balance, 'freez');
777
+ result[code] = account;
778
+ }
779
+ return this.safeBalance (result);
780
+ }
781
+
782
+ parseSwapBalance (response) {
783
+ const result = {
784
+ 'info': response,
785
+ };
786
+ const data = this.safeValue (response, 'data', {});
787
+ for (let i = 0; i < data.length; i++) {
788
+ const balance = data[i];
789
+ //
790
+ // {
791
+ // "userId": "6896693805014120448",
792
+ // "currencyId": "6",
793
+ // "currencyName": "usdt",
794
+ // "amount": "30.56585118",
795
+ // "freezeAmount": "0",
796
+ // "contractType": 1,
797
+ // "id": "6899113714763638819",
798
+ // "createTime": "1644876888934",
799
+ // "modifyTime": "1645787446037",
800
+ // "accountBalance": "30.56585118",
801
+ // "allMargin": "0",
802
+ // "allowTransferOutAmount": "30.56585118"
803
+ // },
804
+ //
805
+ const code = this.safeCurrencyCode (this.safeString (balance, 'currencyName'));
806
+ const account = this.account ();
807
+ account['total'] = this.safeString (balance, 'accountBalance');
808
+ account['free'] = this.safeString (balance, 'allowTransferOutAmount');
809
+ account['used'] = this.safeString (balance, 'freezeAmount');
810
+ result[code] = account;
811
+ }
812
+ return this.safeBalance (result);
813
+ }
814
+
815
+ parseMarginBalance (response, marginType) {
816
+ const result = {
817
+ 'info': response,
818
+ };
819
+ let levers = undefined;
820
+ if (marginType === 'isolated') {
821
+ const message = this.safeValue (response, 'message', {});
822
+ const data = this.safeValue (message, 'datas', {});
823
+ levers = this.safeValue (data, 'levers', []);
824
+ } else {
825
+ const crossResponse = this.safeValue (response, 'result', {});
826
+ levers = this.safeValue (crossResponse, 'list', []);
827
+ }
828
+ for (let i = 0; i < levers.length; i++) {
829
+ const balance = levers[i];
830
+ //
831
+ // Isolated Margin
832
+ //
833
+ // {
834
+ // "cNetUSD": "0.00",
835
+ // "repayLeverShow": "-",
836
+ // "cCanLoanIn": "0.002115400000000",
837
+ // "fNetCNY": "147.76081161",
838
+ // "fLoanIn": "0.00",
839
+ // "repayLevel": 0,
840
+ // "level": 1,
841
+ // "netConvertCNY": "147.760811613032",
842
+ // "cFreeze": "0.00",
843
+ // "cUnitTag": "BTC",
844
+ // "version": 1646783178609,
845
+ // "cAvailableUSD": "0.00",
846
+ // "cNetCNY": "0.00",
847
+ // "riskRate": "-",
848
+ // "fAvailableUSD": "20.49273433",
849
+ // "fNetUSD": "20.49273432",
850
+ // "cShowName": "BTC",
851
+ // "leverMultiple": "5.00",
852
+ // "couldTransferOutFiat": "20.49273433",
853
+ // "noticeLine": "1.13",
854
+ // "fFreeze": "0.00",
855
+ // "cUnitDecimal": 8,
856
+ // "fCanLoanIn": "81.970937320000000",
857
+ // "cAvailable": "0.00",
858
+ // "repayLock": false,
859
+ // "status": 1,
860
+ // "forbidType": 0,
861
+ // "totalConvertCNY": "147.760811613032",
862
+ // "cAvailableCNY": "0.00",
863
+ // "unwindPrice": "0.00",
864
+ // "fOverdraft": "0.00",
865
+ // "fShowName": "USDT",
866
+ // "statusShow": "%E6%AD%A3%E5%B8%B8",
867
+ // "cOverdraft": "0.00",
868
+ // "netConvertUSD": "20.49273433",
869
+ // "cNetBtc": "0.00",
870
+ // "loanInConvertCNY": "0.00",
871
+ // "fAvailableCNY": "147.760811613032",
872
+ // "key": "btcusdt",
873
+ // "fNetBtc": "0.0005291",
874
+ // "fUnitDecimal": 8,
875
+ // "loanInConvertUSD": "0.00",
876
+ // "showName": "BTC/USDT",
877
+ // "startLine": "1.25",
878
+ // "totalConvertUSD": "20.49273433",
879
+ // "couldTransferOutCoin": "0.00",
880
+ // "cEnName": "BTC",
881
+ // "leverMultipleInterest": "3.00",
882
+ // "fAvailable": "20.49273433",
883
+ // "fEnName": "USDT",
884
+ // "forceRepayLine": "1.08",
885
+ // "cLoanIn": "0.00"
886
+ // }
887
+ //
888
+ // Cross Margin
889
+ //
890
+ // [
891
+ // {
892
+ // "fundType": 2,
893
+ // "loanIn": 0,
894
+ // "amount": 0,
895
+ // "freeze": 0,
896
+ // "overdraft": 0,
897
+ // "key": "BTC",
898
+ // "canTransferOut": 0
899
+ // },
900
+ // ],
901
+ //
902
+ const account = this.account ();
903
+ if (marginType === 'isolated') {
904
+ const code = this.safeCurrencyCode (this.safeString (balance, 'fShowName'));
905
+ account['total'] = this.safeString (balance, 'fAvailableUSD'); // total amount in USD
906
+ account['free'] = this.safeString (balance, 'couldTransferOutFiat');
907
+ account['used'] = this.safeString (balance, 'fFreeze');
908
+ result[code] = account;
909
+ } else {
910
+ const code = this.safeCurrencyCode (this.safeString (balance, 'key'));
911
+ account['total'] = this.safeString (balance, 'amount');
912
+ account['free'] = this.safeString (balance, 'canTransferOut');
913
+ account['used'] = this.safeString (balance, 'freeze');
914
+ result[code] = account;
915
+ }
916
+ }
917
+ return this.safeBalance (result);
918
+ }
919
+
920
+ async fetchBalance (params = {}) {
921
+ await this.loadMarkets ();
922
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('fetchBalance', undefined, params);
923
+ const margin = (marketType === 'margin');
924
+ const swap = (marketType === 'swap');
925
+ let marginMethod = undefined;
926
+ const defaultMargin = margin ? 'isolated' : 'cross';
927
+ const marginType = this.safeString2 (this.options, 'defaultMarginType', 'marginType', defaultMargin);
928
+ if (marginType === 'isolated') {
929
+ marginMethod = 'spotV1PrivateGetGetLeverAssetsInfo';
930
+ } else if (marginType === 'cross') {
931
+ marginMethod = 'spotV1PrivateGetGetCrossAssets';
932
+ }
933
+ const method = this.getSupportedMapping (marketType, {
934
+ 'spot': 'spotV1PrivateGetGetAccountInfo',
935
+ 'swap': 'contractV2PrivateGetFundBalance',
936
+ 'margin': marginMethod,
937
+ });
938
+ const request = {
939
+ // 'futuresAccountType': 1, // SWAP
940
+ // 'currencyId': currency['id'], // SWAP
941
+ // 'currencyName': 'usdt', // SWAP
942
+ };
943
+ if (swap) {
944
+ request['futuresAccountType'] = 1;
945
+ }
946
+ const response = await this[method] (this.extend (request, query));
947
+ //
948
+ // Spot
949
+ //
950
+ // {
951
+ // "result": {
952
+ // "coins": [
953
+ // {
954
+ // "isCanWithdraw": "true",
955
+ // "canLoan": false,
956
+ // "fundstype": 51,
957
+ // "showName": "ZB",
958
+ // "isCanRecharge": "true",
959
+ // "cnName": "ZB",
960
+ // "enName": "ZB",
961
+ // "available": "0",
962
+ // "freez": "0",
963
+ // "unitTag": "ZB",
964
+ // "key": "zb",
965
+ // "unitDecimal": 8
966
+ // },
967
+ // ],
968
+ // "version": 1645856691340,
969
+ // "base": {
970
+ // "auth_google_enabled": true,
971
+ // "auth_mobile_enabled": false,
972
+ // "trade_password_enabled": true,
973
+ // "username": "blank@gmail.com"
974
+ // }
975
+ // },
976
+ // "leverPerm": true,
977
+ // "otcPerm": false,
978
+ // "assetPerm": true,
979
+ // "moneyPerm": true,
980
+ // "subUserPerm": true,
981
+ // "entrustPerm": true
982
+ // }
983
+ //
984
+ // Swap
985
+ //
986
+ // {
987
+ // "code": 10000,
988
+ // "data": [
989
+ // {
990
+ // "userId": "6896693805014120448",
991
+ // "currencyId": "6",
992
+ // "currencyName": "usdt",
993
+ // "amount": "30.56585118",
994
+ // "freezeAmount": "0",
995
+ // "contractType": 1,
996
+ // "id": "6899113714763638819",
997
+ // "createTime": "1644876888934",
998
+ // "modifyTime": "1645787446037",
999
+ // "accountBalance": "30.56585118",
1000
+ // "allMargin": "0",
1001
+ // "allowTransferOutAmount": "30.56585118"
1002
+ // },
1003
+ // ],
1004
+ // "desc": "操作成功"
1005
+ // }
1006
+ //
1007
+ // Isolated Margin
1008
+ //
1009
+ // {
1010
+ // "code": 1000,
1011
+ // "message": {
1012
+ // "des": "success",
1013
+ // "isSuc": true,
1014
+ // "datas": {
1015
+ // "leverPerm": true,
1016
+ // "levers": [
1017
+ // {
1018
+ // "cNetUSD": "0.00",
1019
+ // "repayLeverShow": "-",
1020
+ // "cCanLoanIn": "0.002115400000000",
1021
+ // "fNetCNY": "147.76081161",
1022
+ // "fLoanIn": "0.00",
1023
+ // "repayLevel": 0,
1024
+ // "level": 1,
1025
+ // "netConvertCNY": "147.760811613032",
1026
+ // "cFreeze": "0.00",
1027
+ // "cUnitTag": "BTC",
1028
+ // "version": 1646783178609,
1029
+ // "cAvailableUSD": "0.00",
1030
+ // "cNetCNY": "0.00",
1031
+ // "riskRate": "-",
1032
+ // "fAvailableUSD": "20.49273433",
1033
+ // "fNetUSD": "20.49273432",
1034
+ // "cShowName": "BTC",
1035
+ // "leverMultiple": "5.00",
1036
+ // "couldTransferOutFiat": "20.49273433",
1037
+ // "noticeLine": "1.13",
1038
+ // "fFreeze": "0.00",
1039
+ // "cUnitDecimal": 8,
1040
+ // "fCanLoanIn": "81.970937320000000",
1041
+ // "cAvailable": "0.00",
1042
+ // "repayLock": false,
1043
+ // "status": 1,
1044
+ // "forbidType": 0,
1045
+ // "totalConvertCNY": "147.760811613032",
1046
+ // "cAvailableCNY": "0.00",
1047
+ // "unwindPrice": "0.00",
1048
+ // "fOverdraft": "0.00",
1049
+ // "fShowName": "USDT",
1050
+ // "statusShow": "%E6%AD%A3%E5%B8%B8",
1051
+ // "cOverdraft": "0.00",
1052
+ // "netConvertUSD": "20.49273433",
1053
+ // "cNetBtc": "0.00",
1054
+ // "loanInConvertCNY": "0.00",
1055
+ // "fAvailableCNY": "147.760811613032",
1056
+ // "key": "btcusdt",
1057
+ // "fNetBtc": "0.0005291",
1058
+ // "fUnitDecimal": 8,
1059
+ // "loanInConvertUSD": "0.00",
1060
+ // "showName": "BTC/USDT",
1061
+ // "startLine": "1.25",
1062
+ // "totalConvertUSD": "20.49273433",
1063
+ // "couldTransferOutCoin": "0.00",
1064
+ // "cEnName": "BTC",
1065
+ // "leverMultipleInterest": "3.00",
1066
+ // "fAvailable": "20.49273433",
1067
+ // "fEnName": "USDT",
1068
+ // "forceRepayLine": "1.08",
1069
+ // "cLoanIn": "0.00"
1070
+ // }
1071
+ // ]
1072
+ // }
1073
+ // }
1074
+ // }
1075
+ //
1076
+ // Cross Margin
1077
+ //
1078
+ // {
1079
+ // "code": 1000,
1080
+ // "message": "操作成功",
1081
+ // "result": {
1082
+ // "loanIn": 0,
1083
+ // "total": 71.167,
1084
+ // "riskRate": "-",
1085
+ // "list" :[
1086
+ // {
1087
+ // "fundType": 2,
1088
+ // "loanIn": 0,
1089
+ // "amount": 0,
1090
+ // "freeze": 0,
1091
+ // "overdraft": 0,
1092
+ // "key": "BTC",
1093
+ // "canTransferOut": 0
1094
+ // },
1095
+ // ],
1096
+ // "net": 71.167
1097
+ // }
1098
+ // }
1099
+ //
1100
+ // todo: use this somehow
1101
+ // let permissions = response['result']['base'];
1102
+ if (swap) {
1103
+ return this.parseSwapBalance (response);
1104
+ } else if (margin) {
1105
+ return this.parseMarginBalance (response, marginType);
1106
+ } else {
1107
+ return this.parseBalance (response);
1108
+ }
1109
+ }
1110
+
1111
+ parseDepositAddress (depositAddress, currency = undefined) {
1112
+ //
1113
+ // fetchDepositAddress
1114
+ //
1115
+ // {
1116
+ // "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
1117
+ // }
1118
+ //
1119
+ // fetchDepositAddresses
1120
+ //
1121
+ // {
1122
+ // "blockChain": "btc",
1123
+ // "isUseMemo": false,
1124
+ // "address": "1LL5ati6pXHZnTGzHSA3rWdqi4mGGXudwM",
1125
+ // "canWithdraw": true,
1126
+ // "canDeposit": true
1127
+ // }
1128
+ // {
1129
+ // "blockChain": "bts",
1130
+ // "isUseMemo": true,
1131
+ // "account": "btstest",
1132
+ // "memo": "123",
1133
+ // "canWithdraw": true,
1134
+ // "canDeposit": true
1135
+ // }
1136
+ //
1137
+ let address = this.safeString2 (depositAddress, 'key', 'address');
1138
+ let tag = undefined;
1139
+ const memo = this.safeString (depositAddress, 'memo');
1140
+ if (memo !== undefined) {
1141
+ tag = memo;
1142
+ } else if (address.indexOf ('_') >= 0) {
1143
+ const parts = address.split ('_');
1144
+ address = parts[0]; // WARNING: MAY BE tag_address INSTEAD OF address_tag FOR SOME CURRENCIES!!
1145
+ tag = parts[1];
1146
+ }
1147
+ const currencyId = this.safeString (depositAddress, 'blockChain');
1148
+ const code = this.safeCurrencyCode (currencyId, currency);
1149
+ return {
1150
+ 'currency': code,
1151
+ 'address': address,
1152
+ 'tag': tag,
1153
+ 'network': undefined,
1154
+ 'info': depositAddress,
1155
+ };
1156
+ }
1157
+
1158
+ async fetchDepositAddresses (codes = undefined, params = {}) {
1159
+ await this.loadMarkets ();
1160
+ const response = await this.spotV1PrivateGetGetPayinAddress (params);
1161
+ //
1162
+ // {
1163
+ // "code": 1000,
1164
+ // "message": {
1165
+ // "des": "success",
1166
+ // "isSuc": true,
1167
+ // "datas": [
1168
+ // {
1169
+ // "blockChain": "btc",
1170
+ // "isUseMemo": false,
1171
+ // "address": "1LL5ati6pXHZnTGzHSA3rWdqi4mGGXudwM",
1172
+ // "canWithdraw": true,
1173
+ // "canDeposit": true
1174
+ // },
1175
+ // {
1176
+ // "blockChain": "bts",
1177
+ // "isUseMemo": true,
1178
+ // "account": "btstest",
1179
+ // "memo": "123",
1180
+ // "canWithdraw": true,
1181
+ // "canDeposit": true
1182
+ // },
1183
+ // ]
1184
+ // }
1185
+ // }
1186
+ //
1187
+ const message = this.safeValue (response, 'message', {});
1188
+ const datas = this.safeValue (message, 'datas', []);
1189
+ return this.parseDepositAddresses (datas, codes);
1190
+ }
1191
+
1192
+ async fetchDepositAddress (code, params = {}) {
1193
+ await this.loadMarkets ();
1194
+ const currency = this.currency (code);
1195
+ const request = {
1196
+ 'currency': currency['id'],
1197
+ };
1198
+ const response = await this.spotV1PrivateGetGetUserAddress (this.extend (request, params));
1199
+ //
1200
+ // {
1201
+ // "code": 1000,
1202
+ // "message": {
1203
+ // "des": "success",
1204
+ // "isSuc": true,
1205
+ // "datas": {
1206
+ // "key": "0x0af7f36b8f09410f3df62c81e5846da673d4d9a9"
1207
+ // }
1208
+ // }
1209
+ // }
1210
+ //
1211
+ const message = this.safeValue (response, 'message', {});
1212
+ const datas = this.safeValue (message, 'datas', {});
1213
+ return this.parseDepositAddress (datas, currency);
1214
+ }
1215
+
1216
+ async fetchOrderBook (symbol, limit = undefined, params = {}) {
1217
+ await this.loadMarkets ();
1218
+ const market = this.market (symbol);
1219
+ const request = {
1220
+ // 'market': market['id'], // only applicable to SPOT
1221
+ // 'symbol': market['id'], // only applicable to SWAP
1222
+ // 'size': limit, // 1-50 applicable to SPOT and SWAP
1223
+ // 'merge': 5.0, // float default depth only applicable to SPOT
1224
+ // 'scale': 5, // int accuracy, only applicable to SWAP
1225
+ };
1226
+ const marketIdField = market['swap'] ? 'symbol' : 'market';
1227
+ request[marketIdField] = market['id'];
1228
+ const method = this.getSupportedMapping (market['type'], {
1229
+ 'spot': 'spotV1PublicGetDepth',
1230
+ 'swap': 'contractV1PublicGetDepth',
1231
+ });
1232
+ if (limit !== undefined) {
1233
+ request['size'] = limit;
1234
+ }
1235
+ const response = await this[method] (this.extend (request, params));
1236
+ //
1237
+ // Spot
1238
+ //
1239
+ // {
1240
+ // "asks":[
1241
+ // [35000.0,0.2741],
1242
+ // [34949.0,0.0173],
1243
+ // [34900.0,0.5004],
1244
+ // ],
1245
+ // "bids":[
1246
+ // [34119.32,0.0030],
1247
+ // [34107.83,0.1500],
1248
+ // [34104.42,0.1500],
1249
+ // ],
1250
+ // "timestamp":1624536510
1251
+ // }
1252
+ //
1253
+ // Swap
1254
+ //
1255
+ // {
1256
+ // "code": 10000,
1257
+ // "desc": "操作成功",
1258
+ // "data": {
1259
+ // "asks": [
1260
+ // [43416.6,0.02],
1261
+ // [43418.25,0.04],
1262
+ // [43425.82,0.02]
1263
+ // ],
1264
+ // "bids": [
1265
+ // [43414.61,0.1],
1266
+ // [43414.18,0.04],
1267
+ // [43413.03,0.05]
1268
+ // ],
1269
+ // "time": 1645087743071
1270
+ // }
1271
+ // }
1272
+ //
1273
+ let result = undefined;
1274
+ let timestamp = undefined;
1275
+ if (market['type'] === 'swap') {
1276
+ result = this.safeValue (response, 'data');
1277
+ timestamp = this.safeInteger (result, 'time');
1278
+ } else {
1279
+ result = response;
1280
+ timestamp = this.safeTimestamp (response, 'timestamp');
1281
+ }
1282
+ return this.parseOrderBook (result, symbol, timestamp);
1283
+ }
1284
+
1285
+ async fetchTickers (symbols = undefined, params = {}) {
1286
+ await this.loadMarkets ();
1287
+ const response = await this.spotV1PublicGetAllTicker (params);
1288
+ const result = {};
1289
+ const marketsByIdWithoutUnderscore = {};
1290
+ const marketIds = Object.keys (this.markets_by_id);
1291
+ for (let i = 0; i < marketIds.length; i++) {
1292
+ const tickerId = marketIds[i].replace ('_', '');
1293
+ marketsByIdWithoutUnderscore[tickerId] = this.markets_by_id[marketIds[i]];
1294
+ }
1295
+ const ids = Object.keys (response);
1296
+ for (let i = 0; i < ids.length; i++) {
1297
+ const market = this.safeValue (marketsByIdWithoutUnderscore, ids[i]);
1298
+ if (market !== undefined) {
1299
+ const symbol = market['symbol'];
1300
+ const ticker = this.safeValue (response, ids[i]);
1301
+ if (ticker !== undefined) {
1302
+ result[symbol] = this.parseTicker (ticker, market);
1303
+ }
1304
+ }
1305
+ }
1306
+ return this.filterByArray (result, 'symbol', symbols);
1307
+ }
1308
+
1309
+ async fetchTicker (symbol, params = {}) {
1310
+ await this.loadMarkets ();
1311
+ const market = this.market (symbol);
1312
+ const request = {
1313
+ // 'market': market['id'], // only applicable to SPOT
1314
+ // 'symbol': market['id'], // only applicable to SWAP
1315
+ };
1316
+ const marketIdField = market['swap'] ? 'symbol' : 'market';
1317
+ request[marketIdField] = market['id'];
1318
+ const method = this.getSupportedMapping (market['type'], {
1319
+ 'spot': 'spotV1PublicGetTicker',
1320
+ 'swap': 'contractV1PublicGetTicker',
1321
+ });
1322
+ const response = await this[method] (this.extend (request, params));
1323
+ //
1324
+ // Spot
1325
+ //
1326
+ // {
1327
+ // "date":"1624399623587",
1328
+ // "ticker":{
1329
+ // "high":"33298.38",
1330
+ // "vol":"56152.9012",
1331
+ // "last":"32578.55",
1332
+ // "low":"28808.19",
1333
+ // "buy":"32572.68",
1334
+ // "sell":"32615.37",
1335
+ // "turnover":"1764201303.6100",
1336
+ // "open":"31664.85",
1337
+ // "riseRate":"2.89"
1338
+ // }
1339
+ // }
1340
+ //
1341
+ // Swap
1342
+ //
1343
+ // {
1344
+ // "code": 10000,
1345
+ // "desc": "操作成功",
1346
+ // "data": {
1347
+ // "BTC_USDT": [44053.47,44357.77,42911.54,43297.79,53471.264,-1.72,1645093002,302201.255084]
1348
+ // }
1349
+ // }
1350
+ //
1351
+ let ticker = undefined;
1352
+ if (market['type'] === 'swap') {
1353
+ ticker = {};
1354
+ const data = this.safeValue (response, 'data');
1355
+ const values = this.safeValue (data, market['id']);
1356
+ for (let i = 0; i < values.length; i++) {
1357
+ ticker['open'] = this.safeValue (values, 0);
1358
+ ticker['high'] = this.safeValue (values, 1);
1359
+ ticker['low'] = this.safeValue (values, 2);
1360
+ ticker['last'] = this.safeValue (values, 3);
1361
+ ticker['vol'] = this.safeValue (values, 4);
1362
+ ticker['riseRate'] = this.safeValue (values, 5);
1363
+ }
1364
+ } else {
1365
+ ticker = this.safeValue (response, 'ticker', {});
1366
+ ticker['date'] = this.safeValue (response, 'date');
1367
+ }
1368
+ return this.parseTicker (ticker, market);
1369
+ }
1370
+
1371
+ parseTicker (ticker, market = undefined) {
1372
+ //
1373
+ // Spot
1374
+ //
1375
+ // {
1376
+ // "date":"1624399623587", // injected from outside
1377
+ // "high":"33298.38",
1378
+ // "vol":"56152.9012",
1379
+ // "last":"32578.55",
1380
+ // "low":"28808.19",
1381
+ // "buy":"32572.68",
1382
+ // "sell":"32615.37",
1383
+ // "turnover":"1764201303.6100",
1384
+ // "open":"31664.85",
1385
+ // "riseRate":"2.89"
1386
+ // }
1387
+ //
1388
+ // Swap
1389
+ //
1390
+ // {
1391
+ // open: 44083.82,
1392
+ // high: 44357.77,
1393
+ // low: 42911.54,
1394
+ // last: 43097.87,
1395
+ // vol: 53451.641,
1396
+ // riseRate: -2.24
1397
+ // }
1398
+ //
1399
+ const timestamp = this.safeInteger (ticker, 'date', this.milliseconds ());
1400
+ const last = this.safeString (ticker, 'last');
1401
+ return this.safeTicker ({
1402
+ 'symbol': this.safeSymbol (undefined, market),
1403
+ 'timestamp': timestamp,
1404
+ 'datetime': this.iso8601 (timestamp),
1405
+ 'high': this.safeString (ticker, 'high'),
1406
+ 'low': this.safeString (ticker, 'low'),
1407
+ 'bid': this.safeString (ticker, 'buy'),
1408
+ 'bidVolume': undefined,
1409
+ 'ask': this.safeString (ticker, 'sell'),
1410
+ 'askVolume': undefined,
1411
+ 'vwap': undefined,
1412
+ 'open': this.safeString (ticker, 'open'),
1413
+ 'close': last,
1414
+ 'last': last,
1415
+ 'previousClose': undefined,
1416
+ 'change': undefined,
1417
+ 'percentage': undefined,
1418
+ 'average': undefined,
1419
+ 'baseVolume': this.safeString (ticker, 'vol'),
1420
+ 'quoteVolume': undefined,
1421
+ 'info': ticker,
1422
+ }, market, false);
1423
+ }
1424
+
1425
+ parseOHLCV (ohlcv, market = undefined) {
1426
+ if (market['swap']) {
1427
+ const ohlcvLength = ohlcv.length;
1428
+ if (ohlcvLength > 5) {
1429
+ return [
1430
+ this.safeTimestamp (ohlcv, 5),
1431
+ this.safeNumber (ohlcv, 0),
1432
+ this.safeNumber (ohlcv, 1),
1433
+ this.safeNumber (ohlcv, 2),
1434
+ this.safeNumber (ohlcv, 3),
1435
+ this.safeNumber (ohlcv, 4),
1436
+ ];
1437
+ } else {
1438
+ return [
1439
+ this.safeTimestamp (ohlcv, 4),
1440
+ this.safeNumber (ohlcv, 0),
1441
+ this.safeNumber (ohlcv, 1),
1442
+ this.safeNumber (ohlcv, 2),
1443
+ this.safeNumber (ohlcv, 3),
1444
+ undefined,
1445
+ ];
1446
+ }
1447
+ } else {
1448
+ return [
1449
+ this.safeInteger (ohlcv, 0),
1450
+ this.safeNumber (ohlcv, 1),
1451
+ this.safeNumber (ohlcv, 2),
1452
+ this.safeNumber (ohlcv, 3),
1453
+ this.safeNumber (ohlcv, 4),
1454
+ this.safeNumber (ohlcv, 5),
1455
+ ];
1456
+ }
1457
+ }
1458
+
1459
+ async fetchOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1460
+ await this.loadMarkets ();
1461
+ const market = this.market (symbol);
1462
+ const swap = market['swap'];
1463
+ const spot = market['spot'];
1464
+ const options = this.safeValue (this.options, 'timeframes', {});
1465
+ const timeframes = this.safeValue (options, market['type'], {});
1466
+ const timeframeValue = this.safeString (timeframes, timeframe);
1467
+ if (timeframeValue === undefined) {
1468
+ throw new NotSupported (this.id + ' fetchOHLCV() does not support ' + timeframe + ' timeframe for ' + market['type'] + ' markets');
1469
+ }
1470
+ if (limit === undefined) {
1471
+ limit = 1000;
1472
+ }
1473
+ const request = {
1474
+ // 'market': market['id'], // spot only
1475
+ // 'symbol': market['id'], // swap only
1476
+ // 'type': timeframeValue, // spot only
1477
+ // 'period': timeframeValue, // swap only
1478
+ // 'since': since, // spot only
1479
+ // 'size': limit, // spot and swap
1480
+ };
1481
+ const marketIdField = swap ? 'symbol' : 'market';
1482
+ request[marketIdField] = market['id'];
1483
+ const periodField = swap ? 'period' : 'type';
1484
+ request[periodField] = timeframeValue;
1485
+ const price = this.safeString (params, 'price');
1486
+ params = this.omit (params, 'price');
1487
+ let method = this.getSupportedMapping (market['type'], {
1488
+ 'spot': 'spotV1PublicGetKline',
1489
+ 'swap': 'contractV1PublicGetKline',
1490
+ });
1491
+ if (swap) {
1492
+ if (price === 'mark') {
1493
+ method = 'contractV1PublicGetMarkKline';
1494
+ } else if (price === 'index') {
1495
+ method = 'contractV1PublicGetIndexKline';
1496
+ }
1497
+ } else if (spot) {
1498
+ if (since !== undefined) {
1499
+ request['since'] = since;
1500
+ }
1501
+ }
1502
+ if (limit !== undefined) {
1503
+ request['size'] = limit;
1504
+ }
1505
+ const response = await this[method] (this.extend (request, params));
1506
+ //
1507
+ // Spot
1508
+ //
1509
+ // {
1510
+ // "symbol": "BTC",
1511
+ // "data": [
1512
+ // [1645091400000,43183.24,43187.49,43145.92,43182.28,0.9110],
1513
+ // [1645091460000,43182.18,43183.15,43182.06,43183.15,1.4393],
1514
+ // [1645091520000,43182.11,43240.1,43182.11,43240.1,0.3802]
1515
+ // ],
1516
+ // "moneyType": "USDT"
1517
+ // }
1518
+ //
1519
+ // Swap
1520
+ //
1521
+ // {
1522
+ // "code": 10000,
1523
+ // "desc": "操作成功",
1524
+ // "data": [
1525
+ // [41433.44,41433.44,41405.88,41408.75,21.368,1646366460],
1526
+ // [41409.25,41423.74,41408.8,41423.42,9.828,1646366520],
1527
+ // [41423.96,41429.39,41369.98,41370.31,123.104,1646366580]
1528
+ // ]
1529
+ // }
1530
+ //
1531
+ // Mark
1532
+ //
1533
+ // {
1534
+ // "code": 10000,
1535
+ // "desc": "操作成功",
1536
+ // "data": [
1537
+ // [41603.39,41603.39,41591.59,41600.81,1646381760],
1538
+ // [41600.36,41605.75,41587.69,41601.97,1646381820],
1539
+ // [41601.97,41601.97,41562.62,41593.96,1646381880]
1540
+ // ]
1541
+ // }
1542
+ //
1543
+ // Index
1544
+ //
1545
+ // {
1546
+ // "code": 10000,
1547
+ // "desc": "操作成功",
1548
+ // "data": [
1549
+ // [41697.53,41722.29,41689.16,41689.16,1646381640],
1550
+ // [41690.1,41691.73,41611.61,41611.61,1646381700],
1551
+ // [41611.61,41619.49,41594.87,41594.87,1646381760]
1552
+ // ]
1553
+ // }
1554
+ //
1555
+ const data = this.safeValue (response, 'data', []);
1556
+ return this.parseOHLCVs (data, market, timeframe, since, limit);
1557
+ }
1558
+
1559
+ async fetchMarkOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1560
+ const request = {
1561
+ 'price': 'mark',
1562
+ };
1563
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
1564
+ }
1565
+
1566
+ async fetchIndexOHLCV (symbol, timeframe = '1m', since = undefined, limit = undefined, params = {}) {
1567
+ const request = {
1568
+ 'price': 'index',
1569
+ };
1570
+ return await this.fetchOHLCV (symbol, timeframe, since, limit, this.extend (request, params));
1571
+ }
1572
+
1573
+ parseTrade (trade, market = undefined) {
1574
+ //
1575
+ // Spot
1576
+ //
1577
+ // {
1578
+ // "date":1624537391,
1579
+ // "amount":"0.0142",
1580
+ // "price":"33936.42",
1581
+ // "trade_type":"ask",
1582
+ // "type":"sell",
1583
+ // "tid":1718869018
1584
+ // }
1585
+ //
1586
+ // Swap
1587
+ //
1588
+ // {
1589
+ // "amount": "0.002",
1590
+ // "createTime": "1645787446034",
1591
+ // "feeAmount": "-0.05762699",
1592
+ // "feeCurrency": "USDT",
1593
+ // "id": "6902932868050395136",
1594
+ // "maker": false,
1595
+ // "orderId": "6902932868042006528",
1596
+ // "price": "38417.99",
1597
+ // "relizedPnl": "0.30402",
1598
+ // "side": 4,
1599
+ // "userId": "6896693805014120448"
1600
+ // },
1601
+ //
1602
+ const sideField = market['swap'] ? 'side' : 'trade_type';
1603
+ let side = this.safeString (trade, sideField);
1604
+ let takerOrMaker = undefined;
1605
+ const maker = this.safeValue (trade, 'maker');
1606
+ if (maker !== undefined) {
1607
+ takerOrMaker = maker ? 'maker' : 'taker';
1608
+ }
1609
+ if (market['spot']) {
1610
+ side = (side === 'bid') ? 'buy' : 'sell';
1611
+ } else {
1612
+ if (side === '3') {
1613
+ side = 'sell'; // close long
1614
+ } else if (side === '4') {
1615
+ side = 'buy'; // close short
1616
+ } else if (side === '1') {
1617
+ side = 'buy'; // open long
1618
+ } else if (side === '2') {
1619
+ side = 'sell'; // open short
1620
+ }
1621
+ }
1622
+ let timestamp = undefined;
1623
+ if (market['swap']) {
1624
+ timestamp = this.safeInteger (trade, 'createTime');
1625
+ } else {
1626
+ timestamp = this.safeTimestamp (trade, 'date');
1627
+ }
1628
+ const price = this.safeString (trade, 'price');
1629
+ const amount = this.safeString (trade, 'amount');
1630
+ let fee = undefined;
1631
+ const feeCostString = this.safeString (trade, 'feeAmount');
1632
+ if (feeCostString !== undefined) {
1633
+ const feeCurrencyId = this.safeString (trade, 'feeCurrency');
1634
+ fee = {
1635
+ 'cost': feeCostString,
1636
+ 'currency': this.safeCurrencyCode (feeCurrencyId),
1637
+ };
1638
+ }
1639
+ market = this.safeMarket (undefined, market);
1640
+ return this.safeTrade ({
1641
+ 'info': trade,
1642
+ 'id': this.safeString (trade, 'tid'),
1643
+ 'timestamp': timestamp,
1644
+ 'datetime': this.iso8601 (timestamp),
1645
+ 'symbol': market['symbol'],
1646
+ 'type': undefined,
1647
+ 'side': side,
1648
+ 'order': this.safeString (trade, 'orderId'),
1649
+ 'takerOrMaker': takerOrMaker,
1650
+ 'price': price,
1651
+ 'amount': amount,
1652
+ 'cost': undefined,
1653
+ 'fee': fee,
1654
+ }, market);
1655
+ }
1656
+
1657
+ async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
1658
+ if (symbol === undefined) {
1659
+ throw new ArgumentsRequired (this.id + ' fetchTrades() requires a symbol argument');
1660
+ }
1661
+ await this.loadMarkets ();
1662
+ const market = this.market (symbol);
1663
+ const swap = market['swap'];
1664
+ const request = {
1665
+ // 'market': market['id'], // SPOT
1666
+ // 'symbol': market['id'], // SWAP
1667
+ // 'side': 1, // SWAP
1668
+ // 'dateRange': 0, // SWAP
1669
+ // 'startTime': since, // SWAP
1670
+ // 'endtime': this.milliseconds (), // SWAP
1671
+ // 'pageNum': 1, // SWAP
1672
+ // 'pageSize': limit, // SWAP default is 10
1673
+ };
1674
+ if (limit !== undefined) {
1675
+ request['pageSize'] = limit;
1676
+ }
1677
+ if (since !== undefined) {
1678
+ request['startTime'] = since;
1679
+ }
1680
+ const marketIdField = swap ? 'symbol' : 'market';
1681
+ request[marketIdField] = market['id'];
1682
+ if (swap && params['pageNum'] === undefined) {
1683
+ request['pageNum'] = 1;
1684
+ }
1685
+ const method = this.getSupportedMapping (market['type'], {
1686
+ 'spot': 'spotV1PublicGetTrades',
1687
+ 'swap': 'contractV2PrivateGetTradeTradeHistory',
1688
+ });
1689
+ let response = await this[method] (this.extend (request, params));
1690
+ //
1691
+ // Spot
1692
+ //
1693
+ // [
1694
+ // {"date":1624537391,"amount":"0.0142","price":"33936.42","trade_type":"ask","type":"sell","tid":1718869018},
1695
+ // {"date":1624537391,"amount":"0.0010","price":"33936.42","trade_type":"ask","type":"sell","tid":1718869020},
1696
+ // {"date":1624537391,"amount":"0.0133","price":"33936.42","trade_type":"ask","type":"sell","tid":1718869021},
1697
+ // ]
1698
+ //
1699
+ // Swap
1700
+ //
1701
+ // {
1702
+ // "code": 10000,
1703
+ // "data": {
1704
+ // "list": [
1705
+ // {
1706
+ // "amount": "0.002",
1707
+ // "createTime": "1645787446034",
1708
+ // "feeAmount": "-0.05762699",
1709
+ // "feeCurrency": "USDT",
1710
+ // "id": "6902932868050395136",
1711
+ // "maker": false,
1712
+ // "orderId": "6902932868042006528",
1713
+ // "price": "38417.99",
1714
+ // "relizedPnl": "0.30402",
1715
+ // "side": 4,
1716
+ // "userId": "6896693805014120448"
1717
+ // },
1718
+ // ],
1719
+ // "pageNum": 1,
1720
+ // "pageSize": 10
1721
+ // },
1722
+ // "desc": "操作成功"
1723
+ // }
1724
+ //
1725
+ if (swap) {
1726
+ const data = this.safeValue (response, 'data');
1727
+ response = this.safeValue (data, 'list');
1728
+ }
1729
+ return this.parseTrades (response, market, since, limit);
1730
+ }
1731
+
1732
+ async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
1733
+ await this.loadMarkets ();
1734
+ const market = this.market (symbol);
1735
+ const swap = market['swap'];
1736
+ const spot = market['spot'];
1737
+ const timeInForce = this.safeString (params, 'timeInForce');
1738
+ const reduceOnly = this.safeValue (params, 'reduceOnly');
1739
+ const stop = this.safeValue (params, 'stop');
1740
+ const stopPrice = this.safeNumber2 (params, 'triggerPrice', 'stopPrice');
1741
+ if (type === 'market') {
1742
+ throw new InvalidOrder (this.id + ' createOrder() on ' + market['type'] + ' markets does not allow market orders');
1743
+ }
1744
+ let method = this.getSupportedMapping (market['type'], {
1745
+ 'spot': 'spotV1PrivateGetOrder',
1746
+ 'swap': 'contractV2PrivatePostTradeOrder',
1747
+ });
1748
+ const request = {
1749
+ 'amount': this.amountToPrecision (symbol, amount),
1750
+ // 'symbol': market['id'],
1751
+ // 'acctType': 0, // Spot, Margin 0/1/2 [Spot/Isolated/Cross] Optional, Default to: 0 Spot
1752
+ // 'customerOrderId': '1f2g', // Spot, Margin
1753
+ // 'orderType': 1, // Spot, Margin order type 1/2 [PostOnly/IOC] Optional
1754
+ // 'triggerPrice': 30000.0, // Stop trigger price
1755
+ // 'algoPrice': 29000.0, // Stop order price
1756
+ // 'priceType': 1, // Stop Loss Take Profit, 1: Mark price, 2: Last price
1757
+ // 'bizType': 1, // Stop Loss Take Profit, 1: TP, 2: SL
1758
+ };
1759
+ if (stop || stopPrice) {
1760
+ method = 'contractV2PrivatePostTradeOrderAlgo';
1761
+ const orderType = this.safeInteger (params, 'orderType');
1762
+ const priceType = this.safeInteger (params, 'priceType');
1763
+ const bizType = this.safeInteger (params, 'bizType');
1764
+ const algoPrice = this.safeNumber (params, 'algoPrice');
1765
+ request['symbol'] = market['id'];
1766
+ if (side === 'sell' && reduceOnly) {
1767
+ request['side'] = 3; // close long
1768
+ } else if (side === 'buy' && reduceOnly) {
1769
+ request['side'] = 4; // close short
1770
+ } else if (side === 'buy') {
1771
+ request['side'] = 1; // open long
1772
+ } else if (side === 'sell') {
1773
+ request['side'] = 2; // open short
1774
+ } else if (side === 5) {
1775
+ request['side'] = 5; // one way position buy
1776
+ } else if (side === 6) {
1777
+ request['side'] = 6; // one way position sell
1778
+ } else if (side === 0) {
1779
+ request['side'] = 0; // one way position close only
1780
+ }
1781
+ if (type === 'trigger' || orderType === 1) {
1782
+ request['orderType'] = 1;
1783
+ } else if (type === 'stop loss' || type === 'take profit' || orderType === 2 || priceType || bizType) {
1784
+ request['orderType'] = 2;
1785
+ request['priceType'] = priceType;
1786
+ request['bizType'] = bizType;
1787
+ }
1788
+ request['triggerPrice'] = this.priceToPrecision (symbol, stopPrice);
1789
+ request['algoPrice'] = this.priceToPrecision (symbol, algoPrice);
1790
+ } else {
1791
+ if (price) {
1792
+ request['price'] = this.priceToPrecision (symbol, price);
1793
+ }
1794
+ if (spot) {
1795
+ request['tradeType'] = (side === 'buy') ? '1' : '0';
1796
+ request['currency'] = market['id'];
1797
+ if (timeInForce !== undefined) {
1798
+ if (timeInForce === 'PO') {
1799
+ request['orderType'] = 1;
1800
+ } else if (timeInForce === 'IOC') {
1801
+ request['orderType'] = 2;
1802
+ } else {
1803
+ throw new InvalidOrder (this.id + ' createOrder() on ' + market['type'] + ' markets does not allow ' + timeInForce + ' orders');
1804
+ }
1805
+ }
1806
+ } else if (swap) {
1807
+ if (side === 'sell' && reduceOnly) {
1808
+ request['side'] = 3; // close long
1809
+ } else if (side === 'buy' && reduceOnly) {
1810
+ request['side'] = 4; // close short
1811
+ } else if (side === 'buy') {
1812
+ request['side'] = 1; // open long
1813
+ } else if (side === 'sell') {
1814
+ request['side'] = 2; // open short
1815
+ }
1816
+ if (type === 'limit') {
1817
+ request['action'] = 1;
1818
+ } else if (timeInForce === 'IOC') {
1819
+ request['action'] = 3;
1820
+ } else if (timeInForce === 'PO') {
1821
+ request['action'] = 4;
1822
+ } else if (timeInForce === 'FOK') {
1823
+ request['action'] = 5;
1824
+ } else {
1825
+ request['action'] = type;
1826
+ }
1827
+ request['symbol'] = market['id'];
1828
+ request['clientOrderId'] = params['clientOrderId']; // OPTIONAL '^[a-zA-Z0-9-_]{1,36}$', // The user-defined order number
1829
+ request['extend'] = params['extend']; // OPTIONAL {"orderAlgos":[{"bizType":1,"priceType":1,"triggerPrice":"70000"},{"bizType":2,"priceType":1,"triggerPrice":"40000"}]}
1830
+ }
1831
+ }
1832
+ const query = this.omit (params, [ 'reduceOnly', 'stop', 'stopPrice', 'orderType', 'triggerPrice', 'algoPrice', 'priceType', 'bizType' ]);
1833
+ let response = await this[method] (this.extend (request, query));
1834
+ //
1835
+ // Spot
1836
+ //
1837
+ // {
1838
+ // "code": 1000,
1839
+ // "message": "操作成功",
1840
+ // "id": "202202224851151555"
1841
+ // }
1842
+ //
1843
+ // Swap
1844
+ //
1845
+ // {
1846
+ // "code": 10000,
1847
+ // "desc": "操作成功",
1848
+ // "data": {
1849
+ // "orderId": "6901786759944937472",
1850
+ // "orderCode": null
1851
+ // }
1852
+ // }
1853
+ //
1854
+ // Algo order
1855
+ //
1856
+ // {
1857
+ // "code": 10000,
1858
+ // "data": "6919884551305242624",
1859
+ // "desc": "操作成功"
1860
+ // }
1861
+ //
1862
+ if (swap && stop === undefined && stopPrice === undefined) {
1863
+ response = this.safeValue (response, 'data');
1864
+ response['timeInForce'] = timeInForce;
1865
+ response['type'] = request['tradeType'];
1866
+ response['total_amount'] = amount;
1867
+ response['price'] = price;
1868
+ }
1869
+ return this.parseOrder (response, market);
1870
+ }
1871
+
1872
+ async cancelOrder (id, symbol = undefined, params = {}) {
1873
+ if (symbol === undefined) {
1874
+ throw new ArgumentsRequired (this.id + ' cancelOrder() requires a symbol argument');
1875
+ }
1876
+ await this.loadMarkets ();
1877
+ const market = this.market (symbol);
1878
+ const swap = market['swap'];
1879
+ const request = {
1880
+ // 'currency': this.marketId (symbol), // only applicable to SPOT
1881
+ // 'id': id.toString (), // only applicable to SPOT
1882
+ // 'symbol': this.marketId (symbol), // only applicable to SWAP
1883
+ // 'orderId': id.toString (), // only applicable to SWAP
1884
+ // 'clientOrderId': params['clientOrderId'], // only applicable to SWAP
1885
+ };
1886
+ const marketIdField = swap ? 'symbol' : 'currency';
1887
+ request[marketIdField] = this.marketId (symbol);
1888
+ const orderIdField = swap ? 'orderId' : 'id';
1889
+ request[orderIdField] = id.toString ();
1890
+ const method = this.getSupportedMapping (market['type'], {
1891
+ 'spot': 'spotV1PrivateGetCancelOrder',
1892
+ 'swap': 'contractV2PrivatePostTradeCancelOrder',
1893
+ });
1894
+ const response = await this[method] (this.extend (request, params));
1895
+ //
1896
+ // Spot
1897
+ //
1898
+ // {
1899
+ // "code": 1000,
1900
+ // "message": "Success。"
1901
+ // }
1902
+ //
1903
+ // Swap
1904
+ //
1905
+ // {
1906
+ // "code": 10007,
1907
+ // "desc": "orderId与clientOrderId选填1个"
1908
+ // }
1909
+ //
1910
+ return this.parseOrder (response, market);
1911
+ }
1912
+
1913
+ async cancelAllOrders (symbol = undefined, params = {}) {
1914
+ if (symbol === undefined) {
1915
+ throw new ArgumentsRequired (this.id + ' cancelAllOrders() requires a symbol argument');
1916
+ }
1917
+ await this.loadMarkets ();
1918
+ const market = this.market (symbol);
1919
+ const stop = this.safeValue (params, 'stop');
1920
+ if (market['spot']) {
1921
+ throw new NotSupported (this.id + ' cancelAllOrders() is not supported on ' + market['type'] + ' markets');
1922
+ }
1923
+ const request = {
1924
+ 'symbol': market['id'],
1925
+ // 'ids': [ 6904603200733782016, 6819506476072247297 ], // STOP
1926
+ // 'side': params['side'], // STOP, for stop orders: 1 Open long (buy), 2 Open short (sell), 3 Close long (sell), 4 Close Short (Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
1927
+ };
1928
+ let method = 'contractV2PrivatePostTradeCancelAllOrders';
1929
+ if (stop) {
1930
+ method = 'contractV2PrivatePostTradeCancelAlgos';
1931
+ }
1932
+ const query = this.omit (params, 'stop');
1933
+ return await this[method] (this.extend (request, query));
1934
+ }
1935
+
1936
+ async fetchOrder (id, symbol = undefined, params = {}) {
1937
+ if (symbol === undefined) {
1938
+ throw new ArgumentsRequired (this.id + ' fetchOrder() requires a symbol argument');
1939
+ }
1940
+ await this.loadMarkets ();
1941
+ const market = this.market (symbol);
1942
+ const reduceOnly = this.safeValue (params, 'reduceOnly');
1943
+ const stop = this.safeValue (params, 'stop');
1944
+ const swap = market['swap'];
1945
+ const request = {
1946
+ // 'currency': this.marketId (symbol), // only applicable to SPOT
1947
+ // 'id': id.toString (), // only applicable to SPOT
1948
+ // 'orderId': id.toString (), // only applicable to SWAP
1949
+ // 'clientOrderId': params['clientOrderId'], // only applicable to SWAP
1950
+ // 'symbol': market['id'], // STOP and SWAP
1951
+ // 'side': params['side'], // STOP and SWAP, for stop orders: 1 Open long (buy), 2 Open short (sell), 3 Close long (sell), 4 Close Short (Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
1952
+ // 'orderType': 1, // STOP, 1: Plan order, 2: SP/SL
1953
+ // 'bizType': 1, // Plan order, 1: TP, 2: SL
1954
+ // 'status': 1, // STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
1955
+ // 'startTime': since, // STOP and SWAP
1956
+ // 'endTime': params['endTime'], // STOP and SWAP
1957
+ // 'pageNum': 1, // STOP and SWAP, default 1
1958
+ // 'pageSize': limit, // STOP, default 10
1959
+ };
1960
+ const marketIdField = swap ? 'symbol' : 'currency';
1961
+ request[marketIdField] = this.marketId (symbol);
1962
+ const orderIdField = swap ? 'orderId' : 'id';
1963
+ request[orderIdField] = id.toString ();
1964
+ let method = this.getSupportedMapping (market['type'], {
1965
+ 'spot': 'spotV1PrivateGetGetOrder',
1966
+ 'swap': 'contractV2PrivateGetTradeGetOrder',
1967
+ });
1968
+ if (stop) {
1969
+ method = 'contractV2PrivateGetTradeGetOrderAlgos';
1970
+ const orderType = this.safeInteger (params, 'orderType');
1971
+ if (orderType === undefined) {
1972
+ throw new ArgumentsRequired (this.id + ' fetchOrder() requires an orderType parameter for stop orders');
1973
+ }
1974
+ const side = this.safeInteger (params, 'side');
1975
+ const bizType = this.safeInteger (params, 'bizType');
1976
+ if (side === 'sell' && reduceOnly) {
1977
+ request['side'] = 3; // close long
1978
+ } else if (side === 'buy' && reduceOnly) {
1979
+ request['side'] = 4; // close short
1980
+ } else if (side === 'buy') {
1981
+ request['side'] = 1; // open long
1982
+ } else if (side === 'sell') {
1983
+ request['side'] = 2; // open short
1984
+ } else if (side === 5) {
1985
+ request['side'] = 5; // one way position buy
1986
+ } else if (side === 6) {
1987
+ request['side'] = 6; // one way position sell
1988
+ } else if (side === 0) {
1989
+ request['side'] = 0; // one way position close only
1990
+ }
1991
+ if (orderType === 1) {
1992
+ request['orderType'] = 1;
1993
+ } else if (orderType === 2 || bizType) {
1994
+ request['orderType'] = 2;
1995
+ request['bizType'] = bizType;
1996
+ }
1997
+ }
1998
+ const query = this.omit (params, [ 'reduceOnly', 'stop', 'side', 'orderType', 'bizType' ]);
1999
+ let response = await this[method] (this.extend (request, query));
2000
+ //
2001
+ // Spot
2002
+ //
2003
+ // {
2004
+ // 'total_amount': 0.01,
2005
+ // 'id': '20180910244276459',
2006
+ // 'price': 180.0,
2007
+ // 'trade_date': 1536576744960,
2008
+ // 'status': 2,
2009
+ // 'trade_money': '1.96742',
2010
+ // 'trade_amount': 0.01,
2011
+ // 'type': 0,
2012
+ // 'currency': 'eth_usdt'
2013
+ // }
2014
+ //
2015
+ // Swap
2016
+ //
2017
+ // {
2018
+ // "code": 10000,
2019
+ // "data": {
2020
+ // "action": 1,
2021
+ // "amount": "0.002",
2022
+ // "availableAmount": "0.002",
2023
+ // "availableValue": "60",
2024
+ // "avgPrice": "0",
2025
+ // "canCancel": true,
2026
+ // "cancelStatus": 20,
2027
+ // "createTime": "1646185684379",
2028
+ // "entrustType": 1,
2029
+ // "id": "6904603200733782016",
2030
+ // "leverage": 2,
2031
+ // "margin": "30",
2032
+ // "marketId": "100",
2033
+ // "modifyTime": "1646185684416",
2034
+ // "price": "30000",
2035
+ // "priority": 0,
2036
+ // "showStatus": 1,
2037
+ // "side": 1,
2038
+ // "sourceType": 4,
2039
+ // "status": 12,
2040
+ // "tradeAmount": "0",
2041
+ // "tradeValue": "0",
2042
+ // "type": 1,
2043
+ // "userId": "6896693805014120448",
2044
+ // "value": "60"
2045
+ // },
2046
+ // "desc":"操作成功"
2047
+ // }
2048
+ //
2049
+ // Algo order
2050
+ //
2051
+ // {
2052
+ // "code": 10000,
2053
+ // "data": {
2054
+ // "list": [
2055
+ // {
2056
+ // "action": 1,
2057
+ // "algoPrice": "30000",
2058
+ // "amount": "0.003",
2059
+ // "bizType": 0,
2060
+ // "canCancel": true,
2061
+ // "createTime": "1649913941109",
2062
+ // "errorCode": 0,
2063
+ // "id": "6920240642849449984",
2064
+ // "isLong": false,
2065
+ // "leverage": 10,
2066
+ // "marketId": "100",
2067
+ // "modifyTime": "1649913941109",
2068
+ // "orderType": 1,
2069
+ // "priceType": 2,
2070
+ // "side": 5,
2071
+ // "sourceType": 4,
2072
+ // "status": 1,
2073
+ // "submitPrice": "41270.53",
2074
+ // "symbol": "BTC_USDT",
2075
+ // "tradedAmount": "0",
2076
+ // "triggerCondition": "<=",
2077
+ // "triggerPrice": "31000",
2078
+ // "triggerTime": "0",
2079
+ // "userId": "6896693805014120448"
2080
+ // },
2081
+ // ],
2082
+ // "pageNum": 1,
2083
+ // "pageSize": 10
2084
+ // },
2085
+ // "desc": "操作成功"
2086
+ // }
2087
+ //
2088
+ if (stop) {
2089
+ const data = this.safeValue (response, 'data', {});
2090
+ response = this.safeValue (data, 'list', []);
2091
+ const result = [];
2092
+ for (let i = 0; i < response.length; i++) {
2093
+ const entry = response[i];
2094
+ const algoId = this.safeString (entry, 'id');
2095
+ if (id === algoId) {
2096
+ result.push (entry);
2097
+ }
2098
+ }
2099
+ response = result[0];
2100
+ }
2101
+ if (swap && !stop) {
2102
+ response = this.safeValue (response, 'data', {});
2103
+ }
2104
+ return this.parseOrder (response, market);
2105
+ }
2106
+
2107
+ async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
2108
+ if (symbol === undefined) {
2109
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires a symbol argument');
2110
+ }
2111
+ await this.loadMarkets ();
2112
+ const market = this.market (symbol);
2113
+ const reduceOnly = this.safeValue (params, 'reduceOnly');
2114
+ const stop = this.safeValue (params, 'stop');
2115
+ const swap = market['swap'];
2116
+ const request = {
2117
+ 'pageSize': limit, // default pageSize is 50 for spot, 30 for swap
2118
+ // 'currency': market['id'], // only applicable to SPOT
2119
+ // 'pageIndex': 1, // only applicable to SPOT
2120
+ // 'type': params['type'], // only applicable to SWAP
2121
+ // 'dateRange': params['dateRange'], // only applicable to SWAP
2122
+ // 'action': params['action'], // only applicable to SWAP
2123
+ // 'symbol': market['id'], // STOP and SWAP
2124
+ // 'side': params['side'], // STOP and SWAP, for stop orders: 1 Open long (buy), 2 Open short (sell), 3 Close long (sell), 4 Close Short (Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2125
+ // 'orderType': 1, // STOP, 1: Plan order, 2: SP/SL
2126
+ // 'bizType': 1, // Plan order, 1: TP, 2: SL
2127
+ // 'status': 1, // STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2128
+ // 'startTime': since, // STOP and SWAP
2129
+ // 'endTime': params['endTime'], // STOP and SWAP
2130
+ // 'pageNum': 1, // STOP and SWAP, default 1
2131
+ // 'pageSize': limit, // STOP, default 10
2132
+ };
2133
+ const marketIdField = market['swap'] ? 'symbol' : 'currency';
2134
+ request[marketIdField] = market['id'];
2135
+ const pageNumField = market['swap'] ? 'pageNum' : 'pageIndex';
2136
+ request[pageNumField] = 1;
2137
+ if (swap) {
2138
+ request['startTime'] = since;
2139
+ }
2140
+ let method = this.getSupportedMapping (market['type'], {
2141
+ 'spot': 'spotV1PrivateGetGetOrdersIgnoreTradeType',
2142
+ 'swap': 'contractV2PrivateGetTradeGetAllOrders',
2143
+ });
2144
+ // tradeType 交易类型1/0[buy/sell]
2145
+ if ('tradeType' in params) {
2146
+ method = 'spotV1PrivateGetGetOrdersNew';
2147
+ }
2148
+ if (stop) {
2149
+ method = 'contractV2PrivateGetTradeGetOrderAlgos';
2150
+ const orderType = this.safeInteger (params, 'orderType');
2151
+ if (orderType === undefined) {
2152
+ throw new ArgumentsRequired (this.id + ' fetchOrders() requires an orderType parameter for stop orders');
2153
+ }
2154
+ const side = this.safeInteger (params, 'side');
2155
+ const bizType = this.safeInteger (params, 'bizType');
2156
+ if (side === 'sell' && reduceOnly) {
2157
+ request['side'] = 3; // close long
2158
+ } else if (side === 'buy' && reduceOnly) {
2159
+ request['side'] = 4; // close short
2160
+ } else if (side === 'buy') {
2161
+ request['side'] = 1; // open long
2162
+ } else if (side === 'sell') {
2163
+ request['side'] = 2; // open short
2164
+ } else if (side === 5) {
2165
+ request['side'] = 5; // one way position buy
2166
+ } else if (side === 6) {
2167
+ request['side'] = 6; // one way position sell
2168
+ } else if (side === 0) {
2169
+ request['side'] = 0; // one way position close only
2170
+ }
2171
+ if (orderType === 1) {
2172
+ request['orderType'] = 1;
2173
+ } else if (orderType === 2 || bizType) {
2174
+ request['orderType'] = 2;
2175
+ request['bizType'] = bizType;
2176
+ }
2177
+ }
2178
+ const query = this.omit (params, [ 'reduceOnly', 'stop', 'side', 'orderType', 'bizType' ]);
2179
+ let response = undefined;
2180
+ try {
2181
+ response = await this[method] (this.extend (request, query));
2182
+ } catch (e) {
2183
+ if (e instanceof OrderNotFound) {
2184
+ return [];
2185
+ }
2186
+ throw e;
2187
+ }
2188
+ // Spot
2189
+ //
2190
+ // [
2191
+ // {
2192
+ // "acctType": 0,
2193
+ // "currency": "btc_usdt",
2194
+ // "fees": 0,
2195
+ // "id": "202202234857482656",
2196
+ // "price": 30000.0,
2197
+ // "status": 3,
2198
+ // "total_amount": 0.0006,
2199
+ // "trade_amount": 0.0000,
2200
+ // "trade_date": 1645610254524,
2201
+ // "trade_money": 0.000000,
2202
+ // "type": 1,
2203
+ // "useZbFee": false,
2204
+ // "webId": 0
2205
+ // }
2206
+ // ]
2207
+ //
2208
+ // Swap
2209
+ //
2210
+ // {
2211
+ // "code": 10000,
2212
+ // "data": {
2213
+ // "list": [
2214
+ // {
2215
+ // "action": 1,
2216
+ // "amount": "0.004",
2217
+ // "availableAmount": "0.004",
2218
+ // "availableValue": "120",
2219
+ // "avgPrice": "0",
2220
+ // "canCancel": true,
2221
+ // "cancelStatus": 20,
2222
+ // "createTime": "1645609643885",
2223
+ // "entrustType": 1,
2224
+ // "id": "6902187111785635850",
2225
+ // "leverage": 5,
2226
+ // "margin": "24",
2227
+ // "marketId": "100",
2228
+ // "marketName": "BTC_USDT",
2229
+ // "modifyTime": "1645609643889",
2230
+ // "price": "30000",
2231
+ // "showStatus": 1,
2232
+ // "side": 1,
2233
+ // "sourceType": 1,
2234
+ // "status": 12,
2235
+ // "tradeAmount": "0",
2236
+ // "tradeValue": "0",
2237
+ // "type": 1,
2238
+ // "userId": "6896693805014120448",
2239
+ // "value": "120"
2240
+ // },
2241
+ // ],
2242
+ // "pageNum": 1,
2243
+ // "pageSize": 10
2244
+ // },
2245
+ // "desc": "操作成功"
2246
+ // }
2247
+ //
2248
+ // Algo order
2249
+ //
2250
+ // {
2251
+ // "code": 10000,
2252
+ // "data": {
2253
+ // "list": [
2254
+ // {
2255
+ // "action": 1,
2256
+ // "algoPrice": "30000",
2257
+ // "amount": "0.003",
2258
+ // "bizType": 0,
2259
+ // "canCancel": true,
2260
+ // "createTime": "1649913941109",
2261
+ // "errorCode": 0,
2262
+ // "id": "6920240642849449984",
2263
+ // "isLong": false,
2264
+ // "leverage": 10,
2265
+ // "marketId": "100",
2266
+ // "modifyTime": "1649913941109",
2267
+ // "orderType": 1,
2268
+ // "priceType": 2,
2269
+ // "side": 5,
2270
+ // "sourceType": 4,
2271
+ // "status": 1,
2272
+ // "submitPrice": "41270.53",
2273
+ // "symbol": "BTC_USDT",
2274
+ // "tradedAmount": "0",
2275
+ // "triggerCondition": "<=",
2276
+ // "triggerPrice": "31000",
2277
+ // "triggerTime": "0",
2278
+ // "userId": "6896693805014120448"
2279
+ // },
2280
+ // ],
2281
+ // "pageNum": 1,
2282
+ // "pageSize": 10
2283
+ // },
2284
+ // "desc": "操作成功"
2285
+ // }
2286
+ //
2287
+ if (swap) {
2288
+ const data = this.safeValue (response, 'data', {});
2289
+ response = this.safeValue (data, 'list', []);
2290
+ }
2291
+ return this.parseOrders (response, market, since, limit);
2292
+ }
2293
+
2294
+ async fetchCanceledOrders (symbol = undefined, since = undefined, limit = 10, params = {}) {
2295
+ if (symbol === undefined) {
2296
+ throw new ArgumentsRequired (this.id + ' fetchCanceledOrders() requires a symbol argument');
2297
+ }
2298
+ await this.loadMarkets ();
2299
+ const market = this.market (symbol);
2300
+ const reduceOnly = this.safeValue (params, 'reduceOnly');
2301
+ const stop = this.safeValue (params, 'stop');
2302
+ const request = {
2303
+ 'pageSize': limit, // SPOT and STOP, default pageSize is 10, doesn't work with other values now
2304
+ // 'currency': market['id'], // SPOT
2305
+ // 'pageIndex': 1, // SPOT, default pageIndex is 1
2306
+ // 'symbol': market['id'], // STOP
2307
+ // 'side': params['side'], // STOP, for stop orders: 1 Open long (buy), 2 Open short (sell), 3 Close long (sell), 4 Close Short (Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2308
+ // 'orderType': 1, // STOP, 1: Plan order, 2: SP/SL
2309
+ // 'bizType': 1, // Plan order, 1: TP, 2: SL
2310
+ // 'status': 1, // STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2311
+ // 'startTime': since, // STOP
2312
+ // 'endTime': params['endTime'], // STOP
2313
+ // 'pageNum': 1, // STOP, default 1
2314
+ };
2315
+ const marketIdField = market['spot'] ? 'currency' : 'symbol';
2316
+ request[marketIdField] = market['id'];
2317
+ const pageNumField = market['spot'] ? 'pageIndex' : 'pageNum';
2318
+ request[pageNumField] = 1;
2319
+ let method = 'spotV1PrivateGetGetOrdersIgnoreTradeType';
2320
+ if (stop) {
2321
+ method = 'contractV2PrivateGetTradeGetOrderAlgos';
2322
+ const orderType = this.safeInteger (params, 'orderType');
2323
+ if (orderType === undefined) {
2324
+ throw new ArgumentsRequired (this.id + ' fetchCanceledOrders() requires an orderType parameter for stop orders');
2325
+ }
2326
+ const side = this.safeInteger (params, 'side');
2327
+ const bizType = this.safeInteger (params, 'bizType');
2328
+ if (side === 'sell' && reduceOnly) {
2329
+ request['side'] = 3; // close long
2330
+ } else if (side === 'buy' && reduceOnly) {
2331
+ request['side'] = 4; // close short
2332
+ } else if (side === 'buy') {
2333
+ request['side'] = 1; // open long
2334
+ } else if (side === 'sell') {
2335
+ request['side'] = 2; // open short
2336
+ } else if (side === 5) {
2337
+ request['side'] = 5; // one way position buy
2338
+ } else if (side === 6) {
2339
+ request['side'] = 6; // one way position sell
2340
+ } else if (side === 0) {
2341
+ request['side'] = 0; // one way position close only
2342
+ }
2343
+ if (orderType === 1) {
2344
+ request['orderType'] = 1;
2345
+ } else if (orderType === 2 || bizType) {
2346
+ request['orderType'] = 2;
2347
+ request['bizType'] = bizType;
2348
+ }
2349
+ request['status'] = 2;
2350
+ }
2351
+ // tradeType 交易类型1/0[buy/sell]
2352
+ if ('tradeType' in params) {
2353
+ method = 'spotV1PrivateGetGetOrdersNew';
2354
+ }
2355
+ let response = undefined;
2356
+ try {
2357
+ response = await this[method] (this.extend (request, params));
2358
+ } catch (e) {
2359
+ if (e instanceof OrderNotFound) {
2360
+ return [];
2361
+ }
2362
+ throw e;
2363
+ }
2364
+ const query = this.omit (params, [ 'reduceOnly', 'stop', 'side', 'orderType', 'bizType' ]);
2365
+ response = await this[method] (this.extend (request, query));
2366
+ //
2367
+ // Spot
2368
+ //
2369
+ // [
2370
+ // {
2371
+ // "acctType": 0,
2372
+ // "currency": "btc_usdt",
2373
+ // "fees": 0,
2374
+ // "id": "202202234857482656",
2375
+ // "price": 30000.0,
2376
+ // "status": 1,
2377
+ // "total_amount": 0.0006,
2378
+ // "trade_amount": 0.0000,
2379
+ // "trade_date": 1645610254524,
2380
+ // "trade_money": 0.000000,
2381
+ // "type": 1,
2382
+ // "useZbFee": false,
2383
+ // "webId": 0
2384
+ // }
2385
+ // ]
2386
+ //
2387
+ // Algo order
2388
+ //
2389
+ // {
2390
+ // "code": 10000,
2391
+ // "data": {
2392
+ // "list": [
2393
+ // {
2394
+ // "action": 1,
2395
+ // "algoPrice": "30000",
2396
+ // "amount": "0.003",
2397
+ // "bizType": 0,
2398
+ // "canCancel": true,
2399
+ // "createTime": "1649913941109",
2400
+ // "errorCode": 0,
2401
+ // "id": "6920240642849449984",
2402
+ // "isLong": false,
2403
+ // "leverage": 10,
2404
+ // "marketId": "100",
2405
+ // "modifyTime": "1649913941109",
2406
+ // "orderType": 1,
2407
+ // "priceType": 2,
2408
+ // "side": 5,
2409
+ // "sourceType": 4,
2410
+ // "status": 2,
2411
+ // "submitPrice": "41270.53",
2412
+ // "symbol": "BTC_USDT",
2413
+ // "tradedAmount": "0",
2414
+ // "triggerCondition": "<=",
2415
+ // "triggerPrice": "31000",
2416
+ // "triggerTime": "0",
2417
+ // "userId": "6896693805014120448"
2418
+ // },
2419
+ // ],
2420
+ // "pageNum": 1,
2421
+ // "pageSize": 10
2422
+ // },
2423
+ // "desc": "操作成功"
2424
+ // }
2425
+ //
2426
+ if (stop) {
2427
+ const data = this.safeValue (response, 'data', {});
2428
+ response = this.safeValue (data, 'list', []);
2429
+ }
2430
+ const result = [];
2431
+ if (market['type'] === 'spot') {
2432
+ for (let i = 0; i < response.length; i++) {
2433
+ const entry = response[i];
2434
+ const status = this.safeString (entry, 'status');
2435
+ if (status === '1') {
2436
+ result.push (entry);
2437
+ }
2438
+ }
2439
+ response = result;
2440
+ }
2441
+ return this.parseOrders (response, market, since, limit);
2442
+ }
2443
+
2444
+ async fetchClosedOrders (symbol = undefined, since = undefined, limit = 10, params = {}) {
2445
+ if (symbol === undefined) {
2446
+ throw new ArgumentsRequired (this.id + ' fetchClosedOrders() requires a symbol argument');
2447
+ }
2448
+ await this.loadMarkets ();
2449
+ const market = this.market (symbol);
2450
+ const reduceOnly = this.safeValue (params, 'reduceOnly');
2451
+ const stop = this.safeValue (params, 'stop');
2452
+ const request = {
2453
+ 'pageSize': limit, // SPOT and STOP, default pageSize is 10, doesn't work with other values now
2454
+ // 'currency': market['id'], // SPOT
2455
+ // 'pageIndex': 1, // SPOT, default pageIndex is 1
2456
+ // 'symbol': market['id'], // STOP
2457
+ // 'side': params['side'], // STOP, for stop orders: 1 Open long (buy), 2 Open short (sell), 3 Close long (sell), 4 Close Short (Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2458
+ // 'orderType': 1, // STOP, 1: Plan order, 2: SP/SL
2459
+ // 'bizType': 1, // Plan order, 1: TP, 2: SL
2460
+ // 'status': 1, // STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2461
+ // 'startTime': since, // STOP
2462
+ // 'endTime': params['endTime'], // STOP
2463
+ // 'pageNum': 1, // STOP, default 1
2464
+ };
2465
+ const marketIdField = market['spot'] ? 'currency' : 'symbol';
2466
+ request[marketIdField] = market['id'];
2467
+ const pageNumField = market['spot'] ? 'pageIndex' : 'pageNum';
2468
+ request[pageNumField] = 1;
2469
+ let method = 'spotV1PrivateGetGetFinishedAndPartialOrders';
2470
+ if (stop) {
2471
+ method = 'contractV2PrivateGetTradeGetOrderAlgos';
2472
+ const orderType = this.safeInteger (params, 'orderType');
2473
+ if (orderType === undefined) {
2474
+ throw new ArgumentsRequired (this.id + ' fetchClosedOrders() requires an orderType parameter for stop orders');
2475
+ }
2476
+ const side = this.safeInteger (params, 'side');
2477
+ const bizType = this.safeInteger (params, 'bizType');
2478
+ if (side === 'sell' && reduceOnly) {
2479
+ request['side'] = 3; // close long
2480
+ } else if (side === 'buy' && reduceOnly) {
2481
+ request['side'] = 4; // close short
2482
+ } else if (side === 'buy') {
2483
+ request['side'] = 1; // open long
2484
+ } else if (side === 'sell') {
2485
+ request['side'] = 2; // open short
2486
+ } else if (side === 5) {
2487
+ request['side'] = 5; // one way position buy
2488
+ } else if (side === 6) {
2489
+ request['side'] = 6; // one way position sell
2490
+ } else if (side === 0) {
2491
+ request['side'] = 0; // one way position close only
2492
+ }
2493
+ if (orderType === 1) {
2494
+ request['orderType'] = 1;
2495
+ } else if (orderType === 2 || bizType) {
2496
+ request['orderType'] = 2;
2497
+ request['bizType'] = bizType;
2498
+ }
2499
+ request['status'] = 5;
2500
+ }
2501
+ const query = this.omit (params, [ 'reduceOnly', 'stop', 'side', 'orderType', 'bizType' ]);
2502
+ let response = await this[method] (this.extend (request, query));
2503
+ //
2504
+ // Spot
2505
+ //
2506
+ // [
2507
+ // {
2508
+ // "acctType": 0,
2509
+ // "currency": "btc_usdt",
2510
+ // "fees": 0.00823354,
2511
+ // "id": "202204145086706337",
2512
+ // "price": 41167.7,
2513
+ // "status": 2,
2514
+ // "total_amount": 0.0001,
2515
+ // "trade_amount": 0.0001,
2516
+ // "trade_date": 1649917867370,
2517
+ // "trade_money": 4.116770,
2518
+ // "type": 0,
2519
+ // "useZbFee": false,
2520
+ // "webId": 0
2521
+ // },
2522
+ // ]
2523
+ //
2524
+ // Algo order
2525
+ //
2526
+ // {
2527
+ // "code": 10000,
2528
+ // "data": {
2529
+ // "list": [
2530
+ // {
2531
+ // "action": 1,
2532
+ // "algoPrice": "30000",
2533
+ // "amount": "0.003",
2534
+ // "bizType": 0,
2535
+ // "canCancel": true,
2536
+ // "createTime": "1649913941109",
2537
+ // "errorCode": 0,
2538
+ // "id": "6920240642849449984",
2539
+ // "isLong": false,
2540
+ // "leverage": 10,
2541
+ // "marketId": "100",
2542
+ // "modifyTime": "1649913941109",
2543
+ // "orderType": 1,
2544
+ // "priceType": 2,
2545
+ // "side": 5,
2546
+ // "sourceType": 4,
2547
+ // "status": 1,
2548
+ // "submitPrice": "41270.53",
2549
+ // "symbol": "BTC_USDT",
2550
+ // "tradedAmount": "0",
2551
+ // "triggerCondition": "<=",
2552
+ // "triggerPrice": "31000",
2553
+ // "triggerTime": "0",
2554
+ // "userId": "6896693805014120448"
2555
+ // },
2556
+ // ],
2557
+ // "pageNum": 1,
2558
+ // "pageSize": 10
2559
+ // },
2560
+ // "desc": "操作成功"
2561
+ // }
2562
+ //
2563
+ if (stop) {
2564
+ const data = this.safeValue (response, 'data', {});
2565
+ response = this.safeValue (data, 'list', []);
2566
+ }
2567
+ return this.parseOrders (response, market, since, limit);
2568
+ }
2569
+
2570
+ async fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
2571
+ if (symbol === undefined) {
2572
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires a symbol argument');
2573
+ }
2574
+ await this.loadMarkets ();
2575
+ const market = this.market (symbol);
2576
+ const reduceOnly = this.safeValue (params, 'reduceOnly');
2577
+ const stop = this.safeValue (params, 'stop');
2578
+ const swap = market['swap'];
2579
+ const request = {
2580
+ // 'pageSize': limit, // default pageSize is 10 for spot, 30 for swap
2581
+ // 'currency': market['id'], // SPOT
2582
+ // 'pageIndex': 1, // SPOT
2583
+ // 'symbol': market['id'], // SWAP and STOP
2584
+ // 'pageNum': 1, // SWAP and STOP, default 1
2585
+ // 'type': params['type'], // swap only
2586
+ // 'side': params['side'], // SWAP and STOP, for stop orders: 1 Open long (buy), 2 Open short (sell), 3 Close long (sell), 4 Close Short (Buy). One-Way Positions: 5 Buy, 6 Sell, 0 Close Only
2587
+ // 'action': params['action'], // SWAP
2588
+ // 'orderType': 1, // STOP, 1: Plan order, 2: SP/SL
2589
+ // 'bizType': 1, // Plan order, 1: TP, 2: SL
2590
+ // 'status': 1, // STOP, 1: untriggered, 2: cancelled, 3:triggered, 4:failed, 5:completed
2591
+ // 'startTime': since, // SWAP and STOP
2592
+ // 'endTime': params['endTime'], // STOP
2593
+ };
2594
+ if (limit !== undefined) {
2595
+ request['pageSize'] = limit; // default pageSize is 10 for spot, 30 for swap
2596
+ }
2597
+ const marketIdField = market['swap'] ? 'symbol' : 'currency';
2598
+ request[marketIdField] = market['id'];
2599
+ const pageNumField = market['swap'] ? 'pageNum' : 'pageIndex';
2600
+ request[pageNumField] = 1;
2601
+ if (swap && (since !== undefined)) {
2602
+ request['startTime'] = since;
2603
+ }
2604
+ let method = this.getSupportedMapping (market['type'], {
2605
+ 'spot': 'spotV1PrivateGetGetUnfinishedOrdersIgnoreTradeType',
2606
+ 'swap': 'contractV2PrivateGetTradeGetUndoneOrders',
2607
+ });
2608
+ if (stop) {
2609
+ method = 'contractV2PrivateGetTradeGetOrderAlgos';
2610
+ const orderType = this.safeInteger (params, 'orderType');
2611
+ if (orderType === undefined) {
2612
+ throw new ArgumentsRequired (this.id + ' fetchOpenOrders() requires an orderType parameter for stop orders');
2613
+ }
2614
+ const side = this.safeInteger (params, 'side');
2615
+ const bizType = this.safeInteger (params, 'bizType');
2616
+ if (side === 'sell' && reduceOnly) {
2617
+ request['side'] = 3; // close long
2618
+ } else if (side === 'buy' && reduceOnly) {
2619
+ request['side'] = 4; // close short
2620
+ } else if (side === 'buy') {
2621
+ request['side'] = 1; // open long
2622
+ } else if (side === 'sell') {
2623
+ request['side'] = 2; // open short
2624
+ } else if (side === 5) {
2625
+ request['side'] = 5; // one way position buy
2626
+ } else if (side === 6) {
2627
+ request['side'] = 6; // one way position sell
2628
+ } else if (side === 0) {
2629
+ request['side'] = 0; // one way position close only
2630
+ }
2631
+ if (orderType === 1) {
2632
+ request['orderType'] = 1;
2633
+ } else if (orderType === 2 || bizType) {
2634
+ request['orderType'] = 2;
2635
+ request['bizType'] = bizType;
2636
+ }
2637
+ request['status'] = 1;
2638
+ }
2639
+ const query = this.omit (params, [ 'reduceOnly', 'stop', 'side', 'orderType', 'bizType' ]);
2640
+ // tradeType 交易类型1/0[buy/sell]
2641
+ if ('tradeType' in params) {
2642
+ method = 'spotV1PrivateGetGetOrdersNew';
2643
+ }
2644
+ let response = undefined;
2645
+ try {
2646
+ response = await this[method] (this.extend (request, query));
2647
+ } catch (e) {
2648
+ if (e instanceof OrderNotFound) {
2649
+ return [];
2650
+ }
2651
+ throw e;
2652
+ }
2653
+ //
2654
+ // Spot
2655
+ //
2656
+ // [
2657
+ // {
2658
+ // "currency": "btc_usdt",
2659
+ // "id": "20150928158614292",
2660
+ // "price": 1560,
2661
+ // "status": 3,
2662
+ // "total_amount": 0.1,
2663
+ // "trade_amount": 0,
2664
+ // "trade_date": 1443410396717,
2665
+ // "trade_money": 0,
2666
+ // "type": 0,
2667
+ // "fees": "0.03",
2668
+ // "useZbFee": true
2669
+ // },
2670
+ // ]
2671
+ //
2672
+ // Swap
2673
+ //
2674
+ // {
2675
+ // "code": 10000,
2676
+ // "data": {
2677
+ // "list": [
2678
+ // {
2679
+ // "action": 1,
2680
+ // "amount": "0.003",
2681
+ // "availableAmount": "0.003",
2682
+ // "availableValue": "90",
2683
+ // "avgPrice": "0",
2684
+ // "canCancel": true,
2685
+ // "cancelStatus": 20,
2686
+ // "createTime": "1645694610880",
2687
+ // "entrustType": 1,
2688
+ // "id": "6902543489192632320",
2689
+ // "leverage": 5,
2690
+ // "margin": "18",
2691
+ // "marketId": "100",
2692
+ // "modifyTime": "1645694610883",
2693
+ // "price": "30000",
2694
+ // "priority": 0,
2695
+ // "showStatus": 1,
2696
+ // "side": 1,
2697
+ // "sourceType": 1,
2698
+ // "status": 12,
2699
+ // "tradeAmount": "0",
2700
+ // "tradeValue": "0",
2701
+ // "type": 1,
2702
+ // "userId": "6896693805014120448",
2703
+ // "value": "90"
2704
+ // }
2705
+ // ],
2706
+ // "pageNum": 1,
2707
+ // "pageSize": 30
2708
+ // },
2709
+ // "desc": "操作成功"
2710
+ // }
2711
+ //
2712
+ // Algo order
2713
+ //
2714
+ // {
2715
+ // "code": 10000,
2716
+ // "data": {
2717
+ // "list": [
2718
+ // {
2719
+ // "action": 1,
2720
+ // "algoPrice": "30000",
2721
+ // "amount": "0.003",
2722
+ // "bizType": 0,
2723
+ // "canCancel": true,
2724
+ // "createTime": "1649913941109",
2725
+ // "errorCode": 0,
2726
+ // "id": "6920240642849449984",
2727
+ // "isLong": false,
2728
+ // "leverage": 10,
2729
+ // "marketId": "100",
2730
+ // "modifyTime": "1649913941109",
2731
+ // "orderType": 1,
2732
+ // "priceType": 2,
2733
+ // "side": 5,
2734
+ // "sourceType": 4,
2735
+ // "status": 1,
2736
+ // "submitPrice": "41270.53",
2737
+ // "symbol": "BTC_USDT",
2738
+ // "tradedAmount": "0",
2739
+ // "triggerCondition": "<=",
2740
+ // "triggerPrice": "31000",
2741
+ // "triggerTime": "0",
2742
+ // "userId": "6896693805014120448"
2743
+ // },
2744
+ // ],
2745
+ // "pageNum": 1,
2746
+ // "pageSize": 10
2747
+ // },
2748
+ // "desc": "操作成功"
2749
+ // }
2750
+ //
2751
+ if (swap) {
2752
+ const data = this.safeValue (response, 'data', {});
2753
+ response = this.safeValue (data, 'list', []);
2754
+ }
2755
+ return this.parseOrders (response, market, since, limit);
2756
+ }
2757
+
2758
+ parseOrder (order, market = undefined) {
2759
+ //
2760
+ // Spot fetchOrder, fetchClosedOrders
2761
+ //
2762
+ // {
2763
+ // acctType: 0,
2764
+ // currency: 'btc_usdt',
2765
+ // fees: 3.6e-7,
2766
+ // id: '202102282829772463',
2767
+ // price: 45177.5,
2768
+ // status: 2,
2769
+ // total_amount: 0.0002,
2770
+ // trade_amount: 0.0002,
2771
+ // trade_date: 1614515104998,
2772
+ // trade_money: 8.983712,
2773
+ // type: 1,
2774
+ // useZbFee: false
2775
+ // },
2776
+ //
2777
+ // Swap fetchOrder
2778
+ //
2779
+ // {
2780
+ // "action": 1,
2781
+ // "amount": "0.002",
2782
+ // "availableAmount": "0.002",
2783
+ // "availableValue": "60",
2784
+ // "avgPrice": "0",
2785
+ // "canCancel": true,
2786
+ // "cancelStatus": 20,
2787
+ // "createTime": "1646185684379",
2788
+ // "entrustType": 1,
2789
+ // "id": "6904603200733782016",
2790
+ // "leverage": 2,
2791
+ // "margin": "30",
2792
+ // "marketId": "100",
2793
+ // "modifyTime": "1646185684416",
2794
+ // "price": "30000",
2795
+ // "priority": 0,
2796
+ // "showStatus": 1,
2797
+ // "side": 1,
2798
+ // "sourceType": 4,
2799
+ // "status": 12,
2800
+ // "tradeAmount": "0",
2801
+ // "tradeValue": "0",
2802
+ // "type": 1,
2803
+ // "userId": "6896693805014120448",
2804
+ // "value": "60"
2805
+ // },
2806
+ //
2807
+ // Algo fetchOrder, fetchOrders, fetchOpenOrders, fetchClosedOrders
2808
+ //
2809
+ // {
2810
+ // "action": 1,
2811
+ // "algoPrice": "30000",
2812
+ // "amount": "0.003",
2813
+ // "bizType": 0,
2814
+ // "canCancel": true,
2815
+ // "createTime": "1649913941109",
2816
+ // "errorCode": 0,
2817
+ // "id": "6920240642849449984",
2818
+ // "isLong": false,
2819
+ // "leverage": 10,
2820
+ // "marketId": "100",
2821
+ // "modifyTime": "1649913941109",
2822
+ // "orderType": 1,
2823
+ // "priceType": 2,
2824
+ // "side": 5,
2825
+ // "sourceType": 4,
2826
+ // "status": 1,
2827
+ // "submitPrice": "41270.53",
2828
+ // "symbol": "BTC_USDT",
2829
+ // "tradedAmount": "0",
2830
+ // "triggerCondition": "<=",
2831
+ // "triggerPrice": "31000",
2832
+ // "triggerTime": "0",
2833
+ // "userId": "6896693805014120448"
2834
+ // },
2835
+ //
2836
+ // Spot createOrder
2837
+ //
2838
+ // {
2839
+ // code: '1000',
2840
+ // message: '操作成功',
2841
+ // id: '202202224851151555',
2842
+ // type: '1',
2843
+ // total_amount: 0.0002,
2844
+ // price: 30000
2845
+ // }
2846
+ //
2847
+ // Swap createOrder
2848
+ //
2849
+ // {
2850
+ // orderId: '6901786759944937472',
2851
+ // orderCode: null,
2852
+ // timeInForce: 'IOC',
2853
+ // total_amount: 0.0002,
2854
+ // price: 30000
2855
+ // }
2856
+ //
2857
+ // Algo createOrder
2858
+ //
2859
+ // {
2860
+ // "code": 10000,
2861
+ // "data": "6919884551305242624",
2862
+ // "desc": "操作成功"
2863
+ // }
2864
+ //
2865
+ let orderId = market['swap'] ? this.safeValue (order, 'orderId') : this.safeValue (order, 'id');
2866
+ if (orderId === undefined) {
2867
+ orderId = this.safeValue (order, 'id');
2868
+ }
2869
+ let side = this.safeInteger2 (order, 'type', 'side');
2870
+ if (side === undefined) {
2871
+ side = undefined;
2872
+ } else {
2873
+ if (market['type'] === 'spot') {
2874
+ side = (side === 1) ? 'buy' : 'sell';
2875
+ }
2876
+ }
2877
+ let timestamp = this.safeInteger (order, 'trade_date');
2878
+ if (timestamp === undefined) {
2879
+ timestamp = this.safeInteger (order, 'createTime');
2880
+ }
2881
+ const marketId = this.safeString (order, 'currency');
2882
+ market = this.safeMarket (marketId, market, '_');
2883
+ const price = this.safeString2 (order, 'price', 'algoPrice');
2884
+ const filled = market['swap'] ? this.safeString (order, 'tradeAmount') : this.safeString (order, 'trade_amount');
2885
+ let amount = this.safeString (order, 'total_amount');
2886
+ if (amount === undefined) {
2887
+ amount = this.safeString (order, 'amount');
2888
+ }
2889
+ const cost = this.safeString (order, 'trade_money');
2890
+ const status = this.parseOrderStatus (this.safeString (order, 'status'), market);
2891
+ const timeInForce = this.safeString (order, 'timeInForce');
2892
+ const postOnly = (timeInForce === 'PO');
2893
+ const feeCost = this.safeNumber (order, 'fees');
2894
+ let fee = undefined;
2895
+ if (feeCost !== undefined) {
2896
+ let feeCurrency = undefined;
2897
+ const zbFees = this.safeValue (order, 'useZbFee');
2898
+ if (zbFees === true) {
2899
+ feeCurrency = 'ZB';
2900
+ } else {
2901
+ feeCurrency = (side === 'sell') ? market['quote'] : market['base'];
2902
+ }
2903
+ fee = {
2904
+ 'cost': feeCost,
2905
+ 'currency': feeCurrency,
2906
+ };
2907
+ }
2908
+ return this.safeOrder ({
2909
+ 'info': order,
2910
+ 'id': orderId,
2911
+ 'clientOrderId': this.safeString (order, 'userId'),
2912
+ 'timestamp': timestamp,
2913
+ 'datetime': this.iso8601 (timestamp),
2914
+ 'lastTradeTimestamp': undefined,
2915
+ 'symbol': market['symbol'],
2916
+ 'type': 'limit', // market order is not available on ZB
2917
+ 'timeInForce': timeInForce,
2918
+ 'postOnly': postOnly,
2919
+ 'side': side,
2920
+ 'price': price,
2921
+ 'stopPrice': this.safeString (order, 'triggerPrice'),
2922
+ 'average': this.safeString (order, 'avgPrice'),
2923
+ 'cost': cost,
2924
+ 'amount': amount,
2925
+ 'filled': filled,
2926
+ 'remaining': undefined,
2927
+ 'status': status,
2928
+ 'fee': fee,
2929
+ 'trades': undefined,
2930
+ }, market);
2931
+ }
2932
+
2933
+ parseOrderStatus (status, market = undefined) {
2934
+ let statuses = {};
2935
+ if (market['type'] === 'spot') {
2936
+ statuses = {
2937
+ '0': 'open',
2938
+ '1': 'canceled',
2939
+ '2': 'closed',
2940
+ '3': 'open', // partial
2941
+ };
2942
+ } else {
2943
+ statuses = {
2944
+ '1': 'open',
2945
+ '2': 'canceled',
2946
+ '3': 'open', // stop order triggered
2947
+ '4': 'failed',
2948
+ '5': 'closed',
2949
+ };
2950
+ }
2951
+ return this.safeString (statuses, status, status);
2952
+ }
2953
+
2954
+ parseTransactionStatus (status) {
2955
+ const statuses = {
2956
+ '0': 'pending', // submitted, pending confirmation
2957
+ '1': 'failed',
2958
+ '2': 'ok',
2959
+ '3': 'canceled',
2960
+ '5': 'ok', // confirmed
2961
+ };
2962
+ return this.safeString (statuses, status, status);
2963
+ }
2964
+
2965
+ parseTransaction (transaction, currency = undefined) {
2966
+ //
2967
+ // withdraw
2968
+ //
2969
+ // {
2970
+ // "code": 1000,
2971
+ // "message": "success",
2972
+ // "id": "withdrawalId"
2973
+ // }
2974
+ //
2975
+ // fetchWithdrawals
2976
+ //
2977
+ // {
2978
+ // "amount": 0.01,
2979
+ // "fees": 0.001,
2980
+ // "id": 2016042556231,
2981
+ // "manageTime": 1461579340000,
2982
+ // "status": 3,
2983
+ // "submitTime": 1461579288000,
2984
+ // "toAddress": "14fxEPirL9fyfw1i9EF439Pq6gQ5xijUmp",
2985
+ // }
2986
+ //
2987
+ // fetchDeposits
2988
+ //
2989
+ // {
2990
+ // "address": "1FKN1DZqCm8HaTujDioRL2Aezdh7Qj7xxx",
2991
+ // "amount": "1.00000000",
2992
+ // "confirmTimes": 1,
2993
+ // "currency": "BTC",
2994
+ // "description": "Successfully Confirm",
2995
+ // "hash": "7ce842de187c379abafadd64a5fe66c5c61c8a21fb04edff9532234a1dae6xxx",
2996
+ // "id": 558,
2997
+ // "itransfer": 1,
2998
+ // "status": 2,
2999
+ // "submit_time": "2016-12-07 18:51:57",
3000
+ // }
3001
+ //
3002
+ const id = this.safeString (transaction, 'id');
3003
+ const txid = this.safeString (transaction, 'hash');
3004
+ const amount = this.safeNumber (transaction, 'amount');
3005
+ let timestamp = this.parse8601 (this.safeString (transaction, 'submit_time'));
3006
+ timestamp = this.safeInteger (transaction, 'submitTime', timestamp);
3007
+ let address = this.safeString2 (transaction, 'toAddress', 'address');
3008
+ let tag = undefined;
3009
+ if (address !== undefined) {
3010
+ const parts = address.split ('_');
3011
+ address = this.safeString (parts, 0);
3012
+ tag = this.safeString (parts, 1);
3013
+ }
3014
+ const confirmTimes = this.safeInteger (transaction, 'confirmTimes');
3015
+ const updated = this.safeInteger (transaction, 'manageTime');
3016
+ let type = undefined;
3017
+ const currencyId = this.safeString (transaction, 'currency');
3018
+ const code = this.safeCurrencyCode (currencyId, currency);
3019
+ if (address !== undefined) {
3020
+ type = (confirmTimes === undefined) ? 'withdrawal' : 'deposit';
3021
+ }
3022
+ const status = this.parseTransactionStatus (this.safeString (transaction, 'status'));
3023
+ let fee = undefined;
3024
+ const feeCost = this.safeNumber (transaction, 'fees');
3025
+ if (feeCost !== undefined) {
3026
+ fee = {
3027
+ 'cost': feeCost,
3028
+ 'currency': code,
3029
+ };
3030
+ }
3031
+ return {
3032
+ 'info': transaction,
3033
+ 'id': id,
3034
+ 'txid': txid,
3035
+ 'timestamp': timestamp,
3036
+ 'datetime': this.iso8601 (timestamp),
3037
+ 'network': undefined,
3038
+ 'addressFrom': undefined,
3039
+ 'address': address,
3040
+ 'addressTo': address,
3041
+ 'tagFrom': undefined,
3042
+ 'tag': tag,
3043
+ 'tagTo': tag,
3044
+ 'type': type,
3045
+ 'amount': amount,
3046
+ 'currency': code,
3047
+ 'status': status,
3048
+ 'updated': updated,
3049
+ 'fee': fee,
3050
+ };
3051
+ }
3052
+
3053
+ async setLeverage (leverage, symbol = undefined, params = {}) {
3054
+ await this.loadMarkets ();
3055
+ if (symbol === undefined) {
3056
+ throw new ArgumentsRequired (this.id + ' setLeverage() requires a symbol argument');
3057
+ }
3058
+ if ((leverage < 1) || (leverage > 125)) {
3059
+ throw new BadRequest (this.id + ' setLeverage() leverage should be between 1 and 125');
3060
+ }
3061
+ const market = this.market (symbol);
3062
+ let accountType = undefined;
3063
+ if (!market['swap']) {
3064
+ throw new BadSymbol (this.id + ' setLeverage() supports swap contracts only');
3065
+ } else {
3066
+ accountType = 1;
3067
+ }
3068
+ const request = {
3069
+ 'symbol': market['id'],
3070
+ 'leverage': leverage,
3071
+ 'futuresAccountType': accountType, // 1: USDT perpetual swaps
3072
+ };
3073
+ return await this.contractV2PrivatePostSettingSetLeverage (this.extend (request, params));
3074
+ }
3075
+
3076
+ async fetchFundingRateHistory (symbol = undefined, since = undefined, limit = undefined, params = {}) {
3077
+ await this.loadMarkets ();
3078
+ const request = {
3079
+ // 'symbol': market['id'],
3080
+ // 'startTime': since,
3081
+ // 'endTime': endTime, // current time by default
3082
+ // 'limit': limit, // default 100, max 1000
3083
+ };
3084
+ if (symbol !== undefined) {
3085
+ const market = this.market (symbol);
3086
+ symbol = market['symbol'];
3087
+ request['symbol'] = market['id'];
3088
+ }
3089
+ if (since !== undefined) {
3090
+ request['startTime'] = since;
3091
+ }
3092
+ const till = this.safeInteger (params, 'till');
3093
+ const endTime = this.safeString (params, 'endTime');
3094
+ params = this.omit (params, [ 'endTime', 'till' ]);
3095
+ if (till !== undefined) {
3096
+ request['endTime'] = till;
3097
+ } else if (endTime !== undefined) {
3098
+ request['endTime'] = endTime;
3099
+ }
3100
+ if (limit !== undefined) {
3101
+ request['limit'] = limit;
3102
+ }
3103
+ const response = await this.contractV2PublicGetFundingRate (this.extend (request, params));
3104
+ //
3105
+ // {
3106
+ // "code": 10000,
3107
+ // "data": [
3108
+ // {
3109
+ // "symbol": "BTC_USDT",
3110
+ // "fundingRate": "0.0001",
3111
+ // "fundingTime": "1645171200000"
3112
+ // },
3113
+ // ],
3114
+ // "desc": "操作成功"
3115
+ // }
3116
+ //
3117
+ const data = this.safeValue (response, 'data');
3118
+ const rates = [];
3119
+ for (let i = 0; i < data.length; i++) {
3120
+ const entry = data[i];
3121
+ const marketId = this.safeString (entry, 'symbol');
3122
+ const symbol = this.safeSymbol (marketId);
3123
+ const timestamp = this.safeString (entry, 'fundingTime');
3124
+ rates.push ({
3125
+ 'info': entry,
3126
+ 'symbol': symbol,
3127
+ 'fundingRate': this.safeNumber (entry, 'fundingRate'),
3128
+ 'timestamp': timestamp,
3129
+ 'datetime': this.iso8601 (timestamp),
3130
+ });
3131
+ }
3132
+ const sorted = this.sortBy (rates, 'timestamp');
3133
+ return this.filterBySymbolSinceLimit (sorted, symbol, since, limit);
3134
+ }
3135
+
3136
+ async fetchFundingRate (symbol, params = {}) {
3137
+ await this.loadMarkets ();
3138
+ const market = this.market (symbol);
3139
+ if (!market['swap']) {
3140
+ throw new BadSymbol (this.id + ' fetchFundingRate() does not supports contracts only');
3141
+ }
3142
+ const request = {
3143
+ 'symbol': market['id'],
3144
+ };
3145
+ const response = await this.contractV1PublicGetFundingRate (this.extend (request, params));
3146
+ //
3147
+ // {
3148
+ // "code": 10000,
3149
+ // "desc": "操作成功",
3150
+ // "data": {
3151
+ // "fundingRate": "0.0001",
3152
+ // "nextCalculateTime": "2022-02-19 00:00:00"
3153
+ // }
3154
+ // }
3155
+ //
3156
+ const data = this.safeValue (response, 'data');
3157
+ return this.parseFundingRate (data, market);
3158
+ }
3159
+
3160
+ parseFundingRate (contract, market = undefined) {
3161
+ //
3162
+ // fetchFundingRate
3163
+ //
3164
+ // {
3165
+ // "fundingRate": "0.0001",
3166
+ // "nextCalculateTime": "2022-02-19 00:00:00"
3167
+ // }
3168
+ //
3169
+ // fetchFundingRates
3170
+ //
3171
+ // {
3172
+ // "symbol": "BTC_USDT",
3173
+ // "markPrice": "43254.42",
3174
+ // "indexPrice": "43278.61",
3175
+ // "lastFundingRate": "0.0001",
3176
+ // "nextFundingTime": "1646121600000"
3177
+ // }
3178
+ //
3179
+ const marketId = this.safeString (contract, 'symbol');
3180
+ const symbol = this.safeSymbol (marketId, market);
3181
+ const fundingRate = this.safeNumber (contract, 'fundingRate');
3182
+ const nextFundingDatetime = this.safeString (contract, 'nextCalculateTime');
3183
+ return {
3184
+ 'info': contract,
3185
+ 'symbol': symbol,
3186
+ 'markPrice': this.safeString (contract, 'markPrice'),
3187
+ 'indexPrice': this.safeString (contract, 'indexPrice'),
3188
+ 'interestRate': undefined,
3189
+ 'estimatedSettlePrice': undefined,
3190
+ 'timestamp': undefined,
3191
+ 'datetime': undefined,
3192
+ 'fundingRate': fundingRate,
3193
+ 'fundingTimestamp': undefined,
3194
+ 'fundingDatetime': undefined,
3195
+ 'nextFundingRate': undefined,
3196
+ 'nextFundingTimestamp': this.parse8601 (nextFundingDatetime),
3197
+ 'nextFundingDatetime': nextFundingDatetime,
3198
+ 'previousFundingRate': this.safeString (contract, 'lastFundingRate'),
3199
+ 'previousFundingTimestamp': undefined,
3200
+ 'previousFundingDatetime': undefined,
3201
+ };
3202
+ }
3203
+
3204
+ async fetchFundingRates (symbols, params = {}) {
3205
+ await this.loadMarkets ();
3206
+ const response = await this.contractV2PublicGetPremiumIndex (params);
3207
+ //
3208
+ // {
3209
+ // "code": 10000,
3210
+ // "data": [
3211
+ // {
3212
+ // "symbol": "BTC_USDT",
3213
+ // "markPrice": "43254.42",
3214
+ // "indexPrice": "43278.61",
3215
+ // "lastFundingRate": "0.0001",
3216
+ // "nextFundingTime": "1646121600000"
3217
+ // },
3218
+ // ],
3219
+ // "desc":"操作成功"
3220
+ // }
3221
+ //
3222
+ const data = this.safeValue (response, 'data', []);
3223
+ const result = this.parseFundingRates (data);
3224
+ return this.filterByArray (result, 'symbol', symbols);
3225
+ }
3226
+
3227
+ async withdraw (code, amount, address, tag = undefined, params = {}) {
3228
+ [ tag, params ] = this.handleWithdrawTagAndParams (tag, params);
3229
+ const password = this.safeString (params, 'safePwd', this.password);
3230
+ if (password === undefined) {
3231
+ throw new ArgumentsRequired (this.id + ' withdraw() requires exchange.password or a safePwd parameter');
3232
+ }
3233
+ const fees = this.safeNumber (params, 'fees');
3234
+ if (fees === undefined) {
3235
+ throw new ArgumentsRequired (this.id + ' withdraw() requires a fees parameter');
3236
+ }
3237
+ this.checkAddress (address);
3238
+ await this.loadMarkets ();
3239
+ const currency = this.currency (code);
3240
+ if (tag !== undefined) {
3241
+ address += '_' + tag;
3242
+ }
3243
+ const request = {
3244
+ 'amount': this.currencyToPrecision (code, amount),
3245
+ 'currency': currency['id'],
3246
+ 'fees': this.currencyToPrecision (code, fees),
3247
+ // 'itransfer': 0, // agree for an internal transfer, 0 disagree, 1 agree, the default is to disagree
3248
+ 'method': 'withdraw',
3249
+ 'receiveAddr': address,
3250
+ 'safePwd': password,
3251
+ };
3252
+ const response = await this.spotV1PrivateGetWithdraw (this.extend (request, params));
3253
+ //
3254
+ // {
3255
+ // "code": 1000,
3256
+ // "message": "success",
3257
+ // "id": "withdrawalId"
3258
+ // }
3259
+ //
3260
+ const transaction = this.parseTransaction (response, currency);
3261
+ return this.extend (transaction, {
3262
+ 'type': 'withdrawal',
3263
+ 'address': address,
3264
+ 'addressTo': address,
3265
+ 'amount': amount,
3266
+ });
3267
+ }
3268
+
3269
+ async fetchWithdrawals (code = undefined, since = undefined, limit = undefined, params = {}) {
3270
+ await this.loadMarkets ();
3271
+ const request = {
3272
+ // 'currency': currency['id'],
3273
+ // 'pageIndex': 1,
3274
+ // 'pageSize': limit,
3275
+ };
3276
+ let currency = undefined;
3277
+ if (code !== undefined) {
3278
+ currency = this.currency (code);
3279
+ request['currency'] = currency['id'];
3280
+ }
3281
+ if (limit !== undefined) {
3282
+ request['pageSize'] = limit;
3283
+ }
3284
+ const response = await this.spotV1PrivateGetGetWithdrawRecord (this.extend (request, params));
3285
+ //
3286
+ // {
3287
+ // "code": 1000,
3288
+ // "message": {
3289
+ // "des": "success",
3290
+ // "isSuc": true,
3291
+ // "datas": {
3292
+ // "list": [
3293
+ // {
3294
+ // "amount": 0.01,
3295
+ // "fees": 0.001,
3296
+ // "id": 2016042556231,
3297
+ // "manageTime": 1461579340000,
3298
+ // "status": 3,
3299
+ // "submitTime": 1461579288000,
3300
+ // "toAddress": "14fxEPirL9fyfw1i9EF439Pq6gQ5xijUmp",
3301
+ // },
3302
+ // ],
3303
+ // "pageIndex": 1,
3304
+ // "pageSize": 10,
3305
+ // "totalCount": 4,
3306
+ // "totalPage": 1
3307
+ // }
3308
+ // }
3309
+ // }
3310
+ //
3311
+ const message = this.safeValue (response, 'message', {});
3312
+ const datas = this.safeValue (message, 'datas', {});
3313
+ const withdrawals = this.safeValue (datas, 'list', []);
3314
+ return this.parseTransactions (withdrawals, currency, since, limit);
3315
+ }
3316
+
3317
+ async fetchDeposits (code = undefined, since = undefined, limit = undefined, params = {}) {
3318
+ await this.loadMarkets ();
3319
+ const request = {
3320
+ // 'currency': currency['id'],
3321
+ // 'pageIndex': 1,
3322
+ // 'pageSize': limit,
3323
+ };
3324
+ let currency = undefined;
3325
+ if (code !== undefined) {
3326
+ currency = this.currency (code);
3327
+ request['currency'] = currency['id'];
3328
+ }
3329
+ if (limit !== undefined) {
3330
+ request['pageSize'] = limit;
3331
+ }
3332
+ const response = await this.spotV1PrivateGetGetChargeRecord (this.extend (request, params));
3333
+ //
3334
+ // {
3335
+ // "code": 1000,
3336
+ // "message": {
3337
+ // "des": "success",
3338
+ // "isSuc": true,
3339
+ // "datas": {
3340
+ // "list": [
3341
+ // {
3342
+ // "address": "1FKN1DZqCm8HaTujDioRL2Aezdh7Qj7xxx",
3343
+ // "amount": "1.00000000",
3344
+ // "confirmTimes": 1,
3345
+ // "currency": "BTC",
3346
+ // "description": "Successfully Confirm",
3347
+ // "hash": "7ce842de187c379abafadd64a5fe66c5c61c8a21fb04edff9532234a1dae6xxx",
3348
+ // "id": 558,
3349
+ // "itransfer": 1,
3350
+ // "status": 2,
3351
+ // "submit_time": "2016-12-07 18:51:57",
3352
+ // },
3353
+ // ],
3354
+ // "pageIndex": 1,
3355
+ // "pageSize": 10,
3356
+ // "total": 8
3357
+ // }
3358
+ // }
3359
+ // }
3360
+ //
3361
+ const message = this.safeValue (response, 'message', {});
3362
+ const datas = this.safeValue (message, 'datas', {});
3363
+ const deposits = this.safeValue (datas, 'list', []);
3364
+ return this.parseTransactions (deposits, currency, since, limit);
3365
+ }
3366
+
3367
+ async fetchPosition (symbol, params = {}) {
3368
+ await this.loadMarkets ();
3369
+ let market = undefined;
3370
+ if (symbol !== undefined) {
3371
+ market = this.market (symbol);
3372
+ }
3373
+ const request = {
3374
+ 'futuresAccountType': 1, // 1: USDT-M Perpetual Futures
3375
+ // 'symbol': market['id'],
3376
+ // 'marketId': market['id'],
3377
+ // 'side': params['side'],
3378
+ };
3379
+ const response = await this.contractV2PrivateGetPositionsGetPositions (this.extend (request, params));
3380
+ //
3381
+ // {
3382
+ // "code": 10000,
3383
+ // "data": [
3384
+ // {
3385
+ // "amount": "0.002",
3386
+ // "appendAmount": "0",
3387
+ // "autoLightenRatio": "0",
3388
+ // "avgPrice": "38570",
3389
+ // "bankruptcyPrice": "46288.41",
3390
+ // "contractType": 1,
3391
+ // "createTime": "1645784751867",
3392
+ // "freezeAmount": "0",
3393
+ // "freezeList": [
3394
+ // {
3395
+ // "amount": "15.436832",
3396
+ // "currencyId": "6",
3397
+ // "currencyName": "usdt",
3398
+ // "modifyTime": "1645784751867"
3399
+ // }
3400
+ // ],
3401
+ // "id": "6902921567894972486",
3402
+ // "lastAppendAmount": "0",
3403
+ // "leverage": 5,
3404
+ // "liquidateLevel": 1,
3405
+ // "liquidatePrice": "46104",
3406
+ // "maintainMargin": "0.30912384",
3407
+ // "margin": "15.436832",
3408
+ // "marginAppendCount": 0,
3409
+ // "marginBalance": "15.295872",
3410
+ // "marginMode": 1,
3411
+ // "marginRate": "0.020209",
3412
+ // "marketId": "100",
3413
+ // "marketName": "BTC_USDT",
3414
+ // "modifyTime": "1645784751867",
3415
+ // "nominalValue": "77.14736",
3416
+ // "originAppendAmount": "0",
3417
+ // "originId": "6902921567894972591",
3418
+ // "refreshType": "Timer",
3419
+ // "returnRate": "-0.0091",
3420
+ // "side": 0,
3421
+ // "status": 1,
3422
+ // "unrealizedPnl": "-0.14096",
3423
+ // "userId": "6896693805014120448"
3424
+ // }
3425
+ // ],
3426
+ // "desc": "操作成功"
3427
+ // }
3428
+ //
3429
+ const data = this.safeValue (response, 'data', []);
3430
+ const firstPosition = this.safeValue (data, 0);
3431
+ return this.parsePosition (firstPosition, market);
3432
+ }
3433
+
3434
+ async fetchPositions (symbols = undefined, params = {}) {
3435
+ await this.loadMarkets ();
3436
+ let market = undefined;
3437
+ if (symbols !== undefined) {
3438
+ market = this.market (symbols);
3439
+ }
3440
+ const request = {
3441
+ 'futuresAccountType': 1, // 1: USDT-M Perpetual Futures
3442
+ // 'symbol': market['id'],
3443
+ // 'marketId': market['id'],
3444
+ // 'side': params['side'],
3445
+ };
3446
+ const response = await this.contractV2PrivateGetPositionsGetPositions (this.extend (request, params));
3447
+ //
3448
+ // {
3449
+ // "code": 10000,
3450
+ // "data": [
3451
+ // {
3452
+ // "amount": "0.002",
3453
+ // "appendAmount": "0",
3454
+ // "autoLightenRatio": "0",
3455
+ // "avgPrice": "38570",
3456
+ // "bankruptcyPrice": "46288.41",
3457
+ // "contractType": 1,
3458
+ // "createTime": "1645784751867",
3459
+ // "freezeAmount": "0",
3460
+ // "freezeList": [
3461
+ // {
3462
+ // "amount": "15.436832",
3463
+ // "currencyId": "6",
3464
+ // "currencyName": "usdt",
3465
+ // "modifyTime": "1645784751867"
3466
+ // }
3467
+ // ],
3468
+ // "id": "6902921567894972486",
3469
+ // "lastAppendAmount": "0",
3470
+ // "leverage": 5,
3471
+ // "liquidateLevel": 1,
3472
+ // "liquidatePrice": "46104",
3473
+ // "maintainMargin": "0.30912384",
3474
+ // "margin": "15.436832",
3475
+ // "marginAppendCount": 0,
3476
+ // "marginBalance": "15.295872",
3477
+ // "marginMode": 1,
3478
+ // "marginRate": "0.020209",
3479
+ // "marketId": "100",
3480
+ // "marketName": "BTC_USDT",
3481
+ // "modifyTime": "1645784751867",
3482
+ // "nominalValue": "77.14736",
3483
+ // "originAppendAmount": "0",
3484
+ // "originId": "6902921567894972591",
3485
+ // "refreshType": "Timer",
3486
+ // "returnRate": "-0.0091",
3487
+ // "side": 0,
3488
+ // "status": 1,
3489
+ // "unrealizedPnl": "-0.14096",
3490
+ // "userId": "6896693805014120448"
3491
+ // },
3492
+ // ],
3493
+ // "desc": "操作成功"
3494
+ // }
3495
+ //
3496
+ const data = this.safeValue (response, 'data', []);
3497
+ return this.parsePositions (data, market);
3498
+ }
3499
+
3500
+ parsePosition (position, market = undefined) {
3501
+ //
3502
+ // {
3503
+ // "amount": "0.002",
3504
+ // "appendAmount": "0",
3505
+ // "autoLightenRatio": "0",
3506
+ // "avgPrice": "38570",
3507
+ // "bankruptcyPrice": "46288.41",
3508
+ // "contractType": 1,
3509
+ // "createTime": "1645784751867",
3510
+ // "freezeAmount": "0",
3511
+ // "freezeList": [
3512
+ // {
3513
+ // "amount": "15.436832",
3514
+ // "currencyId": "6",
3515
+ // "currencyName": "usdt",
3516
+ // "modifyTime": "1645784751867"
3517
+ // }
3518
+ // ],
3519
+ // "id": "6902921567894972486",
3520
+ // "lastAppendAmount": "0",
3521
+ // "leverage": 5,
3522
+ // "liquidateLevel": 1,
3523
+ // "liquidatePrice": "46104",
3524
+ // "maintainMargin": "0.30912384",
3525
+ // "margin": "15.436832",
3526
+ // "marginAppendCount": 0,
3527
+ // "marginBalance": "15.295872",
3528
+ // "marginMode": 1,
3529
+ // "marginRate": "0.020209",
3530
+ // "marketId": "100",
3531
+ // "marketName": "BTC_USDT",
3532
+ // "modifyTime": "1645784751867",
3533
+ // "nominalValue": "77.14736",
3534
+ // "originAppendAmount": "0",
3535
+ // "originId": "6902921567894972591",
3536
+ // "refreshType": "Timer",
3537
+ // "returnRate": "-0.0091",
3538
+ // "side": 0,
3539
+ // "status": 1,
3540
+ // "unrealizedPnl": "-0.14096",
3541
+ // "userId": "6896693805014120448"
3542
+ // }
3543
+ //
3544
+ market = this.safeMarket (this.safeString (position, 'marketName'), market);
3545
+ const symbol = market['symbol'];
3546
+ const contracts = this.safeString (position, 'amount');
3547
+ const entryPrice = this.safeNumber (position, 'avgPrice');
3548
+ const initialMargin = this.safeString (position, 'margin');
3549
+ const rawSide = this.safeString (position, 'side');
3550
+ const side = (rawSide === '1') ? 'long' : 'short';
3551
+ const openType = this.safeString (position, 'marginMode');
3552
+ const marginType = (openType === '1') ? 'isolated' : 'cross';
3553
+ const leverage = this.safeString (position, 'leverage');
3554
+ const liquidationPrice = this.safeNumber (position, 'liquidatePrice');
3555
+ const unrealizedProfit = this.safeNumber (position, 'unrealizedPnl');
3556
+ const maintenanceMargin = this.safeNumber (position, 'maintainMargin');
3557
+ const marginRatio = this.safeNumber (position, 'marginRate');
3558
+ const notional = this.safeNumber (position, 'nominalValue');
3559
+ const percentage = Precise.stringMul (this.safeString (position, 'returnRate'), '100');
3560
+ const timestamp = this.safeNumber (position, 'createTime');
3561
+ return {
3562
+ 'info': position,
3563
+ 'symbol': symbol,
3564
+ 'contracts': this.parseNumber (contracts),
3565
+ 'contractSize': undefined,
3566
+ 'entryPrice': entryPrice,
3567
+ 'collateral': undefined,
3568
+ 'side': side,
3569
+ 'unrealizedProfit': unrealizedProfit,
3570
+ 'leverage': this.parseNumber (leverage),
3571
+ 'percentage': percentage,
3572
+ 'marginType': marginType,
3573
+ 'notional': notional,
3574
+ 'markPrice': undefined,
3575
+ 'liquidationPrice': liquidationPrice,
3576
+ 'initialMargin': this.parseNumber (initialMargin),
3577
+ 'initialMarginPercentage': undefined,
3578
+ 'maintenanceMargin': maintenanceMargin,
3579
+ 'maintenanceMarginPercentage': undefined,
3580
+ 'marginRatio': marginRatio,
3581
+ 'timestamp': timestamp,
3582
+ 'datetime': this.iso8601 (timestamp),
3583
+ };
3584
+ }
3585
+
3586
+ parsePositions (positions) {
3587
+ const result = [];
3588
+ for (let i = 0; i < positions.length; i++) {
3589
+ result.push (this.parsePosition (positions[i]));
3590
+ }
3591
+ return result;
3592
+ }
3593
+
3594
+ parseLedgerEntryType (type) {
3595
+ const types = {
3596
+ '1': 'realized pnl',
3597
+ '2': 'commission',
3598
+ '3': 'funding fee subtract',
3599
+ '4': 'funding fee addition',
3600
+ '5': 'insurance clear',
3601
+ '6': 'transfer in',
3602
+ '7': 'transfer out',
3603
+ '8': 'margin addition',
3604
+ '9': 'margin subtraction',
3605
+ '10': 'commission addition',
3606
+ '11': 'bill type freeze',
3607
+ '12': 'bill type unfreeze',
3608
+ '13': 'system take over margin',
3609
+ '14': 'transfer',
3610
+ '15': 'realized pnl collection',
3611
+ '16': 'funding fee collection',
3612
+ '17': 'recommender return commission',
3613
+ '18': 'by level subtract positions',
3614
+ '19': 'system add',
3615
+ '20': 'system subtract',
3616
+ '23': 'trading competition take over fund',
3617
+ '24': 'trading contest tickets',
3618
+ '25': 'return of trading contest tickets',
3619
+ '26': 'experience expired recall',
3620
+ '50': 'test register gift',
3621
+ '51': 'register gift',
3622
+ '52': 'deposit gift',
3623
+ '53': 'trading volume gift',
3624
+ '54': 'awards gift',
3625
+ '55': 'trading volume gift',
3626
+ '56': 'awards gift expire',
3627
+ '201': 'open positions',
3628
+ '202': 'close positions',
3629
+ '203': 'take over positions',
3630
+ '204': 'trading competition take over positions',
3631
+ '205': 'one way open long',
3632
+ '206': 'one way open short',
3633
+ '207': 'one way close long',
3634
+ '208': 'one way close short',
3635
+ '301': 'coupon deduction service charge',
3636
+ '302': 'experience deduction',
3637
+ '303': 'experience expired',
3638
+ };
3639
+ return this.safeString (types, type, type);
3640
+ }
3641
+
3642
+ parseLedgerEntry (item, currency = undefined) {
3643
+ //
3644
+ // [
3645
+ // {
3646
+ // "type": 3,
3647
+ // "changeAmount": "0.00434664",
3648
+ // "isIn": 0,
3649
+ // "beforeAmount": "30.53353135",
3650
+ // "beforeFreezeAmount": "21.547",
3651
+ // "createTime": "1646121604997",
3652
+ // "available": "30.52918471",
3653
+ // "unit": "usdt",
3654
+ // "symbol": "BTC_USDT"
3655
+ // },
3656
+ // ],
3657
+ //
3658
+ const timestamp = this.safeString (item, 'createTime');
3659
+ let direction = undefined;
3660
+ const changeDirection = this.safeNumber (item, 'isIn');
3661
+ if (changeDirection === 1) {
3662
+ direction = 'increase';
3663
+ } else {
3664
+ direction = 'reduce';
3665
+ }
3666
+ let fee = undefined;
3667
+ const feeCost = this.safeNumber (item, 'fee');
3668
+ if (feeCost !== undefined) {
3669
+ fee = {
3670
+ 'cost': feeCost,
3671
+ 'currency': this.safeCurrencyCode (this.safeString (item, 'unit')),
3672
+ };
3673
+ }
3674
+ return {
3675
+ 'id': this.safeString (item, 'id'),
3676
+ 'info': item,
3677
+ 'timestamp': timestamp,
3678
+ 'datetime': this.iso8601 (timestamp),
3679
+ 'direction': direction,
3680
+ 'account': this.safeString (item, 'userId'),
3681
+ 'referenceId': undefined,
3682
+ 'referenceAccount': undefined,
3683
+ 'type': this.parseLedgerEntryType (this.safeInteger (item, 'type')),
3684
+ 'currency': this.safeCurrencyCode (this.safeString (item, 'unit')),
3685
+ 'amount': this.safeNumber (item, 'changeAmount'),
3686
+ 'before': this.safeNumber (item, 'beforeAmount'),
3687
+ 'after': this.safeNumber (item, 'available'),
3688
+ 'status': undefined,
3689
+ 'fee': fee,
3690
+ };
3691
+ }
3692
+
3693
+ async fetchLedger (code = undefined, since = undefined, limit = undefined, params = {}) {
3694
+ if (code === undefined) {
3695
+ throw new ArgumentsRequired (this.id + ' fetchLedger() requires a code argument');
3696
+ }
3697
+ await this.loadMarkets ();
3698
+ const currency = this.currency (code);
3699
+ const request = {
3700
+ 'futuresAccountType': 1,
3701
+ // 'currencyId': '11',
3702
+ // 'type': 1,
3703
+ // 'endTime': this.milliseconds (),
3704
+ // 'pageNum': 1,
3705
+ };
3706
+ if (code !== undefined) {
3707
+ request['currencyName'] = currency['id'];
3708
+ }
3709
+ if (since !== undefined) {
3710
+ request['startTime'] = since;
3711
+ }
3712
+ if (limit !== undefined) {
3713
+ request['pageSize'] = limit;
3714
+ }
3715
+ const response = await this.contractV2PrivateGetFundGetBill (this.extend (request, params));
3716
+ //
3717
+ // {
3718
+ // "code": 10000,
3719
+ // "data": {
3720
+ // "list": [
3721
+ // {
3722
+ // "type": 3,
3723
+ // "changeAmount": "0.00434664",
3724
+ // "isIn": 0,
3725
+ // "beforeAmount": "30.53353135",
3726
+ // "beforeFreezeAmount": "21.547",
3727
+ // "createTime": "1646121604997",
3728
+ // "available": "30.52918471",
3729
+ // "unit": "usdt",
3730
+ // "symbol": "BTC_USDT"
3731
+ // },
3732
+ // ],
3733
+ // "pageNum": 1,
3734
+ // "pageSize": 10
3735
+ // },
3736
+ // "desc": "操作成功"
3737
+ // }
3738
+ //
3739
+ const data = this.safeValue (response, 'data', {});
3740
+ const list = this.safeValue (data, 'list', []);
3741
+ return this.parseLedger (list, currency, since, limit);
3742
+ }
3743
+
3744
+ async transfer (code, amount, fromAccount, toAccount, params = {}) {
3745
+ await this.loadMarkets ();
3746
+ const [ marketType, query ] = this.handleMarketTypeAndParams ('transfer', undefined, params);
3747
+ const currency = this.currency (code);
3748
+ const margin = (marketType === 'margin');
3749
+ const swap = (marketType === 'swap');
3750
+ let side = undefined;
3751
+ let marginMethod = undefined;
3752
+ const amountToPrecision = this.currencyToPrecision (code, amount);
3753
+ const request = {
3754
+ 'amount': amountToPrecision, // Swap, Cross Margin, Isolated Margin
3755
+ // 'coin': currency['id'], // Margin
3756
+ // 'currencyName': currency['id'], // Swap
3757
+ // 'clientId': this.safeString (params, 'clientId'), // Swap "2sdfsdfsdf232342"
3758
+ // 'side': side, // Swap, 1:Deposit (zb account -> futures account),0:Withdrawal (futures account -> zb account)
3759
+ // 'marketName': this.safeString (params, 'marketName'), // Isolated Margin
3760
+ };
3761
+ if (swap) {
3762
+ if (fromAccount === 'spot' || toAccount === 'future') {
3763
+ side = 1;
3764
+ } else {
3765
+ side = 0;
3766
+ }
3767
+ request['currencyName'] = currency['id'];
3768
+ request['clientId'] = this.safeString (params, 'clientId');
3769
+ request['side'] = side;
3770
+ } else {
3771
+ const defaultMargin = margin ? 'isolated' : 'cross';
3772
+ const marginType = this.safeString2 (this.options, 'defaultMarginType', 'marginType', defaultMargin);
3773
+ if (marginType === 'isolated') {
3774
+ if (fromAccount === 'spot' || toAccount === 'isolated') {
3775
+ marginMethod = 'spotV1PrivateGetTransferInLever';
3776
+ } else {
3777
+ marginMethod = 'spotV1PrivateGetTransferOutLever';
3778
+ }
3779
+ request['marketName'] = this.safeString (params, 'marketName');
3780
+ } else if (marginType === 'cross') {
3781
+ if (fromAccount === 'spot' || toAccount === 'cross') {
3782
+ marginMethod = 'spotV1PrivateGetTransferInCross';
3783
+ } else {
3784
+ marginMethod = 'spotV1PrivateGetTransferOutCross';
3785
+ }
3786
+ }
3787
+ request['coin'] = currency['id'];
3788
+ }
3789
+ const method = this.getSupportedMapping (marketType, {
3790
+ 'swap': 'contractV2PrivatePostFundTransferFund',
3791
+ 'margin': marginMethod,
3792
+ });
3793
+ const response = await this[method] (this.extend (request, query));
3794
+ //
3795
+ // Swap
3796
+ //
3797
+ // {
3798
+ // "code": 10000,
3799
+ // "data": "2sdfsdfsdf232342",
3800
+ // "desc": "Success"
3801
+ // }
3802
+ //
3803
+ // Margin
3804
+ //
3805
+ // {
3806
+ // "code": 1000,
3807
+ // "message": "Success"
3808
+ // }
3809
+ //
3810
+ return this.extend (this.parseTransfer (response, currency), {
3811
+ 'amount': this.parseNumber (amountToPrecision),
3812
+ 'fromAccount': fromAccount,
3813
+ 'toAccount': toAccount,
3814
+ });
3815
+ }
3816
+
3817
+ parseTransfer (transfer, currency = undefined) {
3818
+ // response samples in 'transfer'
3819
+ const timestamp = this.milliseconds ();
3820
+ return {
3821
+ 'id': this.safeString (transfer, 'data'),
3822
+ 'timestamp': timestamp,
3823
+ 'datetime': this.iso8601 (timestamp),
3824
+ 'currency': this.safeCurrencyCode (undefined, 'currency'),
3825
+ 'amount': undefined,
3826
+ 'fromAccount': undefined,
3827
+ 'toAccount': undefined,
3828
+ 'status': undefined,
3829
+ };
3830
+ }
3831
+
3832
+ async modifyMarginHelper (symbol, amount, type, params = {}) {
3833
+ if (params['positionsId'] === undefined) {
3834
+ throw new ArgumentsRequired (this.id + ' modifyMarginHelper() requires a positionsId argument in the params');
3835
+ }
3836
+ await this.loadMarkets ();
3837
+ const market = this.market (symbol);
3838
+ amount = this.amountToPrecision (symbol, amount);
3839
+ const position = this.safeString (params, 'positionsId');
3840
+ const request = {
3841
+ 'positionsId': position,
3842
+ 'amount': amount,
3843
+ 'type': type, // 1 increase, 0 reduce
3844
+ 'futuresAccountType': 1, // 1: USDT Perpetual Futures
3845
+ };
3846
+ const response = await this.contractV2PrivatePostPositionsUpdateMargin (this.extend (request, params));
3847
+ //
3848
+ // {
3849
+ // "code": 10000,
3850
+ // "data": {
3851
+ // "amount": "0.002",
3852
+ // "appendAmount": "0",
3853
+ // "avgPrice": "43927.23",
3854
+ // "bankruptcyPrice": "41730.86",
3855
+ // "createTime": "1646208695609",
3856
+ // "freezeAmount": "0",
3857
+ // "id": "6900781818669377576",
3858
+ // "keyMark": "6896693805014120448-100-1-",
3859
+ // "lastAppendAmount": "0",
3860
+ // "lastTime": "1646209235505",
3861
+ // "leverage": 20,
3862
+ // "liquidateLevel": 1,
3863
+ // "liquidatePrice": "41898.46",
3864
+ // "maintainMargin": "0",
3865
+ // "margin": "4.392723",
3866
+ // "marginAppendCount": 0,
3867
+ // "marginBalance": "0",
3868
+ // "marginMode": 1,
3869
+ // "marginRate": "0",
3870
+ // "marketId": "100",
3871
+ // "marketName": "BTC_USDT",
3872
+ // "modifyTime": "1646209235505",
3873
+ // "nominalValue": "87.88828",
3874
+ // "originAppendAmount": "0",
3875
+ // "originId": "6904699716827818029",
3876
+ // "positionsMode": 2,
3877
+ // "sellerCurrencyId": "1",
3878
+ // "side": 1,
3879
+ // "status": 1,
3880
+ // "unrealizedPnl": "0.03382",
3881
+ // "usable": true,
3882
+ // "userId": "6896693805014120448"
3883
+ // },
3884
+ // "desc":"操作成功"
3885
+ // }
3886
+ //
3887
+ return this.extend (this.parseModifyMargin (response, market), {
3888
+ 'amount': this.parseNumber (amount),
3889
+ });
3890
+ }
3891
+
3892
+ parseModifyMargin (data, market = undefined) {
3893
+ const innerData = this.safeValue (data, 'data', {});
3894
+ const sideRaw = this.safeInteger (innerData, 'side');
3895
+ const side = (sideRaw === 1) ? 'add' : 'reduce';
3896
+ const statusCode = this.safeInteger (innerData, 'status');
3897
+ const status = (statusCode === 1) ? 'ok' : 'failed';
3898
+ return {
3899
+ 'info': data,
3900
+ 'type': side,
3901
+ 'amount': undefined,
3902
+ 'code': market['quote'],
3903
+ 'symbol': market['symbol'],
3904
+ 'status': status,
3905
+ };
3906
+ }
3907
+
3908
+ async addMargin (symbol, amount, params = {}) {
3909
+ if (params['positionsId'] === undefined) {
3910
+ throw new ArgumentsRequired (this.id + ' addMargin() requires a positionsId argument in the params');
3911
+ }
3912
+ return await this.modifyMarginHelper (symbol, amount, 1, params);
3913
+ }
3914
+
3915
+ async reduceMargin (symbol, amount, params = {}) {
3916
+ if (params['positionsId'] === undefined) {
3917
+ throw new ArgumentsRequired (this.id + ' reduceMargin() requires a positionsId argument in the params');
3918
+ }
3919
+ return await this.modifyMarginHelper (symbol, amount, 0, params);
3920
+ }
3921
+
3922
+ async fetchBorrowRate (code, params = {}) {
3923
+ await this.loadMarkets ();
3924
+ const currency = this.currency (code);
3925
+ const request = {
3926
+ 'coin': currency['id'],
3927
+ };
3928
+ const response = await this.spotV1PrivateGetGetLoans (this.extend (request, params));
3929
+ //
3930
+ // {
3931
+ // code: '1000',
3932
+ // message: '操作成功',
3933
+ // result: [
3934
+ // {
3935
+ // interestRateOfDay: '0.0005',
3936
+ // repaymentDay: '30',
3937
+ // amount: '148804.4841',
3938
+ // balance: '148804.4841',
3939
+ // rateOfDayShow: '0.05 %',
3940
+ // coinName: 'USDT',
3941
+ // lowestAmount: '0.01'
3942
+ // },
3943
+ // ]
3944
+ // }
3945
+ //
3946
+ const timestamp = this.milliseconds ();
3947
+ const data = this.safeValue (response, 'result', []);
3948
+ const rate = this.safeValue (data, 0, {});
3949
+ return {
3950
+ 'currency': this.safeCurrencyCode (this.safeString (rate, 'coinName')),
3951
+ 'rate': this.safeNumber (rate, 'interestRateOfDay'),
3952
+ 'period': this.safeNumber (rate, 'repaymentDay'),
3953
+ 'timestamp': timestamp,
3954
+ 'datetime': this.iso8601 (timestamp),
3955
+ 'info': rate,
3956
+ };
3957
+ }
3958
+
3959
+ async fetchBorrowRates (params = {}) {
3960
+ if (params['coin'] === undefined) {
3961
+ throw new ArgumentsRequired (this.id + ' fetchBorrowRates() requires a coin argument in the params');
3962
+ }
3963
+ await this.loadMarkets ();
3964
+ const currency = this.currency (this.safeString (params, 'coin'));
3965
+ const request = {
3966
+ 'coin': currency['id'],
3967
+ };
3968
+ const response = await this.spotV1PrivateGetGetLoans (this.extend (request, params));
3969
+ //
3970
+ // {
3971
+ // code: '1000',
3972
+ // message: '操作成功',
3973
+ // result: [
3974
+ // {
3975
+ // interestRateOfDay: '0.0005',
3976
+ // repaymentDay: '30',
3977
+ // amount: '148804.4841',
3978
+ // balance: '148804.4841',
3979
+ // rateOfDayShow: '0.05 %',
3980
+ // coinName: 'USDT',
3981
+ // lowestAmount: '0.01'
3982
+ // },
3983
+ // ]
3984
+ // }
3985
+ //
3986
+ const timestamp = this.milliseconds ();
3987
+ const data = this.safeValue (response, 'result');
3988
+ const rates = [];
3989
+ for (let i = 0; i < data.length; i++) {
3990
+ const entry = data[i];
3991
+ rates.push ({
3992
+ 'currency': this.safeCurrencyCode (this.safeString (entry, 'coinName')),
3993
+ 'rate': this.safeNumber (entry, 'interestRateOfDay'),
3994
+ 'period': this.safeNumber (entry, 'repaymentDay'),
3995
+ 'timestamp': timestamp,
3996
+ 'datetime': this.iso8601 (timestamp),
3997
+ 'info': entry,
3998
+ });
3999
+ }
4000
+ return rates;
4001
+ }
4002
+
4003
+ nonce () {
4004
+ return this.milliseconds ();
4005
+ }
4006
+
4007
+ sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
4008
+ const [ section, version, access ] = api;
4009
+ let url = this.implodeHostname (this.urls['api'][section][version][access]);
4010
+ if (access === 'public') {
4011
+ if (path === 'getFeeInfo') {
4012
+ url = this.implodeHostname (this.urls['api'][section][version]['private']) + '/' + path;
4013
+ } else {
4014
+ url += '/' + version + '/' + path;
4015
+ }
4016
+ if (Object.keys (params).length) {
4017
+ url += '?' + this.urlencode (params);
4018
+ }
4019
+ } else if (section === 'contract') {
4020
+ const timestamp = this.milliseconds ();
4021
+ const iso8601 = this.iso8601 (timestamp);
4022
+ let signedString = iso8601 + method + '/Server/api/' + version + '/' + path;
4023
+ params = this.keysort (params);
4024
+ headers = {
4025
+ 'ZB-APIKEY': this.apiKey,
4026
+ 'ZB-TIMESTAMP': iso8601,
4027
+ // 'ZB-LAN': 'cn', // cn, en, kr
4028
+ };
4029
+ url += '/' + version + '/' + path;
4030
+ if (method === 'POST') {
4031
+ headers['Content-Type'] = 'application/json';
4032
+ body = this.json (params);
4033
+ signedString += this.urlencode (params);
4034
+ } else {
4035
+ if (Object.keys (params).length) {
4036
+ const query = this.urlencode (params);
4037
+ url += '?' + query;
4038
+ signedString += query;
4039
+ }
4040
+ }
4041
+ const secret = this.hash (this.encode (this.secret), 'sha1');
4042
+ const signature = this.hmac (this.encode (signedString), this.encode (secret), 'sha256', 'base64');
4043
+ headers['ZB-SIGN'] = signature;
4044
+ } else {
4045
+ let query = this.keysort (this.extend ({
4046
+ 'method': path,
4047
+ 'accesskey': this.apiKey,
4048
+ }, params));
4049
+ const nonce = this.nonce ();
4050
+ query = this.keysort (query);
4051
+ const auth = this.rawencode (query);
4052
+ const secret = this.hash (this.encode (this.secret), 'sha1');
4053
+ const signature = this.hmac (this.encode (auth), this.encode (secret), 'md5');
4054
+ const suffix = 'sign=' + signature + '&reqTime=' + nonce.toString ();
4055
+ url += '/' + path + '?' + auth + '&' + suffix;
4056
+ }
4057
+ return { 'url': url, 'method': method, 'body': body, 'headers': headers };
4058
+ }
4059
+
4060
+ handleErrors (httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody) {
4061
+ if (response === undefined) {
4062
+ return; // fallback to default error handler
4063
+ }
4064
+ if (body[0] === '{') {
4065
+ const feedback = this.id + ' ' + body;
4066
+ this.throwBroadlyMatchedException (this.exceptions['broad'], body, feedback);
4067
+ if ('code' in response) {
4068
+ const code = this.safeString (response, 'code');
4069
+ this.throwExactlyMatchedException (this.exceptions['exact'], code, feedback);
4070
+ if ((code !== '1000') && (code !== '10000')) {
4071
+ throw new ExchangeError (feedback);
4072
+ }
4073
+ }
4074
+ // special case for {"result":false,"message":"服务端忙碌"} (a "Busy Server" reply)
4075
+ const result = this.safeValue (response, 'result');
4076
+ if (result !== undefined) {
4077
+ if (!result) {
4078
+ const message = this.safeString (response, 'message');
4079
+ if (message === '服务端忙碌') {
4080
+ throw new ExchangeNotAvailable (feedback);
4081
+ } else {
4082
+ throw new ExchangeError (feedback);
4083
+ }
4084
+ }
4085
+ }
4086
+ }
4087
+ }
4088
+ };