Wallet - Usage Examples
Example 1: Basic Wallet Lifecycle
Create a wallet, sign a message, verify it, and generate a backup.
from codomyrmex.wallet import WalletManager
# Initialize manager
wallet_mgr = WalletManager()
# Create wallet
address = wallet_mgr.create_wallet("agent_001")
print(f"Wallet created: {address}") # 0x1a2b3c...
# Sign a message
message = b"Authorize transfer of 100 units"
signature = wallet_mgr.sign_message("agent_001", message)
print(f"Signature: {signature.hex()}")
# Verify the signature
is_valid = wallet_mgr.verify_signature("agent_001", message, signature)
print(f"Valid: {is_valid}") # True
# Generate backup metadata
backup = wallet_mgr.backup_wallet("agent_001")
print(f"Backup: {backup}")
Expected Outcome
A wallet address is created, a message is signed with HMAC-SHA256, the signature verifies correctly, and backup metadata (with key hash, never raw key) is returned.
Example 2: Natural Ritual Recovery
Set up knowledge-based recovery and test the recovery flow.
import hashlib
from codomyrmex.wallet import NaturalRitualRecovery, RitualStep, hash_response
recovery = NaturalRitualRecovery()
# Define recovery ritual with secret knowledge
steps = [
RitualStep("What was your first pet's name?", hash_response("Whiskers")),
RitualStep("What city were you born in?", hash_response("Portland")),
RitualStep("What was your childhood nickname?", hash_response("Sparky")),
]
recovery.register_ritual("agent_001", steps)
# Successful recovery
success = recovery.initiate_recovery("agent_001", ["Whiskers", "Portland", "Sparky"])
print(f"Recovery succeeded: {success}") # True
# Failed recovery (wrong answer)
failed = recovery.initiate_recovery("agent_001", ["Fluffy", "Portland", "Sparky"])
print(f"Recovery succeeded: {failed}") # False
print(f"Remaining attempts: {recovery.get_remaining_attempts('agent_001')}")
Expected Outcome
Recovery succeeds with correct answers and fails with incorrect ones. Attempt counter decrements on failure.
Example 3: Key Rotation with Policy
Track signatures and rotate keys when policy thresholds are reached.
from codomyrmex.wallet import WalletManager, KeyRotation, RotationPolicy
# Create wallet
wallet_mgr = WalletManager()
address = wallet_mgr.create_wallet("agent_002")
# Set up rotation tracking with aggressive policy
policy = RotationPolicy(max_age_days=30, max_signatures=100)
rotation = KeyRotation(policy=policy)
rotation.register_wallet("agent_002", address)
# Simulate signing operations
for _ in range(100):
wallet_mgr.sign_message("agent_002", b"data")
rotation.record_signature("agent_002")
# Check if rotation is needed
if rotation.needs_rotation("agent_002"):
old_address = address
new_address = wallet_mgr.rotate_keys("agent_002", reason="signature_limit")
rotation.record_rotation("agent_002", old_address, new_address, "signature_limit")
print(f"Rotated: {old_address} -> {new_address}")
# View rotation history
history = rotation.get_rotation_history("agent_002")
for record in history:
print(f" {record.timestamp}: {record.reason}")
Expected Outcome
After 100 signatures, needs_rotation() returns True. Keys are rotated and the event is recorded in the audit trail.
Example 4: Wallet Facade (Simplified API)
Use the Wallet class for a streamlined single-user experience.
from codomyrmex.wallet import RitualStep, hash_response
from codomyrmex.wallet.wallet import Wallet
# Create and use a wallet
w = Wallet("agent_003")
address = w.create()
print(f"Active: {w.is_active}, Address: {w.address}")
# Sign and verify
sig = w.sign(b"Hello World")
assert w.verify(b"Hello World", sig)
# Set up recovery
w.setup_recovery([
RitualStep("Color?", hash_response("Blue")),
RitualStep("Number?", hash_response("42")),
])
# Rotate keys
new_address = w.rotate(reason="periodic")
print(f"New address: {new_address}")
# Create backup
backup = w.backup()
print(f"Backup timestamp: {backup['backup_ts']}")
Expected Outcome
Complete wallet lifecycle through the simplified facade: create, sign, verify, set up recovery, rotate, and backup.
Example 5: Backup Manager
Create and verify persistent backup files.
from pathlib import Path
from codomyrmex.wallet import WalletManager, BackupManager
wallet_mgr = WalletManager()
address = wallet_mgr.create_wallet("agent_004")
# Create backup manager sharing the same key manager
backup_mgr = BackupManager(key_manager=wallet_mgr.key_manager)
# Create a backup
record = backup_mgr.create_backup(
"agent_004", address, metadata={"note": "pre-rotation backup"}
)
print(f"Backup ID: {record['backup_id']}")
# List backups
backups = backup_mgr.list_backups("agent_004")
print(f"Total backups: {len(backups)}")
# Verify backup integrity
is_valid = backup_mgr.verify_backup("agent_004", record["backup_id"])
print(f"Backup valid: {is_valid}") # True
# After key rotation, backup becomes stale
wallet_mgr.rotate_keys("agent_004")
is_still_valid = backup_mgr.verify_backup("agent_004", record["backup_id"])
print(f"Backup still valid: {is_still_valid}") # False (key changed)
Expected Outcome
Backup is created, listed, and verified. After key rotation, the backup's key hash no longer matches the current key, so verification returns False.
Common Pitfalls & Troubleshooting
-
Issue:
WalletError: User already has a wallet- Solution: Check with
has_wallet()before callingcreate_wallet(), or useget_wallet_address()to retrieve the existing wallet.
- Solution: Check with
-
Issue:
WalletNotFoundError: Wallet not found or locked- Solution: Ensure the wallet was created in the same
WalletManagerinstance (wallets are not persisted across restarts in v0.1.0).
- Solution: Ensure the wallet was created in the same
-
Issue:
RitualError: User is locked out- Solution: The user has exhausted recovery attempts. An admin must call
reset_attempts()to unlock.
- Solution: The user has exhausted recovery attempts. An admin must call
-
Issue: Recovery always fails
- Solution: Ensure responses are hashed with
hash_response()when creatingRitualStepobjects, and that the exact plaintext responses are provided during recovery (case-sensitive).
- Solution: Ensure responses are hashed with
-
Issue: Backup verification fails after rotation
- Solution: This is expected. Create a new backup after each key rotation.