Skip to content

Commit cc136ad

Browse files
author
Matthias Ley
committed
Added fiat and trade functionalities, rehauled UI design
1 parent 4862b62 commit cc136ad

2 files changed

Lines changed: 264 additions & 70 deletions

File tree

TKinter/Bitpanda/crypto_api.py

Lines changed: 104 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
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
912
import requests
1013
import 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

304315
def 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

407449
def 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

442498
def 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+
449527
if __name__ == "__main__":
450528
print(help(__name__))

0 commit comments

Comments
 (0)