Agora é possível criar um novo mnemônico de 12, 18 e 24 palavras;
Também adicionei informações relevantes da carteira como o fingerprint, um identificador de 8 digítos de toda carteira, muito útil para quem usa passphrases.
Outra importante alteração feita é que agora eu consegui fazer o chatGPT adicionar a funcionalidade de alterar o número da conta.
Consegui fazer ele corrigir a informação no hdkeypath, onde não estava mostrando o derivation path index corretamente, estava com um zero a mais.
Na saída agora aparecem:
BIP32 Masterkey: xpriv
BIP32 Extended Private Key (account Level): xpriv/ypriv/zpriv
Derivation Path usado: m/84'/0'/0'/0
Fingerprint da carteira: 00000000
BIP32 Root PrivKey (WIF): L1xxxxxxxx
O código parece bem completo, eu queria adicionar novas funcionalidades, mas não consegui, mas não recomendo de forma alguma que substituam iancoleman por esse, a não ser que seja feito pra fazer testes e conhecer como funciona o esquema de geração de chaves.
import sys
import hashlib
from bip_utils import (
Bip39MnemonicGenerator, Bip39MnemonicValidator, Bip39SeedGenerator,
Bip44, Bip49, Bip84, Bip86, Bip44Coins, Bip49Coins, Bip84Coins, Bip86Coins,
Bip44Changes, Bip32Slip10Secp256k1, Secp256k1PrivateKey, WifEncoder
)
from getpass import getpass
def main():
# Perguntar se deseja criar um novo mnemônico
mnemonic_choice = input("Digite o número de palavras para criar um novo mnemônico (12, 18, 24) ou pressione Enter para usar um mnemônico existente: ").strip()
if mnemonic_choice in ['12', '18', '24']:
# Gerar um novo mnemônico com o número de palavras especificado
num_words = int(mnemonic_choice)
mnemonic = Bip39MnemonicGenerator().FromWordsNumber(num_words)
print(f"Novo mnemônico gerado ({num_words} palavras): {mnemonic}")
else:
# Perguntar pelo mnemônico
mnemonic = input("Digite o mnemônico: ").strip()
# Validar o mnemônico
if not Bip39MnemonicValidator().IsValid(mnemonic):
print("Mnemônico inválido!")
sys.exit(1)
# Perguntar pela passphrase (opcional)
passphrase = getpass("Digite a passphrase (opcional): ").strip()
# Gerar a seed BIP39
seed = Bip39SeedGenerator(mnemonic).Generate(passphrase)
# Definindo os paths padrões
deriv_paths = {
'1': "m/44'/0'", # p2pkh
'2': "m/49'/0'", # p2wpkh-p2sh
'3': "m/84'/0'", # p2wpkh
'4': "m/86'/0'" # p2tr
}
print("Derivation path e tipos de endereços disponíveis:")
print("1: p2pkh (m/44'/0')")
print("2: p2wpkh-p2sh (m/49'/0')")
print("3: p2wpkh (m/84'/0')")
print("4: p2tr (m/86'/0')")
address_type = input("Escolha o tipo de endereço (1-4): ").strip()
if address_type not in deriv_paths:
print("Tipo de endereço inválido!")
sys.exit(1)
# Caminho de derivação base
base_derivation_path = deriv_paths[address_type]
# Perguntar pela conta
account_index = input("Digite o índice da conta (padrão 0): ").strip()
account_index = int(account_index) if account_index.isdigit() else 0
# Perguntar se quer gerar endereços de recebimento (0) ou de troco (1)
address_purpose = input("Gerar endereços de recebimento (0) ou de troco (1)? ").strip()
if address_purpose not in ['0', '1']:
print("Opção inválida!")
sys.exit(1)
# Perguntar a partir de qual index mostrar os endereços
start_index = int(input("A partir de qual index mostrar os endereços (padrão 0)? ").strip() or 0)
# Perguntar quantos endereços mostrar
address_count = int(input("Quantos endereços mostrar (padrão 50)? ").strip() or 50)
# Inicializar a classe BIP adequada
bip_cls_dict = {
'1': (Bip44, Bip44Coins.BITCOIN),
'2': (Bip49, Bip49Coins.BITCOIN),
'3': (Bip84, Bip84Coins.BITCOIN),
'4': (Bip86, Bip86Coins.BITCOIN)
}
bip_cls, coin_type = bip_cls_dict[address_type]
bip_obj = bip_cls.FromSeed(seed, coin_type)
# Derivar a conta principal
bip_acc_obj = bip_obj.Purpose().Coin().Account(account_index)
# Obter o fingerprint da chave pública da raiz BIP32
root_pubkey = bip_obj.PublicKey().RawCompressed().ToBytes()
fingerprint = hashlib.new('ripemd160', hashlib.sha256(root_pubkey).digest()).digest()[:4]
# Derivar os endereços
addresses = []
for i in range(start_index, start_index + address_count):
addr_obj = bip_acc_obj.Change(Bip44Changes(int(address_purpose))).AddressIndex(i)
priv_key = addr_obj.PrivateKey().Raw().ToBytes()
priv_key_wif = WifEncoder.Encode(Secp256k1PrivateKey.FromBytes(priv_key))
addresses.append({
'index': i,
'address': addr_obj.PublicKey().ToAddress(),
'private_key_wif': priv_key_wif,
'hdkeypath': f"{base_derivation_path}/{account_index}'/{address_purpose}/{i}"
})
# Gerar a chave privada BIP32 raiz
bip32_obj = Bip32Slip10Secp256k1.FromSeed(seed)
root_xpriv = bip32_obj.PrivateKey().ToExtended()
# Gerar a chave privada estendida BIP32 no nível da conta
account_xpriv = bip_acc_obj.PrivateKey().ToExtended()
# Gerar o WIF para a chave privada raiz
root_priv_key_bytes = bip32_obj.PrivateKey().Raw().ToBytes()
root_priv_key_wif = WifEncoder.Encode(Secp256k1PrivateKey.FromBytes(root_priv_key_bytes))
# Mostrar os resultados
print("\nMnemônico:", mnemonic)
if passphrase:
print("Passphrase:", passphrase)
print("\nBIP32 Masterkey:", root_xpriv)
print("BIP32 Extended Private Key (account Level):", account_xpriv)
print("Derivation Path usado:", f"{base_derivation_path}/{account_index}'/{address_purpose}")
print("Fingerprint da carteira:", fingerprint.hex())
print("BIP32 Root PrivKey (WIF):", root_priv_key_wif)
print()
for addr in addresses:
print(f"{addr['private_key_wif']} # addr={addr['address']} hdkeypath={addr['hdkeypath']}")
# Perguntar se deseja gerar um arquivo dump.txt
save_to_file = input("Deseja gerar um arquivo dump.txt para importar em uma carteira? (s/n): ").strip().lower()
if save_to_file == 's':
with open('dump.txt', 'w') as f:
f.write(f"Mnemônico: {mnemonic}\n")
if passphrase:
f.write(f"Passphrase: {passphrase}\n")
f.write(f"\nBIP32 Masterkey: {root_xpriv}\n")
f.write(f"BIP32 Extended Private Key (account Level): {account_xpriv}\n")
f.write(f"Derivation Path usado: {base_derivation_path}/{account_index}'/{address_purpose}\n")
f.write(f"Fingerprint da carteira: {fingerprint.hex()}\n")
f.write(f"BIP32 Root PrivKey (WIF): {root_priv_key_wif}\n\n")
for addr in addresses:
f.write(f"{addr['private_key_wif']} # addr={addr['address']} hdkeypath={addr['hdkeypath']}\n")
print("Arquivo dump.txt exportado com sucesso!")
else:
print("Saída salva apenas na tela.")
if __name__ == "__main__":
main()