From 2bf381246b73d0851c21805861a424b3cb446270 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 09:25:13 +0000 Subject: [PATCH] [#479] Add Builder Code (ERC-8021) attribution via dataSuffix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Uses ox/erc8021 Attribution.toDataSuffix with wagmi config-level dataSuffix — auto-appends to all transactions. NEXT_PUBLIC_BUILDER_CODE left empty until operator registers at base.dev. Co-Authored-By: Claude Opus 4.6 (1M context) --- lib/builder-code.ts | 20 ++++++ lib/wagmi.ts | 2 + package-lock.json | 154 +++++++++++++++++++++++++++----------------- package.json | 1 + 4 files changed, 119 insertions(+), 58 deletions(-) create mode 100644 lib/builder-code.ts diff --git a/lib/builder-code.ts b/lib/builder-code.ts new file mode 100644 index 00000000..a5d07f20 --- /dev/null +++ b/lib/builder-code.ts @@ -0,0 +1,20 @@ +/** + * Base Builder Code (ERC-8021) attribution for PlotLink transactions. + * + * Appends a Builder Code suffix to transaction calldata so Base indexers + * can attribute onchain activity back to PlotLink. + * + * Register at base.dev and set NEXT_PUBLIC_BUILDER_CODE in env vars. + */ + +import { Attribution } from "ox/erc8021"; + +const BUILDER_CODE = process.env.NEXT_PUBLIC_BUILDER_CODE ?? ""; + +/** + * Pre-computed ERC-8021 data suffix for the configured Builder Code. + * Returns undefined if Builder Code is not configured (attribution disabled). + */ +export const DATA_SUFFIX: `0x${string}` | undefined = BUILDER_CODE + ? Attribution.toDataSuffix({ codes: [BUILDER_CODE] }) + : undefined; diff --git a/lib/wagmi.ts b/lib/wagmi.ts index ec2bae94..7bb9c22a 100644 --- a/lib/wagmi.ts +++ b/lib/wagmi.ts @@ -3,6 +3,7 @@ import { base, baseSepolia } from "wagmi/chains"; import { injected } from "wagmi/connectors"; import { farcasterMiniApp } from "@farcaster/miniapp-wagmi-connector"; import { createFallbackTransport } from "./rpc"; +import { DATA_SUFFIX } from "./builder-code"; const IS_MAINNET = process.env.NEXT_PUBLIC_CHAIN_ID === "8453"; @@ -14,6 +15,7 @@ export const config = createConfig({ [baseSepolia.id]: IS_MAINNET ? http() : createFallbackTransport(), }, ssr: true, + ...(DATA_SUFFIX ? { dataSuffix: DATA_SUFFIX } : {}), }); declare module "wagmi" { diff --git a/package-lock.json b/package-lock.json index f14f6a22..3175bd6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "@supabase/supabase-js": "^2.99.1", "@tanstack/react-query": "^5.90.21", "next": "16.1.6", + "ox": "^0.14.8", "react": "19.2.3", "react-dom": "19.2.3", "viem": "^2.47.2", @@ -1990,6 +1991,41 @@ "zod": "^3.25.0" } }, + "node_modules/@farcaster/miniapp-core/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/@farcaster/miniapp-core/node_modules/ox": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.4.4.tgz", + "integrity": "sha512-oJPEeCDs9iNiPs6J0rTx+Y0KGeCGyCAA3zo94yZhm8G5WpOxrwUtn2Ie/Y8IyARSqqY/j9JTKA3Fc1xs1DvFnw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@farcaster/miniapp-sdk": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/@farcaster/miniapp-sdk/-/miniapp-sdk-0.2.3.tgz", @@ -2003,6 +2039,41 @@ "ox": "^0.4.4" } }, + "node_modules/@farcaster/miniapp-sdk/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/@farcaster/miniapp-sdk/node_modules/ox": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.4.4.tgz", + "integrity": "sha512-oJPEeCDs9iNiPs6J0rTx+Y0KGeCGyCAA3zo94yZhm8G5WpOxrwUtn2Ie/Y8IyARSqqY/j9JTKA3Fc1xs1DvFnw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/@farcaster/miniapp-wagmi-connector": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@farcaster/miniapp-wagmi-connector/-/miniapp-wagmi-connector-1.1.1.tgz", @@ -9453,9 +9524,9 @@ } }, "node_modules/ox": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.4.4.tgz", - "integrity": "sha512-oJPEeCDs9iNiPs6J0rTx+Y0KGeCGyCAA3zo94yZhm8G5WpOxrwUtn2Ie/Y8IyARSqqY/j9JTKA3Fc1xs1DvFnw==", + "version": "0.14.8", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.8.tgz", + "integrity": "sha512-/0htlpIaWzwMh68v08IhtCRtSGEfNQZnjAQUqIoLxKdn7u88r0EDdVckZin2UMI414GdhqJ62po6nc7atTDE1Q==", "funding": [ { "type": "github", @@ -9464,12 +9535,13 @@ ], "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "^1.10.1", - "@noble/curves": "^1.6.0", - "@noble/hashes": "^1.5.0", - "@scure/bip32": "^1.5.0", - "@scure/bip39": "^1.4.0", - "abitype": "^1.0.6", + "@adraffy/ens-normalize": "^1.11.0", + "@noble/ciphers": "^1.3.0", + "@noble/curves": "1.9.1", + "@noble/hashes": "^1.8.0", + "@scure/bip32": "^1.7.0", + "@scure/bip39": "^1.6.0", + "abitype": "^1.2.3", "eventemitter3": "5.0.1" }, "peerDependencies": { @@ -9481,6 +9553,21 @@ } } }, + "node_modules/ox/node_modules/@noble/curves": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", + "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.8.0" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/ox/node_modules/eventemitter3": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", @@ -11524,23 +11611,6 @@ } } }, - "node_modules/wagmi/node_modules/@noble/curves": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", - "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/wagmi/node_modules/@wagmi/connectors": { "version": "7.2.1", "resolved": "https://registry.npmjs.org/@wagmi/connectors/-/connectors-7.2.1.tgz", @@ -11625,38 +11695,6 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, - "node_modules/wagmi/node_modules/ox": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.14.5.tgz", - "integrity": "sha512-HgmHmBveYO40H/R3K6TMrwYtHsx/u6TAB+GpZlgJCoW0Sq5Ttpjih0IZZiwGQw7T6vdW4IAyobYrE2mdAvyF8Q==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "@adraffy/ens-normalize": "^1.11.0", - "@noble/ciphers": "^1.3.0", - "@noble/curves": "1.9.1", - "@noble/hashes": "^1.8.0", - "@scure/bip32": "^1.7.0", - "@scure/bip39": "^1.6.0", - "abitype": "^1.2.3", - "eventemitter3": "5.0.1" - }, - "peerDependencies": { - "typescript": ">=5.4.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", diff --git a/package.json b/package.json index 1be20cad..b150f485 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@supabase/supabase-js": "^2.99.1", "@tanstack/react-query": "^5.90.21", "next": "16.1.6", + "ox": "^0.14.8", "react": "19.2.3", "react-dom": "19.2.3", "viem": "^2.47.2",