ccxt 4.2.100__py2.py3-none-any.whl → 4.3.2__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.

@@ -6,10 +6,11 @@
6
6
  from ccxt.async_support.base.exchange import Exchange
7
7
  from ccxt.abstract.hyperliquid import ImplicitAPI
8
8
  import asyncio
9
- from ccxt.base.types import Balances, Currencies, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Trade, TransferEntry
9
+ from ccxt.base.types import Balances, Currencies, Int, MarginModification, Market, Num, Order, OrderBook, OrderRequest, CancellationRequest, OrderSide, OrderType, Str, Strings, Trade, TransferEntry
10
10
  from typing import List
11
11
  from ccxt.base.errors import ExchangeError
12
12
  from ccxt.base.errors import ArgumentsRequired
13
+ from ccxt.base.errors import BadRequest
13
14
  from ccxt.base.errors import InvalidOrder
14
15
  from ccxt.base.errors import OrderNotFound
15
16
  from ccxt.base.errors import NotSupported
@@ -44,6 +45,7 @@ class hyperliquid(Exchange, ImplicitAPI):
44
45
  'cancelAllOrders': False,
45
46
  'cancelOrder': True,
46
47
  'cancelOrders': True,
48
+ 'cancelOrdersForSymbols': True,
47
49
  'closeAllPositions': False,
48
50
  'closePosition': False,
49
51
  'createMarketBuyOrderWithCost': False,
@@ -1168,6 +1170,72 @@ class hyperliquid(Exchange, ImplicitAPI):
1168
1170
  #
1169
1171
  return response
1170
1172
 
1173
+ async def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
1174
+ """
1175
+ cancel multiple orders for multiple symbols
1176
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s
1177
+ :see: https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/exchange-endpoint#cancel-order-s-by-cloid
1178
+ :param CancellationRequest[] orders: each order should contain the parameters required by cancelOrder namely id and symbol
1179
+ :param dict [params]: extra parameters specific to the exchange API endpoint
1180
+ :param str [params.vaultAddress]: the vault address
1181
+ :returns dict: an list of `order structures <https://docs.ccxt.com/#/?id=order-structure>`
1182
+ """
1183
+ self.check_required_credentials()
1184
+ await self.load_markets()
1185
+ nonce = self.milliseconds()
1186
+ request = {
1187
+ 'nonce': nonce,
1188
+ # 'vaultAddress': vaultAddress,
1189
+ }
1190
+ cancelReq = []
1191
+ cancelAction = {
1192
+ 'type': '',
1193
+ 'cancels': [],
1194
+ }
1195
+ cancelByCloid = False
1196
+ for i in range(0, len(orders)):
1197
+ order = orders[i]
1198
+ clientOrderId = self.safe_string(order, 'clientOrderId')
1199
+ if clientOrderId is not None:
1200
+ cancelByCloid = True
1201
+ id = self.safe_string(order, 'id')
1202
+ symbol = self.safe_string(order, 'symbol')
1203
+ if symbol is None:
1204
+ raise ArgumentsRequired(self.id + ' cancelOrdersForSymbols() requires a symbol argument in each order')
1205
+ if id is not None and cancelByCloid:
1206
+ raise BadRequest(self.id + ' cancelOrdersForSymbols() all orders must have either id or clientOrderId')
1207
+ assetKey = 'asset' if cancelByCloid else 'a'
1208
+ idKey = 'cloid' if cancelByCloid else 'o'
1209
+ market = self.market(symbol)
1210
+ cancelObj = {}
1211
+ cancelObj[assetKey] = self.parse_to_numeric(market['baseId'])
1212
+ cancelObj[idKey] = clientOrderId if cancelByCloid else self.parse_to_numeric(id)
1213
+ cancelReq.append(cancelObj)
1214
+ cancelAction['type'] = 'cancelByCloid' if cancelByCloid else 'cancel'
1215
+ cancelAction['cancels'] = cancelReq
1216
+ vaultAddress = self.format_vault_address(self.safe_string(params, 'vaultAddress'))
1217
+ signature = self.sign_l1_action(cancelAction, nonce, vaultAddress)
1218
+ request['action'] = cancelAction
1219
+ request['signature'] = signature
1220
+ if vaultAddress is not None:
1221
+ params = self.omit(params, 'vaultAddress')
1222
+ request['vaultAddress'] = vaultAddress
1223
+ response = await self.privatePostExchange(self.extend(request, params))
1224
+ #
1225
+ # {
1226
+ # "status":"ok",
1227
+ # "response":{
1228
+ # "type":"cancel",
1229
+ # "data":{
1230
+ # "statuses":[
1231
+ # "success"
1232
+ # ]
1233
+ # }
1234
+ # }
1235
+ # }
1236
+ #
1237
+ return response
1238
+
1171
1239
  async def edit_order(self, id: str, symbol: str, type: str, side: str, amount: Num = None, price: Num = None, params={}):
1172
1240
  """
1173
1241
  edit a trade order
@@ -1333,7 +1333,7 @@ class kraken(Exchange, ImplicitAPI):
1333
1333
  'ordertype': type,
1334
1334
  'volume': self.amount_to_precision(symbol, amount),
1335
1335
  }
1336
- orderRequest = self.order_request('createOrder()', symbol, type, request, price, params)
1336
+ orderRequest = self.order_request('createOrder', symbol, type, request, price, params)
1337
1337
  response = await self.privatePostAddOrder(self.extend(orderRequest[0], orderRequest[1]))
1338
1338
  #
1339
1339
  # {
@@ -1659,7 +1659,10 @@ class kraken(Exchange, ImplicitAPI):
1659
1659
  request['price'] = trailingAmountString
1660
1660
  request['ordertype'] = 'trailing-stop'
1661
1661
  if reduceOnly:
1662
- request['reduce_only'] = 'true' # not using hasattr(self, boolean) case, because the urlencodedNested transforms it into 'True' string
1662
+ if method == 'createOrderWs':
1663
+ request['reduce_only'] = True # ws request can't have stringified bool
1664
+ else:
1665
+ request['reduce_only'] = 'true' # not using hasattr(self, boolean) case, because the urlencodedNested transforms it into 'True' string
1663
1666
  close = self.safe_value(params, 'close')
1664
1667
  if close is not None:
1665
1668
  close = self.extend({}, close)
@@ -1710,7 +1713,7 @@ class kraken(Exchange, ImplicitAPI):
1710
1713
  }
1711
1714
  if amount is not None:
1712
1715
  request['volume'] = self.amount_to_precision(symbol, amount)
1713
- orderRequest = self.order_request('editOrder()', symbol, type, request, price, params)
1716
+ orderRequest = self.order_request('editOrder', symbol, type, request, price, params)
1714
1717
  response = await self.privatePostEditOrder(self.extend(orderRequest[0], orderRequest[1]))
1715
1718
  #
1716
1719
  # {
@@ -607,6 +607,8 @@ class kucoin(Exchange, ImplicitAPI):
607
607
  'BIFI': 'BIFIF',
608
608
  'VAI': 'VAIOT',
609
609
  'WAX': 'WAXP',
610
+ 'ALT': 'APTOSLAUNCHTOKEN',
611
+ 'KALT': 'ALT', # ALTLAYER
610
612
  },
611
613
  'options': {
612
614
  'version': 'v1',
@@ -1777,7 +1779,7 @@ class kucoin(Exchange, ImplicitAPI):
1777
1779
  address = address.replace('bitcoincash:', '')
1778
1780
  code = None
1779
1781
  if currency is not None:
1780
- code = currency['id']
1782
+ code = self.safe_currency_code(currency['id'])
1781
1783
  if code != 'NIM':
1782
1784
  # contains spaces
1783
1785
  self.check_address(address)
@@ -1823,7 +1825,7 @@ class kucoin(Exchange, ImplicitAPI):
1823
1825
  self.options['versions']['private']['GET']['deposit-addresses'] = version
1824
1826
  chains = self.safe_list(response, 'data', [])
1825
1827
  parsed = self.parse_deposit_addresses(chains, [currency['code']], False, {
1826
- 'currency': currency['id'],
1828
+ 'currency': currency['code'],
1827
1829
  })
1828
1830
  return self.index_by(parsed, 'network')
1829
1831
 
@@ -2800,7 +2802,7 @@ class kucoin(Exchange, ImplicitAPI):
2800
2802
  async def fetch_trades(self, symbol: str, since: Int = None, limit: Int = None, params={}) -> List[Trade]:
2801
2803
  """
2802
2804
  get the list of most recent trades for a particular symbol
2803
- :see: https://docs.kucoin.com/#get-trade-histories
2805
+ :see: https://www.kucoin.com/docs/rest/spot-trading/market-data/get-trade-histories
2804
2806
  :param str symbol: unified symbol of the market to fetch trades for
2805
2807
  :param int [since]: timestamp in ms of the earliest trade to fetch
2806
2808
  :param int [limit]: the maximum amount of trades to fetch
@@ -2965,7 +2967,7 @@ class kucoin(Exchange, ImplicitAPI):
2965
2967
  async def fetch_trading_fee(self, symbol: str, params={}) -> TradingFeeInterface:
2966
2968
  """
2967
2969
  fetch the trading fees for a market
2968
- :see: https://docs.kucoin.com/#actual-fee-rate-of-the-trading-pair
2970
+ :see: https://www.kucoin.com/docs/rest/funding/trade-fee/trading-pair-actual-fee-spot-margin-trade_hf
2969
2971
  :param str symbol: unified market symbol
2970
2972
  :param dict [params]: extra parameters specific to the exchange API endpoint
2971
2973
  :returns dict: a `fee structure <https://docs.ccxt.com/#/?id=fee-structure>`
@@ -3003,7 +3005,7 @@ class kucoin(Exchange, ImplicitAPI):
3003
3005
  async def withdraw(self, code: str, amount: float, address, tag=None, params={}):
3004
3006
  """
3005
3007
  make a withdrawal
3006
- :see: https://docs.kucoin.com/#apply-withdraw-2
3008
+ :see: https://www.kucoin.com/docs/rest/funding/withdrawals/apply-withdraw
3007
3009
  :param str code: unified currency code
3008
3010
  :param float amount: the amount to withdraw
3009
3011
  :param str address: the address to withdraw to
@@ -3164,8 +3166,8 @@ class kucoin(Exchange, ImplicitAPI):
3164
3166
  async def fetch_deposits(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3165
3167
  """
3166
3168
  fetch all deposits made to an account
3167
- :see: https://docs.kucoin.com/#get-deposit-list
3168
- :see: https://docs.kucoin.com/#get-v1-historical-deposits-list
3169
+ :see: https://www.kucoin.com/docs/rest/funding/deposit/get-deposit-list
3170
+ :see: https://www.kucoin.com/docs/rest/funding/deposit/get-v1-historical-deposits-list
3169
3171
  :param str code: unified currency code
3170
3172
  :param int [since]: the earliest time in ms to fetch deposits for
3171
3173
  :param int [limit]: the maximum number of deposits structures to retrieve
@@ -3240,8 +3242,8 @@ class kucoin(Exchange, ImplicitAPI):
3240
3242
  async def fetch_withdrawals(self, code: Str = None, since: Int = None, limit: Int = None, params={}) -> List[Transaction]:
3241
3243
  """
3242
3244
  fetch all withdrawals made from an account
3243
- :see: https://docs.kucoin.com/#get-withdrawals-list
3244
- :see: https://docs.kucoin.com/#get-v1-historical-withdrawals-list
3245
+ :see: https://www.kucoin.com/docs/rest/funding/withdrawals/get-withdrawals-list
3246
+ :see: https://www.kucoin.com/docs/rest/funding/withdrawals/get-v1-historical-withdrawals-list
3245
3247
  :param str code: unified currency code
3246
3248
  :param int [since]: the earliest time in ms to fetch withdrawals for
3247
3249
  :param int [limit]: the maximum number of withdrawals structures to retrieve
@@ -3491,7 +3493,7 @@ class kucoin(Exchange, ImplicitAPI):
3491
3493
  async def transfer(self, code: str, amount: float, fromAccount: str, toAccount: str, params={}) -> TransferEntry:
3492
3494
  """
3493
3495
  transfer currency internally between wallets on the same account
3494
- :see: https://docs.kucoin.com/#inner-transfer
3496
+ :see: https://www.kucoin.com/docs/rest/funding/transfer/inner-transfer
3495
3497
  :see: https://docs.kucoin.com/futures/#transfer-funds-to-kucoin-main-account-2
3496
3498
  :see: https://docs.kucoin.com/spot-hf/#internal-funds-transfers-in-high-frequency-trading-accounts
3497
3499
  :param str code: unified currency code
@@ -3758,7 +3760,7 @@ class kucoin(Exchange, ImplicitAPI):
3758
3760
 
3759
3761
  async def fetch_ledger(self, code: Str = None, since: Int = None, limit: Int = None, params={}):
3760
3762
  """
3761
- :see: https://docs.kucoin.com/#get-account-ledgers
3763
+ :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-spot-margin
3762
3764
  :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-trade_hf
3763
3765
  :see: https://www.kucoin.com/docs/rest/account/basic-info/get-account-ledgers-margin_hf
3764
3766
  fetch the history of changes, actions done by the user or operations that altered balance of the user
ccxt/async_support/okx.py CHANGED
@@ -59,6 +59,7 @@ class okx(Exchange, ImplicitAPI):
59
59
  'cancelOrders': True,
60
60
  'closeAllPositions': False,
61
61
  'closePosition': True,
62
+ 'createConvertTrade': True,
62
63
  'createDepositAddress': False,
63
64
  'createMarketBuyOrderWithCost': True,
64
65
  'createMarketSellOrderWithCost': True,
@@ -7151,6 +7152,57 @@ class okx(Exchange, ImplicitAPI):
7151
7152
  toCurrency = self.currency(toCurrencyId)
7152
7153
  return self.parse_conversion(result, fromCurrency, toCurrency)
7153
7154
 
7155
+ async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
7156
+ """
7157
+ convert from one currency to another
7158
+ :see: https://www.okx.com/docs-v5/en/#funding-account-rest-api-convert-trade
7159
+ :param str id: the id of the trade that you want to make
7160
+ :param str fromCode: the currency that you want to sell and convert from
7161
+ :param str toCode: the currency that you want to buy and convert into
7162
+ :param float [amount]: how much you want to trade in units of the from currency
7163
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7164
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
7165
+ """
7166
+ await self.load_markets()
7167
+ request = {
7168
+ 'quoteId': id,
7169
+ 'baseCcy': fromCode,
7170
+ 'quoteCcy': toCode,
7171
+ 'szCcy': fromCode,
7172
+ 'sz': self.number_to_string(amount),
7173
+ 'side': 'sell',
7174
+ }
7175
+ response = await self.privatePostAssetConvertTrade(self.extend(request, params))
7176
+ #
7177
+ # {
7178
+ # "code": "0",
7179
+ # "data": [
7180
+ # {
7181
+ # "baseCcy": "ETH",
7182
+ # "clTReqId": "",
7183
+ # "fillBaseSz": "0.01023052",
7184
+ # "fillPx": "2932.40104429",
7185
+ # "fillQuoteSz": "30",
7186
+ # "instId": "ETH-USDT",
7187
+ # "quoteCcy": "USDT",
7188
+ # "quoteId": "quoterETH-USDT16461885104612381",
7189
+ # "side": "buy",
7190
+ # "state": "fullyFilled",
7191
+ # "tradeId": "trader16461885203381437",
7192
+ # "ts": "1646188520338"
7193
+ # }
7194
+ # ],
7195
+ # "msg": ""
7196
+ # }
7197
+ #
7198
+ data = self.safe_list(response, 'data', [])
7199
+ result = self.safe_dict(data, 0, {})
7200
+ fromCurrencyId = self.safe_string(result, 'baseCcy', fromCode)
7201
+ fromCurrency = self.currency(fromCurrencyId)
7202
+ toCurrencyId = self.safe_string(result, 'quoteCcy', toCode)
7203
+ toCurrency = self.currency(toCurrencyId)
7204
+ return self.parse_conversion(result, fromCurrency, toCurrency)
7205
+
7154
7206
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
7155
7207
  #
7156
7208
  # fetchConvertQuote
@@ -7171,7 +7223,24 @@ class okx(Exchange, ImplicitAPI):
7171
7223
  # "ttlMs": "10000"
7172
7224
  # }
7173
7225
  #
7174
- timestamp = self.safe_integer(conversion, 'quoteTime')
7226
+ # createConvertTrade
7227
+ #
7228
+ # {
7229
+ # "baseCcy": "ETH",
7230
+ # "clTReqId": "",
7231
+ # "fillBaseSz": "0.01023052",
7232
+ # "fillPx": "2932.40104429",
7233
+ # "fillQuoteSz": "30",
7234
+ # "instId": "ETH-USDT",
7235
+ # "quoteCcy": "USDT",
7236
+ # "quoteId": "quoterETH-USDT16461885104612381",
7237
+ # "side": "buy",
7238
+ # "state": "fullyFilled",
7239
+ # "tradeId": "trader16461885203381437",
7240
+ # "ts": "1646188520338"
7241
+ # }
7242
+ #
7243
+ timestamp = self.safe_integer_2(conversion, 'quoteTime', 'ts')
7175
7244
  fromCoin = self.safe_string(conversion, 'baseCcy')
7176
7245
  fromCode = self.safe_currency_code(fromCoin, fromCurrency)
7177
7246
  to = self.safe_string(conversion, 'quoteCcy')
@@ -7180,12 +7249,12 @@ class okx(Exchange, ImplicitAPI):
7180
7249
  'info': conversion,
7181
7250
  'timestamp': timestamp,
7182
7251
  'datetime': self.iso8601(timestamp),
7183
- 'id': self.safe_string(conversion, 'clQReqId'),
7252
+ 'id': self.safe_string_n(conversion, ['clQReqId', 'tradeId', 'quoteId']),
7184
7253
  'fromCurrency': fromCode,
7185
- 'fromAmount': self.safe_number(conversion, 'baseSz'),
7254
+ 'fromAmount': self.safe_number_2(conversion, 'baseSz', 'fillBaseSz'),
7186
7255
  'toCurrency': toCode,
7187
- 'toAmount': self.safe_number(conversion, 'quoteSz'),
7188
- 'price': self.safe_number(conversion, 'cnvtPx'),
7256
+ 'toAmount': self.safe_number_2(conversion, 'quoteSz', 'fillQuoteSz'),
7257
+ 'price': self.safe_number_2(conversion, 'cnvtPx', 'fillPx'),
7189
7258
  'fee': None,
7190
7259
  }
7191
7260
 
ccxt/async_support/woo.py CHANGED
@@ -45,6 +45,7 @@ class woo(Exchange, ImplicitAPI):
45
45
  'cancelWithdraw': False, # exchange have that endpoint disabled atm, but was once implemented in ccxt per old docs: https://kronosresearch.github.io/wootrade-documents/#cancel-withdraw-request
46
46
  'closeAllPositions': False,
47
47
  'closePosition': False,
48
+ 'createConvertTrade': True,
48
49
  'createDepositAddress': False,
49
50
  'createMarketBuyOrderWithCost': True,
50
51
  'createMarketOrder': False,
@@ -2823,6 +2824,35 @@ class woo(Exchange, ImplicitAPI):
2823
2824
  toCurrency = self.currency(toCurrencyId)
2824
2825
  return self.parse_conversion(data, fromCurrency, toCurrency)
2825
2826
 
2827
+ async def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
2828
+ """
2829
+ convert from one currency to another
2830
+ :see: https://docs.woo.org/#send-quote-rft
2831
+ :param str id: the id of the trade that you want to make
2832
+ :param str fromCode: the currency that you want to sell and convert from
2833
+ :param str toCode: the currency that you want to buy and convert into
2834
+ :param float [amount]: how much you want to trade in units of the from currency
2835
+ :param dict [params]: extra parameters specific to the exchange API endpoint
2836
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
2837
+ """
2838
+ await self.load_markets()
2839
+ request = {
2840
+ 'quoteId': id,
2841
+ }
2842
+ response = await self.v3PrivatePostConvertRft(self.extend(request, params))
2843
+ #
2844
+ # {
2845
+ # "success": True,
2846
+ # "data": {
2847
+ # "quoteId": 123123123,
2848
+ # "counterPartyId": "",
2849
+ # "rftAccepted": 1 # 1 -> success; 2 -> processing; 3 -> fail
2850
+ # }
2851
+ # }
2852
+ #
2853
+ data = self.safe_dict(response, 'data', {})
2854
+ return self.parse_conversion(data)
2855
+
2826
2856
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
2827
2857
  #
2828
2858
  # fetchConvertQuote
@@ -2839,6 +2869,14 @@ class woo(Exchange, ImplicitAPI):
2839
2869
  # "message": 1659084466000
2840
2870
  # }
2841
2871
  #
2872
+ # createConvertTrade
2873
+ #
2874
+ # {
2875
+ # "quoteId": 123123123,
2876
+ # "counterPartyId": "",
2877
+ # "rftAccepted": 1 # 1 -> success; 2 -> processing; 3 -> fail
2878
+ # }
2879
+ #
2842
2880
  timestamp = self.safe_integer(conversion, 'expireTimestamp')
2843
2881
  fromCoin = self.safe_string(conversion, 'sellToken')
2844
2882
  fromCode = self.safe_currency_code(fromCoin, fromCurrency)
ccxt/base/exchange.py CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # -----------------------------------------------------------------------------
6
6
 
7
- __version__ = '4.2.100'
7
+ __version__ = '4.3.2'
8
8
 
9
9
  # -----------------------------------------------------------------------------
10
10
 
@@ -31,7 +31,7 @@ from ccxt.base.decimal_to_precision import decimal_to_precision
31
31
  from ccxt.base.decimal_to_precision import DECIMAL_PLACES, TICK_SIZE, NO_PADDING, TRUNCATE, ROUND, ROUND_UP, ROUND_DOWN, SIGNIFICANT_DIGITS
32
32
  from ccxt.base.decimal_to_precision import number_to_string
33
33
  from ccxt.base.precise import Precise
34
- from ccxt.base.types import BalanceAccount, Currency, IndexType, OrderSide, OrderType, Trade, OrderRequest, Market, MarketType, Str, Num, Strings
34
+ from ccxt.base.types import BalanceAccount, Currency, IndexType, OrderSide, OrderType, Trade, OrderRequest, Market, MarketType, Str, Num, Strings, CancellationRequest
35
35
 
36
36
  # -----------------------------------------------------------------------------
37
37
 
@@ -4318,6 +4318,9 @@ class Exchange(object):
4318
4318
  def cancel_all_orders(self, symbol: Str = None, params={}):
4319
4319
  raise NotSupported(self.id + ' cancelAllOrders() is not supported yet')
4320
4320
 
4321
+ def cancel_orders_for_symbols(self, orders: List[CancellationRequest], params={}):
4322
+ raise NotSupported(self.id + ' cancelOrdersForSymbols() is not supported yet')
4323
+
4321
4324
  def cancel_all_orders_ws(self, symbol: Str = None, params={}):
4322
4325
  raise NotSupported(self.id + ' cancelAllOrdersWs() is not supported yet')
4323
4326
 
ccxt/base/types.py CHANGED
@@ -148,6 +148,10 @@ class OrderRequest(TypedDict):
148
148
  price: Union[None, float]
149
149
  params: Dict[str, Any]
150
150
 
151
+ class CancellationRequest(TypedDict):
152
+ id: Str
153
+ symbol: Str
154
+ clientOrderId: Str
151
155
 
152
156
  class Order(TypedDict):
153
157
  info: Dict[str, Any]
ccxt/binance.py CHANGED
@@ -7,7 +7,7 @@ from ccxt.base.exchange import Exchange
7
7
  from ccxt.abstract.binance import ImplicitAPI
8
8
  import hashlib
9
9
  import json
10
- from ccxt.base.types import Balances, Currencies, Currency, Greeks, Int, Leverage, Leverages, MarginMode, MarginModes, MarginModification, Market, MarketInterface, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
10
+ from ccxt.base.types import Balances, Conversion, Currencies, Currency, Greeks, Int, Leverage, Leverages, MarginMode, MarginModes, MarginModification, Market, MarketInterface, Num, Option, Order, OrderBook, OrderRequest, OrderSide, OrderType, Str, Strings, Ticker, Tickers, Trade, TradingFeeInterface, TradingFees, Transaction, TransferEntry
11
11
  from typing import List
12
12
  from ccxt.base.errors import ExchangeError
13
13
  from ccxt.base.errors import AuthenticationError
@@ -62,6 +62,7 @@ class binance(Exchange, ImplicitAPI):
62
62
  'cancelOrders': True, # contract only
63
63
  'closeAllPositions': False,
64
64
  'closePosition': False, # exchange specific closePosition parameter for binance createOrder is not synonymous with how CCXT uses closePositions
65
+ 'createConvertTrade': True,
65
66
  'createDepositAddress': False,
66
67
  'createLimitBuyOrder': True,
67
68
  'createLimitSellOrder': True,
@@ -11635,3 +11636,56 @@ class binance(Exchange, ImplicitAPI):
11635
11636
  'created': None,
11636
11637
  }
11637
11638
  return result
11639
+
11640
+ def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
11641
+ """
11642
+ convert from one currency to another
11643
+ :see: https://binance-docs.github.io/apidocs/spot/en/#busd-convert-trade
11644
+ :param str id: the id of the trade that you want to make
11645
+ :param str fromCode: the currency that you want to sell and convert from
11646
+ :param str toCode: the currency that you want to buy and convert into
11647
+ :param float [amount]: how much you want to trade in units of the from currency
11648
+ :param dict [params]: extra parameters specific to the exchange API endpoint
11649
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
11650
+ """
11651
+ self.load_markets()
11652
+ request = {
11653
+ 'clientTranId': id,
11654
+ 'asset': fromCode,
11655
+ 'targetAsset': toCode,
11656
+ 'amount': amount,
11657
+ }
11658
+ response = self.sapiPostAssetConvertTransfer(self.extend(request, params))
11659
+ #
11660
+ # {
11661
+ # "tranId": 118263407119,
11662
+ # "status": "S"
11663
+ # }
11664
+ #
11665
+ fromCurrency = self.currency(fromCode)
11666
+ toCurrency = self.currency(toCode)
11667
+ return self.parse_conversion(response, fromCurrency, toCurrency)
11668
+
11669
+ def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
11670
+ #
11671
+ # createConvertTrade
11672
+ #
11673
+ # {
11674
+ # "tranId": 118263407119,
11675
+ # "status": "S"
11676
+ # }
11677
+ #
11678
+ fromCode = self.safe_currency_code(None, fromCurrency)
11679
+ toCode = self.safe_currency_code(None, toCurrency)
11680
+ return {
11681
+ 'info': conversion,
11682
+ 'timestamp': None,
11683
+ 'datetime': None,
11684
+ 'id': self.safe_string(conversion, 'tranId'),
11685
+ 'fromCurrency': fromCode,
11686
+ 'fromAmount': None,
11687
+ 'toCurrency': toCode,
11688
+ 'toAmount': None,
11689
+ 'price': None,
11690
+ 'fee': None,
11691
+ }
ccxt/bingx.py CHANGED
@@ -20,6 +20,7 @@ from ccxt.base.errors import InsufficientFunds
20
20
  from ccxt.base.errors import OrderNotFound
21
21
  from ccxt.base.errors import NotSupported
22
22
  from ccxt.base.errors import DDoSProtection
23
+ from ccxt.base.errors import ExchangeNotAvailable
23
24
  from ccxt.base.decimal_to_precision import DECIMAL_PLACES
24
25
  from ccxt.base.precise import Precise
25
26
 
@@ -397,7 +398,7 @@ class bingx(Exchange, ImplicitAPI):
397
398
  '100400': BadRequest,
398
399
  '100421': BadSymbol, # {"code":100421,"msg":"This pair is currently restricted from API trading","debugMsg":""}
399
400
  '100440': ExchangeError,
400
- '100500': ExchangeError,
401
+ '100500': ExchangeNotAvailable, # {"code":100500,"msg":"The current system is busy, please try again later","debugMsg":""}
401
402
  '100503': ExchangeError,
402
403
  '80001': BadRequest,
403
404
  '80012': InsufficientFunds, # bingx {"code":80012,"msg":"{\"Code\":101253,\"Msg\":\"margin is not enough\"}}
@@ -3717,7 +3718,7 @@ class bingx(Exchange, ImplicitAPI):
3717
3718
  market = None
3718
3719
  if symbol is not None:
3719
3720
  market = self.market(symbol)
3720
- request['symbol'] = symbol
3721
+ request['symbol'] = market['id']
3721
3722
  if since is not None:
3722
3723
  request['startTime'] = since
3723
3724
  if limit is not None:
ccxt/bitget.py CHANGED
@@ -58,6 +58,7 @@ class bitget(Exchange, ImplicitAPI):
58
58
  'cancelOrders': True,
59
59
  'closeAllPositions': True,
60
60
  'closePosition': True,
61
+ 'createConvertTrade': True,
61
62
  'createDepositAddress': False,
62
63
  'createMarketBuyOrderWithCost': True,
63
64
  'createMarketOrderWithCost': False,
@@ -7866,8 +7867,8 @@ class bitget(Exchange, ImplicitAPI):
7866
7867
  """
7867
7868
  self.load_markets()
7868
7869
  request = {
7869
- 'fromCoin': fromCode.upper(),
7870
- 'toCoin': toCode.upper(),
7870
+ 'fromCoin': fromCode,
7871
+ 'toCoin': toCode,
7871
7872
  'fromCoinSize': self.number_to_string(amount),
7872
7873
  }
7873
7874
  response = self.privateConvertGetV2ConvertQuotedPrice(self.extend(request, params))
@@ -7894,6 +7895,54 @@ class bitget(Exchange, ImplicitAPI):
7894
7895
  toCurrency = self.currency(toCurrencyId)
7895
7896
  return self.parse_conversion(data, fromCurrency, toCurrency)
7896
7897
 
7898
+ def create_convert_trade(self, id: str, fromCode: str, toCode: str, amount: Num = None, params={}) -> Conversion:
7899
+ """
7900
+ convert from one currency to another
7901
+ :see: https://www.bitget.com/api-doc/common/convert/Trade
7902
+ :param str id: the id of the trade that you want to make
7903
+ :param str fromCode: the currency that you want to sell and convert from
7904
+ :param str toCode: the currency that you want to buy and convert into
7905
+ :param float amount: how much you want to trade in units of the from currency
7906
+ :param dict [params]: extra parameters specific to the exchange API endpoint
7907
+ :param str params['price']: the price of the conversion, obtained from fetchConvertQuote()
7908
+ :param str params['toAmount']: the amount you want to trade in units of the toCurrency, obtained from fetchConvertQuote()
7909
+ :returns dict: a `conversion structure <https://docs.ccxt.com/#/?id=conversion-structure>`
7910
+ """
7911
+ self.load_markets()
7912
+ price = self.safe_string_2(params, 'price', 'cnvtPrice')
7913
+ if price is None:
7914
+ raise ArgumentsRequired(self.id + ' createConvertTrade() requires a price parameter')
7915
+ toAmount = self.safe_string_2(params, 'toAmount', 'toCoinSize')
7916
+ if toAmount is None:
7917
+ raise ArgumentsRequired(self.id + ' createConvertTrade() requires a toAmount parameter')
7918
+ params = self.omit(params, ['price', 'toAmount'])
7919
+ request = {
7920
+ 'traceId': id,
7921
+ 'fromCoin': fromCode,
7922
+ 'toCoin': toCode,
7923
+ 'fromCoinSize': self.number_to_string(amount),
7924
+ 'toCoinSize': toAmount,
7925
+ 'cnvtPrice': price,
7926
+ }
7927
+ response = self.privateConvertPostV2ConvertTrade(self.extend(request, params))
7928
+ #
7929
+ # {
7930
+ # "code": "00000",
7931
+ # "msg": "success",
7932
+ # "requestTime": 1712123746203,
7933
+ # "data": {
7934
+ # "cnvtPrice": "0.99940076",
7935
+ # "toCoin": "USDC",
7936
+ # "toCoinSize": "4.99700379",
7937
+ # "ts": "1712123746217"
7938
+ # }
7939
+ # }
7940
+ #
7941
+ data = self.safe_dict(response, 'data', {})
7942
+ toCurrencyId = self.safe_string(data, 'toCoin', toCode)
7943
+ toCurrency = self.currency(toCurrencyId)
7944
+ return self.parse_conversion(data, None, toCurrency)
7945
+
7897
7946
  def parse_conversion(self, conversion, fromCurrency: Currency = None, toCurrency: Currency = None) -> Conversion:
7898
7947
  #
7899
7948
  # fetchConvertQuote
@@ -7908,6 +7957,15 @@ class bitget(Exchange, ImplicitAPI):
7908
7957
  # "fee": "0"
7909
7958
  # }
7910
7959
  #
7960
+ # createConvertTrade
7961
+ #
7962
+ # {
7963
+ # "cnvtPrice": "0.99940076",
7964
+ # "toCoin": "USDC",
7965
+ # "toCoinSize": "4.99700379",
7966
+ # "ts": "1712123746217"
7967
+ # }
7968
+ #
7911
7969
  timestamp = self.safe_integer(conversion, 'ts')
7912
7970
  fromCoin = self.safe_string(conversion, 'fromCoin')
7913
7971
  fromCode = self.safe_currency_code(fromCoin, fromCurrency)
@@ -7992,6 +8050,8 @@ class bitget(Exchange, ImplicitAPI):
7992
8050
  #
7993
8051
  # spot
7994
8052
  #
8053
+ # {"code":"00000","msg":"success","requestTime":1713294492511,"data":[...]}"
8054
+ #
7995
8055
  # {"status":"fail","err_code":"01001","err_msg":"系统异常,请稍后重试"}
7996
8056
  # {"status":"error","ts":1595594160149,"err_code":"invalid-parameter","err_msg":"invalid size, valid range: [1,2000]"}
7997
8057
  # {"status":"error","ts":1595684716042,"err_code":"invalid-parameter","err_msg":"illegal sign invalid"}
@@ -8013,13 +8073,13 @@ class bitget(Exchange, ImplicitAPI):
8013
8073
  # {"code":"40108","msg":"","requestTime":1595885064600,"data":null}
8014
8074
  # {"order_id":"513468410013679613","client_oid":null,"symbol":"ethusd","result":false,"err_code":"order_no_exist_error","err_msg":"订单不存在!"}
8015
8075
  #
8016
- message = self.safe_string(response, 'err_msg')
8017
- errorCode = self.safe_string_2(response, 'code', 'err_code')
8076
+ message = self.safe_string_2(response, 'err_msg', 'msg')
8018
8077
  feedback = self.id + ' ' + body
8019
- nonEmptyMessage = ((message is not None) and (message != ''))
8078
+ nonEmptyMessage = ((message is not None) and (message != '') and (message != 'success'))
8020
8079
  if nonEmptyMessage:
8021
8080
  self.throw_exactly_matched_exception(self.exceptions['exact'], message, feedback)
8022
8081
  self.throw_broadly_matched_exception(self.exceptions['broad'], message, feedback)
8082
+ errorCode = self.safe_string_2(response, 'code', 'err_code')
8023
8083
  nonZeroErrorCode = (errorCode is not None) and (errorCode != '00000')
8024
8084
  if nonZeroErrorCode:
8025
8085
  self.throw_exactly_matched_exception(self.exceptions['exact'], errorCode, feedback)
ccxt/bybit.py CHANGED
@@ -4997,7 +4997,7 @@ class bybit(Exchange, ImplicitAPI):
4997
4997
  coin = self.safe_string(result, 'coin')
4998
4998
  currency = self.currency(coin)
4999
4999
  parsed = self.parse_deposit_addresses(chains, [currency['code']], False, {
5000
- 'currency': currency['id'],
5000
+ 'currency': currency['code'],
5001
5001
  })
5002
5002
  return self.index_by(parsed, 'network')
5003
5003