This feature is available for all Dynamic v3 embedded wallets (TSS-MPC). Upgrade is required if you are on v2 or earlier.
Overview
Transaction Review lets you approve or deny embedded wallet signing requests from your own backend before Dynamic signs them. Dynamic sends each signing request to a webhook endpoint you control; your endpoint returns an approve or deny decision.
Transaction Review complements Policies & Rules. Policies enforce rules you configure in the dashboard; Transaction Review delegates the decision to your own service. Both apply before a transaction is signed.
How it works
- A user initiates a signing operation (EVM transaction, Solana transaction, message signing, or others).
- Before signing, Dynamic sends a
POST request with the signing context to your webhook URL.
- Your endpoint returns
{ "proceed": true } to approve, or { "proceed": false, "reason": "..." } to deny.
- If the request is denied, Dynamic returns a
TransactionReviewDenied error to the SDK. The signing is blocked and the transaction is not submitted.
If your webhook is unreachable or times out, the outcome is determined by your configured failure policy.
Configuration
Configure your webhook from the Dynamic dashboard under Wallets → Transaction Review.
| Field | Description |
|---|
| Webhook URL | HTTPS endpoint that receives signing requests. |
| Webhook Secret | Shared secret used to verify requests came from Dynamic. Optional but recommended. |
| Response Verification Key | Your Ed25519 public key in PEM format. If set, Dynamic verifies your response signature. |
| Failure Policy | DENY (default) blocks signing if your webhook is unreachable; ALLOW proceeds. |
Dynamic sends a POST request with Content-Type: application/json.
| Header | Description |
|---|
Content-Type | application/json. |
x-dynamic-signature | HMAC-SHA256 hex digest of the raw request body, signed with your webhook secret. Present only if a secret is configured. |
Body
shareSetType values
| Value | Meaning |
|---|
rootUser | Standard user wallet. |
delegated | Delegated signing (server-side on behalf of user). |
server | Server-initiated signing. |
context fields
The context object contains chain-specific transaction details. Only one field is populated per request.
EVM transaction (evmTransaction)
EVM UserOperation (evmUserOperation)
For ERC-4337 account abstraction:
Solana transaction (svmTransaction)
Solana message (svmMessage)
A raw base64-encoded message string.
EVM typed data (evmTypedData)
EIP-712 structured data for eth_signTypedData requests.
EVM message (evmMessage)
Plain message signing (personal_sign).
Your endpoint must return 200 OK with a JSON body.
To approve:
To deny:
The reason field is optional but recommended. It appears in Dynamic’s logs and events for debugging.
Your endpoint must respond within 5 seconds. A timeout is treated as a failure and falls back to your failure policy.
Verifying requests (HMAC signature)
If you configure a Webhook Secret, Dynamic includes an x-dynamic-signature header containing an HMAC-SHA256 hex digest of the raw request body. Verify this signature before parsing or acting on the body.
HMAC verification requires the exact raw bytes. Use express.raw({ type: 'application/json' }), not express.json(), and parse the body yourself with JSON.parse(req.body.toString()). express.json() mutates the payload (whitespace and key order) and breaks signature verification. The rule examples below reuse the same raw-body setup and the isSignatureValid guard defined here. Always verify the signature before parsing or acting on the body.
Signing responses (Ed25519)
If you configure a Response Verification Key, Dynamic verifies that your webhook response was signed with the corresponding Ed25519 private key. This prevents response tampering by an intermediary.
Generating a key pair
Signing your response
Your endpoint must include an x-dynamic-response-signature header containing the Base64-encoded Ed25519 signature of the raw response body bytes.
Sign the raw bytes of the response body exactly as sent. Do not re-serialize. Any difference in whitespace or key ordering fails verification.
Failure policy
The failure policy determines the outcome when your webhook is unreachable or times out.
| Policy | Behavior when the webhook is unreachable or times out |
|---|
DENY (default) | Signing is blocked; the user receives a TransactionReviewDenied error. |
ALLOW | Signing proceeds as if approved. |
Choose ALLOW only if you prefer availability over strict enforcement and trust your infrastructure to handle outages.
Events
Dynamic emits events you can subscribe to via webhooks for observability.
| Event | Description |
|---|
waas.transaction.review.approved | Transaction review passed; signing will proceed. |
waas.transaction.review.denied | Transaction review denied; signing was blocked. |
Example: Block transactions to specific contracts
Example: Solana — inspect program instructions
Testing your webhook
Use a tool like ngrok to expose a local server during development:
Set the generated HTTPS URL as your webhook URL in the Dynamic dashboard. Use a sandbox environment to test without affecting production.
Dashboard test panel
Once your webhook URL is in the form, the Transaction Review side panel exposes a Test webhook card with a scenario dropdown and a Send test button. Select a scenario (Sign message, EVM transaction, EVM token transfer, EVM user operation, EVM typed data, or Solana transaction) and click Send test to drive a synthetic payload through the same HMAC signing, response signature verification, timeout, and failure-policy code paths as live signing. The test panel emits no events, performs no signing, and writes nothing to the database.
The result panel shows the decision, latency, HTTP status, signature verification state, and the full request and response bodies, so you can iterate on your endpoint without issuing a real transaction.
To simulate a denied response and verify your SDK error handling:
The SDK surfaces this as:
Reference implementation
For a complete, runnable starting point, see the Transaction Review webhook example server. It verifies inbound HMAC signatures, optionally Ed25519-signs responses, and exposes hot-switchable allow, deny, slow, and crash modes for end-to-end testing against the dashboard test panel.