ccxt 4.2.68__py2.py3-none-any.whl → 4.2.70__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.
Potentially problematic release.
This version of ccxt might be problematic. Click here for more details.
- ccxt/__init__.py +1 -1
- ccxt/abstract/htx.py +1 -0
- ccxt/abstract/huobi.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/bitstamp.py +64 -1
- ccxt/async_support/gate.py +166 -3
- ccxt/async_support/gemini.py +147 -70
- ccxt/async_support/hitbtc.py +7 -0
- ccxt/async_support/htx.py +1 -0
- ccxt/async_support/kucoin.py +4 -2
- ccxt/base/exchange.py +1 -1
- ccxt/bitstamp.py +64 -1
- ccxt/gate.py +166 -3
- ccxt/gemini.py +147 -70
- ccxt/hitbtc.py +7 -0
- ccxt/htx.py +1 -0
- ccxt/kucoin.py +4 -2
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/lbank.py +5 -3
- {ccxt-4.2.68.dist-info → ccxt-4.2.70.dist-info}/METADATA +4 -4
- {ccxt-4.2.68.dist-info → ccxt-4.2.70.dist-info}/RECORD +24 -24
- {ccxt-4.2.68.dist-info → ccxt-4.2.70.dist-info}/WHEEL +0 -0
- {ccxt-4.2.68.dist-info → ccxt-4.2.70.dist-info}/top_level.txt +0 -0
ccxt/__init__.py
CHANGED
ccxt/abstract/htx.py
CHANGED
@@ -193,6 +193,7 @@ class ImplicitAPI:
|
|
193
193
|
spot_private_post_v2_sub_user_api_key_modification = spotPrivatePostV2SubUserApiKeyModification = Entry('v2/sub-user/api-key-modification', ['spot', 'private'], 'POST', {'cost': 1})
|
194
194
|
spot_private_post_v2_sub_user_api_key_deletion = spotPrivatePostV2SubUserApiKeyDeletion = Entry('v2/sub-user/api-key-deletion', ['spot', 'private'], 'POST', {'cost': 1})
|
195
195
|
spot_private_post_v1_subuser_transfer = spotPrivatePostV1SubuserTransfer = Entry('v1/subuser/transfer', ['spot', 'private'], 'POST', {'cost': 10})
|
196
|
+
spot_private_post_v1_trust_user_active_credit = spotPrivatePostV1TrustUserActiveCredit = Entry('v1/trust/user/active/credit', ['spot', 'private'], 'POST', {'cost': 10})
|
196
197
|
spot_private_post_v1_order_orders_place = spotPrivatePostV1OrderOrdersPlace = Entry('v1/order/orders/place', ['spot', 'private'], 'POST', {'cost': 0.2})
|
197
198
|
spot_private_post_v1_order_batch_orders = spotPrivatePostV1OrderBatchOrders = Entry('v1/order/batch-orders', ['spot', 'private'], 'POST', {'cost': 0.4})
|
198
199
|
spot_private_post_v1_order_auto_place = spotPrivatePostV1OrderAutoPlace = Entry('v1/order/auto/place', ['spot', 'private'], 'POST', {'cost': 0.2})
|
ccxt/abstract/huobi.py
CHANGED
@@ -193,6 +193,7 @@ class ImplicitAPI:
|
|
193
193
|
spot_private_post_v2_sub_user_api_key_modification = spotPrivatePostV2SubUserApiKeyModification = Entry('v2/sub-user/api-key-modification', ['spot', 'private'], 'POST', {'cost': 1})
|
194
194
|
spot_private_post_v2_sub_user_api_key_deletion = spotPrivatePostV2SubUserApiKeyDeletion = Entry('v2/sub-user/api-key-deletion', ['spot', 'private'], 'POST', {'cost': 1})
|
195
195
|
spot_private_post_v1_subuser_transfer = spotPrivatePostV1SubuserTransfer = Entry('v1/subuser/transfer', ['spot', 'private'], 'POST', {'cost': 10})
|
196
|
+
spot_private_post_v1_trust_user_active_credit = spotPrivatePostV1TrustUserActiveCredit = Entry('v1/trust/user/active/credit', ['spot', 'private'], 'POST', {'cost': 10})
|
196
197
|
spot_private_post_v1_order_orders_place = spotPrivatePostV1OrderOrdersPlace = Entry('v1/order/orders/place', ['spot', 'private'], 'POST', {'cost': 0.2})
|
197
198
|
spot_private_post_v1_order_batch_orders = spotPrivatePostV1OrderBatchOrders = Entry('v1/order/batch-orders', ['spot', 'private'], 'POST', {'cost': 0.4})
|
198
199
|
spot_private_post_v1_order_auto_place = spotPrivatePostV1OrderAutoPlace = Entry('v1/order/auto/place', ['spot', 'private'], 'POST', {'cost': 0.2})
|
ccxt/async_support/__init__.py
CHANGED
ccxt/async_support/bitstamp.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.bitstamp import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
9
|
+
from ccxt.base.types import Balances, Currency, Int, Market, Order, TransferEntry, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import PermissionDenied
|
@@ -98,6 +98,7 @@ class bitstamp(Exchange, ImplicitAPI):
|
|
98
98
|
'setLeverage': False,
|
99
99
|
'setMarginMode': False,
|
100
100
|
'setPositionMode': False,
|
101
|
+
'transfer': True,
|
101
102
|
'withdraw': True,
|
102
103
|
},
|
103
104
|
'urls': {
|
@@ -1983,6 +1984,68 @@ class bitstamp(Exchange, ImplicitAPI):
|
|
1983
1984
|
response = await getattr(self, method)(self.extend(request, params))
|
1984
1985
|
return self.parse_transaction(response, currency)
|
1985
1986
|
|
1987
|
+
async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
|
1988
|
+
"""
|
1989
|
+
transfer currency internally between wallets on the same account
|
1990
|
+
:see: https://www.bitstamp.net/api/#tag/Sub-account/operation/TransferFromMainToSub
|
1991
|
+
:see: https://www.bitstamp.net/api/#tag/Sub-account/operation/TransferFromSubToMain
|
1992
|
+
:param str code: unified currency code
|
1993
|
+
:param float amount: amount to transfer
|
1994
|
+
:param str fromAccount: account to transfer from
|
1995
|
+
:param str toAccount: account to transfer to
|
1996
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1997
|
+
:returns dict: a `transfer structure <https://docs.ccxt.com/#/?id=transfer-structure>`
|
1998
|
+
"""
|
1999
|
+
await self.load_markets()
|
2000
|
+
currency = self.currency(code)
|
2001
|
+
amount = self.currency_to_precision(code, amount)
|
2002
|
+
amount = self.parse_to_numeric(amount)
|
2003
|
+
request = {
|
2004
|
+
'amount': amount,
|
2005
|
+
'currency': currency['id'].upper(),
|
2006
|
+
}
|
2007
|
+
response = None
|
2008
|
+
if fromAccount == 'main':
|
2009
|
+
request['subAccount'] = toAccount
|
2010
|
+
response = await self.privatePostTransferFromMain(self.extend(request, params))
|
2011
|
+
elif toAccount == 'main':
|
2012
|
+
request['subAccount'] = fromAccount
|
2013
|
+
response = await self.privatePostTransferToMain(self.extend(request, params))
|
2014
|
+
else:
|
2015
|
+
raise BadRequest(self.id + ' transfer() only supports from or to main')
|
2016
|
+
#
|
2017
|
+
# {status: 'ok'}
|
2018
|
+
#
|
2019
|
+
transfer = self.parse_transfer(response, currency)
|
2020
|
+
transfer['amount'] = amount
|
2021
|
+
transfer['fromAccount'] = fromAccount
|
2022
|
+
transfer['toAccount'] = toAccount
|
2023
|
+
return transfer
|
2024
|
+
|
2025
|
+
def parse_transfer(self, transfer, currency=None):
|
2026
|
+
#
|
2027
|
+
# {status: 'ok'}
|
2028
|
+
#
|
2029
|
+
status = self.safe_string(transfer, 'status')
|
2030
|
+
return {
|
2031
|
+
'info': transfer,
|
2032
|
+
'id': None,
|
2033
|
+
'timestamp': None,
|
2034
|
+
'datetime': None,
|
2035
|
+
'currency': currency['code'],
|
2036
|
+
'amount': None,
|
2037
|
+
'fromAccount': None,
|
2038
|
+
'toAccount': None,
|
2039
|
+
'status': self.parse_transfer_status(status),
|
2040
|
+
}
|
2041
|
+
|
2042
|
+
def parse_transfer_status(self, status):
|
2043
|
+
statuses = {
|
2044
|
+
'ok': 'ok',
|
2045
|
+
'error': 'failed',
|
2046
|
+
}
|
2047
|
+
return self.safe_string(statuses, status, status)
|
2048
|
+
|
1986
2049
|
def nonce(self):
|
1987
2050
|
return self.milliseconds()
|
1988
2051
|
|
ccxt/async_support/gate.py
CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
|
|
7
7
|
from ccxt.abstract.gate import ImplicitAPI
|
8
8
|
import asyncio
|
9
9
|
import hashlib
|
10
|
-
from ccxt.base.types import Balances, Currency, Greeks, Int, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, FundingHistory, Str, Strings, Ticker, Tickers, Trade, Transaction
|
10
|
+
from ccxt.base.types import Balances, Currency, Greeks, Int, Leverage, Leverages, Market, Order, TransferEntry, OrderBook, OrderRequest, OrderSide, OrderType, FundingHistory, Str, Strings, Ticker, Tickers, Trade, Transaction
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import PermissionDenied
|
@@ -134,7 +134,8 @@ class gate(Exchange, ImplicitAPI):
|
|
134
134
|
'fetchIsolatedBorrowRate': False,
|
135
135
|
'fetchIsolatedBorrowRates': False,
|
136
136
|
'fetchLedger': True,
|
137
|
-
'fetchLeverage':
|
137
|
+
'fetchLeverage': True,
|
138
|
+
'fetchLeverages': True,
|
138
139
|
'fetchLeverageTiers': True,
|
139
140
|
'fetchLiquidations': True,
|
140
141
|
'fetchMarginMode': False,
|
@@ -4199,7 +4200,9 @@ class gate(Exchange, ImplicitAPI):
|
|
4199
4200
|
lastTradeTimestamp = self.safe_integer(order, 'update_time_ms')
|
4200
4201
|
if lastTradeTimestamp is None:
|
4201
4202
|
lastTradeTimestamp = self.safe_timestamp_2(order, 'update_time', 'finish_time')
|
4202
|
-
marketType = '
|
4203
|
+
marketType = 'contract'
|
4204
|
+
if ('currency_pair' in order) or ('market' in order):
|
4205
|
+
marketType = 'spot'
|
4203
4206
|
exchangeSymbol = self.safe_string_2(order, 'currency_pair', 'market', contract)
|
4204
4207
|
symbol = self.safe_symbol(exchangeSymbol, market, '_', marketType)
|
4205
4208
|
# Everything below self(above return) is related to fees
|
@@ -6515,6 +6518,166 @@ class gate(Exchange, ImplicitAPI):
|
|
6515
6518
|
side = '' # side is not used but needs to be present, otherwise crashes in php
|
6516
6519
|
return await self.create_order(symbol, 'market', side, 0, None, params)
|
6517
6520
|
|
6521
|
+
async def fetch_leverage(self, symbol: str, params={}) -> Leverage:
|
6522
|
+
"""
|
6523
|
+
fetch the set leverage for a market
|
6524
|
+
:see: https://www.gate.io/docs/developers/apiv4/en/#get-unified-account-information
|
6525
|
+
:see: https://www.gate.io/docs/developers/apiv4/en/#get-detail-of-lending-market
|
6526
|
+
:see: https://www.gate.io/docs/developers/apiv4/en/#query-one-single-margin-currency-pair-deprecated
|
6527
|
+
:param str symbol: unified market symbol
|
6528
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
6529
|
+
:param boolean [params.unified]: default False, set to True for fetching the unified accounts leverage
|
6530
|
+
:returns dict: a `leverage structure <https://docs.ccxt.com/#/?id=leverage-structure>`
|
6531
|
+
"""
|
6532
|
+
await self.load_markets()
|
6533
|
+
market = None
|
6534
|
+
if symbol is not None:
|
6535
|
+
# unified account does not require a symbol
|
6536
|
+
market = self.market(symbol)
|
6537
|
+
request = {}
|
6538
|
+
response = None
|
6539
|
+
isUnified = self.safe_bool(params, 'unified')
|
6540
|
+
params = self.omit(params, 'unified')
|
6541
|
+
if market['spot']:
|
6542
|
+
request['currency_pair'] = market['id']
|
6543
|
+
if isUnified:
|
6544
|
+
response = await self.publicMarginGetUniCurrencyPairsCurrencyPair(self.extend(request, params))
|
6545
|
+
#
|
6546
|
+
# {
|
6547
|
+
# "currency_pair": "BTC_USDT",
|
6548
|
+
# "base_min_borrow_amount": "0.0001",
|
6549
|
+
# "quote_min_borrow_amount": "1",
|
6550
|
+
# "leverage": "10"
|
6551
|
+
# }
|
6552
|
+
#
|
6553
|
+
else:
|
6554
|
+
response = await self.publicMarginGetCurrencyPairsCurrencyPair(self.extend(request, params))
|
6555
|
+
#
|
6556
|
+
# {
|
6557
|
+
# "id": "BTC_USDT",
|
6558
|
+
# "base": "BTC",
|
6559
|
+
# "quote": "USDT",
|
6560
|
+
# "leverage": 10,
|
6561
|
+
# "min_base_amount": "0.0001",
|
6562
|
+
# "min_quote_amount": "1",
|
6563
|
+
# "max_quote_amount": "40000000",
|
6564
|
+
# "status": 1
|
6565
|
+
# }
|
6566
|
+
#
|
6567
|
+
elif isUnified:
|
6568
|
+
response = await self.privateUnifiedGetAccounts(self.extend(request, params))
|
6569
|
+
#
|
6570
|
+
# {
|
6571
|
+
# "user_id": 10001,
|
6572
|
+
# "locked": False,
|
6573
|
+
# "balances": {
|
6574
|
+
# "ETH": {
|
6575
|
+
# "available": "0",
|
6576
|
+
# "freeze": "0",
|
6577
|
+
# "borrowed": "0.075393666654",
|
6578
|
+
# "negative_liab": "0",
|
6579
|
+
# "futures_pos_liab": "0",
|
6580
|
+
# "equity": "1016.1",
|
6581
|
+
# "total_freeze": "0",
|
6582
|
+
# "total_liab": "0"
|
6583
|
+
# },
|
6584
|
+
# "POINT": {
|
6585
|
+
# "available": "9999999999.017023138734",
|
6586
|
+
# "freeze": "0",
|
6587
|
+
# "borrowed": "0",
|
6588
|
+
# "negative_liab": "0",
|
6589
|
+
# "futures_pos_liab": "0",
|
6590
|
+
# "equity": "12016.1",
|
6591
|
+
# "total_freeze": "0",
|
6592
|
+
# "total_liab": "0"
|
6593
|
+
# },
|
6594
|
+
# "USDT": {
|
6595
|
+
# "available": "0.00000062023",
|
6596
|
+
# "freeze": "0",
|
6597
|
+
# "borrowed": "0",
|
6598
|
+
# "negative_liab": "0",
|
6599
|
+
# "futures_pos_liab": "0",
|
6600
|
+
# "equity": "16.1",
|
6601
|
+
# "total_freeze": "0",
|
6602
|
+
# "total_liab": "0"
|
6603
|
+
# }
|
6604
|
+
# },
|
6605
|
+
# "total": "230.94621713",
|
6606
|
+
# "borrowed": "161.66395521",
|
6607
|
+
# "total_initial_margin": "1025.0524665088",
|
6608
|
+
# "total_margin_balance": "3382495.944473949183",
|
6609
|
+
# "total_maintenance_margin": "205.01049330176",
|
6610
|
+
# "total_initial_margin_rate": "3299.827135672679",
|
6611
|
+
# "total_maintenance_margin_rate": "16499.135678363399",
|
6612
|
+
# "total_available_margin": "3381470.892007440383",
|
6613
|
+
# "unified_account_total": "3381470.892007440383",
|
6614
|
+
# "unified_account_total_liab": "0",
|
6615
|
+
# "unified_account_total_equity": "100016.1",
|
6616
|
+
# "leverage": "2"
|
6617
|
+
# }
|
6618
|
+
#
|
6619
|
+
else:
|
6620
|
+
raise NotSupported(self.id + ' fetchLeverage() does not support ' + market['type'] + ' markets')
|
6621
|
+
return self.parse_leverage(response, market)
|
6622
|
+
|
6623
|
+
async def fetch_leverages(self, symbols: List[str] = None, params={}) -> Leverages:
|
6624
|
+
"""
|
6625
|
+
fetch the set leverage for all leverage markets, only spot margin is supported on gate
|
6626
|
+
:see: https://www.gate.io/docs/developers/apiv4/en/#list-lending-markets
|
6627
|
+
:see: https://www.gate.io/docs/developers/apiv4/en/#list-all-supported-currency-pairs-supported-in-margin-trading-deprecated
|
6628
|
+
:param str[] symbols: a list of unified market symbols
|
6629
|
+
:param dict [params]: extra parameters specific to the exchange API endpoint
|
6630
|
+
:param boolean [params.unified]: default False, set to True for fetching unified account leverages
|
6631
|
+
:returns dict: a list of `leverage structures <https://docs.ccxt.com/#/?id=leverage-structure>`
|
6632
|
+
"""
|
6633
|
+
await self.load_markets()
|
6634
|
+
symbols = self.market_symbols(symbols)
|
6635
|
+
response = None
|
6636
|
+
isUnified = self.safe_bool(params, 'unified')
|
6637
|
+
params = self.omit(params, 'unified')
|
6638
|
+
marketIdRequest = 'id'
|
6639
|
+
if isUnified:
|
6640
|
+
marketIdRequest = 'currency_pair'
|
6641
|
+
response = await self.publicMarginGetUniCurrencyPairs(params)
|
6642
|
+
#
|
6643
|
+
# [
|
6644
|
+
# {
|
6645
|
+
# "currency_pair": "1INCH_USDT",
|
6646
|
+
# "base_min_borrow_amount": "8",
|
6647
|
+
# "quote_min_borrow_amount": "1",
|
6648
|
+
# "leverage": "3"
|
6649
|
+
# },
|
6650
|
+
# ]
|
6651
|
+
#
|
6652
|
+
else:
|
6653
|
+
response = await self.publicMarginGetCurrencyPairs(params)
|
6654
|
+
#
|
6655
|
+
# [
|
6656
|
+
# {
|
6657
|
+
# "id": "1CAT_USDT",
|
6658
|
+
# "base": "1CAT",
|
6659
|
+
# "quote": "USDT",
|
6660
|
+
# "leverage": 3,
|
6661
|
+
# "min_base_amount": "71",
|
6662
|
+
# "min_quote_amount": "1",
|
6663
|
+
# "max_quote_amount": "10000",
|
6664
|
+
# "status": 1
|
6665
|
+
# },
|
6666
|
+
# ]
|
6667
|
+
#
|
6668
|
+
return self.parse_leverages(response, symbols, marketIdRequest, 'spot')
|
6669
|
+
|
6670
|
+
def parse_leverage(self, leverage, market=None) -> Leverage:
|
6671
|
+
marketId = self.safe_string_2(leverage, 'currency_pair', 'id')
|
6672
|
+
leverageValue = self.safe_integer(leverage, 'leverage')
|
6673
|
+
return {
|
6674
|
+
'info': leverage,
|
6675
|
+
'symbol': self.safe_symbol(marketId, market, '_', 'spot'),
|
6676
|
+
'marginMode': None,
|
6677
|
+
'longLeverage': leverageValue,
|
6678
|
+
'shortLeverage': leverageValue,
|
6679
|
+
}
|
6680
|
+
|
6518
6681
|
def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
|
6519
6682
|
if response is None:
|
6520
6683
|
return None
|
ccxt/async_support/gemini.py
CHANGED
@@ -42,7 +42,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
42
42
|
'CORS': None,
|
43
43
|
'spot': True,
|
44
44
|
'margin': False,
|
45
|
-
'swap':
|
45
|
+
'swap': True,
|
46
46
|
'future': False,
|
47
47
|
'option': False,
|
48
48
|
'addMargin': False,
|
@@ -267,11 +267,11 @@ class gemini(Exchange, ImplicitAPI):
|
|
267
267
|
},
|
268
268
|
},
|
269
269
|
'options': {
|
270
|
-
'fetchMarketsMethod': '
|
270
|
+
'fetchMarketsMethod': 'fetch_markets_from_api', # fetch_markets_from_api, fetch_markets_from_web
|
271
271
|
'fetchMarketFromWebRetries': 10,
|
272
272
|
'fetchMarketsFromAPI': {
|
273
273
|
'fetchDetailsForAllSymbols': False,
|
274
|
-
'
|
274
|
+
'quoteCurrencies': ['USDT', 'GUSD', 'USD', 'DAI', 'EUR', 'GBP', 'SGD', 'BTC', 'ETH', 'LTC', 'BCH'],
|
275
275
|
},
|
276
276
|
'fetchMarkets': {
|
277
277
|
'webApiEnable': True, # fetches from WEB
|
@@ -322,10 +322,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
322
322
|
return None
|
323
323
|
#
|
324
324
|
# {
|
325
|
-
# "tradingPairs": [
|
326
|
-
# ["BTCAUD", 2, 8, "0.00001", 10, True],
|
327
|
-
# ...
|
328
|
-
# ],
|
325
|
+
# "tradingPairs": [['BTCUSD', 2, 8, '0.00001', 10, True], ...],
|
329
326
|
# "currencies": [
|
330
327
|
# ["ORCA", "Orca", 204, 6, 0, 6, 8, False, null, "solana"], #, precisions seem to be the 5th index
|
331
328
|
# ["ATOM", "Cosmos", 44, 6, 0, 6, 8, False, null, "cosmos"],
|
@@ -344,6 +341,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
344
341
|
# }
|
345
342
|
#
|
346
343
|
result = {}
|
344
|
+
self.options['tradingPairs'] = self.safe_list(data, 'tradingPairs')
|
347
345
|
currenciesArray = self.safe_value(data, 'currencies', [])
|
348
346
|
for i in range(0, len(currenciesArray)):
|
349
347
|
currency = currenciesArray[i]
|
@@ -540,7 +538,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
540
538
|
return result
|
541
539
|
|
542
540
|
async def fetch_markets_from_api(self, params={}):
|
543
|
-
|
541
|
+
marketIdsRaw = await self.publicGetV1Symbols(params)
|
544
542
|
#
|
545
543
|
# [
|
546
544
|
# "btcusd",
|
@@ -548,87 +546,166 @@ class gemini(Exchange, ImplicitAPI):
|
|
548
546
|
# ...
|
549
547
|
# ]
|
550
548
|
#
|
551
|
-
result =
|
552
|
-
|
553
|
-
|
554
|
-
market = {
|
555
|
-
'symbol': marketId,
|
556
|
-
}
|
557
|
-
result[marketId] = self.parse_market(market)
|
558
|
-
options = self.safe_value(self.options, 'fetchMarketsFromAPI', {})
|
559
|
-
fetchDetailsForAllSymbols = self.safe_bool(options, 'fetchDetailsForAllSymbols', False)
|
560
|
-
fetchDetailsForMarketIds = self.safe_value(options, 'fetchDetailsForMarketIds', [])
|
561
|
-
promises = []
|
549
|
+
result = []
|
550
|
+
options = self.safe_dict(self.options, 'fetchMarketsFromAPI', {})
|
551
|
+
bugSymbol = 'efilfil' # we skip self inexistent test symbol, which bugs other functions
|
562
552
|
marketIds = []
|
563
|
-
|
564
|
-
|
553
|
+
for i in range(0, len(marketIdsRaw)):
|
554
|
+
if marketIdsRaw[i] != bugSymbol:
|
555
|
+
marketIds.append(marketIdsRaw[i])
|
556
|
+
if self.safe_bool(options, 'fetchDetailsForAllSymbols', False):
|
557
|
+
promises = []
|
558
|
+
for i in range(0, len(marketIds)):
|
559
|
+
marketId = marketIds[i]
|
560
|
+
request = {
|
561
|
+
'symbol': marketId,
|
562
|
+
}
|
563
|
+
promises.append(self.publicGetV1SymbolsDetailsSymbol(self.extend(request, params)))
|
564
|
+
#
|
565
|
+
# {
|
566
|
+
# "symbol": "BTCUSD",
|
567
|
+
# "base_currency": "BTC",
|
568
|
+
# "quote_currency": "USD",
|
569
|
+
# "tick_size": 1E-8,
|
570
|
+
# "quote_increment": 0.01,
|
571
|
+
# "min_order_size": "0.00001",
|
572
|
+
# "status": "open",
|
573
|
+
# "wrap_enabled": False
|
574
|
+
# }
|
575
|
+
#
|
576
|
+
responses = await asyncio.gather(*promises)
|
577
|
+
for i in range(0, len(responses)):
|
578
|
+
result.append(self.parse_market(responses[i]))
|
565
579
|
else:
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
# "quote_increment": 0.01,
|
580
|
-
# "min_order_size": "0.00001",
|
581
|
-
# "status": "open",
|
582
|
-
# "wrap_enabled": False
|
583
|
-
# }
|
584
|
-
#
|
585
|
-
promises = await asyncio.gather(*promises)
|
586
|
-
for i in range(0, len(promises)):
|
587
|
-
responseInner = promises[i]
|
588
|
-
marketId = self.safe_string_lower(responseInner, 'symbol')
|
589
|
-
result[marketId] = self.parse_market(responseInner)
|
590
|
-
return self.to_array(result)
|
580
|
+
# use trading-pairs info, if it was fetched
|
581
|
+
tradingPairs = self.safe_list(self.options, 'tradingPairs')
|
582
|
+
if tradingPairs is not None:
|
583
|
+
indexedTradingPairs = self.index_by(tradingPairs, 0)
|
584
|
+
for i in range(0, len(marketIds)):
|
585
|
+
marketId = marketIds[i]
|
586
|
+
tradingPair = self.safe_list(indexedTradingPairs, marketId.upper())
|
587
|
+
if tradingPair is not None:
|
588
|
+
result.append(self.parse_market(tradingPair))
|
589
|
+
else:
|
590
|
+
for i in range(0, len(marketIds)):
|
591
|
+
result.append(self.parse_market(marketIds[i]))
|
592
|
+
return result
|
591
593
|
|
592
594
|
def parse_market(self, response) -> Market:
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
595
|
+
#
|
596
|
+
# response might be:
|
597
|
+
#
|
598
|
+
# btcusd
|
599
|
+
#
|
600
|
+
# or
|
601
|
+
#
|
602
|
+
# [
|
603
|
+
# 'BTCUSD', # symbol
|
604
|
+
# 2, # priceTickDecimalPlaces
|
605
|
+
# 8, # quantityTickDecimalPlaces
|
606
|
+
# '0.00001', # quantityMinimum
|
607
|
+
# 10, # quantityRoundDecimalPlaces
|
608
|
+
# True # minimumsAreInclusive
|
609
|
+
# ],
|
610
|
+
#
|
611
|
+
# or
|
612
|
+
#
|
613
|
+
# {
|
614
|
+
# "symbol": "BTCUSD", # perpetuals have 'PERP' suffix, i.e. DOGEUSDPERP
|
615
|
+
# "base_currency": "BTC",
|
616
|
+
# "quote_currency": "USD",
|
617
|
+
# "tick_size": 1E-8,
|
618
|
+
# "quote_increment": 0.01,
|
619
|
+
# "min_order_size": "0.00001",
|
620
|
+
# "status": "open",
|
621
|
+
# "wrap_enabled": False
|
622
|
+
# "product_type": "swap", # only in perps
|
623
|
+
# "contract_type": "linear", # only in perps
|
624
|
+
# "contract_price_currency": "GUSD" # only in perps
|
625
|
+
# }
|
626
|
+
#
|
627
|
+
marketId = None
|
628
|
+
baseId = None
|
629
|
+
quoteId = None
|
630
|
+
settleId = None
|
631
|
+
tickSize = None
|
632
|
+
increment = None
|
633
|
+
minSize = None
|
634
|
+
status = None
|
635
|
+
swap = False
|
636
|
+
contractSize = None
|
637
|
+
linear = None
|
638
|
+
inverse = None
|
639
|
+
isString = (isinstance(response, str))
|
640
|
+
isArray = (isinstance(response, list))
|
641
|
+
if not isString and not isArray:
|
642
|
+
marketId = self.safe_string_lower(response, 'symbol')
|
643
|
+
minSize = self.safe_number(response, 'min_order_size')
|
644
|
+
tickSize = self.safe_number(response, 'tick_size')
|
645
|
+
increment = self.safe_number(response, 'quote_increment')
|
646
|
+
status = self.parse_market_active(self.safe_string(response, 'status'))
|
647
|
+
baseId = self.safe_string(response, 'base_currency')
|
648
|
+
quoteId = self.safe_string(response, 'quote_currency')
|
649
|
+
settleId = self.safe_string(response, 'contract_price_currency')
|
650
|
+
else:
|
651
|
+
# if no detailed API was called, then parse either string or array
|
652
|
+
if isString:
|
653
|
+
marketId = response
|
654
|
+
else:
|
655
|
+
marketId = self.safe_string_lower(response, 0)
|
656
|
+
minSize = self.safe_number(response, 3)
|
657
|
+
tickSize = self.parse_number(self.parse_precision(self.safe_string(response, 1)))
|
658
|
+
increment = self.parse_number(self.parse_precision(self.safe_string(response, 2)))
|
659
|
+
marketIdUpper = marketId.upper()
|
660
|
+
isPerp = (marketIdUpper.find('PERP') >= 0)
|
661
|
+
marketIdWithoutPerp = marketIdUpper.replace('PERP', '')
|
662
|
+
quoteQurrencies = self.handle_option('fetchMarketsFromAPI', 'quoteCurrencies', [])
|
663
|
+
for i in range(0, len(quoteQurrencies)):
|
664
|
+
quoteCurrency = quoteQurrencies[i]
|
665
|
+
if marketIdWithoutPerp.endswith(quoteCurrency):
|
666
|
+
baseId = marketIdWithoutPerp.replace(quoteCurrency, '')
|
667
|
+
quoteId = quoteCurrency
|
668
|
+
if isPerp:
|
669
|
+
settleId = quoteCurrency # always same
|
670
|
+
break
|
602
671
|
base = self.safe_currency_code(baseId)
|
603
672
|
quote = self.safe_currency_code(quoteId)
|
604
|
-
|
673
|
+
settle = self.safe_currency_code(settleId)
|
674
|
+
symbol = base + '/' + quote
|
675
|
+
if settleId is not None:
|
676
|
+
symbol = symbol + ':' + settle
|
677
|
+
swap = True
|
678
|
+
contractSize = tickSize # always same
|
679
|
+
linear = True # always linear
|
680
|
+
inverse = False
|
681
|
+
type = 'swap' if swap else 'spot'
|
605
682
|
return {
|
606
683
|
'id': marketId,
|
607
|
-
'symbol':
|
684
|
+
'symbol': symbol,
|
608
685
|
'base': base,
|
609
686
|
'quote': quote,
|
610
|
-
'settle':
|
687
|
+
'settle': settle,
|
611
688
|
'baseId': baseId,
|
612
689
|
'quoteId': quoteId,
|
613
|
-
'settleId':
|
614
|
-
'type':
|
615
|
-
'spot':
|
690
|
+
'settleId': settleId,
|
691
|
+
'type': type,
|
692
|
+
'spot': not swap,
|
616
693
|
'margin': False,
|
617
|
-
'swap':
|
694
|
+
'swap': swap,
|
618
695
|
'future': False,
|
619
696
|
'option': False,
|
620
|
-
'active':
|
621
|
-
'contract':
|
622
|
-
'linear':
|
623
|
-
'inverse':
|
624
|
-
'contractSize':
|
697
|
+
'active': status,
|
698
|
+
'contract': swap,
|
699
|
+
'linear': linear,
|
700
|
+
'inverse': inverse,
|
701
|
+
'contractSize': contractSize,
|
625
702
|
'expiry': None,
|
626
703
|
'expiryDatetime': None,
|
627
704
|
'strike': None,
|
628
705
|
'optionType': None,
|
629
706
|
'precision': {
|
630
|
-
'price':
|
631
|
-
'amount':
|
707
|
+
'price': increment,
|
708
|
+
'amount': tickSize,
|
632
709
|
},
|
633
710
|
'limits': {
|
634
711
|
'leverage': {
|
@@ -636,7 +713,7 @@ class gemini(Exchange, ImplicitAPI):
|
|
636
713
|
'max': None,
|
637
714
|
},
|
638
715
|
'amount': {
|
639
|
-
'min':
|
716
|
+
'min': minSize,
|
640
717
|
'max': None,
|
641
718
|
},
|
642
719
|
'price': {
|
ccxt/async_support/hitbtc.py
CHANGED
@@ -332,6 +332,7 @@ class hitbtc(Exchange, ImplicitAPI):
|
|
332
332
|
'2012': BadRequest,
|
333
333
|
'2020': BadRequest,
|
334
334
|
'2022': BadRequest,
|
335
|
+
'2024': InvalidOrder, # Invalid margin mode.
|
335
336
|
'10001': BadRequest,
|
336
337
|
'10021': AccountSuspended,
|
337
338
|
'10022': BadRequest,
|
@@ -349,6 +350,7 @@ class hitbtc(Exchange, ImplicitAPI):
|
|
349
350
|
'20012': ExchangeError,
|
350
351
|
'20014': ExchangeError,
|
351
352
|
'20016': ExchangeError,
|
353
|
+
'20018': ExchangeError, # Withdrawals are unavailable due to the current configuration. Any of: - internal withdrawals are disabled; - in-chain withdrawals are disabled.
|
352
354
|
'20031': ExchangeError,
|
353
355
|
'20032': ExchangeError,
|
354
356
|
'20033': ExchangeError,
|
@@ -359,10 +361,15 @@ class hitbtc(Exchange, ImplicitAPI):
|
|
359
361
|
'20043': ExchangeError,
|
360
362
|
'20044': PermissionDenied,
|
361
363
|
'20045': InvalidOrder,
|
364
|
+
'20047': InvalidOrder, # Order placing exceeds the central counterparty balance limit.
|
365
|
+
'20048': InvalidOrder, # Provided Time-In-Force instruction is invalid or the combination of the instruction and the order type is not allowed.
|
366
|
+
'20049': InvalidOrder, # Provided order type is invalid.
|
362
367
|
'20080': ExchangeError,
|
363
368
|
'21001': ExchangeError,
|
364
369
|
'21003': AccountSuspended,
|
365
370
|
'21004': AccountSuspended,
|
371
|
+
'22004': ExchangeError, # User is not found.
|
372
|
+
'22008': ExchangeError, # Gateway timeout exceeded.
|
366
373
|
},
|
367
374
|
'broad': {},
|
368
375
|
},
|