Skip to main content

Circuitpython module for ethereum wallet creation and signing

Project description

CircuitPython_MiniEthers

Introduction

Documentation Status Discord Build Status Code Style: Ruff

Circuitpython module for ethereum wallet creation and signing

Dependencies

This driver depends on:

Please ensure all dependencies are available on the CircuitPython filesystem. This is easily achieved by downloading the Adafruit library and driver bundle or individual libraries can be installed using circup.

Installing from PyPI

On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally from PyPI. To install for current user:

pip3 install circuitpython-miniethers

To install system-wide (this may be required in some cases):

sudo pip3 install circuitpython-miniethers

To install in a virtual environment in your current project:

mkdir project-name && cd project-name
python3 -m venv .venv
source .env/bin/activate
pip3 install circuitpython-miniethers

Installing to a Connected CircuitPython Device with Circup

Make sure that you have circup installed in your Python environment. Install it with the following command if necessary:

pip3 install circup

With circup installed and your CircuitPython device connected use the following command to install:

circup install miniethers

Or the following command to update an existing version:

circup update

Usage Example

Simple example showcasing wallet creation and message signing.

from circuitpython_miniethers import Signature, Wallet

# The private key is used for both signing methods
# IMPORTANT: In a real app, never hardcode private keys.
# Use environment variables or a secure wallet connection.
privateKey = "0x022b99092266a16a949e6a450f0e88a8288d39d5f1d75c00575a35a0ba270dbc"

# Create a wallet instance from the private key
wallet = Wallet(privateKey)


def generateFlatSignature():
    """
    Signs a simple string message (ERC-191).
    """
    print("--- Signing a Flat String (ERC-191) ---")

    # The message to sign
    message = "hello"

    print(f'Signing message: "{message}"')
    print(f"Signer Address: {wallet.address}")
    print("---")

    flatSignature = wallet.signMessage(message)

    print("Full Flat Signature:", flatSignature)

    # For comparison, let's split the signature into its components
    signature = getattr(Signature, "from")(flatSignature)
    print("Signature Components:")
    print("  r:", signature.r)
    print("  s:", signature.s)
    print("  v:", signature.v)
    print("-----------------------------------------\n")


def signTypedDataMail():
    """
    Signs structured typed data (EIP-712).
    This provides more readable and secure signing prompts in wallets like MetaMask.
    """
    print("--- Signing Typed Data (EIP-712) ---")

    # 1. The Domain Separator: Defines the context of the signature.
    # This prevents a signature from being valid in a different application.
    domain = {
        # The user-friendly name of the signing domain
        "name": "Ether Mail",
        # The current version of the signing domain
        "version": "1",
        # The chain ID of the intended network (1 for Ethereum Mainnet)
        "chainId": 1,
        # The address of the contract that will verify the signature
        "verifyingContract": "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
    }

    # 2. The Types: Defines the structure of the data being signed.
    # You define your primary type ("Mail") and any custom nested types ("Person").
    types = {
        "Person": [
            {"name": "name", "type": "string"},
            {"name": "wallet", "type": "address"},
        ],
        "Mail": [
            {"name": "from", "type": "Person"},  # Nested custom type
            {"name": "to", "type": "Person"},  # Nested custom type
            {"name": "contents", "type": "string"},
        ],
    }

    # 3. The Value: The actual data object to be signed.
    # This object must match the structure defined in `types`.
    value = {
        "from": {
            "name": "Cow",
            "wallet": "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
        },
        "to": {
            "name": "Bob",
            "wallet": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
        },
        "contents": "Hello, Bob! This is a typed message.",
    }

    print("Signing EIP-712 data for address:", wallet.address)
    print("Domain:", domain)
    print("Value:", value)
    print("---")

    # The `_signTypedData` method handles hashing the structured data according to the EIP-712 spec.
    signature = wallet._signTypedData(domain, types, value)

    print("EIP-712 Signature:", signature)
    print("------------------------------------\n")


# Run both signing functions
def main():
    print("CircuitPython MiniEthers - Ethers.js Compatibility Test\n")
    print(f"Wallet Address: {wallet.address}")
    print(f"Private Key: {wallet.privateKey}")
    print(f"Public Key: {wallet.publicKey}\n")

    generateFlatSignature()
    signTypedDataMail()

    print("\n✅ All tests completed successfully!")


if __name__ == "__main__":
    main()

Documentation

API documentation for this library can be found on Read the Docs.

For information on building library documentation, please check out this guide.

Contributing

Contributions are welcome! Please read our Code of Conduct before contributing to help this project stay welcoming.

PS

I participated in EthGlobal New Delhi this year where me and my team created a hardware wallet for our project. For that purpose we chose a Raspberry Pi Pico. And that is when we realised that the hardware is pretty constrained which doesnt allow existing libraries to work. So I wrote a package that worked on the Pico.

And after some time I decided that I should package this properly and share it as a library, so that people can use this if they want to. That’s the story behind this package.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

circuitpython_miniethers-1.0.0.tar.gz (43.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

circuitpython_miniethers-1.0.0-py3-none-any.whl (18.7 kB view details)

Uploaded Python 3

File details

Details for the file circuitpython_miniethers-1.0.0.tar.gz.

File metadata

  • Download URL: circuitpython_miniethers-1.0.0.tar.gz
  • Upload date:
  • Size: 43.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for circuitpython_miniethers-1.0.0.tar.gz
Algorithm Hash digest
SHA256 1cf845e80abe2a8b21ed123bfcde46c3fe50cb15f9ad8aa2537fad13cb57a43f
MD5 32c805f6aa2c487a178b425d58286638
BLAKE2b-256 14cdbfc0f3dd279a660aa24501bf3f6ef436fdb778cad21c503998cece0c8bf4

See more details on using hashes here.

Provenance

The following attestation bundles were made for circuitpython_miniethers-1.0.0.tar.gz:

Publisher: release_pypi.yml on ShambaC/CircuitPython_MiniEthers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file circuitpython_miniethers-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for circuitpython_miniethers-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 bb8ca38f8b69aef219f88d3b1caf99884d424a0498c46f8e34f2bc097954db2d
MD5 83fb30a6011d03fb74f7361e886d1f19
BLAKE2b-256 293aab42bec746ea557e154827e0b40a43ec333de05a228ec00ed1173ceabf30

See more details on using hashes here.

Provenance

The following attestation bundles were made for circuitpython_miniethers-1.0.0-py3-none-any.whl:

Publisher: release_pypi.yml on ShambaC/CircuitPython_MiniEthers

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page