When to read this
- You’re building a custom relayer
- You’re implementing a new chain adapter
- You’re auditing the protocol security
- You want to understand how codes are derived
Performance
The protocol is designed for speed:Two Strategies
Action Codes supports two code generation strategies:Wallet Strategy (Default)
Direct code generation from a user’s wallet. This is what most apps use. How it works:- User’s wallet signs a canonical message
- Code is derived using HMAC-SHA256 with the signature as entropy
- Codes are cryptographically bound to the wallet’s public key
- Validation is immediate — no external dependencies
Delegation Strategy (Advanced)
Pre-authorize a delegated keypair to generate codes on behalf of a wallet. Enables relayer services and automated workflows. How it works:- User signs a delegation proof specifying: delegated keypair, chain, expiration
- Delegated keypair generates codes bound to the proof
- Relayers validate both the delegation proof AND the code signature
- Stolen proofs cannot generate codes (require delegated private key)
- Relayers cannot generate codes (only validate)
- Cross-proof attacks are prevented through cryptographic binding
Core Concepts
Code derivation
Action Codes are deterministically derived:- signature — Wallet signature over canonical message (secret entropy)
- pubkey — User’s wallet public key
- timestamp — Current time, rounded to 2-minute windows
- Unpredictable — Cannot be guessed without the signature
- Verifiable — Can be validated with the signature
- Time-bound — Expire after ~2 minutes
Canonical messages
Every code generation involves signing a deterministic JSON message:Protocol Meta
Metadata attached to transactions:
Maximum size: 512 bytes. When
iss is present, both issuer and intent owner must sign.
Architecture
Components
The Relayer
The relayer is a trusted intermediary that:- Validates codes — Verifies signature, timestamp, format
- Stores state — Encrypted transaction/message payloads
- Coordinates flow — Connects apps and wallets
- Enforces expiry — Rejects expired codes
Security Model
Threat mitigations
For full security details, see Security & Determinism.
Using the Protocol Package
For low-level protocol access:Most applications should use
@actioncodes/sdk instead, which wraps the protocol with a simpler API and handles relayer communication.Chain Adapters
Adapters provide chain-specific functionality:Best Practices
- Set appropriate TTL — Balance security vs. user experience
- Validate server-side — Never trust client-only validation
- Use delegation carefully — Set short expiration windows
- Monitor relayer activity — Watch for unusual patterns
- Handle expiry gracefully — Prompt users to regenerate codes