def list_accounts(): """ List all shared accounts (id, name, balance) """ # Ensure the whole account is included print("\nLoading Bunq API environment...") env = ApiEnvironmentType.PRODUCTION # Authenticate session & load context print("Authenticating and loading context...") api_context = ApiContext(ApiEnvironmentType.PRODUCTION, API_KEY, socket.gethostname()) api_context.ensure_session_active() BunqContext.load_api_context(api_context) # Get user info print("Loading user info...\n") user = endpoint.User.get().value.get_referenced_object() # Fetch account detials accounts = endpoint.MonetaryAccountJoint.list().value for account in accounts: print( f"[{account.id_}] {account.description} (\N{euro sign}{account.balance.value})" )
def authenticate(self): if self.parameter_manager.exists("/bunq/api_context"): self.api_context = self._get_api_context_from_aws() self._ensure_active_session() else: self.api_context = self._create_api_context() BunqContext.load_api_context(self.api_context)
def test_bad_request_with_response_id(self): """ """ BunqContext.load_api_context(self._get_api_context()) with self.assertRaises(ApiException) as caught_exception: MonetaryAccountBank.get(self._INVALID_MONETARY_ACCOUNT_ID) self.assertIsNotNone(caught_exception.exception.response_id)
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Bunq Bank sensor platform.""" from bunq.sdk.context import ( ApiContext, ApiEnvironmentType, BunqContext) from bunq.sdk.exception import BunqException, ApiException from bunq.sdk.model.generated import endpoint from bunq.sdk.json import converter # set environment type api_environment = ApiEnvironmentType.SANDBOX \ if config.get(CONF_SANDBOX) else ApiEnvironmentType.PRODUCTION accs = [] try: # create the api context variable bunq_context = ApiContext( api_environment, config.get(CONF_API_KEY), 'Home Assistant' ) # ensure the key is active, or activate bunq_context.ensure_session_active() # load user context from api context (not IO) # checks if the user has active accounts # raises BunqException otherwise BunqContext.load_api_context(bunq_context) # call the account list endpoint accounts = converter.serialize( endpoint.MonetaryAccount.list().value) # create and add the devices to the list accs = [ BunqAccountSensor( acc['MonetaryAccountBank']['description'], acc['MonetaryAccountBank']['id'], acc['MonetaryAccountBank']['currency'], float(acc['MonetaryAccountBank']['balance']['value'])) for acc in accounts ] async_add_entities(accs) # create the refresh object data = BunqData(hass, bunq_context, accs) # schedule the first update await data.schedule_update(INTERVAL_TO_NEXT_REFRESH) except ApiException as err: # if there is something wrong with the user setup # such as a incorrect key or invalid IP address # log the error and raise HA error # nothing to setup further until the key is changed _LOGGER.error(err) except BunqException as err: # if the Bunq sdk errors out there is # such as API rate limit throtteling # log the error and raise PlatformNotReady to retry _LOGGER.error(err) raise PlatformNotReady
def _register_user(self): api_context = context.ApiContext( self._get_environment(), Config.get_option('API_KEY'), Config.get_option('DEVICE_DESCRIPTION'), [Config.get_option('PERMITTED_IP')]) api_context.save(Config.get_option('API_CONTEXT_FILE_PATH')) BunqContext.load_api_context(api_context) self._pin_certificate()
def setUpClass(cls): cls._PAYMENT_LISTING_PAGE_SIZE = 2 cls._PAYMENT_REQUIRED_COUNT_MINIMUM = cls._PAYMENT_LISTING_PAGE_SIZE * 2 cls._NUMBER_ZERO = 0 cls._PAYMENT_AMOUNT_EUR = '0.01' cls._PAYMENT_CURRENCY = 'EUR' cls._PAYMENT_DESCRIPTION = 'Python test Payment' BunqContext.load_api_context(cls._get_api_context())
def _setup_context(self): if not self._user_is_registered(): self._register_user() api_context = ApiContext.restore( Config.get_option('API_CONTEXT_FILE_PATH')) api_context.ensure_session_active() api_context.save(Config.get_option('API_CONTEXT_FILE_PATH')) BunqContext.load_api_context(api_context)
def fetch_transactions(days): # Ensure the whole account is included print("\nLoading Bunq API environment...") env = ApiEnvironmentType.PRODUCTION # Authenticate session & load context print("Authenticating and loading context...") api_context = ApiContext(ApiEnvironmentType.PRODUCTION, API_KEY, socket.gethostname()) api_context.ensure_session_active() BunqContext.load_api_context(api_context) # Get user info print("Loading user info...") user = endpoint.User.get().value.get_referenced_object() # Fetch account detials account = endpoint.MonetaryAccountJoint.get(ACCOUNT_ID).value description = account.description balance = account.balance.value print( f"\nLoaded account '{description}' with current balance of \N{euro sign}{balance}" ) start_date = datetime.now() - timedelta(days) transactions = [] for transaction in iterate_transactions(ACCOUNT_ID): transaction_dict = { "timestamp": transaction.created, "amount": transaction.amount.value, "description": transaction.description.replace("\r", "").replace("\n", " "), "counterparty": transaction.counterparty_alias.label_monetary_account.display_name, } # Still in range if dateparse.parse(transaction.created) >= start_date: transactions.append(transaction_dict) else: break print(transactions)
def setup_context(self): if isfile(self.determine_bunq_conf_filename()): pass # Config is already present elif self.env == ApiEnvironmentType.SANDBOX: sandbox_user = self.generate_new_sandbox_user() ApiContext(ApiEnvironmentType.SANDBOX, sandbox_user.api_key, socket.gethostname()).save( self.determine_bunq_conf_filename()) else: raise BunqException(self._ERROR_COULD_NOT_DETIRMINE_CONF) api_context = ApiContext.restore(self.determine_bunq_conf_filename()) api_context.ensure_session_active() api_context.save(self.determine_bunq_conf_filename()) BunqContext.load_api_context(api_context)
def setup_context(self): if Path(self.determine_bunq_conf_filename()).is_file(): pass else: sandbox_user = self.generate_new_sandbox_user() ApiContext( ApiEnvironmentType.SANDBOX, sandbox_user.api_key, socket.gethostname() ).save(self.determine_bunq_conf_filename()) self._api_context = ApiContext.restore(self.determine_bunq_conf_filename()) self._api_context.ensure_session_active() self._api_context.save(self.determine_bunq_conf_filename()) BunqContext.load_api_context(self._api_context) self._user_context = BunqContext.user_context()
def main(): parser = argparse.ArgumentParser() parser.add_argument(OPTION_API_KEY) all_option = parser.parse_args() if all_option.api_key is None: raise BunqException(ERROR_OPTION_MISSING_API_KEY) api_context = ApiContext(ApiEnvironmentType.PRODUCTION, all_option.api_key, '*') BunqContext.load_api_context(api_context) end = 50 for i in range(0, end): endpoint.Payment.create(amount=Amount('0.01', 'EUR'), counterparty_alias=Pointer('IBAN', '', ''), description=str(round(i / end * 100, 2)) + " Prozent von deinem Geld", monetary_account_id=) time.sleep(0.33333)
def setup_context(self, reset_config_if_needed=True): if isfile(self.determine_bunq_conf_filename()): pass # Config is already present elif self.env == ApiEnvironmentType.SANDBOX: sandbox_user = self.generate_new_sandbox_user() ApiContext(ApiEnvironmentType.SANDBOX, sandbox_user.api_key, socket.gethostname()).save( self.determine_bunq_conf_filename()) else: raise BunqException(self._ERROR_COULD_NOT_DETERMINE_CONF) try: api_context = ApiContext.restore( self.determine_bunq_conf_filename()) api_context.ensure_session_active() api_context.save(self.determine_bunq_conf_filename()) BunqContext.load_api_context(api_context) except ForbiddenException as forbidden_exception: if reset_config_if_needed: self.__handle_forbidden_exception(forbidden_exception) else: raise forbidden_exception
from bunq.sdk.context import ApiContext, BunqContext from bunq.sdk.context import ApiEnvironmentType import socket apiContext = ApiContext( ApiEnvironmentType.SANDBOX, "sandbox_ae9afa8798dc521804bd1d8900167457243b9fd323e6799a9d42d75d", socket.gethostname()) apiContext.save("bunq.conf") BunqContext.load_api_context(apiContext)
def all_transactions(dt=None): # This should be enough to ensure the whole account is included. if dt == None: dt = epoch env = ApiEnvironmentType.PRODUCTION if not isfile('bunq-production.conf'): raise Exception("No config file found, run start.py first.") # Reload the API context api_context = ApiContext.restore('bunq-production.conf') api_context.ensure_session_active() api_context.save('bunq-production.conf') BunqContext.load_api_context(api_context) # User info user = endpoint.User.get().value.get_referenced_object() # To get a list we want a pagination object. # When making a pagination object yourself you normally only set the 'count' # Then you get the url params from it using 'url_params_count_only' pagination = Pagination() pagination.count = 100 accounts = [] all_monetary_account_bank = endpoint.MonetaryAccountBank.list( pagination.url_params_count_only).value for monetary_account_bank in all_monetary_account_bank: if monetary_account_bank.status == "ACTIVE": accounts.append(monetary_account_bank) all_monetary_account_savings = endpoint.MonetaryAccountSavings.list( pagination.url_params_count_only).value for monetary_account_savings in all_monetary_account_savings: if monetary_account_savings.status == "ACTIVE": accounts.append(monetary_account_savings) # Reload where we where last time. try: with open("seen.pickle", "rb") as fp: seen = pickle.load(fp) except Exception: seen = set() # We will keep a list of transactions that are already processed in this set. # The transactions will contain: # - A set of the two possible roundings of the datestamp # - The ammount of money in absolute value # - The description # - A set containing the two accounts involved # The goal here is that this representation is the same for two accounts when shifting money arround. for a in accounts: aid = a.id_ # keep track of where we are print(a.description) for p in iter_payments(aid): # python can handle the dates we get back date = dateparse.parse(p.created) #round to the second to get a (sort of) unique, but not to precise timestamp since_epoch = int(unix_time(date)) row = [ p.created, p.amount.value, p.description.replace("\r", "").replace("\n", " "), p.alias.label_monetary_account.iban, p.counterparty_alias.label_monetary_account.iban ] # frozenset can be used to hash a set, so the order does not matter. summary = ( unique_float( since_epoch), #take both so there is norounding problem abs(float(p.amount.value)), p.description, frozenset([ p.alias.label_monetary_account.iban, p.counterparty_alias.label_monetary_account.iban ])) # Still in range if date >= dt: if summary in seen: continue else: seen.add(summary) yield (row) else: break with open("seen.pickle", "wb") as fp: pickle.dump(seen, fp)
def setup_context(self, api_key): api_context = ApiContext(ApiEnvironmentType.SANDBOX, api_key, socket.gethostname()) api_context.ensure_session_active() BunqContext.load_api_context(api_context)