Referral Fees & Attribution
What this covers
How to add partner fees to quotes and intents, and how to append ERC-8021 attribution data to transactions.
When to use this
Use this when you are embedding Peer inside another app and need revenue sharing, campaign codes, or Base builder attribution.
Configure a referrer fee
import {
assertValidReferrerFeeConfig,
parseReferrerFeeConfig,
} from '@zkp2p/sdk';
const referrerFeeConfig = assertValidReferrerFeeConfig(
parseReferrerFeeConfig('0xReferrerFeeRecipient', 50),
'getQuote',
);
const quoteResponse = await client.getQuote({
paymentPlatforms: ['wise'],
fiatCurrency: 'USD',
user: buyerAddress,
recipient: buyerAddress,
destinationChainId: 8453,
destinationToken: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
amount: '100',
isExactFiat: true,
referrerFeeConfig,
});
Useful helpers:
assertValidReferrerFeeConfig(config, context)isValidReferrerFeeBps(value)parseReferrerFeeConfig(recipient, feeBpsValue)referrerFeeConfigToPreciseUnits(config)
Carry the same fee into signalIntent()
When a fee is present, use the quote's signalIntentAmount if it is available.
const quote = quoteResponse.responseObject?.quotes?.[0];
if (!quote) {
throw new Error('No quote found');
}
await client.signalIntent({
depositId: BigInt(quote.intent.depositId),
amount: BigInt(quote.signalIntentAmount ?? quote.intent.amount),
toAddress: buyerAddress,
processorName: quote.intent.processorName,
payeeDetails: quote.intent.payeeDetails,
fiatCurrencyCode: quote.intent.fiatCurrencyCode,
conversionRate: BigInt(quote.conversionRate),
referrerFeeConfig,
escrowAddress: quote.intent.escrowAddress as `0x${string}` | undefined,
orchestratorAddress: quote.intent.orchestratorAddress as `0x${string}` | undefined,
});
Add ERC-8021 attribution
The SDK always appends BASE_BUILDER_CODE last. Your referrer codes go in front of it.
import {
BASE_BUILDER_CODE,
ZKP2P_IOS_REFERRER,
appendAttributionToCalldata,
encodeWithAttribution,
getAttributionDataSuffix,
} from '@zkp2p/sdk';
const suffix = getAttributionDataSuffix([ZKP2P_IOS_REFERRER, 'acme-wallet']);
console.log(BASE_BUILDER_CODE, suffix);
const calldata = encodeWithAttribution(
{
abi: escrowAbi,
functionName: 'addFunds',
args: [42n, 100_000000n],
},
['acme-wallet'],
);
const finalCalldata = appendAttributionToCalldata(calldata, 'partner-campaign');
If you are not using SDK write helpers, send the transaction manually:
import { sendTransactionWithAttribution } from '@zkp2p/sdk';
await sendTransactionWithAttribution(
walletClient,
{
address: escrowAddress,
abi: escrowAbi,
functionName: 'addFunds',
args: [42n, 100_000000n],
},
['acme-wallet', 'campaign-q2'],
);
Key points
referrerFeeConfigis for app-level fee sharing;txOverrides.referreris for ERC-8021 attributionsignalIntentAmountis the safest gross amount to pass intosignalIntent()when a fee is appliedBASE_BUILDER_CODEis always appended automatically and cannot be overridden- Mobile apps commonly reuse
ZKP2P_IOS_REFERRERorZKP2P_ANDROID_REFERRERas one of the attribution codes