ccxt 4.2.88__py2.py3-none-any.whl → 4.2.90__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/bingx.py +2 -0
- ccxt/abstract/bybit.py +2 -0
- ccxt/ascendex.py +6 -3
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/ascendex.py +6 -3
- ccxt/async_support/base/exchange.py +15 -2
- ccxt/async_support/bigone.py +2 -2
- ccxt/async_support/binance.py +88 -14
- ccxt/async_support/bingx.py +96 -3
- ccxt/async_support/bit2c.py +2 -2
- ccxt/async_support/bitbank.py +2 -2
- ccxt/async_support/bitfinex.py +2 -2
- ccxt/async_support/bitfinex2.py +4 -3
- ccxt/async_support/bitflyer.py +4 -2
- ccxt/async_support/bitget.py +12 -5
- ccxt/async_support/bitmart.py +6 -4
- ccxt/async_support/bitmex.py +3 -2
- ccxt/async_support/bitopro.py +3 -3
- ccxt/async_support/bitrue.py +3 -2
- ccxt/async_support/bitso.py +2 -2
- ccxt/async_support/bitstamp.py +89 -97
- ccxt/async_support/bitteam.py +2 -2
- ccxt/async_support/bitvavo.py +3 -3
- ccxt/async_support/bl3p.py +2 -2
- ccxt/async_support/blockchaincom.py +2 -2
- ccxt/async_support/blofin.py +4 -2
- ccxt/async_support/bybit.py +57 -5
- ccxt/async_support/cex.py +3 -3
- ccxt/async_support/coinbase.py +42 -22
- ccxt/async_support/coinbaseinternational.py +3 -2
- ccxt/async_support/coinbasepro.py +3 -3
- ccxt/async_support/coincheck.py +2 -2
- ccxt/async_support/coinex.py +101 -13
- ccxt/async_support/coinlist.py +3 -3
- ccxt/async_support/coinmate.py +2 -2
- ccxt/async_support/coinmetro.py +2 -2
- ccxt/async_support/coinone.py +2 -2
- ccxt/async_support/coinsph.py +6 -4
- ccxt/async_support/cryptocom.py +1 -0
- ccxt/async_support/currencycom.py +3 -3
- ccxt/async_support/delta.py +3 -2
- ccxt/async_support/deribit.py +3 -3
- ccxt/async_support/digifinex.py +7 -4
- ccxt/async_support/exmo.py +4 -3
- ccxt/async_support/gate.py +8 -4
- ccxt/async_support/gemini.py +13 -12
- ccxt/async_support/hitbtc.py +8 -5
- ccxt/async_support/hollaex.py +3 -3
- ccxt/async_support/htx.py +7 -4
- ccxt/async_support/huobijp.py +2 -2
- ccxt/async_support/hyperliquid.py +3 -2
- ccxt/async_support/idex.py +3 -3
- ccxt/async_support/independentreserve.py +2 -2
- ccxt/async_support/kraken.py +3 -3
- ccxt/async_support/kucoin.py +43 -18
- ccxt/async_support/kucoinfutures.py +32 -4
- ccxt/async_support/kuna.py +2 -2
- ccxt/async_support/latoken.py +7 -3
- ccxt/async_support/lbank.py +7 -5
- ccxt/async_support/luno.py +4 -2
- ccxt/async_support/lykke.py +2 -2
- ccxt/async_support/mexc.py +57 -9
- ccxt/async_support/ndax.py +2 -2
- ccxt/async_support/oceanex.py +2 -2
- ccxt/async_support/okcoin.py +2 -2
- ccxt/async_support/okx.py +149 -12
- ccxt/async_support/onetrading.py +3 -3
- ccxt/async_support/phemex.py +3 -2
- ccxt/async_support/poloniex.py +3 -3
- ccxt/async_support/probit.py +2 -2
- ccxt/async_support/timex.py +6 -4
- ccxt/async_support/upbit.py +2 -2
- ccxt/async_support/wazirx.py +2 -2
- ccxt/async_support/whitebit.py +3 -3
- ccxt/async_support/woo.py +4 -3
- ccxt/async_support/yobit.py +2 -2
- ccxt/base/exchange.py +65 -12
- ccxt/base/types.py +33 -0
- ccxt/bigone.py +2 -2
- ccxt/binance.py +88 -14
- ccxt/bingx.py +96 -3
- ccxt/bit2c.py +2 -2
- ccxt/bitbank.py +2 -2
- ccxt/bitfinex.py +2 -2
- ccxt/bitfinex2.py +4 -3
- ccxt/bitflyer.py +4 -2
- ccxt/bitget.py +12 -5
- ccxt/bitmart.py +6 -4
- ccxt/bitmex.py +3 -2
- ccxt/bitopro.py +3 -3
- ccxt/bitrue.py +3 -2
- ccxt/bitso.py +2 -2
- ccxt/bitstamp.py +89 -97
- ccxt/bitteam.py +2 -2
- ccxt/bitvavo.py +3 -3
- ccxt/bl3p.py +2 -2
- ccxt/blockchaincom.py +2 -2
- ccxt/blofin.py +4 -2
- ccxt/bybit.py +57 -5
- ccxt/cex.py +3 -3
- ccxt/coinbase.py +42 -22
- ccxt/coinbaseinternational.py +3 -2
- ccxt/coinbasepro.py +3 -3
- ccxt/coincheck.py +2 -2
- ccxt/coinex.py +101 -13
- ccxt/coinlist.py +3 -3
- ccxt/coinmate.py +2 -2
- ccxt/coinmetro.py +2 -2
- ccxt/coinone.py +2 -2
- ccxt/coinsph.py +6 -4
- ccxt/cryptocom.py +1 -0
- ccxt/currencycom.py +3 -3
- ccxt/delta.py +3 -2
- ccxt/deribit.py +3 -3
- ccxt/digifinex.py +7 -4
- ccxt/exmo.py +4 -3
- ccxt/gate.py +8 -4
- ccxt/gemini.py +13 -12
- ccxt/hitbtc.py +8 -5
- ccxt/hollaex.py +3 -3
- ccxt/htx.py +7 -4
- ccxt/huobijp.py +2 -2
- ccxt/hyperliquid.py +3 -2
- ccxt/idex.py +3 -3
- ccxt/independentreserve.py +2 -2
- ccxt/kraken.py +3 -3
- ccxt/kucoin.py +43 -18
- ccxt/kucoinfutures.py +32 -4
- ccxt/kuna.py +2 -2
- ccxt/latoken.py +7 -3
- ccxt/lbank.py +7 -5
- ccxt/luno.py +4 -2
- ccxt/lykke.py +2 -2
- ccxt/mexc.py +57 -9
- ccxt/ndax.py +2 -2
- ccxt/oceanex.py +2 -2
- ccxt/okcoin.py +2 -2
- ccxt/okx.py +149 -12
- ccxt/onetrading.py +3 -3
- ccxt/phemex.py +3 -2
- ccxt/poloniex.py +3 -3
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitget.py +2 -0
- ccxt/pro/bitvavo.py +2 -2
- ccxt/probit.py +2 -2
- ccxt/timex.py +6 -4
- ccxt/upbit.py +2 -2
- ccxt/wazirx.py +2 -2
- ccxt/whitebit.py +3 -3
- ccxt/woo.py +4 -3
- ccxt/yobit.py +2 -2
- {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/METADATA +4 -4
- {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/RECORD +156 -156
- {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/WHEEL +0 -0
- {ccxt-4.2.88.dist-info → ccxt-4.2.90.dist-info}/top_level.txt +0 -0
ccxt/async_support/okx.py
CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
|
|
7
7
|
from ccxt.abstract.okx import ImplicitAPI
|
8
8
|
import asyncio
|
9
9
|
import hashlib
|
10
|
-
from ccxt.base.types import Account, Balances, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
|
10
|
+
from ccxt.base.types import Account, Balances, Currencies, Currency, Greeks, Int, Leverage, MarginModification, Market, MarketInterface, Num, Option, OptionChain, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction, TransferEntry
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import PermissionDenied
|
@@ -107,6 +107,7 @@ class okx(Exchange, ImplicitAPI):
|
|
107
107
|
'fetchLedgerEntry': None,
|
108
108
|
'fetchLeverage': True,
|
109
109
|
'fetchLeverageTiers': False,
|
110
|
+
'fetchMarginAdjustmentHistory': True,
|
110
111
|
'fetchMarketLeverageTiers': True,
|
111
112
|
'fetchMarkets': True,
|
112
113
|
'fetchMarkOHLCV': True,
|
@@ -1543,7 +1544,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1543
1544
|
}
|
1544
1545
|
return self.safe_string(networksById, networkId, networkId)
|
1545
1546
|
|
1546
|
-
async def fetch_currencies(self, params={}):
|
1547
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
1547
1548
|
"""
|
1548
1549
|
fetches all available currencies on an exchange
|
1549
1550
|
:see: https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies
|
@@ -2267,7 +2268,7 @@ class okx(Exchange, ImplicitAPI):
|
|
2267
2268
|
result[code] = account
|
2268
2269
|
return self.safe_balance(result)
|
2269
2270
|
|
2270
|
-
def parse_trading_fee(self, fee, market: Market = None):
|
2271
|
+
def parse_trading_fee(self, fee, market: Market = None) -> TradingFeeInterface:
|
2271
2272
|
# https://www.okx.com/docs-v5/en/#rest-api-account-get-fee-rates
|
2272
2273
|
#
|
2273
2274
|
# {
|
@@ -2287,9 +2288,11 @@ class okx(Exchange, ImplicitAPI):
|
|
2287
2288
|
# OKX returns the fees values opposed to other exchanges, so the sign needs to be flipped
|
2288
2289
|
'maker': self.parse_number(Precise.string_neg(self.safe_string_2(fee, 'maker', 'makerU'))),
|
2289
2290
|
'taker': self.parse_number(Precise.string_neg(self.safe_string_2(fee, 'taker', 'takerU'))),
|
2291
|
+
'percentage': None,
|
2292
|
+
'tierBased': None,
|
2290
2293
|
}
|
2291
2294
|
|
2292
|
-
async def fetch_trading_fee(self, symbol: str, params={}):
|
2295
|
+
async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
2293
2296
|
"""
|
2294
2297
|
fetch the trading fees for a market
|
2295
2298
|
:see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-fee-rates
|
@@ -6034,9 +6037,9 @@ class okx(Exchange, ImplicitAPI):
|
|
6034
6037
|
# }
|
6035
6038
|
#
|
6036
6039
|
data = self.safe_list(response, 'data', [])
|
6040
|
+
entry = self.safe_dict(data, 0, {})
|
6037
6041
|
errorCode = self.safe_string(response, 'code')
|
6038
|
-
|
6039
|
-
return self.extend(self.parse_margin_modification(item, market), {
|
6042
|
+
return self.extend(self.parse_margin_modification(entry, market), {
|
6040
6043
|
'status': 'ok' if (errorCode == '0') else 'failed',
|
6041
6044
|
})
|
6042
6045
|
|
@@ -6051,22 +6054,66 @@ class okx(Exchange, ImplicitAPI):
|
|
6051
6054
|
# "type": "reduce"
|
6052
6055
|
# }
|
6053
6056
|
#
|
6054
|
-
|
6057
|
+
# fetchMarginAdjustmentHistory
|
6058
|
+
#
|
6059
|
+
# {
|
6060
|
+
# bal: '67621.4325135010619812',
|
6061
|
+
# balChg: '-10.0000000000000000',
|
6062
|
+
# billId: '691293628710342659',
|
6063
|
+
# ccy: 'USDT',
|
6064
|
+
# clOrdId: '',
|
6065
|
+
# execType: '',
|
6066
|
+
# fee: '0',
|
6067
|
+
# fillFwdPx: '',
|
6068
|
+
# fillIdxPx: '',
|
6069
|
+
# fillMarkPx: '',
|
6070
|
+
# fillMarkVol: '',
|
6071
|
+
# fillPxUsd: '',
|
6072
|
+
# fillPxVol: '',
|
6073
|
+
# fillTime: '1711089244850',
|
6074
|
+
# from: '',
|
6075
|
+
# instId: 'XRP-USDT-SWAP',
|
6076
|
+
# instType: 'SWAP',
|
6077
|
+
# interest: '0',
|
6078
|
+
# mgnMode: 'isolated',
|
6079
|
+
# notes: '',
|
6080
|
+
# ordId: '',
|
6081
|
+
# pnl: '0',
|
6082
|
+
# posBal: '73.12',
|
6083
|
+
# posBalChg: '10.00',
|
6084
|
+
# px: '',
|
6085
|
+
# subType: '160',
|
6086
|
+
# sz: '10',
|
6087
|
+
# tag: '',
|
6088
|
+
# to: '',
|
6089
|
+
# tradeId: '0',
|
6090
|
+
# ts: '1711089244699',
|
6091
|
+
# type: '6'
|
6092
|
+
# }
|
6093
|
+
#
|
6094
|
+
amountRaw = self.safe_string_2(data, 'amt', 'posBalChg')
|
6055
6095
|
typeRaw = self.safe_string(data, 'type')
|
6056
|
-
type =
|
6096
|
+
type = None
|
6097
|
+
if typeRaw == '6':
|
6098
|
+
type = 'add' if Precise.string_gt(amountRaw, '0') else 'reduce'
|
6099
|
+
else:
|
6100
|
+
type = typeRaw
|
6101
|
+
amount = Precise.string_abs(amountRaw)
|
6057
6102
|
marketId = self.safe_string(data, 'instId')
|
6058
6103
|
responseMarket = self.safe_market(marketId, market)
|
6059
6104
|
code = responseMarket['base'] if responseMarket['inverse'] else responseMarket['quote']
|
6105
|
+
timestamp = self.safe_integer(data, 'ts')
|
6060
6106
|
return {
|
6061
6107
|
'info': data,
|
6062
6108
|
'symbol': responseMarket['symbol'],
|
6063
6109
|
'type': type,
|
6064
|
-
'
|
6065
|
-
'
|
6110
|
+
'marginMode': 'isolated',
|
6111
|
+
'amount': self.parse_number(amount),
|
6066
6112
|
'code': code,
|
6113
|
+
'total': None,
|
6067
6114
|
'status': None,
|
6068
|
-
'timestamp':
|
6069
|
-
'datetime':
|
6115
|
+
'timestamp': timestamp,
|
6116
|
+
'datetime': self.iso8601(timestamp),
|
6070
6117
|
}
|
6071
6118
|
|
6072
6119
|
async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
|
@@ -7087,3 +7134,93 @@ class okx(Exchange, ImplicitAPI):
|
|
7087
7134
|
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
7088
7135
|
raise ExchangeError(feedback) # unknown message
|
7089
7136
|
return None
|
7137
|
+
|
7138
|
+
async def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}) -> List[MarginModification]:
|
7139
|
+
"""
|
7140
|
+
fetches the history of margin added or reduced from contract isolated positions
|
7141
|
+
:see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-7-days
|
7142
|
+
:see: https://www.okx.com/docs-v5/en/#trading-account-rest-api-get-bills-details-last-3-months
|
7143
|
+
:param str [symbol]: not used by okx fetchMarginAdjustmentHistory
|
7144
|
+
:param str [type]: "add" or "reduce"
|
7145
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
7146
|
+
:param boolean [params.auto]: True if fetching auto margin increases
|
7147
|
+
:returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
7148
|
+
"""
|
7149
|
+
await self.load_markets()
|
7150
|
+
auto = self.safe_bool(params, 'auto')
|
7151
|
+
if type is None:
|
7152
|
+
raise ArgumentsRequired(self.id + ' fetchMarginAdjustmentHistory() requires a type argument')
|
7153
|
+
isAdd = type == 'add'
|
7154
|
+
subType = '160' if isAdd else '161'
|
7155
|
+
if auto:
|
7156
|
+
if isAdd:
|
7157
|
+
subType = '162'
|
7158
|
+
else:
|
7159
|
+
raise BadRequest(self.id + ' cannot fetch margin adjustments for type ' + type)
|
7160
|
+
request = {
|
7161
|
+
'subType': subType,
|
7162
|
+
'mgnMode': 'isolated',
|
7163
|
+
}
|
7164
|
+
until = self.safe_integer(params, 'until')
|
7165
|
+
params = self.omit(params, 'until')
|
7166
|
+
if since is not None:
|
7167
|
+
request['startTime'] = since
|
7168
|
+
if limit is not None:
|
7169
|
+
request['limit'] = limit
|
7170
|
+
if until is not None:
|
7171
|
+
request['endTime'] = until
|
7172
|
+
response = None
|
7173
|
+
now = self.milliseconds()
|
7174
|
+
oneWeekAgo = now - 604800000
|
7175
|
+
threeMonthsAgo = now - 7776000000
|
7176
|
+
if (since is None) or (since > oneWeekAgo):
|
7177
|
+
response = await self.privateGetAccountBills(self.extend(request, params))
|
7178
|
+
elif since > threeMonthsAgo:
|
7179
|
+
response = await self.privateGetAccountBillsArchive(self.extend(request, params))
|
7180
|
+
else:
|
7181
|
+
raise BadRequest(self.id + ' fetchMarginAdjustmentHistory() cannot fetch margin adjustments older than 3 months')
|
7182
|
+
#
|
7183
|
+
# {
|
7184
|
+
# code: '0',
|
7185
|
+
# data: [
|
7186
|
+
# {
|
7187
|
+
# bal: '67621.4325135010619812',
|
7188
|
+
# balChg: '-10.0000000000000000',
|
7189
|
+
# billId: '691293628710342659',
|
7190
|
+
# ccy: 'USDT',
|
7191
|
+
# clOrdId: '',
|
7192
|
+
# execType: '',
|
7193
|
+
# fee: '0',
|
7194
|
+
# fillFwdPx: '',
|
7195
|
+
# fillIdxPx: '',
|
7196
|
+
# fillMarkPx: '',
|
7197
|
+
# fillMarkVol: '',
|
7198
|
+
# fillPxUsd: '',
|
7199
|
+
# fillPxVol: '',
|
7200
|
+
# fillTime: '1711089244850',
|
7201
|
+
# from: '',
|
7202
|
+
# instId: 'XRP-USDT-SWAP',
|
7203
|
+
# instType: 'SWAP',
|
7204
|
+
# interest: '0',
|
7205
|
+
# mgnMode: 'isolated',
|
7206
|
+
# notes: '',
|
7207
|
+
# ordId: '',
|
7208
|
+
# pnl: '0',
|
7209
|
+
# posBal: '73.12',
|
7210
|
+
# posBalChg: '10.00',
|
7211
|
+
# px: '',
|
7212
|
+
# subType: '160',
|
7213
|
+
# sz: '10',
|
7214
|
+
# tag: '',
|
7215
|
+
# to: '',
|
7216
|
+
# tradeId: '0',
|
7217
|
+
# ts: '1711089244699',
|
7218
|
+
# type: '6'
|
7219
|
+
# }
|
7220
|
+
# ],
|
7221
|
+
# msg: ''
|
7222
|
+
# }
|
7223
|
+
#
|
7224
|
+
data = self.safe_list(response, 'data')
|
7225
|
+
modifications = self.parse_margin_modifications(data)
|
7226
|
+
return self.filter_by_symbol_since_limit(modifications, symbol, since, limit)
|
ccxt/async_support/onetrading.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.onetrading import ImplicitAPI
|
8
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
8
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction
|
9
9
|
from typing import List
|
10
10
|
from ccxt.base.errors import ExchangeError
|
11
11
|
from ccxt.base.errors import PermissionDenied
|
@@ -325,7 +325,7 @@ class onetrading(Exchange, ImplicitAPI):
|
|
325
325
|
#
|
326
326
|
return self.safe_integer(response, 'epoch_millis')
|
327
327
|
|
328
|
-
async def fetch_currencies(self, params={}):
|
328
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
329
329
|
"""
|
330
330
|
fetches all available currencies on an exchange
|
331
331
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -443,7 +443,7 @@ class onetrading(Exchange, ImplicitAPI):
|
|
443
443
|
'info': market,
|
444
444
|
}
|
445
445
|
|
446
|
-
async def fetch_trading_fees(self, params={}):
|
446
|
+
async def fetch_trading_fees(self, params={}) -> TradingFees:
|
447
447
|
"""
|
448
448
|
fetch the trading fees for multiple markets
|
449
449
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
ccxt/async_support/phemex.py
CHANGED
@@ -7,7 +7,7 @@ from ccxt.async_support.base.exchange import Exchange
|
|
7
7
|
from ccxt.abstract.phemex import ImplicitAPI
|
8
8
|
import hashlib
|
9
9
|
import numbers
|
10
|
-
from ccxt.base.types import Balances, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
|
10
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, MarginModification, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
13
13
|
from ccxt.base.errors import PermissionDenied
|
@@ -971,7 +971,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
971
971
|
result.append(market)
|
972
972
|
return result
|
973
973
|
|
974
|
-
async def fetch_currencies(self, params={}):
|
974
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
975
975
|
"""
|
976
976
|
fetches all available currencies on an exchange
|
977
977
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
@@ -3792,6 +3792,7 @@ class phemex(Exchange, ImplicitAPI):
|
|
3792
3792
|
'info': data,
|
3793
3793
|
'symbol': self.safe_symbol(None, market),
|
3794
3794
|
'type': 'set',
|
3795
|
+
'marginMode': 'isolated',
|
3795
3796
|
'amount': None,
|
3796
3797
|
'total': None,
|
3797
3798
|
'code': market[codeCurrency],
|
ccxt/async_support/poloniex.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.poloniex import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
|
9
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import PermissionDenied
|
@@ -671,7 +671,7 @@ class poloniex(Exchange, ImplicitAPI):
|
|
671
671
|
#
|
672
672
|
return self.parse_tickers(response, symbols)
|
673
673
|
|
674
|
-
async def fetch_currencies(self, params={}):
|
674
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
675
675
|
"""
|
676
676
|
fetches all available currencies on an exchange
|
677
677
|
:see: https://docs.poloniex.com/#public-endpoints-reference-data-currency-information
|
@@ -1570,7 +1570,7 @@ class poloniex(Exchange, ImplicitAPI):
|
|
1570
1570
|
#
|
1571
1571
|
return self.parse_balance(response)
|
1572
1572
|
|
1573
|
-
async def fetch_trading_fees(self, params={}):
|
1573
|
+
async def fetch_trading_fees(self, params={}) -> TradingFees:
|
1574
1574
|
"""
|
1575
1575
|
fetch the trading fees for multiple markets
|
1576
1576
|
:see: https://docs.poloniex.com/#authenticated-endpoints-accounts-fee-info
|
ccxt/async_support/probit.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.probit import ImplicitAPI
|
8
8
|
import math
|
9
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
9
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, 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 ArgumentsRequired
|
@@ -355,7 +355,7 @@ class probit(Exchange, ImplicitAPI):
|
|
355
355
|
'info': market,
|
356
356
|
}
|
357
357
|
|
358
|
-
async def fetch_currencies(self, params={}):
|
358
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
359
359
|
"""
|
360
360
|
:see: https://docs-en.probit.com/reference/currency
|
361
361
|
fetches all available currencies on an exchange
|
ccxt/async_support/timex.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.timex import ImplicitAPI
|
8
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
8
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction
|
9
9
|
from typing import List
|
10
10
|
from ccxt.base.errors import ExchangeError
|
11
11
|
from ccxt.base.errors import PermissionDenied
|
@@ -323,7 +323,7 @@ class timex(Exchange, ImplicitAPI):
|
|
323
323
|
#
|
324
324
|
return self.parse_markets(response)
|
325
325
|
|
326
|
-
async def fetch_currencies(self, params={}):
|
326
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
327
327
|
"""
|
328
328
|
fetches all available currencies on an exchange
|
329
329
|
:see: https://plasma-relay-backend.timex.io/swagger-ui/index.html?urls.primaryName=Relay#/Public/listCurrencies
|
@@ -1096,7 +1096,7 @@ class timex(Exchange, ImplicitAPI):
|
|
1096
1096
|
trades = self.safe_list(response, 'trades', [])
|
1097
1097
|
return self.parse_trades(trades, market, since, limit)
|
1098
1098
|
|
1099
|
-
def parse_trading_fee(self, fee, market: Market = None):
|
1099
|
+
def parse_trading_fee(self, fee, market: Market = None) -> TradingFeeInterface:
|
1100
1100
|
#
|
1101
1101
|
# {
|
1102
1102
|
# "fee": 0.0075,
|
@@ -1110,9 +1110,11 @@ class timex(Exchange, ImplicitAPI):
|
|
1110
1110
|
'symbol': self.safe_symbol(marketId, market),
|
1111
1111
|
'maker': rate,
|
1112
1112
|
'taker': rate,
|
1113
|
+
'percentage': None,
|
1114
|
+
'tierBased': None,
|
1113
1115
|
}
|
1114
1116
|
|
1115
|
-
async def fetch_trading_fee(self, symbol: str, params={}):
|
1117
|
+
async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
1116
1118
|
"""
|
1117
1119
|
fetch the trading fees for a market
|
1118
1120
|
:see: https://plasma-relay-backend.timex.io/swagger-ui/index.html?urls.primaryName=Relay#/Trading/getFees
|
ccxt/async_support/upbit.py
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.upbit import ImplicitAPI
|
8
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
8
|
+
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, Transaction
|
9
9
|
from typing import List
|
10
10
|
from ccxt.base.errors import ExchangeError
|
11
11
|
from ccxt.base.errors import PermissionDenied
|
@@ -836,7 +836,7 @@ class upbit(Exchange, ImplicitAPI):
|
|
836
836
|
#
|
837
837
|
return self.parse_trades(response, market, since, limit)
|
838
838
|
|
839
|
-
async def fetch_trading_fee(self, symbol: str, params={}):
|
839
|
+
async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
|
840
840
|
"""
|
841
841
|
:see: https://docs.upbit.com/reference/%EC%A3%BC%EB%AC%B8-%EA%B0%80%EB%8A%A5-%EC%A0%95%EB%B3%B4
|
842
842
|
fetch the trading fees for a market
|
ccxt/async_support/wazirx.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.wazirx import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Currency, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction
|
9
|
+
from ccxt.base.types import Balances, Currencies, Currency, Int, Market, Num, Order, 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
|
@@ -882,7 +882,7 @@ class wazirx(Exchange, ImplicitAPI):
|
|
882
882
|
}
|
883
883
|
return self.safe_string(statuses, status, status)
|
884
884
|
|
885
|
-
async def fetch_currencies(self, params={}):
|
885
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
886
886
|
"""
|
887
887
|
fetches all available currencies on an exchange
|
888
888
|
:see: https://docs.wazirx.com/#all-coins-39-information-user_data
|
ccxt/async_support/whitebit.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.whitebit import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Bool, Currency, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, Transaction, TransferEntry
|
9
|
+
from ccxt.base.types import Balances, Bool, Currencies, Currency, Int, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees, Transaction, TransferEntry
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import PermissionDenied
|
@@ -401,7 +401,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
401
401
|
'info': market,
|
402
402
|
}
|
403
403
|
|
404
|
-
async def fetch_currencies(self, params={}):
|
404
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
405
405
|
"""
|
406
406
|
fetches all available currencies on an exchange
|
407
407
|
:see: https://docs.whitebit.com/public/http-v4/#asset-status-list
|
@@ -652,7 +652,7 @@ class whitebit(Exchange, ImplicitAPI):
|
|
652
652
|
depositWithdrawFees[code] = self.assign_default_deposit_withdraw_fees(depositWithdrawFees[code], currency)
|
653
653
|
return depositWithdrawFees
|
654
654
|
|
655
|
-
async def fetch_trading_fees(self, params={}):
|
655
|
+
async def fetch_trading_fees(self, params={}) -> TradingFees:
|
656
656
|
"""
|
657
657
|
fetch the trading fees for multiple markets
|
658
658
|
:see: https://docs.whitebit.com/public/http-v4/#asset-status-list
|
ccxt/async_support/woo.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.woo import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Account, Balances, Bool, Currency, Int, Leverage, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, Transaction, TransferEntry
|
9
|
+
from ccxt.base.types import Account, Balances, Bool, Currencies, Currency, Int, Leverage, Market, MarketType, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Trade, TradingFees, Transaction, TransferEntry
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import ArgumentsRequired
|
@@ -77,6 +77,7 @@ class woo(Exchange, ImplicitAPI):
|
|
77
77
|
'fetchIndexOHLCV': False,
|
78
78
|
'fetchLedger': True,
|
79
79
|
'fetchLeverage': True,
|
80
|
+
'fetchMarginAdjustmentHistory': False,
|
80
81
|
'fetchMarginMode': False,
|
81
82
|
'fetchMarkets': True,
|
82
83
|
'fetchMarkOHLCV': False,
|
@@ -620,7 +621,7 @@ class woo(Exchange, ImplicitAPI):
|
|
620
621
|
}
|
621
622
|
return fee
|
622
623
|
|
623
|
-
async def fetch_trading_fees(self, params={}):
|
624
|
+
async def fetch_trading_fees(self, params={}) -> TradingFees:
|
624
625
|
"""
|
625
626
|
fetch the trading fees for multiple markets
|
626
627
|
:see: https://docs.woo.org/#get-account-information-new
|
@@ -673,7 +674,7 @@ class woo(Exchange, ImplicitAPI):
|
|
673
674
|
}
|
674
675
|
return result
|
675
676
|
|
676
|
-
async def fetch_currencies(self, params={}):
|
677
|
+
async def fetch_currencies(self, params={}) -> Currencies:
|
677
678
|
"""
|
678
679
|
fetches all available currencies on an exchange
|
679
680
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
ccxt/async_support/yobit.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
from ccxt.async_support.base.exchange import Exchange
|
7
7
|
from ccxt.abstract.yobit import ImplicitAPI
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Market, Num, Order, OrderBook, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFees
|
10
10
|
from typing import List
|
11
11
|
from ccxt.base.errors import ExchangeError
|
12
12
|
from ccxt.base.errors import ArgumentsRequired
|
@@ -700,7 +700,7 @@ class yobit(Exchange, ImplicitAPI):
|
|
700
700
|
result = self.safe_list(response, market['id'], [])
|
701
701
|
return self.parse_trades(result, market, since, limit)
|
702
702
|
|
703
|
-
async def fetch_trading_fees(self, params={}):
|
703
|
+
async def fetch_trading_fees(self, params={}) -> TradingFees:
|
704
704
|
"""
|
705
705
|
:see: https://yobit.net/en/api
|
706
706
|
fetch the trading fees for multiple markets
|
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.2.
|
7
|
+
__version__ = '4.2.90'
|
8
8
|
|
9
9
|
# -----------------------------------------------------------------------------
|
10
10
|
|
@@ -39,6 +39,7 @@ from ccxt.base.types import BalanceAccount, Currency, IndexType, OrderSide, Orde
|
|
39
39
|
from cryptography.hazmat import backends
|
40
40
|
from cryptography.hazmat.primitives import hashes
|
41
41
|
from cryptography.hazmat.primitives.asymmetric import padding
|
42
|
+
# from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature
|
42
43
|
from cryptography.hazmat.primitives.serialization import load_pem_private_key
|
43
44
|
|
44
45
|
# -----------------------------------------------------------------------------
|
@@ -1314,22 +1315,33 @@ class Exchange(object):
|
|
1314
1315
|
return Exchange.decode(base64.b64decode(s))
|
1315
1316
|
|
1316
1317
|
@staticmethod
|
1317
|
-
def jwt(request, secret, algorithm='sha256', is_rsa=False):
|
1318
|
+
def jwt(request, secret, algorithm='sha256', is_rsa=False, opts={}):
|
1318
1319
|
algos = {
|
1319
1320
|
'sha256': hashlib.sha256,
|
1320
1321
|
'sha384': hashlib.sha384,
|
1321
1322
|
'sha512': hashlib.sha512,
|
1322
1323
|
}
|
1323
1324
|
alg = ('RS' if is_rsa else 'HS') + algorithm[3:]
|
1324
|
-
|
1325
|
+
if 'alg' in opts and opts['alg'] is not None:
|
1326
|
+
alg = opts['alg']
|
1327
|
+
header_opts = {
|
1325
1328
|
'alg': alg,
|
1326
1329
|
'typ': 'JWT',
|
1327
|
-
}
|
1330
|
+
}
|
1331
|
+
if 'kid' in opts and opts['kid'] is not None:
|
1332
|
+
header_opts['kid'] = opts['kid']
|
1333
|
+
if 'nonce' in opts and opts['nonce'] is not None:
|
1334
|
+
header_opts['nonce'] = opts['nonce']
|
1335
|
+
header = Exchange.encode(Exchange.json(header_opts))
|
1328
1336
|
encoded_header = Exchange.base64urlencode(header)
|
1329
1337
|
encoded_data = Exchange.base64urlencode(Exchange.encode(Exchange.json(request)))
|
1330
1338
|
token = encoded_header + '.' + encoded_data
|
1331
|
-
|
1339
|
+
algoType = alg[0:2]
|
1340
|
+
if is_rsa or algoType == 'RS':
|
1332
1341
|
signature = Exchange.base64_to_binary(Exchange.rsa(token, Exchange.decode(secret), algorithm))
|
1342
|
+
elif algoType == 'ES':
|
1343
|
+
rawSignature = Exchange.ecdsa(token, secret, 'p256', algorithm)
|
1344
|
+
signature = Exchange.base16_to_binary(rawSignature['r'] + rawSignature['s'])
|
1333
1345
|
else:
|
1334
1346
|
signature = Exchange.hmac(Exchange.encode(token), secret, algos[algorithm], 'binary')
|
1335
1347
|
return token + '.' + Exchange.base64urlencode(signature)
|
@@ -1362,6 +1374,10 @@ class Exchange(object):
|
|
1362
1374
|
def int_to_base16(num):
|
1363
1375
|
return "%0.2X" % num
|
1364
1376
|
|
1377
|
+
@staticmethod
|
1378
|
+
def random_bytes(length):
|
1379
|
+
return format(random.getrandbits(length * 8), 'x')
|
1380
|
+
|
1365
1381
|
@staticmethod
|
1366
1382
|
def ecdsa(request, secret, algorithm='p256', hash=None, fixed_length=False):
|
1367
1383
|
# your welcome - frosty00
|
@@ -1382,7 +1398,12 @@ class Exchange(object):
|
|
1382
1398
|
digest = Exchange.hash(encoded_request, hash, 'binary')
|
1383
1399
|
else:
|
1384
1400
|
digest = base64.b16decode(encoded_request, casefold=True)
|
1385
|
-
|
1401
|
+
if isinstance(secret, str):
|
1402
|
+
secret = Exchange.encode(secret)
|
1403
|
+
if secret.find(b'-----BEGIN EC PRIVATE KEY-----') > -1:
|
1404
|
+
key = ecdsa.SigningKey.from_pem(secret, hash_function)
|
1405
|
+
else:
|
1406
|
+
key = ecdsa.SigningKey.from_string(base64.b16decode(secret,
|
1386
1407
|
casefold=True), curve=curve_info[0])
|
1387
1408
|
r_binary, s_binary, v = key.sign_digest_deterministic(digest, hashfunc=hash_function,
|
1388
1409
|
sigencode=ecdsa.util.sigencode_strings_canonize)
|
@@ -2249,6 +2270,18 @@ class Exchange(object):
|
|
2249
2270
|
def set_margin(self, symbol: str, amount: float, params={}):
|
2250
2271
|
raise NotSupported(self.id + ' setMargin() is not supported yet')
|
2251
2272
|
|
2273
|
+
def fetch_margin_adjustment_history(self, symbol: Str = None, type: Str = None, since: Num = None, limit: Num = None, params={}):
|
2274
|
+
"""
|
2275
|
+
fetches the history of margin added or reduced from contract isolated positions
|
2276
|
+
:param str [symbol]: unified market symbol
|
2277
|
+
:param str [type]: "add" or "reduce"
|
2278
|
+
:param int [since]: timestamp in ms of the earliest change to fetch
|
2279
|
+
:param int [limit]: the maximum amount of changes to fetch
|
2280
|
+
:param dict params: extra parameters specific to the exchange api endpoint
|
2281
|
+
:returns dict[]: a list of `margin structures <https://docs.ccxt.com/#/?id=margin-loan-structure>`
|
2282
|
+
"""
|
2283
|
+
raise NotSupported(self.id + ' fetchMarginAdjustmentHistory() is not supported yet')
|
2284
|
+
|
2252
2285
|
def set_margin_mode(self, marginMode: str, symbol: Str = None, params={}):
|
2253
2286
|
raise NotSupported(self.id + ' setMarginMode() is not supported yet')
|
2254
2287
|
|
@@ -3732,11 +3765,11 @@ class Exchange(object):
|
|
3732
3765
|
code = currencyId
|
3733
3766
|
if currencyId is not None:
|
3734
3767
|
code = self.common_currency_code(currencyId.upper())
|
3735
|
-
return {
|
3768
|
+
return self.safe_currency_structure({
|
3736
3769
|
'id': currencyId,
|
3737
3770
|
'code': code,
|
3738
3771
|
'precision': None,
|
3739
|
-
}
|
3772
|
+
})
|
3740
3773
|
|
3741
3774
|
def safe_market(self, marketId: Str, market: Market = None, delimiter: Str = None, marketType: Str = None):
|
3742
3775
|
result = self.safe_market_structure({
|
@@ -4390,10 +4423,16 @@ class Exchange(object):
|
|
4390
4423
|
'total': None,
|
4391
4424
|
}
|
4392
4425
|
|
4393
|
-
def common_currency_code(self,
|
4426
|
+
def common_currency_code(self, code: str):
|
4394
4427
|
if not self.substituteCommonCurrencyCodes:
|
4395
|
-
return
|
4396
|
-
|
4428
|
+
return code
|
4429
|
+
# if the provided code already exists value in commonCurrencies dict, then we should not again transform it
|
4430
|
+
# more details at: https://github.com/ccxt/ccxt/issues/21112#issuecomment-2031293691
|
4431
|
+
commonCurrencies = list(self.commonCurrencies.values())
|
4432
|
+
exists = self.in_array(code, commonCurrencies)
|
4433
|
+
if exists:
|
4434
|
+
return code
|
4435
|
+
return self.safe_string(self.commonCurrencies, code, code)
|
4397
4436
|
|
4398
4437
|
def currency(self, code: str):
|
4399
4438
|
if self.currencies is None:
|
@@ -4791,7 +4830,8 @@ class Exchange(object):
|
|
4791
4830
|
def fetch_trading_fee(self, symbol: str, params={}):
|
4792
4831
|
if not self.has['fetchTradingFees']:
|
4793
4832
|
raise NotSupported(self.id + ' fetchTradingFee() is not supported yet')
|
4794
|
-
|
4833
|
+
fees = self.fetch_trading_fees(params)
|
4834
|
+
return self.safe_dict(fees, symbol)
|
4795
4835
|
|
4796
4836
|
def parse_open_interest(self, interest, market: Market = None):
|
4797
4837
|
raise NotSupported(self.id + ' parseOpenInterest() is not supported yet')
|
@@ -5440,3 +5480,16 @@ class Exchange(object):
|
|
5440
5480
|
day = date[5:7]
|
5441
5481
|
reconstructedDate = day + month + year
|
5442
5482
|
return reconstructedDate
|
5483
|
+
|
5484
|
+
def parse_margin_modification(self, data, market: Market = None):
|
5485
|
+
raise NotSupported(self.id + ' parseMarginModification() is not supported yet')
|
5486
|
+
|
5487
|
+
def parse_margin_modifications(self, response: List[object], symbols: List[str] = None, symbolKey: Str = None, marketType: MarketType = None):
|
5488
|
+
marginModifications = []
|
5489
|
+
for i in range(0, len(response)):
|
5490
|
+
info = response[i]
|
5491
|
+
marketId = self.safe_string(info, symbolKey)
|
5492
|
+
market = self.safe_market(marketId, None, None, marketType)
|
5493
|
+
if (symbols is None) or self.in_array(market['symbol'], symbols):
|
5494
|
+
marginModifications.append(self.parse_margin_modification(info, market))
|
5495
|
+
return marginModifications
|