diff --git a/Instruction.txt b/Instruction.txt new file mode 100644 index 00000000..5b428c29 --- /dev/null +++ b/Instruction.txt @@ -0,0 +1,4 @@ +Zamieszczam przykładowy plik csv, w którym przechowywane są dane. +Można też utworzyć nowy pusty plik przy pomocy gui i następnie +dodać do niego wybrane przez siebie waluty. +Domyślnie walutą na który przeliczany jest portfel jest USD. \ No newline at end of file diff --git a/api.py b/api.py new file mode 100644 index 00000000..60c57998 --- /dev/null +++ b/api.py @@ -0,0 +1,64 @@ +from json import JSONDecodeError +import requests + +API_NAMES = ['bittrex', 'bitbay', 'cex'] + + +def get_answer(url): + try: + request = requests.get(url) + answer = request.json() + return answer + except requests.exceptions.ConnectionError: + print('No Internet connection. Check your network and try again later.') + return None + + +def get_orderbook_url(base_currency, wanted_currency, name): + if name == 'bittrex': + return 'https://api.bittrex.com/api/v1.1/public/getorderbook?market=' + base_currency.upper() + '-' + \ + wanted_currency.upper() + "&type=both" + if name == 'bitbay': + return 'https://bitbay.net/API/Public/' + wanted_currency.upper() + base_currency.upper() + '/orderbook.json' + if name == 'bitstamp': + return 'https://www.bitstamp.net/api/v2/order_book/' + base_currency.lower() + wanted_currency.lower() + '/' + if name == 'cex': + return f'https://cex.io/api/order_book/{base_currency.upper()}/{wanted_currency.upper()}' + + +def get_orderbook(base_currency, wanted_currency, name): + answer = get_answer(get_orderbook_url(base_currency, wanted_currency, name)) + buy_offers = [] + + try: + if name == 'bittrex': + for bid in answer['result']['buy']: + buy_offers.append((bid['Quantity'], bid['Rate'])) + if name == 'bitbay' or name == 'cex': + for bid in answer['bids']: + buy_offers.append((bid[1], bid[0])) + except TypeError: + return [] + except KeyError: + return [] + return buy_offers + + +def check_availability_in_api(base_currency, wanted_currency): + if base_currency == wanted_currency: + return True + answer = get_answer(get_orderbook_url(base_currency, wanted_currency, 'bittrex')) + if answer["success"]: + return True + + try: + for i in range(1, len(API_NAMES)): + answer = get_answer(get_orderbook_url(base_currency, wanted_currency, API_NAMES[i])) + if len(answer['bids']) > 0: + return True + except JSONDecodeError: + pass + except KeyError: + pass + + return False diff --git a/main.py b/main.py new file mode 100644 index 00000000..309aa3c9 --- /dev/null +++ b/main.py @@ -0,0 +1,250 @@ +import csv +import tkinter +import tkinter.messagebox +import wallet +import api + +my_wallet = [] +empty_wallet = [] +DEFAULT_CURRENCY = 'USD' +window = tkinter.Tk() + + +# to mój feature dla użytkownika, myślę, że przejrzyste gui może znacząco ułatwić używanie aplikacji :) +def gui(): + window.geometry("300x340") + window.title("API application") + menu_label = tkinter.Label(window, text="Menu", font=("Sans-serif", 13), anchor='e') + menu_label.grid(row=0, column=0, padx=90, pady=5, sticky='n') + menu_button_first = tkinter.Button(window, text="Show wallet", command=lambda: first_button()) + menu_button_first.grid(row=1, column=0, padx=90, pady=5, sticky='nwse') + menu_button_second = tkinter.Button(window, text="Add new currency", command=lambda: second_button()) + menu_button_second.grid(row=2, column=0, padx=90, pady=5, sticky='nwse') + menu_button_third = tkinter.Button(window, text="Remove currency", command=lambda: third_button()) + menu_button_third.grid(row=3, column=0, padx=90, pady=5, sticky='nwse') + menu_button_fourth = tkinter.Button(window, text="Edit currency amount", command=lambda: fourth_button()) + menu_button_fourth.grid(row=4, column=0, padx=90, pady=5, sticky='nwse') + menu_button_fifth = tkinter.Button(window, text="Add amount to currency", command=lambda: fifth_button()) + menu_button_fifth.grid(row=5, column=0, padx=90, pady=5, sticky='nwse') + menu_button_sixth = tkinter.Button(window, text="Convert wallet", command=lambda: sixth_button()) + menu_button_sixth.grid(row=6, column=0, padx=90, pady=5, sticky='nwse') + menu_button_seventh = tkinter.Button(window, text="Make empty wallet", + command=lambda: wallet.save_wallet_to_file(empty_wallet)) + menu_button_seventh.grid(row=7, column=0, padx=90, pady=5, sticky='nwse') + menu_button_eighth = tkinter.Button(window, text="Exit", command=window.quit) + menu_button_eighth.grid(row=8, column=0, padx=90, pady=5, sticky='nwse') + + +def first_button(): + my_wallet = wallet.read_wallet_data() + wallet_str = wallet.print_wallet(my_wallet) + + tkinter.messagebox.showinfo('Wallet', wallet_str) + + +def second_button(): + global my_wallet + try: + my_wallet = wallet.read_wallet_data() + except: + tkinter.messagebox.showinfo('Error!', 'Check your csv file.') + + second_window = tkinter.Toplevel() + second_window.geometry("300x170") + second_window.title("Adding new currency") + window.protocol("WM_DELETE_WINDOW", window.quit()) + + currency_label = tkinter.Label(second_window, text="Enter currency name:", font=("Sans-serif", 13), anchor='e') + currency_field = tkinter.Entry(second_window) + amount_label = tkinter.Label(second_window, text="Enter amount:", font=("Sans-serif", 13), anchor='e') + amount_field = tkinter.Entry(second_window) + add_currency_button = tkinter.Button(second_window, text="Add currency", + command=lambda: second_button_helper(currency_field, amount_field, my_wallet)) + + currency_label.grid(row=0, column=0, pady=(40, 0)) + currency_field.grid(row=0, column=1, pady=(40, 0)) + amount_label.grid(row=1, column=0) + amount_field.grid(row=1, column=1) + add_currency_button.grid(columnspan=2) + + second_window.mainloop() + + +def second_button_helper(currency_field, amount_field, my_wallet): + currency = str(currency_field.get()).upper() + amount = amount_field.get() + try: + if api.check_availability_in_api(DEFAULT_CURRENCY, currency): + wallet.add_currency(currency, float(amount), my_wallet) + else: + tkinter.messagebox.showinfo('Error!', 'Currency is not available in API.') + return + except ValueError: + tkinter.messagebox.showinfo('Error!', 'Wrong amount.') + return + tkinter.messagebox.showinfo('Info', 'Currency added.') + + +def third_button(): + global my_wallet + try: + my_wallet = wallet.read_wallet_data() + except: + tkinter.messagebox.showinfo('Error!', 'Check your csv file.') + + third_window = tkinter.Toplevel() + third_window.geometry("300x170") + third_window.title("Removing currency") + window.protocol("WM_DELETE_WINDOW", window.quit()) + + currency_label = tkinter.Label(third_window, text="Enter currency name:", font=("Sans-serif", 13), anchor='e') + currency_field = tkinter.Entry(third_window) + add_currency_button = tkinter.Button(third_window, text="Remove currency", + command=lambda: third_button_helper(currency_field, my_wallet)) + + currency_label.grid(row=0, column=0, pady=(40, 0)) + currency_field.grid(row=0, column=1, pady=(40, 0)) + add_currency_button.grid(columnspan=2) + + third_window.mainloop() + + +def third_button_helper(currency_field, my_wallet): + currency = str(currency_field.get()).upper() + if wallet.check_currency_in_wallet(currency, my_wallet): + wallet.remove_currency(currency, my_wallet) + tkinter.messagebox.showinfo('Info', 'Currency removed.') + else: + tkinter.messagebox.showinfo('Info', 'There is no such currency in your wallet.') + + +def fourth_button(): + global my_wallet + try: + my_wallet = wallet.read_wallet_data() + except: + tkinter.messagebox.showinfo('Error!', 'Check your csv file.') + + fourth_window = tkinter.Toplevel() + fourth_window.geometry("300x170") + fourth_window.title("Editing amount of currency") + window.protocol("WM_DELETE_WINDOW", window.quit()) + + currency_label = tkinter.Label(fourth_window, text="Enter currency name:", font=("Sans-serif", 13), anchor='e') + currency_field = tkinter.Entry(fourth_window) + amount_label = tkinter.Label(fourth_window, text="Enter amount:", font=("Sans-serif", 13), anchor='e') + amount_field = tkinter.Entry(fourth_window) + add_currency_button = tkinter.Button(fourth_window, text="Edit currency amount", + command=lambda: fourth_button_helper(currency_field, amount_field, my_wallet)) + + currency_label.grid(row=0, column=0, pady=(40, 0)) + currency_field.grid(row=0, column=1, pady=(40, 0)) + amount_label.grid(row=1, column=0) + amount_field.grid(row=1, column=1) + add_currency_button.grid(columnspan=2) + + fourth_window.mainloop() + + +def fourth_button_helper(currency_field, amount_field, my_wallet): + currency = str(currency_field.get()).upper() + amount = amount_field.get() + if wallet.check_currency_in_wallet(currency, my_wallet): + try: + wallet.edit_currency_amount(currency, float(amount), my_wallet) + except ValueError: + tkinter.messagebox.showinfo('Error!', 'Wrong amount.') + tkinter.messagebox.showinfo('Info', 'Currency amount edited.') + else: + tkinter.messagebox.showinfo('Info', 'There is no such currency in your wallet.') + + +def fifth_button(): + global my_wallet + try: + my_wallet = wallet.read_wallet_data() + except: + tkinter.messagebox.showinfo('Error!', 'Check your csv file.') + + fifth_window = tkinter.Toplevel() + fifth_window.geometry("300x170") + fifth_window.title("Adding amount to currency") + window.protocol("WM_DELETE_WINDOW", window.quit()) + + currency_label = tkinter.Label(fifth_window, text="Enter currency name:", font=("Sans-serif", 13), anchor='e') + currency_field = tkinter.Entry(fifth_window) + amount_label = tkinter.Label(fifth_window, text="Enter amount:", font=("Sans-serif", 13), anchor='e') + amount_field = tkinter.Entry(fifth_window) + add_currency_button = tkinter.Button(fifth_window, text="Add amount to currency", + command=lambda: fifth_button_helper(currency_field, amount_field, my_wallet)) + + currency_label.grid(row=0, column=0, pady=(40, 0)) + currency_field.grid(row=0, column=1, pady=(40, 0)) + amount_label.grid(row=1, column=0) + amount_field.grid(row=1, column=1) + add_currency_button.grid(columnspan=2) + + fifth_window.mainloop() + + +def fifth_button_helper(currency_field, amount_field, my_wallet): + currency = str(currency_field.get()).upper() + amount = amount_field.get() + if wallet.check_currency_in_wallet(currency, my_wallet): + try: + wallet.add_currency_amount(currency, float(amount), my_wallet) + except ValueError: + tkinter.messagebox.showinfo('Error!', 'Wrong amount.') + tkinter.messagebox.showinfo('Info', 'Currency amount edited.') + else: + tkinter.messagebox.showinfo('Info', 'There is no such currency in your wallet.') + + +def sixth_button(): + global my_wallet + try: + my_wallet = wallet.read_wallet_data() + except: + tkinter.messagebox.showinfo('Error!', 'Check your csv file.') + + sixth_window = tkinter.Toplevel() + sixth_window.geometry("480x180") + sixth_window.title("Converting wallet") + window.protocol("WM_DELETE_WINDOW", window.quit()) + + info_label = tkinter.Label(sixth_window, text="If you won't entry any currency it will be used default one - USD", + font=("Sans-serif", 13), anchor='e') + currency_label = tkinter.Label(sixth_window, text="Enter currency name:", font=("Sans-serif", 13), anchor='e') + currency_field = tkinter.Entry(sixth_window) + add_currency_button = tkinter.Button(sixth_window, text="Convert wallet", + command=lambda: sixth_button_helper(currency_field)) + + info_label.grid(columnspan=2, pady=(40, 0)) + currency_label.grid(row=1, column=0) + currency_field.grid(row=1, column=1) + add_currency_button.grid(columnspan=2) + + sixth_window.mainloop() + + +def sixth_button_helper(currency_field): + currency = str(currency_field.get()).upper() + if currency == None: + currency = DEFAULT_CURRENCY + try: + converted_wallet = wallet.convert_wallet(my_wallet, currency) + except: + tkinter.messagebox.showinfo('Error!', 'Something went wrong. It is possible that the wallet' + ' cannot be converted to the currency of your choice') + return + tkinter.messagebox.showinfo('Wallet', converted_wallet) + + +def run(): + csv.register_dialect('semicolons', delimiter=';') + gui() + window.mainloop() + + +if __name__ == "__main__": + run() diff --git a/wallet.csv b/wallet.csv new file mode 100644 index 00000000..b484c8c4 --- /dev/null +++ b/wallet.csv @@ -0,0 +1,4 @@ +Currency;Quantity +LTC;5.0 +BTC;4.0 +ETH;6.0 diff --git a/wallet.py b/wallet.py new file mode 100644 index 00000000..e2229e7f --- /dev/null +++ b/wallet.py @@ -0,0 +1,136 @@ +import csv +import api +import tkinter.messagebox + +DEFAULT_CURRENCY = 'USD' +FILENAME = 'wallet.csv' + + +def read_wallet_data(): + try: + csv_wallet = [] + csv_file = open(FILENAME, 'r') + with csv_file: + csv_reader = csv.reader(csv_file, dialect='semicolons') + for row in csv_reader: + try: + if len(row) == 2: + currency = row[0] + amount = float(row[1]) + csv_wallet.append((currency, amount)) + except ValueError: + pass + csv_file.close() + return csv_wallet + except FileNotFoundError: + tkinter.messagebox.showinfo('Error', 'Something went wrong. Check if your file is exist.') + return [] + + +def convert_wallet(wallet, converting_currency): + wallet_money = 0 + for currency in wallet: + wallet_currency_name = currency[0] + quantity = currency[1] + + offers = [] + for api_name in api.API_NAMES: + offers += api.get_orderbook(converting_currency, wallet_currency_name, api_name) + + if len(offers) == 0: + if wallet_currency_name.upper() == converting_currency.upper(): + wallet_money += quantity + continue + print(f"{wallet_currency_name.upper()}-{converting_currency.upper()} is not available in API") + return None + + price = lambda currency_offer: currency_offer[1] + offers.sort(key=price, reverse=True) + + for offer in offers: + offer_quantity = offer[0] + offer_price = offer[1] + if offer_quantity >= quantity: + wallet_money += offer_price * quantity + quantity = 0 + else: + wallet_money += offer_price * offer_quantity + quantity -= offer_quantity + + if quantity == 0: + break + + if quantity > 0: + print(f"There is not enough buy offers on markets for {currency}") + + # print('Totally you have', str(wallet_money), converting_currency, 'in your wallet.') + return_str = 'Totally you have ' + str(wallet_money) + ' ' + converting_currency + ' in your wallet.' + return return_str + + +def save_wallet_to_file(wallet): + csv.register_dialect('semicolons', delimiter=';') + + file = open(FILENAME, 'w+') + with file: + writer = csv.writer(file, dialect='semicolons') + writer.writerow(('Currency', 'Quantity')) + + for currency in wallet: + writer.writerow((currency[0].upper(), currency[1])) + + +def remove_currency(currency_to_remove, wallet): + for currency in wallet: + if currency[0] == currency_to_remove: + wallet.remove(currency) + save_wallet_to_file(wallet) + + +def add_currency(currency_name, amount, wallet): + currency_exist = False + currency_name = currency_name + for currency in wallet: + if currency[0] == currency_name: + remove_currency(currency_name, wallet) + wallet.append((currency_name, amount)) + currency_exist = True + break + if not currency_exist: + wallet.append((currency_name, amount)) + + save_wallet_to_file(wallet) + + +def edit_currency_amount(currency_name, new_amount, wallet): + remove_currency(currency_name, wallet) + add_currency(currency_name, new_amount, wallet) + + +def check_currency_in_wallet(currency_name, wallet): + for currency in wallet: + if currency[0] == currency_name: + return True + return False + + +def add_currency_amount(currency_name, amount_to_add, wallet): + currency_exist = False + currency_name = currency_name + for currency in wallet: + if currency[0] == currency_name: + currency_amount = currency[1] + amount_to_add + remove_currency(currency_name, wallet) + wallet.append((currency_name, currency_amount)) + currency_exist = True + save_wallet_to_file(wallet) + break + if not currency_exist: + print('In your wallet there is no such currency. :(') + + +def print_wallet(wallet): + wallet_str = '' + for currency in wallet: + wallet_str += str(currency[0]) + ' ' + str(currency[1]) + '\n' + return wallet_str