Invoices allow a recipient to pre-generate burn addresses and share them with a sender, so the sender knows exactly where to transfer tokens. This is the recommended way to coordinate private transfers between parties.
What Are Invoices
An invoice encapsulates one or more burn addresses that a recipient generates ahead of time. When a sender receives an invoice, they transfer zERC20 tokens to the burn address(es) listed in it.
Each burn address in an invoice is derived from the recipient's address, a secret, and a tweak, ensuring that only the recipient can later redeem the tokens sent to it.
Prepare Invoice
Generate the invoice artifacts locally before submitting to the ICP storage canister. This step derives the burn addresses and prepares a signature message for wallet signing.
import{prepareInvoiceIssue}from"zerc20-client-sdk";constartifacts=awaitprepareInvoiceIssue({client,// StealthCanisterClientseedHex,// 32-byte hex seed (keccak256 of wallet signature)recipientAddress,// recipient EVM addressrecipientChainId,// chain ID where the recipient will redeemisBatch:false,// true for batch (10 addresses), false for singletag:undefined,// optional, tag for filteringrandomBytes:undefined,// optional, custom random bytesmaxRetries:undefined,// optional, max PoW retries});
Signature:
InvoiceIssueParams:
Field
Type
Required
Description
client
StealthCanisterClient
Yes
ICP canister client
seedHex
string
Yes
32-byte hex seed (see Private Send for derivation)
recipientAddress
string
Yes
Recipient EVM address
recipientChainId
number | bigint
Yes
Chain ID where the recipient will redeem
isBatch
boolean
Yes
true for batch (10 addresses), false for single
tag
string | undefined
No
Tag for categorizing or filtering invoices
randomBytes
(length: number) => Uint8Array
No
Custom random bytes generator for burn address derivation
maxRetries
number | undefined
No
Max PoW retries for burn address generation
InvoiceIssueArtifacts:
Field
Type
Description
invoiceId
string
Unique invoice identifier
recipientAddress
string
Recipient EVM address
recipientChainId
bigint
Chain ID for redemption
burnAddresses
InvoiceBatchBurnAddress[]
Array of burn address entries
signatureMessage
string
Message to sign with the recipient's wallet
tag
string | undefined
Tag, if provided
Each entry in burnAddresses is an InvoiceBatchBurnAddress:
Field
Type
Description
subId
number
Sub-index within the invoice (0-based)
burnAddress
string
Derived burn address
secret
string
Secret used in burn address derivation
tweak
string
Tweak value for address uniqueness
For a single invoice, burnAddresses contains one entry. For a batch invoice, it contains exactly 10.
Submit Invoice
After preparing the invoice, sign the signatureMessage with the recipient's wallet and submit the invoice to the ICP storage canister.
Signature:
The canister verifies the signature against the recipient address embedded in the invoice before accepting it.
List Invoices
Retrieve invoice IDs owned by a specific address. Optionally filter by chain ID or tag.
Signature:
Returns an array of invoice IDs as hex strings. Use these IDs to look up or share specific invoices.
Complete Example
End-to-end flow: prepare an invoice, sign it, submit it, and list all invoices.
Once submitted, the sender can retrieve the invoice to learn the burn address and execute a Private Send. For more on setting up the SDK client, see the SDK Quick Start.