IPrivacy.batchTransferWithAuthorization
batchTransferWithAuthorization(
bytes32 batchId,
AuthorizedTransferItem[] items
) external returns (bool success) Submits a multi-proof batch on behalf of one or more effective senders — each items[i] carries a PrivacyTransferRequest and a PrivacyActionAuthorization whose signature covers that specific item's request under the shared batchId and per-item batchItemIndex. The caller (msg.sender) is recorded as the executor on every authorization; a mismatch between the recovered signer and authorization.effectiveSender, an expired deadline, or a reused nonce reverts the entire batch. The 20-item protocol limit (MaxPrivacyMultiProofBatchItems) is enforced identically to the direct batchTransfer path.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
batchId | bytes32 | ✓ | Shared batch identifier that every authorization.batchId field must match. Should be unique per submission; typically random 32 bytes generated by the executor. |
items | AuthorizedTransferItem[] | ✓ | Between 1 and 20 items, each pairing a PrivacyTransferRequest with its signed PrivacyActionAuthorization. Every item's authorization.batchItemIndex MUST equal its 0-based position in the array — otherwise digest recomputation fails and the batch reverts. |
Returns
bool Returns true when every authorization verifies and every proof applies.
Examples
Submit an authorized batch as an executor
The executor generates batchId first, then hands it to every effective sender so their EIP-712 signatures are bound to the same batch. Client-side index checks catch mislabeled positions before the transaction is sent.
import { createWalletClient, http, toHex, randomBytes } from "viem";
import { privateKeyToAccount } from "viem/accounts";
const PRIVACY = "0x100000000000000000000000000000000000000b" as const;
const MAX_BATCH_ITEMS = 20;
type AuthorizedTransferItem = {
request: any; // PrivacyTransferRequest tuple
authorization: any; // PrivacyActionAuthorization tuple with EIP-712 signature
};
async function submitAuthorizedBatch(items: AuthorizedTransferItem[]) {
if (items.length === 0 || items.length > MAX_BATCH_ITEMS) {
throw new Error(`expected 1..${MAX_BATCH_ITEMS} items, got ${items.length}`);
}
const batchId = toHex(randomBytes(32));
// Each item's authorization.batchId and authorization.batchItemIndex must have
// been included in the EIP-712 message the effective sender already signed.
items.forEach((item, i) => {
if (item.authorization.batchId !== batchId) throw new Error(`item ${i} batchId mismatch`);
if (item.authorization.batchItemIndex !== BigInt(i)) throw new Error(`item ${i} index mismatch`);
});
const executor = createWalletClient({
account: privateKeyToAccount(process.env.EXECUTOR_KEY as `0x${string}`),
transport: http("https://rpc-testnet.maroo.io"),
});
return executor.writeContract({
address: PRIVACY,
abi: privacyAbi,
functionName: "batchTransferWithAuthorization",
args: [batchId, items],
});
}