55- Requires ExchangeRate-API key obtained from https://app.exchangerate-api.com/sign-up
66- BitPanda API Documentation: https://developers.bitpanda.com/platform/#/wallets-get
77"""
8-
8+ import os
9+ import tempfile
10+ import time
11+ import json
912import requests
1013import datetime
1114
@@ -60,13 +63,16 @@ def __get_data(root_url="https://api.bitpanda.com/v1/", sub_url="", headers=None
6063 return return_data
6164
6265 elif resp .status_code == 401 :
63- print ("Wrong API Key / Access token!" )
66+ print ("Bitpanda: Wrong API Key / Access token!" )
6467 return
6568 elif resp .status_code == 500 :
66- print ("Internal server error!" )
69+ print ("Bitpanda: Internal server error!" )
70+ return
71+ elif resp .status_code == 422 :
72+ print ("Bitpanda: API key expired!" )
6773 return
6874 else :
69- print (f"Unknown status code received: { resp .status_code } " )
75+ print (f"Bitpanda: Unknown status code received: { resp .status_code } " )
7076 return
7177
7278
@@ -280,6 +286,9 @@ def __get_exchange_rates(fcsapi_key=None, fcsapi_root_url="https://fcsapi.com/ap
280286 print (f" { len (exchange_rates )} exchange rates generated. This has cost you 2 fcsapi.com credits " .center (120 ,
281287 "*" ))
282288
289+ # add not converted coins to output dict
290+ exchange_rates ["Not converted coins" ] = bitpanda_coins
291+
283292 # undo corrections
284293 exchange_rates [f"BEST/{ currency } " ] = exchange_rates .pop (f"BESTb/{ currency } " )
285294 exchange_rates [f"BTT/{ currency } " ] = exchange_rates .pop (f"BTTN/{ currency } " )
@@ -300,6 +309,8 @@ def get_trades(bitpanda_api_key=None):
300309
301310 print (f"Total invested: { total_invested } " )
302311
312+ return {"balance_data" : balance_data , "total_invested" : total_invested }
313+
303314
304315def get_asset_wallets (enable_conversion = False , bitpanda_api_key = None , forex_api_key = None , exchangerate_api_key = None ,
305316 conversion_currency = "EUR" , conversion_alt_currencies = ["BTC" , "USD" ], conversion_silent = True ):
@@ -316,8 +327,13 @@ def get_asset_wallets(enable_conversion=False, bitpanda_api_key=None, forex_api_
316327 print ("Please provide exchangerate_api_key!" )
317328 return
318329
330+ # fetch wallet_data from bitpanda API
319331 wallet_data = __get_data (sub_url = "asset-wallets" , bitpanda_api_key = bitpanda_api_key )
320- wallets = {}
332+ if not wallet_data :
333+ return
334+
335+ # pre-define output dictionary
336+ wallets = {"return_string" : "" }
321337
322338 # fetch conversion data if enable_conversion is True
323339 if enable_conversion :
@@ -326,9 +342,12 @@ def get_asset_wallets(enable_conversion=False, bitpanda_api_key=None, forex_api_
326342 alt_currencies = conversion_alt_currencies , silent = conversion_silent )
327343
328344 # header
329- tmp = ["" , f" | { 'Current Value' :<20} " ][enable_conversion ]
345+ tmp_filler = f"Current Value [{ conversion_currency } ]"
346+ tmp = ["" , f" | { tmp_filler :<20} " ][enable_conversion ]
330347 sep_length = [66 , 89 ][enable_conversion ]
331- print (f"{ 'Symbol' :<20} | { 'Balance' :<20} | { 'Name' :<20} { tmp } " )
348+ header_text = f"{ 'Symbol' :<20} | { 'Balance' :<20} | { 'Name' :<20} { tmp } "
349+ print (header_text )
350+ wallets ["return_string" ] += f"{ header_text } \n { '-' * sep_length } \n "
332351
333352 # iterate over assets, collect wallet information and create formatted dict 'wallets'
334353 for asset in wallet_data ["attributes" ].keys ():
@@ -341,6 +360,9 @@ def get_asset_wallets(enable_conversion=False, bitpanda_api_key=None, forex_api_
341360
342361 tmp_wallet = {}
343362 for asset , asset_data in wallets .items ():
363+ if asset == "return_string" :
364+ continue
365+
344366 converted_sum = 0
345367 # pre-evaluate if balances in asset are all zero
346368 sum_wallets = sum ([float (f ["attributes" ]["balance" ]) for f in asset_data ])
@@ -369,18 +391,25 @@ def get_asset_wallets(enable_conversion=False, bitpanda_api_key=None, forex_api_
369391
370392 tmp_convert = ["" , f" | { converted_val } " ][enable_conversion ]
371393
372- # print information
373- print (f"{ tmp ['cryptocoin_symbol' ]:<20} | { tmp ['balance' ]:<20} | { tmp ['name' ]:<20} { tmp_convert } " )
394+ # print information and append to return_string
395+ tmp_str = f"{ tmp ['cryptocoin_symbol' ]:<20} | { tmp ['balance' ]:<20} | { tmp ['name' ]:<20} { tmp_convert } "
396+ print (tmp_str )
397+ wallets ["return_string" ] += f"{ tmp_str } \n "
374398
375399 # print converted sum at end
376400 if enable_conversion and converted_sum != 0 :
377401 tmp_wallet [f"summary_{ asset } " ] = {f"Sum { conversion_currency } " : converted_sum ,
378402 "Timestamp" : datetime .datetime .now ()}
379403 print ("-" * sep_length )
380- print (f"{ '' :<66} | { converted_sum :<20} " )
404+ sum_text = f"{ '' :<66} | { converted_sum :<20} "
405+ print (sum_text )
406+ wallets ["return_string" ] += f"{ '-' * sep_length } \n { sum_text } \n { '-' * sep_length } \n "
381407
382- # join dicts
383- wallets = {** wallets , ** tmp_wallet }
408+ # join dicts, append conversion_rates
409+ if enable_conversion :
410+ wallets = {** wallets , ** tmp_wallet , "exchange_rates" : conversion_rates }
411+ else :
412+ wallets = {** wallets , ** tmp_wallet }
384413
385414 return wallets
386415
@@ -390,9 +419,18 @@ def get_fiat_wallets(bitpanda_api_key=None):
390419 if not bitpanda_api_key :
391420 return
392421
393- fiat_data = __get_data ( sub_url = "fiatwallets" )
394- print ( f" { len ( fiat_data ) } fiat wallets " . center ( 66 , "*" ) )
422+ # fetch fiat wallet data
423+ fiat_data = __get_data ( sub_url = "fiatwallets" , bitpanda_api_key = bitpanda_api_key )
395424
425+ # predefine return string
426+ return_string = ""
427+
428+ # print header
429+ tmp_header = f" { len (fiat_data )} fiat wallets " .center (66 , "*" )
430+ print (tmp_header )
431+ return_string += f"{ tmp_header } \n "
432+
433+ # iterate over fiat wallet data
396434 for fiat_wallet in fiat_data :
397435 tmp = fiat_wallet ["attributes" ]
398436
@@ -401,7 +439,11 @@ def get_fiat_wallets(bitpanda_api_key=None):
401439 continue
402440
403441 # print information
404- print (f"{ tmp ['fiat_symbol' ]:<20} | { tmp ['balance' ]:<20} | { tmp ['name' ]:<20} " )
442+ tmp_text = f"{ tmp ['fiat_symbol' ]:<20} | { tmp ['balance' ]:<20} | { tmp ['name' ]:<20} "
443+ print (tmp_text )
444+ return_string += f"{ tmp_text } \n "
445+
446+ return {"fiat_data" : fiat_data , "return_string" : return_string }
405447
406448
407449def get_fiat_transactions (bitpanda_api_key = None ):
@@ -410,33 +452,47 @@ def get_fiat_transactions(bitpanda_api_key=None):
410452 return
411453
412454 # get transaction data
413- transaction_data = __get_data (sub_url = "fiatwallets/transactions" )
455+ transaction_data = __get_data (sub_url = "fiatwallets/transactions" , bitpanda_api_key = bitpanda_api_key )
414456
415457 # get lookup-table
416- lookup = __resolve_bitpanda_crypto_ids ()
458+ lookup = __resolve_bitpanda_crypto_ids (bitpanda_api_key = bitpanda_api_key )
417459
418- # header
419- print (f"{ 'Time' :<30} | { 'Type' :<10} | { 'Fiat ID' :<10} | { 'Fiat Amount' :<15} | { 'Crypto ID' :<10} | "
420- f"{ 'Crypto Amount' :<15} | { 'Price' :<15} " )
460+ # predefine return string
461+ return_string = ""
421462
422- print (f" { len (transaction_data )} fiat transactions " .center (123 , "*" ))
463+ # header
464+ header_tmp = f"{ 'Time' :<30} | { 'Type' :<10} | { 'Fiat ID' :<10} | { 'Fiat Amount' :<15} | { 'Crypto ID' :<10} | " \
465+ f"{ 'Crypto Amount' :<15} | { 'Price' :<15} "
466+ print (header_tmp )
467+ return_string += f"{ header_tmp } \n "
468+ header_sep_tmp = f" { len (transaction_data )} fiat transactions " .center (123 , "*" )
469+ print (header_sep_tmp )
470+ return_string += f"{ header_sep_tmp } \n "
423471
424472 # iterate over transactions
425473 for transaction in transaction_data :
426474 tmp = transaction ["attributes" ]
427475
428476 # print information
429- time = " " .join (tmp ["time" ]["date_iso8601" ].replace ("T" , " " ).split ())
477+ tmp_time = " " .join (tmp ["time" ]["date_iso8601" ].replace ("T" , " " ).split ())
430478 if tmp ["type" ] == "buy" :
431479 trade = tmp ["trade" ]["attributes" ]
432480 if int (trade ["cryptocoin_id" ]) in lookup .keys ():
433481 trade ["cryptocoin_id" ] = f"{ trade ['cryptocoin_id' ]:<2} | { lookup [int (trade ['cryptocoin_id' ])]} "
434- print (f"{ time :<30} | { tmp ['type' ]:<10} | { trade ['fiat_id' ]:<10} | { trade ['amount_fiat' ]:<15} | "
435- f"{ trade ['cryptocoin_id' ]:<10} | { trade ['amount_cryptocoin' ]:<15} | { trade ['price' ]:<15} " )
482+ tmp_str = f"{ tmp_time :<30} | { tmp ['type' ]:<10} | { trade ['fiat_id' ]:<10} | { trade ['amount_fiat' ]:<15} | " \
483+ f"{ trade ['cryptocoin_id' ]:<10} | { trade ['amount_cryptocoin' ]:<15} | { trade ['price' ]:<15} "
484+ print (tmp_str )
485+ return_string += f"{ tmp_str } \n "
436486 elif tmp ["type" ] == "deposit" :
437- print (f"{ time :<30} | { tmp ['type' ]:<10} | { tmp ['fiat_id' ]:<10} | { tmp ['amount' ]:<15} " )
487+ tmp_str = f"{ tmp_time :<30} | { tmp ['type' ]:<10} | { tmp ['fiat_id' ]:<10} | { tmp ['amount' ]:<15} "
488+ print (tmp_str )
489+ return_string += f"{ tmp_str } \n "
438490 else :
439- print (f"Unknown transaction type: { tmp ['type' ]} " )
491+ tmp_str = f"Unknown transaction type: { tmp ['type' ]} "
492+ print (tmp_str )
493+ return_String += f"{ tmp_str } \n "
494+
495+ return {"transaction_data" : transaction_data , "return_string" : return_string }
440496
441497
442498def get_currency_information ():
@@ -446,5 +502,27 @@ def get_currency_information():
446502 print (currency_data )
447503
448504
505+ class DateTimeEncoder (json .JSONEncoder ):
506+ def default (self , z ):
507+ if isinstance (z , datetime .datetime ):
508+ return str (z )
509+ else :
510+ return super ().default (z )
511+
512+
513+ def write_to_temporary_file (data = None , suffix = ".json" ):
514+ """Write data to a temporary file"""
515+ temp_file = tempfile .NamedTemporaryFile (suffix = suffix )
516+ if suffix == ".json" :
517+ temp_file .write (json .dumps (data , indent = 4 , cls = DateTimeEncoder ).encode ())
518+ else :
519+ temp_file .write (data )
520+ temp_file .flush ()
521+ os .startfile (temp_file .name )
522+ time .sleep (1 )
523+ print ("Launched temporary file:" , temp_file .name )
524+ temp_file .close ()
525+
526+
449527if __name__ == "__main__" :
450528 print (help (__name__ ))
0 commit comments