Skip to content

Commit 71af244

Browse files
committed
[Exchanges] add error_describer for proxy erros
1 parent e37bf67 commit 71af244

File tree

6 files changed

+95
-90
lines changed

6 files changed

+95
-90
lines changed

Trading/Exchange/binance/binance_exchange.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -116,14 +116,15 @@ def get_adapter_class(self):
116116

117117
async def get_account_id(self, **kwargs: dict) -> str:
118118
try:
119-
if self.exchange_manager.is_future:
120-
raw_binance_balance = await self.connector.client.fapiPrivateV3GetBalance()
121-
# accountAlias = unique account code
122-
# from https://binance-docs.github.io/apidocs/futures/en/#futures-account-balance-v3-user_data
123-
return raw_binance_balance[0]["accountAlias"]
124-
else:
125-
raw_balance = await self.connector.client.fetch_balance()
126-
return raw_balance[ccxt_constants.CCXT_INFO]["uid"]
119+
with self.connector.error_describer():
120+
if self.exchange_manager.is_future:
121+
raw_binance_balance = await self.connector.client.fapiPrivateV3GetBalance()
122+
# accountAlias = unique account code
123+
# from https://binance-docs.github.io/apidocs/futures/en/#futures-account-balance-v3-user_data
124+
return raw_binance_balance[0]["accountAlias"]
125+
else:
126+
raw_balance = await self.connector.client.fetch_balance()
127+
return raw_balance[ccxt_constants.CCXT_INFO]["uid"]
127128
except (KeyError, IndexError):
128129
# should not happen
129130
raise

Trading/Exchange/bingx/bingx_exchange.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ def get_name(cls) -> str:
8686
return 'bingx'
8787

8888
async def get_account_id(self, **kwargs: dict) -> str:
89-
resp = await self.connector.client.accountV1PrivateGetUid()
90-
return resp["data"]["uid"]
89+
with self.connector.error_describer():
90+
resp = await self.connector.client.accountV1PrivateGetUid()
91+
return resp["data"]["uid"]
9192

9293
async def get_my_recent_trades(self, symbol=None, since=None, limit=None, **kwargs):
9394
# On SPOT Bingx, account recent trades is available under fetch_closed_orders

Trading/Exchange/coinbase/coinbase_exchange.py

+32-30
Original file line numberDiff line numberDiff line change
@@ -172,37 +172,39 @@ def get_adapter_class(self):
172172

173173
async def get_account_id(self, **kwargs: dict) -> str:
174174
try:
175-
# warning might become deprecated
176-
# https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-users
177-
portfolio_id = None
178-
accounts = await self.connector.client.fetch_accounts()
179-
# use portfolio id when possible to enable "coinbase subaccounts" which are called "portfolios"
180-
# note: oldest portfolio portfolio id == user id (from previous v2PrivateGetUser) when using master account
181-
portfolio_ids = set(account[ccxt_constants.CCXT_INFO]['retail_portfolio_id'] for account in accounts)
182-
if len(portfolio_ids) != 1:
183-
is_up_to_date_key = self._is_up_to_date_api_key()
184-
if is_up_to_date_key:
185-
self.logger.error(
186-
f"Unexpected: failed to identify Coinbase portfolio id on up to date API keys: "
187-
f"{portfolio_ids=}"
175+
with self.connector.error_describer():
176+
# warning might become deprecated
177+
# https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-users
178+
portfolio_id = None
179+
accounts = await self.connector.client.fetch_accounts()
180+
# use portfolio id when possible to enable "coinbase subaccounts" which are called "portfolios"
181+
# note: oldest portfolio portfolio id == user id (from previous v2PrivateGetUser) when
182+
# using master account
183+
portfolio_ids = set(account[ccxt_constants.CCXT_INFO]['retail_portfolio_id'] for account in accounts)
184+
if len(portfolio_ids) != 1:
185+
is_up_to_date_key = self._is_up_to_date_api_key()
186+
if is_up_to_date_key:
187+
self.logger.error(
188+
f"Unexpected: failed to identify Coinbase portfolio id on up to date API keys: "
189+
f"{portfolio_ids=}"
190+
)
191+
sorted_portfolios = sorted(
192+
[
193+
account[ccxt_constants.CCXT_INFO]
194+
for account in accounts
195+
],
196+
key=lambda account: account["created_at"],
188197
)
189-
sorted_portfolios = sorted(
190-
[
191-
account[ccxt_constants.CCXT_INFO]
192-
for account in accounts
193-
],
194-
key=lambda account: account["created_at"],
195-
)
196-
portfolio_id = sorted_portfolios[0]['retail_portfolio_id']
197-
self.logger.info(
198-
f"{len(portfolio_ids)} portfolio found on Coinbase account. "
199-
f"This can happen with non up-to-date API keys ({is_up_to_date_key=}). "
200-
f"Using the oldest portfolio id to bind to main account: {portfolio_id=}."
201-
)
202-
else:
203-
portfolio_id = next(iter(portfolio_ids))
204-
return portfolio_id
205-
except ccxt.BaseError as err:
198+
portfolio_id = sorted_portfolios[0]['retail_portfolio_id']
199+
self.logger.info(
200+
f"{len(portfolio_ids)} portfolio found on Coinbase account. "
201+
f"This can happen with non up-to-date API keys ({is_up_to_date_key=}). "
202+
f"Using the oldest portfolio id to bind to main account: {portfolio_id=}."
203+
)
204+
else:
205+
portfolio_id = next(iter(portfolio_ids))
206+
return portfolio_id
207+
except (ccxt.BaseError, octobot_trading.errors.OctoBotExchangeError) as err:
206208
self.logger.exception(
207209
err, True,
208210
f"Error when fetching {self.get_name()} account id: {err} ({err.__class__.__name__}). "

Trading/Exchange/hollaex/hollaex_exchange.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,9 @@ def is_configurable(cls):
8686
return True
8787

8888
async def get_account_id(self, **kwargs: dict) -> str:
89-
user_info = await self.connector.client.private_get_user()
90-
return user_info["id"]
89+
with self.connector.error_describer():
90+
user_info = await self.connector.client.private_get_user()
91+
return user_info["id"]
9192

9293
async def get_symbol_prices(self, symbol, time_frame, limit: int = None, **kwargs: dict):
9394
# ohlcv without limit is not supported, replaced by a default max limit

Trading/Exchange/kucoin/kucoin_exchange.py

+46-47
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import octobot_trading.exchanges.connectors.ccxt.ccxt_connector as ccxt_connector
2626
import octobot_trading.exchanges.connectors.ccxt.enums as ccxt_enums
2727
import octobot_trading.exchanges.connectors.ccxt.constants as ccxt_constants
28+
import octobot_trading.exchanges.connectors.ccxt.ccxt_client_util as ccxt_client_util
2829
import octobot_commons.constants as commons_constants
2930
import octobot_trading.constants as constants
3031
import octobot_trading.enums as trading_enums
@@ -175,56 +176,54 @@ async def get_account_id(self, **kwargs: dict) -> str:
175176
# It is currently impossible to fetch subaccounts account id, use a constant value to identify it.
176177
# updated: 21/05/2024
177178
try:
178-
account_id = None
179-
subaccount_id = None
180-
sub_accounts = await self.connector.client.private_get_sub_accounts()
181-
accounts = sub_accounts.get("data", {}).get("items", {})
182-
has_subaccounts = bool(accounts)
183-
if has_subaccounts:
184-
if len(accounts) == 1:
185-
# only 1 account: use its id or name
186-
account = accounts[0]
187-
# try using subUserId if available
188-
# 'ex subUserId: 65d41ea409407d000160cc17 subName: octobot1'
189-
account_id = account.get("subUserId") or account["subName"]
190-
else:
191-
# more than 1 account: consider other accounts
192-
for account in accounts:
193-
if account["subUserId"]:
194-
subaccount_id = account["subName"]
195-
else:
196-
# only subaccounts have a subUserId: if this condition is True, we are on the main account
197-
account_id = account["subName"]
198-
if account_id and self.exchange_manager.is_future:
199-
account_id = octobot.community.to_community_exchange_internal_name(
200-
account_id, commons_constants.CONFIG_EXCHANGE_FUTURE
179+
with self.connector.error_describer():
180+
account_id = None
181+
subaccount_id = None
182+
sub_accounts = await self.connector.client.private_get_sub_accounts()
183+
accounts = sub_accounts.get("data", {}).get("items", {})
184+
has_subaccounts = bool(accounts)
185+
if has_subaccounts:
186+
if len(accounts) == 1:
187+
# only 1 account: use its id or name
188+
account = accounts[0]
189+
# try using subUserId if available
190+
# 'ex subUserId: 65d41ea409407d000160cc17 subName: octobot1'
191+
account_id = account.get("subUserId") or account["subName"]
192+
else:
193+
# more than 1 account: consider other accounts
194+
for account in accounts:
195+
if account["subUserId"]:
196+
subaccount_id = account["subName"]
197+
else:
198+
# only subaccounts have a subUserId: if this condition is True, we are on the main account
199+
account_id = account["subName"]
200+
if account_id and self.exchange_manager.is_future:
201+
account_id = octobot.community.to_community_exchange_internal_name(
202+
account_id, commons_constants.CONFIG_EXCHANGE_FUTURE
203+
)
204+
if subaccount_id:
205+
# there is at least a subaccount: ensure the current account is the main account as there is no way
206+
# to know the id of the current account (only a list of existing accounts)
207+
subaccount_api_key_details = await self.connector.client.private_get_sub_api_key(
208+
{"subName": subaccount_id}
201209
)
202-
if subaccount_id:
203-
# there is at least a subaccount: ensure the current account is the main account as there is no way
204-
# to know the id of the current account (only a list of existing accounts)
205-
subaccount_api_key_details = await self.connector.client.private_get_sub_api_key(
206-
{"subName": subaccount_id}
207-
)
208-
if "data" not in subaccount_api_key_details or "msg" in subaccount_api_key_details:
209-
# subaccounts can't fetch other accounts data, if this is False, we are on a subaccount
210+
if "data" not in subaccount_api_key_details or "msg" in subaccount_api_key_details:
211+
# subaccounts can't fetch other accounts data, if this is False, we are on a subaccount
212+
self.logger.error(
213+
f"kucoin api changed: it is now possible to call private_get_sub_accounts on subaccounts. "
214+
f"kucoin get_account_id has to be updated. "
215+
f"sub_accounts={sub_accounts} subaccount_api_key_details={subaccount_api_key_details}"
216+
)
217+
return constants.DEFAULT_ACCOUNT_ID
218+
if has_subaccounts and account_id is None:
210219
self.logger.error(
211-
f"kucoin api changed: it is now possible to call private_get_sub_accounts on subaccounts. "
212-
f"kucoin get_account_id has to be updated. "
213-
f"sub_accounts={sub_accounts} subaccount_api_key_details={subaccount_api_key_details}"
220+
f"kucoin api changed: can't fetch master account account_id. "
221+
f"kucoin get_account_id has to be updated."
222+
f"sub_accounts={sub_accounts}"
214223
)
215-
return constants.DEFAULT_ACCOUNT_ID
216-
if has_subaccounts and account_id is None:
217-
self.logger.error(
218-
f"kucoin api changed: can't fetch master account account_id. "
219-
f"kucoin get_account_id has to be updated."
220-
f"sub_accounts={sub_accounts}"
221-
)
222-
account_id = constants.DEFAULT_ACCOUNT_ID
223-
# we are on the master account
224-
return account_id or constants.DEFAULT_ACCOUNT_ID
225-
except ccxt.AuthenticationError:
226-
# when api key is wrong
227-
raise
224+
account_id = constants.DEFAULT_ACCOUNT_ID
225+
# we are on the master account
226+
return account_id or constants.DEFAULT_ACCOUNT_ID
228227
except ccxt.ExchangeError as err:
229228
# ExchangeError('kucoin This user is not a master user')
230229
if "not a master user" not in str(err):

Trading/Exchange/okx/okx_exchange.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ def _fix_limit(self, limit: int) -> int:
198198
async def get_account_id(self, **kwargs: dict) -> str:
199199
accounts = await self.connector.client.fetch_accounts()
200200
try:
201-
return accounts[0]["id"]
201+
with self.connector.error_describer():
202+
return accounts[0]["id"]
202203
except IndexError:
203204
# should never happen as at least one account should be available
204205
return None

0 commit comments

Comments
 (0)