Transaction Structure
A Radix transaction has three layers, each wrapping the previous:
| Layer | Contains | Purpose |
|---|---|---|
| Intent | Header + manifest | Defines what to do and when |
| Signed Intent | Intent + signatures | Authorizes the transaction |
| Notarized Transaction | Signed intent + notary signature | Final submission-ready payload |
The header specifies the validity window (epoch range, ~5 min per epoch), the notary's public key, and a nonce. The manifest contains the instructions.
Build → Sign → Submit
1. Build
Construct the transaction intent with a manifest and header. The epoch window determines how long the transaction remains valid — typically the current epoch ± 2.
2. Sign
One or more parties sign the intent hash with their private keys (Ed25519 or ECDSA secp256k1). For wallet-submitted transactions, the dApp Toolkit handles this automatically.
3. Notarize
The notary signs the signed intent hash. In most dApps, the wallet acts as both signer and notary.
4. Submit
The compiled payload is sent to the network via the Gateway or Core API.
5. Track
Poll the transaction status using the intent hash. Outcomes:
- Committed — accepted on ledger (success or application-level failure)
- Permanently rejected — invalid structure or expired epoch
- Temporarily rejected — may become valid later (e.g., pending dependency)
Subintents and Pre-Authorization
Subintents are independent mini-transactions that compose into a single atomic transaction. Each subintent has its own manifest, header, and signers.
Why Subintents?
- Delegated fee payment — a dApp pays fees on behalf of the user, solving the "double onboarding" problem (user needs XRD before they can do anything)
- Peer-to-peer trading — buyer and seller each sign a subintent; a matchmaker combines them into an atomic swap
- Flash loans — a lending subintent provides liquidity, the user's subintent uses it, and a payback subintent returns it — all atomically
Key Instructions
# Parent defines a child subintent
DEFINE_CHILD SubintentHash("deadbeef...");
# Parent yields to child
YIELD_TO_CHILD SubintentHash("deadbeef...") Expression("ENTIRE_WORKTOP");
# Child yields back to parent
YIELD_TO_PARENT Expression("ENTIRE_WORKTOP");Pre-Authorization Flow
Pre-authorization lets users sign subintents in advance. The dApp can later combine them with its own subintents and submit whenever ready.
- dApp sends a pre-auth request to the wallet with a subintent manifest
- User reviews and signs in the wallet
- Wallet returns the signed subintent to the dApp
- dApp combines it with other subintents and submits as a complete transaction
Practical example
A user pre-authorizes "swap 100 USDC for GBP" via a subintent. The dApp adds a fee-payment subintent and submits the combined transaction — the user never needs to hold XRD for fees.
