Relayer
Relayers submit transactions on your behalf. Most users interact via relayer for all operations.
Why Relayers?
- No ETH needed - Users don't need gas tokens
- Privacy - Your EVM address isn't the
msg.sender - UX - Single flow regardless of operation type
User creates proof/signature locally
│
▼
Sends to relayer (off-chain)
│
▼
Relayer submits tx
│
▼
Contract verifies proof (not msg.sender)
Authorization Model
| Operation | Authorization | How It Works |
|---|---|---|
| Register BPK | EIP-712 signature | User signs typed data, relayer submits |
| Shield | EIP-2612 permit | User signs permit, relayer pulls tokens |
| Transfer | ZK proof | Proof proves BPK ownership — no signature needed |
| Unshield | ZK proof | Proof proves BPK ownership — no signature needed |
Key insight: For transfer and unshield, the ZK proof IS the authorization. The contract verifies the proof, not msg.sender. This means any relayer can submit the transaction without any trust.
SDK Usage
The SDK handles relayer interaction transparently — just pass useRelayer: true:
const client = await createClient({
chainId: 8453,
relayerUrl: 'https://eb-relayer.zkprivacy.dev',
});
const wallet = client.wallet({ spendingKey: keys.spendingKey, account });
await wallet.USD.registerBPK();
await wallet.USD.shield({ amount: 100_000000n, useRelayer: true });
await wallet.USD.transfer({
to: 'zk1qyp5xs...',
amount: 50_000000n,
useRelayer: true,
});
await wallet.USD.unshield(50_000000n, undefined, { useRelayer: true });
The SDK generates the proof or signature locally, sends it to the relayer, and the relayer submits the transaction on-chain. The user never pays gas.
What Relayer Learns
| Information | Relayer Knows? |
|---|---|
| That you're submitting a tx | Yes |
| Timing of submission | Yes |
| Transfer amount | No (encrypted) |
| Your identity | No (if using Tor) |