{"version":3,"file":"builder-code.mjs","names":[],"sources":["../../../src/services/builder-code.ts"],"sourcesContent":["/**\n * Base Builder Code (ERC-8021) — transaction attribution for base.dev analytics.\n *\n * Every transaction on Base sent through OpenClawnch includes a data suffix that\n * attributes the transaction to our builder code. This:\n * 1. Tracks on-chain usage on base.dev\n * 2. Qualifies for Base ecosystem rewards\n * 3. Shows up in app leaderboards\n *\n * The suffix is appended to the `data` field of every sendTransaction call.\n * For native ETH transfers (no data), the suffix becomes the entire data field.\n * Smart contracts ignore trailing calldata — zero impact on execution.\n *\n * @see https://docs.base.org/base-chain/builder-codes/builder-codes\n * @see ERC-8021: https://eip.tools/eip/8021\n */\n\n// ─── Builder Code Configuration ─────────────────────────────────────────\n\n/** OpenClawnch's registered Base Builder Code. */\nexport const BUILDER_CODE = 'bc_z92vaimh';\n\n/**\n * Pre-computed ERC-8021 data suffix for our builder code.\n *\n * Format: [1 byte: code length] [N bytes: UTF-8 code] [0x00] [8021 repeated 8 times]\n *\n * Encoding breakdown for 'bc_z92vaimh':\n *   0b                         = length 11\n *   62635f7a39327661696d68     = 'bc_z92vaimh' UTF-8\n *   00                         = separator\n *   80218021802180218021802180218021 = ERC-8021 magic (8 × 0x8021)\n */\nexport const DATA_SUFFIX = '0x0b62635f7a39327661696d680080218021802180218021802180218021' as const;\n\n/** Base chain IDs where the suffix should be applied. */\nconst BASE_CHAIN_IDS = new Set([\n  8453,   // Base Mainnet\n  84532,  // Base Sepolia\n]);\n\n// ─── Suffix Injection ───────────────────────────────────────────────────\n\n/**\n * Append the ERC-8021 builder code suffix to transaction data.\n *\n * - If data is empty/undefined (native ETH transfer), the suffix becomes the data.\n * - If data exists (contract call), the suffix is appended to the end.\n * - Only applies to Base chain transactions.\n *\n * @param data - Existing transaction data (hex string or undefined)\n * @param chainId - The chain this transaction targets\n * @returns The data with suffix appended, or original data if not Base\n */\nexport function appendBuilderCode(data: string | undefined, chainId: number | undefined): string | undefined {\n  // Only apply to Base chains\n  if (!chainId || !BASE_CHAIN_IDS.has(chainId)) {\n    return data;\n  }\n\n  // Suffix without '0x' prefix for concatenation\n  const suffixHex = DATA_SUFFIX.slice(2);\n\n  if (!data || data === '0x') {\n    // Native ETH transfer — suffix becomes the entire data field\n    return DATA_SUFFIX;\n  }\n\n  // Contract call — append suffix to existing calldata\n  // Remove '0x' from data, concatenate, re-add prefix\n  const cleanData = data.startsWith('0x') ? data.slice(2) : data;\n  return '0x' + cleanData + suffixHex;\n}\n\n/**\n * Check if a transaction's data field already contains our builder code suffix.\n */\nexport function hasBuilderCode(data: string | undefined): boolean {\n  if (!data) return false;\n  return data.endsWith(DATA_SUFFIX.slice(2));\n}\n\n/**\n * Wrap a viem wallet client to automatically append the builder code suffix\n * to all sendTransaction calls on Base.\n *\n * This is the main integration point. Applied once at wallet client creation\n * in walletconnect-service.ts.\n *\n * The wrapper intercepts the `request` method on the transport, catches\n * `eth_sendTransaction` calls, and appends the suffix to the data field.\n */\nexport function wrapWithBuilderCode(walletClient: any, chainId?: number): any {\n  if (!walletClient) return walletClient;\n\n  const effectiveChainId = chainId ?? walletClient.chain?.id;\n\n  // Only wrap for Base chains\n  if (!effectiveChainId || !BASE_CHAIN_IDS.has(effectiveChainId)) {\n    return walletClient;\n  }\n\n  // Store the original sendTransaction\n  const originalSendTransaction = walletClient.sendTransaction?.bind(walletClient);\n  const originalWriteContract = walletClient.writeContract?.bind(walletClient);\n\n  if (originalSendTransaction) {\n    walletClient.sendTransaction = async (args: any) => {\n      // Append builder code to data\n      const modifiedArgs = {\n        ...args,\n        data: appendBuilderCode(args.data, effectiveChainId),\n      };\n      return originalSendTransaction(modifiedArgs);\n    };\n  }\n\n  // writeContract internally calls sendTransaction, so we DON'T need to wrap it\n  // separately — the sendTransaction wrapper catches it. But if the client has\n  // a direct writeContract that bypasses sendTransaction, we wrap it too.\n  // In practice with viem, writeContract encodes ABI → sendTransaction, so\n  // the sendTransaction wrapper is sufficient.\n\n  return walletClient;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAoBA,MAAa,eAAe;;;;;;;;;;;;AAa5B,MAAa,cAAc;;AAG3B,MAAM,iBAAiB,IAAI,IAAI,CAC7B,MACA,MACD,CAAC;;;;;;;;;;;;AAeF,SAAgB,kBAAkB,MAA0B,SAAiD;AAE3G,KAAI,CAAC,WAAW,CAAC,eAAe,IAAI,QAAQ,CAC1C,QAAO;CAIT,MAAM,YAAY,YAAY,MAAM,EAAE;AAEtC,KAAI,CAAC,QAAQ,SAAS,KAEpB,QAAO;AAMT,QAAO,QADW,KAAK,WAAW,KAAK,GAAG,KAAK,MAAM,EAAE,GAAG,QAChC;;;;;AAM5B,SAAgB,eAAe,MAAmC;AAChE,KAAI,CAAC,KAAM,QAAO;AAClB,QAAO,KAAK,SAAS,YAAY,MAAM,EAAE,CAAC;;;;;;;;;;;;AAa5C,SAAgB,oBAAoB,cAAmB,SAAuB;AAC5E,KAAI,CAAC,aAAc,QAAO;CAE1B,MAAM,mBAAmB,WAAW,aAAa,OAAO;AAGxD,KAAI,CAAC,oBAAoB,CAAC,eAAe,IAAI,iBAAiB,CAC5D,QAAO;CAIT,MAAM,0BAA0B,aAAa,iBAAiB,KAAK,aAAa;AAClD,cAAa,eAAe,KAAK,aAAa;AAE5E,KAAI,wBACF,cAAa,kBAAkB,OAAO,SAAc;AAMlD,SAAO,wBAJc;GACnB,GAAG;GACH,MAAM,kBAAkB,KAAK,MAAM,iBAAiB;GACrD,CAC2C;;AAUhD,QAAO"}