Skip to content

Monorepo for Reown's WalletKit Python implementation

License

Unknown, Unknown licenses found

Licenses found

Unknown
LICENSE
Unknown
LICENSE-DOCS
Notifications You must be signed in to change notification settings

actuallyrizzn/walletkit-python

 
 

Repository files navigation

WalletKit Python

Python port of the WalletKit SDK for WalletConnect Protocol.

Status

Production Ready - Full Implementation Complete

Completed

Phase 0: Foundation

  • Virtual environment setup
  • Project structure
  • Testing suite configuration
  • EventEmitter implementation (async support)
  • Storage abstraction (FileStorage, MemoryStorage)
  • JSON-RPC utilities

Phase 1: Core Controllers

  • Type definitions (IWalletKit, IWalletKitEngine)
  • Crypto utilities (X25519, ChaCha20-Poly1305, HKDF)
  • KeyChain implementation
  • Crypto controller (encryption/decryption, key management)
  • URI parsing and formatting utilities
  • Relayer controller (WebSocket communication with reconnection, heartbeat)
  • Pairing controller (URI handling, pairing management)
  • Core class (orchestrates all controllers)

Phase 2: Client API

  • Full SignClient implementation (complete protocol support)
  • Engine controller (SignClient wrapper)
  • WalletKit client (main API with full method surface)
  • Event forwarding and handling
  • Store implementations (SessionStore, ProposalStore, RequestStore)
  • Session authentication support

Phase 3: Additional Controllers

  • Expirer controller (expiry management)
  • EventClient (telemetry)
  • EchoClient (push notifications)
  • Notifications utility

Phase 4: Testing

  • 296+ unit tests passing
  • 81.80% test coverage (exceeds 70% target)
  • Comprehensive test suite covering:
    • Relayer (88% coverage - WebSocket, reconnection, heartbeat)
    • SignClient (78% coverage - all protocol methods, edge cases)
    • Core controllers and utilities
  • Integration test framework

Phase 5: Examples & Documentation

  • Basic wallet example
  • DApp simulator example
  • Full flow example
  • Comprehensive API documentation

Next Steps

  • Integration tests with real WalletConnect relay
  • Error handling improvements (retries, timeouts, reconnection)
  • Performance optimization
  • PyPI distribution

Quick Start

Setup

# Create virtual environment
python -m venv venv

# Activate (Windows)
.\venv\Scripts\Activate.ps1

# Activate (Linux/macOS)
source venv/bin/activate

# Install dependencies
# Option 1: Install all dev dependencies
pip install -e ".[all-dev]"

# Option 2: Install specific groups
pip install -e ".[dev,test]"  # Development and testing tools only

# Option 3: Use requirements files (legacy, pyproject.toml is source of truth)
pip install -r requirements-dev.txt
pip install -e .

Dependency Management

Single Source of Truth: pyproject.toml is the authoritative source for all dependencies.

  • Production dependencies: Defined in [project.dependencies]
  • Optional dependencies: Organized into groups:
    • dev: Development tools (black, flake8, isort, mypy)
    • test: Testing tools (pytest, playwright, etc.)
    • docs: Documentation tools (sphinx)
    • storage: Storage backends (aiosqlite)
    • security: Security auditing (pip-audit)
    • all-dev: Meta-group including dev, test, docs, security

Version Policy:

  • Dependencies use >= lower bounds with upper bounds (e.g., >=11.0.0,<14.0.0)
  • Upper bounds protect against breaking major version changes
  • Regular updates recommended for security and features

Security Monitoring:

  • Run pip-audit regularly to check for vulnerabilities
  • Install with: pip install -e ".[security]" then run pip-audit
  • Consider setting up automated security scanning in CI/CD

Generating Locked Requirements:

# Install pip-tools
pip install pip-tools

# Generate locked requirements.txt from pyproject.toml
pip-compile pyproject.toml -o requirements.txt

# Generate locked requirements-dev.txt
pip-compile pyproject.toml --extra dev --extra test --extra docs --extra security -o requirements-dev.txt

Running Tests

# Run all tests
pytest

# Run with coverage
pytest --cov=walletkit

# Run specific test file
pytest tests/unit/test_events.py

Project Structure

walletkit-python/
├── src/
│   └── walletkit/          # Main package
│       ├── utils/          # ✅ Utilities (events, storage, jsonrpc, crypto, uri)
│       ├── controllers/    # ✅ Controllers (crypto, keychain, relayer, pairing)
│       ├── types/          # ✅ Type definitions
│       ├── constants/      # ✅ Constants
│       └── core.py         # ✅ Core implementation
├── tests/                  # ✅ Test suite
│   ├── unit/              # Unit tests
│   └── integration/        # Integration tests (to be implemented)
├── docs/                   # ✅ Documentation
└── tmp/                    # Reference implementations

Test Results

296+ tests passing ✅
Coverage: 81.80% (exceeds 70% target)
- Relayer: 88% coverage
- SignClient: 78% coverage
- Core utilities: 80%+ coverage

Architecture

The port follows the same architecture as the JavaScript implementation:

  1. Core: Orchestrates all controllers (Crypto, Relayer, Pairing)
  2. Crypto: Handles encryption/decryption, key management
  3. Relayer: Manages WebSocket communication with relay server
  4. Pairing: Handles pairing creation and management
  5. SignClient: Stub implementation (placeholder for full port)
  6. Engine: Wraps SignClient for protocol interactions
  7. WalletKit Client: Main API for wallet integration

Usage Example

Basic Wallet

import asyncio
from walletkit import WalletKit, Core
from walletkit.utils.storage import MemoryStorage

async def main():
    # Initialize Core
    storage = MemoryStorage()
    core = Core(
        project_id="your-project-id",
        storage=storage,
    )
    await core.start()
    
    # Initialize WalletKit
    wallet = await WalletKit.init({
        "core": core,
        "metadata": {
            "name": "My Wallet",
            "description": "My Wallet Description",
            "url": "https://mywallet.com",
            "icons": ["https://mywallet.com/icon.png"],
        },
    })
    
    # Listen for session proposals
    @wallet.on("session_proposal")
    async def on_proposal(event):
        proposal_id = event.get("id")
        # Approve session
        await wallet.approve_session(
            id=proposal_id,
            namespaces={
                "eip155": {
                    "chains": ["eip155:1"],
                    "methods": ["eth_sendTransaction", "eth_sign"],
                    "events": ["chainChanged"],
                },
            },
        )
    
    # Pair with a URI from a dApp
    await wallet.pair("wc:...")
    
    # Keep running
    await asyncio.Event().wait()

asyncio.run(main())

Basic DApp

import asyncio
from walletkit import WalletKit, Core
from walletkit.utils.storage import MemoryStorage

async def main():
    # Initialize
    storage = MemoryStorage()
    core = Core(project_id="your-project-id", storage=storage)
    await core.start()
    
    dapp = await WalletKit.init({
        "core": core,
        "metadata": {
            "name": "My DApp",
            "description": "My DApp Description",
            "url": "https://mydapp.com",
            "icons": ["https://mydapp.com/icon.png"],
        },
    })
    
    # Create pairing URI
    pairing = await dapp.core.pairing.create({
        "methods": ["wc_sessionPropose"],
    })
    uri = pairing.get("uri")
    
    print(f"Share this URI with wallet: {uri}")
    
    await asyncio.Event().wait()

asyncio.run(main())

See examples/ directory for complete runnable examples.

Documentation

See docs/ folder for comprehensive documentation:

Quick Reference

Wallet Integration

from walletkit import WalletKit, Core
from walletkit.utils.storage import MemoryStorage

# Initialize
storage = MemoryStorage()
core = Core(project_id="your-project-id", storage=storage)
await core.start()

wallet = await WalletKit.init({
    "core": core,
    "metadata": {
        "name": "My Wallet",
        "description": "My Wallet Description",
        "url": "https://mywallet.com",
        "icons": ["https://mywallet.com/icon.png"],
    },
})

# Handle session proposals
@wallet.on("session_proposal")
async def on_proposal(event):
    proposal_id = event.get("id")
    # Auto-approve or show UI
    await wallet.approve_session(
        id=proposal_id,
        namespaces={
            "eip155": {
                "chains": ["eip155:1"],
                "methods": ["eth_sendTransaction", "eth_sign"],
                "events": ["chainChanged", "accountsChanged"],
            },
        },
    )

# Handle requests
@wallet.on("session_request")
async def on_request(event):
    topic = event.get("topic")
    request_id = event.get("id")
    # Process request and respond
    await wallet.respond_session_request(
        topic=topic,
        response={
            "id": request_id,
            "jsonrpc": "2.0",
            "result": "0x...",
        },
    )

# Pair with dApp
await wallet.pair("wc:...")

DApp Integration

from walletkit import WalletKit, Core
from walletkit.utils.storage import MemoryStorage

# Initialize
storage = MemoryStorage()
core = Core(project_id="your-project-id", storage=storage)
await core.start()

dapp = await WalletKit.init({
    "core": core,
    "metadata": {
        "name": "My DApp",
        "description": "My DApp Description",
        "url": "https://mydapp.com",
        "icons": ["https://mydapp.com/icon.png"],
    },
})

# Create pairing URI
pairing = await dapp.core.pairing.create({
    "methods": ["wc_sessionPropose"],
})
uri = pairing.get("uri")
print(f"Share this URI: {uri}")

# Wait for session approval
@dapp.on("session_approve")
async def on_approve(event):
    session = event.get("session")
    topic = session.get("topic")
    print(f"Session approved: {topic}")

# Send request
await dapp.engine.request({
    "topic": topic,
    "chainId": "eip155:1",
    "request": {
        "method": "eth_sendTransaction",
        "params": {
            "to": "0x...",
            "value": "0x0",
        },
    },
})

License

Code: Licensed under the GNU Affero General Public License v3.0 (AGPLv3). See LICENSE for details.

Documentation and other non-code materials: Licensed under Creative Commons Attribution-ShareAlike 4.0 International (CC-BY-SA-4.0). See LICENSE-DOCS for details.

About

Monorepo for Reown's WalletKit Python implementation

Resources

License

Unknown, Unknown licenses found

Licenses found

Unknown
LICENSE
Unknown
LICENSE-DOCS

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published

Languages

  • Python 100.0%