GPT先生にbitcoinlibでビットコインのCLIウォレットを構築してと頼んでみました。
bitcoinlibで全て出来るのでわざわざこんなコードを書く必要はないんですが、ドキュメント読み込むより実際に動くコード見せてもらった方が理解が早いので、何度か先生にお願いして基本的な機能を実装したウォレットを作ってもらいました。
import os
import sqlite3
import pyqrcode
from bitcoinlib.wallets import Wallet, wallet_delete
from bitcoinlib.keys import Address
from bitcoinlib.services.services import Service
def create_wallet(wallet_name, wallet_type='p2pkh'):
network = 'testnet'
if wallet_type == 'p2pkh':
wallet = Wallet.create(wallet_name, network=network)
elif wallet_type == 'segwit':
wallet = Wallet.create(wallet_name, network=network, witness_type='segwit')
else:
print(f"Unsupported wallet type: {wallet_type}")
return None
key = wallet.get_key()
address = key.address
wif_key = key.wif
with sqlite3.connect("wallet_metadata.db") as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS wallet_info (name TEXT, address_type TEXT)")
cursor.execute("INSERT INTO wallet_info (name, address_type) VALUES (?, ?)", (wallet_name, wallet_type))
conn.commit()
print(f"Wallet '{wallet_name}' of type '{wallet_type}' created.")
print(f"Address: {address}")
print(f"Key (WIF): {wif_key}")
return wallet
def check_balance(wallet_name):
try:
wallet = Wallet(wallet_name)
address = wallet.get_key().address
svc = Service(network='testnet')
balance = svc.getbalance(address)
print(f"Balance for wallet '{wallet_name}' (address: {address}): {balance} BTC")
return balance
except Exception as e:
print(f"Error checking balance for wallet '{wallet_name}': {e}")
return None
def send_bitcoin(wallet_name, recipient_address, amount):
if amount <= 0:
print("Amount must be greater than 0.")
return None
wallet = Wallet(wallet_name)
try:
tx = wallet.send_to(recipient_address, amount)
print(f"Transaction sent. TXID: {tx.txid}")
return tx.txid
except Exception as e:
print(f"Error sending Bitcoin: {e}")
return None
def send_bitcoin_multiple(wallet_name, recipients):
if not recipients:
print("No recipients provided.")
return None
wallet = Wallet(wallet_name)
outputs = [(address, amount) for address, amount in recipients if amount > 0]
if not outputs:
print("All amounts must be greater than 0.")
return None
try:
tx = wallet.transaction_create(outputs)
tx.sign()
tx.send()
print(f"Transaction sent. TXID: {tx.txid}")
return tx.txid
except Exception as e:
print(f"Error sending Bitcoin: {e}")
return None
def list_wallets():
db_path = os.path.expanduser("~/.bitcoinlib/database/bitcoinlib.sqlite")
conn = sqlite3.connect(db_path)
cursor = conn.cursor()
cursor.execute("SELECT name FROM wallets")
wallets = cursor.fetchall()
conn.close()
with sqlite3.connect("wallet_metadata.db") as conn:
cursor = conn.cursor()
cursor.execute("CREATE TABLE IF NOT EXISTS wallet_info (name TEXT, address_type TEXT)")
cursor.execute("SELECT name, address_type FROM wallet_info")
wallet_info = cursor.fetchall()
if not wallets:
print("No wallets found.")
else:
for wallet in wallets:
name = wallet[0]
address_type = next((wt[1] for wt in wallet_info if wt[0] == name), "unknown")
print(f"Wallet: {name}, Type: {address_type}")
def delete_wallet(wallet_name):
wallet_delete(wallet_name)
with sqlite3.connect("wallet_metadata.db") as conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM wallet_info WHERE name = ?", (wallet_name,))
conn.commit()
print(f"Wallet '{wallet_name}' deleted.")
def view_keys(wallet_name):
try:
wallet = Wallet(wallet_name)
key = wallet.get_key()
wif_key = key.wif
print(f"Wallet '{wallet_name}' key:")
print(f"Key (WIF): {wif_key}")
except Exception as e:
print(f"Error retrieving keys for wallet '{wallet_name}': {e}")
def view_address(wallet_name):
try:
wallet = Wallet(wallet_name)
key = wallet.get_key()
address = key.address
print(f"Wallet '{wallet_name}' address:")
print(f"Address: {address}")
qr = pyqrcode.create(address)
qr.png("qrcode.png", scale=8)
os.system("xdg-open qrcode.png")
except Exception as e:
print(f"Error retrieving address for wallet '{wallet_name}': {e}")
def is_valid_address(address):
return len(address) > 0 and (address.startswith('1') or address.startswith('3') or address.startswith('m') or address.startswith('2') or address.startswith('tb1') or address.startswith('bcrt1'))
def get_valid_amount():
while True:
try:
amount = float(input("Enter amount to send (BTC): "))
if amount <= 0:
raise ValueError("Amount must be greater than 0.")
return amount
except ValueError as e:
print(f"Invalid amount: {e}")
def main():
print("Bitcoin Wallet Application (Testnet)")
print("====================================")
print("1. Create Wallet")
print("2. Check Balance")
print("3. Send Bitcoin")
print("4. Send Bitcoin to Multiple Addresses")
print("5. List Wallets")
print("6. Delete Wallet")
print("7. View Wallet Keys")
print("8. View Wallet Address and QR Code")
print("9. Exit")
while True:
choice = input("Enter your choice: ")
if choice == '1':
wallet_name = input("Enter wallet name: ")
wallet_type = input("Enter wallet type (p2pkh, segwit): ").strip().lower()
create_wallet(wallet_name, wallet_type)
elif choice == '2':
wallet_name = input("Enter wallet name: ")
check_balance(wallet_name)
elif choice == '3':
wallet_name = input("Enter wallet name: ")
recipient_address = input("Enter recipient address: ")
if not is_valid_address(recipient_address):
print("Invalid recipient address.")
continue
amount = get_valid_amount()
send_bitcoin(wallet_name, recipient_address, amount)
elif choice == '4':
wallet_name = input("Enter wallet name: ")
recipients = []
while True:
recipient_address = input("Enter recipient address (or press Enter to finish): ")
if not recipient_address:
break
if not is_valid_address(recipient_address):
print("Invalid recipient address.")
continue
amount = get_valid_amount()
recipients.append((recipient_address, amount))
send_bitcoin_multiple(wallet_name, recipients)
elif choice == '5':
list_wallets()
elif choice == '6':
wallet_name = input("Enter wallet name to delete: ")
delete_wallet(wallet_name)
elif choice == '7':
wallet_name = input("Enter wallet name: ")
view_keys(wallet_name)
elif choice == '8':
wallet_name = input("Enter wallet name: ")
view_address(wallet_name)
elif choice == '9':
print("Exiting...")
break
else:
print("Invalid choice. Please try again.")
if __name__ == '__main__':
main()
テストネットで送金できるか試そうと思ってアドレス生成してテストネットBTC送ってみたんですが、送った事実を忘れて秘密鍵を削除してしまい、X tsats失ってしまいました。bitcoinlibの機能を自分好みにわかりすいインターフェースで表現しただけなので、多分うまくいってるんでしょう。もう取り出せませんが。