Batch transactions¶
Set shouldBatchInMulticall: true on a submission and Photon may combine it with other opted-in transactions on the same chain into a single Multicall3 call. One on-chain transaction carries the whole batch, so the fixed per-transaction overhead is paid once and the cost is shared among the members.
Batching is best-effort: the flag is permission to batch, not a guarantee. If no batch forms, your transaction relays solo with no error and no change in behavior — you never need to handle a "batching unavailable" case.
How a batch forms¶
- You submit with
shouldBatchInMulticall: truevia Submit a transaction. - When Photon picks up an eligible transaction, it holds a short gather window (500 ms) so other opted-in transactions on the same chain can join. A batch carries at most 10 members.
- If at least 2 eligible transactions are gathered, Photon encodes them as one Multicall3
aggregate3Valuecall — the well-known Multicall3 deployment at0xcA11bde05977b3631167028862bE2a173976CA11— and relays that single transaction. Each member'svalueis forwarded to its target. - Every member keeps its own
txIdand status; all members share the sameexecutionTxHash.
Eligibility¶
A transaction can join a batch only if all of the following hold:
- Same chain (and same relaying region — see Region routing) as the other members.
transactionTypeis"flash"(the default).- No
authorizationList— EIP-7702 submissions always relay solo. - No gas overrides:
gasPrice,maxFeePerGas/maxPriorityFeePerGas, andgasLimitmust all be unset.
Transactions that carry the flag but fail an eligibility check are simply relayed solo.
Atomic execution¶
Batches execute atomically: every call is submitted with allowFailure = false, so if any member reverts, the entire batch reverts.
When a batch fails on-chain, Photon automatically clears each member's batch flag and retries every member as a solo transaction, where it succeeds or fails on its own merits. You do not need to resubmit.
Cost split¶
The batch's total cost is split evenly across its members: each member's costUSD is the batch cost divided by the member count. This is a deliberate simplification — there is no per-call gas attribution.
Info
An even split means a cheap call batched with an expensive one pays more than it would alone, and vice versa. Opt in transactions of broadly similar cost — token transfers, claims, mints — and leave heavyweight calls solo.
Silent solo fallback¶
Your transaction relays solo, without any error, when:
- Fewer than 2 eligible transactions arrive within the gather window.
- Multicall3 has no code on the target chain (checked once per chain; batching is disabled there).
- The transaction fails any eligibility check above.
Opting in¶
Requires an api-key header — Get API access.
curl -X POST https://photon.example.com/api/submit-tx \
-H "api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49",
"callData": "0xa9059cbb000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000de0b6b3a7640000",
"chainId": 84532,
"shouldBatchInMulticall": true,
"label": "airdrop-claim-42"
}'
const res = await fetch("https://photon.example.com/api/submit-tx", {
method: "POST",
headers: { "api-key": "YOUR_API_KEY", "Content-Type": "application/json" },
body: JSON.stringify({
to: "0x3dbE34f2C21b3B2980d4dc53f3c7E51e39663F49",
callData: "0xa9059cbb000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb922660000000000000000000000000000000000000000000000000de0b6b3a7640000",
chainId: 84532,
shouldBatchInMulticall: true,
label: "airdrop-claim-42",
}),
});
const body = await res.json();
Response — 201 Created:
{
"success": true,
"data": {
"txId": "68fa3450539a3c9d28bbca33",
"estimatedCostUSD": 0.01
},
"timestamp": "2026-07-29T09:15:12.345Z"
}
Poll Get transaction status to see the final costUSD and the shared executionTxHash once the batch lands.