Skip to content

Commit

Permalink
[Coinbase] support portfolio id
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeDSM committed Nov 21, 2024
1 parent 4318329 commit 6b33d75
Showing 1 changed file with 38 additions and 2 deletions.
40 changes: 38 additions & 2 deletions Trading/Exchange/coinbase/coinbase_exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,37 @@ async def get_account_id(self, **kwargs: dict) -> str:
try:
# warning might become deprecated
# https://docs.cloud.coinbase.com/sign-in-with-coinbase/docs/api-users
user_data = await self.connector.client.v2PrivateGetUser()
return user_data["data"]["id"]
portfolio_id = None
try:
# use portfolio id when possible to enable "coinbase subaccounts" which are called "portfolios"
# note: portfolio id == user id (from v2PrivateGetUser) when using master account
accounts = await self.connector.client.fetch_accounts()
portfolio_ids = set(account[ccxt_constants.CCXT_INFO]['retail_portfolio_id'] for account in accounts)
if len(portfolio_ids) != 1:
is_up_to_date_key = self._is_up_to_date_api_key()
if is_up_to_date_key:
self.logger.error(
f"Unexpected: failed to identify Coinbase portfolio id on up to date API keys: "
f"{portfolio_ids=}"
)
self.logger.info(
f"{len(portfolio_ids)} portfolio found on Coinbase account. "
f"This can happen with non up-to-date API keys ({is_up_to_date_key=}). "
f"Falling back to v2PrivateGetUser() to get the current account id."
)
else:
portfolio_id = next(iter(portfolio_ids))
except (IndexError, KeyError):
pass
if portfolio_id is None:
# fallback to user id
user_data = await self.connector.client.v2PrivateGetUser()
portfolio_id = user_data["data"]["id"]
self.logger.warning(
f"No Coinbase portfolio id can be selected from fetch_accounts(), used v2PrivateGetUser() "
f"to identify user id and use it as portfolio id: {portfolio_id}"
)
return portfolio_id
except ccxt.BaseError as err:
self.logger.exception(
err, True,
Expand All @@ -149,6 +178,13 @@ async def get_account_id(self, **kwargs: dict) -> str:
)
return trading_constants.DEFAULT_ACCOUNT_ID

def _is_up_to_date_api_key(self) -> bool:
return (
self.connector.client.apiKey.find('organizations/') >= 0 or
self.connector.client.apiKey.startswith('-----BEGIN')
)


@_coinbase_retrier
async def get_symbol_prices(self, symbol: str, time_frame: commons_enums.TimeFrames, limit: int = None,
**kwargs: dict) -> typing.Optional[list]:
Expand Down

0 comments on commit 6b33d75

Please sign in to comment.