The core idea
Instead of your app connecting to the user’s wallet directly, the user generates a short-lived code in their wallet app. Your app uses this code to request actions, and the user approves them in their wallet.The lifecycle
Every action code goes through these stages:Generated
User visits actioncode.app and generates a code tied to their wallet.Code is: 8 digits, valid for ~2 minutes, tied to one wallet
Shared
User copies the code and shares it with your app — via text input, chat message, or any other method.Your app: Receives the code and calls
client.resolve(code) to verify itAttached
Your app attaches an action (transaction or message) to the code.Your app: Calls
client.attachTransaction(code, tx) or client.attachMessage(code, msg)User sees: The pending request appears in actioncode.appApproved
User reviews the request in actioncode.app and approves it with their wallet.User wallet: Signs the transaction or message
Status flow
| Status | Meaning |
|---|---|
pending | Code exists, nothing attached yet |
attached | Action attached, waiting for user approval |
finalized | User approved, signature available |
expired | Code timed out (codes live ~2 minutes) |
Where users get codes
Users generate codes at actioncode.app.Open in wallet browser
User opens actioncode.app in their wallet’s built-in browser (Phantom, Solflare, Backpack, etc.)
Why this design?
| Benefit | How |
|---|---|
| No wallet in your app | You never handle private keys or wallet connections |
| Works everywhere | Bots, CLIs, embedded apps — anywhere you can accept 8 digits |
| User stays in control | They approve each action explicitly in their wallet |
| Short-lived | Codes expire in ~2 minutes, limiting exposure |
| One-time use | Each code can only be used once |
SDK methods by stage
| Stage | SDK Method | What it does |
|---|---|---|
| Verify | client.resolve(code) | Check code validity, get wallet address |
| Attach | client.attachTransaction(code, tx) | Attach a transaction for signing |
| Attach | client.attachMessage(code, msg) | Attach a message for signing |
| Watch | client.observeStatus(code) | Stream status updates |
| Check | client.getStatus(code) | One-time status check |