ccxt 4.2.89__py2.py3-none-any.whl → 4.2.91__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/bingx.py +2 -0
- ccxt/abstract/bybit.py +2 -0
- ccxt/ascendex.py +1 -0
- ccxt/async_support/__init__.py +1 -1
- ccxt/async_support/ascendex.py +1 -0
- ccxt/async_support/base/exchange.py +13 -1
- ccxt/async_support/binance.py +81 -9
- ccxt/async_support/bingx.py +94 -1
- ccxt/async_support/bitfinex2.py +1 -0
- ccxt/async_support/bitget.py +2 -0
- ccxt/async_support/bitmex.py +1 -0
- ccxt/async_support/bitrue.py +1 -0
- ccxt/async_support/bybit.py +50 -0
- ccxt/async_support/coinbase.py +43 -21
- ccxt/async_support/coinbaseinternational.py +1 -0
- ccxt/async_support/coinex.py +96 -8
- ccxt/async_support/cryptocom.py +1 -0
- ccxt/async_support/delta.py +1 -0
- ccxt/async_support/digifinex.py +1 -0
- ccxt/async_support/exmo.py +1 -0
- ccxt/async_support/gate.py +2 -0
- ccxt/async_support/gemini.py +11 -9
- ccxt/async_support/hitbtc.py +1 -0
- ccxt/async_support/htx.py +1 -0
- ccxt/async_support/hyperliquid.py +1 -0
- ccxt/async_support/kraken.py +11 -8
- ccxt/async_support/kucoin.py +1 -0
- ccxt/async_support/kucoinfutures.py +32 -4
- ccxt/async_support/mexc.py +1 -0
- ccxt/async_support/okx.py +173 -38
- ccxt/async_support/phemex.py +1 -0
- ccxt/async_support/woo.py +1 -0
- ccxt/base/exchange.py +53 -14
- ccxt/base/types.py +1 -0
- ccxt/binance.py +81 -9
- ccxt/bingx.py +94 -1
- ccxt/bitfinex2.py +1 -0
- ccxt/bitget.py +2 -0
- ccxt/bitmex.py +1 -0
- ccxt/bitrue.py +1 -0
- ccxt/bybit.py +50 -0
- ccxt/coinbase.py +43 -21
- ccxt/coinbaseinternational.py +1 -0
- ccxt/coinex.py +96 -8
- ccxt/cryptocom.py +1 -0
- ccxt/delta.py +1 -0
- ccxt/digifinex.py +1 -0
- ccxt/exmo.py +1 -0
- ccxt/gate.py +2 -0
- ccxt/gemini.py +11 -9
- ccxt/hitbtc.py +1 -0
- ccxt/htx.py +1 -0
- ccxt/hyperliquid.py +1 -0
- ccxt/kraken.py +11 -8
- ccxt/kucoin.py +1 -0
- ccxt/kucoinfutures.py +32 -4
- ccxt/mexc.py +1 -0
- ccxt/okx.py +173 -38
- ccxt/phemex.py +1 -0
- ccxt/pro/__init__.py +1 -1
- ccxt/pro/bitmex.py +35 -17
- ccxt/pro/kucoin.py +85 -0
- ccxt/pro/kucoinfutures.py +141 -76
- ccxt/test/test_async.py +15 -1
- ccxt/test/test_sync.py +15 -1
- ccxt/woo.py +1 -0
- {ccxt-4.2.89.dist-info → ccxt-4.2.91.dist-info}/METADATA +4 -4
- {ccxt-4.2.89.dist-info → ccxt-4.2.91.dist-info}/RECORD +71 -71
- {ccxt-4.2.89.dist-info → ccxt-4.2.91.dist-info}/WHEEL +0 -0
- {ccxt-4.2.89.dist-info → ccxt-4.2.91.dist-info}/top_level.txt +0 -0
ccxt/async_support/okx.py
CHANGED
@@ -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,
|
@@ -1235,7 +1236,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1235
1236
|
# ]
|
1236
1237
|
# }
|
1237
1238
|
#
|
1238
|
-
data = self.
|
1239
|
+
data = self.safe_list(response, 'data', [])
|
1239
1240
|
dataLength = len(data)
|
1240
1241
|
update = {
|
1241
1242
|
'updated': None,
|
@@ -1276,8 +1277,8 @@ class okx(Exchange, ImplicitAPI):
|
|
1276
1277
|
# "msg": ""
|
1277
1278
|
# }
|
1278
1279
|
#
|
1279
|
-
data = self.
|
1280
|
-
first = self.
|
1280
|
+
data = self.safe_list(response, 'data', [])
|
1281
|
+
first = self.safe_dict(data, 0, {})
|
1281
1282
|
return self.safe_integer(first, 'ts')
|
1282
1283
|
|
1283
1284
|
async def fetch_accounts(self, params={}) -> List[Account]:
|
@@ -1307,7 +1308,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1307
1308
|
# "msg": ""
|
1308
1309
|
# }
|
1309
1310
|
#
|
1310
|
-
data = self.
|
1311
|
+
data = self.safe_list(response, 'data', [])
|
1311
1312
|
result = []
|
1312
1313
|
for i in range(0, len(data)):
|
1313
1314
|
account = data[i]
|
@@ -1329,7 +1330,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1329
1330
|
:param dict [params]: extra parameters specific to the exchange API endpoint
|
1330
1331
|
:returns dict[]: an array of objects representing market data
|
1331
1332
|
"""
|
1332
|
-
types = self.
|
1333
|
+
types = self.safe_list(self.options, 'fetchMarkets', [])
|
1333
1334
|
promises = []
|
1334
1335
|
result = []
|
1335
1336
|
for i in range(0, len(types)):
|
@@ -1426,7 +1427,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1426
1427
|
symbol = symbol + '-' + ymd + '-' + strikePrice + '-' + optionType
|
1427
1428
|
optionType = 'put' if (optionType == 'P') else 'call'
|
1428
1429
|
tickSize = self.safe_string(market, 'tickSz')
|
1429
|
-
fees = self.
|
1430
|
+
fees = self.safe_dict_2(self.fees, type, 'trading', {})
|
1430
1431
|
maxLeverage = self.safe_string(market, 'lever', '1')
|
1431
1432
|
maxLeverage = Precise.string_max(maxLeverage, '1')
|
1432
1433
|
maxSpotCost = self.safe_number(market, 'maxMktSz')
|
@@ -1485,7 +1486,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1485
1486
|
'instType': self.convert_to_instrument_type(type),
|
1486
1487
|
}
|
1487
1488
|
if type == 'option':
|
1488
|
-
optionsUnderlying = self.
|
1489
|
+
optionsUnderlying = self.safe_list(self.options, 'defaultUnderlying', ['BTC-USD', 'ETH-USD'])
|
1489
1490
|
promises = []
|
1490
1491
|
for i in range(0, len(optionsUnderlying)):
|
1491
1492
|
underlying = optionsUnderlying[i]
|
@@ -1494,8 +1495,8 @@ class okx(Exchange, ImplicitAPI):
|
|
1494
1495
|
promisesResult = await asyncio.gather(*promises)
|
1495
1496
|
markets = []
|
1496
1497
|
for i in range(0, len(promisesResult)):
|
1497
|
-
res = self.
|
1498
|
-
options = self.
|
1498
|
+
res = self.safe_dict(promisesResult, i, {})
|
1499
|
+
options = self.safe_list(res, 'data', [])
|
1499
1500
|
markets = self.array_concat(markets, options)
|
1500
1501
|
return self.parse_markets(markets)
|
1501
1502
|
response = await self.publicGetPublicInstruments(self.extend(request, params))
|
@@ -1532,7 +1533,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1532
1533
|
# "msg": ""
|
1533
1534
|
# }
|
1534
1535
|
#
|
1535
|
-
dataResponse = self.
|
1536
|
+
dataResponse = self.safe_list(response, 'data', [])
|
1536
1537
|
return self.parse_markets(dataResponse)
|
1537
1538
|
|
1538
1539
|
def safe_network(self, networkId):
|
@@ -1606,7 +1607,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1606
1607
|
# "msg": ""
|
1607
1608
|
# }
|
1608
1609
|
#
|
1609
|
-
data = self.
|
1610
|
+
data = self.safe_list(response, 'data', [])
|
1610
1611
|
result = {}
|
1611
1612
|
dataByCurrencyId = self.group_by(data, 'ccy')
|
1612
1613
|
currencyIds = list(dataByCurrencyId.keys())
|
@@ -1622,11 +1623,11 @@ class okx(Exchange, ImplicitAPI):
|
|
1622
1623
|
maxPrecision = None
|
1623
1624
|
for j in range(0, len(chains)):
|
1624
1625
|
chain = chains[j]
|
1625
|
-
canDeposit = self.
|
1626
|
+
canDeposit = self.safe_bool(chain, 'canDep')
|
1626
1627
|
depositEnabled = canDeposit if (canDeposit) else depositEnabled
|
1627
|
-
canWithdraw = self.
|
1628
|
+
canWithdraw = self.safe_bool(chain, 'canWd')
|
1628
1629
|
withdrawEnabled = canWithdraw if (canWithdraw) else withdrawEnabled
|
1629
|
-
canInternal = self.
|
1630
|
+
canInternal = self.safe_bool(chain, 'canInternal')
|
1630
1631
|
active = True if (canDeposit and canWithdraw and canInternal) else False
|
1631
1632
|
currencyActive = active if (active) else currencyActive
|
1632
1633
|
networkId = self.safe_string(chain, 'chain')
|
@@ -1655,7 +1656,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1655
1656
|
},
|
1656
1657
|
'info': chain,
|
1657
1658
|
}
|
1658
|
-
firstChain = self.
|
1659
|
+
firstChain = self.safe_dict(chains, 0, {})
|
1659
1660
|
result[code] = {
|
1660
1661
|
'info': None,
|
1661
1662
|
'code': code,
|
@@ -1724,8 +1725,8 @@ class okx(Exchange, ImplicitAPI):
|
|
1724
1725
|
# ]
|
1725
1726
|
# }
|
1726
1727
|
#
|
1727
|
-
data = self.
|
1728
|
-
first = self.
|
1728
|
+
data = self.safe_list(response, 'data', [])
|
1729
|
+
first = self.safe_dict(data, 0, {})
|
1729
1730
|
timestamp = self.safe_integer(first, 'ts')
|
1730
1731
|
return self.parse_order_book(first, symbol, timestamp)
|
1731
1732
|
|
@@ -1824,7 +1825,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1824
1825
|
# ]
|
1825
1826
|
# }
|
1826
1827
|
#
|
1827
|
-
data = self.
|
1828
|
+
data = self.safe_list(response, 'data', [])
|
1828
1829
|
first = self.safe_dict(data, 0, {})
|
1829
1830
|
return self.parse_ticker(first, market)
|
1830
1831
|
|
@@ -1845,7 +1846,7 @@ class okx(Exchange, ImplicitAPI):
|
|
1845
1846
|
'instType': self.convert_to_instrument_type(marketType),
|
1846
1847
|
}
|
1847
1848
|
if marketType == 'option':
|
1848
|
-
defaultUnderlying = self.
|
1849
|
+
defaultUnderlying = self.safe_string(self.options, 'defaultUnderlying', 'BTC-USD')
|
1849
1850
|
currencyId = self.safe_string_2(params, 'uly', 'marketId', defaultUnderlying)
|
1850
1851
|
if currencyId is None:
|
1851
1852
|
raise ArgumentsRequired(self.id + ' fetchTickers() requires an underlying uly or marketId parameter for options markets')
|
@@ -2094,7 +2095,7 @@ class okx(Exchange, ImplicitAPI):
|
|
2094
2095
|
return await self.fetch_paginated_call_deterministic('fetchOHLCV', symbol, since, limit, timeframe, params, 200)
|
2095
2096
|
price = self.safe_string(params, 'price')
|
2096
2097
|
params = self.omit(params, 'price')
|
2097
|
-
options = self.
|
2098
|
+
options = self.safe_dict(self.options, 'fetchOHLCV', {})
|
2098
2099
|
timezone = self.safe_string(options, 'timezone', 'UTC')
|
2099
2100
|
if limit is None:
|
2100
2101
|
limit = 100 # default 100, max 100
|
@@ -2207,7 +2208,7 @@ class okx(Exchange, ImplicitAPI):
|
|
2207
2208
|
# }
|
2208
2209
|
#
|
2209
2210
|
rates = []
|
2210
|
-
data = self.
|
2211
|
+
data = self.safe_list(response, 'data', [])
|
2211
2212
|
for i in range(0, len(data)):
|
2212
2213
|
rate = data[i]
|
2213
2214
|
timestamp = self.safe_integer(rate, 'fundingTime')
|
@@ -2229,10 +2230,10 @@ class okx(Exchange, ImplicitAPI):
|
|
2229
2230
|
|
2230
2231
|
def parse_trading_balance(self, response):
|
2231
2232
|
result = {'info': response}
|
2232
|
-
data = self.
|
2233
|
-
first = self.
|
2233
|
+
data = self.safe_list(response, 'data', [])
|
2234
|
+
first = self.safe_dict(data, 0, {})
|
2234
2235
|
timestamp = self.safe_integer(first, 'uTime')
|
2235
|
-
details = self.
|
2236
|
+
details = self.safe_list(first, 'details', [])
|
2236
2237
|
for i in range(0, len(details)):
|
2237
2238
|
balance = details[i]
|
2238
2239
|
currencyId = self.safe_string(balance, 'ccy')
|
@@ -2254,7 +2255,7 @@ class okx(Exchange, ImplicitAPI):
|
|
2254
2255
|
|
2255
2256
|
def parse_funding_balance(self, response):
|
2256
2257
|
result = {'info': response}
|
2257
|
-
data = self.
|
2258
|
+
data = self.safe_list(response, 'data', [])
|
2258
2259
|
for i in range(0, len(data)):
|
2259
2260
|
balance = data[i]
|
2260
2261
|
currencyId = self.safe_string(balance, 'ccy')
|
@@ -2332,8 +2333,8 @@ class okx(Exchange, ImplicitAPI):
|
|
2332
2333
|
# "msg": ""
|
2333
2334
|
# }
|
2334
2335
|
#
|
2335
|
-
data = self.
|
2336
|
-
first = self.
|
2336
|
+
data = self.safe_list(response, 'data', [])
|
2337
|
+
first = self.safe_dict(data, 0, {})
|
2337
2338
|
return self.parse_trading_fee(first, market)
|
2338
2339
|
|
2339
2340
|
async def fetch_balance(self, params={}) -> Balances:
|
@@ -2747,8 +2748,8 @@ class okx(Exchange, ImplicitAPI):
|
|
2747
2748
|
response = await self.privatePostTradeOrderAlgo(request)
|
2748
2749
|
else:
|
2749
2750
|
response = await self.privatePostTradeBatchOrders(request)
|
2750
|
-
data = self.
|
2751
|
-
first = self.
|
2751
|
+
data = self.safe_list(response, 'data', [])
|
2752
|
+
first = self.safe_dict(data, 0, {})
|
2752
2753
|
order = self.parse_order(first, market)
|
2753
2754
|
order['type'] = type
|
2754
2755
|
order['side'] = side
|
@@ -4127,7 +4128,7 @@ class okx(Exchange, ImplicitAPI):
|
|
4127
4128
|
# ]
|
4128
4129
|
# }
|
4129
4130
|
#
|
4130
|
-
data = self.
|
4131
|
+
data = self.safe_list(response, 'data', [])
|
4131
4132
|
return self.parse_ledger(data, currency, since, limit)
|
4132
4133
|
|
4133
4134
|
def parse_ledger_entry_type(self, type):
|
@@ -6036,9 +6037,9 @@ class okx(Exchange, ImplicitAPI):
|
|
6036
6037
|
# }
|
6037
6038
|
#
|
6038
6039
|
data = self.safe_list(response, 'data', [])
|
6040
|
+
entry = self.safe_dict(data, 0, {})
|
6039
6041
|
errorCode = self.safe_string(response, 'code')
|
6040
|
-
|
6041
|
-
return self.extend(self.parse_margin_modification(item, market), {
|
6042
|
+
return self.extend(self.parse_margin_modification(entry, market), {
|
6042
6043
|
'status': 'ok' if (errorCode == '0') else 'failed',
|
6043
6044
|
})
|
6044
6045
|
|
@@ -6053,22 +6054,66 @@ class okx(Exchange, ImplicitAPI):
|
|
6053
6054
|
# "type": "reduce"
|
6054
6055
|
# }
|
6055
6056
|
#
|
6056
|
-
|
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')
|
6057
6095
|
typeRaw = self.safe_string(data, 'type')
|
6058
|
-
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)
|
6059
6102
|
marketId = self.safe_string(data, 'instId')
|
6060
6103
|
responseMarket = self.safe_market(marketId, market)
|
6061
6104
|
code = responseMarket['base'] if responseMarket['inverse'] else responseMarket['quote']
|
6105
|
+
timestamp = self.safe_integer(data, 'ts')
|
6062
6106
|
return {
|
6063
6107
|
'info': data,
|
6064
6108
|
'symbol': responseMarket['symbol'],
|
6065
6109
|
'type': type,
|
6066
|
-
'
|
6067
|
-
'
|
6110
|
+
'marginMode': 'isolated',
|
6111
|
+
'amount': self.parse_number(amount),
|
6068
6112
|
'code': code,
|
6113
|
+
'total': None,
|
6069
6114
|
'status': None,
|
6070
|
-
'timestamp':
|
6071
|
-
'datetime':
|
6115
|
+
'timestamp': timestamp,
|
6116
|
+
'datetime': self.iso8601(timestamp),
|
6072
6117
|
}
|
6073
6118
|
|
6074
6119
|
async def reduce_margin(self, symbol: str, amount, params={}) -> MarginModification:
|
@@ -7089,3 +7134,93 @@ class okx(Exchange, ImplicitAPI):
|
|
7089
7134
|
self.throw_exactly_matched_exception(self.exceptions['exact'], code, feedback)
|
7090
7135
|
raise ExchangeError(feedback) # unknown message
|
7091
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/phemex.py
CHANGED
ccxt/async_support/woo.py
CHANGED
ccxt/base/exchange.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
# -----------------------------------------------------------------------------
|
6
6
|
|
7
|
-
__version__ = '4.2.
|
7
|
+
__version__ = '4.2.91'
|
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
|
|
@@ -2270,7 +2303,7 @@ class Exchange(object):
|
|
2270
2303
|
def parse_to_int(self, number):
|
2271
2304
|
# Solve Common intmisuse ex: int((since / str(1000)))
|
2272
2305
|
# using a number which is not valid in ts
|
2273
|
-
stringifiedNumber =
|
2306
|
+
stringifiedNumber = self.number_to_string(number)
|
2274
2307
|
convertedNumber = float(stringifiedNumber)
|
2275
2308
|
return int(convertedNumber)
|
2276
2309
|
|
@@ -4393,12 +4426,6 @@ class Exchange(object):
|
|
4393
4426
|
def common_currency_code(self, code: str):
|
4394
4427
|
if not self.substituteCommonCurrencyCodes:
|
4395
4428
|
return code
|
4396
|
-
# if the provided code already exists value in commonCurrencies dict, then we should not again transform it
|
4397
|
-
# more details at: https://github.com/ccxt/ccxt/issues/21112#issuecomment-2031293691
|
4398
|
-
commonCurrencies = list(self.commonCurrencies.values())
|
4399
|
-
exists = self.in_array(code, commonCurrencies)
|
4400
|
-
if exists:
|
4401
|
-
return code
|
4402
4429
|
return self.safe_string(self.commonCurrencies, code, code)
|
4403
4430
|
|
4404
4431
|
def currency(self, code: str):
|
@@ -4952,7 +4979,6 @@ class Exchange(object):
|
|
4952
4979
|
:returns dict: objects with withdraw and deposit fees, indexed by currency codes
|
4953
4980
|
"""
|
4954
4981
|
depositWithdrawFees = {}
|
4955
|
-
codes = self.marketCodes(codes)
|
4956
4982
|
isArray = isinstance(response, list)
|
4957
4983
|
responseKeys = response
|
4958
4984
|
if not isArray:
|
@@ -5447,3 +5473,16 @@ class Exchange(object):
|
|
5447
5473
|
day = date[5:7]
|
5448
5474
|
reconstructedDate = day + month + year
|
5449
5475
|
return reconstructedDate
|
5476
|
+
|
5477
|
+
def parse_margin_modification(self, data, market: Market = None):
|
5478
|
+
raise NotSupported(self.id + ' parseMarginModification() is not supported yet')
|
5479
|
+
|
5480
|
+
def parse_margin_modifications(self, response: List[object], symbols: List[str] = None, symbolKey: Str = None, marketType: MarketType = None):
|
5481
|
+
marginModifications = []
|
5482
|
+
for i in range(0, len(response)):
|
5483
|
+
info = response[i]
|
5484
|
+
marketId = self.safe_string(info, symbolKey)
|
5485
|
+
market = self.safe_market(marketId, None, None, marketType)
|
5486
|
+
if (symbols is None) or self.in_array(market['symbol'], symbols):
|
5487
|
+
marginModifications.append(self.parse_margin_modification(info, market))
|
5488
|
+
return marginModifications
|
ccxt/base/types.py
CHANGED