π Crypto Portfolio Tracker with Blockchain Ledger | Python + CTkinter GUI πΉπ₯
Demo :
Click Video πππ
Features:
-
Embedded YouTube Short
-
Short description (100–150 words) from above
-
Code snippet (GitHub/Drive link optional)
-
Hashtags for SEO (#Python #Blockchain #Crypto #PortfolioApp #FuzzuTech)
Code :
import customtkinter as ctk
import requests
import hashlib
import json
import os
from datetime import datetime
# ---------------- Blockchain Class ---------------- #
class Block:
def __init__(self, index, timestamp, data, previous_hash):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.hash = self.calculate_hash()
def calculate_hash(self):
block_string = f"{self.index}{self.timestamp}{self.data}{self.previous_hash}"
return hashlib.sha256(block_string.encode()).hexdigest()
class Blockchain:
def __init__(self):
self.chain = [self.create_genesis_block()]
def create_genesis_block(self):
return Block(0, str(datetime.now()), "Genesis Block", "0")
def get_latest_block(self):
return self.chain[-1]
def add_block(self, data):
prev_block = self.get_latest_block()
new_block = Block(len(self.chain), str(datetime.now()), data, prev_block.hash)
self.chain.append(new_block)
def is_chain_valid(self):
for i in range(1, len(self.chain)):
curr = self.chain[i]
prev = self.chain[i - 1]
if curr.hash != curr.calculate_hash():
return False
if curr.previous_hash != prev.hash:
return False
return True
def to_dict(self):
return [block.__dict__ for block in self.chain]
def save_chain(self, filename="ledger.json"):
with open(filename, "w") as f:
json.dump(self.to_dict(), f, indent=4)
def load_chain(self, filename="ledger.json"):
if os.path.exists(filename):
with open(filename, "r") as f:
data = json.load(f)
self.chain = []
for block_data in data:
block = Block(
block_data['index'],
block_data['timestamp'],
block_data['data'],
block_data['previous_hash']
)
block.hash = block_data['hash']
self.chain.append(block)
# ---------------- Portfolio Tracker ---------------- #
class Portfolio:
def __init__(self):
self.holdings = {}
self.blockchain = Blockchain()
self.blockchain.load_chain()
def add_transaction(self, coin, amount, action, price):
if action == "BUY":
self.holdings[coin] = self.holdings.get(coin, 0) + amount
elif action == "SELL":
self.holdings[coin] = self.holdings.get(coin, 0) - amount
if self.holdings[coin] < 0:
self.holdings[coin] = 0
# Add to blockchain
data = {"coin": coin, "amount": amount, "action": action, "price": price}
self.blockchain.add_block(data)
self.blockchain.save_chain()
def get_holdings(self):
return self.holdings
def get_value(self):
total = 0
for coin, amt in self.holdings.items():
price = get_price(coin)
total += amt * price
return total
# ---------------- API Integration ---------------- #
def get_price(coin):
try:
url = f"https://api.coingecko.com/api/v3/simple/price?ids={coin}&vs_currencies=usd"
response = requests.get(url).json()
return response[coin]["usd"]
except:
return 0
# ---------------- GUI ---------------- #
class CryptoApp:
def __init__(self, root):
self.portfolio = Portfolio()
root.title("Crypto Portfolio Tracker with Blockchain Ledger")
root.geometry("550x600")
ctk.set_appearance_mode("dark")
ctk.set_default_color_theme("blue")
self.frame = ctk.CTkFrame(root, corner_radius=20)
self.frame.pack(pady=20, padx=20, fill="both", expand=True)
self.title = ctk.CTkLabel(self.frame, text="π Crypto Portfolio Tracker (Blockchain)", font=("Arial", 24, "bold"))
self.title.pack(pady=10)
# Entry fields
self.coin_entry = ctk.CTkEntry(self.frame, placeholder_text="Enter Coin (e.g. bitcoin)")
self.coin_entry.pack(pady=5)
self.amount_entry = ctk.CTkEntry(self.frame, placeholder_text="Enter Amount")
self.amount_entry.pack(pady=5)
self.action_var = ctk.StringVar(value="BUY")
self.buy_button = ctk.CTkRadioButton(self.frame, text="BUY", variable=self.action_var, value="BUY")
self.sell_button = ctk.CTkRadioButton(self.frame, text="SELL", variable=self.action_var, value="SELL")
self.buy_button.pack(pady=5)
self.sell_button.pack(pady=5)
self.add_button = ctk.CTkButton(self.frame, text="Add Transaction", command=self.add_transaction)
self.add_button.pack(pady=10)
self.holdings_label = ctk.CTkLabel(self.frame, text="Your Holdings:", font=("Arial", 18, "bold"))
self.holdings_label.pack(pady=10)
self.holdings_text = ctk.CTkTextbox(self.frame, height=150, width=500)
self.holdings_text.pack(pady=10)
self.refresh_button = ctk.CTkButton(self.frame, text="Refresh Portfolio Value", command=self.show_holdings)
self.refresh_button.pack(pady=5)
self.verify_button = ctk.CTkButton(self.frame, text="Verify Blockchain", command=self.verify_blockchain)
self.verify_button.pack(pady=5)
self.status_label = ctk.CTkLabel(self.frame, text="")
self.status_label.pack(pady=10)
def add_transaction(self):
coin = self.coin_entry.get().lower()
try:
amount = float(self.amount_entry.get())
except:
self.status_label.configure(text="⚠️ Enter valid amount!")
return
price = get_price(coin)
if price == 0:
self.status_label.configure(text="⚠️ Invalid Coin!")
return
action = self.action_var.get()
self.portfolio.add_transaction(coin, amount, action, price)
self.status_label.configure(text=f"✅ {action} {amount} {coin} at ${price}")
self.show_holdings()
def show_holdings(self):
holdings = self.portfolio.get_holdings()
self.holdings_text.delete("1.0", "end")
total_value = 0
for coin, amt in holdings.items():
price = get_price(coin)
value = amt * price
self.holdings_text.insert("end", f"{coin.upper()}: {amt} (Value: ${value:.2f})\n")
total_value += value
self.holdings_text.insert("end", f"\nTotal Portfolio Value: ${total_value:.2f}")
def verify_blockchain(self):
valid = self.portfolio.blockchain.is_chain_valid()
if valid:
self.status_label.configure(text="✅ Blockchain is Valid!")
else:
self.status_label.configure(text="❌ Blockchain is Corrupted!")
# ---------------- Run App ---------------- #
if __name__ == "__main__":
root = ctk.CTk()
app = CryptoApp(root)
root.mainloop()
Comments
Post a Comment