ccxt 3.1.60__py2.py3-none-any.whl → 4.0.3__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 -1
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/base/exchange.py +1 -1
- ccxt/pro/__init__.py +1 -1
- {ccxt-3.1.60.dist-info → ccxt-4.0.3.dist-info}/METADATA +4 -4
- {ccxt-3.1.60.dist-info → ccxt-4.0.3.dist-info}/RECORD +9 -23
- ccxt/async_support/btcex.py +0 -2519
- ccxt/async_support/buda.py +0 -1063
- ccxt/async_support/itbit.py +0 -771
- ccxt/async_support/ripio.py +0 -1102
- ccxt/async_support/stex.py +0 -2508
- ccxt/async_support/xt.py +0 -4420
- ccxt/async_support/zb.py +0 -4127
- ccxt/btcex.py +0 -2519
- ccxt/buda.py +0 -1063
- ccxt/itbit.py +0 -771
- ccxt/ripio.py +0 -1102
- ccxt/stex.py +0 -2508
- ccxt/xt.py +0 -4419
- ccxt/zb.py +0 -4126
- {ccxt-3.1.60.dist-info → ccxt-4.0.3.dist-info}/WHEEL +0 -0
- {ccxt-3.1.60.dist-info → ccxt-4.0.3.dist-info}/top_level.txt +0 -0
ccxt/stex.py
DELETED
@@ -1,2508 +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.stex import ImplicitAPI
|
8
|
-
from ccxt.base.types import OrderSide
|
9
|
-
from typing import Optional
|
10
|
-
from typing import List
|
11
|
-
from ccxt.base.errors import ExchangeError
|
12
|
-
from ccxt.base.errors import PermissionDenied
|
13
|
-
from ccxt.base.errors import AccountSuspended
|
14
|
-
from ccxt.base.errors import ArgumentsRequired
|
15
|
-
from ccxt.base.errors import BadRequest
|
16
|
-
from ccxt.base.errors import BadSymbol
|
17
|
-
from ccxt.base.errors import InsufficientFunds
|
18
|
-
from ccxt.base.errors import InvalidOrder
|
19
|
-
from ccxt.base.errors import OrderNotFound
|
20
|
-
from ccxt.base.errors import DDoSProtection
|
21
|
-
from ccxt.base.errors import AuthenticationError
|
22
|
-
from ccxt.base.decimal_to_precision import TICK_SIZE
|
23
|
-
from ccxt.base.precise import Precise
|
24
|
-
|
25
|
-
|
26
|
-
class stex(Exchange, ImplicitAPI):
|
27
|
-
|
28
|
-
def describe(self):
|
29
|
-
return self.deep_extend(super(stex, self).describe(), {
|
30
|
-
'id': 'stex',
|
31
|
-
'name': 'STEX', # formerly known.exchange
|
32
|
-
'countries': ['EE'], # Estonia
|
33
|
-
'rateLimit': 1000 / 3, # https://help.stex.com/en/articles/2815043-api-3-rate-limits
|
34
|
-
'certified': False,
|
35
|
-
# new metainfo interface
|
36
|
-
'has': {
|
37
|
-
'CORS': None,
|
38
|
-
'spot': True,
|
39
|
-
'margin': False,
|
40
|
-
'swap': False,
|
41
|
-
'future': False,
|
42
|
-
'option': False,
|
43
|
-
'addMargin': False,
|
44
|
-
'cancelAllOrders': True,
|
45
|
-
'cancelOrder': True,
|
46
|
-
'createDepositAddress': True,
|
47
|
-
'createMarketOrder': False,
|
48
|
-
'createOrder': True,
|
49
|
-
'createReduceOnlyOrder': False,
|
50
|
-
'fetchBalance': True,
|
51
|
-
'fetchBorrowRate': False,
|
52
|
-
'fetchBorrowRateHistories': False,
|
53
|
-
'fetchBorrowRateHistory': False,
|
54
|
-
'fetchBorrowRates': False,
|
55
|
-
'fetchBorrowRatesPerSymbol': False,
|
56
|
-
'fetchClosedOrder': True,
|
57
|
-
'fetchCurrencies': True,
|
58
|
-
'fetchDeposit': True,
|
59
|
-
'fetchDepositAddress': True,
|
60
|
-
'fetchDeposits': True,
|
61
|
-
'fetchDepositWithdrawFee': 'emulated',
|
62
|
-
'fetchDepositWithdrawFees': True,
|
63
|
-
'fetchFundingHistory': False,
|
64
|
-
'fetchFundingRate': False,
|
65
|
-
'fetchFundingRateHistory': False,
|
66
|
-
'fetchFundingRates': False,
|
67
|
-
'fetchIndexOHLCV': False,
|
68
|
-
'fetchLeverage': False,
|
69
|
-
'fetchLeverageTiers': False,
|
70
|
-
'fetchMarginMode': False,
|
71
|
-
'fetchMarkets': True,
|
72
|
-
'fetchMarkOHLCV': False,
|
73
|
-
'fetchMyTrades': True,
|
74
|
-
'fetchOHLCV': True,
|
75
|
-
'fetchOpenInterestHistory': False,
|
76
|
-
'fetchOpenOrders': True,
|
77
|
-
'fetchOrder': True,
|
78
|
-
'fetchOrderBook': True,
|
79
|
-
'fetchOrderTrades': True,
|
80
|
-
'fetchPosition': False,
|
81
|
-
'fetchPositionMode': False,
|
82
|
-
'fetchPositions': False,
|
83
|
-
'fetchPositionsRisk': False,
|
84
|
-
'fetchPremiumIndexOHLCV': False,
|
85
|
-
'fetchTicker': True,
|
86
|
-
'fetchTickers': True,
|
87
|
-
'fetchTime': True,
|
88
|
-
'fetchTrades': True,
|
89
|
-
'fetchTradingFee': True,
|
90
|
-
'fetchTradingFees': False,
|
91
|
-
'fetchTransactionFees': True,
|
92
|
-
'fetchWithdrawal': True,
|
93
|
-
'fetchWithdrawals': True,
|
94
|
-
'reduceMargin': False,
|
95
|
-
'setLeverage': False,
|
96
|
-
'setMarginMode': False,
|
97
|
-
'setPositionMode': False,
|
98
|
-
'transfer': True,
|
99
|
-
'withdraw': True,
|
100
|
-
},
|
101
|
-
'version': 'v3',
|
102
|
-
'urls': {
|
103
|
-
'logo': 'https://user-images.githubusercontent.com/1294454/69680782-03fd0b80-10bd-11ea-909e-7f603500e9cc.jpg',
|
104
|
-
'api': {
|
105
|
-
'rest': 'https://api3.stex.com',
|
106
|
-
},
|
107
|
-
'www': 'https://www.stex.com',
|
108
|
-
'doc': [
|
109
|
-
'https://apidocs.stex.com/',
|
110
|
-
'https://help.stex.com/en/collections/1593608-api-v3-documentation',
|
111
|
-
],
|
112
|
-
'fees': 'https://app.stex.com/en/pairs-specification',
|
113
|
-
'referral': 'https://app.stex.com?ref=36416021',
|
114
|
-
},
|
115
|
-
'requiredCredentials': {
|
116
|
-
'apiKey': False,
|
117
|
-
'secret': False,
|
118
|
-
'token': True,
|
119
|
-
},
|
120
|
-
'timeframes': {
|
121
|
-
'1m': '1',
|
122
|
-
'5m': '5',
|
123
|
-
'30m': '30',
|
124
|
-
'1h': '60',
|
125
|
-
'4h': '240',
|
126
|
-
'12h': '720',
|
127
|
-
'1d': '1D', # default
|
128
|
-
},
|
129
|
-
'api': {
|
130
|
-
'public': {
|
131
|
-
'get': {
|
132
|
-
'currencies': 1, # Available Currencies
|
133
|
-
'currencies/{currencyId}': 1, # Get currency info
|
134
|
-
'markets': 1, # Available markets
|
135
|
-
'pairs-groups': 1, # Available currency pairs groups(as displayed at stex trading page)
|
136
|
-
'currency_pairs/list/{code}': 1, # Available currency pairs
|
137
|
-
'currency_pairs/group/{currencyPairGroupId}': 1, # Available currency pairs for a given group
|
138
|
-
'currency_pairs/{currencyPairId}': 1, # Get currency pair information
|
139
|
-
'ticker': 1, # Tickers list for all currency pairs
|
140
|
-
'ticker/{currencyPairId}': 1, # Ticker for currency pair
|
141
|
-
'trades/{currencyPairId}': 1, # Trades for given currency pair
|
142
|
-
'orderbook/{currencyPairId}': 1, # Orderbook for given currency pair
|
143
|
-
'chart/{currencyPairId}/{candlesType}': 1, # A list of candles for given currency pair
|
144
|
-
'deposit-statuses': 1, # Available Deposit Statuses
|
145
|
-
'deposit-statuses/{statusId}': 1, # Get deposit status info
|
146
|
-
'withdrawal-statuses': 1, # Available Withdrawal Statuses
|
147
|
-
'withdrawal-statuses/{statusId}': 1, # Get status info
|
148
|
-
'ping': 1, # Test API is working and get server time
|
149
|
-
'mobile-versions': 1, # Shows the official mobile applications data
|
150
|
-
'twitter': 1, # Get the last 20 posts(stex.com) on Twitter
|
151
|
-
},
|
152
|
-
},
|
153
|
-
'trading': {
|
154
|
-
'get': {
|
155
|
-
'fees/{currencyPairId}': 1, # Returns the user's fees for a given currency pair
|
156
|
-
'orders': 12, # List your currently open orders
|
157
|
-
'orders/{currencyPairId}': 6, # List your currently open orders for given currency pair
|
158
|
-
'order/{orderId}': 12, # Get a single order
|
159
|
-
},
|
160
|
-
'post': {
|
161
|
-
'orders/{currencyPairId}': 1.5, # Create new order and put it to the orders processing queue
|
162
|
-
'orders/bulk/{currencyPairId}': 12, # Create new orders in a bulk and put it to the orders processing queue
|
163
|
-
},
|
164
|
-
'delete': {
|
165
|
-
'orders': 30, # Delete all active orders
|
166
|
-
'orders/{currencyPairId}': 12, # Delete active orders for given currency pair
|
167
|
-
'order/{orderId}': 1.5, # Cancel order
|
168
|
-
},
|
169
|
-
},
|
170
|
-
'reports': {
|
171
|
-
'get': {
|
172
|
-
'currencies': 12, # Get a list of currencies user had any activity in
|
173
|
-
'currency_pairs': 12, # Gets the list of currency pairs the user had orders in for all the time
|
174
|
-
'orders': 12, # Get past orders
|
175
|
-
'orders/{orderId}': 12, # Get specified order details
|
176
|
-
'trades/{currencyPairId}': 12, # Get a list of user trades according to request parameters
|
177
|
-
'background/{listMode}': 12, # Get reports list for category
|
178
|
-
'background/{id}': 12, # Get some report info
|
179
|
-
'background/download/{id}': 12, # Get file by id
|
180
|
-
},
|
181
|
-
'post': {
|
182
|
-
'background/create': 12, # Create new report
|
183
|
-
},
|
184
|
-
'delete': {
|
185
|
-
'background/{id}': 12, # Remove report by id
|
186
|
-
},
|
187
|
-
},
|
188
|
-
'profile': {
|
189
|
-
'get': {
|
190
|
-
'info': 3, # Account information
|
191
|
-
'wallets': 3, # Get a list of user wallets
|
192
|
-
'wallets/{walletId}': 3, # Single wallet information
|
193
|
-
'wallets/address/{walletId}': 3, # Get deposit address for given wallet
|
194
|
-
'deposits': 3, # Get a list of deposits made by user
|
195
|
-
'deposits/{id}': 3, # Get deposit by id
|
196
|
-
'rewards': 3, # Get a list of rewards obtained by user(e.g. in trading competitions)
|
197
|
-
'rewards/{id}': 3, # Get reward by id
|
198
|
-
'addressbook': 3, # Get a list of user address book items
|
199
|
-
'addressbook/{itemId}': 3, # Single address book item
|
200
|
-
'withdrawals': 3, # Get a list of withdrawals made by user
|
201
|
-
'withdrawals/{id}': 3, # Get withdrawal by id
|
202
|
-
'notifications': 3, # Get notifications
|
203
|
-
'notifications/price': 3, # Get a list of active price alerts
|
204
|
-
'favorite/currency_pairs': 3, # Get favorite currency pairs
|
205
|
-
'token-scopes': 3, # Get current token scopes
|
206
|
-
},
|
207
|
-
'post': {
|
208
|
-
'wallets/burn/{walletId}': 3, # Burns the given wallet
|
209
|
-
'wallets/{walletId}/hold_amount': 3, # Move a part of the funds on the wallet to the "hold" to keep it safe from trading
|
210
|
-
'wallets/{currencyId}': 3, # Create a wallet for given currency
|
211
|
-
'wallets/address/{walletId}': 3, # Create new deposit address
|
212
|
-
'addressbook/disable_item/{itemId}': 3, # Disables the address book item
|
213
|
-
'addressbook/enable_item/{itemId}': 3, # Enable the address book item
|
214
|
-
'addressbook/enable_strict_wd': 3, # Restrict the withdrawals to only addresses that are active in addressbook
|
215
|
-
'addressbook/disable_strict_wd': 3, # Remove restriction to withdraw to only addresses that are active in addressbook. E.g. allow to withdraw to any address.
|
216
|
-
'withdraw': 30, # Create withdrawal request
|
217
|
-
'notifications/price': 3, # Create new price alert
|
218
|
-
'referral/program': 3, # Create referral program
|
219
|
-
'referral/insert/{code}': 3, # Insert referral code
|
220
|
-
'referral/bonus_transfer/{currencyId}': 3, # Transfer referral bonuses balance to main balance for given currency
|
221
|
-
},
|
222
|
-
'put': {
|
223
|
-
'favorite/currency_pairs/set': 3, # Set favorite currency pairs
|
224
|
-
},
|
225
|
-
'delete': {
|
226
|
-
'addressbook/{itemId}': 3, # Deletes address book item
|
227
|
-
'withdraw/{withdrawalId}': 30, # Cancel unconfirmed withdrawal
|
228
|
-
'notifications/price/{priceAlertId}': 3, # Delete the price alert by ID
|
229
|
-
},
|
230
|
-
},
|
231
|
-
'verification': {
|
232
|
-
'get': {
|
233
|
-
'countries': 1, # Countries list, beta
|
234
|
-
'status': 1, # Get status verify
|
235
|
-
'fractal/url': 1, # Generate verify url from Fractal
|
236
|
-
'smart-id': 1, # Check Smart-ID verify
|
237
|
-
'stex': 1, # Get information about your KYC, beta
|
238
|
-
'cryptonomica/code': 1, # Get Discount code for Cryptonomica
|
239
|
-
},
|
240
|
-
'post': {
|
241
|
-
'smart-id': 1, # Initialization Smart-ID verify(Send request to Smart-ID App)
|
242
|
-
'stex': 1, # Update information regarding of your KYC verification, beta
|
243
|
-
'cryptonomica': 1, # Add verification from Cryptonomica
|
244
|
-
},
|
245
|
-
},
|
246
|
-
'settings': {
|
247
|
-
'get': {
|
248
|
-
'notifications/{event}': 1, # User event notification settings
|
249
|
-
'notifications': 1, # User events notification settings
|
250
|
-
},
|
251
|
-
'put': {
|
252
|
-
'notifications': 1, # Set notification settings
|
253
|
-
'notifications/set': 1,
|
254
|
-
},
|
255
|
-
},
|
256
|
-
},
|
257
|
-
'fees': {
|
258
|
-
'trading': {
|
259
|
-
'tierBased': False,
|
260
|
-
'percentage': True,
|
261
|
-
'taker': self.parse_number('0.002'),
|
262
|
-
'maker': self.parse_number('0.002'),
|
263
|
-
},
|
264
|
-
},
|
265
|
-
'commonCurrencies': {
|
266
|
-
'BC': 'Bitcoin Confidential',
|
267
|
-
'BITS': 'Bitcoinus',
|
268
|
-
'BITSW': 'BITS',
|
269
|
-
'BHD': 'Bithold',
|
270
|
-
'BTH': 'Bithereum',
|
271
|
-
'MPH': 'Chasyr Token',
|
272
|
-
'SBTC': 'SBTCT', # SiamBitcoin
|
273
|
-
},
|
274
|
-
'options': {
|
275
|
-
'parseOrderToPrecision': False,
|
276
|
-
'networks': {
|
277
|
-
'ERC20': 5,
|
278
|
-
'ETH': 5,
|
279
|
-
'OMNI': 10,
|
280
|
-
'XLM': 20,
|
281
|
-
'BEP2': 22,
|
282
|
-
'TRC20': 24,
|
283
|
-
'TRX': 24,
|
284
|
-
'SOL': 25,
|
285
|
-
'BEP20': 501,
|
286
|
-
},
|
287
|
-
'accountsByType': {
|
288
|
-
'spot': 'spot',
|
289
|
-
'hold': 'hold',
|
290
|
-
'funding': 'funding',
|
291
|
-
'referal': 'referal',
|
292
|
-
},
|
293
|
-
'transfer': {
|
294
|
-
'fillResponseFromRequest': True,
|
295
|
-
},
|
296
|
-
},
|
297
|
-
'precisionMode': TICK_SIZE,
|
298
|
-
'exceptions': {
|
299
|
-
'exact': {
|
300
|
-
# {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}}
|
301
|
-
# {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}}
|
302
|
-
'Wrong parameters': BadRequest,
|
303
|
-
'Unauthenticated.': AuthenticationError, # {"message":"Unauthenticated."}
|
304
|
-
'Server Error': ExchangeError, # {"message": "Server Error"}
|
305
|
-
'This feature is only enabled for users verifies by Cryptonomica': PermissionDenied, # {"success":false,"message":"This feature is only enabled for users verifies by Cryptonomica"}
|
306
|
-
'Too Many Attempts.': DDoSProtection, # {"message": "Too Many Attempts."}
|
307
|
-
'Selected Pair is disabled': BadSymbol, # {"success":false,"message":"Selected Pair is disabled"}
|
308
|
-
'Invalid scope(s) provided.': PermissionDenied, # {"message": "Invalid scope(s) provided."}
|
309
|
-
'The maximum amount of open orders with the same price cannot exceed 10': InvalidOrder, # {"success":false,"message":"The maximum amount of open orders with the same price cannot exceed 10"}
|
310
|
-
'Your account not verified!': AccountSuspended, # {"success":false,"message":"Your account not verified!","unified_message":{"message_id":"verification_required_to_continue","substitutions":null},"notice":"Please be informed that parameter `message` is deprecated and will be removed. Use unified_message instead."}
|
311
|
-
},
|
312
|
-
'broad': {
|
313
|
-
'Not enough': InsufficientFunds, # {"success":false,"message":"Not enough ETH"}
|
314
|
-
},
|
315
|
-
},
|
316
|
-
})
|
317
|
-
|
318
|
-
def fetch_currencies(self, params={}):
|
319
|
-
"""
|
320
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1currencies/get
|
321
|
-
fetches all available currencies on an exchange
|
322
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
323
|
-
:returns dict: an associative dictionary of currencies
|
324
|
-
"""
|
325
|
-
response = self.publicGetCurrencies(params)
|
326
|
-
#
|
327
|
-
# {
|
328
|
-
# "success":true,
|
329
|
-
# "data":[
|
330
|
-
# {
|
331
|
-
# "id":1,
|
332
|
-
# "code":"BTC",
|
333
|
-
# "name":"Bitcoin",
|
334
|
-
# "active":true,
|
335
|
-
# "delisted":false,
|
336
|
-
# "precision":8,
|
337
|
-
# "minimum_tx_confirmations":1,
|
338
|
-
# "minimum_withdrawal_amount":"0.00200000",
|
339
|
-
# "minimum_deposit_amount":"0.00000000",
|
340
|
-
# "deposit_fee_currency_id":1,
|
341
|
-
# "deposit_fee_currency_code":"BTC",
|
342
|
-
# "deposit_fee_const":"0.00000000",
|
343
|
-
# "deposit_fee_percent":"0.00000000",
|
344
|
-
# "withdrawal_fee_currency_id":1,
|
345
|
-
# "withdrawal_fee_currency_code":"BTC",
|
346
|
-
# "withdrawal_fee_const":"0.00100000",
|
347
|
-
# "withdrawal_fee_percent":"0.00000000",
|
348
|
-
# "block_explorer_url":"https:\/\/blockchain.info\/tx\/",
|
349
|
-
# "protocol_specific_settings":null
|
350
|
-
# },
|
351
|
-
# ]
|
352
|
-
# }
|
353
|
-
#
|
354
|
-
result = {}
|
355
|
-
currencies = self.safe_value(response, 'data', [])
|
356
|
-
for i in range(0, len(currencies)):
|
357
|
-
currency = currencies[i]
|
358
|
-
id = self.safe_string(currency, 'id')
|
359
|
-
numericId = self.safe_integer(currency, 'id')
|
360
|
-
# todo: will need to rethink the fees
|
361
|
-
# to add support for multiple withdrawal/deposit methods and
|
362
|
-
# differentiated fees for each particular method
|
363
|
-
code = self.safe_currency_code(self.safe_string(currency, 'code'))
|
364
|
-
precision = self.parse_number(self.parse_precision(self.safe_string(currency, 'precision')))
|
365
|
-
fee = self.safe_number(currency, 'withdrawal_fee_const') # todo: redesign
|
366
|
-
active = self.safe_value(currency, 'active', True)
|
367
|
-
result[code] = {
|
368
|
-
'id': id,
|
369
|
-
'numericId': numericId,
|
370
|
-
'code': code,
|
371
|
-
'info': currency,
|
372
|
-
'type': None,
|
373
|
-
'name': self.safe_string(currency, 'name'),
|
374
|
-
'active': active,
|
375
|
-
'deposit': None,
|
376
|
-
'withdraw': None,
|
377
|
-
'fee': fee,
|
378
|
-
'precision': precision,
|
379
|
-
'limits': {
|
380
|
-
'amount': {
|
381
|
-
'min': precision,
|
382
|
-
'max': None,
|
383
|
-
},
|
384
|
-
'deposit': {
|
385
|
-
'min': self.safe_number(currency, 'minimum_deposit_amount'),
|
386
|
-
'max': None,
|
387
|
-
},
|
388
|
-
'withdraw': {
|
389
|
-
'min': self.safe_number(currency, 'minimum_withdrawal_amount'),
|
390
|
-
'max': None,
|
391
|
-
},
|
392
|
-
},
|
393
|
-
'networks': {},
|
394
|
-
}
|
395
|
-
return result
|
396
|
-
|
397
|
-
def fetch_markets(self, params={}):
|
398
|
-
"""
|
399
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1currency_pairs~1list~1{code}/get
|
400
|
-
retrieves data on all markets for stex
|
401
|
-
:param dict params: extra parameters specific to the exchange api endpoint
|
402
|
-
:returns [dict]: an array of objects representing market data
|
403
|
-
"""
|
404
|
-
request = {
|
405
|
-
'code': 'ALL',
|
406
|
-
}
|
407
|
-
response = self.publicGetCurrencyPairsListCode(self.extend(request, params))
|
408
|
-
#
|
409
|
-
# {
|
410
|
-
# "success":true,
|
411
|
-
# "data":[
|
412
|
-
# {
|
413
|
-
# "id":935,
|
414
|
-
# "currency_id":662,
|
415
|
-
# "currency_code":"ABET",
|
416
|
-
# "currency_name":"Altbet",
|
417
|
-
# "market_currency_id":1,
|
418
|
-
# "market_code":"BTC",
|
419
|
-
# "market_name":"Bitcoin",
|
420
|
-
# "min_order_amount":"0.00000010",
|
421
|
-
# "min_buy_price":"0.00000001",
|
422
|
-
# "min_sell_price":"0.00000001",
|
423
|
-
# "buy_fee_percent":"0.20000000",
|
424
|
-
# "sell_fee_percent":"0.20000000",
|
425
|
-
# "active":true,
|
426
|
-
# "delisted":false,
|
427
|
-
# "pair_message":"",
|
428
|
-
# "currency_precision":8,
|
429
|
-
# "market_precision":8,
|
430
|
-
# "symbol":"ABET_BTC",
|
431
|
-
# "group_name":"BTC",
|
432
|
-
# "group_id":1
|
433
|
-
# }
|
434
|
-
# ]
|
435
|
-
# }
|
436
|
-
#
|
437
|
-
result = []
|
438
|
-
markets = self.safe_value(response, 'data', [])
|
439
|
-
for i in range(0, len(markets)):
|
440
|
-
market = markets[i]
|
441
|
-
id = self.safe_string(market, 'id')
|
442
|
-
numericId = self.safe_integer(market, 'id')
|
443
|
-
baseId = self.safe_string(market, 'currency_id')
|
444
|
-
quoteId = self.safe_string(market, 'market_currency_id')
|
445
|
-
baseNumericId = self.safe_integer(market, 'currency_id')
|
446
|
-
quoteNumericId = self.safe_integer(market, 'market_currency_id')
|
447
|
-
base = self.safe_currency_code(self.safe_string(market, 'currency_code'))
|
448
|
-
quote = self.safe_currency_code(self.safe_string(market, 'market_code'))
|
449
|
-
minBuyPrice = self.safe_string(market, 'min_buy_price')
|
450
|
-
minSellPrice = self.safe_string(market, 'min_sell_price')
|
451
|
-
minPrice = Precise.string_max(minBuyPrice, minSellPrice)
|
452
|
-
buyFee = Precise.string_div(self.safe_string(market, 'buy_fee_percent'), '100')
|
453
|
-
sellFee = Precise.string_div(self.safe_string(market, 'sell_fee_percent'), '100')
|
454
|
-
fee = self.parse_number(Precise.string_max(buyFee, sellFee))
|
455
|
-
result.append({
|
456
|
-
'id': id,
|
457
|
-
'numericId': numericId,
|
458
|
-
'symbol': base + '/' + quote,
|
459
|
-
'base': base,
|
460
|
-
'quote': quote,
|
461
|
-
'settle': None,
|
462
|
-
'baseId': baseId,
|
463
|
-
'quoteId': quoteId,
|
464
|
-
'settleId': None,
|
465
|
-
'baseNumericId': baseNumericId,
|
466
|
-
'quoteNumericId': quoteNumericId,
|
467
|
-
'type': 'spot',
|
468
|
-
'spot': True,
|
469
|
-
'margin': False,
|
470
|
-
'swap': False,
|
471
|
-
'future': False,
|
472
|
-
'option': False,
|
473
|
-
'active': self.safe_value(market, 'active'),
|
474
|
-
'contract': False,
|
475
|
-
'linear': None,
|
476
|
-
'inverse': None,
|
477
|
-
'taker': fee,
|
478
|
-
'maker': fee,
|
479
|
-
'contractSize': None,
|
480
|
-
'expiry': None,
|
481
|
-
'expiryDatetime': None,
|
482
|
-
'strike': None,
|
483
|
-
'optionType': None,
|
484
|
-
'precision': {
|
485
|
-
'amount': self.parse_number(self.parse_precision(self.safe_string(market, 'currency_precision'))),
|
486
|
-
'price': self.parse_number(self.parse_precision(self.safe_string(market, 'market_precision'))),
|
487
|
-
},
|
488
|
-
'limits': {
|
489
|
-
'leverage': {
|
490
|
-
'min': None,
|
491
|
-
'max': None,
|
492
|
-
},
|
493
|
-
'amount': {
|
494
|
-
'min': self.safe_number(market, 'min_order_amount'),
|
495
|
-
'max': None,
|
496
|
-
},
|
497
|
-
'price': {
|
498
|
-
'min': minPrice,
|
499
|
-
'max': None,
|
500
|
-
},
|
501
|
-
'cost': {
|
502
|
-
'min': None,
|
503
|
-
'max': None,
|
504
|
-
},
|
505
|
-
},
|
506
|
-
'info': market,
|
507
|
-
})
|
508
|
-
return result
|
509
|
-
|
510
|
-
def fetch_ticker(self, symbol: str, params={}):
|
511
|
-
"""
|
512
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1ticker~1{currencyPairId}/get
|
513
|
-
fetches a price ticker, a statistical calculation with the information calculated over the past 24 hours for a specific market
|
514
|
-
:param str symbol: unified symbol of the market to fetch the ticker for
|
515
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
516
|
-
:returns dict: a `ticker structure <https://docs.ccxt.com/#/?id=ticker-structure>`
|
517
|
-
"""
|
518
|
-
self.load_markets()
|
519
|
-
market = self.market(symbol)
|
520
|
-
request = {
|
521
|
-
'currencyPairId': market['id'],
|
522
|
-
}
|
523
|
-
response = self.publicGetTickerCurrencyPairId(self.extend(request, params))
|
524
|
-
#
|
525
|
-
# {
|
526
|
-
# "success": True,
|
527
|
-
# "data": {
|
528
|
-
# "id": 2,
|
529
|
-
# "amount_multiplier": 1,
|
530
|
-
# "currency_code": "ETH",
|
531
|
-
# "market_code": "BTC",
|
532
|
-
# "currency_name": "Ethereum",
|
533
|
-
# "market_name": "Bitcoin",
|
534
|
-
# "symbol": "ETH_BTC",
|
535
|
-
# "group_name": "BTC",
|
536
|
-
# "group_id": 1,
|
537
|
-
# "ask": "0.02069998",
|
538
|
-
# "bid": "0.02028622",
|
539
|
-
# "last": "0.02049224",
|
540
|
-
# "open": "0.02059605",
|
541
|
-
# "low": "0.01977744",
|
542
|
-
# "high": "0.02097005",
|
543
|
-
# "volume": "480.43248971",
|
544
|
-
# "volumeQuote": "23491.29826130",
|
545
|
-
# "count": "7384",
|
546
|
-
# "fiatsRate": {
|
547
|
-
# "USD": 7230.86,
|
548
|
-
# "EUR": 6590.79,
|
549
|
-
# "UAH": 173402,
|
550
|
-
# "AUD": 10595.51,
|
551
|
-
# "IDR": 101568085,
|
552
|
-
# "CNY": 50752,
|
553
|
-
# "KRW": 8452295,
|
554
|
-
# "JPY": 784607,
|
555
|
-
# "VND": 167315119,
|
556
|
-
# "INR": 517596,
|
557
|
-
# "GBP": 5607.25,
|
558
|
-
# "CAD": 9602.63,
|
559
|
-
# "BRL": 30472,
|
560
|
-
# "RUB": 460718
|
561
|
-
# },
|
562
|
-
# "timestamp": 1574698235601
|
563
|
-
# }
|
564
|
-
# }
|
565
|
-
#
|
566
|
-
ticker = self.safe_value(response, 'data', {})
|
567
|
-
return self.parse_ticker(ticker, market)
|
568
|
-
|
569
|
-
def fetch_time(self, params={}):
|
570
|
-
"""
|
571
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1ping/get
|
572
|
-
fetches the current integer timestamp in milliseconds from the exchange server
|
573
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
574
|
-
:returns int: the current integer timestamp in milliseconds from the exchange server
|
575
|
-
"""
|
576
|
-
response = self.publicGetPing(params)
|
577
|
-
#
|
578
|
-
# {
|
579
|
-
# "success": True,
|
580
|
-
# "data": {
|
581
|
-
# "server_datetime": {
|
582
|
-
# "date": "2019-01-22 15:13:34.233796",
|
583
|
-
# "timezone_type": 3,
|
584
|
-
# "timezone": "UTC"
|
585
|
-
# },
|
586
|
-
# "server_timestamp": 1548170014
|
587
|
-
# }
|
588
|
-
# }
|
589
|
-
#
|
590
|
-
data = self.safe_value(response, 'data', {})
|
591
|
-
serverDatetime = self.safe_value(data, 'server_datetime', {})
|
592
|
-
return self.parse8601(self.safe_string(serverDatetime, 'date'))
|
593
|
-
|
594
|
-
def fetch_order_book(self, symbol: str, limit: Optional[int] = None, params={}):
|
595
|
-
"""
|
596
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1orderbook~1{currencyPairId}/get
|
597
|
-
fetches information on open orders with bid(buy) and ask(sell) prices, volumes and other data
|
598
|
-
:param str symbol: unified symbol of the market to fetch the order book for
|
599
|
-
:param int|None limit: the maximum amount of order book entries to return
|
600
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
601
|
-
:returns dict: A dictionary of `order book structures <https://docs.ccxt.com/#/?id=order-book-structure>` indexed by market symbols
|
602
|
-
"""
|
603
|
-
self.load_markets()
|
604
|
-
market = self.market(symbol)
|
605
|
-
request = {
|
606
|
-
'currencyPairId': market['id'],
|
607
|
-
}
|
608
|
-
if limit is not None:
|
609
|
-
request['limit_bids'] = limit # returns all if set to 0, default 100
|
610
|
-
request['limit_asks'] = limit # returns all if set to 0, default 100
|
611
|
-
response = self.publicGetOrderbookCurrencyPairId(self.extend(request, params))
|
612
|
-
#
|
613
|
-
# {
|
614
|
-
# "success": True,
|
615
|
-
# "data": {
|
616
|
-
# "ask": [
|
617
|
-
# {"currency_pair_id": 2, "amount": "2.17865373", "price": "0.02062917", "amount2": "0.04494382", "count": 1, "cumulative_amount": 2.17865373},
|
618
|
-
# {"currency_pair_id": 2, "amount": "2.27521743", "price": "0.02062918", "amount2": "0.04693587", "count": 1, "cumulative_amount": 4.45387116},
|
619
|
-
# {"currency_pair_id": 2, "amount": "1.26980049", "price": "0.02063170", "amount2": "0.02619814", "count": 1, "cumulative_amount": 5.72367165},
|
620
|
-
# ],
|
621
|
-
# "bid": [
|
622
|
-
# {"currency_pair_id": 2, "amount": "0.00978005", "price": "0.02057000", "amount2": "0.00020118", "count": 1, "cumulative_amount": 0.00978005},
|
623
|
-
# {"currency_pair_id": 2, "amount": "0.00500000", "price": "0.02056000", "amount2": "0.00010280", "count": 1, "cumulative_amount": 0.01478005},
|
624
|
-
# {"currency_pair_id": 2, "amount": "0.77679882", "price": "0.02054001", "amount2": "0.01595546", "count": 1, "cumulative_amount": 0.79157887},
|
625
|
-
# ],
|
626
|
-
# "ask_total_amount": 2555.749174609999,
|
627
|
-
# "bid_total_amount": 29.180037330000005
|
628
|
-
# }
|
629
|
-
# }
|
630
|
-
#
|
631
|
-
orderbook = self.safe_value(response, 'data', {})
|
632
|
-
return self.parse_order_book(orderbook, symbol, None, 'bid', 'ask', 'price', 'amount')
|
633
|
-
|
634
|
-
def parse_ticker(self, ticker, market=None):
|
635
|
-
#
|
636
|
-
# {
|
637
|
-
# "id": 2,
|
638
|
-
# "amount_multiplier": 1,
|
639
|
-
# "currency_code": "ETH",
|
640
|
-
# "market_code": "BTC",
|
641
|
-
# "currency_name": "Ethereum",
|
642
|
-
# "market_name": "Bitcoin",
|
643
|
-
# "symbol": "ETH_BTC",
|
644
|
-
# "group_name": "BTC",
|
645
|
-
# "group_id": 1,
|
646
|
-
# "ask": "0.02069998",
|
647
|
-
# "bid": "0.02028622",
|
648
|
-
# "last": "0.02049224",
|
649
|
-
# "open": "0.02059605",
|
650
|
-
# "low": "0.01977744",
|
651
|
-
# "high": "0.02097005",
|
652
|
-
# "volume": "480.43248971",
|
653
|
-
# "volumeQuote": "23491.29826130",
|
654
|
-
# "count": "7384",
|
655
|
-
# "fiatsRate": {
|
656
|
-
# "USD": 7230.86,
|
657
|
-
# "EUR": 6590.79,
|
658
|
-
# "UAH": 173402,
|
659
|
-
# "AUD": 10595.51,
|
660
|
-
# "IDR": 101568085,
|
661
|
-
# "CNY": 50752,
|
662
|
-
# "KRW": 8452295,
|
663
|
-
# "JPY": 784607,
|
664
|
-
# "VND": 167315119,
|
665
|
-
# "INR": 517596,
|
666
|
-
# "GBP": 5607.25,
|
667
|
-
# "CAD": 9602.63,
|
668
|
-
# "BRL": 30472,
|
669
|
-
# "RUB": 460718
|
670
|
-
# },
|
671
|
-
# "timestamp": 1574698235601
|
672
|
-
# }
|
673
|
-
#
|
674
|
-
timestamp = self.safe_integer(ticker, 'timestamp')
|
675
|
-
marketId = self.safe_string_2(ticker, 'id', 'symbol')
|
676
|
-
symbol = self.safe_symbol(marketId, market, '_')
|
677
|
-
last = self.safe_string(ticker, 'last')
|
678
|
-
open = self.safe_string(ticker, 'open')
|
679
|
-
return self.safe_ticker({
|
680
|
-
'symbol': symbol,
|
681
|
-
'timestamp': timestamp,
|
682
|
-
'datetime': self.iso8601(timestamp),
|
683
|
-
'high': self.safe_string(ticker, 'high'),
|
684
|
-
'low': self.safe_string(ticker, 'low'),
|
685
|
-
'bid': self.safe_string(ticker, 'bid'),
|
686
|
-
'bidVolume': None,
|
687
|
-
'ask': self.safe_string(ticker, 'ask'),
|
688
|
-
'askVolume': None,
|
689
|
-
'vwap': None,
|
690
|
-
'open': open,
|
691
|
-
'close': last,
|
692
|
-
'last': last,
|
693
|
-
'previousClose': None, # previous day close
|
694
|
-
'change': None,
|
695
|
-
'percentage': None,
|
696
|
-
'average': None,
|
697
|
-
'baseVolume': self.safe_string(ticker, 'volumeQuote'),
|
698
|
-
'quoteVolume': self.safe_string(ticker, 'volume'),
|
699
|
-
'info': ticker,
|
700
|
-
}, market)
|
701
|
-
|
702
|
-
def fetch_tickers(self, symbols: Optional[List[str]] = None, params={}):
|
703
|
-
"""
|
704
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1ticker/get
|
705
|
-
fetches price tickers for multiple markets, statistical calculations with the information calculated over the past 24 hours each market
|
706
|
-
:param [str]|None symbols: unified symbols of the markets to fetch the ticker for, all market tickers are returned if not assigned
|
707
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
708
|
-
:returns dict: a dictionary of `ticker structures <https://docs.ccxt.com/#/?id=ticker-structure>`
|
709
|
-
"""
|
710
|
-
self.load_markets()
|
711
|
-
response = self.publicGetTicker(params)
|
712
|
-
#
|
713
|
-
# {
|
714
|
-
# "success":true,
|
715
|
-
# "data":[
|
716
|
-
# {
|
717
|
-
# "id":262,
|
718
|
-
# "amount_multiplier":1,
|
719
|
-
# "currency_code":"ARDR",
|
720
|
-
# "market_code":"BTC",
|
721
|
-
# "currency_name":"ARDOR",
|
722
|
-
# "market_name":"Bitcoin",
|
723
|
-
# "symbol":"ARDR_BTC",
|
724
|
-
# "group_name":"BTC",
|
725
|
-
# "group_id":1,
|
726
|
-
# "ask":"0.00000630",
|
727
|
-
# "bid":"0.00000613",
|
728
|
-
# "last":"0.00000617",
|
729
|
-
# "open":"0.00000620",
|
730
|
-
# "low":"0.00000614",
|
731
|
-
# "high":"0.00000630",
|
732
|
-
# "volume":"30.37795305",
|
733
|
-
# "volumeQuote":"4911487.01996544",
|
734
|
-
# "count":"710",
|
735
|
-
# "fiatsRate":{
|
736
|
-
# "USD":7230.86,
|
737
|
-
# "EUR":6590.79,
|
738
|
-
# "UAH":173402,
|
739
|
-
# "AUD":10744.52,
|
740
|
-
# "IDR":101568085,
|
741
|
-
# "CNY":50752,
|
742
|
-
# "KRW":8452295,
|
743
|
-
# "JPY":784607,
|
744
|
-
# "VND":167315119,
|
745
|
-
# "INR":517596,
|
746
|
-
# "GBP":5607.25,
|
747
|
-
# "CAD":9602.63,
|
748
|
-
# "BRL":30472,
|
749
|
-
# "RUB":467358
|
750
|
-
# },
|
751
|
-
# "timestamp":1574698617304,
|
752
|
-
# "group_position":1
|
753
|
-
# },
|
754
|
-
# ]
|
755
|
-
# }
|
756
|
-
#
|
757
|
-
tickers = self.safe_value(response, 'data', [])
|
758
|
-
return self.parse_tickers(tickers, symbols)
|
759
|
-
|
760
|
-
def parse_ohlcv(self, ohlcv, market=None):
|
761
|
-
#
|
762
|
-
# {
|
763
|
-
# "time": 1566086400000,
|
764
|
-
# "close": 0.01895,
|
765
|
-
# "open": 0.01812427,
|
766
|
-
# "high": 0.0191588,
|
767
|
-
# "low": 0.01807001,
|
768
|
-
# "volume": 2588.597813750006
|
769
|
-
# }
|
770
|
-
#
|
771
|
-
return [
|
772
|
-
self.safe_integer(ohlcv, 'time'),
|
773
|
-
self.safe_number(ohlcv, 'open'),
|
774
|
-
self.safe_number(ohlcv, 'high'),
|
775
|
-
self.safe_number(ohlcv, 'low'),
|
776
|
-
self.safe_number(ohlcv, 'close'),
|
777
|
-
self.safe_number(ohlcv, 'volume'),
|
778
|
-
]
|
779
|
-
|
780
|
-
def fetch_ohlcv(self, symbol: str, timeframe='1m', since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
781
|
-
"""
|
782
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1chart~1{currencyPairId}~1{candlesType}/get
|
783
|
-
fetches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
784
|
-
:param str symbol: unified symbol of the market to fetch OHLCV data for
|
785
|
-
:param str timeframe: the length of time each candle represents
|
786
|
-
:param int|None since: timestamp in ms of the earliest candle to fetch
|
787
|
-
:param int|None limit: the maximum amount of candles to fetch
|
788
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
789
|
-
:returns [[int]]: A list of candles ordered, open, high, low, close, volume
|
790
|
-
"""
|
791
|
-
self.load_markets()
|
792
|
-
market = self.market(symbol)
|
793
|
-
request = {
|
794
|
-
'currencyPairId': market['id'],
|
795
|
-
'candlesType': self.safe_string(self.timeframes, timeframe, timeframe), # default 1d
|
796
|
-
# 'timeStart': 1574709092, # unix timestamp in seconds, required
|
797
|
-
# 'timeEnd': 1574709092, # unix timestamp in seconds, required
|
798
|
-
# 'limit': 100, # default 100, optional
|
799
|
-
# 'offset' 100, # optional, pagination within timerange
|
800
|
-
}
|
801
|
-
if limit is None:
|
802
|
-
limit = 100
|
803
|
-
else:
|
804
|
-
request['limit'] = limit
|
805
|
-
duration = self.parse_timeframe(timeframe)
|
806
|
-
timerange = limit * duration
|
807
|
-
if since is None:
|
808
|
-
request['timeEnd'] = self.seconds()
|
809
|
-
request['timeStart'] = request['timeEnd'] - timerange
|
810
|
-
else:
|
811
|
-
request['timeStart'] = self.parse_to_int(since / 1000)
|
812
|
-
request['timeEnd'] = self.sum(request['timeStart'], timerange)
|
813
|
-
response = self.publicGetChartCurrencyPairIdCandlesType(self.extend(request, params))
|
814
|
-
#
|
815
|
-
# {
|
816
|
-
# "success": True,
|
817
|
-
# "data": [
|
818
|
-
# {
|
819
|
-
# "time": 1566086400000,
|
820
|
-
# "close": 0.01895,
|
821
|
-
# "open": 0.01812427,
|
822
|
-
# "high": 0.0191588,
|
823
|
-
# "low": 0.01807001,
|
824
|
-
# "volume": 2588.597813750006
|
825
|
-
# },
|
826
|
-
# ]
|
827
|
-
# }
|
828
|
-
#
|
829
|
-
data = self.safe_value(response, 'data', [])
|
830
|
-
return self.parse_ohlcvs(data, market, timeframe, since, limit)
|
831
|
-
|
832
|
-
def parse_trade(self, trade, market=None):
|
833
|
-
#
|
834
|
-
# public fetchTrades
|
835
|
-
#
|
836
|
-
# {
|
837
|
-
# "id": 35989317,
|
838
|
-
# "price": "0.02033813",
|
839
|
-
# "amount": "3.60000000",
|
840
|
-
# "type": "BUY",
|
841
|
-
# "timestamp": "1574713503"
|
842
|
-
# }
|
843
|
-
#
|
844
|
-
# private fetchMyTrades, fetchClosedOrder, fetchOrderTrades
|
845
|
-
#
|
846
|
-
# {
|
847
|
-
# "id": 658745,
|
848
|
-
# "buy_order_id": 6587453,
|
849
|
-
# "sell_order_id": 6587459,
|
850
|
-
# "price": 0.012285,
|
851
|
-
# "amount": 6.35,
|
852
|
-
# "trade_type": "SELL",
|
853
|
-
# "timestamp": "1538737692"
|
854
|
-
# }
|
855
|
-
#
|
856
|
-
id = self.safe_string(trade, 'id')
|
857
|
-
timestamp = self.safe_timestamp(trade, 'timestamp')
|
858
|
-
priceString = self.safe_string(trade, 'price')
|
859
|
-
amountString = self.safe_string(trade, 'amount')
|
860
|
-
symbol = None
|
861
|
-
if (symbol is None) and (market is not None):
|
862
|
-
symbol = market['symbol']
|
863
|
-
side = self.safe_string_lower_2(trade, 'type', 'trade_type')
|
864
|
-
return self.safe_trade({
|
865
|
-
'info': trade,
|
866
|
-
'timestamp': timestamp,
|
867
|
-
'datetime': self.iso8601(timestamp),
|
868
|
-
'symbol': symbol,
|
869
|
-
'id': id,
|
870
|
-
'order': None,
|
871
|
-
'type': None,
|
872
|
-
'takerOrMaker': None,
|
873
|
-
'side': side,
|
874
|
-
'price': priceString,
|
875
|
-
'amount': amountString,
|
876
|
-
'cost': None,
|
877
|
-
'fee': None,
|
878
|
-
}, market)
|
879
|
-
|
880
|
-
def fetch_trades(self, symbol: str, since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
881
|
-
"""
|
882
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1trades~1{currencyPairId}/get
|
883
|
-
get the list of most recent trades for a particular symbol
|
884
|
-
:param str symbol: unified symbol of the market to fetch trades for
|
885
|
-
:param int|None since: timestamp in ms of the earliest trade to fetch
|
886
|
-
:param int|None limit: the maximum amount of trades to fetch
|
887
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
888
|
-
:returns [dict]: a list of `trade structures <https://docs.ccxt.com/en/latest/manual.html?#public-trades>`
|
889
|
-
"""
|
890
|
-
self.load_markets()
|
891
|
-
market = self.market(symbol)
|
892
|
-
request = {
|
893
|
-
'currencyPairId': market['id'],
|
894
|
-
# 'sort': 'ASC', # ASC or DESC, default DESC
|
895
|
-
# 'from': 1574709092, # unix timestamp, optional
|
896
|
-
# 'till': 1574709092, # unix timestamp, optional
|
897
|
-
# 'limit': 100, # default 100, optional
|
898
|
-
# 'offset': 100, # optional
|
899
|
-
}
|
900
|
-
if limit is not None:
|
901
|
-
request['limit'] = limit # currently limited to 100 or fewer
|
902
|
-
if since is not None:
|
903
|
-
request['sort'] = 'ASC' # needed to make the from param work
|
904
|
-
request['from'] = self.parse_to_int(since / 1000)
|
905
|
-
response = self.publicGetTradesCurrencyPairId(self.extend(request, params))
|
906
|
-
#
|
907
|
-
# {
|
908
|
-
# "success": True,
|
909
|
-
# "data": [
|
910
|
-
# {
|
911
|
-
# "id": 35989317,
|
912
|
-
# "price": "0.02033813",
|
913
|
-
# "amount": "3.60000000",
|
914
|
-
# "type": "BUY",
|
915
|
-
# "timestamp": "1574713503"
|
916
|
-
# },
|
917
|
-
# ]
|
918
|
-
# }
|
919
|
-
#
|
920
|
-
trades = self.safe_value(response, 'data', [])
|
921
|
-
return self.parse_trades(trades, market, since, limit)
|
922
|
-
|
923
|
-
def fetch_trading_fee(self, symbol: str, params={}):
|
924
|
-
"""
|
925
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1fees~1{currencyPairId}/get
|
926
|
-
fetch the trading fees for a market
|
927
|
-
:param str symbol: unified market symbol
|
928
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
929
|
-
:returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
|
930
|
-
"""
|
931
|
-
self.load_markets()
|
932
|
-
market = self.market(symbol)
|
933
|
-
request = {
|
934
|
-
'currencyPairId': market['id'],
|
935
|
-
}
|
936
|
-
response = self.tradingGetFeesCurrencyPairId(self.extend(request, params))
|
937
|
-
#
|
938
|
-
# {
|
939
|
-
# success: True,
|
940
|
-
# data: {buy_fee: '0.00200000', sell_fee: '0.00200000'},
|
941
|
-
# unified_message: {message_id: 'operation_successful', substitutions: []}
|
942
|
-
# }
|
943
|
-
#
|
944
|
-
data = self.safe_value(response, 'data')
|
945
|
-
return {
|
946
|
-
'info': response,
|
947
|
-
'symbol': market['symbol'],
|
948
|
-
'maker': self.safe_number(data, 'sell_fee'),
|
949
|
-
'taker': self.safe_number(data, 'buy_fee'),
|
950
|
-
'percentage': True,
|
951
|
-
'tierBased': True,
|
952
|
-
}
|
953
|
-
|
954
|
-
def parse_balance(self, response):
|
955
|
-
result = {
|
956
|
-
'info': response,
|
957
|
-
'timestamp': None,
|
958
|
-
'datetime': None,
|
959
|
-
}
|
960
|
-
balances = self.safe_value(response, 'data', [])
|
961
|
-
for i in range(0, len(balances)):
|
962
|
-
balance = balances[i]
|
963
|
-
code = self.safe_currency_code(self.safe_string(balance, 'currency_id'))
|
964
|
-
account = self.account()
|
965
|
-
account['free'] = self.safe_string(balance, 'balance')
|
966
|
-
account['used'] = self.safe_string(balance, 'frozen_balance')
|
967
|
-
result[code] = account
|
968
|
-
return self.safe_balance(result)
|
969
|
-
|
970
|
-
def fetch_balance(self, params={}):
|
971
|
-
"""
|
972
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1wallets/get
|
973
|
-
query for balance and get the amount of funds available for trading or funds locked in orders
|
974
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
975
|
-
:returns dict: a `balance structure <https://docs.ccxt.com/en/latest/manual.html?#balance-structure>`
|
976
|
-
"""
|
977
|
-
self.load_markets()
|
978
|
-
# self.load_accounts()
|
979
|
-
response = self.profileGetWallets(params)
|
980
|
-
#
|
981
|
-
# {
|
982
|
-
# "success": True,
|
983
|
-
# "data": [
|
984
|
-
# {
|
985
|
-
# "id": null,
|
986
|
-
# "currency_id": 665,
|
987
|
-
# "delisted": False,
|
988
|
-
# "disabled": False,
|
989
|
-
# "disable_deposits": False,
|
990
|
-
# "currency_code": "ORM",
|
991
|
-
# "currency_name": "Orium",
|
992
|
-
# "currency_type_id": 5,
|
993
|
-
# "balance": "0",
|
994
|
-
# "frozen_balance": "0",
|
995
|
-
# "bonus_balance": "0",
|
996
|
-
# "total_balance": "0",
|
997
|
-
# "protocol_specific_settings": null,
|
998
|
-
# "rates": {"BTC": "0.00000000020", "USD": "0.00000147"},
|
999
|
-
# },
|
1000
|
-
# {
|
1001
|
-
# "id": null,
|
1002
|
-
# "currency_id": 272,
|
1003
|
-
# "delisted": False,
|
1004
|
-
# "disabled": False,
|
1005
|
-
# "disable_deposits": False,
|
1006
|
-
# "currency_code": "USDT",
|
1007
|
-
# "currency_name": "TetherUSD",
|
1008
|
-
# "currency_type_id": 23,
|
1009
|
-
# "balance": "0",
|
1010
|
-
# "frozen_balance": "0",
|
1011
|
-
# "bonus_balance": "0",
|
1012
|
-
# "total_balance": "0",
|
1013
|
-
# "protocol_specific_settings": [
|
1014
|
-
# {"protocol_name": "OMNI", "protocol_id": 10, "active": True, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 10, "withdrawal_fee_percent": 0, "block_explorer_url": "https://omniexplorer.info/search/"},
|
1015
|
-
# {"protocol_name": "ERC20", "protocol_id": 5, "active": True, "withdrawal_fee_const": 1.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://etherscan.io/tx/"},
|
1016
|
-
# {"protocol_name": "TRON", "protocol_id": 24, "active": True, "withdrawal_fee_currency_id": 272, "withdrawal_fee_const": 0.2, "withdrawal_fee_percent": 0, "block_explorer_url": "https://tronscan.org/#/transaction/"}
|
1017
|
-
# ],
|
1018
|
-
# "rates": {"BTC": "0.00013893", "USD": "1"},
|
1019
|
-
# },
|
1020
|
-
# ]
|
1021
|
-
# }
|
1022
|
-
#
|
1023
|
-
return self.parse_balance(response)
|
1024
|
-
|
1025
|
-
def parse_order_status(self, status):
|
1026
|
-
statuses = {
|
1027
|
-
'PROCESSING': 'open',
|
1028
|
-
'PENDING': 'open',
|
1029
|
-
'PARTIAL': 'open',
|
1030
|
-
'FINISHED': 'closed',
|
1031
|
-
'CANCELLED': 'canceled',
|
1032
|
-
}
|
1033
|
-
return self.safe_string(statuses, status, status)
|
1034
|
-
|
1035
|
-
def parse_order(self, order, market=None):
|
1036
|
-
#
|
1037
|
-
# createOrder, fetchOpenOrders, fetchClosedOrders, cancelOrder, fetchOrder, fetchClosedOrder
|
1038
|
-
#
|
1039
|
-
# {
|
1040
|
-
# "id": 828680665,
|
1041
|
-
# "currency_pair_id": 1,
|
1042
|
-
# "currency_pair_name": "NXT_BTC",
|
1043
|
-
# "price": "0.011384",
|
1044
|
-
# "trigger_price": 0.011385,
|
1045
|
-
# "initial_amount": "13.942",
|
1046
|
-
# "processed_amount": "3.724", # missing in fetchClosedOrder
|
1047
|
-
# "type": "SELL",
|
1048
|
-
# "original_type": "STOP_LIMIT_SELL",
|
1049
|
-
# "created": "2019-01-17 10:14:48",
|
1050
|
-
# "timestamp": "1547720088",
|
1051
|
-
# "status": "PARTIAL"
|
1052
|
-
# # fetchClosedOrder only
|
1053
|
-
# "trades": [
|
1054
|
-
# {
|
1055
|
-
# "id": 658745,
|
1056
|
-
# "buy_order_id": 658745,
|
1057
|
-
# "sell_order_id": 828680665,
|
1058
|
-
# "price": 0.012285,
|
1059
|
-
# "amount": 6.35,
|
1060
|
-
# "trade_type": "SELL",
|
1061
|
-
# "timestamp": "1538737692"
|
1062
|
-
# }
|
1063
|
-
# ],
|
1064
|
-
# # fetchClosedOrder only
|
1065
|
-
# "fees": [
|
1066
|
-
# {
|
1067
|
-
# "id": 1234567,
|
1068
|
-
# "currency_id": 1,
|
1069
|
-
# "amount": 0.00025,
|
1070
|
-
# "timestamp": "1548149238"
|
1071
|
-
# }
|
1072
|
-
# ]
|
1073
|
-
# }
|
1074
|
-
#
|
1075
|
-
id = self.safe_string(order, 'id')
|
1076
|
-
status = self.parse_order_status(self.safe_string(order, 'status'))
|
1077
|
-
marketId = self.safe_string_2(order, 'currency_pair_id', 'currency_pair_name')
|
1078
|
-
symbol = self.safe_symbol(marketId, market, '_')
|
1079
|
-
timestamp = self.safe_timestamp(order, 'timestamp')
|
1080
|
-
price = self.safe_string(order, 'price')
|
1081
|
-
amount = self.safe_string(order, 'initial_amount')
|
1082
|
-
filled = self.safe_string(order, 'processed_amount')
|
1083
|
-
remaining = None
|
1084
|
-
cost = None
|
1085
|
-
if filled is not None:
|
1086
|
-
if amount is not None:
|
1087
|
-
remaining = Precise.string_sub(amount, filled)
|
1088
|
-
if self.options['parseOrderToPrecision']:
|
1089
|
-
remaining = self.amount_to_precision(symbol, remaining)
|
1090
|
-
remaining = Precise.string_max(remaining, '0.0')
|
1091
|
-
if price is not None:
|
1092
|
-
if cost is None:
|
1093
|
-
cost = Precise.string_mul(price, filled)
|
1094
|
-
type = self.safe_string(order, 'original_type')
|
1095
|
-
if (type == 'BUY') or (type == 'SELL'):
|
1096
|
-
type = None
|
1097
|
-
side = self.safe_string_lower(order, 'type')
|
1098
|
-
trades = self.safe_value(order, 'trades')
|
1099
|
-
stopPrice = self.safe_number(order, 'trigger_price')
|
1100
|
-
result = {
|
1101
|
-
'info': order,
|
1102
|
-
'id': id,
|
1103
|
-
'clientOrderId': None,
|
1104
|
-
'timestamp': timestamp,
|
1105
|
-
'datetime': self.iso8601(timestamp),
|
1106
|
-
'lastTradeTimestamp': None,
|
1107
|
-
'symbol': symbol,
|
1108
|
-
'type': type,
|
1109
|
-
'timeInForce': None,
|
1110
|
-
'postOnly': None,
|
1111
|
-
'side': side,
|
1112
|
-
'price': price,
|
1113
|
-
'stopPrice': stopPrice,
|
1114
|
-
'triggerPrice': stopPrice,
|
1115
|
-
'amount': amount,
|
1116
|
-
'cost': cost,
|
1117
|
-
'average': None,
|
1118
|
-
'filled': filled,
|
1119
|
-
'remaining': remaining,
|
1120
|
-
'status': status,
|
1121
|
-
'trades': trades,
|
1122
|
-
}
|
1123
|
-
fees = self.safe_value(order, 'fees')
|
1124
|
-
if fees is None:
|
1125
|
-
result['fee'] = None
|
1126
|
-
else:
|
1127
|
-
numFees = len(fees)
|
1128
|
-
if numFees > 0:
|
1129
|
-
result['fees'] = []
|
1130
|
-
for i in range(0, len(fees)):
|
1131
|
-
feeCost = self.safe_string(fees[i], 'amount')
|
1132
|
-
if feeCost is not None:
|
1133
|
-
feeCurrencyId = self.safe_string(fees[i], 'currency_id')
|
1134
|
-
feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
|
1135
|
-
result['fees'].append({
|
1136
|
-
'cost': feeCost,
|
1137
|
-
'currency': feeCurrencyCode,
|
1138
|
-
})
|
1139
|
-
else:
|
1140
|
-
result['fee'] = None
|
1141
|
-
return self.safe_order(result, market)
|
1142
|
-
|
1143
|
-
def create_order(self, symbol: str, type, side: OrderSide, amount, price=None, params={}):
|
1144
|
-
"""
|
1145
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1orders~1{currencyPairId}/post
|
1146
|
-
create a trade order
|
1147
|
-
:param str symbol: unified symbol of the market to create an order in
|
1148
|
-
:param str type: 'market' or 'limit'
|
1149
|
-
:param str side: 'buy' or 'sell'
|
1150
|
-
:param float amount: how much of currency you want to trade in units of base currency
|
1151
|
-
:param float|None price: the price at which the order is to be fullfilled, in units of the quote currency, ignored in market orders
|
1152
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1153
|
-
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1154
|
-
"""
|
1155
|
-
if type == 'market':
|
1156
|
-
raise ExchangeError(self.id + ' createOrder() allows limit orders only')
|
1157
|
-
self.load_markets()
|
1158
|
-
market = self.market(symbol)
|
1159
|
-
if type == 'limit':
|
1160
|
-
type = side
|
1161
|
-
request = {
|
1162
|
-
'currencyPairId': market['id'],
|
1163
|
-
'type': type.upper(), # 'BUY', 'SELL', 'STOP_LIMIT_BUY', 'STOP_LIMIT_SELL'
|
1164
|
-
'amount': float(self.amount_to_precision(symbol, amount)), # required
|
1165
|
-
'price': float(self.price_to_precision(symbol, price)), # required
|
1166
|
-
# 'trigger_price': 123.45 # required for STOP_LIMIT_BUY or STOP_LIMIT_SELL
|
1167
|
-
}
|
1168
|
-
response = self.tradingPostOrdersCurrencyPairId(self.extend(request, params))
|
1169
|
-
#
|
1170
|
-
# {
|
1171
|
-
# "success": True,
|
1172
|
-
# "data": {
|
1173
|
-
# "id": 828680665,
|
1174
|
-
# "currency_pair_id": 1,
|
1175
|
-
# "currency_pair_name": "NXT_BTC",
|
1176
|
-
# "price": "0.011384",
|
1177
|
-
# "trigger_price": 0.011385,
|
1178
|
-
# "initial_amount": "13.942",
|
1179
|
-
# "processed_amount": "3.724",
|
1180
|
-
# "type": "SELL",
|
1181
|
-
# "original_type": "STOP_LIMIT_SELL",
|
1182
|
-
# "created": "2019-01-17 10:14:48",
|
1183
|
-
# "timestamp": "1547720088",
|
1184
|
-
# "status": "PARTIAL"
|
1185
|
-
# }
|
1186
|
-
# }
|
1187
|
-
#
|
1188
|
-
data = self.safe_value(response, 'data', {})
|
1189
|
-
return self.parse_order(data, market)
|
1190
|
-
|
1191
|
-
def fetch_order(self, id: str, symbol: Optional[str] = None, params={}):
|
1192
|
-
"""
|
1193
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1order~1{orderId}/get
|
1194
|
-
fetches information on an order made by the user
|
1195
|
-
:param str|None symbol: unified symbol of the market the order was made in
|
1196
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1197
|
-
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1198
|
-
"""
|
1199
|
-
self.load_markets()
|
1200
|
-
request = {
|
1201
|
-
'orderId': id,
|
1202
|
-
}
|
1203
|
-
response = self.tradingGetOrderOrderId(self.extend(request, params))
|
1204
|
-
#
|
1205
|
-
# {
|
1206
|
-
# "success": True,
|
1207
|
-
# "data": {
|
1208
|
-
# "id": 828680665,
|
1209
|
-
# "currency_pair_id": 1,
|
1210
|
-
# "currency_pair_name": "NXT_BTC",
|
1211
|
-
# "price": "0.011384",
|
1212
|
-
# "trigger_price": 0.011385,
|
1213
|
-
# "initial_amount": "13.942",
|
1214
|
-
# "processed_amount": "3.724",
|
1215
|
-
# "type": "SELL",
|
1216
|
-
# "original_type": "STOP_LIMIT_SELL",
|
1217
|
-
# "created": "2019-01-17 10:14:48",
|
1218
|
-
# "timestamp": "1547720088",
|
1219
|
-
# "status": "PARTIAL"
|
1220
|
-
# }
|
1221
|
-
# }
|
1222
|
-
#
|
1223
|
-
data = self.safe_value(response, 'data', {})
|
1224
|
-
market = None
|
1225
|
-
if symbol is not None:
|
1226
|
-
market = self.market(symbol)
|
1227
|
-
return self.parse_order(data, market)
|
1228
|
-
|
1229
|
-
def fetch_closed_order(self, id: str, symbol: Optional[str] = None, params={}):
|
1230
|
-
"""
|
1231
|
-
see https://apidocs.stex.com/#tag/Trading-History-and-Reports/paths/~1reports~1orders~1{orderId}/get
|
1232
|
-
fetch an open order by it's id
|
1233
|
-
:param str id: order id
|
1234
|
-
:param str|None symbol: unified market symbol, default is None
|
1235
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1236
|
-
:returns dict: an `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1237
|
-
"""
|
1238
|
-
self.load_markets()
|
1239
|
-
request = {
|
1240
|
-
'orderId': id,
|
1241
|
-
}
|
1242
|
-
response = self.reportsGetOrdersOrderId(self.extend(request, params))
|
1243
|
-
#
|
1244
|
-
# {
|
1245
|
-
# "success": True,
|
1246
|
-
# "data": {
|
1247
|
-
# "id": 5478965,
|
1248
|
-
# "currency_pair_id": 1,
|
1249
|
-
# "currency_pair_name": "NXT_BTC",
|
1250
|
-
# "price": "0.00013800",
|
1251
|
-
# "initial_amount": "1.00000000",
|
1252
|
-
# "type": "BUY",
|
1253
|
-
# "created": "2019-01-22 09:27:17",
|
1254
|
-
# "timestamp": 1548149237,
|
1255
|
-
# "status": "FINISHED",
|
1256
|
-
# "trades": [
|
1257
|
-
# {
|
1258
|
-
# "id": 658745,
|
1259
|
-
# "buy_order_id": 6587453,
|
1260
|
-
# "sell_order_id": 6587459,
|
1261
|
-
# "price": 0.012285,
|
1262
|
-
# "amount": 6.35,
|
1263
|
-
# "trade_type": "SELL",
|
1264
|
-
# "timestamp": "1538737692"
|
1265
|
-
# }
|
1266
|
-
# ],
|
1267
|
-
# "fees": [
|
1268
|
-
# {
|
1269
|
-
# "id": 1234567,
|
1270
|
-
# "currency_id": 1,
|
1271
|
-
# "amount": 0.00025,
|
1272
|
-
# "timestamp": "1548149238"
|
1273
|
-
# }
|
1274
|
-
# ]
|
1275
|
-
# }
|
1276
|
-
# }
|
1277
|
-
#
|
1278
|
-
data = self.safe_value(response, 'data', {})
|
1279
|
-
market = None
|
1280
|
-
if symbol is not None:
|
1281
|
-
market = self.market(symbol)
|
1282
|
-
return self.parse_order(data, market)
|
1283
|
-
|
1284
|
-
def fetch_order_trades(self, id: str, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
1285
|
-
"""
|
1286
|
-
fetch all the trades made from a single order
|
1287
|
-
:param str id: order id
|
1288
|
-
:param str|None symbol: unified market symbol
|
1289
|
-
:param int|None since: the earliest time in ms to fetch trades for
|
1290
|
-
:param int|None limit: the maximum number of trades to retrieve
|
1291
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1292
|
-
:returns [dict]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
1293
|
-
"""
|
1294
|
-
order = self.fetch_closed_order(id, symbol, params)
|
1295
|
-
return order['trades']
|
1296
|
-
|
1297
|
-
def fetch_open_orders(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
1298
|
-
"""
|
1299
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1orders/get
|
1300
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1orders~1{currencyPairId}/get
|
1301
|
-
fetch all unfilled currently open orders
|
1302
|
-
:param str|None symbol: unified market symbol
|
1303
|
-
:param int|None since: the earliest time in ms to fetch open orders for
|
1304
|
-
:param int|None limit: the maximum number of open orders structures to retrieve
|
1305
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1306
|
-
:returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1307
|
-
"""
|
1308
|
-
self.load_markets()
|
1309
|
-
market = None
|
1310
|
-
method = 'tradingGetOrders'
|
1311
|
-
request = {
|
1312
|
-
# 'limit': 100, # default 100
|
1313
|
-
# 'offset': 100,
|
1314
|
-
}
|
1315
|
-
if symbol is not None:
|
1316
|
-
method = 'tradingGetOrdersCurrencyPairId'
|
1317
|
-
market = self.market(symbol)
|
1318
|
-
request['currencyPairId'] = market['id']
|
1319
|
-
if limit is not None:
|
1320
|
-
request['limit'] = limit
|
1321
|
-
response = getattr(self, method)(self.extend(request, params))
|
1322
|
-
#
|
1323
|
-
# {
|
1324
|
-
# "success": True,
|
1325
|
-
# "data": [
|
1326
|
-
# {
|
1327
|
-
# "id": 828680665,
|
1328
|
-
# "currency_pair_id": 1,
|
1329
|
-
# "currency_pair_name": "NXT_BTC",
|
1330
|
-
# "price": "0.011384",
|
1331
|
-
# "trigger_price": 0.011385,
|
1332
|
-
# "initial_amount": "13.942",
|
1333
|
-
# "processed_amount": "3.724",
|
1334
|
-
# "type": "SELL",
|
1335
|
-
# "original_type": "STOP_LIMIT_SELL",
|
1336
|
-
# "created": "2019-01-17 10:14:48",
|
1337
|
-
# "timestamp": "1547720088",
|
1338
|
-
# "status": "PARTIAL"
|
1339
|
-
# }
|
1340
|
-
# ]
|
1341
|
-
# }
|
1342
|
-
#
|
1343
|
-
data = self.safe_value(response, 'data', [])
|
1344
|
-
return self.parse_orders(data, market, since, limit)
|
1345
|
-
|
1346
|
-
def cancel_order(self, id: str, symbol: Optional[str] = None, params={}):
|
1347
|
-
"""
|
1348
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1order~1{orderId}/delete
|
1349
|
-
cancels an open order
|
1350
|
-
:param str id: order id
|
1351
|
-
:param str|None symbol: not used by stex cancelOrder()
|
1352
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1353
|
-
:returns dict: An `order structure <https://docs.ccxt.com/#/?id=order-structure>`
|
1354
|
-
"""
|
1355
|
-
self.load_markets()
|
1356
|
-
request = {
|
1357
|
-
'orderId': id,
|
1358
|
-
}
|
1359
|
-
response = self.tradingDeleteOrderOrderId(self.extend(request, params))
|
1360
|
-
#
|
1361
|
-
# {
|
1362
|
-
# "success": True,
|
1363
|
-
# "data": {
|
1364
|
-
# "put_into_processing_queue": [
|
1365
|
-
# {
|
1366
|
-
# "id": 828680665,
|
1367
|
-
# "currency_pair_id": 1,
|
1368
|
-
# "currency_pair_name": "NXT_BTC",
|
1369
|
-
# "price": "0.011384",
|
1370
|
-
# "trigger_price": 0.011385,
|
1371
|
-
# "initial_amount": "13.942",
|
1372
|
-
# "processed_amount": "3.724",
|
1373
|
-
# "type": "SELL",
|
1374
|
-
# "original_type": "STOP_LIMIT_SELL",
|
1375
|
-
# "created": "2019-01-17 10:14:48",
|
1376
|
-
# "timestamp": "1547720088",
|
1377
|
-
# "status": "PARTIAL"
|
1378
|
-
# }
|
1379
|
-
# ],
|
1380
|
-
# "not_put_into_processing_queue": [
|
1381
|
-
# {
|
1382
|
-
# "id": 828680665,
|
1383
|
-
# "currency_pair_id": 1,
|
1384
|
-
# "currency_pair_name": "NXT_BTC",
|
1385
|
-
# "price": "0.011384",
|
1386
|
-
# "trigger_price": 0.011385,
|
1387
|
-
# "initial_amount": "13.942",
|
1388
|
-
# "processed_amount": "3.724",
|
1389
|
-
# "type": "SELL",
|
1390
|
-
# "original_type": "STOP_LIMIT_SELL",
|
1391
|
-
# "created": "2019-01-17 10:14:48",
|
1392
|
-
# "timestamp": "1547720088",
|
1393
|
-
# "status": "PARTIAL"
|
1394
|
-
# }
|
1395
|
-
# ],
|
1396
|
-
# "message": "string"
|
1397
|
-
# }
|
1398
|
-
# }
|
1399
|
-
#
|
1400
|
-
data = self.safe_value(response, 'data', {})
|
1401
|
-
acceptedOrders = self.safe_value(data, 'put_into_processing_queue', [])
|
1402
|
-
rejectedOrders = self.safe_value(data, 'not_put_into_processing_queue', [])
|
1403
|
-
numAcceptedOrders = len(acceptedOrders)
|
1404
|
-
numRejectedOrders = len(rejectedOrders)
|
1405
|
-
if numAcceptedOrders < 1:
|
1406
|
-
if numRejectedOrders < 1:
|
1407
|
-
raise OrderNotFound(self.id + ' cancelOrder() received an empty response: ' + self.json(response))
|
1408
|
-
else:
|
1409
|
-
return self.parse_order(rejectedOrders[0])
|
1410
|
-
else:
|
1411
|
-
if numRejectedOrders < 1:
|
1412
|
-
return self.parse_order(acceptedOrders[0])
|
1413
|
-
else:
|
1414
|
-
raise OrderNotFound(self.id + ' cancelOrder() received an empty response: ' + self.json(response))
|
1415
|
-
|
1416
|
-
def cancel_all_orders(self, symbol: Optional[str] = None, params={}):
|
1417
|
-
"""
|
1418
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1orders/delete
|
1419
|
-
see https://apidocs.stex.com/#tag/Trading/paths/~1trading~1orders~1{currencyPairId}/delete
|
1420
|
-
cancel all open orders
|
1421
|
-
:param str|None symbol: unified market symbol, only orders in the market of self symbol are cancelled when symbol is not None
|
1422
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1423
|
-
:returns [dict]: a list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
|
1424
|
-
"""
|
1425
|
-
self.load_markets()
|
1426
|
-
request = {}
|
1427
|
-
method = 'tradingDeleteOrders'
|
1428
|
-
if symbol is not None:
|
1429
|
-
market = self.market(symbol)
|
1430
|
-
request['currencyPairId'] = market['id']
|
1431
|
-
method = 'tradingDeleteOrdersCurrencyPairId'
|
1432
|
-
response = getattr(self, method)(self.extend(request, params))
|
1433
|
-
#
|
1434
|
-
# {
|
1435
|
-
# "success":true,
|
1436
|
-
# "data":{
|
1437
|
-
# "put_into_processing_queue":[],
|
1438
|
-
# "not_put_into_processing_queue":[],
|
1439
|
-
# "message":"Orders operations are handled in processing queue, therefore cancelling is not immediate."
|
1440
|
-
# }
|
1441
|
-
# }
|
1442
|
-
#
|
1443
|
-
return response
|
1444
|
-
|
1445
|
-
def fetch_my_trades(self, symbol: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
1446
|
-
"""
|
1447
|
-
see https://apidocs.stex.com/#tag/Trading-History-and-Reports/paths/~1reports~1trades~1{currencyPairId}/get
|
1448
|
-
fetch all trades made by the user
|
1449
|
-
:param str symbol: unified market symbol
|
1450
|
-
:param int|None since: the earliest time in ms to fetch trades for
|
1451
|
-
:param int|None limit: the maximum number of trades structures to retrieve
|
1452
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1453
|
-
:returns [dict]: a list of `trade structures <https://docs.ccxt.com/#/?id=trade-structure>`
|
1454
|
-
"""
|
1455
|
-
if symbol is None:
|
1456
|
-
raise ArgumentsRequired(self.id + ' fetchMyTrades() requires a symbol argument')
|
1457
|
-
self.load_markets()
|
1458
|
-
market = self.market(symbol)
|
1459
|
-
request = {
|
1460
|
-
'currencyPairId': market['id'],
|
1461
|
-
# 'timeStart': '2019-11-26T19:54:55.901Z', # datetime in iso format
|
1462
|
-
# 'timeEnd': '2019-11-26T19:54:55.901Z', # datetime in iso format
|
1463
|
-
# 'limit': 100, # default 100
|
1464
|
-
# 'offset': 100,
|
1465
|
-
}
|
1466
|
-
if since is not None:
|
1467
|
-
request['timeStart'] = self.iso8601(since)
|
1468
|
-
if limit is not None:
|
1469
|
-
request['limit'] = limit
|
1470
|
-
response = self.reportsGetTradesCurrencyPairId(self.extend(request, params))
|
1471
|
-
#
|
1472
|
-
# {
|
1473
|
-
# "success": True,
|
1474
|
-
# "data": [
|
1475
|
-
# {
|
1476
|
-
# "id": 658745,
|
1477
|
-
# "buy_order_id": 6587453,
|
1478
|
-
# "sell_order_id": 6587459,
|
1479
|
-
# "price": 0.012285,
|
1480
|
-
# "amount": 6.35,
|
1481
|
-
# "trade_type": "SELL",
|
1482
|
-
# "timestamp": "1538737692"
|
1483
|
-
# }
|
1484
|
-
# ]
|
1485
|
-
# }
|
1486
|
-
#
|
1487
|
-
trades = self.safe_value(response, 'data', [])
|
1488
|
-
return self.parse_trades(trades, market, since, limit)
|
1489
|
-
|
1490
|
-
def create_deposit_address(self, code: str, params={}):
|
1491
|
-
"""
|
1492
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1wallets~1{currencyId}/post
|
1493
|
-
create a currency deposit address
|
1494
|
-
:param str code: unified currency code of the currency for the deposit address
|
1495
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1496
|
-
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
1497
|
-
"""
|
1498
|
-
self.load_markets()
|
1499
|
-
currency = self.currency(code)
|
1500
|
-
request = {
|
1501
|
-
'currencyId': currency['id'],
|
1502
|
-
# Default value is the value that represents legacy protocol.
|
1503
|
-
# In case of USDT it is 10 OMNI was the default previously.
|
1504
|
-
# The list of protocols can be obtained from the /public/currencies/{currencyId}
|
1505
|
-
# 'protocol_id': 10,
|
1506
|
-
}
|
1507
|
-
response = self.profilePostWalletsCurrencyId(self.extend(request, params))
|
1508
|
-
#
|
1509
|
-
# {
|
1510
|
-
# "success": True,
|
1511
|
-
# "data": {
|
1512
|
-
# "id": 45875,
|
1513
|
-
# "currency_id": 1,
|
1514
|
-
# "delisted": False,
|
1515
|
-
# "disabled": False,
|
1516
|
-
# "disable_deposits": False,
|
1517
|
-
# "code": "BTC",
|
1518
|
-
# "balance": "0.198752",
|
1519
|
-
# "frozen_balance": "1.5784",
|
1520
|
-
# "bonus_balance": "0.000",
|
1521
|
-
# "deposit_address": {
|
1522
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1523
|
-
# "address_name": "Address",
|
1524
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
1525
|
-
# "additional_address_parameter_name": "Destination Tag",
|
1526
|
-
# "notification": "",
|
1527
|
-
# "protocol_id": 10,
|
1528
|
-
# "protocol_name": "Tether OMNI",
|
1529
|
-
# "supports_new_address_creation": False
|
1530
|
-
# },
|
1531
|
-
# "multi_deposit_addresses": [
|
1532
|
-
# {
|
1533
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1534
|
-
# "address_name": "Address",
|
1535
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
1536
|
-
# "additional_address_parameter_name": "Destination Tag",
|
1537
|
-
# "notification": "",
|
1538
|
-
# "protocol_id": 10,
|
1539
|
-
# "protocol_name": "Tether OMNI",
|
1540
|
-
# "supports_new_address_creation": False
|
1541
|
-
# }
|
1542
|
-
# ],
|
1543
|
-
# "withdrawal_additional_field_name": "Payment ID(optional)",
|
1544
|
-
# "rates": {"BTC": 0.000001},
|
1545
|
-
# "protocol_specific_settings": [
|
1546
|
-
# {
|
1547
|
-
# "protocol_name": "Tether OMNI",
|
1548
|
-
# "protocol_id": 10,
|
1549
|
-
# "active": True,
|
1550
|
-
# "withdrawal_fee_currency_id": 1,
|
1551
|
-
# "withdrawal_fee_const": 0.002,
|
1552
|
-
# "withdrawal_fee_percent": 0,
|
1553
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
1554
|
-
# }
|
1555
|
-
# ]
|
1556
|
-
# }
|
1557
|
-
# }
|
1558
|
-
#
|
1559
|
-
data = self.safe_value(response, 'data', {})
|
1560
|
-
depositAddress = self.safe_value(data, 'deposit_address', {})
|
1561
|
-
address = self.safe_string(depositAddress, 'address')
|
1562
|
-
tag = self.safe_string(depositAddress, 'additional_address_parameter')
|
1563
|
-
self.check_address(address)
|
1564
|
-
return {
|
1565
|
-
'currency': code,
|
1566
|
-
'address': address,
|
1567
|
-
'tag': tag,
|
1568
|
-
'info': response,
|
1569
|
-
}
|
1570
|
-
|
1571
|
-
def fetch_deposit_address(self, code: str, params={}):
|
1572
|
-
"""
|
1573
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1wallets~1{walletId}/get
|
1574
|
-
fetch the deposit address for a currency associated with self account
|
1575
|
-
:param str code: unified currency code
|
1576
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1577
|
-
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
1578
|
-
"""
|
1579
|
-
self.load_markets()
|
1580
|
-
balance = self.fetch_balance()
|
1581
|
-
wallets = self.safe_value(balance['info'], 'data', [])
|
1582
|
-
walletsByCurrencyId = self.index_by(wallets, 'currency_id')
|
1583
|
-
currency = self.currency(code)
|
1584
|
-
wallet = self.safe_value(walletsByCurrencyId, currency['id'])
|
1585
|
-
if wallet is None:
|
1586
|
-
raise ExchangeError(self.id + ' fetchDepositAddress() could not find the wallet id for currency code ' + code + ', try to call createDepositAddress() first')
|
1587
|
-
walletId = self.safe_integer(wallet, 'id')
|
1588
|
-
if walletId is None:
|
1589
|
-
raise ExchangeError(self.id + ' fetchDepositAddress() could not find the wallet id for currency code ' + code + ', try to call createDepositAddress() first')
|
1590
|
-
request = {
|
1591
|
-
'walletId': walletId,
|
1592
|
-
}
|
1593
|
-
response = self.profileGetWalletsWalletId(self.extend(request, params))
|
1594
|
-
#
|
1595
|
-
# {
|
1596
|
-
# "success": True,
|
1597
|
-
# "data": {
|
1598
|
-
# "id": 45875,
|
1599
|
-
# "currency_id": 1,
|
1600
|
-
# "delisted": False,
|
1601
|
-
# "disabled": False,
|
1602
|
-
# "disable_deposits": False,
|
1603
|
-
# "code": "BTC",
|
1604
|
-
# "balance": "0.198752",
|
1605
|
-
# "frozen_balance": "1.5784",
|
1606
|
-
# "bonus_balance": "0.000",
|
1607
|
-
# "deposit_address": {
|
1608
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1609
|
-
# "address_name": "Address",
|
1610
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
1611
|
-
# "additional_address_parameter_name": "Destination Tag",
|
1612
|
-
# "notification": "",
|
1613
|
-
# "protocol_id": 10,
|
1614
|
-
# "protocol_name": "Tether OMNI",
|
1615
|
-
# "supports_new_address_creation": False
|
1616
|
-
# },
|
1617
|
-
# "multi_deposit_addresses": [
|
1618
|
-
# {
|
1619
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1620
|
-
# "address_name": "Address",
|
1621
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
1622
|
-
# "additional_address_parameter_name": "Destination Tag",
|
1623
|
-
# "notification": "",
|
1624
|
-
# "protocol_id": 10,
|
1625
|
-
# "protocol_name": "Tether OMNI",
|
1626
|
-
# "supports_new_address_creation": False
|
1627
|
-
# }
|
1628
|
-
# ],
|
1629
|
-
# "withdrawal_additional_field_name": "Payment ID(optional)",
|
1630
|
-
# "rates": {"BTC": 0.000001},
|
1631
|
-
# "protocol_specific_settings": [
|
1632
|
-
# {
|
1633
|
-
# "protocol_name": "Tether OMNI",
|
1634
|
-
# "protocol_id": 10,
|
1635
|
-
# "active": True,
|
1636
|
-
# "withdrawal_fee_currency_id": 1,
|
1637
|
-
# "withdrawal_fee_const": 0.002,
|
1638
|
-
# "withdrawal_fee_percent": 0,
|
1639
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
1640
|
-
# }
|
1641
|
-
# ]
|
1642
|
-
# }
|
1643
|
-
# }
|
1644
|
-
#
|
1645
|
-
data = self.safe_value(response, 'data', [])
|
1646
|
-
depositAddress = self.safe_value(data, 'deposit_address', {})
|
1647
|
-
address = self.safe_string(depositAddress, 'address')
|
1648
|
-
tag = self.safe_string(depositAddress, 'additional_address_parameter')
|
1649
|
-
self.check_address(address)
|
1650
|
-
return {
|
1651
|
-
'currency': code,
|
1652
|
-
'address': address,
|
1653
|
-
'tag': tag,
|
1654
|
-
'network': None,
|
1655
|
-
'info': response,
|
1656
|
-
}
|
1657
|
-
|
1658
|
-
def sign(self, path, api='public', method='GET', params={}, headers=None, body=None):
|
1659
|
-
url = self.urls['api']['rest'] + '/' + api + '/' + self.implode_params(path, params)
|
1660
|
-
query = self.omit(params, self.extract_params(path))
|
1661
|
-
if api == 'public':
|
1662
|
-
if query:
|
1663
|
-
url += '?' + self.urlencode(query)
|
1664
|
-
else:
|
1665
|
-
self.check_required_credentials()
|
1666
|
-
headers = {
|
1667
|
-
'Authorization': 'Bearer ' + self.token,
|
1668
|
-
}
|
1669
|
-
if method == 'GET' or method == 'DELETE':
|
1670
|
-
if query:
|
1671
|
-
url += '?' + self.urlencode(query)
|
1672
|
-
else:
|
1673
|
-
body = self.json(query)
|
1674
|
-
if query:
|
1675
|
-
headers['Content-Type'] = 'application/json'
|
1676
|
-
return {'url': url, 'method': method, 'body': body, 'headers': headers}
|
1677
|
-
|
1678
|
-
def parse_transaction_status(self, status):
|
1679
|
-
statuses = {
|
1680
|
-
'processing': 'pending',
|
1681
|
-
'checking by system': 'pending',
|
1682
|
-
'hodl': 'pending',
|
1683
|
-
'amount too low': 'failed',
|
1684
|
-
'not confirmed': 'pending',
|
1685
|
-
'cancelled by user': 'canceled',
|
1686
|
-
'approved': 'pending',
|
1687
|
-
'finished': 'ok',
|
1688
|
-
'withdrawal error': 'failed',
|
1689
|
-
'deposit error': 'failed',
|
1690
|
-
'cancelled by admin': 'canceled',
|
1691
|
-
'awaiting': 'pending',
|
1692
|
-
}
|
1693
|
-
return self.safe_string(statuses, status, status)
|
1694
|
-
|
1695
|
-
def parse_transaction(self, transaction, currency=None):
|
1696
|
-
#
|
1697
|
-
# fetchDeposit & fetchDeposits
|
1698
|
-
#
|
1699
|
-
# {
|
1700
|
-
# "id": 123654789,
|
1701
|
-
# "currency_id": 1,
|
1702
|
-
# "currency_code": "BTC",
|
1703
|
-
# "deposit_fee_currency_id": 1,
|
1704
|
-
# "deposit_fee_currency_code": "BTC",
|
1705
|
-
# "amount": 0.25,
|
1706
|
-
# "fee": 0.00025,
|
1707
|
-
# "txid": "qwertyuhgfdsasdfgh",
|
1708
|
-
# "protocol_id": 0,
|
1709
|
-
# "deposit_status_id": 1,
|
1710
|
-
# "status": "PROCESSING",
|
1711
|
-
# "status_color": "#BC3D51",
|
1712
|
-
# "created_at": "2018-11-28 12:32:08",
|
1713
|
-
# "timestamp": "1543409389",
|
1714
|
-
# "confirmations": "1 of 2"
|
1715
|
-
# }
|
1716
|
-
#
|
1717
|
-
# fetchWithdrawal and fetchWithdrawals
|
1718
|
-
#
|
1719
|
-
# {
|
1720
|
-
# "id": 65899,
|
1721
|
-
# "amount": "0.00600000",
|
1722
|
-
# "currency_id": 1,
|
1723
|
-
# "currency_code": "BTC",
|
1724
|
-
# "fee": "0.00400000",
|
1725
|
-
# "fee_currency_id": 1,
|
1726
|
-
# "fee_currency_code": "BTC",
|
1727
|
-
# "withdrawal_status_id": 1,
|
1728
|
-
# "status": "Not Confirmed",
|
1729
|
-
# "status_color": "#BC3D51",
|
1730
|
-
# "created_at": "2019-01-21 09:36:05",
|
1731
|
-
# "created_ts": "1548063365",
|
1732
|
-
# "updated_at": "2019-01-21 09:36:05",
|
1733
|
-
# "updated_ts": "1548063365",
|
1734
|
-
# "txid": null,
|
1735
|
-
# "protocol_id": 0,
|
1736
|
-
# "withdrawal_address": {
|
1737
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1738
|
-
# "address_name": "Address",
|
1739
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
1740
|
-
# "additional_address_parameter_name": "Destination Tag",
|
1741
|
-
# "notification": "",
|
1742
|
-
# "protocol_id": 10,
|
1743
|
-
# "protocol_name": "Tether OMNI",
|
1744
|
-
# "supports_new_address_creation": False
|
1745
|
-
# }
|
1746
|
-
# }
|
1747
|
-
#
|
1748
|
-
id = self.safe_string(transaction, 'id')
|
1749
|
-
withdrawalAddress = self.safe_value(transaction, 'withdrawal_address', {})
|
1750
|
-
address = self.safe_string(withdrawalAddress, 'address')
|
1751
|
-
tag = self.safe_string(withdrawalAddress, 'additional_address_parameter')
|
1752
|
-
currencyId = self.safe_string(transaction, 'currency_id')
|
1753
|
-
code = None
|
1754
|
-
if currencyId in self.currencies_by_id:
|
1755
|
-
currency = self.currencies_by_id[currencyId]
|
1756
|
-
else:
|
1757
|
-
code = self.common_currency_code(self.safe_string(transaction, 'currency_code'))
|
1758
|
-
if (code is None) and (currency is not None):
|
1759
|
-
code = currency['code']
|
1760
|
-
type = 'deposit' if ('deposit_status_id' in transaction) else 'withdrawal'
|
1761
|
-
amount = self.safe_number(transaction, 'amount')
|
1762
|
-
status = self.parse_transaction_status(self.safe_string_lower(transaction, 'status'))
|
1763
|
-
timestamp = self.safe_timestamp_2(transaction, 'timestamp', 'created_ts')
|
1764
|
-
updated = self.safe_timestamp(transaction, 'updated_ts')
|
1765
|
-
txid = self.safe_string(transaction, 'txid')
|
1766
|
-
fee = None
|
1767
|
-
feeCost = self.safe_number(transaction, 'fee')
|
1768
|
-
if feeCost is not None:
|
1769
|
-
feeCurrencyId = self.safe_string_2(transaction, 'fee_currency_id', 'deposit_fee_currency_id')
|
1770
|
-
feeCurrencyCode = self.safe_currency_code(feeCurrencyId)
|
1771
|
-
fee = {
|
1772
|
-
'cost': feeCost,
|
1773
|
-
'currency': feeCurrencyCode,
|
1774
|
-
}
|
1775
|
-
network = self.safe_string(withdrawalAddress, 'protocol_name')
|
1776
|
-
return {
|
1777
|
-
'info': transaction,
|
1778
|
-
'id': id,
|
1779
|
-
'txid': txid,
|
1780
|
-
'timestamp': timestamp,
|
1781
|
-
'datetime': self.iso8601(timestamp),
|
1782
|
-
'network': network,
|
1783
|
-
'addressFrom': None,
|
1784
|
-
'address': address,
|
1785
|
-
'addressTo': address,
|
1786
|
-
'tagFrom': None,
|
1787
|
-
'tag': tag,
|
1788
|
-
'tagTo': tag,
|
1789
|
-
'type': type,
|
1790
|
-
'amount': amount,
|
1791
|
-
'currency': code,
|
1792
|
-
'status': status,
|
1793
|
-
'updated': updated,
|
1794
|
-
'fee': fee,
|
1795
|
-
}
|
1796
|
-
|
1797
|
-
def fetch_deposit(self, id: str, code: Optional[str] = None, params={}):
|
1798
|
-
"""
|
1799
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1deposits~1{id}/get
|
1800
|
-
fetch information on a deposit
|
1801
|
-
:param str id: deposit id
|
1802
|
-
:param str|None code: not used by stex fetchDeposit()
|
1803
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1804
|
-
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1805
|
-
"""
|
1806
|
-
self.load_markets()
|
1807
|
-
request = {
|
1808
|
-
'id': id,
|
1809
|
-
}
|
1810
|
-
response = self.profileGetDepositsId(self.extend(request, params))
|
1811
|
-
#
|
1812
|
-
# {
|
1813
|
-
# success: True,
|
1814
|
-
# data: {
|
1815
|
-
# id: '21974074',
|
1816
|
-
# currency_id: '272',
|
1817
|
-
# block_explorer_url: 'https://omniexplorer.info/search/',
|
1818
|
-
# currency_code: 'USDT',
|
1819
|
-
# deposit_fee_currency_id: '272',
|
1820
|
-
# deposit_fee_currency_code: 'USDT',
|
1821
|
-
# amount: '11.00000000',
|
1822
|
-
# fee: '0.00000000',
|
1823
|
-
# deposit_status_id: '3',
|
1824
|
-
# status: 'FINISHED',
|
1825
|
-
# status_color: '#00BE75',
|
1826
|
-
# txid: '15b50da4600a5021dbddaed8f4a71de093bf206ea66eb4ab2f151e3e9e2fed71',
|
1827
|
-
# protocol_id: '24',
|
1828
|
-
# confirmations: '129 of 20',
|
1829
|
-
# created_at: '2022-05-16 16:38:40',
|
1830
|
-
# timestamp: '1652719120',
|
1831
|
-
# protocol_specific_settings: [{
|
1832
|
-
# protocol_name: 'TRON',
|
1833
|
-
# protocol_id: '24',
|
1834
|
-
# block_explorer_url: 'https://tronscan.org/#/transaction/'
|
1835
|
-
# }]
|
1836
|
-
# },
|
1837
|
-
# unified_message: {
|
1838
|
-
# message_id: 'operation_successful',
|
1839
|
-
# substitutions: []
|
1840
|
-
# }
|
1841
|
-
# }
|
1842
|
-
#
|
1843
|
-
data = self.safe_value(response, 'data', {})
|
1844
|
-
return self.parse_transaction(data)
|
1845
|
-
|
1846
|
-
def fetch_deposits(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
1847
|
-
"""
|
1848
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1deposits/get
|
1849
|
-
fetch all deposits made to an account
|
1850
|
-
:param str|None code: unified currency code
|
1851
|
-
:param int|None since: the earliest time in ms to fetch deposits for
|
1852
|
-
:param int|None limit: the maximum number of deposits structures to retrieve
|
1853
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1854
|
-
:returns [dict]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1855
|
-
"""
|
1856
|
-
self.load_markets()
|
1857
|
-
currency = None
|
1858
|
-
request = {}
|
1859
|
-
if code is not None:
|
1860
|
-
currency = self.currency(code)
|
1861
|
-
request['currencyId'] = currency['id']
|
1862
|
-
if limit is not None:
|
1863
|
-
request['limit'] = limit
|
1864
|
-
if since is not None:
|
1865
|
-
request['timeStart'] = since
|
1866
|
-
response = self.profileGetDeposits(self.extend(request, params))
|
1867
|
-
#
|
1868
|
-
# {
|
1869
|
-
# "success": True,
|
1870
|
-
# "data": [
|
1871
|
-
# {
|
1872
|
-
# "id": 123654789,
|
1873
|
-
# "currency_id": 1,
|
1874
|
-
# "currency_code": "BTC",
|
1875
|
-
# "deposit_fee_currency_id": 1,
|
1876
|
-
# "deposit_fee_currency_code": "BTC",
|
1877
|
-
# "amount": 0.25,
|
1878
|
-
# "fee": 0.00025,
|
1879
|
-
# "txid": "qwertyuhgfdsasdfgh",
|
1880
|
-
# "protocol_id": 0,
|
1881
|
-
# "deposit_status_id": 1,
|
1882
|
-
# "status": "PROCESSING",
|
1883
|
-
# "status_color": "#BC3D51",
|
1884
|
-
# "created_at": "2018-11-28 12:32:08",
|
1885
|
-
# "timestamp": "1543409389",
|
1886
|
-
# "confirmations": "1 of 2",
|
1887
|
-
# "protocol_specific_settings": {
|
1888
|
-
# "protocol_name": "Tether OMNI",
|
1889
|
-
# "protocol_id": 10,
|
1890
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
1891
|
-
# }
|
1892
|
-
# }
|
1893
|
-
# ]
|
1894
|
-
# }
|
1895
|
-
#
|
1896
|
-
deposits = self.safe_value(response, 'data', [])
|
1897
|
-
return self.parse_transactions(deposits, currency, since, limit)
|
1898
|
-
|
1899
|
-
def fetch_withdrawal(self, id: str, code: Optional[str] = None, params={}):
|
1900
|
-
"""
|
1901
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1withdrawals~1{id}/get
|
1902
|
-
fetch data on a currency withdrawal via the withdrawal id
|
1903
|
-
:param str id: withdrawal id
|
1904
|
-
:param str|None code: not used by stex.fetchWithdrawal
|
1905
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1906
|
-
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1907
|
-
"""
|
1908
|
-
self.load_markets()
|
1909
|
-
request = {
|
1910
|
-
'id': id,
|
1911
|
-
}
|
1912
|
-
response = self.profileGetWithdrawalsId(self.extend(request, params))
|
1913
|
-
#
|
1914
|
-
# {
|
1915
|
-
# "success": True,
|
1916
|
-
# "data": {
|
1917
|
-
# "id": 65899,
|
1918
|
-
# "amount": "0.00600000",
|
1919
|
-
# "currency_id": 1,
|
1920
|
-
# "currency_code": "BTC",
|
1921
|
-
# "fee": "0.00400000",
|
1922
|
-
# "fee_currency_id": 1,
|
1923
|
-
# "fee_currency_code": "BTC",
|
1924
|
-
# "withdrawal_status_id": 1,
|
1925
|
-
# "status": "Not Confirmed",
|
1926
|
-
# "status_color": "#BC3D51",
|
1927
|
-
# "created_at": "2019-01-21 09:36:05",
|
1928
|
-
# "created_ts": "1548063365",
|
1929
|
-
# "updated_at": "2019-01-21 09:36:05",
|
1930
|
-
# "updated_ts": "1548063365",
|
1931
|
-
# "reason": "string",
|
1932
|
-
# "txid": null,
|
1933
|
-
# "protocol_id": 0,
|
1934
|
-
# "withdrawal_address": {
|
1935
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1936
|
-
# "address_name": "Address",
|
1937
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
1938
|
-
# "additional_address_parameter_name": "Destination Tag",
|
1939
|
-
# "notification": "",
|
1940
|
-
# "protocol_id": 10,
|
1941
|
-
# "protocol_name": "Tether OMNI",
|
1942
|
-
# "supports_new_address_creation": False
|
1943
|
-
# },
|
1944
|
-
# "protocol_specific_settings": {
|
1945
|
-
# "protocol_name": "Tether OMNI",
|
1946
|
-
# "protocol_id": 10,
|
1947
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
1948
|
-
# }
|
1949
|
-
# }
|
1950
|
-
# }
|
1951
|
-
#
|
1952
|
-
data = self.safe_value(response, 'data', {})
|
1953
|
-
return self.parse_transaction(data)
|
1954
|
-
|
1955
|
-
def fetch_withdrawals(self, code: Optional[str] = None, since: Optional[int] = None, limit: Optional[int] = None, params={}):
|
1956
|
-
"""
|
1957
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1withdrawals/get
|
1958
|
-
fetch all withdrawals made from an account
|
1959
|
-
:param str|None code: unified currency code
|
1960
|
-
:param int|None since: the earliest time in ms to fetch withdrawals for
|
1961
|
-
:param int|None limit: the maximum number of withdrawals structures to retrieve
|
1962
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
1963
|
-
:returns [dict]: a list of `transaction structures <https://docs.ccxt.com/#/?id=transaction-structure>`
|
1964
|
-
"""
|
1965
|
-
self.load_markets()
|
1966
|
-
currency = None
|
1967
|
-
request = {}
|
1968
|
-
if code is not None:
|
1969
|
-
currency = self.currency(code)
|
1970
|
-
request['currencyId'] = currency['id']
|
1971
|
-
if limit is not None:
|
1972
|
-
request['limit'] = limit
|
1973
|
-
if since is not None:
|
1974
|
-
request['timeStart'] = since
|
1975
|
-
response = self.profileGetWithdrawals(self.extend(request, params))
|
1976
|
-
#
|
1977
|
-
# {
|
1978
|
-
# "success": True,
|
1979
|
-
# "data": [
|
1980
|
-
# {
|
1981
|
-
# "id": 65899,
|
1982
|
-
# "amount": "0.00600000",
|
1983
|
-
# "currency_id": 1,
|
1984
|
-
# "currency_code": "BTC",
|
1985
|
-
# "fee": "0.00400000",
|
1986
|
-
# "fee_currency_id": 1,
|
1987
|
-
# "fee_currency_code": "BTC",
|
1988
|
-
# "withdrawal_status_id": 1,
|
1989
|
-
# "status": "Not Confirmed",
|
1990
|
-
# "status_color": "#BC3D51",
|
1991
|
-
# "created_at": "2019-01-21 09:36:05",
|
1992
|
-
# "created_ts": "1548063365",
|
1993
|
-
# "updated_at": "2019-01-21 09:36:05",
|
1994
|
-
# "updated_ts": "1548063365",
|
1995
|
-
# "txid": null,
|
1996
|
-
# "protocol_id": 0,
|
1997
|
-
# "withdrawal_address": {
|
1998
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
1999
|
-
# "address_name": "Address",
|
2000
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
2001
|
-
# "additional_address_parameter_name": "Destination Tag",
|
2002
|
-
# "notification": "",
|
2003
|
-
# "protocol_id": 10,
|
2004
|
-
# "protocol_name": "Tether OMNI",
|
2005
|
-
# "supports_new_address_creation": False
|
2006
|
-
# },
|
2007
|
-
# "protocol_specific_settings": {
|
2008
|
-
# "protocol_name": "Tether OMNI",
|
2009
|
-
# "protocol_id": 10,
|
2010
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
2011
|
-
# }
|
2012
|
-
# }
|
2013
|
-
# ]
|
2014
|
-
# }
|
2015
|
-
#
|
2016
|
-
withdrawals = self.safe_value(response, 'data', [])
|
2017
|
-
return self.parse_transactions(withdrawals, currency, since, limit)
|
2018
|
-
|
2019
|
-
def transfer(self, code: str, amount, fromAccount, toAccount, params={}):
|
2020
|
-
"""
|
2021
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1referral~1bonus_transfer~1{currencyId}/post
|
2022
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1wallets~1{walletId}~1hold_amount/post
|
2023
|
-
transfer currency internally between wallets on the same account
|
2024
|
-
:param str code: unified currency code
|
2025
|
-
:param float amount: amount to transfer
|
2026
|
-
:param str fromAccount: account to transfer from
|
2027
|
-
:param str toAccount: account to transfer to
|
2028
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
2029
|
-
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
|
2030
|
-
"""
|
2031
|
-
self.load_markets()
|
2032
|
-
currency = self.currency(code)
|
2033
|
-
method = None
|
2034
|
-
request = {}
|
2035
|
-
if fromAccount == 'referal' and toAccount == 'spot':
|
2036
|
-
request['currencyId'] = currency['id']
|
2037
|
-
method = 'profilePostReferralBonusTransferCurrencyId'
|
2038
|
-
elif toAccount == 'hold':
|
2039
|
-
request['walletId'] = fromAccount
|
2040
|
-
amount = self.currency_to_precision(code, amount)
|
2041
|
-
amount = Precise.string_neg(amount)
|
2042
|
-
request['amount'] = amount
|
2043
|
-
method = 'profilePostWalletsWalletIdHoldAmount'
|
2044
|
-
elif fromAccount == 'hold':
|
2045
|
-
request['walletId'] = toAccount
|
2046
|
-
request['amount'] = amount
|
2047
|
-
method = 'profilePostWalletsWalletIdHoldAmount'
|
2048
|
-
else:
|
2049
|
-
raise ExchangeError(self.id + ' transfer() only allows transfers of referal to spot and between a walletId and funding')
|
2050
|
-
response = getattr(self, method)(self.extend(request, params))
|
2051
|
-
#
|
2052
|
-
# profilePostReferralBonusTransferCurrencyId
|
2053
|
-
# {
|
2054
|
-
# "success": True,
|
2055
|
-
# "data": ""
|
2056
|
-
# }
|
2057
|
-
#
|
2058
|
-
# profilePostWalletsWalletIdHoldAmount
|
2059
|
-
# {
|
2060
|
-
# success: True,
|
2061
|
-
# data: {
|
2062
|
-
# id: '4055802',
|
2063
|
-
# currency_id: '272',
|
2064
|
-
# currency_code: 'USDT',
|
2065
|
-
# currency_name: 'TetherUSD',
|
2066
|
-
# balance: '10.00000000',
|
2067
|
-
# frozen_balance: '0.00000000',
|
2068
|
-
# bonus_balance: '0.00000000',
|
2069
|
-
# hold_balance: '1.00000000',
|
2070
|
-
# total_balance: '11.00000000',
|
2071
|
-
# disable_deposits: False,
|
2072
|
-
# disable_withdrawals: False,
|
2073
|
-
# withdrawal_limit: '0.00000000',
|
2074
|
-
# delisted: False,
|
2075
|
-
# disabled: False,
|
2076
|
-
# deposit_address: null,
|
2077
|
-
# multi_deposit_addresses: [{
|
2078
|
-
# address: 'TYzhabfHWMLgLnMW46ZyUHkUVJPXaDgdxK',
|
2079
|
-
# address_name: 'Deposit Address',
|
2080
|
-
# additional_address_parameter: null,
|
2081
|
-
# additional_address_parameter_name: null,
|
2082
|
-
# notification: '',
|
2083
|
-
# protocol_id: '24',
|
2084
|
-
# protocol_name: 'TRON',
|
2085
|
-
# supports_new_address_creation: False
|
2086
|
-
# }],
|
2087
|
-
# contract_or_asset_id: '31',
|
2088
|
-
# contract_field_name: null,
|
2089
|
-
# withdrawal_additional_field_name: null,
|
2090
|
-
# depo_message: '',
|
2091
|
-
# wd_message: '',
|
2092
|
-
# currency_type_id: '23',
|
2093
|
-
# protocol_specific_settings: [{
|
2094
|
-
# {
|
2095
|
-
# protocol_name: 'ERC20',
|
2096
|
-
# protocol_id: '5',
|
2097
|
-
# active: True,
|
2098
|
-
# disable_deposits: False,
|
2099
|
-
# disable_withdrawals: False,
|
2100
|
-
# withdrawal_limit: '0',
|
2101
|
-
# deposit_fee_currency_id: '272',
|
2102
|
-
# deposit_fee_currency_code: 'USDT',
|
2103
|
-
# deposit_fee_percent: '0',
|
2104
|
-
# deposit_fee_const: '0',
|
2105
|
-
# withdrawal_fee_currency_id: '272',
|
2106
|
-
# withdrawal_fee_currency_code: 'USDT',
|
2107
|
-
# withdrawal_fee_const: '10',
|
2108
|
-
# withdrawal_fee_percent: '0',
|
2109
|
-
# block_explorer_url: 'https://etherscan.io/tx/',
|
2110
|
-
# contract_or_asset_id: '0xdac17f958d2ee523a2206206994597c13d831ec7',
|
2111
|
-
# contract_field_name: '',
|
2112
|
-
# withdrawal_additional_field_name: '',
|
2113
|
-
# depo_message: '',
|
2114
|
-
# wd_message: ''
|
2115
|
-
# },
|
2116
|
-
# ...
|
2117
|
-
# ],
|
2118
|
-
# coin_info: {
|
2119
|
-
# twitter: 'https://twitter.com/Tether_to',
|
2120
|
-
# version: '',
|
2121
|
-
# facebook: 'https://www.facebook.com/tether.to',
|
2122
|
-
# telegram: '',
|
2123
|
-
# icon_large: 'https://app-coin-images.stex.com/large/usdt.png',
|
2124
|
-
# icon_small: 'https://app-coin-images.stex.com/small/usdt.png',
|
2125
|
-
# description: 'Tether(USDT) is a cryptocurrency with a value meant to mirror the value of the U.S. dollar. The idea was to create a stable cryptocurrency that can be used like digital dollars. Coins that serve self purpose of being a stable dollar substitute are called “stable coins.” Tether is the most popular stable coin and even acts dollar replacement on many popular exchanges! According to their site, Tether converts cash into digital currency, to anchor or “tether” the value of the coin to the price of national currencies like the US dollar, the Euro, and the Yen. Like other cryptos it uses blockchain. Unlike other cryptos, it is [according to the official Tether site] “100% backed by USD”(USD is held in reserve). The primary use of Tether is that it offers some stability to the otherwise volatile crypto space and offers liquidity to exchanges who can’t deal in dollars and with banks(for example to the sometimes controversial but leading exchange Bitfinex).The digital coins are issued by a company called Tether Limited that is governed by the laws of the British Virgin Islands, according to the legal part of its website. It is incorporated in Hong Kong. It has emerged that Jan Ludovicus van der Velde is the CEO of cryptocurrency exchange Bitfinex, which has been accused of being involved in the price manipulation of bitcoin,. Many people trading on exchanges, including Bitfinex, will use tether to buy other cryptocurrencies like bitcoin. Tether Limited argues that using self method to buy virtual currencies allows users to move fiat in and out of an exchange more quickly and cheaply. Also, exchanges typically have rocky relationships with banks, and using Tether is a way to circumvent that.USDT is fairly simple to use. Once on exchanges like Poloniex or Bittrex, it can be used to purchase Bitcoin and other cryptocurrencies. It can be easily transferred from an exchange to any Omni Layer enabled wallet. Tether has no transaction fees, although external wallets and exchanges may charge one. In order to convert USDT to USD and vise versa through the Tether.to Platform, users must pay a small fee. Buying and selling Tether for Bitcoin can be done through a variety of exchanges like the ones mentioned previously or through the Tether.to platform, which also allows the conversion between USD to and from your bank account.',
|
2126
|
-
# official_site: 'https://tether.to/',
|
2127
|
-
# official_block_explorer: 'https://etherscan.io/token/0xdac17f958d2ee523a2206206994597c13d831ec7'
|
2128
|
-
# },
|
2129
|
-
# rates: {
|
2130
|
-
# BTC: '0.00003372',
|
2131
|
-
# USD: '1'
|
2132
|
-
# }
|
2133
|
-
# },
|
2134
|
-
# unified_message: {
|
2135
|
-
# message_id: 'operation_successful',
|
2136
|
-
# substitutions: []
|
2137
|
-
# }
|
2138
|
-
# }
|
2139
|
-
#
|
2140
|
-
data = self.safe_value(response, 'data', {})
|
2141
|
-
transfer = self.parse_transfer(data, currency)
|
2142
|
-
transferOptions = self.safe_value(self.options, 'transfer', {})
|
2143
|
-
fillResponseFromRequest = self.safe_value(transferOptions, 'fillResponseFromRequest', True)
|
2144
|
-
if fillResponseFromRequest:
|
2145
|
-
transfer['fromAccount'] = fromAccount
|
2146
|
-
transfer['toAccount'] = toAccount
|
2147
|
-
if isinstance(amount, str) and Precise.string_lt(amount, '0'):
|
2148
|
-
amount = self.parse_number(Precise.string_neg(amount))
|
2149
|
-
transfer['amount'] = amount
|
2150
|
-
if transfer['currency'] is None:
|
2151
|
-
transfer['currency'] = code
|
2152
|
-
return transfer
|
2153
|
-
|
2154
|
-
def parse_transfer(self, transfer, currency=None):
|
2155
|
-
#
|
2156
|
-
# {
|
2157
|
-
# "id": 45875,
|
2158
|
-
# "currency_id": 1,
|
2159
|
-
# "currency_code": "USDT",
|
2160
|
-
# "currency_name": "TetherUSD",
|
2161
|
-
# "balance": "0.198752",
|
2162
|
-
# "frozen_balance": "1.5784",
|
2163
|
-
# "bonus_balance": "0.000",
|
2164
|
-
# "hold_balance": "0.000",
|
2165
|
-
# "total_balance": "1.777152",
|
2166
|
-
# "disable_deposits": False,
|
2167
|
-
# "disable_withdrawals": False,
|
2168
|
-
# "withdrawal_limit": "string",
|
2169
|
-
# "delisted": False,
|
2170
|
-
# "disabled": False,
|
2171
|
-
# "deposit_address": {
|
2172
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
2173
|
-
# "address_name": "Address",
|
2174
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
2175
|
-
# "additional_address_parameter_name": "Destination Tag",
|
2176
|
-
# "notification": "",
|
2177
|
-
# "protocol_id": 10,
|
2178
|
-
# "protocol_name": "Tether OMNI",
|
2179
|
-
# "supports_new_address_creation": False
|
2180
|
-
# },
|
2181
|
-
# "multi_deposit_addresses": [{
|
2182
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
2183
|
-
# "address_name": "Address",
|
2184
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
2185
|
-
# "additional_address_parameter_name": "Destination Tag",
|
2186
|
-
# "notification": "",
|
2187
|
-
# "protocol_id": 10,
|
2188
|
-
# "protocol_name": "Tether OMNI",
|
2189
|
-
# "supports_new_address_creation": False
|
2190
|
-
# }],
|
2191
|
-
# "withdrawal_additional_field_name": "Payment ID(optional)",
|
2192
|
-
# "currency_type_id": 23,
|
2193
|
-
# "protocol_specific_settings": [{
|
2194
|
-
# "protocol_name": "Tether OMNI",
|
2195
|
-
# "protocol_id": 10,
|
2196
|
-
# "active": True,
|
2197
|
-
# "disable_deposits": False,
|
2198
|
-
# "disable_withdrawals": False,
|
2199
|
-
# "withdrawal_limit": 0,
|
2200
|
-
# "deposit_fee_currency_id": 272,
|
2201
|
-
# "deposit_fee_currency_code": "USDT",
|
2202
|
-
# "deposit_fee_percent": 0,
|
2203
|
-
# "deposit_fee_const": 0,
|
2204
|
-
# "withdrawal_fee_currency_id": 1,
|
2205
|
-
# "withdrawal_fee_currency_code": "USDT",
|
2206
|
-
# "withdrawal_fee_const": 0.002,
|
2207
|
-
# "withdrawal_fee_percent": 0,
|
2208
|
-
# "block_explorer_url": "https://omniexplorer.info/search/",
|
2209
|
-
# "withdrawal_additional_field_name": ""
|
2210
|
-
# }],
|
2211
|
-
# "coin_info": {
|
2212
|
-
# "twitter": "https://twitter.com/btc",
|
2213
|
-
# "version": "",
|
2214
|
-
# "facebook": "https://www.facebook.com/bitcoins",
|
2215
|
-
# "telegram": "",
|
2216
|
-
# "icon_large": "https://app-coin-images.stex.com/large/btc.png",
|
2217
|
-
# "icon_small": "https://app-coin-images.stex.com/small/btc.png",
|
2218
|
-
# "description": "Bitcoin is the first successful internet money based on peer-to-peer technology;....",
|
2219
|
-
# "official_site": "http://www.bitcoin.org",
|
2220
|
-
# "official_block_explorer": "https://blockchair.com/bitcoin/"
|
2221
|
-
# },
|
2222
|
-
# "rates": {
|
2223
|
-
# "BTC": 0.000001
|
2224
|
-
# }
|
2225
|
-
# }
|
2226
|
-
#
|
2227
|
-
currencyId = self.safe_string(transfer, 'currency_id')
|
2228
|
-
code = None
|
2229
|
-
if currencyId in self.currencies_by_id:
|
2230
|
-
currency = self.currencies_by_id[currencyId]
|
2231
|
-
else:
|
2232
|
-
code = self.common_currency_code(self.safe_string(transfer, 'currency_code'))
|
2233
|
-
if code is None:
|
2234
|
-
code = self.safe_value(currency, 'code')
|
2235
|
-
return {
|
2236
|
-
'info': transfer,
|
2237
|
-
'id': self.safe_string(transfer, 'id'),
|
2238
|
-
'timestamp': None,
|
2239
|
-
'datetime': None,
|
2240
|
-
'currency': code,
|
2241
|
-
'amount': None,
|
2242
|
-
'fromAccount': None,
|
2243
|
-
'toAccount': None,
|
2244
|
-
'status': None,
|
2245
|
-
}
|
2246
|
-
|
2247
|
-
def withdraw(self, code: str, amount, address, tag=None, params={}):
|
2248
|
-
"""
|
2249
|
-
see https://apidocs.stex.com/#tag/Profile/paths/~1profile~1withdraw/post
|
2250
|
-
make a withdrawal
|
2251
|
-
:param str code: unified currency code
|
2252
|
-
:param float amount: the amount to withdraw
|
2253
|
-
:param str address: the address to withdraw to
|
2254
|
-
:param str|None tag:
|
2255
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
2256
|
-
:returns dict: a `transaction structure <https://docs.ccxt.com/#/?id=transaction-structure>`
|
2257
|
-
"""
|
2258
|
-
tag, params = self.handle_withdraw_tag_and_params(tag, params)
|
2259
|
-
self.check_address(address)
|
2260
|
-
self.load_markets()
|
2261
|
-
currency = self.currency(code)
|
2262
|
-
request = {
|
2263
|
-
'currency_id': currency['id'],
|
2264
|
-
'amount': float(self.currency_to_precision(code, amount)),
|
2265
|
-
'address': address,
|
2266
|
-
# 'protocol_id': 10, # optional, to be used with multicurrency wallets like USDT
|
2267
|
-
# 'additional_address_parameter': tag, # optional
|
2268
|
-
}
|
2269
|
-
if tag is not None:
|
2270
|
-
request['additional_address_parameter'] = tag
|
2271
|
-
networks = self.safe_value(self.options, 'networks', {})
|
2272
|
-
networkRaw = self.safe_string_upper(params, 'network') # self line allows the user to specify either ERC20 or ETH
|
2273
|
-
network = self.safe_integer(networks, networkRaw, self.parse_to_int(networkRaw)) # handle ERC20>ETH alias
|
2274
|
-
if network is not None:
|
2275
|
-
request['protocol_id'] = network
|
2276
|
-
params = self.omit(params, 'network')
|
2277
|
-
response = self.profilePostWithdraw(self.extend(request, params))
|
2278
|
-
#
|
2279
|
-
# {
|
2280
|
-
# "success": True,
|
2281
|
-
# "data": {
|
2282
|
-
# "id": 65899,
|
2283
|
-
# "amount": "0.00600000",
|
2284
|
-
# "currency_id": 1,
|
2285
|
-
# "currency_code": "BTC",
|
2286
|
-
# "fee": "0.00400000",
|
2287
|
-
# "fee_currency_id": 1,
|
2288
|
-
# "fee_currency_code": "BTC",
|
2289
|
-
# "withdrawal_status_id": 1,
|
2290
|
-
# "status": "Not Confirmed",
|
2291
|
-
# "status_color": "#BC3D51",
|
2292
|
-
# "created_at": "2019-01-21 09:36:05",
|
2293
|
-
# "created_ts": "1548063365",
|
2294
|
-
# "updated_at": "2019-01-21 09:36:05",
|
2295
|
-
# "updated_ts": "1548063365",
|
2296
|
-
# "txid": null,
|
2297
|
-
# "protocol_id": 0,
|
2298
|
-
# "withdrawal_address": {
|
2299
|
-
# "address": "0X12WERTYUIIJHGFVBNMJHGDFGHJ765SDFGHJ",
|
2300
|
-
# "address_name": "Address",
|
2301
|
-
# "additional_address_parameter": "qwertyuiopasdfghjkl",
|
2302
|
-
# "additional_address_parameter_name": "Destination Tag",
|
2303
|
-
# "notification": "",
|
2304
|
-
# "protocol_id": 10,
|
2305
|
-
# "protocol_name": "Tether OMNI",
|
2306
|
-
# "supports_new_address_creation": False
|
2307
|
-
# }
|
2308
|
-
# }
|
2309
|
-
# }
|
2310
|
-
#
|
2311
|
-
data = self.safe_value(response, 'data', {})
|
2312
|
-
return self.parse_transaction(data, currency)
|
2313
|
-
|
2314
|
-
def fetch_transaction_fees(self, codes=None, params={}):
|
2315
|
-
"""
|
2316
|
-
*DEPRECATED* please use fetchDepositWithdrawFees instead
|
2317
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1currencies/get
|
2318
|
-
:param [str]|None codes: list of unified currency codes
|
2319
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
2320
|
-
:returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
|
2321
|
-
"""
|
2322
|
-
self.load_markets()
|
2323
|
-
#
|
2324
|
-
# {
|
2325
|
-
# "success": True,
|
2326
|
-
# "data": [
|
2327
|
-
# {
|
2328
|
-
# "id": 1,
|
2329
|
-
# "code": "BTC",
|
2330
|
-
# "name": "Bitcoin",
|
2331
|
-
# "active": True,
|
2332
|
-
# "delisted": False,
|
2333
|
-
# "precision": 8,
|
2334
|
-
# "minimum_tx_confirmations": 24,
|
2335
|
-
# "minimum_withdrawal_amount": "0.009",
|
2336
|
-
# "minimum_deposit_amount": "0.000003",
|
2337
|
-
# "deposit_fee_currency_id": 1,
|
2338
|
-
# "deposit_fee_currency_code": "ETH",
|
2339
|
-
# "deposit_fee_const": "0.00001",
|
2340
|
-
# "deposit_fee_percent": "0",
|
2341
|
-
# "withdrawal_fee_currency_id": 1,
|
2342
|
-
# "withdrawal_fee_currency_code": "ETH",
|
2343
|
-
# "withdrawal_fee_const": "0.0015",
|
2344
|
-
# "withdrawal_fee_percent": "0",
|
2345
|
-
# "withdrawal_limit": "string",
|
2346
|
-
# "block_explorer_url": "https://blockchain.info/tx/",
|
2347
|
-
# "protocol_specific_settings": [
|
2348
|
-
# {
|
2349
|
-
# "protocol_name": "Tether OMNI",
|
2350
|
-
# "protocol_id": 10,
|
2351
|
-
# "active": True,
|
2352
|
-
# "withdrawal_fee_currency_id": 1,
|
2353
|
-
# "withdrawal_fee_const": 0.002,
|
2354
|
-
# "withdrawal_fee_percent": 0,
|
2355
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
2356
|
-
# }
|
2357
|
-
# ]
|
2358
|
-
# }
|
2359
|
-
# ]
|
2360
|
-
# }
|
2361
|
-
#
|
2362
|
-
currencyKeys = list(self.currencies.keys())
|
2363
|
-
result = {}
|
2364
|
-
for i in range(0, len(currencyKeys)):
|
2365
|
-
code = currencyKeys[i]
|
2366
|
-
currency = self.currencies[code]
|
2367
|
-
if codes is not None and not self.in_array(code, codes):
|
2368
|
-
continue
|
2369
|
-
info = self.safe_value(currency, 'info')
|
2370
|
-
result[code] = {
|
2371
|
-
'withdraw': self.safe_number(currency, 'fee'),
|
2372
|
-
'deposit': self.safe_number(info, 'deposit_fee_const'),
|
2373
|
-
'info': info,
|
2374
|
-
}
|
2375
|
-
return result
|
2376
|
-
|
2377
|
-
def fetch_deposit_withdraw_fees(self, codes=None, params={}):
|
2378
|
-
"""
|
2379
|
-
fetch deposit and withdraw fees
|
2380
|
-
see https://apidocs.stex.com/#tag/Public/paths/~1public~1currencies/get
|
2381
|
-
:param [str]|None codes: list of unified currency codes
|
2382
|
-
:param dict params: extra parameters specific to the stex api endpoint
|
2383
|
-
:returns dict: a list of `fee structures <https://docs.ccxt.com/#/?id=fee-structure>`
|
2384
|
-
"""
|
2385
|
-
self.load_markets()
|
2386
|
-
response = self.publicGetCurrencies(params)
|
2387
|
-
#
|
2388
|
-
# {
|
2389
|
-
# "success": True,
|
2390
|
-
# "data": [
|
2391
|
-
# {
|
2392
|
-
# "id": 1,
|
2393
|
-
# "code": "BTC",
|
2394
|
-
# "name": "Bitcoin",
|
2395
|
-
# "active": True,
|
2396
|
-
# "delisted": False,
|
2397
|
-
# "precision": 8,
|
2398
|
-
# "minimum_tx_confirmations": 24,
|
2399
|
-
# "minimum_withdrawal_amount": "0.009",
|
2400
|
-
# "minimum_deposit_amount": "0.000003",
|
2401
|
-
# "deposit_fee_currency_id": 1,
|
2402
|
-
# "deposit_fee_currency_code": "ETH",
|
2403
|
-
# "deposit_fee_const": "0.00001",
|
2404
|
-
# "deposit_fee_percent": "0",
|
2405
|
-
# "withdrawal_fee_currency_id": 1,
|
2406
|
-
# "withdrawal_fee_currency_code": "ETH",
|
2407
|
-
# "withdrawal_fee_const": "0.0015",
|
2408
|
-
# "withdrawal_fee_percent": "0",
|
2409
|
-
# "withdrawal_limit": "string",
|
2410
|
-
# "block_explorer_url": "https://blockchain.info/tx/",
|
2411
|
-
# "protocol_specific_settings": [
|
2412
|
-
# {
|
2413
|
-
# "protocol_name": "Tether OMNI",
|
2414
|
-
# "protocol_id": 10,
|
2415
|
-
# "active": True,
|
2416
|
-
# "withdrawal_fee_currency_id": 1,
|
2417
|
-
# "withdrawal_fee_const": 0.002,
|
2418
|
-
# "withdrawal_fee_percent": 0,
|
2419
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
2420
|
-
# }
|
2421
|
-
# ]
|
2422
|
-
# }
|
2423
|
-
# ...
|
2424
|
-
# ]
|
2425
|
-
# }
|
2426
|
-
#
|
2427
|
-
data = self.safe_value(response, 'data')
|
2428
|
-
return self.parse_deposit_withdraw_fees(data, codes, 'code')
|
2429
|
-
|
2430
|
-
def parse_deposit_withdraw_fee(self, fee, currency=None):
|
2431
|
-
#
|
2432
|
-
# {
|
2433
|
-
# "id": 1,
|
2434
|
-
# "code": "BTC",
|
2435
|
-
# "name": "Bitcoin",
|
2436
|
-
# "active": True,
|
2437
|
-
# "delisted": False,
|
2438
|
-
# "precision": 8,
|
2439
|
-
# "minimum_tx_confirmations": 24,
|
2440
|
-
# "minimum_withdrawal_amount": "0.009",
|
2441
|
-
# "minimum_deposit_amount": "0.000003",
|
2442
|
-
# "deposit_fee_currency_id": 1,
|
2443
|
-
# "deposit_fee_currency_code": "ETH",
|
2444
|
-
# "deposit_fee_const": "0.00001",
|
2445
|
-
# "deposit_fee_percent": "0",
|
2446
|
-
# "withdrawal_fee_currency_id": 1,
|
2447
|
-
# "withdrawal_fee_currency_code": "ETH",
|
2448
|
-
# "withdrawal_fee_const": "0.0015",
|
2449
|
-
# "withdrawal_fee_percent": "0",
|
2450
|
-
# "withdrawal_limit": "string",
|
2451
|
-
# "block_explorer_url": "https://blockchain.info/tx/",
|
2452
|
-
# "protocol_specific_settings": [
|
2453
|
-
# {
|
2454
|
-
# "protocol_name": "Tether OMNI",
|
2455
|
-
# "protocol_id": 10,
|
2456
|
-
# "active": True,
|
2457
|
-
# "withdrawal_fee_currency_id": 1,
|
2458
|
-
# "withdrawal_fee_const": 0.002,
|
2459
|
-
# "withdrawal_fee_percent": 0,
|
2460
|
-
# "block_explorer_url": "https://omniexplorer.info/search/"
|
2461
|
-
# }
|
2462
|
-
# ]
|
2463
|
-
# }
|
2464
|
-
#
|
2465
|
-
result = {
|
2466
|
-
'withdraw': {
|
2467
|
-
'fee': self.safe_number(fee, 'withdrawal_fee_const'),
|
2468
|
-
'percentage': False,
|
2469
|
-
},
|
2470
|
-
'deposit': {
|
2471
|
-
'fee': self.safe_number(fee, 'deposit_fee_const'),
|
2472
|
-
'percentage': False,
|
2473
|
-
},
|
2474
|
-
'networks': {},
|
2475
|
-
}
|
2476
|
-
networks = self.safe_value(fee, 'protocol_specific_settings', [])
|
2477
|
-
for i in range(0, len(networks)):
|
2478
|
-
network = networks[i]
|
2479
|
-
networkId = self.safe_string(network, 'protocol_name')
|
2480
|
-
networkCode = self.network_id_to_code(networkId)
|
2481
|
-
result['networks'][networkCode] = {
|
2482
|
-
'withdraw': {
|
2483
|
-
'fee': self.safe_number(network, 'withdrawal_fee_const'),
|
2484
|
-
'percentage': False,
|
2485
|
-
},
|
2486
|
-
'deposit': {
|
2487
|
-
'fee': None,
|
2488
|
-
'percentage': None,
|
2489
|
-
},
|
2490
|
-
}
|
2491
|
-
return result
|
2492
|
-
|
2493
|
-
def handle_errors(self, httpCode, reason, url, method, headers, body, response, requestHeaders, requestBody):
|
2494
|
-
if response is None:
|
2495
|
-
return None # fallback to default error handler
|
2496
|
-
#
|
2497
|
-
# {"success":false,"message":"Wrong parameters","errors":{"candleType":["Invalid Candle Type!"]}}
|
2498
|
-
# {"success":false,"message":"Wrong parameters","errors":{"time":["timeStart or timeEnd is less then 1"]}}
|
2499
|
-
# {"success":false,"message":"Not enough ETH"}
|
2500
|
-
#
|
2501
|
-
success = self.safe_value(response, 'success', False)
|
2502
|
-
if not success:
|
2503
|
-
message = self.safe_string(response, 'message')
|
2504
|
-
feedback = self.id + ' ' + body
|
2505
|
-
self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
|
2506
|
-
self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
|
2507
|
-
raise ExchangeError(feedback) # unknown message
|
2508
|
-
return None
|