ccxt 4.4.62__py2.py3-none-any.whl → 4.4.64__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/abstract/binance.py +1 -0
- ccxt/abstract/binancecoinm.py +1 -0
- ccxt/abstract/binanceus.py +1 -0
- ccxt/abstract/binanceusdm.py +1 -0
- ccxt/abstract/bitmart.py +5 -1
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/base/exchange.py +1 -1
- ccxt/async_support/binance.py +4 -4
- ccxt/async_support/bingx.py +1 -1
- ccxt/async_support/bitmart.py +155 -54
- ccxt/async_support/bybit.py +5 -5
- ccxt/async_support/gate.py +106 -145
- ccxt/async_support/phemex.py +18 -12
- ccxt/async_support/tradeogre.py +3 -3
- ccxt/async_support/whitebit.py +2 -4
- ccxt/base/exchange.py +12 -7
- ccxt/binance.py +4 -4
- ccxt/bingx.py +1 -1
- ccxt/bitmart.py +155 -54
- ccxt/bybit.py +5 -5
- ccxt/gate.py +106 -145
- ccxt/phemex.py +17 -12
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitmart.py +64 -53
- ccxt/pro/bitopro.py +1 -1
- ccxt/pro/gate.py +4 -0
- ccxt/pro/vertex.py +5 -0
- ccxt/tradeogre.py +3 -3
- ccxt/whitebit.py +2 -4
- {ccxt-4.4.62.dist-info → ccxt-4.4.64.dist-info}/METADATA +4 -4
- {ccxt-4.4.62.dist-info → ccxt-4.4.64.dist-info}/RECORD +35 -35
- {ccxt-4.4.62.dist-info → ccxt-4.4.64.dist-info}/LICENSE.txt +0 -0
- {ccxt-4.4.62.dist-info → ccxt-4.4.64.dist-info}/WHEEL +0 -0
- {ccxt-4.4.62.dist-info → ccxt-4.4.64.dist-info}/top_level.txt +0 -0
ccxt/gate.py
CHANGED
@@ -23,7 +23,6 @@ from ccxt.base.errors import OrderImmediatelyFillable
|
|
23
23
|
from ccxt.base.errors import NotSupported
|
24
24
|
from ccxt.base.errors import RateLimitExceeded
|
25
25
|
from ccxt.base.errors import ExchangeNotAvailable
|
26
|
-
from ccxt.base.errors import BadResponse
|
27
26
|
from ccxt.base.decimal_to_precision import TICK_SIZE
|
28
27
|
from ccxt.base.precise import Precise
|
29
28
|
|
@@ -1797,100 +1796,80 @@ class gate(Exchange, ImplicitAPI):
|
|
1797
1796
|
self.load_unified_status()
|
1798
1797
|
response = self.publicSpotGetCurrencies(params)
|
1799
1798
|
#
|
1800
|
-
#
|
1801
|
-
#
|
1802
|
-
#
|
1803
|
-
#
|
1804
|
-
#
|
1805
|
-
#
|
1806
|
-
#
|
1807
|
-
#
|
1808
|
-
#
|
1809
|
-
#
|
1810
|
-
#
|
1811
|
-
#
|
1812
|
-
#
|
1813
|
-
|
1814
|
-
# "deposit_disabled":false,
|
1815
|
-
# "trade_disabled":false,
|
1816
|
-
# "chain":"ETH"
|
1817
|
-
# }
|
1818
|
-
#
|
1799
|
+
# [
|
1800
|
+
# {
|
1801
|
+
# "currency": "USDT_ETH",
|
1802
|
+
# "name": "Tether",
|
1803
|
+
# "delisted": False,
|
1804
|
+
# "withdraw_disabled": False,
|
1805
|
+
# "withdraw_delayed": False,
|
1806
|
+
# "deposit_disabled": False,
|
1807
|
+
# "trade_disabled": True,
|
1808
|
+
# "chain": "ETH"
|
1809
|
+
# },
|
1810
|
+
# ]
|
1811
|
+
#
|
1812
|
+
indexedCurrencies = self.index_by(response, 'currency')
|
1819
1813
|
result: dict = {}
|
1820
1814
|
for i in range(0, len(response)):
|
1821
1815
|
entry = response[i]
|
1822
1816
|
currencyId = self.safe_string(entry, 'currency')
|
1823
|
-
currencyIdLower = self.safe_string_lower(entry, 'currency')
|
1824
1817
|
parts = currencyId.split('_')
|
1825
|
-
|
1826
|
-
|
1827
|
-
|
1828
|
-
|
1829
|
-
|
1830
|
-
|
1831
|
-
|
1832
|
-
|
1833
|
-
|
1834
|
-
|
1835
|
-
|
1836
|
-
|
1837
|
-
|
1838
|
-
|
1839
|
-
|
1840
|
-
|
1818
|
+
partFirst = self.safe_string(parts, 0)
|
1819
|
+
# if there's an underscore then the second part is always the chain name(except the _OLD suffix)
|
1820
|
+
currencyName = currencyId if currencyId.endswith('_OLD') else partFirst
|
1821
|
+
withdrawEnabled = not self.safe_bool(entry, 'withdraw_disabled')
|
1822
|
+
depositEnabled = not self.safe_bool(entry, 'deposit_disabled')
|
1823
|
+
tradeDisabled = not self.safe_bool(entry, 'trade_disabled')
|
1824
|
+
precision = self.parse_number('0.0001') # temporary safe default, because no value provided from API
|
1825
|
+
code = self.safe_currency_code(currencyName)
|
1826
|
+
# check leveraged tokens(e.g. BTC3S, ETH5L)
|
1827
|
+
isLeveragedToken = False
|
1828
|
+
if currencyId.endswith('3S') or currencyId.endswith('3L') or currencyId.endswith('5S') or currencyId.endswith('5L'):
|
1829
|
+
realCurrencyId = currencyId[0:-2]
|
1830
|
+
if realCurrencyId in indexedCurrencies:
|
1831
|
+
isLeveragedToken = True
|
1832
|
+
type = 'leveraged' if isLeveragedToken else 'crypto'
|
1833
|
+
# some networks are null, they are mostly obsolete & unsupported dead tokens, so we can default their networkId to their tokenname
|
1834
|
+
networkId = self.safe_string(entry, 'chain', currencyId)
|
1835
|
+
networkCode = self.network_id_to_code(networkId, code)
|
1836
|
+
networkEntry = {
|
1837
|
+
'info': entry,
|
1838
|
+
'id': networkId,
|
1839
|
+
'network': networkCode,
|
1840
|
+
'limits': {
|
1841
|
+
'deposit': {
|
1842
|
+
'min': None,
|
1843
|
+
'max': None,
|
1844
|
+
},
|
1845
|
+
'withdraw': {
|
1846
|
+
'min': None,
|
1847
|
+
'max': None,
|
1848
|
+
},
|
1849
|
+
},
|
1850
|
+
'active': not tradeDisabled,
|
1851
|
+
'deposit': depositEnabled,
|
1852
|
+
'withdraw': withdrawEnabled,
|
1853
|
+
'fee': None,
|
1854
|
+
'precision': precision,
|
1855
|
+
}
|
1856
|
+
# check if first entry for the specific currency
|
1857
|
+
if not (code in result):
|
1841
1858
|
result[code] = {
|
1842
|
-
'id':
|
1859
|
+
'id': currencyName,
|
1860
|
+
'lowerCaseId': currencyName.lower(),
|
1843
1861
|
'code': code,
|
1844
|
-
'
|
1845
|
-
'
|
1846
|
-
'active': active,
|
1847
|
-
'deposit': depositEnabled,
|
1848
|
-
'withdraw': withdrawEnabled,
|
1849
|
-
'fee': None,
|
1850
|
-
'fees': [],
|
1851
|
-
'precision': self.parse_number('1e-4'),
|
1862
|
+
'type': type,
|
1863
|
+
'precision': precision,
|
1852
1864
|
'limits': self.limits,
|
1853
1865
|
'networks': {},
|
1866
|
+
'info': [], # will be filled below
|
1854
1867
|
}
|
1855
|
-
|
1856
|
-
|
1857
|
-
withdrawAvailable = self.safe_value(result[code], 'withdraw')
|
1858
|
-
withdrawAvailable = withdrawEnabled if (withdrawEnabled) else withdrawAvailable
|
1859
|
-
networks = self.safe_value(result[code], 'networks', {})
|
1860
|
-
if networkCode is not None:
|
1861
|
-
networks[networkCode] = {
|
1862
|
-
'info': entry,
|
1863
|
-
'id': networkId,
|
1864
|
-
'network': networkCode,
|
1865
|
-
'currencyId': currencyId,
|
1866
|
-
'lowerCaseCurrencyId': currencyIdLower,
|
1867
|
-
'deposit': depositEnabled,
|
1868
|
-
'withdraw': withdrawEnabled,
|
1869
|
-
'active': active,
|
1870
|
-
'fee': None,
|
1871
|
-
'precision': self.parse_number('1e-4'),
|
1872
|
-
'limits': {
|
1873
|
-
'amount': {
|
1874
|
-
'min': None,
|
1875
|
-
'max': None,
|
1876
|
-
},
|
1877
|
-
'withdraw': {
|
1878
|
-
'min': None,
|
1879
|
-
'max': None,
|
1880
|
-
},
|
1881
|
-
'deposit': {
|
1882
|
-
'min': None,
|
1883
|
-
'max': None,
|
1884
|
-
},
|
1885
|
-
},
|
1886
|
-
}
|
1887
|
-
result[code]['networks'] = networks
|
1888
|
-
info = self.safe_value(result[code], 'info', [])
|
1868
|
+
result[code]['networks'][networkCode] = networkEntry
|
1869
|
+
info = self.safe_list(result[code], 'info', [])
|
1889
1870
|
info.append(entry)
|
1890
1871
|
result[code]['info'] = info
|
1891
|
-
result[code][
|
1892
|
-
result[code]['deposit'] = depositAvailable
|
1893
|
-
result[code]['withdraw'] = withdrawAvailable
|
1872
|
+
result[code] = self.safe_currency_structure(result[code]) # self is needed after adding network entry
|
1894
1873
|
return result
|
1895
1874
|
|
1896
1875
|
def fetch_funding_rate(self, symbol: str, params={}) -> FundingRate:
|
@@ -2135,6 +2114,27 @@ class gate(Exchange, ImplicitAPI):
|
|
2135
2114
|
}
|
2136
2115
|
return result
|
2137
2116
|
|
2117
|
+
def fetch_deposit_addresses_by_network(self, code: str, params={}) -> List[DepositAddress]:
|
2118
|
+
"""
|
2119
|
+
fetch a dictionary of addresses for a currency, indexed by network
|
2120
|
+
:param str code: unified currency code of the currency for the deposit address
|
2121
|
+
:param dict [params]: extra parameters specific to the api endpoint
|
2122
|
+
:returns dict: a dictionary of `address structures <https://docs.ccxt.com/#/?id=address-structure>` indexed by the network
|
2123
|
+
"""
|
2124
|
+
self.load_markets()
|
2125
|
+
currency = self.currency(code)
|
2126
|
+
request = {
|
2127
|
+
'currency': currency['id'],
|
2128
|
+
}
|
2129
|
+
response = self.privateWalletGetDepositAddress(self.extend(request, params))
|
2130
|
+
chains = self.safe_value(response, 'multichain_addresses', [])
|
2131
|
+
currencyId = self.safe_string(response, 'currency')
|
2132
|
+
currency = self.safe_currency(currencyId, currency)
|
2133
|
+
parsed = self.parse_deposit_addresses(chains, [currency['code']], False, {
|
2134
|
+
'currency': currency['id'],
|
2135
|
+
})
|
2136
|
+
return self.index_by(parsed, 'network')
|
2137
|
+
|
2138
2138
|
def fetch_deposit_address(self, code: str, params={}) -> DepositAddress:
|
2139
2139
|
"""
|
2140
2140
|
fetch the deposit address for a currency associated with self account
|
@@ -2147,65 +2147,30 @@ class gate(Exchange, ImplicitAPI):
|
|
2147
2147
|
:returns dict: an `address structure <https://docs.ccxt.com/#/?id=address-structure>`
|
2148
2148
|
"""
|
2149
2149
|
self.load_markets()
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2150
|
+
networkCode = None
|
2151
|
+
networkCode, params = self.handle_network_code_and_params(params)
|
2152
|
+
chainsIndexedById = self.fetch_deposit_addresses_by_network(code, params)
|
2153
|
+
selectedNetworkId = self.select_network_code_from_unified_networks(code, networkCode, chainsIndexedById)
|
2154
|
+
return chainsIndexedById[selectedNetworkId]
|
2155
|
+
|
2156
|
+
def parse_deposit_address(self, depositAddress, currency=None):
|
2157
2157
|
#
|
2158
|
-
#
|
2159
|
-
#
|
2160
|
-
#
|
2161
|
-
#
|
2162
|
-
#
|
2163
|
-
#
|
2164
|
-
#
|
2165
|
-
# "payment_id": "391331007",
|
2166
|
-
# "payment_name": "Tag",
|
2167
|
-
# "obtain_failed": 0
|
2168
|
-
# }
|
2169
|
-
# ]
|
2170
|
-
# }
|
2158
|
+
# {
|
2159
|
+
# chain: "BTC",
|
2160
|
+
# address: "1Nxu.......Ys",
|
2161
|
+
# payment_id: "",
|
2162
|
+
# payment_name: "",
|
2163
|
+
# obtain_failed: "0",
|
2164
|
+
# }
|
2171
2165
|
#
|
2172
|
-
|
2173
|
-
code = self.safe_currency_code(currencyId)
|
2174
|
-
networkId = self.network_code_to_id(rawNetwork, code)
|
2175
|
-
network = None
|
2176
|
-
tag = None
|
2177
|
-
address = None
|
2178
|
-
if networkId is not None:
|
2179
|
-
addresses = self.safe_value(response, 'multichain_addresses')
|
2180
|
-
for i in range(0, len(addresses)):
|
2181
|
-
entry = addresses[i]
|
2182
|
-
entryNetwork = self.safe_string(entry, 'chain')
|
2183
|
-
if networkId == entryNetwork:
|
2184
|
-
obtainFailed = self.safe_integer(entry, 'obtain_failed')
|
2185
|
-
if obtainFailed:
|
2186
|
-
break
|
2187
|
-
address = self.safe_string(entry, 'address')
|
2188
|
-
tag = self.safe_string(entry, 'payment_id')
|
2189
|
-
network = self.network_id_to_code(networkId, code)
|
2190
|
-
break
|
2191
|
-
else:
|
2192
|
-
addressField = self.safe_string(response, 'address')
|
2193
|
-
if addressField is not None:
|
2194
|
-
if addressField.find('New address is being generated for you, please wait') >= 0:
|
2195
|
-
raise BadResponse(self.id + ' ' + 'New address is being generated for you, please wait a few seconds and try again to get the address.')
|
2196
|
-
if addressField.find(' ') >= 0:
|
2197
|
-
splitted = addressField.split(' ')
|
2198
|
-
address = splitted[0]
|
2199
|
-
tag = splitted[1]
|
2200
|
-
else:
|
2201
|
-
address = addressField
|
2166
|
+
address = self.safe_string(depositAddress, 'address')
|
2202
2167
|
self.check_address(address)
|
2203
2168
|
return {
|
2204
|
-
'info':
|
2205
|
-
'currency': code,
|
2206
|
-
'network': network,
|
2169
|
+
'info': depositAddress,
|
2170
|
+
'currency': self.safe_string(currency, 'code'),
|
2207
2171
|
'address': address,
|
2208
|
-
'tag':
|
2172
|
+
'tag': self.safe_string(depositAddress, 'payment_id'),
|
2173
|
+
'network': self.network_id_to_code(self.safe_string(depositAddress, 'chain')),
|
2209
2174
|
}
|
2210
2175
|
|
2211
2176
|
def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
@@ -3818,14 +3783,10 @@ class gate(Exchange, ImplicitAPI):
|
|
3818
3783
|
}
|
3819
3784
|
if tag is not None:
|
3820
3785
|
request['memo'] = tag
|
3821
|
-
|
3822
|
-
|
3823
|
-
|
3824
|
-
|
3825
|
-
request['chain'] = network
|
3826
|
-
params = self.omit(params, 'network')
|
3827
|
-
else:
|
3828
|
-
request['chain'] = currency['id'] # todo: currencies have network-junctions
|
3786
|
+
networkCode = None
|
3787
|
+
networkCode, params = self.handle_network_code_and_params(params)
|
3788
|
+
if networkCode is not None:
|
3789
|
+
request['chain'] = self.network_code_to_id(networkCode)
|
3829
3790
|
response = self.privateWithdrawalsPostWithdrawals(self.extend(request, params))
|
3830
3791
|
#
|
3831
3792
|
# {
|
ccxt/phemex.py
CHANGED
@@ -685,7 +685,8 @@ class phemex(Exchange, ImplicitAPI):
|
|
685
685
|
# }
|
686
686
|
#
|
687
687
|
id = self.safe_string(market, 'symbol')
|
688
|
-
|
688
|
+
contractUnderlyingAssets = self.safe_string(market, 'contractUnderlyingAssets')
|
689
|
+
baseId = self.safe_string(market, 'baseCurrency', contractUnderlyingAssets)
|
689
690
|
quoteId = self.safe_string(market, 'quoteCurrency')
|
690
691
|
settleId = self.safe_string(market, 'settleCurrency')
|
691
692
|
base = self.safe_currency_code(baseId)
|
@@ -695,6 +696,9 @@ class phemex(Exchange, ImplicitAPI):
|
|
695
696
|
inverse = False
|
696
697
|
if settleId != quoteId:
|
697
698
|
inverse = True
|
699
|
+
# some unhandled cases
|
700
|
+
if not ('baseCurrency' in market) and base == quote:
|
701
|
+
base = settle
|
698
702
|
priceScale = self.safe_integer(market, 'priceScale')
|
699
703
|
ratioScale = self.safe_integer(market, 'ratioScale')
|
700
704
|
valueScale = self.safe_integer(market, 'valueScale')
|
@@ -880,7 +884,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
880
884
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
881
885
|
:returns dict[]: an array of objects representing market data
|
882
886
|
"""
|
883
|
-
|
887
|
+
v2ProductsPromise = self.v2GetPublicProducts(params)
|
884
888
|
#
|
885
889
|
# {
|
886
890
|
# "code":0,
|
@@ -1030,7 +1034,8 @@ class phemex(Exchange, ImplicitAPI):
|
|
1030
1034
|
# }
|
1031
1035
|
# }
|
1032
1036
|
#
|
1033
|
-
|
1037
|
+
v1ProductsPromise = self.v1GetExchangePublicProducts(params)
|
1038
|
+
v2Products, v1Products = [v2ProductsPromise, v1ProductsPromise]
|
1034
1039
|
v1ProductsData = self.safe_value(v1Products, 'data', [])
|
1035
1040
|
#
|
1036
1041
|
# {
|
@@ -1067,14 +1072,14 @@ class phemex(Exchange, ImplicitAPI):
|
|
1067
1072
|
# ]
|
1068
1073
|
# }
|
1069
1074
|
#
|
1070
|
-
v2ProductsData = self.
|
1071
|
-
products = self.
|
1072
|
-
perpetualProductsV2 = self.
|
1075
|
+
v2ProductsData = self.safe_dict(v2Products, 'data', {})
|
1076
|
+
products = self.safe_list(v2ProductsData, 'products', [])
|
1077
|
+
perpetualProductsV2 = self.safe_list(v2ProductsData, 'perpProductsV2', [])
|
1073
1078
|
products = self.array_concat(products, perpetualProductsV2)
|
1074
|
-
riskLimits = self.
|
1075
|
-
riskLimitsV2 = self.
|
1079
|
+
riskLimits = self.safe_list(v2ProductsData, 'riskLimits', [])
|
1080
|
+
riskLimitsV2 = self.safe_list(v2ProductsData, 'riskLimitsV2', [])
|
1076
1081
|
riskLimits = self.array_concat(riskLimits, riskLimitsV2)
|
1077
|
-
currencies = self.
|
1082
|
+
currencies = self.safe_list(v2ProductsData, 'currencies', [])
|
1078
1083
|
riskLimitsById = self.index_by(riskLimits, 'symbol')
|
1079
1084
|
v1ProductsById = self.index_by(v1ProductsData, 'symbol')
|
1080
1085
|
currenciesByCode = self.index_by(currencies, 'currency')
|
@@ -1084,14 +1089,14 @@ class phemex(Exchange, ImplicitAPI):
|
|
1084
1089
|
type = self.safe_string_lower(market, 'type')
|
1085
1090
|
if (type == 'perpetual') or (type == 'perpetualv2') or (type == 'perpetualpilot'):
|
1086
1091
|
id = self.safe_string(market, 'symbol')
|
1087
|
-
riskLimitValues = self.
|
1092
|
+
riskLimitValues = self.safe_dict(riskLimitsById, id, {})
|
1088
1093
|
market = self.extend(market, riskLimitValues)
|
1089
|
-
v1ProductsValues = self.
|
1094
|
+
v1ProductsValues = self.safe_dict(v1ProductsById, id, {})
|
1090
1095
|
market = self.extend(market, v1ProductsValues)
|
1091
1096
|
market = self.parse_swap_market(market)
|
1092
1097
|
else:
|
1093
1098
|
baseCurrency = self.safe_string(market, 'baseCurrency')
|
1094
|
-
currencyValues = self.
|
1099
|
+
currencyValues = self.safe_dict(currenciesByCode, baseCurrency, {})
|
1095
1100
|
valueScale = self.safe_string(currencyValues, 'valueScale', '8')
|
1096
1101
|
market = self.extend(market, {'valueScale': valueScale})
|
1097
1102
|
market = self.parse_spot_market(market)
|
ccxt/pro/__init__.py
CHANGED
ccxt/pro/bitmart.py
CHANGED
@@ -131,8 +131,10 @@ class bitmart(ccxt.async_support.bitmart):
|
|
131
131
|
rawSubscriptions.append(message)
|
132
132
|
messageHashes.append(channel + ':' + market['symbol'])
|
133
133
|
# exclusion, futures "tickers" need one generic request for all symbols
|
134
|
-
if (type != 'spot') and (channel == 'ticker'):
|
135
|
-
|
134
|
+
# if (type != 'spot') and (channel == 'ticker'):
|
135
|
+
# rawSubscriptions = [channelType + '/' + channel]
|
136
|
+
# }
|
137
|
+
# Exchange update from 2025-02-11 supports subscription by trading pair for swap
|
136
138
|
request: dict = {
|
137
139
|
'args': rawSubscriptions,
|
138
140
|
}
|
@@ -898,39 +900,42 @@ class bitmart(ccxt.async_support.bitmart):
|
|
898
900
|
|
899
901
|
def parse_ws_trade(self, trade: dict, market: Market = None):
|
900
902
|
# spot
|
901
|
-
#
|
902
|
-
#
|
903
|
-
#
|
904
|
-
#
|
905
|
-
#
|
906
|
-
#
|
907
|
-
#
|
903
|
+
# {
|
904
|
+
# "ms_t": 1740320841473,
|
905
|
+
# "price": "2806.54",
|
906
|
+
# "s_t": 1740320841,
|
907
|
+
# "side": "sell",
|
908
|
+
# "size": "0.77598",
|
909
|
+
# "symbol": "ETH_USDT"
|
910
|
+
# }
|
911
|
+
#
|
908
912
|
# swap
|
909
|
-
#
|
910
|
-
#
|
911
|
-
#
|
912
|
-
#
|
913
|
-
#
|
914
|
-
#
|
915
|
-
#
|
916
|
-
#
|
917
|
-
#
|
918
|
-
# "create_time_mill":1701618503517,
|
919
|
-
# "created_at":"2023-12-03T15:48:23.517518538Z"
|
920
|
-
# }
|
913
|
+
# {
|
914
|
+
# "trade_id": "3000000245258661",
|
915
|
+
# "symbol": "ETHUSDT",
|
916
|
+
# "deal_price": "2811.1",
|
917
|
+
# "deal_vol": "1858",
|
918
|
+
# "way": 2,
|
919
|
+
# "m": True,
|
920
|
+
# "created_at": "2025-02-23T13:59:59.646490751Z"
|
921
|
+
# }
|
921
922
|
#
|
922
|
-
contractId = self.safe_string(trade, 'contract_id')
|
923
|
-
marketType = 'spot' if (contractId is None) else 'swap'
|
924
|
-
marketDelimiter = '_' if (marketType == 'spot') else ''
|
925
|
-
timestamp = self.safe_integer(trade, 'create_time_mill', self.safe_timestamp(trade, 's_t'))
|
926
923
|
marketId = self.safe_string(trade, 'symbol')
|
924
|
+
market = self.safe_market(marketId, market)
|
925
|
+
timestamp = self.safe_integer(trade, 'ms_t')
|
926
|
+
datetime: Str = None
|
927
|
+
if timestamp is None:
|
928
|
+
datetime = self.safe_string(trade, 'created_at')
|
929
|
+
timestamp = self.parse8601(datetime)
|
930
|
+
else:
|
931
|
+
datetime = self.iso8601(timestamp)
|
927
932
|
return self.safe_trade({
|
928
933
|
'info': trade,
|
929
934
|
'id': self.safe_string(trade, 'trade_id'),
|
930
935
|
'order': None,
|
931
936
|
'timestamp': timestamp,
|
932
|
-
'datetime':
|
933
|
-
'symbol':
|
937
|
+
'datetime': datetime,
|
938
|
+
'symbol': market['symbol'],
|
934
939
|
'type': None,
|
935
940
|
'side': self.safe_string(trade, 'side'),
|
936
941
|
'price': self.safe_string_2(trade, 'price', 'deal_price'),
|
@@ -956,20 +961,22 @@ class bitmart(ccxt.async_support.bitmart):
|
|
956
961
|
# ],
|
957
962
|
# "table": "spot/ticker"
|
958
963
|
# }
|
959
|
-
#
|
960
|
-
#
|
961
|
-
#
|
962
|
-
#
|
963
|
-
#
|
964
|
-
#
|
965
|
-
#
|
966
|
-
#
|
967
|
-
#
|
968
|
-
#
|
969
|
-
#
|
970
|
-
#
|
971
|
-
#
|
972
|
-
#
|
964
|
+
#
|
965
|
+
# {
|
966
|
+
# "data": {
|
967
|
+
# "symbol": "ETHUSDT",
|
968
|
+
# "last_price": "2807.73",
|
969
|
+
# "volume_24": "2227011952",
|
970
|
+
# "range": "0.0273398194664491",
|
971
|
+
# "mark_price": "2807.5",
|
972
|
+
# "index_price": "2808.71047619",
|
973
|
+
# "ask_price": "2808.04",
|
974
|
+
# "ask_vol": "7371",
|
975
|
+
# "bid_price": "2807.28",
|
976
|
+
# "bid_vol": "3561"
|
977
|
+
# },
|
978
|
+
# "group": "futures/ticker:ETHUSDT@100ms"
|
979
|
+
# }
|
973
980
|
#
|
974
981
|
self.handle_bid_ask(client, message)
|
975
982
|
table = self.safe_string(message, 'table')
|
@@ -990,17 +997,19 @@ class bitmart(ccxt.async_support.bitmart):
|
|
990
997
|
|
991
998
|
def parse_ws_swap_ticker(self, ticker, market: Market = None):
|
992
999
|
#
|
993
|
-
#
|
994
|
-
#
|
995
|
-
#
|
996
|
-
#
|
997
|
-
#
|
998
|
-
#
|
999
|
-
#
|
1000
|
-
#
|
1001
|
-
#
|
1002
|
-
#
|
1003
|
-
#
|
1000
|
+
# {
|
1001
|
+
# "symbol": "ETHUSDT",
|
1002
|
+
# "last_price": "2807.73",
|
1003
|
+
# "volume_24": "2227011952",
|
1004
|
+
# "range": "0.0273398194664491",
|
1005
|
+
# "mark_price": "2807.5",
|
1006
|
+
# "index_price": "2808.71047619",
|
1007
|
+
# "ask_price": "2808.04",
|
1008
|
+
# "ask_vol": "7371",
|
1009
|
+
# "bid_price": "2807.28",
|
1010
|
+
# "bid_vol": "3561"
|
1011
|
+
# }
|
1012
|
+
#
|
1004
1013
|
marketId = self.safe_string(ticker, 'symbol')
|
1005
1014
|
return self.safe_ticker({
|
1006
1015
|
'symbol': self.safe_symbol(marketId, market, '', 'swap'),
|
@@ -1019,10 +1028,12 @@ class bitmart(ccxt.async_support.bitmart):
|
|
1019
1028
|
'previousClose': None,
|
1020
1029
|
'change': None,
|
1021
1030
|
'percentage': None,
|
1022
|
-
'average':
|
1031
|
+
'average': None,
|
1023
1032
|
'baseVolume': None,
|
1024
1033
|
'quoteVolume': self.safe_string(ticker, 'volume_24'),
|
1025
1034
|
'info': ticker,
|
1035
|
+
'markPrice': self.safe_string(ticker, 'mark_price'),
|
1036
|
+
'indexPrice': self.safe_string(ticker, 'index_price'),
|
1026
1037
|
}, market)
|
1027
1038
|
|
1028
1039
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
ccxt/pro/bitopro.py
CHANGED
@@ -77,7 +77,7 @@ class bitopro(ccxt.async_support.bitopro):
|
|
77
77
|
if limit is None:
|
78
78
|
endPart = market['id']
|
79
79
|
else:
|
80
|
-
endPart = market['id'] + ':' + limit
|
80
|
+
endPart = market['id'] + ':' + self.number_to_string(limit)
|
81
81
|
orderbook = await self.watch_public('order-books', messageHash, endPart)
|
82
82
|
return orderbook.limit()
|
83
83
|
|
ccxt/pro/gate.py
CHANGED
@@ -1892,6 +1892,10 @@ class gate(ccxt.async_support.gate):
|
|
1892
1892
|
'signature': signature,
|
1893
1893
|
'req_param': reqParams,
|
1894
1894
|
}
|
1895
|
+
if (channel == 'spot.order_place') or (channel == 'futures.order_place'):
|
1896
|
+
payload['req_header'] = {
|
1897
|
+
'x-gate-channel-id': 'ccxt',
|
1898
|
+
}
|
1895
1899
|
request: dict = {
|
1896
1900
|
'id': requestId,
|
1897
1901
|
'time': time,
|
ccxt/pro/vertex.py
CHANGED
@@ -55,6 +55,11 @@ class vertex(ccxt.async_support.vertex):
|
|
55
55
|
},
|
56
56
|
'ws': {
|
57
57
|
'inflate': True,
|
58
|
+
'options': {
|
59
|
+
'headers': {
|
60
|
+
'Sec-WebSocket-Extensions': 'permessage-deflate', # requires permessage-deflate extension, maybe we can set self in client implementation when self.inflateis True
|
61
|
+
},
|
62
|
+
},
|
58
63
|
},
|
59
64
|
},
|
60
65
|
'streaming': {
|
ccxt/tradeogre.py
CHANGED
@@ -511,11 +511,11 @@ class tradeogre(Exchange, ImplicitAPI):
|
|
511
511
|
if type == 'market':
|
512
512
|
raise BadRequest(self.id + ' createOrder does not support market orders')
|
513
513
|
if price is None:
|
514
|
-
raise ArgumentsRequired(self.id + ' createOrder requires a
|
514
|
+
raise ArgumentsRequired(self.id + ' createOrder requires a price parameter')
|
515
515
|
request: dict = {
|
516
516
|
'market': market['id'],
|
517
|
-
'quantity': self.
|
518
|
-
'price': self.
|
517
|
+
'quantity': self.amount_to_precision(symbol, amount),
|
518
|
+
'price': self.price_to_precision(symbol, price),
|
519
519
|
}
|
520
520
|
response = None
|
521
521
|
if side == 'buy':
|
ccxt/whitebit.py
CHANGED
@@ -2603,12 +2603,10 @@ class whitebit(Exchange, ImplicitAPI):
|
|
2603
2603
|
url += '?' + self.urlencode(query)
|
2604
2604
|
if accessibility == 'private':
|
2605
2605
|
self.check_required_credentials()
|
2606
|
-
nonce = self.nonce()
|
2607
|
-
timestamp = self.parse_to_int(nonce / 1000)
|
2608
|
-
timestampString = str(timestamp)
|
2606
|
+
nonce = str(self.nonce())
|
2609
2607
|
secret = self.encode(self.secret)
|
2610
2608
|
request = '/' + 'api' + '/' + version + pathWithParams
|
2611
|
-
body = self.json(self.extend({'request': request, 'nonce':
|
2609
|
+
body = self.json(self.extend({'request': request, 'nonce': nonce}, params))
|
2612
2610
|
payload = self.string_to_base64(body)
|
2613
2611
|
signature = self.hmac(self.encode(payload), secret, hashlib.sha512)
|
2614
2612
|
headers = {
|