def _load_all_accounts(self): """ This function allows to load every account that the user has on Coinbase These accounts will be used to calculate the taxes, 'in fine'. Only the accounts with an real UUID are taken into account """ # Get the list of accounts (not paginated for coinbase pro) accounts_list = self.api_client.get_accounts() # Save all used accounts for account in accounts_list: # If the ID is a valid UUID, save the account and print it in DEBUG logs match = re.search(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", account['id']) if match: # Get the various values id = account['id'] name = "Account in " + account['currency'] crypto_balance = account['available'] crypto_currency = account['currency'] # Debug print fcrypt_log.debug(f"Adding account: {id} ==> {name}: {crypto_balance} {crypto_currency}") # Add the account in our list self.accounts.append(account)
def _load_all_accounts(self): """ This function allows to load every account that the user has on Coinbase These accounts will be used to calculate the taxes, 'in fine'. Only the accounts with an real UUID are taken into account """ accounts_list = [] other_pages = True last_id = "" while other_pages: # Get account according to pagination if last_id == "": api_answer = self.api_client.get_accounts() else: api_answer = self.api_client.get_accounts(starting_after=last_id) accounts_list = accounts_list + api_answer['data'] if ((api_answer.pagination is not None) and (api_answer.pagination["next_uri"] is not None) and (api_answer.pagination["next_uri"] != "")): # Get the pagination object pagination_obj = api_answer.pagination # Extract 'starting_after' key from next_uri parsed = urlparse.urlparse(pagination_obj["next_uri"]) last_id = parse_qs(parsed.query)['starting_after'][0] else: other_pages = False # Save all used accounts for account in accounts_list: # If the ID is a valid UUID, save the account and print it in DEBUG logs match = re.search(r"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}", account['id']) if match: # Get the various values id = account['id'] name = account['name'] crypto_balance = account['balance']['amount'] crypto_currency = account['currency'] native_balance = account['native_balance']['amount'] native_currency = account['native_balance']['currency'] # Debug print fcrypt_log.debug( f"Adding account: {id} ==> {name}: {crypto_balance} {crypto_currency}" + f" ({native_balance} {native_currency})") # Add the account in our list self.accounts.append(account)
def get_wallet_value_at(self, crypto_currency: str, fiat_currency: str, time: datetime.datetime) -> Decimal: """ This function allows to get the value of a wallet at a given time. :param crypto_currency: Crypto currency of the wallet :type crypto_currency: str :param fiat_currency: Fiat currency for the result (EUR, USD, etc.) :type fiat_currency: str :param time: Time where the value is wanted :type time: datetime.datetime :returns: Decimal -- The wallet value at the given time """ # Firstly, get the wallet balance at the given time balance = self.get_wallet_balance_at(crypto_currency, time) time_str = str(time) normal_balance = str(balance.normalize()) # Print debug fcrypt_log.debug(f"[WALLET] Balance at {time_str}: {normal_balance} {crypto_currency}") if balance != 0: # Now get the equivalent value in fiat rate_currency = crypto_currency + "-" + fiat_currency rate_value = self._find_rate_value_from_finders(rate_currency, time) if rate_value == Decimal(0): # Print error fcrypt_log.warning( f"[WALLET] NO RATE FOUND FOR NOT NULL BALANCE !!! Currency: {crypto_currency} \ - Fiat: {fiat_currency}") # Return 0 wallet_value = Decimal(0) else: # Calculate the wallet value wallet_value = rate_value * balance # Print info fcrypt_log.debug( f"[WALLET] Value of {crypto_currency} wallet at {time_str}: {wallet_value} {fiat_currency}") else: wallet_value = Decimal(0) return wallet_value
def _load_all_transactions(self): """ This function allows to load every transaction that the user has done on Coinbase These transactions, in fine, will allow us to go back in time in the account, to know what was on each account, at a given time """ # Get all transactions for account in self.accounts: transactions_list = [] other_pages = True last_id = "" while other_pages: # Get account according to pagination if last_id == "": # Get the transactions for this account tmp_transactions = self.api_client.get_transactions(account['id']) else: # Get the transactions for this account tmp_transactions = self.api_client.get_transactions(account['id'], starting_after=last_id) transactions_list = transactions_list + tmp_transactions['data'] if ((tmp_transactions.pagination is not None) and (tmp_transactions.pagination["next_uri"] is not None) and (tmp_transactions.pagination["next_uri"] != "")): # Get the pagination object pagination_obj = tmp_transactions.pagination # Extract 'starting_after' key from next_uri parsed = urlparse.urlparse(pagination_obj["next_uri"]) last_id = parse_qs(parsed.query)['starting_after'][0] else: other_pages = False # Print the transactions for transaction in transactions_list: # print(transaction) transaction_type = transaction['type'] amount = transaction['amount']['amount'] currency = transaction['amount']['currency'] date = transaction['updated_at'] if not str.startswith(amount, "-"): amount = "+" + amount account = self._extract_account_id(transaction['resource_path']) fcrypt_log.debug(f"[TRANSACTION][{transaction_type}] {date}: {amount} {currency} ==> {account}") self.transactions.extend(transactions_list)
def get_wallet_balance_at(self, currency: str, time: datetime.datetime) -> Decimal: """ This function allows to get the balance of a wallet at a given time. :param currency: Currency we want the value for :type currency: str :param time: Time where the value is wanted :type time: datetime.datetime :returns: Decimal -- The wallet balance at the given time """ # Firstly, get the corresponding account ID account_id = "" for account in self.accounts: if ('currency' in account) and (account['currency'] == currency): account_id = account['id'] current_balance = Decimal(account['balance']) if account_id == "": raise ValueError("No account found for this currency") # Then apply every transaction in reverse if the datetime of this transaction # is posterior to the wanted datetime for transaction in self.transactions: # Extract account ID tmp_account_id = transaction["account_id"] # Check if the account ids correspond if (tmp_account_id == account_id): # Extract the datetime operation_datetime = isoparse(transaction['created_at']) # If datetime posterior or equal to the time given by user, reverse it if operation_datetime >= time: trans_amount = Decimal(transaction['amount']) tmp_balance = current_balance - trans_amount fcrypt_log.debug(f"[REVERSED TRANSACTION] {trans_amount} {currency} ==> {account_id}") fcrypt_log.debug( f"[REVERSED TRANSACTION] Operation {current_balance}-{trans_amount} = {tmp_balance}") current_balance = tmp_balance return current_balance
def _load_all_transactions(self): """ This function allows to load every transaction that the user has done on Coinbase These transactions, in fine, will allow us to go back in time in the account, to know what was on each account, at a given time """ # Get all transactions for account in self.accounts: # Get all account history for the current account history_gen = self.api_client.get_account_history(account['id']) movements_list = list(history_gen) # Print and take into account the transactions for movement in movements_list: movement_type = movement.get("type", "[NOT KNOWN]") amount = movement.get("amount", "[NOT KNOWN]") balance = movement.get("balance", "[NOT KNOWN]") details = movement.get("details", "[NOT KNOWN]") date = movement.get("created_at", "[NOT KNOWN]") if not str.startswith(amount, "-"): amount = "+" + amount # Copy the dictionary and add the account ID in it tmp_movement = movement.copy() tmp_movement["account_id"] = account['id'] fcrypt_log.debug( f"[TRANSACTION] {movement_type} | {date}: {amount} {account['currency']} ==> {account['id']}") fcrypt_log.debug(f" Balance: {balance} {account['currency']}") fcrypt_log.debug(f" Details: {details}") # Add the account movement according to its type if movement_type == "fee": self.fee.append(tmp_movement) else: self.transactions.append(tmp_movement)