ccxt 4.3.33__py2.py3-none-any.whl → 4.3.35__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/binance.py +1 -0
- ccxt/abstract/binancecoinm.py +1 -0
- ccxt/abstract/binanceus.py +1 -0
- ccxt/abstract/binanceusdm.py +1 -0
- ccxt/ace.py +2 -2
- ccxt/alpaca.py +2 -2
- ccxt/ascendex.py +2 -2
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/ace.py +2 -2
- ccxt/async_support/alpaca.py +2 -2
- ccxt/async_support/ascendex.py +2 -2
- ccxt/async_support/base/exchange.py +56 -40
- ccxt/async_support/bigone.py +2 -2
- ccxt/async_support/binance.py +6 -5
- ccxt/async_support/bingx.py +4 -3
- ccxt/async_support/bit2c.py +1 -1
- ccxt/async_support/bitbank.py +1 -1
- ccxt/async_support/bitbns.py +1 -1
- ccxt/async_support/bitfinex.py +2 -2
- ccxt/async_support/bitfinex2.py +1 -1
- ccxt/async_support/bitflyer.py +1 -1
- ccxt/async_support/bitget.py +4 -4
- ccxt/async_support/bithumb.py +1 -1
- ccxt/async_support/bitmart.py +4 -9
- ccxt/async_support/bitmex.py +3 -3
- ccxt/async_support/bitopro.py +3 -3
- ccxt/async_support/bitrue.py +2 -2
- ccxt/async_support/bitso.py +2 -2
- ccxt/async_support/bitstamp.py +2 -2
- ccxt/async_support/bitteam.py +3 -3
- ccxt/async_support/bitvavo.py +2 -2
- ccxt/async_support/blockchaincom.py +1 -1
- ccxt/async_support/blofin.py +3 -3
- ccxt/async_support/btcalpha.py +3 -3
- ccxt/async_support/btcbox.py +1 -1
- ccxt/async_support/btcmarkets.py +6 -4
- ccxt/async_support/btcturk.py +1 -1
- ccxt/async_support/bybit.py +3 -3
- ccxt/async_support/cex.py +1 -1
- ccxt/async_support/coinbase.py +156 -58
- ccxt/async_support/coinbaseexchange.py +1 -1
- ccxt/async_support/coinbaseinternational.py +3 -3
- ccxt/async_support/coincheck.py +2 -2
- ccxt/async_support/coinex.py +28 -21
- ccxt/async_support/coinlist.py +2 -2
- ccxt/async_support/coinmate.py +2 -2
- ccxt/async_support/coinmetro.py +2 -2
- ccxt/async_support/coinone.py +1 -1
- ccxt/async_support/coinsph.py +2 -2
- ccxt/async_support/cryptocom.py +1 -1
- ccxt/async_support/currencycom.py +2 -2
- ccxt/async_support/delta.py +1 -1
- ccxt/async_support/deribit.py +2 -2
- ccxt/async_support/digifinex.py +2 -2
- ccxt/async_support/exmo.py +2 -2
- ccxt/async_support/gate.py +2 -2
- ccxt/async_support/gemini.py +3 -3
- ccxt/async_support/hitbtc.py +2 -2
- ccxt/async_support/hollaex.py +1 -1
- ccxt/async_support/htx.py +2 -2
- ccxt/async_support/huobijp.py +2 -2
- ccxt/async_support/hyperliquid.py +2 -2
- ccxt/async_support/idex.py +2 -2
- ccxt/async_support/indodax.py +2 -2
- ccxt/async_support/kraken.py +5 -3
- ccxt/async_support/krakenfutures.py +1 -1
- ccxt/async_support/kucoin.py +2 -2
- ccxt/async_support/kuna.py +2 -2
- ccxt/async_support/latoken.py +2 -2
- ccxt/async_support/lbank.py +1 -1
- ccxt/async_support/luno.py +1 -1
- ccxt/async_support/lykke.py +1 -1
- ccxt/async_support/mercado.py +1 -1
- ccxt/async_support/mexc.py +1 -1
- ccxt/async_support/ndax.py +2 -2
- ccxt/async_support/novadax.py +3 -3
- ccxt/async_support/oceanex.py +2 -2
- ccxt/async_support/okcoin.py +3 -3
- ccxt/async_support/okx.py +3 -3
- ccxt/async_support/onetrading.py +2 -2
- ccxt/async_support/p2b.py +2 -2
- ccxt/async_support/paymium.py +1 -1
- ccxt/async_support/phemex.py +4 -4
- ccxt/async_support/poloniex.py +3 -3
- ccxt/async_support/poloniexfutures.py +2 -2
- ccxt/async_support/probit.py +3 -3
- ccxt/async_support/timex.py +2 -2
- ccxt/async_support/tokocrypto.py +1 -1
- ccxt/async_support/tradeogre.py +1 -1
- ccxt/async_support/upbit.py +3 -3
- ccxt/async_support/wavesexchange.py +1 -1
- ccxt/async_support/wazirx.py +3 -3
- ccxt/async_support/whitebit.py +3 -3
- ccxt/async_support/woo.py +3 -3
- ccxt/async_support/woofipro.py +3 -3
- ccxt/async_support/yobit.py +1 -1
- ccxt/async_support/zaif.py +2 -2
- ccxt/async_support/zonda.py +1 -1
- ccxt/base/exchange.py +107 -76
- ccxt/base/types.py +0 -1
- ccxt/bigone.py +2 -2
- ccxt/binance.py +6 -5
- ccxt/bingx.py +4 -3
- ccxt/bit2c.py +1 -1
- ccxt/bitbank.py +1 -1
- ccxt/bitbns.py +1 -1
- ccxt/bitfinex.py +2 -2
- ccxt/bitfinex2.py +1 -1
- ccxt/bitflyer.py +1 -1
- ccxt/bitget.py +4 -4
- ccxt/bithumb.py +1 -1
- ccxt/bitmart.py +4 -9
- ccxt/bitmex.py +3 -3
- ccxt/bitopro.py +3 -3
- ccxt/bitrue.py +2 -2
- ccxt/bitso.py +2 -2
- ccxt/bitstamp.py +2 -2
- ccxt/bitteam.py +3 -3
- ccxt/bitvavo.py +2 -2
- ccxt/blockchaincom.py +1 -1
- ccxt/blofin.py +3 -3
- ccxt/btcalpha.py +3 -3
- ccxt/btcbox.py +1 -1
- ccxt/btcmarkets.py +6 -4
- ccxt/btcturk.py +1 -1
- ccxt/bybit.py +3 -3
- ccxt/cex.py +1 -1
- ccxt/coinbase.py +156 -58
- ccxt/coinbaseexchange.py +1 -1
- ccxt/coinbaseinternational.py +3 -3
- ccxt/coincheck.py +2 -2
- ccxt/coinex.py +28 -21
- ccxt/coinlist.py +2 -2
- ccxt/coinmate.py +2 -2
- ccxt/coinmetro.py +2 -2
- ccxt/coinone.py +1 -1
- ccxt/coinsph.py +2 -2
- ccxt/cryptocom.py +1 -1
- ccxt/currencycom.py +2 -2
- ccxt/delta.py +1 -1
- ccxt/deribit.py +2 -2
- ccxt/digifinex.py +2 -2
- ccxt/exmo.py +2 -2
- ccxt/gate.py +2 -2
- ccxt/gemini.py +3 -3
- ccxt/hitbtc.py +2 -2
- ccxt/hollaex.py +1 -1
- ccxt/htx.py +2 -2
- ccxt/huobijp.py +2 -2
- ccxt/hyperliquid.py +2 -2
- ccxt/idex.py +2 -2
- ccxt/indodax.py +2 -2
- ccxt/kraken.py +5 -3
- ccxt/krakenfutures.py +1 -1
- ccxt/kucoin.py +2 -2
- ccxt/kuna.py +2 -2
- ccxt/latoken.py +2 -2
- ccxt/lbank.py +1 -1
- ccxt/luno.py +1 -1
- ccxt/lykke.py +1 -1
- ccxt/mercado.py +1 -1
- ccxt/mexc.py +1 -1
- ccxt/ndax.py +2 -2
- ccxt/novadax.py +3 -3
- ccxt/oceanex.py +2 -2
- ccxt/okcoin.py +3 -3
- ccxt/okx.py +3 -3
- ccxt/onetrading.py +2 -2
- ccxt/p2b.py +2 -2
- ccxt/paymium.py +1 -1
- ccxt/phemex.py +4 -4
- ccxt/poloniex.py +3 -3
- ccxt/poloniexfutures.py +2 -2
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/binance.py +331 -2
- ccxt/pro/bitget.py +24 -1
- ccxt/pro/bitmart.py +1 -1
- ccxt/pro/bitmex.py +98 -1
- ccxt/pro/bybit.py +82 -1
- ccxt/pro/gate.py +173 -1
- ccxt/pro/kraken.py +1 -1
- ccxt/pro/kucoinfutures.py +4 -0
- ccxt/pro/okx.py +244 -1
- ccxt/probit.py +3 -3
- ccxt/test/base/__init__.py +1 -0
- ccxt/test/base/test_crypto.py +1 -1
- ccxt/test/base/test_liquidation.py +50 -0
- ccxt/timex.py +2 -2
- ccxt/tokocrypto.py +1 -1
- ccxt/tradeogre.py +1 -1
- ccxt/upbit.py +3 -3
- ccxt/wavesexchange.py +1 -1
- ccxt/wazirx.py +3 -3
- ccxt/whitebit.py +3 -3
- ccxt/woo.py +3 -3
- ccxt/woofipro.py +3 -3
- ccxt/yobit.py +1 -1
- ccxt/zaif.py +2 -2
- ccxt/zonda.py +1 -1
- {ccxt-4.3.33.dist-info → ccxt-4.3.35.dist-info}/METADATA +4 -4
- {ccxt-4.3.33.dist-info → ccxt-4.3.35.dist-info}/RECORD +204 -203
- {ccxt-4.3.33.dist-info → ccxt-4.3.35.dist-info}/WHEEL +0 -0
- {ccxt-4.3.33.dist-info → ccxt-4.3.35.dist-info}/top_level.txt +0 -0
ccxt/pro/bybit.py
CHANGED
@@ -7,7 +7,7 @@ import ccxt.async_support
|
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import asyncio
|
9
9
|
import hashlib
|
10
|
-
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
10
|
+
from ccxt.base.types import Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, Trade
|
11
11
|
from ccxt.async_support.base.ws.client import Client
|
12
12
|
from typing import List
|
13
13
|
from ccxt.base.errors import ExchangeError
|
@@ -32,6 +32,10 @@ class bybit(ccxt.async_support.bybit):
|
|
32
32
|
'fetchTradesWs': False,
|
33
33
|
'fetchBalanceWs': False,
|
34
34
|
'watchBalance': True,
|
35
|
+
'watchLiquidations': True,
|
36
|
+
'watchLiquidationsForSymbols': False,
|
37
|
+
'watchMyLiquidations': False,
|
38
|
+
'watchMyLiquidationsForSymbols': False,
|
35
39
|
'watchMyTrades': True,
|
36
40
|
'watchOHLCV': True,
|
37
41
|
'watchOHLCVForSymbols': False,
|
@@ -1124,6 +1128,82 @@ class bybit(ccxt.async_support.bybit):
|
|
1124
1128
|
client.resolve(positions, messageHash)
|
1125
1129
|
client.resolve(newPositions, 'positions')
|
1126
1130
|
|
1131
|
+
async def watch_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
1132
|
+
"""
|
1133
|
+
watch the public liquidations of a trading pair
|
1134
|
+
:see: https://bybit-exchange.github.io/docs/v5/websocket/public/liquidation
|
1135
|
+
:param str symbol: unified CCXT market symbol
|
1136
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
1137
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
1138
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
1139
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
1140
|
+
"""
|
1141
|
+
await self.load_markets()
|
1142
|
+
market = self.market(symbol)
|
1143
|
+
symbol = market['symbol']
|
1144
|
+
url = self.get_url_by_market_type(symbol, False, 'watchLiquidations', params)
|
1145
|
+
params = self.clean_params(params)
|
1146
|
+
messageHash = 'liquidations::' + symbol
|
1147
|
+
topic = 'liquidation.' + market['id']
|
1148
|
+
newLiquidation = await self.watch_topics(url, [messageHash], [topic], params)
|
1149
|
+
if self.newUpdates:
|
1150
|
+
return [newLiquidation]
|
1151
|
+
return self.filter_by_symbols_since_limit(self.liquidations, [symbol], since, limit, True)
|
1152
|
+
|
1153
|
+
def handle_liquidation(self, client: Client, message):
|
1154
|
+
#
|
1155
|
+
# {
|
1156
|
+
# "data": {
|
1157
|
+
# "price": "0.03803",
|
1158
|
+
# "side": "Buy",
|
1159
|
+
# "size": "1637",
|
1160
|
+
# "symbol": "GALAUSDT",
|
1161
|
+
# "updatedTime": 1673251091822
|
1162
|
+
# },
|
1163
|
+
# "topic": "liquidation.GALAUSDT",
|
1164
|
+
# "ts": 1673251091822,
|
1165
|
+
# "type": "snapshot"
|
1166
|
+
# }
|
1167
|
+
#
|
1168
|
+
rawLiquidation = self.safe_dict(message, 'data', {})
|
1169
|
+
marketId = self.safe_string(rawLiquidation, 'symbol')
|
1170
|
+
market = self.safe_market(marketId, None, '', 'contract')
|
1171
|
+
symbol = self.safe_symbol(marketId)
|
1172
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation, market)
|
1173
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
1174
|
+
if liquidations is None:
|
1175
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
1176
|
+
liquidations = ArrayCache(limit)
|
1177
|
+
liquidations.append(liquidation)
|
1178
|
+
self.liquidations[symbol] = liquidations
|
1179
|
+
client.resolve([liquidation], 'liquidations')
|
1180
|
+
client.resolve([liquidation], 'liquidations::' + symbol)
|
1181
|
+
|
1182
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
1183
|
+
#
|
1184
|
+
# {
|
1185
|
+
# "price": "0.03803",
|
1186
|
+
# "side": "Buy",
|
1187
|
+
# "size": "1637",
|
1188
|
+
# "symbol": "GALAUSDT",
|
1189
|
+
# "updatedTime": 1673251091822
|
1190
|
+
# }
|
1191
|
+
#
|
1192
|
+
marketId = self.safe_string(liquidation, 'symbol')
|
1193
|
+
market = self.safe_market(marketId, market, '', 'contract')
|
1194
|
+
timestamp = self.safe_integer(liquidation, 'updatedTime')
|
1195
|
+
return self.safe_liquidation({
|
1196
|
+
'info': liquidation,
|
1197
|
+
'symbol': self.safe_symbol(marketId, market),
|
1198
|
+
'contracts': self.safe_number(liquidation, 'size'),
|
1199
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
1200
|
+
'price': self.safe_number(liquidation, 'price'),
|
1201
|
+
'baseValue': None,
|
1202
|
+
'quoteValue': None,
|
1203
|
+
'timestamp': timestamp,
|
1204
|
+
'datetime': self.iso8601(timestamp),
|
1205
|
+
})
|
1206
|
+
|
1127
1207
|
async def watch_orders(self, symbol: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Order]:
|
1128
1208
|
"""
|
1129
1209
|
watches information on multiple orders made by the user
|
@@ -1830,6 +1910,7 @@ class bybit(ccxt.async_support.bybit):
|
|
1830
1910
|
'ticketInfo': self.handle_my_trades,
|
1831
1911
|
'user.openapi.perp.trade': self.handle_my_trades,
|
1832
1912
|
'position': self.handle_positions,
|
1913
|
+
'liquidation': self.handle_liquidation,
|
1833
1914
|
'pong': self.handle_pong,
|
1834
1915
|
'order.create': self.handle_order_ws,
|
1835
1916
|
'order.amend': self.handle_order_ws,
|
ccxt/pro/gate.py
CHANGED
@@ -6,13 +6,14 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Liquidation, Order, OrderBook, Position, Str, Strings, Ticker, Tickers, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import AuthenticationError
|
13
13
|
from ccxt.base.errors import ArgumentsRequired
|
14
14
|
from ccxt.base.errors import BadRequest
|
15
15
|
from ccxt.base.errors import InvalidNonce
|
16
|
+
from ccxt.base.precise import Precise
|
16
17
|
|
17
18
|
|
18
19
|
class gate(ccxt.async_support.gate):
|
@@ -30,6 +31,10 @@ class gate(ccxt.async_support.gate):
|
|
30
31
|
'watchOHLCV': True,
|
31
32
|
'watchBalance': True,
|
32
33
|
'watchOrders': True,
|
34
|
+
'watchLiquidations': False,
|
35
|
+
'watchLiquidationsForSymbols': False,
|
36
|
+
'watchMyLiquidations': True,
|
37
|
+
'watchMyLiquidationsForSymbols': True,
|
33
38
|
'watchPositions': True,
|
34
39
|
},
|
35
40
|
'urls': {
|
@@ -963,6 +968,172 @@ class gate(ccxt.async_support.gate):
|
|
963
968
|
client.resolve(self.orders, messageHash)
|
964
969
|
client.resolve(self.orders, 'orders')
|
965
970
|
|
971
|
+
async def watch_my_liquidations(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
972
|
+
"""
|
973
|
+
watch the public liquidations of a trading pair
|
974
|
+
:see: https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
|
975
|
+
:see: https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
|
976
|
+
:see: https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
|
977
|
+
:param str symbol: unified CCXT market symbol
|
978
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
979
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
980
|
+
:param dict [params]: exchange specific parameters for the bitmex api endpoint
|
981
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
982
|
+
"""
|
983
|
+
return self.watch_my_liquidations_for_symbols([symbol], since, limit, params)
|
984
|
+
|
985
|
+
async def watch_my_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
986
|
+
"""
|
987
|
+
watch the private liquidations of a trading pair
|
988
|
+
:see: https://www.gate.io/docs/developers/futures/ws/en/#liquidates-api
|
989
|
+
:see: https://www.gate.io/docs/developers/delivery/ws/en/#liquidates-api
|
990
|
+
:see: https://www.gate.io/docs/developers/options/ws/en/#liquidates-channel
|
991
|
+
:param str symbol: unified CCXT market symbol
|
992
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
993
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
994
|
+
:param dict [params]: exchange specific parameters for the gate api endpoint
|
995
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
996
|
+
"""
|
997
|
+
await self.load_markets()
|
998
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
999
|
+
market = self.get_market_from_symbols(symbols)
|
1000
|
+
type = None
|
1001
|
+
query = None
|
1002
|
+
type, query = self.handle_market_type_and_params('watchMyLiquidationsForSymbols', market, params)
|
1003
|
+
typeId = self.get_supported_mapping(type, {
|
1004
|
+
'future': 'futures',
|
1005
|
+
'swap': 'futures',
|
1006
|
+
'option': 'options',
|
1007
|
+
})
|
1008
|
+
subType = None
|
1009
|
+
subType, query = self.handle_sub_type_and_params('watchMyLiquidationsForSymbols', market, query)
|
1010
|
+
isInverse = (subType == 'inverse')
|
1011
|
+
url = self.get_url_by_market_type(type, isInverse)
|
1012
|
+
payload = []
|
1013
|
+
messageHash = ''
|
1014
|
+
if self.is_empty(symbols):
|
1015
|
+
if typeId != 'futures' and not isInverse:
|
1016
|
+
raise BadRequest(self.id + ' watchMyLiquidationsForSymbols() does not support listening to all symbols, you must call watchMyLiquidations() instead for each symbol you wish to watch.')
|
1017
|
+
messageHash = 'myLiquidations'
|
1018
|
+
payload.append('not all')
|
1019
|
+
else:
|
1020
|
+
symbolsLength = len(symbols)
|
1021
|
+
if symbolsLength != 1:
|
1022
|
+
raise BadRequest(self.id + ' watchMyLiquidationsForSymbols() only allows one symbol at a time. To listen to several symbols call watchMyLiquidationsForSymbols() several times.')
|
1023
|
+
messageHash = 'myLiquidations::' + symbols[0]
|
1024
|
+
payload.append(market['id'])
|
1025
|
+
channel = typeId + '.liquidates'
|
1026
|
+
newLiquidations = await self.subscribe_private(url, messageHash, payload, channel, query, True)
|
1027
|
+
if self.newUpdates:
|
1028
|
+
return newLiquidations
|
1029
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
1030
|
+
|
1031
|
+
def handle_liquidation(self, client: Client, message):
|
1032
|
+
#
|
1033
|
+
# future / delivery
|
1034
|
+
# {
|
1035
|
+
# "channel":"futures.liquidates",
|
1036
|
+
# "event":"update",
|
1037
|
+
# "time":1541505434,
|
1038
|
+
# "time_ms":1541505434123,
|
1039
|
+
# "result":[
|
1040
|
+
# {
|
1041
|
+
# "entry_price":209,
|
1042
|
+
# "fill_price":215.1,
|
1043
|
+
# "left":0,
|
1044
|
+
# "leverage":0.0,
|
1045
|
+
# "liq_price":213,
|
1046
|
+
# "margin":0.007816722941,
|
1047
|
+
# "mark_price":213,
|
1048
|
+
# "order_id":4093362,
|
1049
|
+
# "order_price":215.1,
|
1050
|
+
# "size":-124,
|
1051
|
+
# "time":1541486601,
|
1052
|
+
# "time_ms":1541486601123,
|
1053
|
+
# "contract":"BTC_USD",
|
1054
|
+
# "user":"1040xxxx"
|
1055
|
+
# }
|
1056
|
+
# ]
|
1057
|
+
# }
|
1058
|
+
# option
|
1059
|
+
# {
|
1060
|
+
# "channel":"options.liquidates",
|
1061
|
+
# "event":"update",
|
1062
|
+
# "time":1630654851,
|
1063
|
+
# "result":[
|
1064
|
+
# {
|
1065
|
+
# "user":"1xxxx",
|
1066
|
+
# "init_margin":1190,
|
1067
|
+
# "maint_margin":1042.5,
|
1068
|
+
# "order_margin":0,
|
1069
|
+
# "time":1639051907,
|
1070
|
+
# "time_ms":1639051907000
|
1071
|
+
# }
|
1072
|
+
# ]
|
1073
|
+
# }
|
1074
|
+
#
|
1075
|
+
rawLiquidations = self.safe_list(message, 'result', [])
|
1076
|
+
newLiquidations = []
|
1077
|
+
for i in range(0, len(rawLiquidations)):
|
1078
|
+
rawLiquidation = rawLiquidations[i]
|
1079
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation)
|
1080
|
+
symbol = self.safe_string(liquidation, 'symbol')
|
1081
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
1082
|
+
if liquidations is None:
|
1083
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
1084
|
+
liquidations = ArrayCache(limit)
|
1085
|
+
liquidations.append(liquidation)
|
1086
|
+
self.liquidations[symbol] = liquidations
|
1087
|
+
client.resolve(liquidations, 'myLiquidations::' + symbol)
|
1088
|
+
client.resolve(newLiquidations, 'myLiquidations')
|
1089
|
+
|
1090
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
1091
|
+
#
|
1092
|
+
# future / delivery
|
1093
|
+
# {
|
1094
|
+
# "entry_price": 209,
|
1095
|
+
# "fill_price": 215.1,
|
1096
|
+
# "left": 0,
|
1097
|
+
# "leverage": 0.0,
|
1098
|
+
# "liq_price": 213,
|
1099
|
+
# "margin": 0.007816722941,
|
1100
|
+
# "mark_price": 213,
|
1101
|
+
# "order_id": 4093362,
|
1102
|
+
# "order_price": 215.1,
|
1103
|
+
# "size": -124,
|
1104
|
+
# "time": 1541486601,
|
1105
|
+
# "time_ms": 1541486601123,
|
1106
|
+
# "contract": "BTC_USD",
|
1107
|
+
# "user": "1040xxxx"
|
1108
|
+
# }
|
1109
|
+
# option
|
1110
|
+
# {
|
1111
|
+
# "user": "1xxxx",
|
1112
|
+
# "init_margin": 1190,
|
1113
|
+
# "maint_margin": 1042.5,
|
1114
|
+
# "order_margin": 0,
|
1115
|
+
# "time": 1639051907,
|
1116
|
+
# "time_ms": 1639051907000
|
1117
|
+
# }
|
1118
|
+
#
|
1119
|
+
marketId = self.safe_string(liquidation, 'contract')
|
1120
|
+
market = self.safe_market(marketId, market)
|
1121
|
+
timestamp = self.safe_integer(liquidation, 'time_ms')
|
1122
|
+
originalSize = self.safe_string(liquidation, 'size')
|
1123
|
+
left = self.safe_string(liquidation, 'left')
|
1124
|
+
amount = Precise.string_abs(Precise.string_sub(originalSize, left))
|
1125
|
+
return self.safe_liquidation({
|
1126
|
+
'info': liquidation,
|
1127
|
+
'symbol': self.safe_symbol(marketId, market),
|
1128
|
+
'contracts': self.parse_number(amount),
|
1129
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
1130
|
+
'price': self.safe_number(liquidation, 'fill_price'),
|
1131
|
+
'baseValue': None,
|
1132
|
+
'quoteValue': None,
|
1133
|
+
'timestamp': timestamp,
|
1134
|
+
'datetime': self.iso8601(timestamp),
|
1135
|
+
})
|
1136
|
+
|
966
1137
|
def handle_error_message(self, client: Client, message):
|
967
1138
|
# {
|
968
1139
|
# "time": 1647274664,
|
@@ -1126,6 +1297,7 @@ class gate(ccxt.async_support.gate):
|
|
1126
1297
|
'trades': self.handle_trades,
|
1127
1298
|
'order_book_update': self.handle_order_book,
|
1128
1299
|
'balances': self.handle_balance,
|
1300
|
+
'liquidates': self.handle_liquidation,
|
1129
1301
|
}
|
1130
1302
|
method = self.safe_value(v4Methods, channelType)
|
1131
1303
|
if method is not None:
|
ccxt/pro/kraken.py
CHANGED
@@ -1230,7 +1230,7 @@ class kraken(ccxt.async_support.kraken):
|
|
1230
1230
|
messageHashes = []
|
1231
1231
|
for i in range(0, len(symbols)):
|
1232
1232
|
messageHashes.append(self.get_message_hash(unifiedName, None, self.symbol(symbols[i])))
|
1233
|
-
# for WS subscriptions, we can't use .
|
1233
|
+
# for WS subscriptions, we can't use .marketIds(symbols), instead a custom is field needed
|
1234
1234
|
markets = self.markets_for_symbols(symbols)
|
1235
1235
|
wsMarketIds = []
|
1236
1236
|
for i in range(0, len(markets)):
|
ccxt/pro/kucoinfutures.py
CHANGED
@@ -18,6 +18,10 @@ class kucoinfutures(ccxt.async_support.kucoinfutures):
|
|
18
18
|
return self.deep_extend(super(kucoinfutures, self).describe(), {
|
19
19
|
'has': {
|
20
20
|
'ws': True,
|
21
|
+
'watchLiquidations': False,
|
22
|
+
'watchLiquidatinsForSymbols': False,
|
23
|
+
'watchMyLiquidations': None,
|
24
|
+
'watchMyLiquidationsForSymbols': None,
|
21
25
|
'watchTicker': True,
|
22
26
|
'watchTickers': True,
|
23
27
|
'watchBidsAsks': True,
|
ccxt/pro/okx.py
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
import ccxt.async_support
|
7
7
|
from ccxt.async_support.base.ws.cache import ArrayCache, ArrayCacheBySymbolById, ArrayCacheBySymbolBySide, ArrayCacheByTimestamp
|
8
8
|
import hashlib
|
9
|
-
from ccxt.base.types import Balances, Int, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade
|
9
|
+
from ccxt.base.types import Balances, Int, Liquidation, Num, Order, OrderBook, OrderSide, OrderType, Position, Str, Strings, Ticker, Tickers, FundingRate, FundingRates, Trade
|
10
10
|
from ccxt.async_support.base.ws.client import Client
|
11
11
|
from typing import List
|
12
12
|
from ccxt.base.errors import ExchangeError
|
@@ -29,6 +29,10 @@ class okx(ccxt.async_support.okx):
|
|
29
29
|
'watchTradesForSymbols': True,
|
30
30
|
'watchOrderBookForSymbols': True,
|
31
31
|
'watchBalance': True,
|
32
|
+
'watchLiquidations': 'emulated',
|
33
|
+
'watchLiquidationsForSymbols': True,
|
34
|
+
'watchMyLiquidations': 'emulated',
|
35
|
+
'watchMyLiquidationsForSymbols': True,
|
32
36
|
'watchOHLCV': True,
|
33
37
|
'watchOHLCVForSymbols': True,
|
34
38
|
'watchOrders': True,
|
@@ -399,6 +403,240 @@ class okx(ccxt.async_support.okx):
|
|
399
403
|
client.resolve(tickers, messageHash)
|
400
404
|
return message
|
401
405
|
|
406
|
+
async def watch_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
407
|
+
"""
|
408
|
+
watch the public liquidations of a trading pair
|
409
|
+
:see: https://www.okx.com/docs-v5/en/#public-data-websocket-liquidation-orders-channel
|
410
|
+
:param str symbol: unified CCXT market symbol
|
411
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
412
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
413
|
+
:param dict [params]: exchange specific parameters for the okx api endpoint
|
414
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
415
|
+
"""
|
416
|
+
await self.load_markets()
|
417
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
418
|
+
messageHash = 'liquidations'
|
419
|
+
if symbols is not None:
|
420
|
+
messageHash += '::' + ','.join(symbols)
|
421
|
+
market = self.get_market_from_symbols(symbols)
|
422
|
+
type = None
|
423
|
+
type, params = self.handle_market_type_and_params('watchliquidationsForSymbols', market, params)
|
424
|
+
channel = 'liquidation-orders'
|
425
|
+
if type == 'spot':
|
426
|
+
type = 'SWAP'
|
427
|
+
elif type == 'future':
|
428
|
+
type = 'futures'
|
429
|
+
uppercaseType = type.upper()
|
430
|
+
request = {
|
431
|
+
'instType': uppercaseType,
|
432
|
+
}
|
433
|
+
newLiquidations = await self.subscribe('public', messageHash, channel, None, self.extend(request, params))
|
434
|
+
if self.newUpdates:
|
435
|
+
return newLiquidations
|
436
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
437
|
+
|
438
|
+
def handle_liquidation(self, client: Client, message):
|
439
|
+
#
|
440
|
+
# {
|
441
|
+
# "arg": {
|
442
|
+
# "channel": "liquidation-orders",
|
443
|
+
# "instType": "SWAP"
|
444
|
+
# },
|
445
|
+
# "data": [
|
446
|
+
# {
|
447
|
+
# "details": [
|
448
|
+
# {
|
449
|
+
# "bkLoss": "0",
|
450
|
+
# "bkPx": "0.007831",
|
451
|
+
# "ccy": "",
|
452
|
+
# "posSide": "short",
|
453
|
+
# "side": "buy",
|
454
|
+
# "sz": "13",
|
455
|
+
# "ts": "1692266434010"
|
456
|
+
# }
|
457
|
+
# ],
|
458
|
+
# "instFamily": "IOST-USDT",
|
459
|
+
# "instId": "IOST-USDT-SWAP",
|
460
|
+
# "instType": "SWAP",
|
461
|
+
# "uly": "IOST-USDT"
|
462
|
+
# }
|
463
|
+
# ]
|
464
|
+
# }
|
465
|
+
#
|
466
|
+
rawLiquidations = self.safe_list(message, 'data', [])
|
467
|
+
for i in range(0, len(rawLiquidations)):
|
468
|
+
rawLiquidation = rawLiquidations[i]
|
469
|
+
liquidation = self.parse_ws_liquidation(rawLiquidation)
|
470
|
+
symbol = self.safe_string(liquidation, 'symbol')
|
471
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
472
|
+
if liquidations is None:
|
473
|
+
limit = self.safe_integer(self.options, 'liquidationsLimit', 1000)
|
474
|
+
liquidations = ArrayCache(limit)
|
475
|
+
liquidations.append(liquidation)
|
476
|
+
self.liquidations[symbol] = liquidations
|
477
|
+
client.resolve([liquidation], 'liquidations')
|
478
|
+
client.resolve([liquidation], 'liquidations::' + symbol)
|
479
|
+
|
480
|
+
async def watch_my_liquidations_for_symbols(self, symbols: List[str] = None, since: Int = None, limit: Int = None, params={}) -> List[Liquidation]:
|
481
|
+
"""
|
482
|
+
watch the private liquidations of a trading pair
|
483
|
+
:see: https://www.okx.com/docs-v5/en/#trading-account-websocket-balance-and-position-channel
|
484
|
+
:param str symbol: unified CCXT market symbol
|
485
|
+
:param int [since]: the earliest time in ms to fetch liquidations for
|
486
|
+
:param int [limit]: the maximum number of liquidation structures to retrieve
|
487
|
+
:param dict [params]: exchange specific parameters for the okx api endpoint
|
488
|
+
:returns dict: an array of `liquidation structures <https://github.com/ccxt/ccxt/wiki/Manual#liquidation-structure>`
|
489
|
+
"""
|
490
|
+
await self.load_markets()
|
491
|
+
isStop = self.safe_value_2(params, 'stop', 'trigger', False)
|
492
|
+
params = self.omit(params, ['stop', 'trigger'])
|
493
|
+
await self.authenticate({'access': 'business' if isStop else 'private'})
|
494
|
+
symbols = self.market_symbols(symbols, None, True, True)
|
495
|
+
messageHash = 'myLiquidations'
|
496
|
+
if symbols is not None:
|
497
|
+
messageHash += '::' + ','.join(symbols)
|
498
|
+
channel = 'balance_and_position'
|
499
|
+
newLiquidations = await self.subscribe('private', messageHash, channel, None, params)
|
500
|
+
if self.newUpdates:
|
501
|
+
return newLiquidations
|
502
|
+
return self.filter_by_symbols_since_limit(self.liquidations, symbols, since, limit, True)
|
503
|
+
|
504
|
+
def handle_my_liquidation(self, client: Client, message):
|
505
|
+
#
|
506
|
+
# {
|
507
|
+
# "arg": {
|
508
|
+
# "channel": "balance_and_position",
|
509
|
+
# "uid": "77982378738415879"
|
510
|
+
# },
|
511
|
+
# "data": [{
|
512
|
+
# "pTime": "1597026383085",
|
513
|
+
# "eventType": "snapshot",
|
514
|
+
# "balData": [{
|
515
|
+
# "ccy": "BTC",
|
516
|
+
# "cashBal": "1",
|
517
|
+
# "uTime": "1597026383085"
|
518
|
+
# }],
|
519
|
+
# "posData": [{
|
520
|
+
# "posId": "1111111111",
|
521
|
+
# "tradeId": "2",
|
522
|
+
# "instId": "BTC-USD-191018",
|
523
|
+
# "instType": "FUTURES",
|
524
|
+
# "mgnMode": "cross",
|
525
|
+
# "posSide": "long",
|
526
|
+
# "pos": "10",
|
527
|
+
# "ccy": "BTC",
|
528
|
+
# "posCcy": "",
|
529
|
+
# "avgPx": "3320",
|
530
|
+
# "uTIme": "1597026383085"
|
531
|
+
# }],
|
532
|
+
# "trades": [{
|
533
|
+
# "instId": "BTC-USD-191018",
|
534
|
+
# "tradeId": "2",
|
535
|
+
# }]
|
536
|
+
# }]
|
537
|
+
# }
|
538
|
+
#
|
539
|
+
rawLiquidations = self.safe_list(message, 'data', [])
|
540
|
+
for i in range(0, len(rawLiquidations)):
|
541
|
+
rawLiquidation = rawLiquidations[i]
|
542
|
+
eventType = self.safe_string(rawLiquidation, 'eventType')
|
543
|
+
if eventType != 'liquidation':
|
544
|
+
return
|
545
|
+
liquidation = self.parse_ws_my_liquidation(rawLiquidation)
|
546
|
+
symbol = self.safe_string(liquidation, 'symbol')
|
547
|
+
liquidations = self.safe_value(self.liquidations, symbol)
|
548
|
+
if liquidations is None:
|
549
|
+
limit = self.safe_integer(self.options, 'myLiquidationsLimit', 1000)
|
550
|
+
liquidations = ArrayCache(limit)
|
551
|
+
liquidations.append(liquidation)
|
552
|
+
self.liquidations[symbol] = liquidations
|
553
|
+
client.resolve([liquidation], 'myLiquidations')
|
554
|
+
client.resolve([liquidation], 'myLiquidations::' + symbol)
|
555
|
+
|
556
|
+
def parse_ws_my_liquidation(self, liquidation, market=None):
|
557
|
+
#
|
558
|
+
# {
|
559
|
+
# "pTime": "1597026383085",
|
560
|
+
# "eventType": "snapshot",
|
561
|
+
# "balData": [{
|
562
|
+
# "ccy": "BTC",
|
563
|
+
# "cashBal": "1",
|
564
|
+
# "uTime": "1597026383085"
|
565
|
+
# }],
|
566
|
+
# "posData": [{
|
567
|
+
# "posId": "1111111111",
|
568
|
+
# "tradeId": "2",
|
569
|
+
# "instId": "BTC-USD-191018",
|
570
|
+
# "instType": "FUTURES",
|
571
|
+
# "mgnMode": "cross",
|
572
|
+
# "posSide": "long",
|
573
|
+
# "pos": "10",
|
574
|
+
# "ccy": "BTC",
|
575
|
+
# "posCcy": "",
|
576
|
+
# "avgPx": "3320",
|
577
|
+
# "uTIme": "1597026383085"
|
578
|
+
# }],
|
579
|
+
# "trades": [{
|
580
|
+
# "instId": "BTC-USD-191018",
|
581
|
+
# "tradeId": "2",
|
582
|
+
# }]
|
583
|
+
# }
|
584
|
+
#
|
585
|
+
posData = self.safe_list(liquidation, 'posData', [])
|
586
|
+
firstPosData = self.safe_dict(posData, 0, {})
|
587
|
+
marketId = self.safe_string(firstPosData, 'instId')
|
588
|
+
market = self.safe_market(marketId, market)
|
589
|
+
timestamp = self.safe_integer(firstPosData, 'uTIme')
|
590
|
+
return self.safe_liquidation({
|
591
|
+
'info': liquidation,
|
592
|
+
'symbol': self.safe_symbol(marketId, market),
|
593
|
+
'contracts': self.safe_number(firstPosData, 'pos'),
|
594
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
595
|
+
'price': self.safe_number(liquidation, 'avgPx'),
|
596
|
+
'baseValue': None,
|
597
|
+
'quoteValue': None,
|
598
|
+
'timestamp': timestamp,
|
599
|
+
'datetime': self.iso8601(timestamp),
|
600
|
+
})
|
601
|
+
|
602
|
+
def parse_ws_liquidation(self, liquidation, market=None):
|
603
|
+
#
|
604
|
+
# public liquidation
|
605
|
+
# {
|
606
|
+
# "details": [
|
607
|
+
# {
|
608
|
+
# "bkLoss": "0",
|
609
|
+
# "bkPx": "0.007831",
|
610
|
+
# "ccy": "",
|
611
|
+
# "posSide": "short",
|
612
|
+
# "side": "buy",
|
613
|
+
# "sz": "13",
|
614
|
+
# "ts": "1692266434010"
|
615
|
+
# }
|
616
|
+
# ],
|
617
|
+
# "instFamily": "IOST-USDT",
|
618
|
+
# "instId": "IOST-USDT-SWAP",
|
619
|
+
# "instType": "SWAP",
|
620
|
+
# "uly": "IOST-USDT"
|
621
|
+
# }
|
622
|
+
#
|
623
|
+
details = self.safe_list(liquidation, 'details', [])
|
624
|
+
liquidationDetails = self.safe_dict(details, 0, {})
|
625
|
+
marketId = self.safe_string(liquidation, 'instId')
|
626
|
+
market = self.safe_market(marketId, market)
|
627
|
+
timestamp = self.safe_integer(liquidationDetails, 'ts')
|
628
|
+
return self.safe_liquidation({
|
629
|
+
'info': liquidation,
|
630
|
+
'symbol': self.safe_symbol(marketId, market),
|
631
|
+
'contracts': self.safe_number(liquidationDetails, 'sz'),
|
632
|
+
'contractSize': self.safe_number(market, 'contractSize'),
|
633
|
+
'price': self.safe_number(liquidationDetails, 'bkPx'),
|
634
|
+
'baseValue': None,
|
635
|
+
'quoteValue': None,
|
636
|
+
'timestamp': timestamp,
|
637
|
+
'datetime': self.iso8601(timestamp),
|
638
|
+
})
|
639
|
+
|
402
640
|
async def watch_ohlcv(self, symbol: str, timeframe='1m', since: Int = None, limit: Int = None, params={}) -> List[list]:
|
403
641
|
"""
|
404
642
|
watches historical candlestick data containing the open, high, low, and close price, and the volume of a market
|
@@ -819,6 +1057,9 @@ class okx(ccxt.async_support.okx):
|
|
819
1057
|
await self.authenticate()
|
820
1058
|
return await self.subscribe('private', 'account', 'account', None, params)
|
821
1059
|
|
1060
|
+
def handle_balance_and_position(self, client: Client, message):
|
1061
|
+
self.handle_my_liquidation(client, message)
|
1062
|
+
|
822
1063
|
def handle_balance(self, client: Client, message):
|
823
1064
|
#
|
824
1065
|
# {
|
@@ -1600,6 +1841,8 @@ class okx(ccxt.async_support.okx):
|
|
1600
1841
|
# 'margin_account': self.handle_balance,
|
1601
1842
|
'orders': self.handle_orders,
|
1602
1843
|
'orders-algo': self.handle_orders,
|
1844
|
+
'liquidation-orders': self.handle_liquidation,
|
1845
|
+
'balance_and_position': self.handle_balance_and_position,
|
1603
1846
|
}
|
1604
1847
|
method = self.safe_value(methods, channel)
|
1605
1848
|
if method is None:
|
ccxt/probit.py
CHANGED
@@ -276,7 +276,7 @@ class probit(Exchange, ImplicitAPI):
|
|
276
276
|
markets = self.safe_value(response, 'data', [])
|
277
277
|
return self.parse_markets(markets)
|
278
278
|
|
279
|
-
def parse_market(self, market) -> Market:
|
279
|
+
def parse_market(self, market: dict) -> Market:
|
280
280
|
id = self.safe_string(market, 'id')
|
281
281
|
baseId = self.safe_string(market, 'base_currency_id')
|
282
282
|
quoteId = self.safe_string(market, 'quote_currency_id')
|
@@ -1511,7 +1511,7 @@ class probit(Exchange, ImplicitAPI):
|
|
1511
1511
|
'info': transaction,
|
1512
1512
|
}
|
1513
1513
|
|
1514
|
-
def parse_transaction_status(self, status):
|
1514
|
+
def parse_transaction_status(self, status: Str):
|
1515
1515
|
statuses: dict = {
|
1516
1516
|
'requested': 'pending',
|
1517
1517
|
'pending': 'pending',
|
@@ -1720,7 +1720,7 @@ class probit(Exchange, ImplicitAPI):
|
|
1720
1720
|
self.options['expires'] = self.sum(self.milliseconds(), expiresIn * 1000)
|
1721
1721
|
return response
|
1722
1722
|
|
1723
|
-
def handle_errors(self, code, reason, url, method, headers, body, response, requestHeaders, requestBody):
|
1723
|
+
def handle_errors(self, code: int, reason: str, url: str, method: str, headers: dict, body: str, response, requestHeaders, requestBody):
|
1724
1724
|
if response is None:
|
1725
1725
|
return None # fallback to default error handler
|
1726
1726
|
if 'errorCode' in response:
|
ccxt/test/base/__init__.py
CHANGED
@@ -14,6 +14,7 @@ from ccxt.test.base.test_funding_rate_history import test_funding_rate_history #
|
|
14
14
|
from ccxt.test.base.test_last_price import test_last_price # noqa E402
|
15
15
|
from ccxt.test.base.test_ledger_entry import test_ledger_entry # noqa E402
|
16
16
|
from ccxt.test.base.test_leverage_tier import test_leverage_tier # noqa E402
|
17
|
+
from ccxt.test.base.test_liquidation import test_liquidation # noqa E402
|
17
18
|
from ccxt.test.base.test_margin_mode import test_margin_mode # noqa E402
|
18
19
|
from ccxt.test.base.test_margin_modification import test_margin_modification # noqa E402
|
19
20
|
from ccxt.test.base.test_market import test_market # noqa E402
|
ccxt/test/base/test_crypto.py
CHANGED
@@ -42,7 +42,7 @@ assert hash(encode('sexyfish'), 'md5', 'hex') == 'c8a35464aa9d5683585786f44d5889
|
|
42
42
|
assert hash(encode(''), 'sha1', 'hex') == 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
|
43
43
|
assert hash(encode('nutella'), 'sha1', 'hex') == 'b3d60a34b744159793c483b067c56d8affc5111a'
|
44
44
|
assert hmac(encode('hello'), encode('there'), hashlib.sha256, 'hex') == '551e1c1ecbce0fe9b643745a376584a6289f5f43a46861b315fac9edc8d52a26'
|
45
|
-
assert hmac(encode('a message'), encode('a secret'),
|
45
|
+
assert hmac(encode('a message'), encode('a secret'), hashlib.md5, 'hex') == '0bfa503bdbc7358185fcd49b4869e23d'
|
46
46
|
|
47
47
|
# ---------------------------------------------------------------------------------------------------------------------
|
48
48
|
|