ccxt 4.5.1__py2.py3-none-any.whl → 4.5.2__py2.py3-none-any.whl
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.
- ccxt/__init__.py +1 -5
- ccxt/ascendex.py +1 -1
- ccxt/async_support/__init__.py +1 -5
- ccxt/async_support/ascendex.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +17 -12
- ccxt/async_support/bitget.py +1 -1
- ccxt/async_support/indodax.py +11 -12
- ccxt/async_support/okx.py +2 -2
- ccxt/async_support/poloniex.py +1 -1
- ccxt/async_support/zonda.py +12 -0
- ccxt/base/exchange.py +1 -1
- ccxt/binance.py +17 -12
- ccxt/bitget.py +1 -1
- ccxt/indodax.py +11 -12
- ccxt/okx.py +2 -2
- ccxt/poloniex.py +1 -1
- ccxt/pro/__init__.py +1 -3
- ccxt/pro/bitget.py +151 -26
- ccxt/pro/bitmart.py +1 -1
- ccxt/pro/gemini.py +6 -2
- ccxt/pro/hyperliquid.py +4 -0
- ccxt/pro/kraken.py +3 -6
- ccxt/test/tests_async.py +2 -25
- ccxt/test/tests_sync.py +2 -25
- ccxt/zonda.py +12 -0
- {ccxt-4.5.1.dist-info → ccxt-4.5.2.dist-info}/METADATA +111 -113
- {ccxt-4.5.1.dist-info → ccxt-4.5.2.dist-info}/RECORD +31 -38
- ccxt/abstract/ellipx.py +0 -25
- ccxt/abstract/vertex.py +0 -19
- ccxt/async_support/ellipx.py +0 -2029
- ccxt/async_support/vertex.py +0 -3050
- ccxt/ellipx.py +0 -2029
- ccxt/pro/vertex.py +0 -948
- ccxt/vertex.py +0 -3050
- {ccxt-4.5.1.dist-info → ccxt-4.5.2.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.5.1.dist-info → ccxt-4.5.2.dist-info}/WHEEL +0 -0
- {ccxt-4.5.1.dist-info → ccxt-4.5.2.dist-info}/top_level.txt +0 -0
ccxt/ellipx.py
DELETED
@@ -1,2029 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
|
3
|
-
# PLEASE DO NOT EDIT THIS FILE, IT IS GENERATED AND WILL BE OVERWRITTEN:
|
4
|
-
# https://github.com/ccxt/ccxt/blob/master/CONTRIBUTING.md#how-to-contribute-code
|
5
|
-
|
6
|
-
from ccxt.base.exchange import Exchange
|
7
|
-
from ccxt.abstract.ellipx import ImplicitAPI
|
8
|
-
import math
|
9
|
-
from ccxt.base.types import Any, Balances, Currencies, DepositAddress, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Ticker, Trade, TradingFeeInterface, Transaction
|
10
|
-
from typing import List
|
11
|
-
from ccxt.base.errors import ExchangeError
|
12
|
-
from ccxt.base.errors import AuthenticationError
|
13
|
-
from ccxt.base.errors import PermissionDenied
|
14
|
-
from ccxt.base.errors import ArgumentsRequired
|
15
|
-
from ccxt.base.errors import BadRequest
|
16
|
-
from ccxt.base.errors import NotSupported
|
17
|
-
from ccxt.base.errors import DDoSProtection
|
18
|
-
from ccxt.base.decimal_to_precision import TICK_SIZE
|
19
|
-
from ccxt.base.precise import Precise
|
20
|
-
|
21
|
-
|
22
|
-
class ellipx(Exchange, ImplicitAPI):
|
23
|
-
|
24
|
-
def describe(self) -> Any:
|
25
|
-
return self.deep_extend(super(ellipx, self).describe(), {
|
26
|
-
'id': 'ellipx',
|
27
|
-
'name': 'Ellipx',
|
28
|
-
'countries': ['PL'],
|
29
|
-
'rateLimit': 200, # todo check
|
30
|
-
'version': 'v1',
|
31
|
-
'certified': False,
|
32
|
-
'pro': False,
|
33
|
-
'has': {
|
34
|
-
'CORS': None,
|
35
|
-
'spot': True,
|
36
|
-
'margin': False,
|
37
|
-
'swap': False,
|
38
|
-
'future': False,
|
39
|
-
'option': False,
|
40
|
-
'addMargin': False,
|
41
|
-
'borrowCrossMargin': False,
|
42
|
-
'borrowIsolatedMargin': False,
|
43
|
-
'borrowMargin': False,
|
44
|
-
'cancelAllOrders': False,
|
45
|
-
'cancelAllOrdersAfter': False,
|
46
|
-
'cancelOrder': True,
|
47
|
-
'cancelOrders': False,
|
48
|
-
'cancelWithdraw': False,
|
49
|
-
'closeAllPositions': False,
|
50
|
-
'closePosition': False,
|
51
|
-
'createConvertTrade': False,
|
52
|
-
'createDepositAddress': False,
|
53
|
-
'createMarketBuyOrderWithCost': False,
|
54
|
-
'createMarketOrder': False,
|
55
|
-
'createMarketOrderWithCost': False,
|
56
|
-
'createMarketSellOrderWithCost': False,
|
57
|
-
'createOrder': True,
|
58
|
-
'createOrderWithTakeProfitAndStopLoss': False,
|
59
|
-
'createOrderWithTakeProfitAndStopLossWs': False,
|
60
|
-
'createPostOnlyOrder': False,
|
61
|
-
'createReduceOnlyOrder': False,
|
62
|
-
'createStopLimitOrder': False,
|
63
|
-
'createStopLossOrder': False,
|
64
|
-
'createStopMarketOrder': False,
|
65
|
-
'createStopOrder': False,
|
66
|
-
'createTakeProfitOrder': False,
|
67
|
-
'createTrailingAmountOrder': False,
|
68
|
-
'createTrailingPercentOrder': False,
|
69
|
-
'createTriggerOrder': False,
|
70
|
-
'fetchAccounts': False,
|
71
|
-
'fetchBalance': True,
|
72
|
-
'fetchBorrowInterest': False,
|
73
|
-
'fetchBorrowRate': False,
|
74
|
-
'fetchBorrowRateHistories': False,
|
75
|
-
'fetchBorrowRateHistory': False,
|
76
|
-
'fetchBorrowRates': False,
|
77
|
-
'fetchBorrowRatesPerSymbol': False,
|
78
|
-
'fetchCanceledAndClosedOrders': False,
|
79
|
-
'fetchCanceledOrders': False,
|
80
|
-
'fetchClosedOrder': False,
|
81
|
-
'fetchClosedOrders': False,
|
82
|
-
'fetchConvertCurrencies': False,
|
83
|
-
'fetchConvertQuote': False,
|
84
|
-
'fetchConvertTrade': False,
|
85
|
-
'fetchConvertTradeHistory': False,
|
86
|
-
'fetchCrossBorrowRate': False,
|
87
|
-
'fetchCrossBorrowRates': False,
|
88
|
-
'fetchCurrencies': True,
|
89
|
-
'fetchDepositAddress': True,
|
90
|
-
'fetchDeposits': False,
|
91
|
-
'fetchDepositsWithdrawals': False,
|
92
|
-
'fetchFundingHistory': False,
|
93
|
-
'fetchFundingInterval': False,
|
94
|
-
'fetchFundingIntervals': False,
|
95
|
-
'fetchFundingRate': False,
|
96
|
-
'fetchFundingRateHistory': False,
|
97
|
-
'fetchFundingRates': False,
|
98
|
-
'fetchGreeks': False,
|
99
|
-
'fetchIndexOHLCV': False,
|
100
|
-
'fetchIsolatedBorrowRate': False,
|
101
|
-
'fetchIsolatedBorrowRates': False,
|
102
|
-
'fetchIsolatedPositions': False,
|
103
|
-
'fetchLedger': False,
|
104
|
-
'fetchLeverage': False,
|
105
|
-
'fetchLeverages': False,
|
106
|
-
'fetchLeverageTiers': False,
|
107
|
-
'fetchLiquidations': False,
|
108
|
-
'fetchLongShortRatio': False,
|
109
|
-
'fetchLongShortRatioHistory': False,
|
110
|
-
'fetchMarginAdjustmentHistory': False,
|
111
|
-
'fetchMarginMode': False,
|
112
|
-
'fetchMarginModes': False,
|
113
|
-
'fetchMarketLeverageTiers': False,
|
114
|
-
'fetchMarkets': True,
|
115
|
-
'fetchMarkOHLCV': False,
|
116
|
-
'fetchMarkPrices': False,
|
117
|
-
'fetchMyLiquidations': False,
|
118
|
-
'fetchMySettlementHistory': False,
|
119
|
-
'fetchMyTrades': False,
|
120
|
-
'fetchOHLCV': True,
|
121
|
-
'fetchOpenInterest': False,
|
122
|
-
'fetchOpenInterestHistory': False,
|
123
|
-
'fetchOpenInterests': False,
|
124
|
-
'fetchOpenOrder': False,
|
125
|
-
'fetchOpenOrders': True,
|
126
|
-
'fetchOption': False,
|
127
|
-
'fetchOptionChain': False,
|
128
|
-
'fetchOrder': True,
|
129
|
-
'fetchOrderBook': True,
|
130
|
-
'fetchOrders': True,
|
131
|
-
'fetchOrderTrades': True,
|
132
|
-
'fetchPosition': False,
|
133
|
-
'fetchPositionHistory': False,
|
134
|
-
'fetchPositionMode': False,
|
135
|
-
'fetchPositions': False,
|
136
|
-
'fetchPositionsForSymbol': False,
|
137
|
-
'fetchPositionsHistory': False,
|
138
|
-
'fetchPositionsRisk': False,
|
139
|
-
'fetchPremiumIndexOHLCV': False,
|
140
|
-
'fetchSettlementHistory': False,
|
141
|
-
'fetchStatus': False,
|
142
|
-
'fetchTicker': True,
|
143
|
-
'fetchTickers': False,
|
144
|
-
'fetchTime': False,
|
145
|
-
'fetchTrades': True,
|
146
|
-
'fetchTradingFee': True,
|
147
|
-
'fetchTradingFees': False,
|
148
|
-
'fetchTransactions': False,
|
149
|
-
'fetchTransfers': False,
|
150
|
-
'fetchVolatilityHistory': False,
|
151
|
-
'fetchWithdrawals': False,
|
152
|
-
'reduceMargin': False,
|
153
|
-
'repayCrossMargin': False,
|
154
|
-
'repayIsolatedMargin': False,
|
155
|
-
'repayMargin': False,
|
156
|
-
'sandbox': False,
|
157
|
-
'setLeverage': False,
|
158
|
-
'setMargin': False,
|
159
|
-
'setMarginMode': False,
|
160
|
-
'setPositionMode': False,
|
161
|
-
'transfer': False,
|
162
|
-
'withdraw': True,
|
163
|
-
},
|
164
|
-
'timeframes': {
|
165
|
-
'1m': '1m',
|
166
|
-
'5m': '5m',
|
167
|
-
'10m': '10m',
|
168
|
-
'1h': '1h',
|
169
|
-
'6h': '6h',
|
170
|
-
'12h': '12h',
|
171
|
-
'1d': '1d',
|
172
|
-
},
|
173
|
-
'urls': {
|
174
|
-
'logo': 'https://github.com/user-attachments/assets/e07c3f40-281c-4cdf-bacf-fa1c58218a2c',
|
175
|
-
'api': {
|
176
|
-
'public': 'https://data.ellipx.com',
|
177
|
-
'private': 'https://app.ellipx.com/_rest',
|
178
|
-
'_rest': 'https://app.ellipx.com/_rest',
|
179
|
-
},
|
180
|
-
'www': 'https://www.ellipx.com',
|
181
|
-
'doc': 'https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM',
|
182
|
-
'fees': 'https://www.ellipx.com/pages/pricing',
|
183
|
-
'referral': '', # todo
|
184
|
-
},
|
185
|
-
'api': {
|
186
|
-
'_rest': {
|
187
|
-
'get': {
|
188
|
-
'Market': 1,
|
189
|
-
'Market/{currencyPair}': 1,
|
190
|
-
'Crypto/Token/Info': 1,
|
191
|
-
},
|
192
|
-
},
|
193
|
-
'public': {
|
194
|
-
'get': {
|
195
|
-
'Market/{currencyPair}:getDepth': 1,
|
196
|
-
'Market/{currencyPair}:ticker': 1,
|
197
|
-
'Market/{currencyPair}:getTrades': 1,
|
198
|
-
'Market/{currencyPair}:getGraph': 1,
|
199
|
-
'CMC:summary': 1,
|
200
|
-
'CMC/{currencyPair}:ticker': 1,
|
201
|
-
},
|
202
|
-
},
|
203
|
-
'private': {
|
204
|
-
'get': {
|
205
|
-
'User/Wallet': 1,
|
206
|
-
'Market/{currencyPair}/Order': 1,
|
207
|
-
'Market/Order/{orderUuid}': 1,
|
208
|
-
'Market/{currencyPair}/Trade': 1,
|
209
|
-
'Market/TradeFee:query': 1,
|
210
|
-
'Unit/{currency}': 1,
|
211
|
-
'Crypto/Token/{currency}': 1,
|
212
|
-
'Crypto/Token/{currency}:chains': 1,
|
213
|
-
},
|
214
|
-
'post': {
|
215
|
-
'Market/{currencyPair}/Order': 1,
|
216
|
-
'Crypto/Address:fetch': 1,
|
217
|
-
'Crypto/Disbursement:withdraw': 1,
|
218
|
-
},
|
219
|
-
'delete': {
|
220
|
-
'Market/Order/{orderUuid}': 1,
|
221
|
-
},
|
222
|
-
},
|
223
|
-
},
|
224
|
-
'fees': {
|
225
|
-
'trading': {
|
226
|
-
'tierBased': True,
|
227
|
-
'feeSide': 'get',
|
228
|
-
'percentage': True,
|
229
|
-
'maker': self.parse_number('0.0025'), # default 25bps
|
230
|
-
'taker': self.parse_number('0.0030'), # default 30bps
|
231
|
-
'tiers': {
|
232
|
-
# volume in USDT
|
233
|
-
'maker': [
|
234
|
-
[self.parse_number('0'), self.parse_number('0.0025')], # 0-10k: 25bps
|
235
|
-
[self.parse_number('10000'), self.parse_number('0.0020')], # 10k-50k: 20bps
|
236
|
-
[self.parse_number('50000'), self.parse_number('0.0015')], # 50k-100k: 15bps
|
237
|
-
[self.parse_number('100000'), self.parse_number('0.0010')], # 100k-1M: 10bps
|
238
|
-
[self.parse_number('1000000'), self.parse_number('0.0008')], # 1M-5M: 8bps
|
239
|
-
[self.parse_number('5000000'), self.parse_number('0.0003')], # 5M-15M: 3bps
|
240
|
-
[self.parse_number('15000000'), self.parse_number('0.0000')], # 15M-75M: 0bps
|
241
|
-
[self.parse_number('75000000'), self.parse_number('0.0000')], # 75M-100M: 0bps
|
242
|
-
[self.parse_number('100000000'), self.parse_number('0.0000')], # 100M+: 0bps
|
243
|
-
],
|
244
|
-
'taker': [
|
245
|
-
[self.parse_number('0'), self.parse_number('0.0030')], # 0-10k: 30bps
|
246
|
-
[self.parse_number('10000'), self.parse_number('0.0025')], # 10k-50k: 25bps
|
247
|
-
[self.parse_number('50000'), self.parse_number('0.0020')], # 50k-100k: 20bps
|
248
|
-
[self.parse_number('100000'), self.parse_number('0.0015')], # 100k-1M: 15bps
|
249
|
-
[self.parse_number('1000000'), self.parse_number('0.0012')], # 1M-5M: 12bps
|
250
|
-
[self.parse_number('5000000'), self.parse_number('0.0010')], # 5M-15M: 10bps
|
251
|
-
[self.parse_number('15000000'), self.parse_number('0.0008')], # 15M-75M: 8bps
|
252
|
-
[self.parse_number('75000000'), self.parse_number('0.0005')], # 75M-100M: 5bps
|
253
|
-
[self.parse_number('100000000'), self.parse_number('0.0003')], # 100M+: 3bps
|
254
|
-
],
|
255
|
-
},
|
256
|
-
},
|
257
|
-
'stablecoin': {
|
258
|
-
'tierBased': False,
|
259
|
-
'percentage': True,
|
260
|
-
'maker': self.parse_number('0.0000'), # 0%
|
261
|
-
'taker': self.parse_number('0.000015'), # 0.0015%
|
262
|
-
},
|
263
|
-
},
|
264
|
-
'options': {
|
265
|
-
'defaultType': 'spot',
|
266
|
-
'recvWindow': 5 * 1000,
|
267
|
-
'broker': 'CCXT',
|
268
|
-
'networks': {
|
269
|
-
'Bitcoin': 'Bitcoin',
|
270
|
-
'Ethereum': 'ERC20',
|
271
|
-
},
|
272
|
-
'defaultNetwork': 'defaultNetwork',
|
273
|
-
'defaultNetworkCodeReplacements': {
|
274
|
-
'BTC': 'Bitcoin',
|
275
|
-
'ETH': 'Ethereum',
|
276
|
-
},
|
277
|
-
},
|
278
|
-
'features': {
|
279
|
-
'spot': {
|
280
|
-
'sandbox': False,
|
281
|
-
'createOrder': {
|
282
|
-
'marginMode': False,
|
283
|
-
'triggerPrice': False,
|
284
|
-
'triggerPriceType': None,
|
285
|
-
'triggerDirection': False,
|
286
|
-
'stopLossPrice': False,
|
287
|
-
'takeProfitPrice': False,
|
288
|
-
'attachedStopLossTakeProfit': None,
|
289
|
-
'timeInForce': {
|
290
|
-
'IOC': False,
|
291
|
-
'FOK': False,
|
292
|
-
'PO': False,
|
293
|
-
'GTD': False,
|
294
|
-
},
|
295
|
-
'hedged': False,
|
296
|
-
'selfTradePrevention': False,
|
297
|
-
'trailing': False,
|
298
|
-
'leverage': False,
|
299
|
-
'marketBuyByCost': True,
|
300
|
-
'marketBuyRequiresPrice': False,
|
301
|
-
'iceberg': False,
|
302
|
-
},
|
303
|
-
'createOrders': None,
|
304
|
-
'fetchMyTrades': None,
|
305
|
-
'fetchOrder': {
|
306
|
-
'marginMode': False,
|
307
|
-
'trigger': False,
|
308
|
-
'trailing': False,
|
309
|
-
'symbolRequired': False,
|
310
|
-
},
|
311
|
-
'fetchOpenOrders': {
|
312
|
-
'marginMode': False,
|
313
|
-
'limit': None,
|
314
|
-
'trigger': False,
|
315
|
-
'trailing': False,
|
316
|
-
'symbolRequired': True,
|
317
|
-
},
|
318
|
-
'fetchOrders': {
|
319
|
-
'marginMode': False,
|
320
|
-
'limit': None, # todo
|
321
|
-
'daysBack': None, # todo
|
322
|
-
'untilDays': None, # todo
|
323
|
-
'trigger': False,
|
324
|
-
'trailing': False,
|
325
|
-
'symbolRequired': True,
|
326
|
-
},
|
327
|
-
'fetchClosedOrders': None,
|
328
|
-
'fetchOHLCV': {
|
329
|
-
'limit': 100,
|
330
|
-
},
|
331
|
-
},
|
332
|
-
'swap': {
|
333
|
-
'linear': None,
|
334
|
-
'inverse': None,
|
335
|
-
},
|
336
|
-
'future': {
|
337
|
-
'linear': None,
|
338
|
-
'inverse': None,
|
339
|
-
},
|
340
|
-
},
|
341
|
-
'commonCurrencies': {},
|
342
|
-
'exceptions': {
|
343
|
-
'exact': {
|
344
|
-
# todo
|
345
|
-
'400': BadRequest,
|
346
|
-
'401': AuthenticationError,
|
347
|
-
'403': PermissionDenied,
|
348
|
-
'404': BadRequest,
|
349
|
-
'429': DDoSProtection,
|
350
|
-
'418': PermissionDenied,
|
351
|
-
'500': ExchangeError,
|
352
|
-
'504': ExchangeError,
|
353
|
-
},
|
354
|
-
'broad': {},
|
355
|
-
},
|
356
|
-
'precisionMode': TICK_SIZE,
|
357
|
-
})
|
358
|
-
|
359
|
-
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
360
|
-
path = self.implode_params(path, params)
|
361
|
-
url = self.urls['api'][api] + '/' + path
|
362
|
-
if api == 'private':
|
363
|
-
self.check_required_credentials()
|
364
|
-
nonce = self.uuid()
|
365
|
-
timestamp = str(self.seconds())
|
366
|
-
if method == 'GET':
|
367
|
-
body = ''
|
368
|
-
else:
|
369
|
-
body = self.json(params)
|
370
|
-
params = self.extend({
|
371
|
-
'_key': self.apiKey,
|
372
|
-
'_time': timestamp,
|
373
|
-
'_nonce': nonce,
|
374
|
-
}, params)
|
375
|
-
query = self.urlencode(params)
|
376
|
-
bodyHash = self.hash(self.encode(body), 'sha256')
|
377
|
-
# Create sign string components
|
378
|
-
bodyHashBytes = self.base16_to_binary(bodyHash)
|
379
|
-
nulByte = self.number_to_be(0, 1)
|
380
|
-
components = [
|
381
|
-
self.encode(method),
|
382
|
-
nulByte,
|
383
|
-
self.encode(path),
|
384
|
-
nulByte,
|
385
|
-
self.encode(query),
|
386
|
-
nulByte,
|
387
|
-
bodyHashBytes,
|
388
|
-
]
|
389
|
-
# Join with null byte separator using encode
|
390
|
-
signString = self.binary_concat_array(components)
|
391
|
-
sec = self.secret
|
392
|
-
remainder = self.calculate_mod(len(sec), 4)
|
393
|
-
paddingLength = 4 - remainder if remainder else 0
|
394
|
-
secretWithPadding = self.secret.replace('-', '+')
|
395
|
-
secretWithPadding = secretWithPadding.replace('_', '/')
|
396
|
-
secretWithPadding = secretWithPadding.ljust(len(self.secret) + paddingLength, '=')
|
397
|
-
secretBytes = self.base64_to_binary(secretWithPadding)
|
398
|
-
seed = self.array_slice(secretBytes, 0, 32) # Extract first 32 bytes
|
399
|
-
signature = self.eddsa(signString, seed, 'ed25519')
|
400
|
-
params['_sign'] = signature
|
401
|
-
if params:
|
402
|
-
url += '?' + self.urlencode(params)
|
403
|
-
if method == 'GET':
|
404
|
-
body = None
|
405
|
-
else:
|
406
|
-
headers = {
|
407
|
-
'Content-Type': 'application/json',
|
408
|
-
}
|
409
|
-
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
410
|
-
|
411
|
-
def calculate_mod(self, a, b):
|
412
|
-
# trick to fix php transpiling error
|
413
|
-
return a % b
|
414
|
-
|
415
|
-
def fetch_markets(self, params={}) -> List[Market]:
|
416
|
-
"""
|
417
|
-
Fetches market information from the exchange.
|
418
|
-
|
419
|
-
https://docs.ccxt.com/en/latest/manual.html#markets
|
420
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.1a1t05wpgfof
|
421
|
-
|
422
|
-
:param dict [params]: - Extra parameters specific to the exchange API endpoint
|
423
|
-
:returns Promise<Market[]>: An array of market structures.
|
424
|
-
"""
|
425
|
-
response = self._restGetMarket(params)
|
426
|
-
# {
|
427
|
-
# Market__: "mkt-lrnp2e-eaor-eobj-ua73-75j6sjxe",
|
428
|
-
# Primary_Unit__: "unit-aebkye-u35b-e5zm-zt22-2qvwhsqa",
|
429
|
-
# Secondary_Unit__: "unit-jcevlk-soxf-fepb-yjwm-b32q5bom",
|
430
|
-
# Primary_Step: null,
|
431
|
-
# Secondary_Step: null,
|
432
|
-
# Status: "active",
|
433
|
-
# Default_Scale: "5",
|
434
|
-
# Priority: "100",
|
435
|
-
# Created: {
|
436
|
-
# unix: "1728113809",
|
437
|
-
# us: "0",
|
438
|
-
# iso: "2024-10-05 07:36:49.000000",
|
439
|
-
# tz: "UTC",
|
440
|
-
# full: "1728113809000000",
|
441
|
-
# unixms: "1728113809000",
|
442
|
-
# },
|
443
|
-
# Start: {
|
444
|
-
# unix: "1728295200",
|
445
|
-
# us: "0",
|
446
|
-
# iso: "2024-10-07 10:00:00.000000",
|
447
|
-
# tz: "UTC",
|
448
|
-
# full: "1728295200000000",
|
449
|
-
# unixms: "1728295200000",
|
450
|
-
# },
|
451
|
-
# Key: "BTC_USDC",
|
452
|
-
# Primary: {
|
453
|
-
# Unit__: "unit-aebkye-u35b-e5zm-zt22-2qvwhsqa",
|
454
|
-
# Currency__: "BTC",
|
455
|
-
# Crypto_Token__: "crtok-c5v3mh-grfn-hl5d-lmel-fvggbf4i",
|
456
|
-
# Key: "BTC",
|
457
|
-
# Symbol: "BTC",
|
458
|
-
# Symbol_Position: "after",
|
459
|
-
# Name: "Bitcoin",
|
460
|
-
# Decimals: "8",
|
461
|
-
# Display_Decimals: "8",
|
462
|
-
# Legacy_Decimals: null,
|
463
|
-
# Type: "crypto_token",
|
464
|
-
# Visible: "Y",
|
465
|
-
# Created: {
|
466
|
-
# unix: "1495247415",
|
467
|
-
# us: "0",
|
468
|
-
# iso: "2017-05-20 02:30:15.000000",
|
469
|
-
# tz: "UTC",
|
470
|
-
# full: "1495247415000000",
|
471
|
-
# unixms: "1495247415000",
|
472
|
-
# },
|
473
|
-
# },
|
474
|
-
# Secondary: {
|
475
|
-
# Unit__: "unit-jcevlk-soxf-fepb-yjwm-b32q5bom",
|
476
|
-
# Currency__: null,
|
477
|
-
# Crypto_Token__: "crtok-ptabkh-ra4r-anbd-cqra-bqfbtnba",
|
478
|
-
# Key: "USDC",
|
479
|
-
# Symbol: null,
|
480
|
-
# Symbol_Position: "before",
|
481
|
-
# Name: "Circle USD",
|
482
|
-
# Decimals: "6",
|
483
|
-
# Display_Decimals: "6",
|
484
|
-
# Legacy_Decimals: null,
|
485
|
-
# Type: "crypto_token",
|
486
|
-
# Visible: "Y",
|
487
|
-
# Created: {
|
488
|
-
# unix: "1694859829",
|
489
|
-
# us: "0",
|
490
|
-
# iso: "2023-09-16 10:23:49.000000",
|
491
|
-
# tz: "UTC",
|
492
|
-
# full: "1694859829000000",
|
493
|
-
# unixms: "1694859829000",
|
494
|
-
# },
|
495
|
-
# },
|
496
|
-
# }
|
497
|
-
markets = self.safe_value(response, 'data', [])
|
498
|
-
return self.parse_markets(markets)
|
499
|
-
|
500
|
-
def parse_market(self, market: dict) -> Market:
|
501
|
-
id = self.safe_string(market, 'Key')
|
502
|
-
base = self.safe_string(market['Primary'], 'Key')
|
503
|
-
quote = self.safe_string(market['Secondary'], 'Key')
|
504
|
-
baseId = self.safe_string(market['Primary'], 'Crypto_Token__')
|
505
|
-
quoteId = self.safe_string(market['Secondary'], 'Crypto_Token__')
|
506
|
-
status = self.safe_string(market, 'Status') == 'active'
|
507
|
-
created = self.safe_timestamp(market['Created'], 'unix')
|
508
|
-
amountPrecision = self.parse_number(self.parse_precision(self.safe_string(market['Primary'], 'Decimals')))
|
509
|
-
pricePrecision = self.parse_number(self.parse_precision(self.safe_string(market['Secondary'], 'Decimals')))
|
510
|
-
fees = self.fees # should use fetchTradingFees
|
511
|
-
return self.safe_market_structure({
|
512
|
-
'id': id,
|
513
|
-
'symbol': base + '/' + quote,
|
514
|
-
'base': base,
|
515
|
-
'quote': quote,
|
516
|
-
'settle': None,
|
517
|
-
'baseId': baseId,
|
518
|
-
'quoteId': quoteId,
|
519
|
-
'settleId': None,
|
520
|
-
'type': 'spot',
|
521
|
-
'spot': True,
|
522
|
-
'margin': False,
|
523
|
-
'swap': False,
|
524
|
-
'future': False,
|
525
|
-
'option': False,
|
526
|
-
'active': status,
|
527
|
-
'contract': False,
|
528
|
-
'linear': None,
|
529
|
-
'inverse': None,
|
530
|
-
'taker': fees['trading']['taker'],
|
531
|
-
'maker': fees['trading']['maker'],
|
532
|
-
'contractSize': None,
|
533
|
-
'expiry': None,
|
534
|
-
'expiryDatetime': None,
|
535
|
-
'strike': None,
|
536
|
-
'optionType': None,
|
537
|
-
'precision': {
|
538
|
-
'amount': amountPrecision,
|
539
|
-
'price': pricePrecision,
|
540
|
-
},
|
541
|
-
'limits': {
|
542
|
-
'amount': {
|
543
|
-
'min': None,
|
544
|
-
'max': None,
|
545
|
-
},
|
546
|
-
'price': {
|
547
|
-
'min': None,
|
548
|
-
'max': None,
|
549
|
-
},
|
550
|
-
'cost': {
|
551
|
-
'min': None,
|
552
|
-
'max': None,
|
553
|
-
},
|
554
|
-
},
|
555
|
-
'info': market,
|
556
|
-
'created': created,
|
557
|
-
})
|
558
|
-
|
559
|
-
def fetch_ticker(self, symbol: str, params={}) -> Ticker:
|
560
|
-
"""
|
561
|
-
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
562
|
-
|
563
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.d2jylz4u6pmu
|
564
|
-
|
565
|
-
:param str symbol: unified symbol of the market to fetch the ticker for
|
566
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
567
|
-
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
568
|
-
"""
|
569
|
-
self.load_markets()
|
570
|
-
market = self.market(symbol)
|
571
|
-
marketId = market['id']
|
572
|
-
request = {
|
573
|
-
'currencyPair': marketId,
|
574
|
-
}
|
575
|
-
response = self.publicGetMarketCurrencyPairTicker(self.extend(request, params))
|
576
|
-
#
|
577
|
-
# {
|
578
|
-
# "data": {
|
579
|
-
# "market": "BTC_USDC",
|
580
|
-
# "ticker": {
|
581
|
-
# "time": 1730814600,
|
582
|
-
# "count": 2135,
|
583
|
-
# "high": {
|
584
|
-
# "v": "74766990000",
|
585
|
-
# "e": 6,
|
586
|
-
# "f": 74766.99
|
587
|
-
# },
|
588
|
-
# "low": {
|
589
|
-
# "v": "68734020000",
|
590
|
-
# "e": 6,
|
591
|
-
# "f": 68734.02
|
592
|
-
# },
|
593
|
-
# "avg": {
|
594
|
-
# "v": "72347941430",
|
595
|
-
# "e": 6,
|
596
|
-
# "f": 72347.94143
|
597
|
-
# },
|
598
|
-
# "vwap": {
|
599
|
-
# "v": "73050064447",
|
600
|
-
# "e": 6,
|
601
|
-
# "f": 73050.064447
|
602
|
-
# },
|
603
|
-
# "vol": {
|
604
|
-
# "v": "4885361",
|
605
|
-
# "e": 8,
|
606
|
-
# "f": 0.04885361
|
607
|
-
# },
|
608
|
-
# "secvol": {
|
609
|
-
# "v": "3568759346",
|
610
|
-
# "e": 6,
|
611
|
-
# "f": 3568.759346
|
612
|
-
# },
|
613
|
-
# "open": {
|
614
|
-
# "v": "68784020000",
|
615
|
-
# "e": 6,
|
616
|
-
# "f": 68784.02
|
617
|
-
# },
|
618
|
-
# "close": {
|
619
|
-
# "v": "73955570000",
|
620
|
-
# "e": 6,
|
621
|
-
# "f": 73955.57
|
622
|
-
# }
|
623
|
-
# }
|
624
|
-
# },
|
625
|
-
# "request_id": "cbf183e0-7a62-4674-838c-6693031fa240",
|
626
|
-
# "result": "success",
|
627
|
-
# "time": 0.015463566
|
628
|
-
# }
|
629
|
-
#
|
630
|
-
ticker = self.safe_value(response['data'], 'ticker', {})
|
631
|
-
return self.parse_ticker(ticker, market)
|
632
|
-
|
633
|
-
def parse_ticker(self, ticker: dict, market: Market = None) -> Ticker:
|
634
|
-
timestamp = self.safe_integer_product(ticker, 'time', 1000)
|
635
|
-
open = self.parse_amount(self.safe_value(ticker, 'open'))
|
636
|
-
high = self.parse_amount(self.safe_value(ticker, 'high'))
|
637
|
-
low = self.parse_amount(self.safe_value(ticker, 'low'))
|
638
|
-
close = self.parse_amount(self.safe_value(ticker, 'close'))
|
639
|
-
avg = self.parse_amount(self.safe_value(ticker, 'avg'))
|
640
|
-
vwap = self.parse_amount(self.safe_value(ticker, 'vwap'))
|
641
|
-
baseVolume = self.parse_amount(self.safe_value(ticker, 'vol'))
|
642
|
-
quoteVolume = self.parse_amount(self.safe_value(ticker, 'secvol'))
|
643
|
-
# count = self.safe_integer(ticker, 'count'); not used
|
644
|
-
return self.safe_ticker({
|
645
|
-
'symbol': self.safe_symbol(None, market),
|
646
|
-
'timestamp': timestamp,
|
647
|
-
'datetime': self.iso8601(timestamp),
|
648
|
-
'high': high,
|
649
|
-
'low': low,
|
650
|
-
'bid': None,
|
651
|
-
'bidVolume': None,
|
652
|
-
'ask': None,
|
653
|
-
'askVolume': None,
|
654
|
-
'vwap': vwap,
|
655
|
-
'open': open,
|
656
|
-
'close': close,
|
657
|
-
'last': close,
|
658
|
-
'previousClose': None,
|
659
|
-
'change': None,
|
660
|
-
'percentage': None,
|
661
|
-
'average': avg,
|
662
|
-
'baseVolume': baseVolume,
|
663
|
-
'quoteVolume': quoteVolume,
|
664
|
-
'info': ticker,
|
665
|
-
}, market)
|
666
|
-
|
667
|
-
def fetch_order_book(self, symbol: str, limit: Int = None, params={}) -> OrderBook:
|
668
|
-
"""
|
669
|
-
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
670
|
-
|
671
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.bqmucewhkpdz
|
672
|
-
|
673
|
-
:param str symbol: unified symbol of the market to fetch the order book for
|
674
|
-
:param int [limit]: the maximum amount of order book entries to return the exchange not supported yet.
|
675
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
676
|
-
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
677
|
-
"""
|
678
|
-
self.load_markets()
|
679
|
-
market = self.market(symbol)
|
680
|
-
marketId = market['id']
|
681
|
-
request = {
|
682
|
-
'currencyPair': marketId,
|
683
|
-
}
|
684
|
-
response = self.publicGetMarketCurrencyPairGetDepth(self.extend(request, params))
|
685
|
-
# {
|
686
|
-
# "data": {
|
687
|
-
# "asks": [
|
688
|
-
# {
|
689
|
-
# "price": {
|
690
|
-
# "v": "74941875231",
|
691
|
-
# "e": 6,
|
692
|
-
# "f": 74941.875231
|
693
|
-
# },
|
694
|
-
# "amount": {
|
695
|
-
# "v": "149",
|
696
|
-
# "e": 8,
|
697
|
-
# "f": 0.00000149
|
698
|
-
# }
|
699
|
-
# },
|
700
|
-
# {
|
701
|
-
# "price": {
|
702
|
-
# "v": "75063426037",
|
703
|
-
# "e": 6,
|
704
|
-
# "f": 75063.426037
|
705
|
-
# },
|
706
|
-
# "amount": {
|
707
|
-
# "v": "335",
|
708
|
-
# "e": 8,
|
709
|
-
# "f": 0.00000335
|
710
|
-
# }
|
711
|
-
# }
|
712
|
-
# ],
|
713
|
-
# "bids": [
|
714
|
-
# {
|
715
|
-
# "price": {
|
716
|
-
# "v": "64518711040",
|
717
|
-
# "e": 6,
|
718
|
-
# "f": 64518.71104
|
719
|
-
# },
|
720
|
-
# "amount": {
|
721
|
-
# "v": "132",
|
722
|
-
# "e": 8,
|
723
|
-
# "f": 0.00000132
|
724
|
-
# }
|
725
|
-
# },
|
726
|
-
# {
|
727
|
-
# "price": {
|
728
|
-
# "v": "64263569273",
|
729
|
-
# "e": 6,
|
730
|
-
# "f": 64263.569273
|
731
|
-
# },
|
732
|
-
# "amount": {
|
733
|
-
# "v": "210",
|
734
|
-
# "e": 8,
|
735
|
-
# "f": 0.0000021
|
736
|
-
# }
|
737
|
-
# }
|
738
|
-
# ],
|
739
|
-
# "market": "BTC_USDC"
|
740
|
-
# },
|
741
|
-
# "request_id": "71b7dffc-3120-4e46-a0bb-49ece5aea7e1",
|
742
|
-
# "result": "success",
|
743
|
-
# "time": 0.000074661
|
744
|
-
# }
|
745
|
-
data = self.safe_value(response, 'data', {}) # exchange specific v e f params
|
746
|
-
timestamp = self.milliseconds() # the exchange does not provide timestamp for self.
|
747
|
-
dataBidsLength = len(data['bids'])
|
748
|
-
dataAsksLength = len(data['asks'])
|
749
|
-
for i in range(0, dataBidsLength):
|
750
|
-
data['bids'][i]['price'] = self.parse_amount(data['bids'][i]['price'])
|
751
|
-
data['bids'][i]['amount'] = self.parse_amount(data['bids'][i]['amount'])
|
752
|
-
for i in range(0, dataAsksLength):
|
753
|
-
data['asks'][i]['price'] = self.parse_amount(data['asks'][i]['price'])
|
754
|
-
data['asks'][i]['amount'] = self.parse_amount(data['asks'][i]['amount'])
|
755
|
-
return self.parse_order_book(data, symbol, timestamp, 'bids', 'asks', 'price', 'amount')
|
756
|
-
|
757
|
-
def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}):
|
758
|
-
"""
|
759
|
-
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market, default will return the last 24h period.
|
760
|
-
|
761
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.w65baeuhxwt8
|
762
|
-
|
763
|
-
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
764
|
-
:param str timeframe: the length of time each candle represents
|
765
|
-
:param int [since]: timestamp in ms of the earliest candle to fetch
|
766
|
-
:param int [limit]: the maximum amount of candles to fetch
|
767
|
-
:param dict [params]: extra parameters specific to the API endpoint
|
768
|
-
:param int [params.until]: timestamp in ms of the earliest candle to fetch
|
769
|
-
:returns OHLCV[]: A list of candles ordered, open, high, low, close, volume
|
770
|
-
"""
|
771
|
-
self.load_markets()
|
772
|
-
methodName = 'fetchOHLCV'
|
773
|
-
paginate = False
|
774
|
-
paginate, params = self.handle_option_and_params(params, methodName, 'paginate')
|
775
|
-
if paginate:
|
776
|
-
return self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 1000)
|
777
|
-
market = self.market(symbol)
|
778
|
-
marketId = market['id']
|
779
|
-
time_frame = self.safe_string(self.timeframes, timeframe, None)
|
780
|
-
request: dict = {
|
781
|
-
'currencyPair': marketId,
|
782
|
-
'interval': time_frame,
|
783
|
-
}
|
784
|
-
if since is not None:
|
785
|
-
request['start'] = int(math.floor(since / 1000))
|
786
|
-
until: Int = None
|
787
|
-
until, params = self.handle_option_and_params(params, methodName, 'until')
|
788
|
-
if until is not None:
|
789
|
-
request['end'] = until
|
790
|
-
# {
|
791
|
-
# "data": {
|
792
|
-
# "market": "BTC_USDC",
|
793
|
-
# "real_end": 1730970780,
|
794
|
-
# "requested_end": 1730970784,
|
795
|
-
# "start": 1730884200,
|
796
|
-
# "stats": [
|
797
|
-
# {
|
798
|
-
# "time": 1730884200,
|
799
|
-
# "count": 48,
|
800
|
-
# "high": {"v": "73898950000", "e": 6, "f": 73898.95},
|
801
|
-
# "low": {"v": "73642930000", "e": 6, "f": 73642.93},
|
802
|
-
# "open": {"v": "73830990000", "e": 6, "f": 73830.99},
|
803
|
-
# "close": {"v": "73682510000", "e": 6, "f": 73682.51},
|
804
|
-
# "vol": {"v": "88159", "e": 8, "f": 0.00088159}
|
805
|
-
# }
|
806
|
-
# ]
|
807
|
-
# }
|
808
|
-
# }
|
809
|
-
# No limit parameter supported by the API
|
810
|
-
response = self.publicGetMarketCurrencyPairGetGraph(self.extend(request, params))
|
811
|
-
data = self.safe_dict(response, 'data', {})
|
812
|
-
ohlcv = self.safe_list(data, 'stats', [])
|
813
|
-
return self.parse_ohlcvs(ohlcv, market, timeframe, since, limit)
|
814
|
-
|
815
|
-
def parse_ohlcv(self, ohlcv, market: Market = None) -> list:
|
816
|
-
return [
|
817
|
-
self.safe_integer(ohlcv, 'time') * 1000, # timestamp
|
818
|
-
self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'open'))), # open
|
819
|
-
self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'high'))), # high
|
820
|
-
self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'low'))), # low
|
821
|
-
self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'close'))), # close
|
822
|
-
self.parse_number(self.parse_amount(self.safe_dict(ohlcv, 'vol'))), # volume
|
823
|
-
]
|
824
|
-
|
825
|
-
def fetch_currencies(self, params={}) -> Currencies:
|
826
|
-
"""
|
827
|
-
fetches information on all currencies from the exchange, including deposit/withdrawal details and available chains
|
828
|
-
|
829
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.x65f9s9j74jf
|
830
|
-
|
831
|
-
:param dict [params]: extra parameters specific to the ellipx API endpoint
|
832
|
-
:param str [params.Can_Deposit]: filter currencies by deposit availability, Y for available
|
833
|
-
:param number [params.results_per_page]: number of results per page, default 100
|
834
|
-
:param str [params._expand]: additional fields to expand in response, default '/Crypto_Token,/Crypto_Chain'
|
835
|
-
:returns Promise<Currencies>: An object of currency structures indexed by currency codes
|
836
|
-
"""
|
837
|
-
response = self._restGetCryptoTokenInfo(self.extend({
|
838
|
-
'Can_Deposit': 'Y',
|
839
|
-
'results_per_page': 100,
|
840
|
-
'_expand': '/Crypto_Token,/Crypto_Chain',
|
841
|
-
}, params))
|
842
|
-
result = {}
|
843
|
-
data = self.safe_list(response, 'data', [])
|
844
|
-
for i in range(0, len(data)):
|
845
|
-
networkEntry = data[i]
|
846
|
-
#
|
847
|
-
# {
|
848
|
-
# "Crypto_Token_Info__": "crtev-5nsn35-f4ir-g5hp-iaft-i4ztx6zu",
|
849
|
-
# "Crypto_Token__": "crtok-c5v3mh-grfn-hl5d-lmel-fvggbf4i",
|
850
|
-
# "Crypto_Chain__": "chain-xjbini-7wlz-dmzf-gm7z-zf7ei6fq",
|
851
|
-
# "Type": "native",
|
852
|
-
# "Symbol": null,
|
853
|
-
# "Name": null,
|
854
|
-
# "Contract_Address": null,
|
855
|
-
# "Minimum_Deposit": {
|
856
|
-
# "v": "6",
|
857
|
-
# "e": "6",
|
858
|
-
# "f": "6.0e-6"
|
859
|
-
# },
|
860
|
-
# "Minimum_Withdraw": {
|
861
|
-
# "v": "15",
|
862
|
-
# "e": "5",
|
863
|
-
# "f": "0.00015"
|
864
|
-
# },
|
865
|
-
# "Withdraw_Fee": {
|
866
|
-
# "v": "1",
|
867
|
-
# "e": "4",
|
868
|
-
# "f": "0.0001"
|
869
|
-
# },
|
870
|
-
# "Minimum_Collect": null,
|
871
|
-
# "Status": "valid",
|
872
|
-
# "Can_Deposit": "Y",
|
873
|
-
# "Decimals": null,
|
874
|
-
# "Priority": "100",
|
875
|
-
# "Created": {
|
876
|
-
# "unix": "1727552199",
|
877
|
-
# "us": "0",
|
878
|
-
# "iso": "2024-09-28 19:36:39.000000",
|
879
|
-
# "tz": "UTC",
|
880
|
-
# "full": "1727552199000000",
|
881
|
-
# "unixms": "1727552199000"
|
882
|
-
# },
|
883
|
-
# "Crypto_Token": {
|
884
|
-
# "Crypto_Token__": "crtok-c5v3mh-grfn-hl5d-lmel-fvggbf4i",
|
885
|
-
# "Name": "Bitcoin",
|
886
|
-
# "Symbol": "BTC",
|
887
|
-
# "Decimals": "8",
|
888
|
-
# "CMC_Id": "1",
|
889
|
-
# "Priority": "100",
|
890
|
-
# "Can_Deposit": "Y",
|
891
|
-
# "Category": "token",
|
892
|
-
# "Testnet": "N",
|
893
|
-
# "Created": {
|
894
|
-
# "unix": "1727552113",
|
895
|
-
# "us": "0",
|
896
|
-
# "iso": "2024-09-28 19:35:13.000000",
|
897
|
-
# "tz": "UTC",
|
898
|
-
# "full": "1727552113000000",
|
899
|
-
# "unixms": "1727552113000"
|
900
|
-
# },
|
901
|
-
# "Logo": [
|
902
|
-
# {
|
903
|
-
# "Crypto_Token_Logo__": "ctklg-aoozyr-rzm5-fphf-dhm7-5wbtetha",
|
904
|
-
# "Crypto_Token__": "crtok-c5v3mh-grfn-hl5d-lmel-fvggbf4i",
|
905
|
-
# "Blob__": "blob-d6hvgx-37s5-dh5h-ogj5-qxqvnaoy",
|
906
|
-
# "Default": "Y",
|
907
|
-
# "Format": "png",
|
908
|
-
# "Priority": "0",
|
909
|
-
# "Created": {
|
910
|
-
# "unix": "1730196627",
|
911
|
-
# "us": "929660",
|
912
|
-
# "iso": "2024-10-29 10:10:27.929660",
|
913
|
-
# "tz": "UTC",
|
914
|
-
# "full": "1730196627929660",
|
915
|
-
# "unixms": "1730196627929"
|
916
|
-
# },
|
917
|
-
# "Source": {
|
918
|
-
# "Media_Image__": "blob-d6hvgx-37s5-dh5h-ogj5-qxqvnaoy",
|
919
|
-
# "Url": "https://static.atonline.net/image/m_X7_tnmIYFCwn6EUVQuMKqrCuPB3CMl4ONTegeYpC0wIg68YZM0CuBpbjspnYwz/1a942eab068a2173e66d08c736283cfe22e1c1ed"
|
920
|
-
# }
|
921
|
-
# }
|
922
|
-
# ]
|
923
|
-
# },
|
924
|
-
# "Crypto_Chain": {
|
925
|
-
# "Crypto_Chain__": "chain-xjbini-7wlz-dmzf-gm7z-zf7ei6fq",
|
926
|
-
# "EVM_Chain__": null,
|
927
|
-
# "Crypto_Token__": "crtok-c5v3mh-grfn-hl5d-lmel-fvggbf4i",
|
928
|
-
# "Name": "Bitcoin",
|
929
|
-
# "Key": "bitcoin",
|
930
|
-
# "Type": "Bitcoin",
|
931
|
-
# "Curve": "secp256k1",
|
932
|
-
# "Backend_Url": null,
|
933
|
-
# "Wallet_Verification_Methods": {
|
934
|
-
# "signature": True
|
935
|
-
# },
|
936
|
-
# "Block_Margin": "3",
|
937
|
-
# "Created": {
|
938
|
-
# "unix": "1725340084",
|
939
|
-
# "us": "0",
|
940
|
-
# "iso": "2024-09-03 05:08:04.000000",
|
941
|
-
# "tz": "UTC",
|
942
|
-
# "full": "1725340084000000",
|
943
|
-
# "unixms": "1725340084000"
|
944
|
-
# }
|
945
|
-
# }
|
946
|
-
# }
|
947
|
-
#
|
948
|
-
id = self.safe_string(networkEntry, 'Crypto_Token__')
|
949
|
-
token = self.safe_dict(networkEntry, 'Crypto_Token', {})
|
950
|
-
code = self.safe_currency_code(self.safe_string(token, 'Symbol'))
|
951
|
-
if not (code in result):
|
952
|
-
result[code] = {
|
953
|
-
'id': id,
|
954
|
-
'code': code,
|
955
|
-
'info': [],
|
956
|
-
'type': None,
|
957
|
-
'name': self.safe_string(token, 'Name'),
|
958
|
-
'active': None,
|
959
|
-
'deposit': None,
|
960
|
-
'withdraw': None,
|
961
|
-
'fee': None,
|
962
|
-
'precision': None,
|
963
|
-
'limits': {
|
964
|
-
'amount': {
|
965
|
-
'min': None,
|
966
|
-
'max': None,
|
967
|
-
},
|
968
|
-
'withdraw': {
|
969
|
-
'min': None,
|
970
|
-
'max': None,
|
971
|
-
},
|
972
|
-
'deposit': {
|
973
|
-
'min': None,
|
974
|
-
'max': None,
|
975
|
-
},
|
976
|
-
},
|
977
|
-
'networks': {},
|
978
|
-
}
|
979
|
-
networkId = self.safe_string(networkEntry, 'Crypto_Chain__')
|
980
|
-
cryptoChainDict = self.safe_string(networkEntry, 'Crypto_Chain')
|
981
|
-
networkName = self.safe_string(cryptoChainDict, 'Type', 'default')
|
982
|
-
networkCode = self.network_id_to_code(networkName)
|
983
|
-
result[code]['networks'][networkCode] = {
|
984
|
-
'id': networkId,
|
985
|
-
'network': networkCode,
|
986
|
-
'active': self.safe_string(networkEntry, 'Status') == 'valid',
|
987
|
-
'deposit': self.safe_string(networkEntry, 'Can_Deposit') == 'Y',
|
988
|
-
'withdraw': None,
|
989
|
-
'fee': self.parse_number(self.parse_amount(networkEntry['Withdraw_Fee'])),
|
990
|
-
'precision': self.parse_number(self.parse_precision(self.safe_string(token, 'Decimals'))),
|
991
|
-
'limits': {
|
992
|
-
'amount': {
|
993
|
-
'min': None,
|
994
|
-
'max': None,
|
995
|
-
},
|
996
|
-
'withdraw': {
|
997
|
-
'min': self.parse_amount(networkEntry['Minimum_Withdraw']),
|
998
|
-
'max': None,
|
999
|
-
},
|
1000
|
-
'deposit': {
|
1001
|
-
'min': self.parse_amount(networkEntry['Minimum_Deposit']),
|
1002
|
-
'max': None,
|
1003
|
-
},
|
1004
|
-
},
|
1005
|
-
}
|
1006
|
-
infos = self.safe_list(result[code], 'info', [])
|
1007
|
-
infos.append(networkEntry)
|
1008
|
-
result[code]['info'] = infos
|
1009
|
-
# only after all entries are formed in currencies, restructure each entry
|
1010
|
-
allKeys = list(result.keys())
|
1011
|
-
for i in range(0, len(allKeys)):
|
1012
|
-
code = allKeys[i]
|
1013
|
-
result[code] = self.safe_currency_structure(result[code]) # self is needed after adding network entry
|
1014
|
-
return result
|
1015
|
-
|
1016
|
-
def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
1017
|
-
"""
|
1018
|
-
fetches all completed trades for a particular market/symbol
|
1019
|
-
:param str symbol: unified market symbol(e.g. 'BTC/USDT')
|
1020
|
-
:param int [since]: timestamp in ms of the earliest trade to fetch
|
1021
|
-
:param int [limit]: the maximum amount of trades to fetch
|
1022
|
-
:param dict [params]: extra parameters specific to the EllipX API endpoint
|
1023
|
-
:param str [params.before]: get trades before the given trade ID
|
1024
|
-
:returns Trade[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
1025
|
-
"""
|
1026
|
-
self.load_markets()
|
1027
|
-
market = self.market(symbol)
|
1028
|
-
marketId = market['id']
|
1029
|
-
request = {
|
1030
|
-
'currencyPair': marketId,
|
1031
|
-
}
|
1032
|
-
# endpoint support before trade id.
|
1033
|
-
# The actual endpoint URL will be: https://data.ellipx.com/Market/{currencyPair}:getTrades
|
1034
|
-
# {
|
1035
|
-
# "id": "BTC_USDC:1731053859:914141972:0",
|
1036
|
-
# "pair": [
|
1037
|
-
# "BTC",
|
1038
|
-
# "USDC"
|
1039
|
-
# ],
|
1040
|
-
# "bid": {
|
1041
|
-
# "id": "mktor-swishf-uv6n-hrzj-63ye-bdqnk33q",
|
1042
|
-
# "iss": "ellipx:beta",
|
1043
|
-
# "uniq": "order:1731053859:914141972:0"
|
1044
|
-
# },
|
1045
|
-
# "ask": {
|
1046
|
-
# "id": "mktor-p3ozvt-qurz-gmzo-bf5n-g4rcuy6u",
|
1047
|
-
# "iss": "ellipx:beta",
|
1048
|
-
# "uniq": "order:1731053859:874659786:0"
|
1049
|
-
# },
|
1050
|
-
# "type": "bid",
|
1051
|
-
# "amount": {
|
1052
|
-
# "v": "412",
|
1053
|
-
# "e": 8,
|
1054
|
-
# "f": 0.00000412
|
1055
|
-
# },
|
1056
|
-
# "price": {
|
1057
|
-
# "v": "75878090000",
|
1058
|
-
# "e": 6,
|
1059
|
-
# "f": 75878.09
|
1060
|
-
# },
|
1061
|
-
# "date": "2024-11-08T08:17:39.914141972Z"
|
1062
|
-
# }
|
1063
|
-
response = self.publicGetMarketCurrencyPairGetTrades(self.extend(request, params))
|
1064
|
-
data = self.safe_dict(response, 'data', {})
|
1065
|
-
trades = self.safe_list(data, 'trades', [])
|
1066
|
-
return self.parse_trades(trades, market, since, limit)
|
1067
|
-
|
1068
|
-
def parse_trade(self, trade, market=None) -> Trade:
|
1069
|
-
# Format of trade ID: "BTC_USDC:1731053859:914141972:0"
|
1070
|
-
id = self.safe_string(trade, 'id')
|
1071
|
-
# fetchTrades and fetchMyTrades return different trade structures
|
1072
|
-
date = self.safe_dict(trade, 'date')
|
1073
|
-
timestamp = None
|
1074
|
-
if date is None:
|
1075
|
-
timestamp = self.parse8601(self.safe_string(trade, 'date'))
|
1076
|
-
else:
|
1077
|
-
timestamp = self.safe_integer(date, 'unixms')
|
1078
|
-
type = self.safe_string(trade, 'type')
|
1079
|
-
side = 'buy' if (type == 'bid') else 'sell'
|
1080
|
-
amount = self.safe_dict(trade, 'amount')
|
1081
|
-
price = self.safe_dict(trade, 'price')
|
1082
|
-
amountFloat = self.parse_amount(amount)
|
1083
|
-
priceFloat = self.parse_amount(price)
|
1084
|
-
# fetchTrades and fetchMyTrades return different trade structures
|
1085
|
-
pair = self.safe_list(trade, 'pair')
|
1086
|
-
marketSymbol = None
|
1087
|
-
if pair is None:
|
1088
|
-
symbol = self.safe_string(trade, 'pair')
|
1089
|
-
base, quote = symbol.split('_')
|
1090
|
-
marketSymbol = base + '/' + quote
|
1091
|
-
else:
|
1092
|
-
marketSymbol = self.safe_string(pair, 0) + '/' + self.safe_string(pair, 1)
|
1093
|
-
bidOrder = self.safe_dict(trade, 'bid')
|
1094
|
-
askOrder = self.safe_dict(trade, 'ask')
|
1095
|
-
isBuy = (side == 'buy')
|
1096
|
-
orderId = self.safe_string(bidOrder, 'id') if isBuy else self.safe_string(askOrder, 'id')
|
1097
|
-
return self.safe_trade({
|
1098
|
-
'id': id,
|
1099
|
-
'info': trade,
|
1100
|
-
'timestamp': timestamp,
|
1101
|
-
'datetime': self.iso8601(timestamp),
|
1102
|
-
'symbol': marketSymbol,
|
1103
|
-
'type': None,
|
1104
|
-
'side': side,
|
1105
|
-
'order': orderId,
|
1106
|
-
'takerOrMaker': None,
|
1107
|
-
'price': priceFloat,
|
1108
|
-
'amount': amountFloat,
|
1109
|
-
'cost': None,
|
1110
|
-
'fee': None,
|
1111
|
-
})
|
1112
|
-
|
1113
|
-
def fetch_balance(self, params={}) -> Balances:
|
1114
|
-
"""
|
1115
|
-
query for balance and get the amount of funds available for trading or funds locked in orders
|
1116
|
-
|
1117
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.ihrjov144txg
|
1118
|
-
|
1119
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1120
|
-
:returns dict: a `balance structure <https://docs.ccxt.com/#/?id=balance-structure>`
|
1121
|
-
"""
|
1122
|
-
self.load_markets()
|
1123
|
-
response = self.privateGetUserWallet(params)
|
1124
|
-
# {
|
1125
|
-
# "User_Wallet__": "usw-vv7hzo-qel5-gupk-neqi-7f3wz5pq",
|
1126
|
-
# "User__": "usr-...",
|
1127
|
-
# "Realm__": "usrr-cb3c7n-qvxv-fdrb-uc2q-gpja2foi",
|
1128
|
-
# "Unit__": "unit-aebkye-u35b-e5zm-zt22-2qvwhsqa",
|
1129
|
-
# "Balance": {
|
1130
|
-
# "value": "0.00006394",
|
1131
|
-
# "value_int": "6394",
|
1132
|
-
# "value_disp": "0.00006394",
|
1133
|
-
# "value_xint": {
|
1134
|
-
# "v": "6394",
|
1135
|
-
# "e": 8,
|
1136
|
-
# "f": 0.00006394
|
1137
|
-
# },
|
1138
|
-
# "display": "0.00006394BTC",
|
1139
|
-
# "display_short": "0.00006394BTC",
|
1140
|
-
# "currency": "BTC",
|
1141
|
-
# "unit": "BTC",
|
1142
|
-
# "has_vat": False,
|
1143
|
-
# "tax_profile": null
|
1144
|
-
# },
|
1145
|
-
# "Balance_Date": {
|
1146
|
-
# "unix": 1731128270,
|
1147
|
-
# "us": 426208,
|
1148
|
-
# "iso": "2024-11-09 04:57:50.426208",
|
1149
|
-
# "tz": "UTC",
|
1150
|
-
# "full": "1731128270426208",
|
1151
|
-
# "unixms": "1731128270426"
|
1152
|
-
# },
|
1153
|
-
# "Liabilities": {
|
1154
|
-
# "value": "0.00000000",
|
1155
|
-
# "value_int": "0",
|
1156
|
-
# "value_disp": "0.00000000",
|
1157
|
-
# "value_xint": {
|
1158
|
-
# "v": "0",
|
1159
|
-
# "e": 8,
|
1160
|
-
# "f": 0
|
1161
|
-
# },
|
1162
|
-
# "display": "0.00000000BTC",
|
1163
|
-
# "display_short": "0.00000000BTC",
|
1164
|
-
# "currency": "BTC",
|
1165
|
-
# "unit": "BTC",
|
1166
|
-
# "has_vat": False,
|
1167
|
-
# "tax_profile": null
|
1168
|
-
# },
|
1169
|
-
# "Index": "5",
|
1170
|
-
# "Backend": "virtual",
|
1171
|
-
# "Disable_Limits": "N",
|
1172
|
-
# "Unencumbered_Balance": {
|
1173
|
-
# "value": "0.00006394",
|
1174
|
-
# "value_int": "6394",
|
1175
|
-
# "value_disp": "0.00006394",
|
1176
|
-
# "value_xint": {
|
1177
|
-
# "v": "6394",
|
1178
|
-
# "e": 8,
|
1179
|
-
# "f": 0.00006394
|
1180
|
-
# },
|
1181
|
-
# "display": "0.00006394BTC",
|
1182
|
-
# "display_short": "0.00006394BTC",
|
1183
|
-
# "currency": "BTC",
|
1184
|
-
# "unit": "BTC",
|
1185
|
-
# "has_vat": False,
|
1186
|
-
# "tax_profile": null
|
1187
|
-
# }
|
1188
|
-
# }
|
1189
|
-
result: dict = {
|
1190
|
-
'info': response,
|
1191
|
-
'timestamp': None,
|
1192
|
-
'datetime': None,
|
1193
|
-
}
|
1194
|
-
dataArray = self.safe_list(response, 'data', [])
|
1195
|
-
# Use first item's timestamp if available
|
1196
|
-
dataArrayLength = len(dataArray)
|
1197
|
-
if dataArrayLength > 0:
|
1198
|
-
firstItem = dataArray[0]
|
1199
|
-
balanceDate = self.safe_dict(firstItem, 'Balance_Date', {})
|
1200
|
-
result['timestamp'] = self.safe_integer(balanceDate, 'unixms')
|
1201
|
-
result['datetime'] = self.iso8601(result['timestamp'])
|
1202
|
-
# Process each balance entry
|
1203
|
-
for i in range(0, len(dataArray)):
|
1204
|
-
entry = dataArray[i]
|
1205
|
-
balance = self.safe_dict(entry, 'Balance', {})
|
1206
|
-
code = self.safe_string(balance, 'currency')
|
1207
|
-
if code is not None:
|
1208
|
-
account = {
|
1209
|
-
'free': self.parse_amount(entry['Unencumbered_Balance']['value_xint']),
|
1210
|
-
'used': self.parse_amount(entry['Liabilities']['value_xint']),
|
1211
|
-
'total': self.parse_amount(balance['value_xint']),
|
1212
|
-
}
|
1213
|
-
result[code] = account
|
1214
|
-
return self.safe_balance(result)
|
1215
|
-
|
1216
|
-
def create_order(self, symbol: str, type: OrderType, side: OrderSide, amount: float, price: Num = None, params={}):
|
1217
|
-
"""
|
1218
|
-
create a new order in a market
|
1219
|
-
|
1220
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.yzfak2n2bwpo
|
1221
|
-
|
1222
|
-
:param str symbol: unified market symbol(e.g. 'BTC/USDT')
|
1223
|
-
:param str type: order type - the exchange automatically sets type to 'limit' if price defined, 'market' if None
|
1224
|
-
:param str side: 'buy' or 'sell'
|
1225
|
-
:param float [amount]: amount of base currency to trade(can be None if using Spend_Limit)
|
1226
|
-
:param float [price]: price per unit of base currency for limit orders
|
1227
|
-
:param dict [params]: extra parameters specific to the EllipX API endpoint
|
1228
|
-
:param float [params.cost]: maximum amount to spend in quote currency(required for market orders if amount None)
|
1229
|
-
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1230
|
-
"""
|
1231
|
-
self.load_markets()
|
1232
|
-
market = self.market(symbol)
|
1233
|
-
# the exchange automatically sets the type to 'limit' if the price is defined and to 'market' if it is not
|
1234
|
-
marketId = market['id']
|
1235
|
-
orderType = 'bid'
|
1236
|
-
if side == 'buy':
|
1237
|
-
orderType = 'bid'
|
1238
|
-
else:
|
1239
|
-
orderType = 'ask'
|
1240
|
-
request: Any = {
|
1241
|
-
'currencyPair': marketId,
|
1242
|
-
'Type': orderType,
|
1243
|
-
}
|
1244
|
-
if amount is not None:
|
1245
|
-
request['Amount'] = self.amount_to_precision(symbol, amount)
|
1246
|
-
if price is not None:
|
1247
|
-
request['Price'] = self.price_to_precision(symbol, price)
|
1248
|
-
cost = self.safe_string(params, 'cost')
|
1249
|
-
if cost is not None:
|
1250
|
-
params = self.omit(params, 'cost')
|
1251
|
-
request['Spend_Limit'] = self.price_to_precision(symbol, cost)
|
1252
|
-
response = self.privatePostMarketCurrencyPairOrder(self.extend(request, params))
|
1253
|
-
# {
|
1254
|
-
# "result": "success",
|
1255
|
-
# "data": {
|
1256
|
-
# "Market_Order__": "mktor-x2grmu-zwo5-fyxc-4gue-vd4ouvsa",
|
1257
|
-
# "Market__": "mkt-lrnp2e-eaor-eobj-ua73-75j6sjxe",
|
1258
|
-
# "User__": "usr-...",
|
1259
|
-
# "Uniq": "order:1728719021:583795548:0",
|
1260
|
-
# "Type": "bid",
|
1261
|
-
# "Status": "pending",
|
1262
|
-
# "Flags": {},
|
1263
|
-
# "Amount": {
|
1264
|
-
# "v": "100000000",
|
1265
|
-
# "e": 8,
|
1266
|
-
# "f": 1
|
1267
|
-
# },
|
1268
|
-
# "Price": null,
|
1269
|
-
# "Spend_Limit": {
|
1270
|
-
# "v": "1000000",
|
1271
|
-
# "e": 6,
|
1272
|
-
# "f": 1
|
1273
|
-
# },
|
1274
|
-
# "Executed": {
|
1275
|
-
# "v": "0",
|
1276
|
-
# "e": 0,
|
1277
|
-
# "f": 0
|
1278
|
-
# },
|
1279
|
-
# "Secured": {
|
1280
|
-
# "v": "1000000",
|
1281
|
-
# "e": 6,
|
1282
|
-
# "f": 1
|
1283
|
-
# },
|
1284
|
-
# "Version": "0",
|
1285
|
-
# "Created": {
|
1286
|
-
# "unix": 1728719020,
|
1287
|
-
# "us": 315195,
|
1288
|
-
# "iso": "2024-10-12 07:43:40.315195",
|
1289
|
-
# "tz": "UTC",
|
1290
|
-
# "full": "1728719020315195",
|
1291
|
-
# "unixms": "1728719020315"
|
1292
|
-
# },
|
1293
|
-
# "Updated": {
|
1294
|
-
# "unix": 1728719020,
|
1295
|
-
# "us": 315195,
|
1296
|
-
# "iso": "2024-10-12 07:43:40.315195",
|
1297
|
-
# "tz": "UTC",
|
1298
|
-
# "full": "1728719020315195",
|
1299
|
-
# "unixms": "1728719020315"
|
1300
|
-
# }
|
1301
|
-
# }
|
1302
|
-
# }
|
1303
|
-
order = self.safe_dict(response, 'data', {})
|
1304
|
-
return self.parse_order(order, market)
|
1305
|
-
|
1306
|
-
def fetch_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
1307
|
-
"""
|
1308
|
-
fetches information on an order made by the user
|
1309
|
-
:param str id: the order ID by createOrder or fetchOrders
|
1310
|
-
:param str|None symbol: not used by ellipx.fetchOrder
|
1311
|
-
:param dict [params]: extra parameters specific to the EllipX API endpoint
|
1312
|
-
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1313
|
-
"""
|
1314
|
-
self.load_markets()
|
1315
|
-
request = {
|
1316
|
-
'orderUuid': id,
|
1317
|
-
}
|
1318
|
-
response = self.privateGetMarketOrderOrderUuid(self.extend(request, params))
|
1319
|
-
data = self.safe_dict(response, 'data', {})
|
1320
|
-
return self.parse_order(data, None)
|
1321
|
-
|
1322
|
-
def fetch_orders_by_status(self, status, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1323
|
-
"""
|
1324
|
-
fetches a list of orders placed on the exchange
|
1325
|
-
|
1326
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.5z2nh2b5s81n
|
1327
|
-
|
1328
|
-
:param str status: 'open' or 'closed', omit for all orders
|
1329
|
-
:param str symbol: unified market symbol
|
1330
|
-
:param int [since]: timestamp in ms of the earliest order
|
1331
|
-
:param int [limit]: the maximum amount of orders to fetch
|
1332
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1333
|
-
:returns dict[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1334
|
-
"""
|
1335
|
-
self.load_markets()
|
1336
|
-
market = None
|
1337
|
-
request: Any = {}
|
1338
|
-
if symbol is not None:
|
1339
|
-
market = self.market(symbol)
|
1340
|
-
marketId = market['id']
|
1341
|
-
request['currencyPair'] = marketId
|
1342
|
-
if status is not None:
|
1343
|
-
request['Status'] = status
|
1344
|
-
response = self.privateGetMarketCurrencyPairOrder(self.extend(request, params))
|
1345
|
-
# {
|
1346
|
-
# "result": "success",
|
1347
|
-
# "data": [
|
1348
|
-
# {
|
1349
|
-
# "Market_Order__": "mktor-aglvd2-iy5v-enbj-nwrb-scqsnosa",
|
1350
|
-
# "Market__": "mkt-lrnp2e-eaor-eobj-ua73-75j6sjxe",
|
1351
|
-
# "User__": "usr-...",
|
1352
|
-
# "Uniq": "order:1728712511:964332600:0",
|
1353
|
-
# "Type": "ask",
|
1354
|
-
# "Status": "open",
|
1355
|
-
# "Flags": {},
|
1356
|
-
# "Amount": {
|
1357
|
-
# "v": "1",
|
1358
|
-
# "e": 8,
|
1359
|
-
# "f": 1.0e-8
|
1360
|
-
# },
|
1361
|
-
# "Price": {
|
1362
|
-
# "v": "63041306872",
|
1363
|
-
# "e": 6,
|
1364
|
-
# "f": 63041.306872
|
1365
|
-
# },
|
1366
|
-
# "Spend_Limit": null,
|
1367
|
-
# "Executed": {
|
1368
|
-
# "v": "892",
|
1369
|
-
# "e": 8,
|
1370
|
-
# "f": 8.92e-6
|
1371
|
-
# },
|
1372
|
-
# "Secured": null,
|
1373
|
-
# "Version": "3",
|
1374
|
-
# "Created": {
|
1375
|
-
# "unix": 1728712510,
|
1376
|
-
# "us": 669096,
|
1377
|
-
# "iso": "2024-10-12 05:55:10.669096",
|
1378
|
-
# "tz": "UTC",
|
1379
|
-
# "full": "1728712510669096",
|
1380
|
-
# "unixms": "1728712510669"
|
1381
|
-
# },
|
1382
|
-
# "Updated": {
|
1383
|
-
# "unix": 1728712510,
|
1384
|
-
# "us": 669096,
|
1385
|
-
# "iso": "2024-10-12 05:55:10.669096",
|
1386
|
-
# "tz": "UTC",
|
1387
|
-
# "full": "1728712510669096",
|
1388
|
-
# "unixms": "1728712510669"
|
1389
|
-
# }
|
1390
|
-
# }
|
1391
|
-
# ],
|
1392
|
-
# "paging": {
|
1393
|
-
# "page_no": 1,
|
1394
|
-
# "count": "1",
|
1395
|
-
# "page_max": 1,
|
1396
|
-
# "results_per_page": 20
|
1397
|
-
# }
|
1398
|
-
# }
|
1399
|
-
data = self.safe_value(response, 'data', [])
|
1400
|
-
return self.parse_orders(data, market, since, limit)
|
1401
|
-
|
1402
|
-
def fetch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}):
|
1403
|
-
"""
|
1404
|
-
fetches information on multiple orders made by the user
|
1405
|
-
|
1406
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.5z2nh2b5s81n
|
1407
|
-
|
1408
|
-
:param str symbol: unified market symbol of the market orders were made in
|
1409
|
-
:param int|None since: timestamp in ms of the earliest order
|
1410
|
-
:param int|None limit: the maximum amount of orders to fetch
|
1411
|
-
:param dict params: extra parameters specific to the exchange API endpoint
|
1412
|
-
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1413
|
-
"""
|
1414
|
-
if symbol is None:
|
1415
|
-
raise ArgumentsRequired(self.id + ' fetchOrders requires a symbol parameter')
|
1416
|
-
return self.fetch_orders_by_status(None, symbol, since, limit, params)
|
1417
|
-
|
1418
|
-
def fetch_open_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1419
|
-
"""
|
1420
|
-
fetches information on open orders made by the user
|
1421
|
-
|
1422
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.5z2nh2b5s81n
|
1423
|
-
|
1424
|
-
:param str symbol: unified market symbol of the market orders were made in
|
1425
|
-
:param int|None since: timestamp in ms of the earliest order
|
1426
|
-
:param int|None limit: the maximum amount of orders to fetch
|
1427
|
-
:param dict params: extra parameters specific to the exchange API endpoint
|
1428
|
-
:returns Order[]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1429
|
-
"""
|
1430
|
-
if symbol is None:
|
1431
|
-
raise ArgumentsRequired(self.id + ' fetchOpenOrders requires a symbol parameter')
|
1432
|
-
return self.fetch_orders_by_status('open', symbol, since, limit, params)
|
1433
|
-
|
1434
|
-
def parse_order(self, order, market=None) -> Order:
|
1435
|
-
id = self.safe_string(order, 'Market_Order__')
|
1436
|
-
timestamp = self.safe_integer(self.safe_dict(order, 'Created'), 'unixms')
|
1437
|
-
orderType = self.safe_string(order, 'Type')
|
1438
|
-
side = 'sell'
|
1439
|
-
if orderType == 'bid':
|
1440
|
-
side = 'buy'
|
1441
|
-
status = self.parse_order_status(self.safe_string(order, 'Status'))
|
1442
|
-
amount = self.parse_number(self.parse_amount(self.safe_dict(order, 'Amount')))
|
1443
|
-
price = self.parse_number(self.parse_amount(self.safe_dict(order, 'Price')))
|
1444
|
-
type = 'market' if (price is None) else 'limit'
|
1445
|
-
executed = self.parse_number(self.parse_amount(self.safe_dict(order, 'Executed')))
|
1446
|
-
filled = executed
|
1447
|
-
remaining = self.parse_number(self.parse_amount(self.safe_dict(order, 'Secured')))
|
1448
|
-
cost = self.parse_number(self.parse_amount(self.safe_dict(order, 'Total_Spent')))
|
1449
|
-
symbol = market['symbol'] if market else None
|
1450
|
-
clientOrderId = None
|
1451
|
-
timeInForce = 'GTC' # default to Good Till Cancelled
|
1452
|
-
postOnly = False
|
1453
|
-
updated = self.safe_dict(order, 'Updated', {})
|
1454
|
-
lastTradeTimestamp = self.safe_integer(updated, 'unixms', None)
|
1455
|
-
return self.safe_order({
|
1456
|
-
'id': id,
|
1457
|
-
'clientOrderId': clientOrderId,
|
1458
|
-
'info': order,
|
1459
|
-
'timestamp': timestamp,
|
1460
|
-
'datetime': self.iso8601(timestamp),
|
1461
|
-
'lastTradeTimestamp': lastTradeTimestamp,
|
1462
|
-
'status': self.parse_order_status(status),
|
1463
|
-
'symbol': symbol,
|
1464
|
-
'type': type,
|
1465
|
-
'timeInForce': timeInForce,
|
1466
|
-
'postOnly': postOnly,
|
1467
|
-
'side': side,
|
1468
|
-
'price': price,
|
1469
|
-
'triggerPrice': None,
|
1470
|
-
'average': None,
|
1471
|
-
'cost': cost,
|
1472
|
-
'amount': amount,
|
1473
|
-
'filled': filled,
|
1474
|
-
'remaining': remaining,
|
1475
|
-
'fee': None,
|
1476
|
-
'trades': None,
|
1477
|
-
}, market)
|
1478
|
-
|
1479
|
-
def cancel_order(self, id: str, symbol: Str = None, params={}) -> Order:
|
1480
|
-
"""
|
1481
|
-
Cancels an open order on the exchange
|
1482
|
-
|
1483
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.f1qu1pb1rebn
|
1484
|
-
|
1485
|
-
:param str id: - The order ID to cancel(format: mktor-xxxxx-xxxx-xxxx-xxxx-xxxxxxxx)
|
1486
|
-
:param str [symbol]: - ellipx.cancelOrder does not use the symbol parameter
|
1487
|
-
:param dict [params]: - Extra parameters specific to the exchange API
|
1488
|
-
:returns Promise<dict>: A Promise that resolves to the canceled order info
|
1489
|
-
"""
|
1490
|
-
self.load_markets()
|
1491
|
-
request = {
|
1492
|
-
'orderUuid': id,
|
1493
|
-
}
|
1494
|
-
response = self.privateDeleteMarketOrderOrderUuid(self.extend(request, params))
|
1495
|
-
# {
|
1496
|
-
# result: "success",
|
1497
|
-
# request_id: "887dba33-d11b-43f0-8034-dd7890882cc5",
|
1498
|
-
# time: "0.8975801467895508",
|
1499
|
-
# data: True,
|
1500
|
-
# access: {
|
1501
|
-
# "mktor-rf5k5b-5fhf-dmde-wxqj-3y23jeii": {
|
1502
|
-
# required: "A",
|
1503
|
-
# available: "O",
|
1504
|
-
# },
|
1505
|
-
# },
|
1506
|
-
# }
|
1507
|
-
# self endpoint always returns True and a warning message if the order cancelled before.
|
1508
|
-
warningResponse = self.safe_value(response, 'warning', None)
|
1509
|
-
statusResponse = self.safe_bool(response, 'data')
|
1510
|
-
status = 'canceled'
|
1511
|
-
if statusResponse is not True or warningResponse is not None:
|
1512
|
-
status = 'closed'
|
1513
|
-
return self.safe_order({
|
1514
|
-
'id': id,
|
1515
|
-
'clientOrderId': None,
|
1516
|
-
'info': self.json(response), # original response
|
1517
|
-
'timestamp': None,
|
1518
|
-
'datetime': None,
|
1519
|
-
'lastTradeTimestamp': None,
|
1520
|
-
'status': status,
|
1521
|
-
'symbol': None,
|
1522
|
-
'type': None,
|
1523
|
-
'timeInForce': None,
|
1524
|
-
'postOnly': None,
|
1525
|
-
'side': None,
|
1526
|
-
'price': None,
|
1527
|
-
'triggerPrice': None,
|
1528
|
-
'average': None,
|
1529
|
-
'cost': None,
|
1530
|
-
'amount': None,
|
1531
|
-
'filled': None,
|
1532
|
-
'remaining': None,
|
1533
|
-
'fee': None,
|
1534
|
-
'trades': None,
|
1535
|
-
}, None)
|
1536
|
-
|
1537
|
-
def fetch_order_trades(self, id: str, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
|
1538
|
-
"""
|
1539
|
-
fetch all the trades made from a single order
|
1540
|
-
:param str id: order id
|
1541
|
-
:param str symbol: unified market symbol
|
1542
|
-
:param int [since]: the earliest time in ms to fetch trades for
|
1543
|
-
:param int [limit]: the maximum number of trades to retrieve
|
1544
|
-
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1545
|
-
:returns dict[]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
1546
|
-
"""
|
1547
|
-
if symbol is None:
|
1548
|
-
raise ArgumentsRequired('fetchMyTrades requires a symbol parameter')
|
1549
|
-
self.load_markets()
|
1550
|
-
market = self.market(symbol)
|
1551
|
-
currencyPair = market['id']
|
1552
|
-
request = {
|
1553
|
-
'Market_Order__': id,
|
1554
|
-
'currencyPair': currencyPair,
|
1555
|
-
}
|
1556
|
-
response = self.privateGetMarketCurrencyPairTrade(self.extend(request, params))
|
1557
|
-
# {
|
1558
|
-
# "result": "success",
|
1559
|
-
# "request_id": "fc5be99d-d085-46f8-9228-e46d0996f112",
|
1560
|
-
# "time": 0.030913114547729492,
|
1561
|
-
# "data": [
|
1562
|
-
# {
|
1563
|
-
# "id": "DOGE_USDC:1731505789:911642994:0",
|
1564
|
-
# "pair": "DOGE_USDC",
|
1565
|
-
# "bid": {
|
1566
|
-
# "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
|
1567
|
-
# },
|
1568
|
-
# "ask": {
|
1569
|
-
# "id": "mktor-oxmac4-mtkf-gi3o-mamg-u2cboqe4"
|
1570
|
-
# },
|
1571
|
-
# "type": "bid",
|
1572
|
-
# "amount": {
|
1573
|
-
# "v": "334609419",
|
1574
|
-
# "e": 8,
|
1575
|
-
# "f": 3.34609419
|
1576
|
-
# },
|
1577
|
-
# "price": {
|
1578
|
-
# "v": "410673",
|
1579
|
-
# "e": 6,
|
1580
|
-
# "f": 0.410673
|
1581
|
-
# },
|
1582
|
-
# "date": {
|
1583
|
-
# "unix": 1731505789,
|
1584
|
-
# "us": 911642,
|
1585
|
-
# "iso": "2024-11-13 13:49:49.911642",
|
1586
|
-
# "tz": "UTC",
|
1587
|
-
# "full": "1731505789911642",
|
1588
|
-
# "unixms": "1731505789911"
|
1589
|
-
# }
|
1590
|
-
# },
|
1591
|
-
# {
|
1592
|
-
# "id": "DOGE_USDC:1731505789:911642994:4",
|
1593
|
-
# "pair": "DOGE_USDC",
|
1594
|
-
# "bid": {
|
1595
|
-
# "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
|
1596
|
-
# },
|
1597
|
-
# "ask": {
|
1598
|
-
# "id": "mktor-cmtztk-3z3n-gupp-uqdg-74g4wjfq"
|
1599
|
-
# },
|
1600
|
-
# "type": "bid",
|
1601
|
-
# "amount": {
|
1602
|
-
# "v": "145453950",
|
1603
|
-
# "e": 8,
|
1604
|
-
# "f": 1.4545395
|
1605
|
-
# },
|
1606
|
-
# "price": {
|
1607
|
-
# "v": "412589",
|
1608
|
-
# "e": 6,
|
1609
|
-
# "f": 0.412589
|
1610
|
-
# },
|
1611
|
-
# "date": {
|
1612
|
-
# "unix": 1731505789,
|
1613
|
-
# "us": 911642,
|
1614
|
-
# "iso": "2024-11-13 13:49:49.911642",
|
1615
|
-
# "tz": "UTC",
|
1616
|
-
# "full": "1731505789911642",
|
1617
|
-
# "unixms": "1731505789911"
|
1618
|
-
# }
|
1619
|
-
# },
|
1620
|
-
# {
|
1621
|
-
# "id": "DOGE_USDC:1731505789:911642994:2",
|
1622
|
-
# "pair": "DOGE_USDC",
|
1623
|
-
# "bid": {
|
1624
|
-
# "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
|
1625
|
-
# },
|
1626
|
-
# "ask": {
|
1627
|
-
# "id": "mktor-6tyslh-b33b-flnm-2ata-acjkco4y"
|
1628
|
-
# },
|
1629
|
-
# "type": "bid",
|
1630
|
-
# "amount": {
|
1631
|
-
# "v": "587627076",
|
1632
|
-
# "e": 8,
|
1633
|
-
# "f": 5.87627076
|
1634
|
-
# },
|
1635
|
-
# "price": {
|
1636
|
-
# "v": "411005",
|
1637
|
-
# "e": 6,
|
1638
|
-
# "f": 0.411005
|
1639
|
-
# },
|
1640
|
-
# "date": {
|
1641
|
-
# "unix": 1731505789,
|
1642
|
-
# "us": 911642,
|
1643
|
-
# "iso": "2024-11-13 13:49:49.911642",
|
1644
|
-
# "tz": "UTC",
|
1645
|
-
# "full": "1731505789911642",
|
1646
|
-
# "unixms": "1731505789911"
|
1647
|
-
# }
|
1648
|
-
# },
|
1649
|
-
# {
|
1650
|
-
# "id": "DOGE_USDC:1731505789:911642994:1",
|
1651
|
-
# "pair": "DOGE_USDC",
|
1652
|
-
# "bid": {
|
1653
|
-
# "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
|
1654
|
-
# },
|
1655
|
-
# "ask": {
|
1656
|
-
# "id": "mktor-ihpjlj-5ufj-dm5l-fmud-oftkqcgu"
|
1657
|
-
# },
|
1658
|
-
# "type": "bid",
|
1659
|
-
# "amount": {
|
1660
|
-
# "v": "475845734",
|
1661
|
-
# "e": 8,
|
1662
|
-
# "f": 4.75845734
|
1663
|
-
# },
|
1664
|
-
# "price": {
|
1665
|
-
# "v": "410830",
|
1666
|
-
# "e": 6,
|
1667
|
-
# "f": 0.41083
|
1668
|
-
# },
|
1669
|
-
# "date": {
|
1670
|
-
# "unix": 1731505789,
|
1671
|
-
# "us": 911642,
|
1672
|
-
# "iso": "2024-11-13 13:49:49.911642",
|
1673
|
-
# "tz": "UTC",
|
1674
|
-
# "full": "1731505789911642",
|
1675
|
-
# "unixms": "1731505789911"
|
1676
|
-
# }
|
1677
|
-
# },
|
1678
|
-
# {
|
1679
|
-
# "id": "DOGE_USDC:1731505789:911642994:3",
|
1680
|
-
# "pair": "DOGE_USDC",
|
1681
|
-
# "bid": {
|
1682
|
-
# "id": "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4"
|
1683
|
-
# },
|
1684
|
-
# "ask": {
|
1685
|
-
# "id": "mktor-d2uyb3-nzsj-aevn-dikr-tq3sxhre"
|
1686
|
-
# },
|
1687
|
-
# "type": "bid",
|
1688
|
-
# "amount": {
|
1689
|
-
# "v": "641013461",
|
1690
|
-
# "e": 8,
|
1691
|
-
# "f": 6.41013461
|
1692
|
-
# },
|
1693
|
-
# "price": {
|
1694
|
-
# "v": "411846",
|
1695
|
-
# "e": 6,
|
1696
|
-
# "f": 0.411846
|
1697
|
-
# },
|
1698
|
-
# "date": {
|
1699
|
-
# "unix": 1731505789,
|
1700
|
-
# "us": 911642,
|
1701
|
-
# "iso": "2024-11-13 13:49:49.911642",
|
1702
|
-
# "tz": "UTC",
|
1703
|
-
# "full": "1731505789911642",
|
1704
|
-
# "unixms": "1731505789911"
|
1705
|
-
# }
|
1706
|
-
# }
|
1707
|
-
# ],
|
1708
|
-
# "access": {
|
1709
|
-
# "mkt-xrkg5l-akjz-cxxl-3a2e-mul5gfo4": {
|
1710
|
-
# "required": "r",
|
1711
|
-
# "available": "?"
|
1712
|
-
# },
|
1713
|
-
# "mktor-xb3ne5-emm5-fx7e-xggk-fyfoiye4": {
|
1714
|
-
# "required": "R",
|
1715
|
-
# "available": "O"
|
1716
|
-
# }
|
1717
|
-
# },
|
1718
|
-
# "paging": {
|
1719
|
-
# "page_no": 1,
|
1720
|
-
# "count": "5",
|
1721
|
-
# "page_max": 1,
|
1722
|
-
# "results_per_page": 20
|
1723
|
-
# }
|
1724
|
-
# }
|
1725
|
-
data = self.safe_list(response, 'data')
|
1726
|
-
return self.parse_trades(data, market, since, limit)
|
1727
|
-
|
1728
|
-
def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
|
1729
|
-
"""
|
1730
|
-
fetches a crypto deposit address for a specific currency
|
1731
|
-
|
1732
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.k7qe5aricayh
|
1733
|
-
|
1734
|
-
:param str code: unified currency code(e.g. "BTC", "ETH", "USDT")
|
1735
|
-
:param dict [params]: extra parameters specific to the EllipX API endpoint
|
1736
|
-
:returns dict: an address structure {
|
1737
|
-
'currency': string, # unified currency code
|
1738
|
-
'address': string, # the address for deposits
|
1739
|
-
'tag': string|None, # tag/memo for deposits if needed
|
1740
|
-
'network': object, # network object from currency info
|
1741
|
-
'info': object # raw response from exchange
|
1742
|
-
}
|
1743
|
-
:throws ExchangeError if: currency does not support deposits
|
1744
|
-
"""
|
1745
|
-
self.load_markets()
|
1746
|
-
currency = self.currency(code)
|
1747
|
-
network = self.safe_value(currency['info'], 'Crypto_Chain', None)
|
1748
|
-
request = {
|
1749
|
-
'Crypto_Token__': self.safe_string(network, 'Crypto_Token__'),
|
1750
|
-
'Crypto_Chain__': self.safe_string(network, 'Crypto_Chain__'),
|
1751
|
-
}
|
1752
|
-
response = self.privatePostCryptoAddressFetch(self.extend(request, params))
|
1753
|
-
data = self.safe_value(response, 'data', {})
|
1754
|
-
address = self.safe_string(data, 'Address')
|
1755
|
-
tag = self.safe_string(data, 'memo')
|
1756
|
-
self.check_address(address)
|
1757
|
-
return {
|
1758
|
-
'currency': code,
|
1759
|
-
'address': address,
|
1760
|
-
'tag': tag,
|
1761
|
-
'network': network,
|
1762
|
-
'info': response,
|
1763
|
-
}
|
1764
|
-
|
1765
|
-
def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
1766
|
-
"""
|
1767
|
-
Fetches the current trading fees(maker and taker) applicable to the user.
|
1768
|
-
|
1769
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.kki5jay2c8it
|
1770
|
-
|
1771
|
-
:param str [symbol]: Not used by EllipX are not symbol-specific.
|
1772
|
-
:param dict [params]: Extra parameters specific to the EllipX API endpoint.
|
1773
|
-
:returns Promise<dict>: A promise resolving to a unified trading fee structure:
|
1774
|
-
{
|
1775
|
-
'info': object, # the raw response from the exchange
|
1776
|
-
'symbol': None, # symbol is not used for self exchange
|
1777
|
-
'maker': number, # maker fee rate in decimal form
|
1778
|
-
'taker': number, # taker fee rate in decimal form
|
1779
|
-
'percentage': True, # indicates fees are in percentage
|
1780
|
-
'tierBased': False, # indicates fees do not vary by volume tiers
|
1781
|
-
}
|
1782
|
-
"""
|
1783
|
-
self.load_markets()
|
1784
|
-
response = self.privateGetMarketTradeFeeQuery(params)
|
1785
|
-
#
|
1786
|
-
# Example response:
|
1787
|
-
# {
|
1788
|
-
# "result": "success",
|
1789
|
-
# "data": {
|
1790
|
-
# "maker": 15.0, # in basis points
|
1791
|
-
# "taker": 25.0, # in basis points
|
1792
|
-
# "volume": 123456.78,
|
1793
|
-
# "promo": {
|
1794
|
-
# # promotional discounts if any
|
1795
|
-
# }
|
1796
|
-
# }
|
1797
|
-
# }
|
1798
|
-
#
|
1799
|
-
data = self.safe_value(response, 'data', {})
|
1800
|
-
maker = self.safe_number(data, 'maker') # in basis points
|
1801
|
-
taker = self.safe_number(data, 'taker') # in basis points
|
1802
|
-
makerFee = maker / 10000 if (maker is not None) else None
|
1803
|
-
takerFee = taker / 10000 if (taker is not None) else None
|
1804
|
-
return {
|
1805
|
-
'info': response,
|
1806
|
-
'symbol': None, # the exchange only have separate fees for stablecoin pairs
|
1807
|
-
'maker': makerFee,
|
1808
|
-
'taker': takerFee,
|
1809
|
-
'percentage': True, # fees are expressed in percentages
|
1810
|
-
'tierBased': True, # fees can vary based on volume tiers
|
1811
|
-
}
|
1812
|
-
|
1813
|
-
def withdraw(self, code: str, amount: float, address: str, tag: Str = None, params={}) -> Transaction:
|
1814
|
-
"""
|
1815
|
-
Make a withdrawal request
|
1816
|
-
|
1817
|
-
https://docs.google.com/document/d/1ZXzTQYffKE_EglTaKptxGQERRnunuLHEMmar7VC9syM/edit?tab=t.0#heading=h.zegupoa8g4t9
|
1818
|
-
|
1819
|
-
:param str code: unified currency code
|
1820
|
-
:param number amount: Amount to withdraw
|
1821
|
-
:param str address: Destination wallet address
|
1822
|
-
:param str [tag]: Additional tag/memo for currencies that require it
|
1823
|
-
:param dict params: Extra parameters specific to the EllipX API endpoint(Crypto_Chain__, Unit__)
|
1824
|
-
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1825
|
-
"""
|
1826
|
-
self.check_address(address)
|
1827
|
-
self.load_markets()
|
1828
|
-
currency = self.currency(code)
|
1829
|
-
networks = self.safe_value(currency, 'networks')
|
1830
|
-
if networks is None:
|
1831
|
-
raise NotSupported(self.id + ' withdraw() for ' + code + ' is not supported')
|
1832
|
-
chainsResponse = self.privateGetUnitCurrency({'currency': currency['code']}) # fetch Unit__ params for currency
|
1833
|
-
chainsData = self.safe_value(chainsResponse, 'data', [])
|
1834
|
-
unit = self.safe_string(chainsData, 'Unit__')
|
1835
|
-
# check params again and omit params
|
1836
|
-
self.omit(params, 'Unit__')
|
1837
|
-
self.omit(params, 'Crypto_Chain__')
|
1838
|
-
amountString = str(amount)
|
1839
|
-
request = {
|
1840
|
-
'Unit__': unit,
|
1841
|
-
'amount': amountString,
|
1842
|
-
'address': address,
|
1843
|
-
'Crypto_Chain__': networks['id'],
|
1844
|
-
}
|
1845
|
-
if tag is not None:
|
1846
|
-
request['memo'] = tag
|
1847
|
-
response = self.privatePostCryptoDisbursementWithdraw(self.extend(request, params))
|
1848
|
-
# {
|
1849
|
-
# Crypto_Disbursement__: "crdsb-4pw3kg-ipn5-amvb-da4n-6xncy4r4",
|
1850
|
-
# Crypto_Token__: "crtok-dnehz4-wbgv-bunf-iyd3-m7gtsz2q",
|
1851
|
-
# Crypto_Chain__: "chain-kjfvwn-l2xn-eclc-ul5d-mb6fu5hm",
|
1852
|
-
# User__: "usr-5oint6-ozpr-alfp-2wxi-zgbm4osy",
|
1853
|
-
# Value: {
|
1854
|
-
# v: "1000000000",
|
1855
|
-
# e: "8",
|
1856
|
-
# f: "10",
|
1857
|
-
# },
|
1858
|
-
# Value_USD: "4.08723",
|
1859
|
-
# Address: "D6z62LUwyNBi3QbPkzW8C4m7VDAgu9wb2Z",
|
1860
|
-
# Status: "pending",
|
1861
|
-
# Transaction: null,
|
1862
|
-
# Requested: {
|
1863
|
-
# unix: "1731570982",
|
1864
|
-
# us: "203569",
|
1865
|
-
# iso: "2024-11-14 07:56:22.203569",
|
1866
|
-
# tz: "UTC",
|
1867
|
-
# full: "1731570982203569",
|
1868
|
-
# unixms: "1731570982203",
|
1869
|
-
# },
|
1870
|
-
# Scheduled: null,
|
1871
|
-
# Processed: null,
|
1872
|
-
# Amount: {
|
1873
|
-
# value: "10.00000000",
|
1874
|
-
# value_int: "1000000000",
|
1875
|
-
# value_disp: "10.00000000",
|
1876
|
-
# value_xint: {
|
1877
|
-
# v: "1000000000",
|
1878
|
-
# e: "8",
|
1879
|
-
# f: "10",
|
1880
|
-
# },
|
1881
|
-
# display: "10.00000000DOGE",
|
1882
|
-
# display_short: "10.00000000DOGE",
|
1883
|
-
# currency: "DOGE",
|
1884
|
-
# unit: "DOGE",
|
1885
|
-
# has_vat: False,
|
1886
|
-
# tax_profile: null,
|
1887
|
-
# raw: {
|
1888
|
-
# value: "10.00000000",
|
1889
|
-
# value_int: "1000000000",
|
1890
|
-
# value_disp: "10.00000000",
|
1891
|
-
# value_xint: {
|
1892
|
-
# v: "1000000000",
|
1893
|
-
# e: "8",
|
1894
|
-
# f: "10",
|
1895
|
-
# },
|
1896
|
-
# display: "10.00000000DOGE",
|
1897
|
-
# display_short: "10.00000000DOGE",
|
1898
|
-
# currency: "DOGE",
|
1899
|
-
# unit: "DOGE",
|
1900
|
-
# has_vat: False,
|
1901
|
-
# tax_profile: null,
|
1902
|
-
# },
|
1903
|
-
# tax: {
|
1904
|
-
# value: "10.00000000",
|
1905
|
-
# value_int: "1000000000",
|
1906
|
-
# value_disp: "10.00000000",
|
1907
|
-
# value_xint: {
|
1908
|
-
# v: "1000000000",
|
1909
|
-
# e: "8",
|
1910
|
-
# f: "10",
|
1911
|
-
# },
|
1912
|
-
# display: "10.00000000DOGE",
|
1913
|
-
# display_short: "10.00000000DOGE",
|
1914
|
-
# currency: "DOGE",
|
1915
|
-
# unit: "DOGE",
|
1916
|
-
# has_vat: True,
|
1917
|
-
# tax_profile: null,
|
1918
|
-
# },
|
1919
|
-
# tax_only: {
|
1920
|
-
# value: "0.000",
|
1921
|
-
# value_int: "0",
|
1922
|
-
# value_disp: "0",
|
1923
|
-
# value_xint: {
|
1924
|
-
# v: "0",
|
1925
|
-
# e: "3",
|
1926
|
-
# f: "0",
|
1927
|
-
# },
|
1928
|
-
# display: "¥0",
|
1929
|
-
# display_short: "¥0",
|
1930
|
-
# currency: "JPY",
|
1931
|
-
# unit: "JPY",
|
1932
|
-
# has_vat: False,
|
1933
|
-
# tax_profile: null,
|
1934
|
-
# },
|
1935
|
-
# tax_rate: "0",
|
1936
|
-
# },
|
1937
|
-
# }
|
1938
|
-
data = self.safe_dict(response, 'data')
|
1939
|
-
amountResponse = self.safe_dict(data, 'Amount')
|
1940
|
-
requested = self.safe_dict(data, 'Requested')
|
1941
|
-
processed = self.safe_dict(data, 'Processed')
|
1942
|
-
withdrawId = self.safe_string(data, 'Crypto_Disbursement__')
|
1943
|
-
timestamp = self.safe_integer(requested, 'unixms')
|
1944
|
-
return {
|
1945
|
-
'info': response,
|
1946
|
-
'id': withdrawId,
|
1947
|
-
'txid': None,
|
1948
|
-
'timestamp': timestamp,
|
1949
|
-
'datetime': self.iso8601(timestamp),
|
1950
|
-
'network': self.safe_string(data, 'Crypto_Chain__'),
|
1951
|
-
'address': self.safe_string(data, 'Address'),
|
1952
|
-
'addressTo': self.safe_string(data, 'Address'),
|
1953
|
-
'addressFrom': None,
|
1954
|
-
'tag': tag,
|
1955
|
-
'tagTo': tag,
|
1956
|
-
'tagFrom': None,
|
1957
|
-
'type': 'withdrawal',
|
1958
|
-
'amount': self.safe_number(amountResponse, 'value'),
|
1959
|
-
'currency': code,
|
1960
|
-
'status': self.parse_transaction_status(self.safe_string(data, 'Status')),
|
1961
|
-
'updated': self.safe_timestamp(processed, 'unix'),
|
1962
|
-
'internal': False,
|
1963
|
-
'comment': None,
|
1964
|
-
'fee': {
|
1965
|
-
'currency': code,
|
1966
|
-
'cost': None, # Fee information not provided in response
|
1967
|
-
'rate': None,
|
1968
|
-
},
|
1969
|
-
}
|
1970
|
-
|
1971
|
-
def parse_transaction_status(self, status: str) -> str:
|
1972
|
-
statuses = {
|
1973
|
-
'pending': 'pending',
|
1974
|
-
'completed': 'ok',
|
1975
|
-
'failed': 'failed',
|
1976
|
-
'cancelled': 'canceled',
|
1977
|
-
}
|
1978
|
-
return self.safe_string(statuses, status, status)
|
1979
|
-
|
1980
|
-
def parse_order_status(self, status):
|
1981
|
-
statuses = {
|
1982
|
-
'pending': 'open', # starting state of all orders
|
1983
|
-
'running': 'open', # when order is being executed
|
1984
|
-
'post-pending': 'open', # post-only order waiting to be placed
|
1985
|
-
'open': 'open', # active order in the orderbook
|
1986
|
-
'stop': 'open', # when stop order not yet triggered
|
1987
|
-
'invalid': 'rejected', # order rejected
|
1988
|
-
'done': 'closed', # order fully executed
|
1989
|
-
'cancel': 'canceled', # order canceled by user
|
1990
|
-
'canceled': 'canceled', # alternative spelling
|
1991
|
-
}
|
1992
|
-
return self.safe_string(statuses, status, status)
|
1993
|
-
|
1994
|
-
def parse_amount(self, amount) -> Str:
|
1995
|
-
v = self.safe_string(amount, 'v', None)
|
1996
|
-
e = self.safe_integer(amount, 'e', None)
|
1997
|
-
if v is None or e is None:
|
1998
|
-
return None
|
1999
|
-
precise = Precise(v)
|
2000
|
-
precise.decimals = e
|
2001
|
-
precise.reduce()
|
2002
|
-
amountString = str(precise)
|
2003
|
-
return amountString
|
2004
|
-
|
2005
|
-
def to_amount(self, amount: float, precision: float) -> dict:
|
2006
|
-
v = str(amount)
|
2007
|
-
e = precision
|
2008
|
-
return {
|
2009
|
-
'v': v,
|
2010
|
-
'e': e,
|
2011
|
-
}
|
2012
|
-
|
2013
|
-
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
2014
|
-
# {
|
2015
|
-
# "code": 404,
|
2016
|
-
# "error": "Not Found: Crypto\\Token(US)",
|
2017
|
-
# "exception": "Exception\\NotFound",
|
2018
|
-
# "message": "[I18N:error_not_found]",
|
2019
|
-
# "request": "cc83738a-2438-4f53-ae44-f15306c07f32",
|
2020
|
-
# "result": "error",
|
2021
|
-
# "time": 0.0089569091796875,
|
2022
|
-
# "token": "error_not_found"
|
2023
|
-
# }
|
2024
|
-
errorCode = self.safe_string(response, 'code')
|
2025
|
-
message = self.safe_string(response, 'message')
|
2026
|
-
if errorCode is not None:
|
2027
|
-
self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, message)
|
2028
|
-
raise ExchangeError(self.id + ' ' + message)
|
2029
|
-
return None
|