### Setup Integration Tests Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Prepare the environment for integration tests by setting up Node.js, installing a custom CLI tool, and installing npm dependencies. ```sh # on Ubuntu chmod +x ./tests/integration/js-scripts/setup_node_v22.sh ./tests/integration/js-scripts/setup_node_v22.sh # As sudo apt-get install -y nodejs # As sudo cd tests/integration/js-scripts npm install ``` -------------------------------- ### Example Usage of go-kzg-verify Source: https://github.com/ethereum/eth-account/blob/main/tests/_scripts/go-kzg-verify/README.md An example command demonstrating how to run the go-kzg-verify utility, specifying the test data directory and the output file path. ```bash ./go-kzg-verify ./consensus-spec-tests/tests/general/deneb/kzg/compute_cells_and_kzg_proofs/small ./output.json ``` -------------------------------- ### Install eth-account Source: https://github.com/ethereum/eth-account/blob/main/README.md Install the eth-account library using pip. This is the primary method for setting up the library for use. ```sh python -m pip install eth-account ``` -------------------------------- ### Build and Test Release Package Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Build the package intended for release and install it in a temporary virtual environment to perform pre-release testing. ```sh git checkout main && git pull make package-test ``` -------------------------------- ### Install Development Dependencies Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Install project dependencies using pip within a virtual environment. This includes setting up the project in editable mode and installing pre-commit hooks. ```sh cd eth-account virtualenv -p python venv . venv/bin/activate python -m pip install -e ".[dev]" pre-commit install ``` -------------------------------- ### Sign EIP-7702 Set-Code Transaction Source: https://context7.com/ethereum/eth-account/llms.txt Example of signing an EIP-7702 set-code transaction using a private key. ```python sender_key = "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318" tx = { "type": 4, # EIP-7702 set-code transaction "chainId": 1337, "nonce": 0, "to": "0x09616C3d61b3331fc4109a9E41a8BDB7d9776609", "value": 0, "gas": 100_000, "maxFeePerGas": 2 * 10**9, "maxPriorityFeePerGas": 2 * 10**9, "authorizationList": [signed_auth], } signed_tx = Account.sign_transaction(tx, sender_key) ``` -------------------------------- ### Build Documentation Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Generate the project's documentation locally to review before publishing. ```sh make docs ``` -------------------------------- ### Run go-kzg-verify Utility Source: https://github.com/ethereum/eth-account/blob/main/tests/_scripts/go-kzg-verify/README.md Execute the go-kzg-verify tool with paths to the consensus-spec-tests directory and the desired output file. ```bash ./go-kzg-verify ``` -------------------------------- ### Build go-kzg-verify Source: https://github.com/ethereum/eth-account/blob/main/tests/_scripts/go-kzg-verify/README.md Build the go-kzg-verify utility using Go 1.24 or later. This command compiles the source code into an executable file. ```bash cd go-kzg-verify go build -o go-kzg-verify ``` -------------------------------- ### Save and Decrypt Keystore Source: https://context7.com/ethereum/eth-account/llms.txt Demonstrates saving a keystore to disk and decrypting it with a password. ```python with open("my-keyfile.json", "w") as f: json.dump(keystore, f) # Decrypt — accepts the dict or a JSON string recovered_key = Account.decrypt(keystore, password) print(recovered_key.hex()) ``` -------------------------------- ### Build Release Notes Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Generate the release notes by specifying the version part to bump. This command should be run before bumping the version number. ```sh make notes bump=$$VERSION_PART_TO_BUMP$$ ``` -------------------------------- ### LocalAccount: Create and Sign Messages/Transactions Source: https://context7.com/ethereum/eth-account/llms.txt Demonstrates creating a LocalAccount from a private key and using it to sign messages and transactions without re-providing the key. ```python from eth_account import Account from eth_account.messages import encode_defunct # Create a LocalAccount acct = Account.from_key("0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364") print(acct.address) # checksummed address print(acct.key.hex()) # raw private key bytes print(bytes(acct).hex()) # same as acct.key # Sign a message without passing the key signed_msg = acct.sign_message(encode_defunct(text="Hello!")) # Sign a transaction without passing the key signed_tx = acct.sign_transaction({ "chainId": 1, "nonce": 0, "to": "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55", "value": 10**17, "gas": 21000, "maxFeePerGas": 20*10**9, "maxPriorityFeePerGas": 2*10**9, }) # Encrypt the key to a keystore file keystore = acct.encrypt("my-password") ``` -------------------------------- ### Release New Version Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Automate the process of bumping the version, creating a git tag, building the package, and pushing to GitHub and PyPI. ```sh make release bump=$$VERSION_PART_TO_BUMP$$ ``` -------------------------------- ### Lint Code with Make Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Enforce code style consistency across the library by running the linting process using the make command. ```sh make lint ``` -------------------------------- ### Account.create_with_mnemonic Source: https://context7.com/ethereum/eth-account/llms.txt Generates a new BIP-39 mnemonic and derives the first account from it, returning both the account and the mnemonic phrase. Useful for wallet initialization. ```APIDOC ## Account.create_with_mnemonic — Generate a new account and its mnemonic Creates a fresh BIP-39 mnemonic and derives the first account from it, returning both. Useful for wallet initialization flows. ### Method `Account.create_with_mnemonic(num_words: int = 12, language: Language = Language.ENGLISH)` ### Parameters #### Path Parameters - **num_words** (int) - Optional - The number of words in the mnemonic phrase (12 or 24). Defaults to 12. - **language** (Language) - Optional - The language of the mnemonic phrase. Defaults to English. ### Request Example ```python from eth_account import Account from eth_account.types import Language Account.enable_unaudited_hdwallet_features() # Default: 12-word English mnemonic acct, mnemonic = Account.create_with_mnemonic() print(mnemonic) # e.g. "word1 word2 ... word12" print(acct.address) # 24-word Spanish mnemonic acct24, mnemonic24 = Account.create_with_mnemonic( num_words=24, language=Language.SPANISH, ) # Round-trip: re-derive the same account from the mnemonic recovered = Account.from_mnemonic(mnemonic) assert acct == recovered ``` ``` -------------------------------- ### Clone the eth-account Repository Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Fork the repository to your GitHub account and clone it locally to begin development. ```sh git clone git@github.com:your-github-username/eth-account.git ``` -------------------------------- ### Account.from_key Source: https://context7.com/ethereum/eth-account/llms.txt Loads an account from an existing private key. The private key can be supplied as a hex string, bytes, or integer. ```APIDOC ## Account.from_key — Load an account from an existing private key Returns a `LocalAccount` wrapping a known private key supplied as hex string, bytes, or int. ### Method `Account.from_key(private_key)` ### Parameters #### Path Parameters - **private_key** (str | bytes | int) - Required - The private key to load the account from. ### Request Example ```python from eth_account import Account private_key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" acct = Account.from_key(private_key) print(acct.address) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' print(acct.key.hex()) # '0xb25c7db3...' # Also accepts int or bytes acct2 = Account.from_key(0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364) assert acct.address == acct2.address ``` ``` -------------------------------- ### Account.create Source: https://context7.com/ethereum/eth-account/llms.txt Generates a new random private key and returns it as a LocalAccount. Optional extra entropy can be provided to supplement OS randomness. ```APIDOC ## Account.create — Generate a new private key Creates a new random private key and returns it as a `LocalAccount`. Optional extra entropy may be mixed in to supplement OS randomness. ### Method `Account.create(extra_entropy: str = '')` ### Parameters #### Path Parameters - **extra_entropy** (str) - Optional - Additional entropy string to mix into the key generation. ### Request Example ```python from eth_account import Account # Generate a new account with optional extra entropy acct = Account.create("some extra entropy string") print(acct.address) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' (random each run) print(acct.key.hex()) # '0x8676e9a8...' (random 32-byte private key) # The returned LocalAccount also exposes sign_message, sign_transaction, encrypt ``` ``` -------------------------------- ### Generate new account and mnemonic Source: https://context7.com/ethereum/eth-account/llms.txt Creates a fresh BIP-39 mnemonic and derives the first account from it, returning both. Useful for wallet initialization flows. Supports specifying the number of words and language for the mnemonic. Can be used to round-trip and re-derive the account from the generated mnemonic. ```python from eth_account import Account from eth_account.types import Language Account.enable_unaudited_hdwallet_features() # Default: 12-word English mnemonic acct, mnemonic = Account.create_with_mnemonic() print(mnemonic) # e.g. "word1 word2 ... word12" print(acct.address) # 24-word Spanish mnemonic acct24, mnemonic24 = Account.create_with_mnemonic( num_words=24, language=Language.SPANISH, ) # Round-trip: re-derive the same account from the mnemonic recovered = Account.from_mnemonic(mnemonic) assert acct == recovered ``` -------------------------------- ### Generate a new account Source: https://context7.com/ethereum/eth-account/llms.txt Create a new random private key and returns it as a LocalAccount. Optional extra entropy may be mixed in to supplement OS randomness. ```python from eth_account import Account # Generate a new account with optional extra entropy acct = Account.create("some extra entropy string") print(acct.address) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' (random each run) print(acct.key.hex()) # '0x8676e9a8...' (random 32-byte private key) # The returned LocalAccount also exposes sign_message, sign_transaction, encrypt ``` -------------------------------- ### Encrypt and decrypt keystore file Source: https://context7.com/ethereum/eth-account/llms.txt Encrypt creates an EIP-55 encrypted JSON keystore dict using scrypt KDF by default. Decrypt reverses the process, recovering the raw private key bytes. Supports 'pbkdf2' as an alternative KDF. ```python import json from eth_account import Account private_key = 0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364 password = "correct-horse-battery-staple" # Encrypt — uses scrypt KDF by default; can also use 'pbkdf2' keystore = Account.encrypt(private_key, password) print(keystore["address"]) # '5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' print(keystore["version"]) # 3 ``` -------------------------------- ### Load account from private key Source: https://context7.com/ethereum/eth-account/llms.txt Returns a LocalAccount wrapping a known private key supplied as hex string, bytes, or int. Accepts hex string, integer, or bytes for the private key. ```python from eth_account import Account private_key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" acct = Account.from_key(private_key) print(acct.address) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' print(acct.key.hex()) # '0xb25c7db3...' # Also accepts int or bytes acct2 = Account.from_key(0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364) assert acct.address == acct2.address ``` -------------------------------- ### LocalAccount Methods Source: https://context7.com/ethereum/eth-account/llms.txt LocalAccount provides signing methods without requiring the private key argument, useful for repeated operations. It can sign messages and transactions, and encrypt keys to keystore files. ```APIDOC ## LocalAccount ### Description `LocalAccount` is an object representing an account with an embedded private key, typically returned by `Account.create()`, `Account.from_key()`, or `Account.from_mnemonic()`. It mirrors `Account`'s signing methods but does not require the private key to be passed explicitly. ### Methods - **address** (property): Returns the checksummed address of the account. - **key** (property): Returns the raw private key bytes. - **sign_message**(message, private_key=None): Signs a message using the account's private key. - **sign_transaction**(transaction, private_key=None): Signs a transaction using the account's private key. - **encrypt**(password): Encrypts the account's private key to a keystore file. ``` -------------------------------- ### Run All Tests Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Execute all tests, including core and integration tests, using pytest. ```sh pytest tests ``` -------------------------------- ### Run Core Tests Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Execute the core test suite using pytest to explore the codebase and ensure basic functionality. ```sh pytest tests/core ``` -------------------------------- ### Validate Release Notes Source: https://github.com/ethereum/eth-account/blob/main/docs/contributing.md Ensure that the release notes fragments are correctly formatted and can be processed without errors. ```sh make validate-newsfragments ``` -------------------------------- ### Encrypt with Specific KDF and Iterations Source: https://context7.com/ethereum/eth-account/llms.txt Encrypts a private key using Account.encrypt, allowing explicit specification of the Key Derivation Function (KDF) and iteration count. ```python # Specify KDF and iteration count explicitly keystore_pbkdf2 = Account.encrypt(private_key, password, kdf="pbkdf2", iterations=100000) ``` -------------------------------- ### Account.encrypt / Account.decrypt Source: https://context7.com/ethereum/eth-account/llms.txt Encrypts a private key into an EIP-55 compatible JSON keystore dict using a password, and decrypts a keystore dict back into a private key. Supports scrypt KDF by default and can also use pbkdf2. ```APIDOC ## Account.encrypt / Account.decrypt — Keystore file (Web3 Secret Storage) `encrypt` creates an EIP-55 encrypted JSON keystore dict (compatible with geth, parity, MetaMask). `decrypt` reverses the process, recovering the raw private key bytes. ### Method `Account.encrypt(private_key, password, kdf='scrypt')` `Account.decrypt(keystore_dict, password)` ### Parameters #### encrypt - **private_key** (int | bytes) - Required - The private key to encrypt. - **password** (str) - Required - The password to use for encryption. - **kdf** (str) - Optional - The Key Derivation Function to use ('scrypt' or 'pbkdf2'). Defaults to 'scrypt'. #### decrypt - **keystore_dict** (dict) - Required - The JSON keystore dictionary. - **password** (str) - Required - The password to use for decryption. ### Request Example ```python import json from eth_account import Account private_key = 0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364 password = "correct-horse-battery-staple" # Encrypt — uses scrypt KDF by default; can also use 'pbkdf2' keystore = Account.encrypt(private_key, password) print(keystore["address"]) # '5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' print(keystore["version"]) # 3 # Decrypt decrypted_private_key = Account.decrypt(keystore, password) assert decrypted_private_key == private_key ``` ``` -------------------------------- ### Output JSON Format Source: https://github.com/ethereum/eth-account/blob/main/tests/_scripts/go-kzg-verify/README.md The structure of the JSON output generated by the tool, detailing test case results including blob, commitment, versioned hash, cell proofs, and the signed transaction. ```json [ { "test_name": "compute_cells_and_kzg_proofs_case_valid_0", "blob": "0x...", "commitment": "0x...", "versioned_hash": "0x01...", "cell_proofs": ["0x...", ...], "signed_transaction_hex": "0x03..." } ] ``` -------------------------------- ### Account.from_mnemonic Source: https://context7.com/ethereum/eth-account/llms.txt Derives an Ethereum private key from a BIP-39 mnemonic seed phrase using BIP-32/BIP-44 HD derivation. Requires `enable_unaudited_hdwallet_features()` to be called first. ```APIDOC ## Account.from_mnemonic — Derive an account from a BIP-39 mnemonic phrase Derives an Ethereum private key from a BIP-39 mnemonic seed phrase following the BIP-32/BIP-44 HD derivation path. Must call `enable_unaudited_hdwallet_features()` first. ### Method `Account.from_mnemonic(mnemonic: str, account_path: str = "m/44'/60'/0'/0/0")` ### Parameters #### Path Parameters - **mnemonic** (str) - Required - The BIP-39 mnemonic phrase. - **account_path** (str) - Optional - The BIP-44 derivation path. Defaults to `"m/44'/60'/0'/0/0"`. ### Request Example ```python from eth_account import Account Account.enable_unaudited_hdwallet_features() mnemonic = ( "coral allow abandon recipe top tray caught video climb similar " "prepare bracket antenna rubber announce gauge volume " "hub hood burden skill immense add acid" ) acct = Account.from_mnemonic(mnemonic) print(acct.address) # '0x9AdA5dAD14d925f4df1378409731a9B71Bc8569d' # Derive multiple accounts from the same mnemonic using different BIP-44 paths for i in range(3): a = Account.from_mnemonic( "health embark april buyer eternal leopard want before nominee head thing tackle", account_path=f"m/44'/60'/0'/0/{i}", ) print(a.address) # '0x61Cc15522D06983Ac7aADe23f9d5433d38e78195' # '0x1240460F6E370f28079E5F9B52f9DcB759F051b7' # '0xd30dC9f996539826C646Eb48bb45F6ee1D1474af' ``` ``` -------------------------------- ### Derive account from mnemonic Source: https://context7.com/ethereum/eth-account/llms.txt Derives an Ethereum private key from a BIP-39 mnemonic seed phrase following the BIP-32/BIP-44 HD derivation path. Must call `enable_unaudited_hdwallet_features()` first. Supports deriving multiple accounts from the same mnemonic using different BIP-44 paths. ```python from eth_account import Account Account.enable_unaudited_hdwallet_features() mnemonic = ( "coral allow abandon recipe top tray caught video climb similar " "prepare bracket antenna rubber announce gauge volume " "hub hood burden skill immense add acid" ) acct = Account.from_mnemonic(mnemonic) print(acct.address) # '0x9AdA5dAD14d925f4df1378409731a9B71Bc8569d' # Derive multiple accounts from the same mnemonic using different BIP-44 paths for i in range(3): a = Account.from_mnemonic( "health embark april buyer eternal leopard want before nominee head thing tackle", account_path=f"m/44'/60'/0'/0/{i}", ) print(a.address) # '0x61Cc15522D06983Ac7aADe23f9d5433d38e78195' # '0x1240460F6E370f28079E5F9B52f9DcB759F051b7' # '0xd30dC9f996539826C646Eb48bb45F6ee1D1474af' ``` -------------------------------- ### Sign EIP-191 Message with Private Key Source: https://context7.com/ethereum/eth-account/llms.txt Signs a `SignableMessage` using `Account.sign_message` and returns a `SignedMessage` object containing the signature components (v, r, s) and the full signature. ```python from eth_account import Account from eth_account.messages import encode_defunct key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" signable = encode_defunct(text="Hello, Ethereum!") signed = Account.sign_message(signable, key) print(signed.message_hash.hex()) # keccak256 of the prefixed message print(signed.v) # 27 or 28 print(hex(signed.r)) print(hex(signed.s)) print(signed.signature.hex()) # 65-byte r+s+v signature # Equivalent usage via LocalAccount (no need to pass the key again) acct = Account.from_key(key) signed2 = acct.sign_message(signable) assert signed == signed2 ``` -------------------------------- ### Account.unsafe_sign_hash: Sign Raw Hash Source: https://context7.com/ethereum/eth-account/llms.txt Signs an arbitrary 32-byte hash directly without an EIP-191 prefix. Use only when you control the hash construction. ```python from eth_account import Account from eth_utils import keccak key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" # Only use this when you explicitly construct and control the hash raw_hash = keccak(text="a known message I constructed") signed = Account.unsafe_sign_hash(raw_hash, key) print(signed.v, hex(signed.r), hex(signed.s)) print(signed.signature.hex()) # Recover signer using _recover_hash (internal, use recover_message for EIP-191 messages) recovered = Account._recover_hash(raw_hash, signature=signed.signature) print(recovered) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' ``` -------------------------------- ### Account.sign_authorization Source: https://context7.com/ethereum/eth-account/llms.txt Signs an EIP-7702 authorization tuple, which authorizes an EOA to temporarily delegate its code to a smart contract address for the duration of a transaction. ```APIDOC ## Account.sign_authorization — Sign an EIP-7702 authorization (set-code delegation) Signs an EIP-7702 authorization tuple that authorizes an EOA to temporarily delegate its code to a smart contract address for the duration of a transaction. ```python from eth_account import Account authority_key = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" auth = { "chainId": 1337, "address": "0x5ce9454909639d2d17a3f753ce7d93fa0b9ab12e", # contract to delegate to "nonce": 1, } signed_auth = Account.sign_authorization(auth, authority_key) print(signed_auth.chain_id) # 1337 print(signed_auth.y_parity) # 0 or 1 print(signed_auth.signature) # Verify the authority address import binascii print("0x" + binascii.hexlify(signed_auth.authority).decode()) # should match the address derived from authority_key ``` ``` -------------------------------- ### Account.unsafe_sign_hash Source: https://context7.com/ethereum/eth-account/llms.txt Signs an arbitrary 32-byte hash directly without an EIP-191 prefix. This method should only be used when the hash construction is fully controlled by the user. ```APIDOC ## Account.unsafe_sign_hash ### Description Signs an arbitrary 32-byte hash directly. This method bypasses EIP-191 message formatting and should be used with extreme caution, only when the user has complete control over the hash construction. ### Method `Account.unsafe_sign_hash(hash_bytes, private_key)` ### Parameters - **hash_bytes** (bytes): The 32-byte hash to sign. - **private_key** (str | bytes | int | PrivateKey): The private key to use for signing. ### Returns - A signature object containing `v`, `r`, `s`, and the `signature` in bytes. ``` -------------------------------- ### Sign EIP-712 Structured Data Source: https://context7.com/ethereum/eth-account/llms.txt Signs structured data according to EIP-712, compatible with eth_signTypedData_v4. Supports both one-step and two-step signing processes. The recovered signer can be verified using Account.recover_message. ```python from eth_account import Account from eth_account.messages import encode_typed_data key = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" domain_data = { "name": "Ether Mail", "version": "1", "chainId": 1, "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", } message_types = { "Person": [ {"name": "name", "type": "string"}, {"name": "wallet", "type": "address"}, ], "Mail": [ {"name": "from", "type": "Person"}, {"name": "to", "type": "Person"}, {"name": "contents", "type": "string"}, ], } message_data = { "from": {"name": "Cow", "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"}, "to": {"name": "Bob", "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"}, "contents": "Hello, Bob!", } # One-step sign (recommended) signed = Account.sign_typed_data(key, domain_data, message_types, message_data) print(signed.message_hash.hex()) # 'c5bb16ccc59ae9a3ad1cb8343d4e3351f057c994a97656e1aff8c134e56f7530' # Two-step: encode then sign signable = encode_typed_data(domain_data, message_types, message_data) signed2 = Account.sign_message(signable, key) assert signed == signed2 # Recover signer from EIP-712 signature signer = Account.recover_message(signable, signature=signed.signature) print(signer) # '0x...' ``` -------------------------------- ### encode_defunct Source: https://context7.com/ethereum/eth-account/llms.txt Encodes a human-readable string for signing in the style of `eth_sign` and MetaMask's personal sign. This is the most common message encoding for wallet signatures. ```APIDOC ## encode_defunct — Encode a plain-text message (EIP-191 version E) Encodes a human-readable string (or bytes/hex) for signing in the style of `eth_sign` / MetaMask's personal sign. This is the most common message encoding for wallet signatures. ```python from eth_account import Account from eth_account.messages import encode_defunct key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" # Encode from unicode text msg = encode_defunct(text="I♥SF") print(msg) # SignableMessage(version=b'E', header=b'thereum Signed Message:\n6', body=b'I\xe2\x99\xa5SF') # Sign the encoded message signed = Account.sign_message(msg, key) print(signed.signature.hex()) # '0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3...' # Encode from raw bytes or hex string — all three produce identical results assert encode_defunct(b"I\xe2\x99\xa5SF") == encode_defunct(text="I♥SF") assert encode_defunct(hexstr="0x49e299a55346") == encode_defunct(text="I♥SF") ``` ``` -------------------------------- ### Account.sign_message Source: https://context7.com/ethereum/eth-account/llms.txt Signs any `SignableMessage` (produced by `encode_defunct`, `encode_intended_validator`, or `encode_typed_data`) and returns a `SignedMessage` containing `v`, `r`, `s`, and the full 65-byte `signature`. ```APIDOC ## Account.sign_message — Sign an EIP-191 message Signs any `SignableMessage` (produced by `encode_defunct`, `encode_intended_validator`, or `encode_typed_data`) and returns a `SignedMessage` containing `v`, `r`, `s`, and the full 65-byte `signature`. ```python from eth_account import Account from eth_account.messages import encode_defunct key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" signable = encode_defunct(text="Hello, Ethereum!") signed = Account.sign_message(signable, key) print(signed.message_hash.hex()) # keccak256 of the prefixed message print(signed.v) # 27 or 28 print(hex(signed.r)) print(hex(signed.s)) print(signed.signature.hex()) # 65-byte r+s+v signature # Equivalent usage via LocalAccount (no need to pass the key again) acct = Account.from_key(key) signed2 = acct.sign_message(signable) assert signed == signed2 ``` ``` -------------------------------- ### Encode Defunct Message for Signing (EIP-191) Source: https://context7.com/ethereum/eth-account/llms.txt Encodes a human-readable string into a format suitable for signing with `eth_sign` or MetaMask's personal sign. Supports encoding from unicode text, raw bytes, or hex strings. ```python from eth_account import Account from eth_account.messages import encode_defunct key = "0xb25c7db31feed9122727bf0939dc769a96564b2de4c4726d035b36ecf1e5b364" # Encode from unicode text msg = encode_defunct(text="I♥SF") print(msg) # Sign the encoded message signed = Account.sign_message(msg, key) print(signed.signature.hex()) # Encode from raw bytes or hex string — all three produce identical results assert encode_defunct(b"I\xe2\x99\xa5SF") == encode_defunct(text="I♥SF") assert encode_defunct(hexstr="0x49e299a55346") == encode_defunct(text="I♥SF") ``` -------------------------------- ### Sign EIP-7702 Authorization Source: https://context7.com/ethereum/eth-account/llms.txt Signs an EIP-7702 authorization tuple, enabling an EOA to temporarily delegate its code to a smart contract for a transaction's duration. The signature can be verified by checking the derived authority address against the provided key. ```python from eth_account import Account authority_key = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" auth = { "chainId": 1337, "address": "0x5ce9454909639d2d17a3f753ce7d93fa0b9ab12e", # contract to delegate to "nonce": 1, } signed_auth = Account.sign_authorization(auth, authority_key) print(signed_auth.chain_id) # 1337 print(signed_auth.y_parity) # 0 or 1 print(signed_auth.signature) # Verify the authority address import binascii print("0x" + binascii.hexlify(signed_auth.authority).decode()) # should match the address derived from authority_key ``` -------------------------------- ### Account.sign_transaction Source: https://context7.com/ethereum/eth-account/llms.txt Signs an Ethereum transaction dict with a local private key. Supports legacy, EIP-1559 (type 2), EIP-2930 (type 1), EIP-4844 blob (type 3), and EIP-7702 (type 4) transactions. ```APIDOC ## Account.sign_transaction — Sign Ethereum transactions (all types) Signs a transaction dict with a local private key. Supports legacy, EIP-1559 (type 2), EIP-2930 access list (type 1), EIP-4844 blob (type 3), and EIP-7702 set-code (type 4) transactions. Returns a `SignedTransaction` with `raw_transaction` ready for broadcast. ```python from eth_account import Account key = "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318" # --- EIP-1559 dynamic fee transaction (type 2, recommended) --- tx_eip1559 = { "type": 2, "chainId": 1, "nonce": 0, "to": "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55", "value": 10 ** 18, # 1 ETH in wei "gas": 21000, "maxFeePerGas": 20 * 10**9, # 20 gwei "maxPriorityFeePerGas": 2 * 10**9, # 2 gwei } signed = Account.sign_transaction(tx_eip1559, key) print(signed.raw_transaction.hex()) # broadcast with w3.eth.send_raw_transaction(signed.raw_transaction) print(signed.hash.hex()) # --- Legacy transaction --- tx_legacy = { "chainId": 1, "nonce": 1, "to": "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55", "value": 1_000_000_000, "gas": 21000, "gasPrice": 50 * 10**9, } signed_legacy = Account.sign_transaction(tx_legacy, key) # --- EIP-4844 blob transaction (type 3) --- blob_tx = { "type": 3, "chainId": 1, "nonce": 2, "to": "0x09616C3d61b3331fc4109a9E41a8BDB7d9776609", "value": 0, "gas": 100_000, "maxFeePerGas": 20 * 10**9, "maxPriorityFeePerGas": 2 * 10**9, "maxFeePerBlobGas": 10**9, } empty_blob = b"\x00" * 32 * 4096 # 4096 field elements of 32 bytes each signed_blob = Account.sign_transaction(blob_tx, key, blobs=[empty_blob]) # blobVersionedHashes are computed automatically from the blob data ``` ``` -------------------------------- ### Recover Signer from Raw Transaction Source: https://context7.com/ethereum/eth-account/llms.txt Recovers the checksummed address of the signing account from a given serialized (RLP-encoded) signed transaction. ```python from eth_account import Account raw_tx = "0xf86a8086d55698372431831e848094f0109fc8df283027b6285cc889f5aa624eac1f55843b9aca008025a009ebb6ca057a0535d6186462bc0b465b561c94a295bdb0621fc19208ab149a9ca0440ffd775ce91a833ab410777204d5341a6f9fa91216a6f3ee2c051fea6a0428" signer = Account.recover_transaction(raw_tx) print(signer) # '0x2c7536E3605D9C16a7a3D7b1898e529396a65c23' ``` -------------------------------- ### Account.recover_message Source: https://context7.com/ethereum/eth-account/llms.txt Given a `SignableMessage` and either a `(v, r, s)` tuple or a raw 65-byte signature, returns the checksummed Ethereum address of the signer. ```APIDOC ## Account.recover_message — Recover signer address from a message signature Given a `SignableMessage` and either a `(v, r, s)` tuple or a raw 65-byte signature, returns the checksummed Ethereum address of the signer. ```python from eth_account import Account from eth_account.messages import encode_defunct message = encode_defunct(text="I♥SF") # Recover from v, r, s tuple (values as int, hex str, or bytes all accepted) vrs = ( 28, "0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3", "0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce", ) signer = Account.recover_message(message, vrs=vrs) print(signer) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' # Recover from concatenated 65-byte signature sig = "0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c" signer2 = Account.recover_message(message, signature=sig) assert signer == signer2 ``` ``` -------------------------------- ### Sign Ethereum Transactions Source: https://context7.com/ethereum/eth-account/llms.txt Signs various types of Ethereum transactions including legacy, EIP-1559, EIP-2930, EIP-4844 blob, and EIP-7702 set-code transactions. The output is a SignedTransaction object with a raw_transaction attribute ready for broadcasting. ```python from eth_account import Account key = "0x4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318" # --- EIP-1559 dynamic fee transaction (type 2, recommended) --- tx_eip1559 = { "type": 2, "chainId": 1, "nonce": 0, "to": "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55", "value": 10 ** 18, # 1 ETH in wei "gas": 21000, "maxFeePerGas": 20 * 10**9, # 20 gwei "maxPriorityFeePerGas": 2 * 10**9, # 2 gwei } signed = Account.sign_transaction(tx_eip1559, key) print(signed.raw_transaction.hex()) # broadcast with w3.eth.send_raw_transaction(signed.raw_transaction) print(signed.hash.hex()) # --- Legacy transaction --- tx_legacy = { "chainId": 1, "nonce": 1, "to": "0xF0109fC8DF283027b6285cc889F5aA624EaC1F55", "value": 1_000_000_000, "gas": 21000, "gasPrice": 50 * 10**9, } signed_legacy = Account.sign_transaction(tx_legacy, key) # --- EIP-4844 blob transaction (type 3) --- blob_tx = { "type": 3, "chainId": 1, "nonce": 2, "to": "0x09616C3d61b3331fc4109a9E41a8BDB7d9776609", "value": 0, "gas": 100_000, "maxFeePerGas": 20 * 10**9, "maxPriorityFeePerGas": 2 * 10**9, "maxFeePerBlobGas": 10**9, } empty_blob = b"\x00" * 32 * 4096 # 4096 field elements of 32 bytes each signed_blob = Account.sign_transaction(blob_tx, key, blobs=[empty_blob]) # blobVersionedHashes are computed automatically from the blob data ``` -------------------------------- ### Recover Signer Address from EIP-191 Message Signature Source: https://context7.com/ethereum/eth-account/llms.txt Recovers the checksummed Ethereum address of the signer given a `SignableMessage` and either a (v, r, s) tuple or a raw 65-byte signature. ```python from eth_account import Account from eth_account.messages import encode_defunct message = encode_defunct(text="I♥SF") # Recover from v, r, s tuple (values as int, hex str, or bytes all accepted) vrs = ( 28, "0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb3", "0x3e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce", ) signer = Account.recover_message(message, vrs=vrs) print(signer) # '0x5ce9454909639D2D17A3F753ce7d93fa0b9aB12E' # Recover from concatenated 65-byte signature sig = "0xe6ca9bba58c88611fad66a6ce8f996908195593807c4b38bd528d2cff09d4eb33e5bfbbf4d3e39b1a2fd816a7680c19ebebaf3a141b239934ad43cb33fcec8ce1c" signer2 = Account.recover_message(message, signature=sig) assert signer == signer2 ``` -------------------------------- ### Account.sign_typed_data Source: https://context7.com/ethereum/eth-account/llms.txt Encodes and signs structured typed data per EIP-7702, compatible with MetaMask's eth_signTypedData_v4. Supports both 3-argument and single full_message dict forms. ```APIDOC ## Account.sign_typed_data — EIP-712 structured data signing Encodes and signs structured typed data per EIP-712, compatible with MetaMask's `eth_signTypedData_v4`. Supports both the 3-argument form (`domain_data`, `message_types`, `message_data`) and a single `full_message` dict. ```python from eth_account import Account from eth_account.messages import encode_typed_data key = "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" domain_data = { "name": "Ether Mail", "version": "1", "chainId": 1, "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC", } message_types = { "Person": [ {"name": "name", "type": "string"}, {"name": "wallet", "type": "address"}, ], "Mail": [ {"name": "from", "type": "Person"}, {"name": "to", "type": "Person"}, {"name": "contents", "type": "string"}, ], } message_data = { "from": {"name": "Cow", "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826"}, "to": {"name": "Bob", "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB"}, "contents": "Hello, Bob!", } # One-step sign (recommended) signed = Account.sign_typed_data(key, domain_data, message_types, message_data) print(signed.message_hash.hex()) # 'c5bb16ccc59ae9a3ad1cb8343d4e3351f057c994a97656e1aff8c134e56f7530' # Two-step: encode then sign signable = encode_typed_data(domain_data, message_types, message_data) signed2 = Account.sign_message(signable, key) assert signed == signed2 # Recover signer from EIP-712 signature signer = Account.recover_message(signable, signature=signed.signature) print(signer) # '0x...' ``` ```