From 25ea69f995ef699318799667cf333239bdf6f4aa Mon Sep 17 00:00:00 2001 From: Youssef Date: Thu, 8 Oct 2026 13:54:47 +0100 Subject: [PATCH] docs(builder-codes): pass dataSuffix per call in wagmi and add volume tracking --- .../builder-codes/for-app-developers.mdx | 251 ++++++++++-------- .../specifications/builder-codes/overview.mdx | 2 +- 2 files changed, 134 insertions(+), 119 deletions(-) diff --git a/docs/specifications/builder-codes/for-app-developers.mdx b/docs/specifications/builder-codes/for-app-developers.mdx index 42f6ec3db..2c4e982a1 100644 --- a/docs/specifications/builder-codes/for-app-developers.mdx +++ b/docs/specifications/builder-codes/for-app-developers.mdx @@ -12,7 +12,7 @@ Once your project is registered on [Base Dashboard](https://dashboard.base.org/) If users also access your app on the web or through other clients, you'll need to integrate the `dataSuffix` parameter to capture that activity. -When you register a project on [Base Dashboard](https://dashboard.base.org/), you will receive a **Builder Code**—a random string (e.g., `bc_b7k3p9da`) that you'll use to generate your attribution suffix. The recommended approach is to configure `dataSuffix` at the client level, which appends your Builder Code to all transactions. +When you register a project on [Base Dashboard](https://dashboard.base.org/), you will receive a **Builder Code**—a random string (e.g., `bc_b7k3p9da`) that you'll use to generate your attribution suffix. With Viem, configure `dataSuffix` once on the wallet client to append your Builder Code to every transaction it sends. With Wagmi, pass `dataSuffix` on each write call. You can find your code anytime under **Settings** → **Project Settings** → **Builder Code**. Switch the format to **Encoded String** to copy the full ERC-8021 suffix, the same hex value `Attribution.toDataSuffix` returns. @@ -20,6 +20,10 @@ When you register a project on [Base Dashboard](https://dashboard.base.org/), yo ## Quick Setup with Wagmi + + Wagmi does not apply a `dataSuffix` set in `createConfig` to transactions sent through a connected wallet, such as an injected browser extension. Wagmi passes `createConfig` options to its public client only, not to the connector client that sends `sendTransaction`, `writeContract` and `sendCalls` requests, so those transactions go out without your Builder Code. Pass the suffix on each call as shown below. See [wagmi issue #5248](https://github.com/wevm/wagmi/issues/5248) for status. + + Install the required packages. Requires viem version `2.45.0` or higher. @@ -29,53 +33,112 @@ When you register a project on [Base Dashboard](https://dashboard.base.org/), yo ``` - - Add the `dataSuffix` option to your Wagmi config. This automatically appends your Builder Code to all transactions. + + Generate the ERC-8021 suffix once and import it wherever your app sends a transaction. - ```typescript config.ts lines expandable wrap - import { createConfig, http } from "wagmi"; - import { base } from "wagmi/chains"; + ```typescript attribution.ts lines wrap import { Attribution } from "ox/erc8021"; // Get your Builder Code from Base Dashboard > Settings > Project Settings > Builder Code - const DATA_SUFFIX = Attribution.toDataSuffix({ + export const DATA_SUFFIX = Attribution.toDataSuffix({ codes: ["YOUR-BUILDER-CODE"], }); - - export const config = createConfig({ - chains: [base], - transports: { - [base.id]: http(), - }, - dataSuffix: DATA_SUFFIX, - }); ``` - - With the config in place, all transactions automatically include your Builder Code—no changes to your hooks or components. This works with both `useSendTransaction` and `useSendCalls`. - - ```tsx App.tsx lines expandable wrap - import { useSendTransaction } from "wagmi"; - import { parseEther } from "viem"; - - function SendButton() { - const { sendTransaction } = useSendTransaction(); - - return ( - - ); - } - ``` + + Pass `dataSuffix` to `useSendTransaction` and `useWriteContract`, which append it to the calldata before the wallet signs. For `useSendCalls`, pass it in the `dataSuffix` capability; the connected wallet appends it, so this requires a wallet that supports the [`dataSuffix` capability](/specifications/builder-codes/for-wallet-developers). + + + + ```tsx SendButton.tsx lines expandable wrap + import { useSendTransaction } from "wagmi"; + import { parseEther } from "viem"; + import { DATA_SUFFIX } from "./attribution"; + + function SendButton() { + const { sendTransaction } = useSendTransaction(); + + return ( + + ); + } + ``` + + + ```tsx MintButton.tsx lines expandable wrap + import { useWriteContract } from "wagmi"; + import { abi } from "./abi"; + import { DATA_SUFFIX } from "./attribution"; + + function MintButton() { + const { writeContract } = useWriteContract(); + + return ( + + ); + } + ``` + + + ```tsx SendCallsButton.tsx lines expandable wrap + import { useSendCalls } from "wagmi"; + import { parseEther } from "viem"; + import { DATA_SUFFIX } from "./attribution"; + + function SendCallsButton() { + const { sendCalls } = useSendCalls(); + + return ( + + ); + } + ``` + + + + To confirm the suffix is applied, send a test transaction and check its input data as described in [Verify Attribution](#verify-attribution). @@ -112,7 +175,7 @@ When you register a project on [Base Dashboard](https://dashboard.base.org/), yo - All transactions sent through this client automatically include your Builder Code. + Calls to `sendTransaction` and `writeContract` through this client append your Builder Code automatically. `sendCalls` passes it to the wallet as the `dataSuffix` capability. ```typescript send-transaction.ts lines expandable wrap import { parseEther } from "viem"; @@ -138,84 +201,6 @@ Privy provides a `dataSuffix` plugin that automatically appends your Builder Cod See the [Privy Builder Codes integration guide](https://docs.privy.io/recipes/evm/base-builder-codes) for setup instructions. -## Legacy: Per-Transaction Approach - - - If you need to append the suffix on a per-transaction basis rather than at the client level, you can pass `dataSuffix` directly to the transaction. - - - - ```tsx App.tsx lines expandable wrap - import { useSendTransaction } from "wagmi"; - import { parseEther } from "viem"; - import { Attribution } from "ox/erc8021"; - - const DATA_SUFFIX = Attribution.toDataSuffix({ - codes: ["YOUR-BUILDER-CODE"], - }); - - function App() { - const { sendTransaction } = useSendTransaction(); - - return ( - - ); - } - ``` - - - When using `useSendCalls`, pass the suffix via the `capabilities` object. This requires the connected wallet to support the `dataSuffix` capability. - - ```tsx App.tsx lines expandable wrap - import { useSendCalls } from "wagmi"; - import { parseEther } from "viem"; - import { Attribution } from "ox/erc8021"; - - const DATA_SUFFIX = Attribution.toDataSuffix({ - codes: ["YOUR-BUILDER-CODE"], - }); - - function App() { - const { sendCalls } = useSendCalls(); - - return ( - - ); - } - ``` - - - - ## Verify Attribution To confirm your Builder Code is being appended correctly: @@ -244,6 +229,7 @@ Builder Codes tell you which onchain transactions came from your app. To measure | D1, D7 and D30 retention | The date each address was first seen, and whether it came back in a later period | Block timestamp of the address's first successful attributed transaction | | Conversion funnel | Open, connect, submit, success, joined on wallet address and transaction hash | Page load, `eth_requestAccounts`, the hash or call bundle ID returned on submit, and the receipt | | Onchain activity attributed to your app | Transactions whose ERC-8021 suffix contains your Builder Code | `input` of the transaction, or `callData` of each UserOperation | +| ETH and USDC volume | Value and token transfers sent by the user in an attributed transaction | Transaction `value` and `Transfer` logs in the receipt (see step 4) | @@ -366,6 +352,35 @@ Builder Codes tell you which onchain transactions came from your app. To measure To backfill history, or to catch transactions sent outside your app's UI, scan Base blocks (or your contracts' logs with `eth_getLogs`) for calldata that ends with the ERC-8021 marker, and decode each match the same way. + + Base Dashboard reports spot trading volume, borrow TVL and lending TVL for your project. To measure the ETH or USDC that your attributed transactions move, read it from the same transaction and receipt you fetched in step 3: + + - **ETH:** the `value` of an EOA transaction. For a smart account, ETH moves in an internal call from the account, so it is not in the outer transaction `value` or in any log. Read it from a call trace (`debug_traceTransaction` with the `callTracer`) on a node or provider that supports it. + - **USDC and other ERC-20 tokens:** `Transfer` logs in the receipt emitted by the token contract, filtered to transfers sent from the user's address. Filtering by sender also separates the UserOperations in a bundle, since each one has its own `sender`. + + ```typescript get-attributed-volume.ts lines expandable wrap + import { erc20Abi, isAddressEqual, parseEventLogs, type Address, type Transaction, type TransactionReceipt } from "viem"; + + // USDC on Base + const USDC = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"; + + // Pass the transaction and receipt fetched in step 3, and the sender of each row where success and attributed are true + export function getAttributedVolume(tx: Transaction, receipt: TransactionReceipt, sender: Address) { + const usdcTransfers = parseEventLogs({ abi: erc20Abi, eventName: "Transfer", logs: receipt.logs }) + .filter((log) => isAddressEqual(log.address, USDC) && isAddressEqual(log.args.from, sender)); + + return { + // Native ETH sent directly by an EOA. Smart account ETH transfers need a call trace. + ethWei: isAddressEqual(tx.from, sender) ? tx.value : 0n, + // USDC uses 6 decimals: format with formatUnits(usdc, 6) + usdc: usdcTransfers.reduce((sum, log) => sum + log.args.value, 0n), + }; + } + ``` + + Sum these values per day, week or month to report the volume attributed to your Builder Code. To report a single currency, convert each amount at the price for its block timestamp from a price source of your choice. + + Join the in-app signals from step 2 with the onchain rows from step 3 on the lowercased wallet address, and on the transaction hash for the submit and success stages. Then: diff --git a/docs/specifications/builder-codes/overview.mdx b/docs/specifications/builder-codes/overview.mdx index 52df5de40..6749279b8 100644 --- a/docs/specifications/builder-codes/overview.mdx +++ b/docs/specifications/builder-codes/overview.mdx @@ -29,7 +29,7 @@ Each code has associated metadata. Onchain metadata primarily includes a "payout ## Benefits - **Rewards:** If your app drives transactions, Builder Codes let Base automatically attribute that usage back to you, unlocking rewards as the program expands. -- **Analytics:** Base Dashboard shows spot trading volume, borrow TVL and lending TVL derived from your Builder Code activity. To measure users, retention and conversion yourself, see [Track User Analytics](/specifications/builder-codes/for-app-developers#track-user-analytics). +- **Analytics:** Base Dashboard shows spot trading volume, borrow TVL and lending TVL derived from your Builder Code activity. To measure users, retention, conversion and the ETH or USDC volume your attributed transactions move yourself, see [Track User Analytics](/specifications/builder-codes/for-app-developers#track-user-analytics). - **Visibility:** Apps with Builder Codes can show up in discovery surfaces like App Leaderboards, Base App store, and ecosystem spotlights. ## FAQ