From 39dcf0667555570d57b7d4430be558c488094506 Mon Sep 17 00:00:00 2001 From: Dan Cortes <3639170+dgca@users.noreply.github.com> Date: Tue, 3 Feb 2026 14:44:53 -0700 Subject: [PATCH 1/3] docs: Update builder code docs to suggest using dataSuffix at the client level --- .../builder-codes/builder-codes.mdx | 237 +++++++++++++----- 1 file changed, 180 insertions(+), 57 deletions(-) diff --git a/docs/base-chain/builder-codes/builder-codes.mdx b/docs/base-chain/builder-codes/builder-codes.mdx index ce3f27b59..51e7834e3 100644 --- a/docs/base-chain/builder-codes/builder-codes.mdx +++ b/docs/base-chain/builder-codes/builder-codes.mdx @@ -5,88 +5,82 @@ description: "Integrate Builder Codes to attribute onchain activity to your app ## What are Builder Codes -Base Builder Codes are an ERC-721 NFT collection where unique codes (e.g. “abc123”) are minted to help identify builders onchain. +Base Builder Codes are an ERC-721 NFT collection where unique codes (e.g. "abc123") are minted to help identify builders onchain. -Each code has associated metadata. Onchain metadata primarily includes a “payout address” where each code declares where potential rewards should be sent to. Offchain metadata includes more details about the app including its name and site. +Each code has associated metadata. Onchain metadata primarily includes a "payout address" where each code declares where potential rewards should be sent to. Offchain metadata includes more details about the app including its name and site. ## Automatic Builder-Code Attribution on Base Once your app is registered on [Base.dev](http://base.dev/), the Base App will auto-append your Base Builder Code to transactions its users make in your app (e.g. via your mini app, or the Base App's browser). This powers your onchain analytics in [Base.dev](http://base.dev/) and qualifies you for potential future rewards. - ## For App Developers -When you register on [base.dev](https://base.dev/), you will receive a **Builder Code**—a random string (e.g., `bc_b7k3p9da` ) that you'll use to generate your attribution suffix. +When you register on [base.dev](https://base.dev/), you will receive a **Builder Code**—a random string (e.g., `bc_b7k3p9da`) that you'll use to generate your attribution suffix. You can find your code anytime under **Settings** → **Builder Code**. - - +The recommended approach is to configure `dataSuffix` at the client level, which automatically appends your Builder Code to all transactions. + + + Requires [viem](https://viem.sh) version 2.45.0 or higher, or [wagmi](https://wagmi.sh) version 2.17.0 or higher. + -This will allow you to append the encoded version of your builder code. +### Quick setup with Wagmi - ```bash Terminal - npm i ox - ``` - + + + Install the required packages. The `dataSuffix` feature requires viem version 2.45.0 or higher. - - Navigate to **base.dev > Settings > Builder Codes** to find your unique builder code. + ```bash + npm i ox wagmi viem + ``` - - Use the `Attribution.toDataSuffix` method from the `ox` library to encode your builder code: + + Add the `dataSuffix` option to your Wagmi config. This automatically appends your Builder Code to all transactions. - ```ts App.tsx + ```ts config.ts + import { createConfig, http } from "wagmi"; + import { base } from "wagmi/chains"; import { Attribution } from "ox/erc8021"; + // Get your Builder Code from base.dev > Settings > Builder Codes const DATA_SUFFIX = Attribution.toDataSuffix({ - codes: ["YOUR-BUILDER-CODE"], // obtained from base.dev > Settings > Builder Codes + codes: ["YOUR-BUILDER-CODE"], + }); + + export const config = createConfig({ + chains: [base], + transports: { + [base.id]: http(), + }, + dataSuffix: DATA_SUFFIX, }); ``` - - Use Wagmi's `useSendCalls` hook with the `dataSuffix` capability to append attribution data to your transactions. + + 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`. - ```ts App.tsx - import { useSendCalls } from "wagmi"; + ```tsx App.tsx + 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 { sendCalls } = useSendCalls(); + function SendButton() { + const { sendTransaction } = useSendTransaction(); return ( ); } @@ -94,15 +88,144 @@ This will allow you to append the encoded version of your builder code. +### Quick setup with Viem + + + + Install the required packages. The `dataSuffix` feature requires viem version 2.45.0 or higher. + + ```bash + npm i ox viem + ``` + + + + Add the `dataSuffix` option when creating your wallet client. See the [viem wallet client docs](https://viem.sh/docs/clients/wallet) for more configuration options. + + ```ts client.ts + import { createWalletClient, http } from "viem"; + import { base } from "viem/chains"; + import { Attribution } from "ox/erc8021"; + + // Get your Builder Code from base.dev > Settings > Builder Codes + const DATA_SUFFIX = Attribution.toDataSuffix({ + codes: ["YOUR-BUILDER-CODE"], + }); + + export const walletClient = createWalletClient({ + chain: base, + transport: http(), + dataSuffix: DATA_SUFFIX, + }); + ``` + + + + All transactions sent through this client automatically include your Builder Code. + + ```ts + import { parseEther } from "viem"; + import { walletClient } from "./client"; + + const hash = await walletClient.sendTransaction({ + to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", + value: parseEther("0.01"), + }); + ``` + + + +### 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 + 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 + 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, see [How do I verify that my transaction was properly attributed?](/base-chain/builder-codes/builder-codes-faq#how-do-i-verify-that-my-transaction-was-properly-attributed) in the FAQ. + ## For Wallet Developers Wallet providers need to support the `dataSuffix` capability to enable attribution. This involves accepting the capability and appending the suffix to the calldata before signing. - + Your wallet should accept a `dataSuffix` object in the `capabilities` object of `wallet_sendCalls`. - ```typescript lines + ```typescript type DataSuffixCapability = { value: `0x${string}`; // hex-encoded bytes provided by the app optional?: boolean; // whether the capability is optional @@ -111,14 +234,14 @@ Wallet providers need to support the `dataSuffix` capability to enable attributi - + When constructing the transaction or User Operation, extract the `dataSuffix` and append it to the calldata. Append to `tx.data`. - ```typescript lines + ```typescript // Minimal example for EOA function applySuffixToEOA(tx, capabilities) { const suffix = capabilities.dataSuffix?.value @@ -135,7 +258,7 @@ Wallet providers need to support the `dataSuffix` capability to enable attributi Append to `userOp.callData` (not the transaction-level calldata). - ```typescript lines + ```typescript // Minimal example for ERC-4337 function applySuffixToUserOp(userOp, capabilities) { const suffix = capabilities.dataSuffix?.value @@ -152,11 +275,11 @@ Wallet providers need to support the `dataSuffix` capability to enable attributi - - Wallets may also include their own attribution code (their own ERC-8021 suffix) by simply prepending the wallet’s own suffix before the app’s. + + Wallets may also include their own attribution code (their own ERC-8021 suffix) by prepending the wallet's suffix before the app's. - * **No interaction required with apps:** The wallet handles this independently. - * **Multi-code support:** ERC-8021 natively supports multiple attribution codes. + - **No interaction required with apps:** The wallet handles this independently. + - **Multi-code support:** ERC-8021 natively supports multiple attribution codes. **Example:** @@ -191,7 +314,7 @@ Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-sol - + Set `to = BRIDGE_CAMPAIGN_ADDRESS` and attach a call to `Flywheel.send`. @@ -251,7 +374,7 @@ Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-sol - + [Terminally Onchain](https://terminallyonchain.com/) is a production Next.js app that exposes the bridge via a command terminal UI. Users connect a Solana wallet, type commands such as to bridge and call a contract on Base: You can use [Terminally Onchain](https://terminallyonchain.com/) to test bridge transactions with Builder Codes like so: From 3862c220d02586c196f353056db8480cf777efda Mon Sep 17 00:00:00 2001 From: Dan Cortes <3639170+dgca@users.noreply.github.com> Date: Tue, 3 Feb 2026 14:53:47 -0700 Subject: [PATCH 2/3] Titlecase --- .../builder-codes/builder-codes.mdx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/docs/base-chain/builder-codes/builder-codes.mdx b/docs/base-chain/builder-codes/builder-codes.mdx index 51e7834e3..35a0e3358 100644 --- a/docs/base-chain/builder-codes/builder-codes.mdx +++ b/docs/base-chain/builder-codes/builder-codes.mdx @@ -27,10 +27,10 @@ The recommended approach is to configure `dataSuffix` at the client level, which Requires [viem](https://viem.sh) version 2.45.0 or higher, or [wagmi](https://wagmi.sh) version 2.17.0 or higher. -### Quick setup with Wagmi +### Quick Setup with Wagmi - + Install the required packages. The `dataSuffix` feature requires viem version 2.45.0 or higher. ```bash @@ -38,7 +38,7 @@ The recommended approach is to configure `dataSuffix` at the client level, which ``` - + Add the `dataSuffix` option to your Wagmi config. This automatically appends your Builder Code to all transactions. ```ts config.ts @@ -61,7 +61,7 @@ The recommended approach is to configure `dataSuffix` at the client level, which ``` - + 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 @@ -88,10 +88,10 @@ The recommended approach is to configure `dataSuffix` at the client level, which -### Quick setup with Viem +### Quick Setup with Viem - + Install the required packages. The `dataSuffix` feature requires viem version 2.45.0 or higher. ```bash @@ -99,7 +99,7 @@ The recommended approach is to configure `dataSuffix` at the client level, which ``` - + Add the `dataSuffix` option when creating your wallet client. See the [viem wallet client docs](https://viem.sh/docs/clients/wallet) for more configuration options. ```ts client.ts @@ -120,7 +120,7 @@ The recommended approach is to configure `dataSuffix` at the client level, which ``` - + All transactions sent through this client automatically include your Builder Code. ```ts @@ -135,7 +135,7 @@ The recommended approach is to configure `dataSuffix` at the client level, which -### Legacy: Per-transaction approach +### 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. @@ -213,7 +213,7 @@ The recommended approach is to configure `dataSuffix` at the client level, which -### Verify attribution +### Verify Attribution To confirm your Builder Code is being appended correctly, see [How do I verify that my transaction was properly attributed?](/base-chain/builder-codes/builder-codes-faq#how-do-i-verify-that-my-transaction-was-properly-attributed) in the FAQ. @@ -222,7 +222,7 @@ To confirm your Builder Code is being appended correctly, see [How do I verify t Wallet providers need to support the `dataSuffix` capability to enable attribution. This involves accepting the capability and appending the suffix to the calldata before signing. - + Your wallet should accept a `dataSuffix` object in the `capabilities` object of `wallet_sendCalls`. ```typescript @@ -234,7 +234,7 @@ Wallet providers need to support the `dataSuffix` capability to enable attributi - + When constructing the transaction or User Operation, extract the `dataSuffix` and append it to the calldata. @@ -275,7 +275,7 @@ Wallet providers need to support the `dataSuffix` capability to enable attributi - + Wallets may also include their own attribution code (their own ERC-8021 suffix) by prepending the wallet's suffix before the app's. - **No interaction required with apps:** The wallet handles this independently. @@ -297,7 +297,7 @@ Wallet providers need to support the `dataSuffix` capability to enable attributi Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-solana-bridge) via the [`hookData`](https://github.com/base/flywheel/blob/30266bba4649b0eb161e55bfa4755651049a5d1f/src/hooks/BridgeReferralFees.sol#L75) mechanism. Currently available for **Solana → Base** flows only. - + When you register on base.dev, you will find a Builder Code under your app's settings. This is a random string (e.g., k3p9da) that you will use to generate your attribution suffix. @@ -314,7 +314,7 @@ Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-sol - + Set `to = BRIDGE_CAMPAIGN_ADDRESS` and attach a call to `Flywheel.send`. @@ -374,7 +374,7 @@ Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-sol - + [Terminally Onchain](https://terminallyonchain.com/) is a production Next.js app that exposes the bridge via a command terminal UI. Users connect a Solana wallet, type commands such as to bridge and call a contract on Base: You can use [Terminally Onchain](https://terminallyonchain.com/) to test bridge transactions with Builder Codes like so: From 722fc475ce0f08d97097267b9563d269e902b8c2 Mon Sep 17 00:00:00 2001 From: Dan Cortes <3639170+dgca@users.noreply.github.com> Date: Tue, 3 Feb 2026 18:40:01 -0700 Subject: [PATCH 3/3] Split buidler code docs to separate pages --- .../builder-codes/app-developers.mdx | 229 ++++++++ .../builder-codes/bridge-developers.mdx | 177 ++++++ .../builder-codes/builder-codes-faq.mdx | 104 ---- .../builder-codes/builder-codes.mdx | 532 +++--------------- .../builder-codes/wallet-developers.mdx | 80 +++ docs/docs.json | 20 +- 6 files changed, 595 insertions(+), 547 deletions(-) create mode 100644 docs/base-chain/builder-codes/app-developers.mdx create mode 100644 docs/base-chain/builder-codes/bridge-developers.mdx delete mode 100644 docs/base-chain/builder-codes/builder-codes-faq.mdx create mode 100644 docs/base-chain/builder-codes/wallet-developers.mdx diff --git a/docs/base-chain/builder-codes/app-developers.mdx b/docs/base-chain/builder-codes/app-developers.mdx new file mode 100644 index 000000000..0e2cdd70d --- /dev/null +++ b/docs/base-chain/builder-codes/app-developers.mdx @@ -0,0 +1,229 @@ +--- +title: "Builder Codes for App Developers" +sidebarTitle: "For App Developers" +description: "Integrate Builder Codes into your app using Wagmi or Viem to attribute onchain activity." +--- + +## Automatic Attribution on Base + +Once your app is registered on [base.dev](http://base.dev/), the Base App will auto-append your Builder Code to transactions its users make in your app (e.g. via your mini app, or the Base App's browser). This powers your onchain analytics in [base.dev](http://base.dev/) and qualifies you for potential future rewards. + +## Integrating Outside the Base App + +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 on [base.dev](https://base.dev/), 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. + + + You can find your code anytime under **Settings** → **Builder Code**. + + +## Quick Setup with Wagmi + + + + Install the required packages. Requires viem version `2.45.0` or higher. + + ```bash + npm i ox wagmi viem + ``` + + + + Add the `dataSuffix` option to your Wagmi config. This automatically appends your Builder Code to all transactions. + + ```ts config.ts + import { createConfig, http } from "wagmi"; + import { base } from "wagmi/chains"; + import { Attribution } from "ox/erc8021"; + + // Get your Builder Code from base.dev > Settings > Builder Codes + 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 + import { useSendTransaction } from "wagmi"; + import { parseEther } from "viem"; + + function SendButton() { + const { sendTransaction } = useSendTransaction(); + + return ( + + ); + } + ``` + + + +## Quick Setup with Viem + + + + Install the required packages. Requires viem version `2.45.0` or higher. + + ```bash + npm i ox viem + ``` + + + + Add the `dataSuffix` option when creating your wallet client. See the [viem wallet client docs](https://viem.sh/docs/clients/wallet) for more configuration options. + + ```ts client.ts + import { createWalletClient, http } from "viem"; + import { base } from "viem/chains"; + import { Attribution } from "ox/erc8021"; + + // Get your Builder Code from base.dev > Settings > Builder Codes + const DATA_SUFFIX = Attribution.toDataSuffix({ + codes: ["YOUR-BUILDER-CODE"], + }); + + export const walletClient = createWalletClient({ + chain: base, + transport: http(), + dataSuffix: DATA_SUFFIX, + }); + ``` + + + + All transactions sent through this client automatically include your Builder Code. + + ```ts + import { parseEther } from "viem"; + import { walletClient } from "./client"; + + const hash = await walletClient.sendTransaction({ + to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", + value: parseEther("0.01"), + }); + ``` + + + +## 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 + 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 + 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: + +**1. Check base.dev** + +- Visit [base.dev](https://base.dev) +- Select **Onchain** from the transaction type dropdown +- Under the Total Transactions section, attribution counts increment when transactions with your code are processed + +**2. Use a Block Explorer (Basescan, Etherscan, etc.)** + +- Find your transaction hash +- View the input data field +- Verify the last 16 bytes are the `8021` repeating +- Decode the suffix to confirm your Builder Code is present + +**3. Open Source Tools** + +- Use the [Builder Code Validation](https://builder-code-checker.vercel.app/) tool +- Select transaction type +- Enter the transaction or UserOperation hash +- Click the **Check Attribution** button diff --git a/docs/base-chain/builder-codes/bridge-developers.mdx b/docs/base-chain/builder-codes/bridge-developers.mdx new file mode 100644 index 000000000..aad5da6b9 --- /dev/null +++ b/docs/base-chain/builder-codes/bridge-developers.mdx @@ -0,0 +1,177 @@ +--- +title: "Builder Codes for Bridge Developers" +sidebarTitle: "For Bridge Developers" +description: "Integrate Builder Codes with the Base-Solana bridge using hookData." +--- + +Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-solana-bridge) via the [`hookData`](https://github.com/base/flywheel/blob/30266bba4649b0eb161e55bfa4755651049a5d1f/src/hooks/BridgeReferralFees.sol#L75) mechanism. Currently available for **Solana → Base** flows only. + + + + When you register on base.dev, you will find a Builder Code under your app's settings. This is a random string (e.g., k3p9da) that you will use to generate your attribution suffix. + + + + ABI-encode the user address, your code, and fee: + + ```solidity + bytes memory hookData = abi.encode( + 0xUSER, // destination address on Base (NOT the Twin) + 0xBUILDER_CODE, // your builder code in type string memory + 100 // feeBps (100 = 1%) + ); + ``` + + + + + Set `to = BRIDGE_CAMPAIGN_ADDRESS` and attach a call to `Flywheel.send`. + + + + For a bridge with no follow-up call: + + ``` + to: // 0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9 on Base Sepolia + amount: 100 + call: + ty: Call + to: // 0x00000F14AD09382841DB481403D1775ADeE1179F on Base Sepolia + value: 0 + data: abi.encodeWithSelector( + Flywheel.send.selector, + , // 0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9 on Base Sepolia + , + hookData + ) + ``` + + + To chain additional calls, use `DelegateCall` with `Multicall`: + + ```solidity + Call[] memory calls = new Call[](2); + + // 1) Flywheel attribution (must be first) + calls[0] = Call({ + to: , // 0x00000F14AD09382841DB481403D1775ADeE1179F on Base Sepolia + value: 0, + data: abi.encodeWithSelector( + Flywheel.send.selector, + , // 0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9 on Base Sepolia + , // e.g. For SOL on Base Sepolia, use 0xCace0c896714DaF7098FFD8CC54aFCFe0338b4BC + hookData + ) + }); + + // 2) Your follow-up call + calls[1] = Call({ + to: , + value: 0, + data: abi.encodeWithSelector(YourContract.yourFunction.selector) + }); + ``` + + Then set the bridge call to: + + ``` + call: + ty: DelegateCall + to: // 0xcA11bde05977b3631167028862bE2a173976CA11 on Base Mainnet + data: abi.encodeWithSelector(Multicall.multicall.selector, calls) + ``` + + + + + + [Terminally Onchain](https://terminallyonchain.com/) is a production Next.js app that exposes the bridge via a command terminal UI. Users connect a Solana wallet, type commands such as to bridge and call a contract on Base: + + You can use [Terminally Onchain](https://terminallyonchain.com/) to test bridge transactions with Builder Codes like so: + + ```bash + bridge 0.0001 sol 0xYOUR_DESTINATION_ADDRESS --with-bc YOUR_BUILDER_CODE --bc-fee YOUR_FEE_BPS + ``` + + To see how this is implemented, you can take a look at the [Github repo](https://github.com/base/sol2base/blob/e0c283035be1e3e345d329e2d77b05e29a1d38b3/src/components/MainContent.tsx#L667): + + ```typescript sol2base/MainContent.tsx expandable + // Constants + const BRIDGE_CAMPAIGN_ADDRESS = "0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9"; + const FLYWHEEL_ADDRESS = "0x00000F14AD09382841DB481403D1775ADeE1179F"; + const MULTICALL_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11"; + + // Encode hookData: (address user, string code, uint8 feeBps) + const buildBuilderHookData = ( + destination: string, + builderCode: string, + feeBps: number + ) => { + const coder = new AbiCoder(); + return coder.encode( + ["address", "string", "uint8"], + [destination, builderCode, feeBps] + ); + }; + + // Build Flywheel.send call + const buildBuilderCall = ( + destination: string, + builderCode: string, + feeBps: number, + tokenAddress: string + ): BaseContractCall => { + const hookData = buildBuilderHookData(destination, builderCode, feeBps); + const data = encodeFunctionData({ + abi: FLYWHEEL_ABI, + functionName: "send", + args: [BRIDGE_CAMPAIGN_ADDRESS, tokenAddress, hookData], + }); + return { type: "call", target: FLYWHEEL_ADDRESS, value: "0", data }; + }; + + // Wrap builder + user calls in Multicall (for chained calls) + const buildMulticall = ( + builder: BaseContractCall, + userCall: BaseContractCall + ): BaseContractCall => { + const data = encodeFunctionData({ + abi: MULTICALL_ABI, + functionName: "multicall", + args: [ + [ + { target: builder.target, callData: builder.data }, + { target: userCall.target, callData: userCall.data }, + ], + ], + }); + return { type: "delegatecall", target: MULTICALL_ADDRESS, value: "0", data }; + }; + + // Usage: attach builder code to bridge + if (payload.flags.withBc) { + const builderCall = buildBuilderCall( + destination, + builderCode, + feeBps, + remoteToken + ); + callOption = userCall ? buildMulticall(builderCall, userCall) : builderCall; + } + + // Set destination to campaign address when using builder codes + const destinationForBridge = builderCode + ? BRIDGE_CAMPAIGN_ADDRESS + : payload.destination; + ``` + + + + +## Contract Addresses + +| Contract | Base Mainnet | Base Sepolia | +| -------- | ------------ | ------------ | +| `BRIDGE_CAMPAIGN_ADDRESS` | `0x539A97cc4724d5b2740DB98Bc71445448eFC1Bde` | `0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9` | +| `FLYWHEEL_ADDRESS` | `0x00000F14AD09382841DB481403D1775ADeE1179F` | `0x00000F14AD09382841DB481403D1775ADeE1179F` | +| `MULTICALL_ADDRESS` | `0xcA11bde05977b3631167028862bE2a173976CA11` | `0xcA11bde05977b3631167028862bE2a173976CA11` | diff --git a/docs/base-chain/builder-codes/builder-codes-faq.mdx b/docs/base-chain/builder-codes/builder-codes-faq.mdx deleted file mode 100644 index 8e36f6242..000000000 --- a/docs/base-chain/builder-codes/builder-codes-faq.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: "Builder Codes FAQ" -description: "Common questions about Builder Codes, ERC-8021 transaction attribution, gas costs, and SDK support on Base." ---- - -### What is a "Builder Code" and where do I get one? - -A **Builder Code** is an ASCII string (like `"baseapp"` or `"bc_xyz456"`) that identifies your application in the ERC-8021 attribution system. When your app's transactions include this code, protocols can identify and reward you. - - - Obtain your Builder Code [here](/base-chain/builder-codes/builder-codes). - - -### What are the benefits of supporting Builder Codes? - -- **Rewards:** If your app drives transactions, Builder Codes let Base automatically attribute that usage back to you, unlocking rewards as our program expands. -- **Analytics:** Developers can reliably track onchain usage, user acquisition, and conversion metrics in Base.dev. -- **Visibility:** Apps with Builder Codes can show up in discovery surfaces like our App Leaderboards, Base App store, and ecosystem spotlights. - -### Do I need to modify my smart contracts to use ERC-8021? - -**No.** The attribution suffix is appended to the end of transaction calldata. Smart contracts execute normally and ignore the extra data. Attribution is extracted by offchain indexers after the fact. - -This means: - -- Any existing smart contract automatically supports ERC-8021 -- No upgrades or redeployments required -- Zero impact on contract execution - -### How much additional gas do Builder Codes cost? - -The ERC-8021 suffix adds a negligible amount of gas to each transaction at 16 gas per non-zero byte. - -### Will Builder Codes expose my identity? - -**No.** Builder Codes only associate transactions with your application—they don't expose any wallet information that isn't already public onchain. - -### Can I use ERC-8021 with Externally Owned Accounts (EOAs)? - -**Yes.** ERC-8021 works with both EOAs and smart contract wallets. - -### How do I verify that my transaction was properly attributed? - -**1. Check base.dev** - -- Visit [base.dev](https://base.dev) -- Select **Onchain** from the transaction type dropdown -- Under the Total Transactions section, attribution counts increment when transactions with your code are processed - -**2. Use a Block Explorer (Basescan, Etherscan, etc.)** - -- Find your transaction hash -- View the input data field -- Verify the last 16 bytes are the `8021` repeating. -- Decode the suffix to confirm your Builder Code is present - -**3. Open Source Tools** - -- Use the [Builder Code Validation](https://builder-code-checker.vercel.app/) tool -- Select transaction type -- Enter the transaction or UserOperation hash -- Click the **Check Attribution** button - - -### What wallets and SDKs currently support ERC-8021? - -**EOAs:** - -All EOA wallets support `dataSuffix` by default. - -**SDKs:** - -- **viem/wagmi** - TypeScript SDK with native `dataSuffix` parameter support for server-side and client-side transactions - - -This requires `viem@2.45.0` or higher - - -**Embedded Wallets:** - -- **Privy** - Embedded wallet solution with ERC-8021 capability -- **Turnkey** - Infrastructure for programmatic wallets - -**Smart Wallets:** - -Wallets supporting ERC-5792 can use the `DataSuffixCapability` for clean suffix appending: - -```javascript -await wallet.sendCalls({ - calls: [...], - capabilities: { - dataSuffix: { - value: "0x07626173656170700080218021802180218021802180218021" - optional: true - } - } -}); -``` - -## Additional Resources - -- [Official ERC-8021 Proposal ](https://eip.tools/eip/8021) -- [Builder Code Docs](/base-chain/builder-codes/builder-codes) -- [Builder Code Validation tool](https://builder-code-checker.vercel.app/) diff --git a/docs/base-chain/builder-codes/builder-codes.mdx b/docs/base-chain/builder-codes/builder-codes.mdx index 35a0e3358..4373a0284 100644 --- a/docs/base-chain/builder-codes/builder-codes.mdx +++ b/docs/base-chain/builder-codes/builder-codes.mdx @@ -1,473 +1,121 @@ --- title: "Base Builder Codes" -description: "Integrate Builder Codes to attribute onchain activity to your app or wallet." +description: "Attribute onchain activity to your app or wallet with Builder Codes." --- -## What are Builder Codes +## What Are Builder Codes Base Builder Codes are an ERC-721 NFT collection where unique codes (e.g. "abc123") are minted to help identify builders onchain. Each code has associated metadata. Onchain metadata primarily includes a "payout address" where each code declares where potential rewards should be sent to. Offchain metadata includes more details about the app including its name and site. -## Automatic Builder-Code Attribution on Base + + Get your Builder Code by registering on [base.dev](https://base.dev/). You can find your code under **Settings** → **Builder Code**. + -Once your app is registered on [Base.dev](http://base.dev/), the Base App will auto-append your Base Builder Code to transactions its users make in your app (e.g. via your mini app, or the Base App's browser). This powers your onchain analytics in [Base.dev](http://base.dev/) and qualifies you for potential future rewards. +## Integration Guides -## For App Developers + + + Integrate Builder Codes using Wagmi or Viem + + + Implement the dataSuffix capability + + + Integrate with the Base-Solana bridge + + -When you register on [base.dev](https://base.dev/), you will receive a **Builder Code**—a random string (e.g., `bc_b7k3p9da`) that you'll use to generate your attribution suffix. +## Benefits - - You can find your code anytime under **Settings** → **Builder Code**. - +- **Rewards:** If your app drives transactions, Builder Codes let Base automatically attribute that usage back to you, unlocking rewards as the program expands. +- **Analytics:** Reliably track onchain usage, user acquisition, and conversion metrics in Base.dev. +- **Visibility:** Apps with Builder Codes can show up in discovery surfaces like App Leaderboards, Base App store, and ecosystem spotlights. -The recommended approach is to configure `dataSuffix` at the client level, which automatically appends your Builder Code to all transactions. +## FAQ - - Requires [viem](https://viem.sh) version 2.45.0 or higher, or [wagmi](https://wagmi.sh) version 2.17.0 or higher. - +### Do I Need to Modify My Smart Contracts? -### Quick Setup with Wagmi - - - - Install the required packages. The `dataSuffix` feature requires viem version 2.45.0 or higher. - - ```bash - npm i ox wagmi viem - ``` - - - - Add the `dataSuffix` option to your Wagmi config. This automatically appends your Builder Code to all transactions. - - ```ts config.ts - import { createConfig, http } from "wagmi"; - import { base } from "wagmi/chains"; - import { Attribution } from "ox/erc8021"; - - // Get your Builder Code from base.dev > Settings > Builder Codes - 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 - import { useSendTransaction } from "wagmi"; - import { parseEther } from "viem"; - - function SendButton() { - const { sendTransaction } = useSendTransaction(); - - return ( - - ); - } - ``` - - - -### Quick Setup with Viem - - - - Install the required packages. The `dataSuffix` feature requires viem version 2.45.0 or higher. - - ```bash - npm i ox viem - ``` - - - - Add the `dataSuffix` option when creating your wallet client. See the [viem wallet client docs](https://viem.sh/docs/clients/wallet) for more configuration options. - - ```ts client.ts - import { createWalletClient, http } from "viem"; - import { base } from "viem/chains"; - import { Attribution } from "ox/erc8021"; - - // Get your Builder Code from base.dev > Settings > Builder Codes - const DATA_SUFFIX = Attribution.toDataSuffix({ - codes: ["YOUR-BUILDER-CODE"], - }); - - export const walletClient = createWalletClient({ - chain: base, - transport: http(), - dataSuffix: DATA_SUFFIX, - }); - ``` - - - - All transactions sent through this client automatically include your Builder Code. - - ```ts - import { parseEther } from "viem"; - import { walletClient } from "./client"; - - const hash = await walletClient.sendTransaction({ - to: "0x70997970c51812dc3a010c7d01b50e0d17dc79c8", - value: parseEther("0.01"), - }); - ``` - - - -### 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 - 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 - 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 ( - - ); - } - ``` - - - +**No.** The attribution suffix is appended to the end of transaction calldata. Smart contracts execute normally and ignore the extra data. Attribution is extracted by offchain indexers after the fact. -### Verify Attribution +This means: -To confirm your Builder Code is being appended correctly, see [How do I verify that my transaction was properly attributed?](/base-chain/builder-codes/builder-codes-faq#how-do-i-verify-that-my-transaction-was-properly-attributed) in the FAQ. +- Any existing smart contract automatically supports ERC-8021 +- No upgrades or redeployments required +- Zero impact on contract execution -## For Wallet Developers +### How Much Additional Gas Do Builder Codes Cost? -Wallet providers need to support the `dataSuffix` capability to enable attribution. This involves accepting the capability and appending the suffix to the calldata before signing. +The ERC-8021 suffix adds a negligible amount of gas to each transaction at 16 gas per non-zero byte. - - - Your wallet should accept a `dataSuffix` object in the `capabilities` object of `wallet_sendCalls`. +### Will Builder Codes Expose My Identity? - ```typescript - type DataSuffixCapability = { - value: `0x${string}`; // hex-encoded bytes provided by the app - optional?: boolean; // whether the capability is optional - } - ``` - - - - - When constructing the transaction or User Operation, extract the `dataSuffix` and append it to the calldata. - - - - Append to `tx.data`. - - ```typescript - // Minimal example for EOA - function applySuffixToEOA(tx, capabilities) { - const suffix = capabilities.dataSuffix?.value - if (!suffix) return tx - - return { - ...tx, - // Append suffix bytes (remove 0x prefix from suffix if tx.data has it) - data: tx.data + suffix.slice(2) - } - } - ``` - - - Append to `userOp.callData` (not the transaction-level calldata). - - ```typescript - // Minimal example for ERC-4337 - function applySuffixToUserOp(userOp, capabilities) { - const suffix = capabilities.dataSuffix?.value - if (!suffix) return userOp - - return { - ...userOp, - // Append suffix bytes to the UserOp callData - callData: userOp.callData + suffix.slice(2) - } - } - ``` - - - - - - Wallets may also include their own attribution code (their own ERC-8021 suffix) by prepending the wallet's suffix before the app's. - - - **No interaction required with apps:** The wallet handles this independently. - - **Multi-code support:** ERC-8021 natively supports multiple attribution codes. - - **Example:** - - ```typescript - finalSuffix = walletSuffix + appSuffix - ``` - - This ensures both the app and the wallet receive onchain attribution. - - - - -## For Base-Solana Bridge Developers - -Builder codes work with the [Base-Solana bridge](/base-chain/quickstart/base-solana-bridge) via the [`hookData`](https://github.com/base/flywheel/blob/30266bba4649b0eb161e55bfa4755651049a5d1f/src/hooks/BridgeReferralFees.sol#L75) mechanism. Currently available for **Solana → Base** flows only. - - - - When you register on base.dev, you will find a Builder Code under your app's settings. This is a random string (e.g., k3p9da) that you will use to generate your attribution suffix. - - - - ABI-encode the user address, your code, and fee: - - ```solidity - bytes memory hookData = abi.encode( - 0xUSER, // destination address on Base (NOT the Twin) - 0xBUILDER_CODE, // your builder code in type string memory - 100 // feeBps (100 = 1%) - ); - ``` - - - - - Set `to = BRIDGE_CAMPAIGN_ADDRESS` and attach a call to `Flywheel.send`. - - - - For a bridge with no follow-up call: - - ``` - to: // 0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9 on Base Sepolia - amount: 100 - call: - ty: Call - to: // 0x00000F14AD09382841DB481403D1775ADeE1179F on Base Sepolia - value: 0 - data: abi.encodeWithSelector( - Flywheel.send.selector, - , // 0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9 on Base Sepolia - , - hookData - ) - ``` - - - To chain additional calls, use `DelegateCall` with `Multicall`: - - ```solidity - Call[] memory calls = new Call[](2); - - // 1) Flywheel attribution (must be first) - calls[0] = Call({ - to: , // 0x00000F14AD09382841DB481403D1775ADeE1179F on Base Sepolia - value: 0, - data: abi.encodeWithSelector( - Flywheel.send.selector, - , // 0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9 on Base Sepolia - , // e.g. For SOL on Base Sepolia, use 0xCace0c896714DaF7098FFD8CC54aFCFe0338b4BC - hookData - ) - }); - - // 2) Your follow-up call - calls[1] = Call({ - to: , - value: 0, - data: abi.encodeWithSelector(YourContract.yourFunction.selector) - }); - ``` - - Then set the bridge call to: - - ``` - call: - ty: DelegateCall - to: // 0xcA11bde05977b3631167028862bE2a173976CA11 on Base Mainnet - data: abi.encodeWithSelector(Multicall.multicall.selector, calls) - ``` - - - - - - [Terminally Onchain](https://terminallyonchain.com/) is a production Next.js app that exposes the bridge via a command terminal UI. Users connect a Solana wallet, type commands such as to bridge and call a contract on Base: - - You can use [Terminally Onchain](https://terminallyonchain.com/) to test bridge transactions with Builder Codes like so: - - ```bash - bridge 0.0001 sol 0xYOUR_DESTINATION_ADDRESS --with-bc YOUR_BUILDER_CODE --bc-fee YOUR_FEE_BPS - ``` - - To see how this is implemented, you can take a look at the [Github repo](https://github.com/base/sol2base/blob/e0c283035be1e3e345d329e2d77b05e29a1d38b3/src/components/MainContent.tsx#L667): - - ```typescript sol2base/MainContent.tsx expandable - // Constants - const BRIDGE_CAMPAIGN_ADDRESS = "0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9"; - const FLYWHEEL_ADDRESS = "0x00000F14AD09382841DB481403D1775ADeE1179F"; - const MULTICALL_ADDRESS = "0xcA11bde05977b3631167028862bE2a173976CA11"; - - // Encode hookData: (address user, string code, uint8 feeBps) - const buildBuilderHookData = ( - destination: string, - builderCode: string, - feeBps: number - ) => { - const coder = new AbiCoder(); - return coder.encode( - ["address", "string", "uint8"], - [destination, builderCode, feeBps] - ); - }; - - // Build Flywheel.send call - const buildBuilderCall = ( - destination: string, - builderCode: string, - feeBps: number, - tokenAddress: string - ): BaseContractCall => { - const hookData = buildBuilderHookData(destination, builderCode, feeBps); - const data = encodeFunctionData({ - abi: FLYWHEEL_ABI, - functionName: "send", - args: [BRIDGE_CAMPAIGN_ADDRESS, tokenAddress, hookData], - }); - return { type: "call", target: FLYWHEEL_ADDRESS, value: "0", data }; - }; - - // Wrap builder + user calls in Multicall (for chained calls) - const buildMulticall = ( - builder: BaseContractCall, - userCall: BaseContractCall - ): BaseContractCall => { - const data = encodeFunctionData({ - abi: MULTICALL_ABI, - functionName: "multicall", - args: [ - [ - { target: builder.target, callData: builder.data }, - { target: userCall.target, callData: userCall.data }, - ], - ], - }); - return { type: "delegatecall", target: MULTICALL_ADDRESS, value: "0", data }; - }; - - // Usage: attach builder code to bridge - if (payload.flags.withBc) { - const builderCall = buildBuilderCall( - destination, - builderCode, - feeBps, - remoteToken - ); - callOption = userCall ? buildMulticall(builderCall, userCall) : builderCall; - } +**No.** Builder Codes only associate transactions with your application—they don't expose any wallet information that isn't already public onchain. + +### Can I Use ERC-8021 with Externally Owned Accounts (EOAs)? + +**Yes.** ERC-8021 works with both EOAs and smart contract wallets. + +### How Do I Verify That My Transaction Was Properly Attributed? - // Set destination to campaign address when using builder codes - const destinationForBridge = builderCode - ? BRIDGE_CAMPAIGN_ADDRESS - : payload.destination; - ``` +**1. Check base.dev** + +- Visit [base.dev](https://base.dev) +- Select **Onchain** from the transaction type dropdown +- Under the Total Transactions section, attribution counts increment when transactions with your code are processed + +**2. Use a Block Explorer (Basescan, Etherscan, etc.)** + +- Find your transaction hash +- View the input data field +- Verify the last 16 bytes are the `8021` repeating +- Decode the suffix to confirm your Builder Code is present + +**3. Open Source Tools** + +- Use the [Builder Code Validation](https://builder-code-checker.vercel.app/) tool +- Select transaction type +- Enter the transaction or UserOperation hash +- Click the **Check Attribution** button + +### Which Wallets Currently Support ERC-8021? + +**EOAs:** + +All EOA wallets support `dataSuffix` by default. + +**Smart Wallets:** + +Wallets supporting ERC-5792 can use the `DataSuffixCapability` for clean suffix appending. + + + ```javascript + await wallet.sendCalls({ + calls: [ + // your transaction calls + ], + capabilities: { + dataSuffix: { + value: "0x07626173656170700080218021802180218021802180218021", + optional: true + } + } + }); + ``` + - - +**Embedded Wallets:** +- **Privy** - Embedded wallet solution with ERC-8021 capability +- **Turnkey** - Infrastructure for programmatic wallets -## Contract Addresses +## Additional Resources -| Contract | Base Mainnet | Base Sepolia | -| -------- | ------------ | ------------ | -| `BRIDGE_CAMPAIGN_ADDRESS` | `0x539A97cc4724d5b2740DB98Bc71445448eFC1Bde` | `0xE2AD1C34382410C30d826B019A0B3700F5c4e6c9` | -| `FLYWHEEL_ADDRESS` | `0x00000F14AD09382841DB481403D1775ADeE1179F` | `0x00000F14AD09382841DB481403D1775ADeE1179F` | -| `MULTICALL_ADDRESS` | `0xcA11bde05977b3631167028862bE2a173976CA11` | `0xcA11bde05977b3631167028862bE2a173976CA11` | +- [Official ERC-8021 Proposal](https://eip.tools/eip/8021) +- [Builder Code Validation Tool](https://builder-code-checker.vercel.app/) -## Give feedback! +## Give Feedback! Base is constantly working to improve the Builder Codes experience. If you diff --git a/docs/base-chain/builder-codes/wallet-developers.mdx b/docs/base-chain/builder-codes/wallet-developers.mdx new file mode 100644 index 000000000..4882b873b --- /dev/null +++ b/docs/base-chain/builder-codes/wallet-developers.mdx @@ -0,0 +1,80 @@ +--- +title: "Builder Codes for Wallet Developers" +sidebarTitle: "For Wallet Developers" +description: "Implement the dataSuffix capability in your wallet to enable Builder Code attribution." +--- + +## Overview + +Wallet providers need to support the `dataSuffix` capability to enable attribution. This involves accepting the capability and appending the suffix to the calldata before signing. + + + + Your wallet should accept a `dataSuffix` object in the `capabilities` object of `wallet_sendCalls`. + + ```typescript + type DataSuffixCapability = { + value: `0x${string}`; // hex-encoded bytes provided by the app + optional?: boolean; // whether the capability is optional + } + ``` + + + + + When constructing the transaction or User Operation, extract the `dataSuffix` and append it to the calldata. + + + + Append to `tx.data`. + + ```typescript + // Minimal example for EOA + function applySuffixToEOA(tx, capabilities) { + const suffix = capabilities.dataSuffix?.value + if (!suffix) return tx + + return { + ...tx, + // Append suffix bytes (remove 0x prefix from suffix if tx.data has it) + data: tx.data + suffix.slice(2) + } + } + ``` + + + Append to `userOp.callData` (not the transaction-level calldata). + + ```typescript + // Minimal example for ERC-4337 + function applySuffixToUserOp(userOp, capabilities) { + const suffix = capabilities.dataSuffix?.value + if (!suffix) return userOp + + return { + ...userOp, + // Append suffix bytes to the UserOp callData + callData: userOp.callData + suffix.slice(2) + } + } + ``` + + + + + + Wallets may also include their own attribution code (their own ERC-8021 suffix) by prepending the wallet's suffix before the app's. + + - **No interaction required with apps:** The wallet handles this independently. + - **Multi-code support:** ERC-8021 natively supports multiple attribution codes. + + **Example:** + + ```typescript + finalSuffix = walletSuffix + appSuffix + ``` + + This ensures both the app and the wallet receive onchain attribution. + + + diff --git a/docs/docs.json b/docs/docs.json index 91ca5053a..8f8998bd9 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -122,7 +122,9 @@ "group": "Builder Codes", "pages": [ "base-chain/builder-codes/builder-codes", - "base-chain/builder-codes/builder-codes-faq" + "base-chain/builder-codes/app-developers", + "base-chain/builder-codes/wallet-developers", + "base-chain/builder-codes/bridge-developers" ] }, { @@ -1515,10 +1517,26 @@ ] }, "redirects": [ + { + "source": "/base-chain/builder-codes/builder-codes-faq", + "destination": "/base-chain/builder-codes/builder-codes" + }, { "source": "/base-chain/quickstart/builder-codes", "destination": "/base-chain/builder-codes/builder-codes" }, + { + "source": "/base-chain/builder-codes/builder-codes-app-developers", + "destination": "/base-chain/builder-codes/app-developers" + }, + { + "source": "/base-chain/builder-codes/builder-codes-wallet-developers", + "destination": "/base-chain/builder-codes/wallet-developers" + }, + { + "source": "/base-chain/builder-codes/builder-codes-bridge-developers", + "destination": "/base-chain/builder-codes/bridge-developers" + }, { "source": "/get-started/ai-prompting", "destination": "/get-started/docs-mcp"