Skip to content

About

A set of tools for nerding around with crypto. ๐Ÿ’ป๐Ÿ”ง

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

ย 

History

54 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Cryptowrench ๐Ÿ”‘๐Ÿ”ฎ

This is a set of tools that I created to learn and play around with blockchains and cryptocurrencies in general.

Install with:

pip -m install cryptowrench

Feel free to use it for your own projects.

๐Ÿ“– Examples

Create a new wallet

from cryptowrench.wallet import Wallet

# This will create a root wallet automatically
root_wallet = Wallet()

# Now you can show the mnemonic words generated. Store them in a safe place!
# They will help you recover your wallet if you ever lose your computer. You can
# also use them to import this wallet into a different wallet application.
print(root_wallet.words)

# IMPORTANT NOTE: You should never use your root wallet to sign transactions
# directly. Instead, you are supposed to use it to generate multiple "child
# wallets" using the method introduced in BIP 32 (see: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki).
# These child wallets are the ones you should use for receiving and sending
# transactions.

# Enough talk! Let's create our first child wallet!
child_wallet = root_wallet.hd_wallet("m/84'/0'/0'/0/0")

# That's it :)

# These are your keys (in serialized format). For details on key serialization,
# see: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki#Serialization_format
print(child_wallet.serialized_extended_private_key)
print(child_wallet.serialized_extended_public_key)

# Now let's see your bitcoin address so people can send you lots of BTCs.
print(child_wallet.address.bitcoin.P2WPKH_wit0)

Import an existing wallet (from mnemonic words)

from cryptowrench.wallet import Wallet

# IMPORTANT: Do not use the following words to generate your wallet because they
# are not random and they are publicly available in the internet. If you do it,
# you will lose all your money and axe-throwing monkeys will descend from the
# skies to hunt you down.
words = 'fetch pool sight try enhance squirrel must range rotate maple resemble forest'
# If your wallet had a password, you should pass it to the Wallet class as well.
pwd = ''

# This will import a root wallet from the provided mnemonic and password.
root_wallet = Wallet(mnemonic=words, passphrase=pwd)

# This is the first child wallet.
child_wallet = root_wallet.hd_wallet("m/84'/0'/0'/0/0")
print(f"P2WPKH0:  {child_wallet.address.bitcoin.P2WPKH_wit0}")

# You can also generate old wallet formats, like this:

# Original bitcoin wallet format (P2PKH or Pay-to-PubKey-Hash).
# How to recognize them? They start with the number 1.
# NOTE: it is not recommended to use this wallet format nowadays because it uses
# the most amount of space inside a transaction and is therefore the most
# "expensive" address type.
child_wallet = root_wallet.hd_wallet("m/44'/0'/0'/0/0")
print(f"P2PKH:    {child_wallet.address.bitcoin.P2PKH}")

# BIP 13 bitcoin wallet format (P2SH or Pay-to-Script-Hash).
# How to recognize them? They start with the number 3.
# NOTE: to better understand what these addresses enable in the bitcoin
# blockchain, refert to the original BIP that introduced them:
# https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki
# Also you can take a look at BIP 16, which introduced the corresponding new
# transaction type: https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki
child_wallet = root_wallet.hd_wallet("m/49'/0'/0'/0/0")
print(f"P2SH:     {child_wallet.address.bitcoin.P2SH}")

# Finally, if your seed comes from an Ethereum wallet, you can also peek into
# those addresses as well:
child_wallet = root_wallet.hd_wallet("m/44'/60'/0'/0/0")
print(f"Ethereum: {child_wallet.address.ethereum}")

Create a wallet from entropy

from cryptowrench.wallet import Wallet

# Public test entropy, for demonstration only. Never send funds to this wallet.
entropy = bytes.fromhex('00000000000000000000000000000000')
master_wallet = Wallet(
    entropy=entropy,
    passphrase='My_P4$$phrase',
    language='english')

print(master_wallet.words)
# abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about

child_wallet = master_wallet.hd_wallet("m/84'/0'/0'/0/0")
print(child_wallet.serialized_extended_public_key)
# b'zpub6vgLkXzKPJKREftSon6FqywPeMhN9HybFPuothTnaUxDXvdFkaux55mYN6YDFRTnhs2EWFy5foonj3oPdNqEQ87Ea2sgfdvQAsctyaAdyLr'

Entropy must be raw bytes of length 16, 20, 24, 28 or 32 (128, 160, 192, 224 or 256 bits). Convert hexadecimal text with bytes.fromhex(...) before passing it in. All byte values and leading zeros are preserved. Entropy length determines the number of mnemonic words, so supplying both entropy and strength raises ValueError.

Entropy is converted into BIP39 mnemonic words, then the words and optional passphrase derive the seed. Different passphrases produce different wallets; recovery requires the same passphrase. Unicode normalization follows BIP39. Wallet(seed=...) instead accepts seed bytes directly and skips mnemonic and passphrase processing.

Import an existing wallet (from seed)

from cryptowrench.wallet import Wallet

# IMPORTANT: Do not use the following seed to generate your wallet because is
# not random and it is publicly available in the internet. If you do it, you
# will lose all your money and angry elephants will eat all your crops.
# Make sure the seed is in bytes.
seed = bytes.fromhex('000102030405060708090a0b0c0d0e0f')

# This will import a root wallet from the provided seed.
root_wallet = Wallet(seed=seed)

# This is the first child wallet.
child_wallet = root_wallet.hd_wallet("m/44'/60'/0'/0/0")
print(f"Ethereum:  {child_wallet.address.ethereum}")

๐Ÿ”ง Compatible wallet arguments

Options that do not apply to the selected source raise ValueError.

Source Allowed options
None (random creation) strength, language, passphrase, main_net
entropy language, passphrase, main_net
mnemonic passphrase, main_net; language is detected from the words
seed main_net
private_key chain_code, main_net
wif None; WIF determines the network

Supply arguments from only one source. Omitted arguments use the defaults when needed: English, empty passphrase, mainnet, and 128-bit random generation.

derivation_path and fingerprint_parent_key must be supplied together, alongside an explicit private_key and chain_code. They describe serialization metadata for an existing extended key; they do not derive a child wallet. The fingerprint must contain four bytes.

๐Ÿ”ฌ Testing

The test suite uses pytest and covers wallet creation and imports, key validation, Ethereum checksums, and HD derivation. BIP32 and BIP39 checks use published test vectors.

From the repository root, install the development dependencies and run the suite with uv:

uv sync --group dev
uv run pytest

Tests are grouped into two categories:

  • Unit tests (tests/unit/) check private-key validation and Ethereum checksums.
  • Integration tests (tests/integration/) check wallet creation, imports, and HD derivation.

Run a category, a specific file, or a single test:

uv run pytest -m unit
uv run pytest -m integration
uv run pytest tests/integration/test_entropy.py
uv run pytest tests/integration/test_entropy.py::test_empty_passphrase_matches_default -v

โš  Disclaimer

Although I try my best to make these tools as correct and reliable as possible, please for the love of dinosaurs do not rely on them for storing your money. Use a proper wallet for that instead (see: ethereum.org/en/wallets/ for some fully featured ones).

That said, this library has been tested against publicly available test vectors (i.e. from bip32 and bip39, among others), which means that it should be mostly correct for those functionalities. Expect more tests to be added in the future, and see Testing to run the suite yourself.

๐Ÿค Colaborate :)

Please create issues/pull requests/feature requests where needed. I'm also looking to collaborate in other open source projects, so let me know if you would like to talk!

About

A set of tools for nerding around with crypto. ๐Ÿ’ป๐Ÿ”ง

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages