diff --git a/README.md b/README.md index ac34052..2b9bf8c 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,20 @@ Table Of Contents # Roll2Mnemonic -This multifaceted tool empowers you to effortlessly create secure mnemonic seed phrases using either manual dice rolls or coin tosses. It then goes a step further by generating corresponding private keys and public addresses for all available Bitcoin script types. Whether you prefer manual or automated methods, this tool has you covered. +This multifaceted tool empowers you to effortlessly create secure mnemonic seed phrases using either manual dice rolls, coin tosses or seed phrases. It then goes a step further by generating corresponding private keys and public addresses for all available Bitcoin script types. Whether you prefer manual or automated methods, this tool has you covered. ## Features -- **Dice Roll:** - 1. Manual Dice Roll: You have the option to roll physical dice or coin toss and input the data into the program as binary (1 or 0) or numbers (1 to 6). This method ensures true randomness in generating your mnemonic seed phrase. - 2. Automated Dice Roll: If you prefer a quicker approach, the program can generate random dice rolls for you. The automated dice roll function guarantees the randomness required for secure seed phrase generation. -- **Mnemonic Seed Generation:** Once the dice roll data is collected, the program seamlessly proceeds to generate a valid checksum then generates a BIP39 mnemonic seed phrase. This seed phrase is the foundation for generating Bitcoin private keys and public addresses. -- **Mnemonic Code Converter:** The mnemonic seed phrase is then passed through to the Mnemonic Code Converter within the same program. This converter is capable of generating BIP39 private keys and public addresses for all script types: Legacy (P2PKH), Nested SegWit (P2SH-P2WPKH), Native SegWit (P2WPKH), and Taproot (P2TR). +- **Dice Roll To Mnemonic:** + 1. Physical Dice or Coin Toss: You have the flexibility to roll physical dice or conduct a coin toss and input the resulting data as either binary (1 or 0) or numbers (1 to 6). This method ensures absolute randomness for generating your mnemonic seed phrase. + 2. Dice Roll From Entropy: For a quicker approach, the program can generate random dice rolls for you. The automated dice roll function guarantees the essential randomness needed for a secure seed phrase. + 3. Mnemonic Seed Generation: After collecting the dice roll data, the program seamlessly proceeds to generate a valid checksum and creates a BIP39 mnemonic seed phrase. This seed phrase forms the cornerstone for generating Bitcoin private keys and public addresses. + 4. Mnemonic Code Converter: The generated mnemonic seed phrase is then processed through the Mnemonic Code Converter, capable of generating BIP39 private keys and public addresses for all script types: Legacy (P2PKH), Nested SegWit (P2SH-P2WPKH), Native SegWit (P2WPKH), and Taproot (P2TR). +- **Seed To Mnemonic:** + 1. Generate Hex Seed From Entropy: The program can generate a Hex seed from entropy. The automated function guarantees the essential randomness required for secure seed generation. + 2. Mnemonic Seed Generation: After collecting the Hex seed, the program seamlessly proceeds to generate a valid checksum and creates a BIP39 mnemonic seed phrase. + 3. Own Mnemonic Seed Phrase: You have the option to enter your own mnemonic seed phrase into the program. + 4. Mnemonic Code Converter: The generated mnemonic seed phrase is then processed through the Mnemonic Code Converter, capable of generating BIP39 private keys and public addresses for all script types: Legacy (P2PKH), Nested SegWit (P2SH-P2WPKH), Native SegWit (P2WPKH), and Taproot (P2TR). - **QR Code Generator:** A built in QR code generator from text. @@ -82,7 +87,7 @@ https://www.python.org/downloads/ https://pip.pypa.io/en/stable/installation/ ``` -3. Clone or download the repository and extract it. +3. Clone or download the repository (Make sure you have the latest release), and extract it. 4. Cloning dependencies, same method for all operating systems: @@ -139,7 +144,7 @@ Now your offline device should have all the required dependencies to run offline ## Demo Video - [![Video](http://img.youtube.com/vi/TV6SB6fHE-s/0.jpg)](http://www.youtube.com/watch?v=TV6SB6fHE-s) + [![Video](http://img.youtube.com/vi/zpM8gb1_vQQ/0.jpg)](https://www.youtube.com/watch?v=zpM8gb1_vQQ) ## Support and Feedback diff --git a/common.py b/common.py index 17f5d23..bd47443 100644 --- a/common.py +++ b/common.py @@ -2,9 +2,10 @@ from mnemonic import Mnemonic import platform import subprocess +import keyboard import os +import locale import datetime -from mnemonic import Mnemonic from bip32utils import BIP32Key import hashlib import binascii @@ -15,13 +16,17 @@ from bitcoinaddress.key.key import Key from bitcoinaddress.address import Address from bitcoinutils.setup import setup -from bitcoinutils.keys import P2pkhAddress, PrivateKey +from bitcoinutils.keys import P2pkhAddress, PrivateKey, PublicKey from art import * import tkinter as tk from tkinter import ttk import qrcode from PIL import Image, ImageTk - + + +# Set the locale to your preferred formatting (e.g., en_US.UTF-8) +locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') + # Functions to print text in color def print_red(*args): text = ' '.join(map(str, args)) @@ -65,6 +70,27 @@ def print_centered_art_text(text, convert, fonttype): # Print centered text tprint(centered_text, font=fonttype) +def maximize_window(): + system = platform.system() + + if system == 'Windows': + # Windows: Send Win + Up Arrow + keyboard.press_and_release('win+up') + elif system == 'Darwin': + # macOS: Send Ctrl + Command + F + keyboard.press_and_release('ctrl+cmd+f') + elif system == 'Linux': + try: + # Linux: Send Alt + F10 (using wmctrl if available) + subprocess.check_output(['wmctrl', '--version']) + subprocess.run(['wmctrl', '-r', ':ACTIVE:', '-b', 'add,maximized_vert,maximized_horz']) + except subprocess.CalledProcessError: + # If wmctrl is not available, send Alt + F10 using keyboard + keyboard.press_and_release('alt+f10') + else: + print(f"Unsupported operating system: {system}") + + # Function to check if a seed phrase is valid def is_valid_seed(seed_phrase): try: diff --git a/diceroll.py b/diceroll.py index c8a3173..aa6297d 100644 --- a/diceroll.py +++ b/diceroll.py @@ -24,10 +24,17 @@ def word_to_binary(word, word_list): binary_representation = bin(index)[2:].zfill(11) return binary_representation +import random + def roll_dice(n): - return [int(random.randint(1, 6) % 2 == 0) for _ in range(n)] # odd numbers are 0, even numbers are 1 -# return [int(random.randint(1, 6) > 3) for _ in range(n)] # You can enable this code to convert from (1, 2 or 3) to 0 and (4, 5 or 6) to 1 - + auto_dice_list = [] + for i in range(10000): + auto_dice = [int(random.randint(1, 1000)) for _ in range(n)] + auto_dice_list.append(auto_dice) + auto_dice = random.choice(auto_dice_list) + auto_dice_binary = [1 if num % 2 == 0 else 0 for num in auto_dice] # odd numbers are converted 0, even numbers are converted 1 + return auto_dice_binary + def roll_dice_auto(num_words): while True: mnemo = Mnemonic("english") @@ -104,7 +111,8 @@ def roll_dice_auto(num_words): print() print_red(f" You've chosen to generate a {num_words}-word mnemonic seed phrase." f"\n This requires rolling {mnemonic_bits} bits randomly and calculating {bit_checksum} bits for a valid checksum, totaling {total_bits} bits." - f"\n The dice will be rolled {mnemonic_bits} times.") + f"\n For each bit in the {mnemonic_bits} bits, a 1,000-sided dice will be roll 10,000 times and the results will be stored in a list." + f"\n Subsequently, a random number will be selected from the list and transformed into 0 if it's odd or 1 if it's even.") print() # Print the appended messages if the seed is valid for msg in print_list_blue[:-3]: @@ -115,8 +123,6 @@ def roll_dice_auto(num_words): for msg in print_list_blue[-3:]: print_blue(msg) return mnemonic - - def roll_dice_manual_binary(num_words): mnemo = Mnemonic("english") diff --git a/mccmainnet.py b/mccmainnet.py index 2f5bc90..0d92e74 100644 --- a/mccmainnet.py +++ b/mccmainnet.py @@ -109,30 +109,40 @@ def generate_mainnet_addresses(seed_phrase, num_child_keys, passphrase): TaprootWIFR = address_key_taprootR.WalletImportFormat() TaprootWIFC = address_key_taprootC.WalletImportFormat() - # Pubic addresses + # Public Keys setup("mainnet") - LegacyR = PrivateKey(LegacyWIFR).get_public_key().get_address().to_string() - LegacyC = PrivateKey(LegacyWIFC).get_public_key().get_address().to_string() - NestedR = generate_p2sh_p2wpkh_address(address_key_nestedR.PublicKey()) - NestedC = generate_p2sh_p2wpkh_address(address_key_nestedC.PublicKey()) - NativeR = PrivateKey(NativeWIFR).get_public_key().get_segwit_address().to_string() - NativeC = PrivateKey(NativeWIFC).get_public_key().get_segwit_address().to_string() - TaprootR = PrivateKey(TaprootWIFR).get_public_key().get_taproot_address().to_string() - TaprootC = PrivateKey(TaprootWIFC).get_public_key().get_taproot_address().to_string() + LegacyPKR = PrivateKey(LegacyWIFR).get_public_key().to_hex(compressed=True) + LegacyPKC = PrivateKey(LegacyWIFC).get_public_key().to_hex(compressed=True) + NestedPKR = binascii.hexlify(address_key_nestedR.PublicKey()).decode('utf-8') + NestedPKC = binascii.hexlify(address_key_nestedC.PublicKey()).decode('utf-8') + NativePKR = PrivateKey(NativeWIFR).get_public_key().to_hex(compressed=True) + NativePKC = PrivateKey(NativeWIFC).get_public_key().to_hex(compressed=True) + TaprootPKR = PrivateKey(TaprootWIFR).get_public_key().to_hex(compressed=True) + TaprootPKC = PrivateKey(TaprootWIFC).get_public_key().to_hex(compressed=True) + + # Pubic addresses + LegacyAddR = PublicKey(LegacyPKR).get_address().to_string() + LegacyAddC = PublicKey(LegacyPKC).get_address().to_string() + NestedAddR = generate_p2sh_p2wpkh_address(address_key_nestedR.PublicKey()) + NestedAddC = generate_p2sh_p2wpkh_address(address_key_nestedC.PublicKey()) + NativeAddR = PublicKey(NativePKR).get_segwit_address().to_string() + NativeAddC = PublicKey(NativePKC).get_segwit_address().to_string() + TaprootAddR = PublicKey(TaprootPKR).get_taproot_address().to_string() + TaprootAddC = PublicKey(TaprootPKC).get_taproot_address().to_string() # Append keys, addresses & WIFs to addresses lists - addresses["Legacy (P2PKH)R"].append((xprv_root_key, legacy_acc_ext_xpub_key, "", "44", LegacyR, LegacyWIFR)) - addresses["Legacy (P2PKH)C"].append(("44", LegacyC, LegacyWIFC)) - addresses["Nested SegWit (P2SH-P2WPKH)R"].append((yprv_root_key, nested_acc_ext_xpub_key, nested_acc_ext_ypub_key, "49", NestedR, NestedWIFR)) - addresses["Nested SegWit (P2SH-P2WPKH)C"].append(("49", NestedC, NestedWIFC)) - addresses["Native SegWit (P2WPKH)R"].append((zprv_root_key, native_acc_ext_xpub_key, native_acc_ext_zpub_key, "84", NativeR, NativeWIFR)) - addresses["Native SegWit (P2WPKH)C"].append(("84", NativeC, NativeWIFC)) - addresses["Taproot (P2TR)R"].append((xprv_root_key, taproot_acc_ext_xpub_key, "", "86", TaprootR, TaprootWIFR)) - addresses["Taproot (P2TR)C"].append(("86", TaprootC, TaprootWIFC)) + addresses["Legacy (P2PKH)R"].append((xprv_root_key, legacy_acc_ext_xpub_key, "", "44", LegacyAddR, LegacyPKR, LegacyWIFR)) + addresses["Legacy (P2PKH)C"].append(("44", LegacyAddC, LegacyPKC, LegacyWIFC)) + addresses["Nested SegWit (P2SH-P2WPKH)R"].append((yprv_root_key, nested_acc_ext_xpub_key, nested_acc_ext_ypub_key, "49", NestedAddR, NestedPKR, NestedWIFR)) + addresses["Nested SegWit (P2SH-P2WPKH)C"].append(("49", NestedAddC, NestedPKC, NestedWIFC)) + addresses["Native SegWit (P2WPKH)R"].append((zprv_root_key, native_acc_ext_xpub_key, native_acc_ext_zpub_key, "84", NativeAddR, NativePKR, NativeWIFR)) + addresses["Native SegWit (P2WPKH)C"].append(("84", NativeAddC, NativePKC, NativeWIFC)) + addresses["Taproot (P2TR)R"].append((xprv_root_key, taproot_acc_ext_xpub_key, "", "86", TaprootAddR, TaprootPKR, TaprootWIFR)) + addresses["Taproot (P2TR)C"].append(("86", TaprootAddC, TaprootPKC, TaprootWIFC)) return addresses, bip39_root_key -def print_address_details(script_type, addresses): +def print_address_details(script_type, addresses, is_full): print() print() @@ -151,75 +161,57 @@ def print_address_details(script_type, addresses): print_green(f" Acc. Ext. Pub. Key: {extpubkey2}") format_info = { - "Legacy (P2PKH)": (38, 111), - "Nested SegWit (P2SH-P2WPKH)": (38, 111), - "Native SegWit (P2WPKH)": (46, 119), - "Taproot (P2TR)": (66, 139) + "Legacy (P2PKH)": (37, 111) if not is_full else (38, 182), + "Nested SegWit (P2SH-P2WPKH)": (37, 111) if not is_full else (38, 182), + "Native SegWit (P2WPKH)": (45, 119) if not is_full else (46, 190), + "Taproot (P2TR)": (65, 139) if not is_full else (66, 210) } if script_type in format_info: - address_width, line_width = format_info[script_type] + address_width, line_width = format_info[script_type] header_template = f" Derivation Path".ljust(28) address_template = "Bitcoin Address".ljust(address_width) wif_template = "Private Key / WIF (Wallet Import Format)" + pk_template = "Public Key".ljust(70) if is_full else "" print_purple(" Receive Addresses:") - print_cyan(f"{header_template} {address_template} {wif_template}") + print_cyan(f"{header_template} {address_template} {pk_template} {wif_template}") print_cyan(f" " + "-" * line_width) - for index, (rootkey, extpubkey1, extpubkey2, BIP, address, wif) in enumerate(addresses[f'{script_type}R']): + for index, (rootkey, extpubkey1, extpubkey2, BIP, address, PK, wif) in enumerate(addresses[f'{script_type}R']): path = f" m/{BIP}'/0'/0'/0/{index}".ljust(20) address = address.ljust(address_width) - print(f" {path} {address} {wif}") + pk = PK.ljust(70) if is_full else "" + print(f" {path} {address} {pk} {wif}") print() print_purple(" Change Addresses:") - print_cyan(f"{header_template} {address_template} {wif_template}") + print_cyan(f"{header_template} {address_template} {pk_template} {wif_template}") print_cyan(f" " + "-" * line_width) - for index, (BIP, address, wif) in enumerate(addresses[f'{script_type}C']): + for index, (BIP, address, PK, wif) in enumerate(addresses[f'{script_type}C']): path = f" m/{BIP}'/0'/0'/1/{index}".ljust(20) address = address.ljust(address_width) - print(f" {path} {address} {wif}") + pk = PK.ljust(70) if is_full else "" + print(f" {path} {address} {pk} {wif}") # Function to generate wallets -def generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase): +def generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase, list_type): if is_valid_seed(seed_phrase): #Recheck if the mnemonic seed phrase is valid seed = Mnemonic("english").to_seed(seed_phrase, passphrase=passphrase) hex_seed = binascii.hexlify(seed).decode('utf-8') - # Format Information box - creator_info = f"Created By : Sani Fahs" - twitter_info = f"Twitter : @SaniExp" - github_info = f"GitHub : https://github.com/FahsSani" - lightning_info = f"Lightning Donations : sani@walletofsatoshi.com" - max_info_length = max(len(creator_info), len(twitter_info), len(github_info), len(lightning_info)) - box_width = max_info_length + 4 # Adjust the box width based on the max info length - info_box = " " + "+" + "-" * (box_width - 2) + "+" - info_box += f"\n | {creator_info.ljust(max_info_length)} |" - info_box += f"\n | {twitter_info.ljust(max_info_length)} |" - info_box += f"\n | {github_info.ljust(max_info_length)} |" - info_box += f"\n | {lightning_info.ljust(max_info_length)} |" - info_box += "\n +" + "-" * (box_width - 2) + "+" - addresses, bip39_root_key = generate_mainnet_addresses(seed_phrase, num_child_keys, passphrase=passphrase) - # Clear terminal - clear_terminal() - - # Print title - text3 = "* ROLL TO MNEMONIC *" - print_centered_art_text(text3, 5, "Standard") - - # Print data - print_bright_orange(info_box) - print() - print_red(" Mnemonic Seed Phrase:", seed_phrase) - print_red(" Passphrase :", passphrase) + print_red(f"\n Mnemonic Seed Phrase: {seed_phrase}") + print_red(f" Passphrase : {passphrase}") print_red(" BIP39 Seed Hex :", hex_seed) for script_type in ["Legacy (P2PKH)", "Nested SegWit (P2SH-P2WPKH)", "Native SegWit (P2WPKH)", "Taproot (P2TR)"]: - print_address_details(script_type, addresses) + if list_type == "AddMain": + print_address_details(script_type, addresses, is_full=False) + else: + print_address_details(script_type, addresses, is_full=True) print() print_red(" To verify the mnemonic seed phrase, keys and addresses, visit: https://iancoleman.io/bip39/") diff --git a/mcctestnet.py b/mcctestnet.py index 37d8189..cf37c29 100644 --- a/mcctestnet.py +++ b/mcctestnet.py @@ -109,35 +109,45 @@ def generate_testnet_addresses(seed_phrase, num_child_keys, passphrase): TaprootWIFR = address_key_taprootR.WalletImportFormat() TaprootWIFC = address_key_taprootC.WalletImportFormat() + # Public Keys + setup("testnet") + LegacyPKR = PrivateKey(LegacyWIFR).get_public_key().to_hex(compressed=True) + LegacyPKC = PrivateKey(LegacyWIFC).get_public_key().to_hex(compressed=True) + NestedPKR = binascii.hexlify(address_key_nestedR.PublicKey()).decode('utf-8') + NestedPKC = binascii.hexlify(address_key_nestedC.PublicKey()).decode('utf-8') + NativePKR = PrivateKey(NativeWIFR).get_public_key().to_hex(compressed=True) + NativePKC = PrivateKey(NativeWIFC).get_public_key().to_hex(compressed=True) + TaprootPKR = PrivateKey(TaprootWIFR).get_public_key().to_hex(compressed=True) + TaprootPKC = PrivateKey(TaprootWIFC).get_public_key().to_hex(compressed=True) + # Pubic addresses - setup("testnet") # Use testnet setup - LegacyR = PrivateKey(LegacyWIFR).get_public_key().get_address().to_string() - LegacyC = PrivateKey(LegacyWIFC).get_public_key().get_address().to_string() - NestedR = generate_p2sh_p2wpkh_address(address_key_nestedR.PublicKey()) - NestedC = generate_p2sh_p2wpkh_address(address_key_nestedC.PublicKey()) - NativeR = PrivateKey(NativeWIFR).get_public_key().get_segwit_address().to_string() - NativeC = PrivateKey(NativeWIFC).get_public_key().get_segwit_address().to_string() - TaprootR = PrivateKey(TaprootWIFR).get_public_key().get_taproot_address().to_string() - TaprootC = PrivateKey(TaprootWIFC).get_public_key().get_taproot_address().to_string() + LegacyAddR = PublicKey(LegacyPKR).get_address().to_string() + LegacyAddC = PublicKey(LegacyPKC).get_address().to_string() + NestedAddR = generate_p2sh_p2wpkh_address(address_key_nestedR.PublicKey()) + NestedAddC = generate_p2sh_p2wpkh_address(address_key_nestedC.PublicKey()) + NativeAddR = PublicKey(NativePKR).get_segwit_address().to_string() + NativeAddC = PublicKey(NativePKC).get_segwit_address().to_string() + TaprootAddR = PublicKey(TaprootPKR).get_taproot_address().to_string() + TaprootAddC = PublicKey(TaprootPKC).get_taproot_address().to_string() # Append keys, addresses & WIFs to addresses lists - addresses["Legacy (P2PKH)R"].append((tprv_root_key, legacy_acc_ext_tpub_key, "", "44", LegacyR, LegacyWIFR)) - addresses["Legacy (P2PKH)C"].append(("44", LegacyC, LegacyWIFC)) - addresses["Nested SegWit (P2SH-P2WPKH)R"].append((uprv_root_key, nested_acc_ext_tpub_key, nested_acc_ext_upub_key, "49", NestedR, NestedWIFR)) - addresses["Nested SegWit (P2SH-P2WPKH)C"].append(("49", NestedC, NestedWIFC)) - addresses["Native SegWit (P2WPKH)R"].append((vprv_root_key, native_acc_ext_tpub_key, native_acc_ext_vpub_key, "84", NativeR, NativeWIFR)) - addresses["Native SegWit (P2WPKH)C"].append(("84", NativeC, NativeWIFC)) - addresses["Taproot (P2TR)R"].append((tprv_root_key, taproot_acc_ext_tpub_key, "", "86", TaprootR, TaprootWIFR)) - addresses["Taproot (P2TR)C"].append(("86", TaprootC, TaprootWIFC)) + addresses["Legacy (P2PKH)R"].append((tprv_root_key, legacy_acc_ext_tpub_key, "", "44", LegacyAddR, LegacyPKR, LegacyWIFR)) + addresses["Legacy (P2PKH)C"].append(("44", LegacyAddC, LegacyPKC, LegacyWIFC)) + addresses["Nested SegWit (P2SH-P2WPKH)R"].append((uprv_root_key, nested_acc_ext_tpub_key, nested_acc_ext_upub_key, "49", NestedAddR, NestedPKR, NestedWIFR)) + addresses["Nested SegWit (P2SH-P2WPKH)C"].append(("49", NestedAddC, NestedPKC, NestedWIFC)) + addresses["Native SegWit (P2WPKH)R"].append((vprv_root_key, native_acc_ext_tpub_key, native_acc_ext_vpub_key, "84", NativeAddR, NativePKR, NativeWIFR)) + addresses["Native SegWit (P2WPKH)C"].append(("84", NativeAddC, NativePKC, NativeWIFC)) + addresses["Taproot (P2TR)R"].append((tprv_root_key, taproot_acc_ext_tpub_key, "", "86", TaprootAddR, TaprootPKR, TaprootWIFR)) + addresses["Taproot (P2TR)C"].append(("86", TaprootAddC, TaprootPKC, TaprootWIFC)) return addresses, bip39_root_key -def print_address_details(script_type, addresses): +def print_address_details(script_type, addresses, is_full): print() print() - + if script_type == "Legacy (P2PKH)": - print_bright_orange(" BITCOIN - TESTNET:") + print_bright_orange(" BITCOIN - MAINNET:") print_bright_orange(" " + "-" * 18) print_blue(f" Script Type - {script_type}:") @@ -151,75 +161,57 @@ def print_address_details(script_type, addresses): print_green(f" Acc. Ext. Pub. Key: {extpubkey2}") format_info = { - "Legacy (P2PKH)": (38, 111), - "Nested SegWit (P2SH-P2WPKH)": (38, 111), - "Native SegWit (P2WPKH)": (46, 119), - "Taproot (P2TR)": (66, 139) + "Legacy (P2PKH)": (37, 111) if not is_full else (38, 182), + "Nested SegWit (P2SH-P2WPKH)": (37, 111) if not is_full else (38, 182), + "Native SegWit (P2WPKH)": (45, 119) if not is_full else (46, 190), + "Taproot (P2TR)": (65, 139) if not is_full else (66, 210) } if script_type in format_info: - address_width, line_width = format_info[script_type] + address_width, line_width = format_info[script_type] header_template = f" Derivation Path".ljust(28) address_template = "Bitcoin Address".ljust(address_width) wif_template = "Private Key / WIF (Wallet Import Format)" + pk_template = "Public Key".ljust(70) if is_full else "" print_purple(" Receive Addresses:") - print_cyan(f"{header_template} {address_template} {wif_template}") + print_cyan(f"{header_template} {address_template} {pk_template} {wif_template}") print_cyan(f" " + "-" * line_width) - for index, (rootkey, extpubkey1, extpubkey2, BIP, address, wif) in enumerate(addresses[f'{script_type}R']): + for index, (rootkey, extpubkey1, extpubkey2, BIP, address, PK, wif) in enumerate(addresses[f'{script_type}R']): path = f" m/{BIP}'/1'/0'/0/{index}".ljust(20) address = address.ljust(address_width) - print(f" {path} {address} {wif}") + pk = PK.ljust(70) if is_full else "" + print(f" {path} {address} {pk} {wif}") print() print_purple(" Change Addresses:") - print_cyan(f"{header_template} {address_template} {wif_template}") + print_cyan(f"{header_template} {address_template} {pk_template} {wif_template}") print_cyan(f" " + "-" * line_width) - for index, (BIP, address, wif) in enumerate(addresses[f'{script_type}C']): + for index, (BIP, address, PK, wif) in enumerate(addresses[f'{script_type}C']): path = f" m/{BIP}'/1'/0'/1/{index}".ljust(20) address = address.ljust(address_width) - print(f" {path} {address} {wif}") + pk = PK.ljust(70) if is_full else "" + print(f" {path} {address} {pk} {wif}") # Function to generate testnet wallets -def generate_testnet_wallet(seed_phrase, num_child_keys, passphrase): +def generate_testnet_wallet(seed_phrase, num_child_keys, passphrase, list_type): if is_valid_seed(seed_phrase): #Recheck if the mnemonic seed phrase is valid seed = Mnemonic("english").to_seed(seed_phrase, passphrase=passphrase) hex_seed = binascii.hexlify(seed).decode('utf-8') - # Format Information box - creator_info = f"Created By : Sani Fahs" - twitter_info = f"Twitter : @SaniExp" - github_info = f"GitHub : https://github.com/FahsSani" - lightning_info = f"Lightning Donations : sani@walletofsatoshi.com" - max_info_length = max(len(creator_info), len(twitter_info), len(github_info), len(lightning_info)) - box_width = max_info_length + 4 # Adjust the box width based on the max info length - info_box = " " + "+" + "-" * (box_width - 2) + "+" - info_box += f"\n | {creator_info.ljust(max_info_length)} |" - info_box += f"\n | {twitter_info.ljust(max_info_length)} |" - info_box += f"\n | {github_info.ljust(max_info_length)} |" - info_box += f"\n | {lightning_info.ljust(max_info_length)} |" - info_box += "\n +" + "-" * (box_width - 2) + "+" - addresses, bip39_root_key = generate_testnet_addresses(seed_phrase, num_child_keys, passphrase=passphrase) - # Clear terminal - clear_terminal() - - # Print title - text3 = "* ROLL TO MNEMONIC *" - print_centered_art_text(text3, 5, "Standard") - - # Print data - print_bright_orange(info_box) - print() - print_red(" Mnemonic Seed Phrase:", seed_phrase) - print_red(" Passphrase :", passphrase) + print_red(f"\n Mnemonic Seed Phrase: {seed_phrase}") + print_red(f" Passphrase : {passphrase}") print_red(" BIP39 Seed Hex :", hex_seed) for script_type in ["Legacy (P2PKH)", "Nested SegWit (P2SH-P2WPKH)", "Native SegWit (P2WPKH)", "Taproot (P2TR)"]: - print_address_details(script_type, addresses) + if list_type == "AddMain": + print_address_details(script_type, addresses, is_full=False) + else: + print_address_details(script_type, addresses, is_full=True) print() print_red(" To verify the mnemonic seed phrase, keys and addresses, visit: https://iancoleman.io/bip39/") diff --git a/requirements.txt b/requirements.txt index 89773f8..10485a8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,5 @@ bech32>=1.2.0 bitcoinaddress==0.1.5 bitcoin-utils==0.6.3 art>=6.0 -qrcode[pil]>=7.4.2 \ No newline at end of file +qrcode[pil]>=7.4.2 +keyboard>=0.13.5 \ No newline at end of file diff --git a/start.py b/start.py index c312ad2..e4feea2 100644 --- a/start.py +++ b/start.py @@ -29,40 +29,59 @@ def disclaimer(): """) def foot_note(): - print( - " For binary to decimal conversion verification, visit: https://www.rapidtables.com/convert/number/binary-to-decimal.html") - print( - " To cross-check decimal to index/word conversion, visit: https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt") - print(" For confirming your mnemonic seed phrase, visit: https://iancoleman.io/bip39/") - print( - " Please note that binary numbers start from 0, while the BIP39 wordlist starts from 1, so remember to add 1 to the decimal result to match the word.") + print(f"\n To confirm binary to decimal conversion, visit: https://www.rapidtables.com/convert/number/binary-to-decimal.html") + print(" To cross-check decimal to index/word conversion, visit: https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt") + print(" To confirm your mnemonic seed phrase, visit: https://iancoleman.io/bip39/") + print(" Please note that binary numbers start from 0, while the BIP39 wordlist starts from 1, so remember to add 1 to the decimal result to match the word.") def enable_buttons(): - generate_manual_button.config(state="normal") - generate_random_button.config(state="normal") - continue_button.config(state="normal") + start_dice_button.config(state="normal") + continue_button.config(state="normal") + continue_button2.config(state="normal") result_label.config(text="") + result_label2.config(text="") def disable_buttons(): - generate_random_button.config(state="disabled") - generate_manual_button.config(state="disabled") - continue_button.config(state="disabled") - result_label.config(text="The 'Generate' buttons are temporarily disabled to prevent potential errors.\n Functionality will be reactivated once you've completed entering the numbers.") + start_dice_button.config(state="disabled") + continue_button.config(state="disabled") + continue_button2.config(state="disabled") + result_label.config(text="Buttons are temporarily disabled to prevent potential errors.\n Functionality will be reactivated once you've completed Dice Roll.") + result_label2.config(text="Buttons are temporarily disabled to prevent potential errors.\n Functionality will be reactivated once you've completed Dice Roll.") + +def on_own_dice_select(): + dice_choice_binary.config(state="normal") + dice_choice_dice.config(state="normal") + +def on_entropy_dice_select(): + dice_choice_binary.config(state="disabled") + dice_choice_dice.config(state="disabled") + +def on_own_mnemonic_select(): + frame12.grid_remove() + frame13.grid() + frame14.grid_remove() + result_label2.config(text="") + +def on_entropy_mnemonic_select(): + frame12.grid() + frame13.grid_remove() + frame14.grid() + result_label2.config(text="") # Function to generate QR code def generate_qr_code(): - text = qr_text_entry.get("1.0", "end-1c") + text = qr_text_entry.get("1.0", "end-1c") # Get all text from the Text widget if text: qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, - box_size=10, - border=4, + box_size=5, + border=2, ) qr.add_data(text) qr.make(fit=True) qr_img = qr.make_image(fill_color="black", back_color="white") - qr_img = qr_img.resize((270, 270)) # Resize the image if needed + qr_img = qr_img.resize((250, 250)) # Resize the image if needed # Convert the PIL image to a PhotoImage object qr_photo = ImageTk.PhotoImage(qr_img) @@ -82,10 +101,22 @@ def clear_qr_code(): qr_code_label.image = None qr_text_entry.delete("1.0", "end") +def format_with_thousand_separator(value): + return locale.format_string("%d", value, grouping=True) + +def on_entry_change(event): + try: + value = int(entropy_entry2.get().replace(',', '')) + formatted_value = format_with_thousand_separator(value) + entropy_entry2.delete(0, tk.END) + entropy_entry2.insert(0, formatted_value) + except ValueError: + pass + def main(): # Clear terminal clear_terminal() - + # Print title text2 = "* ROLL TO MNEMONIC *" print_centered_art_text(text2, 5, "Standard") @@ -96,7 +127,7 @@ def main(): github_info = f"GitHub : https://github.com/FahsSani" lightning_info = f"Lightning Donations : sani@walletofsatoshi.com" max_info_length = max(len(creator_info), len(twitter_info), len(github_info), len(lightning_info)) - box_width = max_info_length + 4 + box_width = max_info_length + 4 info_box = " " + "+" + "-" * (box_width - 2) + "+" info_box += f"\n | {creator_info.ljust(max_info_length)} |" info_box += f"\n | {twitter_info.ljust(max_info_length)} |" @@ -105,63 +136,129 @@ def main(): info_box += "\n +" + "-" * (box_width - 2) + "+" print_bright_orange(info_box) -def generate_random_dice_numbers(): - main() - global seed_phrase - num_words = int(num_words_var.get()) - mnemonic_seed = roll_dice_auto(num_words) - seed_phrase = ' '.join(mnemonic_seed) - print_green(f"\n Mnemonic Seed Phrase: {seed_phrase}\n") - foot_note() - continue_button.config(state="normal") - result_label.config(text="") - -def generate_manual_dice_numbers(): +def start_dice(): + global seed_phrase main() - global seed_phrase + dice = dice_type.get() num_words = int(num_words_var.get()) - choice = dice_choice_var.get() - if choice == "Binary": - disable_buttons() - mnemonic_seed = roll_dice_manual_binary(num_words) - enable_buttons() - seed_phrase = ' '.join(mnemonic_seed) - print_green(f"\n Mnemonic Seed Phrase: {seed_phrase}\n") - foot_note() - result_label.config(text="") - else: - disable_buttons() - mnemonic_seed = roll_dice_manual_num(num_words) - enable_buttons() - seed_phrase = ' '.join(mnemonic_seed) - print_green(f"\n Mnemonic Seed Phrase: {seed_phrase}\n") - foot_note() + if dice == "Entropy": + mnemonic_seed = roll_dice_auto(num_words) + continue_button.config(state="normal") result_label.config(text="") + elif dice == "Own": + choice = dice_choice_var.get() + if choice == "Binary": + disable_buttons() + mnemonic_seed = roll_dice_manual_binary(num_words) + enable_buttons() + else: + disable_buttons() + mnemonic_seed = roll_dice_manual_num(num_words) + enable_buttons() + + seed_phrase = ' '.join(mnemonic_seed) + print_green(f"\n Mnemonic Seed Phrase: {seed_phrase}") + foot_note() + result_label.config(text="Dice Roll Completed Successfully.") + def mnemonic_converter(): global seed_phrase passphrase = passphrase_entry.get().strip() - + list_type = add_list_type_var.get() try: num_child_keys = int(child_keys_entry.get()) if 1 <= num_child_keys <= 25: - network_type = network_type_var.get() + network_type = network_type_var.get() + result_label.config(text="Mnemonic Seed Phrase Generated Successfully.") if network_type == "Mainnet": - generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase) + generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase, list_type) elif network_type == "Testnet": - generate_testnet_wallet(seed_phrase, num_child_keys, passphrase) + generate_testnet_wallet(seed_phrase, num_child_keys, passphrase, list_type) else: result_label.config(text="Invalid number of child keys. Must be between 1 and 25.") except ValueError: result_label.config(text="Invalid number of child keys. Must be an integer.") +def mnemonic_converter2(): + main() + passphrase = passphrase_entry2.get().strip() + num_words = int(num_words_var2.get()) + mnemonic_type2_value = mnemonic_type2.get() + list_type = add_list_type2_var.get() + + if mnemonic_type2_value == "Entropy": + try: + num_child_keys = int(child_keys_entry2.get()) + if 1 <= num_child_keys <= 25: + try: + entropy_generation = int(entropy_entry2.get().replace(',', '')) + if 1000 <= entropy_generation <= 10000000: + entropy_lengths = {"12": 128, "15": 160, "18": 192, "21": 224, "24": 256} + entropy_bytes = entropy_lengths.get(str(num_words)) + + random_data_list = [os.urandom(entropy_bytes // 8) for _ in range(entropy_generation)] + print(f"\n Generating a list of {entropy_generation:,} random Hex entropies.") + entropy_display = display_entropy2.get() + if entropy_display == "Display": + for i, entropy in enumerate(random_data_list): + print(f" Entropy {i + 1:,}: {entropy.hex()}") + while True: + chosen_entropy = random.choice(random_data_list) + print(f"\n Choosing a random Hex entropy from the list.") + if entropy_display == "Display": + print(f" Entropy {random_data_list.index(chosen_entropy) + 1:,}: {chosen_entropy.hex()} has been chosen.\n") + mnemonic = Mnemonic("english") + seed_phrase = mnemonic.to_mnemonic(chosen_entropy) + + if is_valid_seed(seed_phrase): + result_label2.config(text="Mnemonic Seed Phrase Generated Successfully.") + network_type = network_type2_var.get() + if network_type == "Mainnet": + generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase, list_type) + elif network_type == "Testnet": + generate_testnet_wallet(seed_phrase, num_child_keys, passphrase, list_type) + return + else: + result_label2.config(text="Invalid number of entropies, must be between 10,000 and 10,000,000.") + except ValueError: + result_label2.config(text="Invalid number of entropies, must be an integer.") + else: + result_label2.config(text="Invalid number of child keys, must be between 1 and 25.") + except ValueError: + result_label2.config(text="Invalid number of child keys, must be an integer.") + + else: + seed_phrase = frame13_entry.get("1.0", "end-1c") + try: + num_child_keys = int(child_keys_entry2.get()) + if 1 <= num_child_keys <= 25: + try: + if is_valid_seed(seed_phrase): + result_label2.config(text="Mnemonic Seed Phrase Generated Successfully.") + network_type = network_type2_var.get() + if network_type == "Mainnet": + generate_mainnet_wallet(seed_phrase, num_child_keys, passphrase, list_type) + elif network_type == "Testnet": + generate_testnet_wallet(seed_phrase, num_child_keys, passphrase, list_type) + else: + result_label2.config(text="Invalid Mnemonic Seed Phrase, make sure that the seed phrase is valid" + "\nand that there are no spaces before or after the seed phrase.") + except Exception as e: + result_label2.config(text=f"An error occurred while generating the wallet: {str(e)}") + else: + result_label2.config(text="Invalid number of child keys, must be between 1 and 25.") + except ValueError: + result_label2.config(text="Invalid number of child keys, must be an integer.") + +maximize_window() disclaimer() # Create the main window root = tk.Tk() root.title("Roll2Mnemonic") -root.geometry("455x530") +root.geometry("450x480") # Create tabs notebook = ttk.Notebook(root) @@ -169,86 +266,189 @@ def mnemonic_converter(): # Create tab 1: Dice Roll tab1 = tk.Frame(notebook) -notebook.add(tab1, text="Dice Roll & Mnemonic Code Converter") +notebook.add(tab1, text="Dice Roll To Mnemonic") + +frame0 = tk.LabelFrame(tab1, text="Dice Roll Type", labelanchor="n") +frame0.grid(row=0, column=0, columnspan=12, padx=10, pady=5) +dice_type = tk.StringVar() +dice_type.set("Entropy") +dice_type_entropy = tk.Radiobutton(frame0, text="Generate From Entropy", variable=dice_type, value="Entropy") +dice_type_own = tk.Radiobutton(frame0, text="Enter Your Own Numbers", variable=dice_type, value="Own") +dice_type_entropy.grid(row=0, column=0, padx=10, pady=0) +dice_type_own.grid(row=0, column=1, padx=10, pady=0) +dice_type_own.bind("", lambda event: on_own_dice_select()) +dice_type_entropy.bind("", lambda event: on_entropy_dice_select()) frame1 = tk.LabelFrame(tab1, text="Mnemonic Seed Phrase Word Count", labelanchor="n") -frame1.grid(row=0, column=0, columnspan=5, padx=10, pady=10) +frame1.grid(row=1, column=0, columnspan=12, padx=10, pady=5) num_words_var = tk.IntVar() num_words_var.set(12) - mnemonic_words = [12, 15, 18, 21, 24] - for i, word_count in enumerate(mnemonic_words): num_words_button = tk.Radiobutton(frame1, text=str(word_count) + " Words", variable=num_words_var, value=word_count, command=lambda count=word_count: num_words_var.set(count)) num_words_button.grid(row=0, column=i + 2, padx=4, pady=0) -frame2 = tk.LabelFrame(tab1, text="Choose Manual Dice Input Type", padx=10, pady=1, labelanchor="n") -frame2.grid(row=1, column=0, columnspan=2, padx=10, pady=10) - +frame2 = tk.LabelFrame(tab1, text="Choose Input Type", padx=10, pady=0, labelanchor="n") +frame2.grid(row=2, column=0, columnspan=12, padx=10, pady=5) dice_choice_var = tk.StringVar() dice_choice_var.set("Binary") dice_choice_binary = tk.Radiobutton(frame2, text="Binary/Coin Toss", variable=dice_choice_var, value="Binary") dice_choice_dice = tk.Radiobutton(frame2, text="6-sided Dice Roll", variable=dice_choice_var, value="Dice") -dice_choice_binary.grid(row=0, column=0, padx=5, pady=0) -dice_choice_dice.grid(row=0, column=1, padx=5, pady=0) +dice_choice_binary.grid(row=0, column=0, padx=4, pady=0) +dice_choice_dice.grid(row=0, column=1, padx=4, pady=0) -generate_random_button = tk.Button(tab1, text="Generate Random Dice Numbers", command=generate_random_dice_numbers) -generate_manual_button = tk.Button(tab1, text="Generate Manual Dice Numbers", command=generate_manual_dice_numbers) -generate_random_button.grid(row=2, column=0, padx=22, pady=10) -generate_manual_button.grid(row=2, column=1, padx=22, pady=10) +start_dice_button = tk.Button(tab1, text="Start Dice Roll", command=start_dice) +start_dice_button.grid(row=3, column=0, columnspan=12, padx=10, pady=5) -frame3 = tk.LabelFrame(tab1, text="Passphrase (optional)", padx=10, pady=10, labelanchor="n") -frame3.grid(row=4, column=0, columnspan=10, padx=10, pady=10) - -passphrase_entry = tk.Entry(frame3) +frame3 = tk.LabelFrame(tab1, text="Passphrase (optional)", padx=10, pady=5, labelanchor="n") +frame3.grid(row=4, column=0, columnspan=1, padx=26, pady=0) +passphrase_entry = tk.Entry(frame3, justify="center") passphrase_entry.grid(row=0, column=1) -passphrase_entry.config(width=40) +passphrase_entry.config(width=25) -frame4 = tk.LabelFrame(tab1, text="Number of Child Keys (1-25)", padx=10, pady=10, labelanchor="n") -frame4.grid(row=5, column=0, columnspan=10, padx=10, pady=10) +frame4 = tk.LabelFrame(tab1, text="Number Of Child Keys (1-25)", padx=10, pady=5, labelanchor="n") +frame4.grid(row=4, column=1, columnspan=1, padx=10, pady=10) child_keys_entry = tk.Entry(frame4, justify="center") -child_keys_entry.insert(0, "5") +child_keys_entry.insert(0, "5") child_keys_entry.grid(row=0, column=1) -child_keys_entry.config(width=25) - -frame5 = tk.LabelFrame(tab1, text="Choose Network Type", padx=10, pady=0, labelanchor="n") -frame5.grid(row=6, column=0, columnspan=2, padx=10, pady=10) +child_keys_entry.config(width=25) + +frame5 = tk.LabelFrame(tab1, text="Addresses Details", padx=10, pady=0, labelanchor="n") +frame5.grid(row=5, column=0, columnspan=12, padx=10, pady=6) +add_list_type_var = tk.StringVar() +add_list_type_var.set("AddMain") +add_list_type_addmain = tk.Radiobutton(frame5, text="Addresses & Private Keys", variable=add_list_type_var, value="AddMain") +add_list_type_addfull = tk.Radiobutton(frame5, text="Addresses & Public/Private Keys", variable=add_list_type_var, value="AddFull") +add_list_type_addmain.grid(row=0, column=0, padx=5, pady=0) +add_list_type_addfull.grid(row=0, column=1, padx=5, pady=0) + +frame6 = tk.LabelFrame(tab1, text="Choose Network Type", padx=10, pady=0, labelanchor="n") +frame6.grid(row=6, column=0, columnspan=12, padx=10, pady=0) network_type_var = tk.StringVar() network_type_var.set("Mainnet") -network_type_mainnet = tk.Radiobutton(frame5, text="Mainnet", variable=network_type_var, value="Mainnet") -network_type_testnet = tk.Radiobutton(frame5, text="Testnet", variable=network_type_var, value="Testnet") -network_type_mainnet.grid(row=0, column=0, padx=5, pady=1) -network_type_testnet.grid(row=0, column=1, padx=5, pady=1) +network_type_mainnet = tk.Radiobutton(frame6, text="Mainnet", variable=network_type_var, value="Mainnet") +network_type_testnet = tk.Radiobutton(frame6, text="Testnet", variable=network_type_var, value="Testnet") +network_type_mainnet.grid(row=0, column=0, padx=5, pady=0) +network_type_testnet.grid(row=0, column=1, padx=5, pady=0) -continue_button = tk.Button(tab1, text="Mnemonic Code Converter", command=mnemonic_converter) -continue_button.grid(row=7, column=0, columnspan=2, padx=10, pady=10) +continue_button = tk.Button(tab1, text="Generate Keys & Addresses", command=mnemonic_converter) +continue_button.grid(row=7, column=0, columnspan=12, padx=10, pady=10) -result_label = tk.Label(tab1, text="", padx=10, pady=20, fg="red") -result_label.grid(row=8, column=0, columnspan=2) +result_label = tk.Label(tab1, text="", padx=10, pady=5, fg="red") +result_label.grid(row=8, column=0, columnspan=12) -# Create tab 2: QR Code Generator +# Create tab 2: Mnemonic Code Converter tab2 = tk.Frame(notebook) -notebook.add(tab2, text="QR Code Generator") +notebook.add(tab2, text="Seed To Mnemonic") + +frame11 = tk.LabelFrame(tab2, text="Mnemonic Seed Phrase", labelanchor="n") +frame11.grid(row=0, column=0, columnspan=12, padx=10, pady=5) +mnemonic_type2 = tk.StringVar() +mnemonic_type2.set("Entropy") +mnemonic_type2_entropy = tk.Radiobutton(frame11, text="Generate From Entropy", variable=mnemonic_type2, value="Entropy") +mnemonic_type2_own = tk.Radiobutton(frame11, text="Enter Your Own Seed", variable=mnemonic_type2, value="Own") +mnemonic_type2_entropy.grid(row=0, column=0, padx=10, pady=0) +mnemonic_type2_own.grid(row=0, column=1, padx=10, pady=0) +mnemonic_type2_own.bind("", lambda event: on_own_mnemonic_select()) +mnemonic_type2_entropy.bind("", lambda event: on_entropy_mnemonic_select()) + +frame12 = tk.LabelFrame(tab2, text="Mnemonic Seed Phrase Word Count", labelanchor="n") +frame12.grid(row=2, column=0, columnspan=12, padx=10, pady=5) +num_words_var2 = tk.IntVar() +num_words_var2.set(12) +mnemonic_words = [12, 15, 18, 21, 24] +for i, word_count in enumerate(mnemonic_words): + num_words_button = tk.Radiobutton(frame12, text=str(word_count) + " Words", variable=num_words_var2, value=word_count, + command=lambda count=word_count: num_words_var2.set(count)) + num_words_button.grid(row=0, column=i + 2, padx=4, pady=0) -qr_label = tk.LabelFrame(tab2, text="Enter the intended text then click Generate QR Code", padx=10, pady=0, labelanchor="n") +frame13 = tk.LabelFrame(tab2, text="Enter Your Own Mnemonic Seed Phrase (12, 15, 18, 21, 24 Words Only)", padx=10, pady=5, labelanchor="n") +frame13.grid(row=2, column=0, columnspan=12, padx=11, pady=5) +frame13_entry = tk.Text(frame13, height=7, width=54, font=("Helvetica", 9)) +frame13_entry.grid(row=0, column=0, padx=10, pady=0) +frame13_entry.insert("1.0", "Word1 Word2 Word3 .....") + +frame14 = tk.LabelFrame(tab2, text="Enter Number Of Hex Entropies To Generate (1,000 - 10,000,000)", padx=10, pady=6,labelanchor="n") +frame14.grid(row=3, column=0, columnspan=12, padx=10, pady=6) + +entropy_entry2 = tk.Entry(frame14, justify="center") +entropy_entry2.insert(0, "1,000,000") +entropy_entry2.grid(row=0, column=0, columnspan=6, padx=5, pady=0) +entropy_entry2.config(width=30) +entropy_entry2.bind("", on_entry_change) + +display_entropy2 = tk.StringVar() +display_entropy2.set("Hide") +display_entropy2_yes = tk.Radiobutton(frame14, text="Display Entropy", variable=display_entropy2, value="Display") +display_entropy2_no = tk.Radiobutton(frame14, text="Hide Entropy", variable=display_entropy2, value="Hide") +display_entropy2_yes.grid(row=0, column=10) +display_entropy2_no.grid(row=0, column=11) + +label_below_radios = tk.Label(frame14, text="Displaying a long list of entropies may take a significant amount of time", fg="red") +label_below_radios.grid(row=1, column=0, columnspan=12) + +frame15 = tk.LabelFrame(tab2, text="Passphrase (optional)", padx=10, pady=5, labelanchor="n") +frame15.grid(row=5, column=0, columnspan=6, padx=10, pady=5) +passphrase_entry2 = tk.Entry(frame15, justify="center") +passphrase_entry2.grid(row=0, column=1) +passphrase_entry2.config(width=25) + +frame16 = tk.LabelFrame(tab2, text="Number Of Child Keys (1-25)", padx=10, pady=5, labelanchor="n") +frame16.grid(row=5, column=6, columnspan=6, padx=10, pady=5) +child_keys_entry2 = tk.Entry(frame16, justify="center") +child_keys_entry2.insert(0, "5") +child_keys_entry2.grid(row=0, column=1) +child_keys_entry2.config(width=25) + +frame17 = tk.LabelFrame(tab2, text="Addresses Details", padx=10, pady=0, labelanchor="n") +frame17.grid(row=7, column=0, columnspan=12, padx=10, pady=6) +add_list_type2_var = tk.StringVar() +add_list_type2_var.set("AddMain") +add_list_type2_addmain = tk.Radiobutton(frame17, text="Addresses & Private Keys", variable=add_list_type2_var, value="AddMain") +add_list_type2_addfull = tk.Radiobutton(frame17, text="Addresses & Public/Private Keys", variable=add_list_type2_var, value="AddFull") +add_list_type2_addmain.grid(row=0, column=0, padx=5, pady=0) +add_list_type2_addfull.grid(row=0, column=1, padx=5, pady=0) + +frame18 = tk.LabelFrame(tab2, text="Choose Network Type", padx=10, pady=0, labelanchor="n") +frame18.grid(row=8, column=0, columnspan=12, padx=10, pady=6) +network_type2_var = tk.StringVar() +network_type2_var.set("Mainnet") +network_type2_mainnet = tk.Radiobutton(frame18, text="Mainnet", variable=network_type2_var, value="Mainnet") +network_type2_testnet = tk.Radiobutton(frame18, text="Testnet", variable=network_type2_var, value="Testnet") +network_type2_mainnet.grid(row=0, column=0, padx=5, pady=0) +network_type2_testnet.grid(row=0, column=1, padx=5, pady=0) + +continue_button2 = tk.Button(tab2, text="Generate Mnemonic Seed Phrase", command=mnemonic_converter2) +continue_button2.grid(row=9, column=0, columnspan=12, padx=10, pady=6) + +result_label2 = tk.Label(tab2, text="", padx=10, pady=3, fg="red") +result_label2.grid(row=10, column=0, columnspan=12) + +# Create tab 3: QR Code Generator +tab3 = tk.Frame(notebook) +notebook.add(tab3, text="QR Code Generator") + +qr_label = tk.LabelFrame(tab3, text="Enter the intended text then click Generate QR Code", padx=10, pady=0, + labelanchor="n") qr_label.grid(row=0, column=0, columnspan=12, padx=10, pady=5) -qr_text_entry = tk.Text(qr_label, height=5, width=65, font=("Helvetica", 8)) +qr_text_entry = tk.Text(qr_label, height=3, width=55, font=("Helvetica", 9)) qr_text_entry.grid(row=1, column=0, columnspan=12, padx=3, pady=5) -qr_warning_label = tk.Label(tab2, text=f"Make sure to copy the intended text correctly." - "\nWatch for unnecessary spaces, mistakes may lead to serious losses." - "\nFor added privacy, QR code and text will be cleared after 1 minute of generation.", fg="red") +qr_warning_label = tk.Label(tab3, text=f"Make sure to copy the intended text correctly." + "\nWatch for unnecessary spaces, mistakes may lead to serious losses." + "\nFor added privacy, QR code and text will be cleared after 1 minute of generation.", fg="red") qr_warning_label.grid(row=2, column=0, columnspan=11, padx=10, pady=0) -generate_qr_button = tk.Button(tab2, text="Generate QR Code", command=generate_qr_code) +generate_qr_button = tk.Button(tab3, text="Generate QR Code", command=generate_qr_code) generate_qr_button.grid(row=6, column=0, columnspan=11, padx=10, pady=10) -qr_code_label = tk.Label(tab2) +qr_code_label = tk.Label(tab3) qr_code_label.grid(row=7, column=0, columnspan=11) continue_button.config(state="disabled") -result_label.config(text=f"The 'Mnemonic Code Converter' button is temporarily disabled. \nGenerate dice numbers to enable.") - +result_label.config(text=f"The 'Generate Keys & Addresses' button is temporarily disabled. \nGenerate dice numbers to enable.") +on_entropy_mnemonic_select() +on_entropy_dice_select() root.mainloop()