Relayer
A relayer broadcasts users' zero-knowledge proofs on-chain so users pay no gas and their wallet never touches the transaction. It charges a flat fee plus a percentage, paid in the transacted token.
What is a Relayer?
A relayer is a node that submits RAIL20 transactions for users. The user signs a message and sends the transfer details; the relayer derives the account keys, builds the zero-knowledge proof, pays the gas, and broadcasts it. Because the user's own wallet never sends the transaction, there is no on-chain link between the user's public address and the pool activity.
Why Use a Relayer?
Transacting directly from your own wallet leaks metadata - your public address, IP, and timing. Routing through a relayer breaks that link, and it lets you transact without holding ETH for gas: the relayer fronts gas and deducts its fee from the transacted token.
Relayer Fee
The relayer fee is a flat amount plus a percentage of the transacted value. Fees are paid to the RAIL20 fee recipient 0xd962c7a67b74EEe8D418189f7917A18577A4775d. There is no on-chain fee-splitting contract and no revenue-sharing tiers.
| Pool | Flat fee | Percentage |
|---|---|---|
| ETH pool | 0.00025 ETH | 0.35% |
| USDC pool | 1 USDC | 0.35% |
How It Works
1. User signs the RAIL20 message (derives account keys in the browser)
2. User POSTs { signature, pool, amount, recipient } to the relayer (/api/withdraw)
3. Relayer derives the keys, scans the pool, and selects the user's notes
4. Relayer builds the zk-SNARK proof (2 inputs, 2 outputs) and checks nullifier status
5. Relayer submits the transact() call to the token's pool and pays gas
6. Relayer fee (flat + 0.35%) is taken from the transacted token
7. Pool verifies the proof, records nullifiers, inserts commitmentsRelayer API
The hosted relayer is served from https://api.rail20.org. Key endpoints:
| Endpoint | Purpose |
|---|---|
/api/health | Relayer status and liveness |
/api/balance | Derive shielded balance from notes |
/api/deposit/prepare | Prepare a shield (deposit) |
/api/withdraw | Relay a private withdraw / transfer proof |
/api/assets | Supported tokens and pools |
/api/intent-status | Poll cross-chain intent settlement |
Relaying a Withdrawal
The client sends its account signature and the transfer details; the relayer derives the account keys, builds the zero-knowledge proof, and broadcasts the transaction. The proof is not constructed by the caller.
// Relay a private withdraw / transfer through the hosted relayer.
const res = await fetch("https://api.rail20.org/api/withdraw", {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
signature, // wallet signature; derives the account keys
pool: "usdc", // "eth" or "usdc" (defaults to "eth")
amount: "60", // amount to send
recipient: bobAddress, // recipient (shielded address, or public for a withdraw)
// Batch (max 2, circuit 2-output limit):
// recipients: [{ address, amount }, { address, amount }]
}),
});
const { txHash } = await res.json();