From 9c6c835bfa79c4a1be0e29a8e3187b1637878368 Mon Sep 17 00:00:00 2001 From: Liam Horne Date: Wed, 21 Oct 2026 17:02:06 -0400 Subject: [PATCH 1/3] feat(accounts): point the Accounts demos at the t14-checkpoint devnet The t14-checkpoint devnet runs joshie/configurable-t14-devnet-checkpoint, which renames the configurable account hash domains and RPC fields. - Repoint the RPC proxy, tailnet URL and Node snippet from multisig-1113. - Pin viem's ox to the wevm/ox#519 preview for the new hash domains. - Rename multisigSimulation to configurableAccountSimulation in the proxy, so the node estimates a new account's first transaction correctly. Configuration updates still fail until viem ships the renamed precompile ABI. Co-Authored-By: Claude Opus 5.5 --- pnpm-lock.yaml | 37 ++++--------------- pnpm-workspace.yaml | 2 + .../guides/account-sandbox-devnet.ts | 2 +- src/components/guides/devnet-network.ts | 4 +- src/pages/_api/api/devnet-rpc.ts | 22 +++++++++-- src/snippets/accounts-devnet.ts | 2 +- 6 files changed, 33 insertions(+), 36 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8460a7f24..32559eb55 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,6 +6,7 @@ settings: overrides: vocs: https://pkg.pr.new/vocs@1c023ba + viem>ox: https://pkg.pr.new/ox@bf010ee tapimo>accounts: 0.18.4 baseline-browser-mapping@<2.11.0: 2.11.0 browserslist@<4.28.7: 4.28.7 @@ -5055,14 +5056,6 @@ packages: outvariant@1.4.0: resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} - ox@0.14.30: - resolution: {integrity: sha512-LI11uu+8iiM1B3CLckgd++YF1a0A2k5wDoM9ZeQMiL21BOzQs6L//BLS6hb1HSEKCyycdDIQLsVQx9MjpcC0hA==} - peerDependencies: - typescript: '>=5.4.0' - peerDependenciesMeta: - typescript: - optional: true - ox@0.14.33: resolution: {integrity: sha512-rooA/4o7bBof4Ge2VH/eovfNPb/AEEYyrNj03wggc55g5HZD8Pjs/OeWhttgjic3dDcqn0r29bDuvQEdTiUemQ==} peerDependencies: @@ -5087,8 +5080,9 @@ packages: typescript: optional: true - ox@0.14.56: - resolution: {integrity: sha512-Feinlj+deWEam6RIwurRE+eHZ2N3hoUb3AAjQ10BmxRCYIymfqNkv0eZ+4ln4GkgDmSGLD2rGtTMqsFYSVDC6w==} + ox@https://pkg.pr.new/ox@bf010ee: + resolution: {integrity: sha512-CSWABGIgNHezjt0UVCh4Rn0UCfTv9SdHvO9BpZ6WYogVIuW/D/bCjHRK6ELMnT2aQBWo2rtI7gb8GZQfHJ1vjA==, tarball: https://pkg.pr.new/ox@bf010ee} + version: 0.14.57-755f436.0 peerDependencies: typescript: '>=5.4.0' peerDependenciesMeta: @@ -11351,21 +11345,6 @@ snapshots: outvariant@1.4.0: {} - ox@0.14.30(typescript@6.0.3)(zod@4.6.5): - dependencies: - '@adraffy/ens-normalize': 1.11.1 - '@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.4(typescript@6.0.3)(zod@4.6.5) - eventemitter3: 5.0.1 - optionalDependencies: - typescript: 6.0.3 - transitivePeerDependencies: - - zod - ox@0.14.33(typescript@6.0.3)(zod@4.6.5): dependencies: '@adraffy/ens-normalize': 1.11.1 @@ -11411,7 +11390,7 @@ snapshots: transitivePeerDependencies: - zod - ox@0.14.56(typescript@6.0.3)(zod@4.6.5): + ox@https://pkg.pr.new/ox@bf010ee(typescript@6.0.3)(zod@4.6.5): dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 @@ -12635,7 +12614,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.6.5) isows: 1.0.7(ws@8.21.0) - ox: 0.14.30(typescript@6.0.3)(zod@4.6.5) + ox: https://pkg.pr.new/ox@bf010ee(typescript@6.0.3)(zod@4.6.5) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 @@ -12652,7 +12631,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.6.5) isows: 1.0.7(ws@8.21.0) - ox: 0.14.45(typescript@6.0.3)(zod@4.6.5) + ox: https://pkg.pr.new/ox@bf010ee(typescript@6.0.3)(zod@4.6.5) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 @@ -12669,7 +12648,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.6.5) isows: 1.0.7(ws@8.21.0) - ox: 0.14.56(typescript@6.0.3)(zod@4.6.5) + ox: https://pkg.pr.new/ox@bf010ee(typescript@6.0.3)(zod@4.6.5) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 19ae7941d..2acef8a1f 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -31,6 +31,8 @@ onlyBuiltDependencies: overrides: vocs: https://pkg.pr.new/vocs@1c023ba + # Configurable account hash domains matching the t14-checkpoint devnet (wevm/ox#519). + 'viem>ox': https://pkg.pr.new/ox@bf010ee # accounts 0.18.5 was published with unresolved catalog dependencies. 'tapimo>accounts': 0.18.4 'baseline-browser-mapping@<2.11.0': 2.11.0 diff --git a/src/components/guides/account-sandbox-devnet.ts b/src/components/guides/account-sandbox-devnet.ts index da953222b..423f01863 100644 --- a/src/components/guides/account-sandbox-devnet.ts +++ b/src/components/guides/account-sandbox-devnet.ts @@ -1,6 +1,6 @@ /** * Devnet adapter for the account sandbox. It sends the sandbox's actions as real transactions on - * the internal multisig-1113 devnet, which runs configurable accounts (TIP-1107 to TIP-1114) and + * the internal t14-checkpoint devnet, which runs configurable accounts (TIP-1107 to TIP-1114) and * configurable access keys (TIP-1111). * * - Only real signing runs on devnet. Passkeys are real WebAuthn passkeys, so creating and signing diff --git a/src/components/guides/devnet-network.ts b/src/components/guides/devnet-network.ts index 14a95f963..be212b261 100644 --- a/src/components/guides/devnet-network.ts +++ b/src/components/guides/devnet-network.ts @@ -2,12 +2,12 @@ import type { Address } from 'viem' import { developersApiPath } from '../../marketing/app/_lib/developersPaths' /** - * Where the Accounts demos reach the multisig-1113 devnet. Kept apart from + * Where the Accounts demos reach the t14-checkpoint devnet. Kept apart from * `account-sandbox-devnet.ts` so small demos can import these values without bundling the adapter. */ /** The demo devnet's Tailscale RPC, for Node scripts on the tailnet. */ -export const devnetTailnetRpcUrl = 'http://multisig-1113-nodes-rpc-service.tail388b2e.ts.net:8545' +export const devnetTailnetRpcUrl = 'http://t14-checkpoint-nodes-rpc-service.tail388b2e.ts.net:8545' /** * Pages reach the devnet through the docs site's same-origin proxy (`/api/devnet-rpc`), which holds diff --git a/src/pages/_api/api/devnet-rpc.ts b/src/pages/_api/api/devnet-rpc.ts index adc4b5610..824792ccd 100644 --- a/src/pages/_api/api/devnet-rpc.ts +++ b/src/pages/_api/api/devnet-rpc.ts @@ -1,9 +1,10 @@ -// Same-origin JSON-RPC proxy for the Accounts demos on the multisig-1113 devnet. +// Same-origin JSON-RPC proxy for the Accounts demos on the t14-checkpoint devnet. // Its public endpoint sits behind the shared `previews` API key, which must stay server-side, // and HTTPS pages can't call the Tailscale-only HTTP endpoint. Without a key (local dev on the // tailnet), it forwards to the Tailscale RPC instead. -const publicUpstream = process.env.DEVNET_RPC_URL ?? 'https://rpc-multisig-1113.devnet.tempoxyz.dev' -const tailnetUpstream = 'http://multisig-1113-nodes-rpc-service.tail388b2e.ts.net:8545' +const publicUpstream = + process.env.DEVNET_RPC_URL ?? 'https://rpc-t14-checkpoint.devnet.tempoxyz.dev' +const tailnetUpstream = 'http://t14-checkpoint-nodes-rpc-service.tail388b2e.ts.net:8545' const maxRequestBytes = 256 * 1024 const maxResponseBytes = 4 * 1024 * 1024 @@ -24,6 +25,7 @@ export async function POST(request: Request): Promise { const calls = Array.isArray(parsed) ? parsed : [parsed] if (calls.length === 0 || calls.length > maxBatch || !calls.every(isAllowedCall)) return failure(400, 'Unsupported demo RPC request') + if (calls.map(renameSimulation).includes(true)) body = JSON.stringify(parsed) } catch { return failure(400, 'Invalid JSON-RPC request') } @@ -73,6 +75,20 @@ function isAllowedCall(call: unknown) { return allowedMethods.has(method) || allowedPrefixes.some((prefix) => method.startsWith(prefix)) } +// ox still sends the simulation hint as `multisigSimulation`, and the t14-checkpoint node reads +// `configurableAccountSimulation`. Without it, the node underestimates a new account's first +// transaction and it runs out of gas. Remove once ox sends the new name. +function renameSimulation(call: unknown) { + const [request] = (call as { params?: unknown[] }).params ?? [] + if (!request || typeof request !== 'object' || !('multisigSimulation' in request)) return false + const { multisigSimulation, ...rest } = request as Record + ;(call as { params: unknown[] }).params[0] = { + ...rest, + configurableAccountSimulation: multisigSimulation, + } + return true +} + function failure(status: number, message: string) { return Response.json( { jsonrpc: '2.0', id: null, error: { code: -32000, message } }, diff --git a/src/snippets/accounts-devnet.ts b/src/snippets/accounts-devnet.ts index e6be86f55..f67961046 100644 --- a/src/snippets/accounts-devnet.ts +++ b/src/snippets/accounts-devnet.ts @@ -11,7 +11,7 @@ const rpcKey = process.env.TEMPO_DEVNET_RPC_KEY export const client = createClient({ chain: tempoDevnet, - transport: http('https://rpc-multisig-1113.devnet.tempoxyz.dev', { + transport: http('https://rpc-t14-checkpoint.devnet.tempoxyz.dev', { fetchOptions: { headers: { Authorization: `Basic ${btoa(`previews:${rpcKey}`)}` } }, }), }) From 6bcb7c17b32aa962a3e9007344eaceeb85c7fa94 Mon Sep 17 00:00:00 2001 From: Liam Horne Date: Wed, 21 Oct 2026 17:26:04 -0400 Subject: [PATCH 2/3] fix(accounts): parse the renamed config update event and upgrade salt domain The t14-checkpoint node emits ConfigurableAccountConfigUpdated and salts in-place upgrades with tempo:configurable-account:upgrade. viem still expects MultisigConfigUpdated, so updateConfigSync threw after a successful update. Send the update directly and parse the new event. Co-Authored-By: Claude Opus 5.5 --- src/components/guides/UpgradeAccountDemo.tsx | 2 +- .../guides/account-sandbox-devnet.test.ts | 4 +++- .../guides/account-sandbox-devnet.ts | 21 +++++++++++++++---- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/components/guides/UpgradeAccountDemo.tsx b/src/components/guides/UpgradeAccountDemo.tsx index 4274dd9b4..c6b12b193 100644 --- a/src/components/guides/UpgradeAccountDemo.tsx +++ b/src/components/guides/UpgradeAccountDemo.tsx @@ -41,7 +41,7 @@ async function loadDemo() { ]), // The configuration salt Tempo assigns an upgraded account. upgradeSalt: (address: Address) => - viem.keccak256(viem.concat([viem.toHex('tempo:multisig:upgrade'), address])), + viem.keccak256(viem.concat([viem.toHex('tempo:configurable-account:upgrade'), address])), } } diff --git a/src/components/guides/account-sandbox-devnet.test.ts b/src/components/guides/account-sandbox-devnet.test.ts index ccde4ccd8..ba837d74a 100644 --- a/src/components/guides/account-sandbox-devnet.test.ts +++ b/src/components/guides/account-sandbox-devnet.test.ts @@ -488,7 +488,9 @@ describe('upgrading a plain key account', () => { it('uses Tempo’s upgrade salt for the address', async () => { const { concat, keccak256, toHex } = await import('viem') - expect(upgradeSalt(address)).toBe(keccak256(concat([toHex('tempo:multisig:upgrade'), address]))) + expect(upgradeSalt(address)).toBe( + keccak256(concat([toHex('tempo:configurable-account:upgrade'), address])), + ) }) it('records owners sorted by address, at version 1', () => { diff --git a/src/components/guides/account-sandbox-devnet.ts b/src/components/guides/account-sandbox-devnet.ts index 423f01863..e62895897 100644 --- a/src/components/guides/account-sandbox-devnet.ts +++ b/src/components/guides/account-sandbox-devnet.ts @@ -29,6 +29,7 @@ import { isAddressEqual, keccak256, parseAbi, + parseEventLogs, toHex, } from 'viem' import { generatePrivateKey } from 'viem/accounts' @@ -256,10 +257,15 @@ const nativeMultisig: Address = '0xAACC000000000000000000000000000000000000' const upgradeAbi = parseAbi([ 'function upgradeAccount(uint8 threshold, (address owner, uint8 weight)[] owners) returns (bytes32)', ]) +// viem's `Abis.nativeMultisig` still names this event `MultisigConfigUpdated`, so +// `accounts.updateConfigSync` can't find it. Remove once viem ships the renamed ABI. +const configUpdatedAbi = parseAbi([ + 'event ConfigurableAccountConfigUpdated(address indexed account, bytes32 salt, uint64 version, uint8 threshold, (address owner, uint8 weight)[] owners)', +]) /** The configuration salt Tempo assigns an account upgraded in place. */ export function upgradeSalt(address: Address) { - return keccak256(concat([toHex('tempo:multisig:upgrade'), address])) + return keccak256(concat([toHex('tempo:configurable-account:upgrade'), address])) } /** @@ -997,11 +1003,18 @@ export function createDevnetAdapter( const next = { owners, threshold: account.committed.threshold } if (sameConfig(next, session.config)) return undefined const approvers = updateApprovers(session, account) - const { config, receipt } = await client.accounts.updateConfigSync({ + const receipt = await client.writeContractSync({ account: signingAccount(session, localAccounts(approvers)), - nextConfig: next, + ...Tempo.Actions.accounts.updateConfig.call({ + currentConfig: session.config, + nextConfig: next, + }), + throwOnReceiptRevert: true, }) - session.config = config + const [log] = parseEventLogs({ abi: configUpdatedAbi, logs: receipt.logs, strict: true }) + if (!log) + throw new DevnetRejection('invalid-config', 'Devnet recorded no configuration update.') + session.config = Tempo.AccountConfig.from(log.args) session.lastUpdate = receipt.transactionHash return receipt.transactionHash } From f74411bb2f51cf99ba9a9bca581385546bbc36fb Mon Sep 17 00:00:00 2001 From: Liam Horne Date: Wed, 21 Oct 2026 17:35:46 -0400 Subject: [PATCH 3/3] fix(deps): scope the ox preview override to the docs' viem viem>ox also replaced ox under transitive viem 2.54.6, which imports the MultisigConfig export the preview dropped, and broke the build. Co-Authored-By: Claude Opus 5.5 --- pnpm-lock.yaml | 31 +++++++++++++++++++++++++++---- pnpm-workspace.yaml | 2 +- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32559eb55..6696935ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: overrides: vocs: https://pkg.pr.new/vocs@1c023ba - viem>ox: https://pkg.pr.new/ox@bf010ee + viem@2.57.5>ox: https://pkg.pr.new/ox@bf010ee tapimo>accounts: 0.18.4 baseline-browser-mapping@<2.11.0: 2.11.0 browserslist@<4.28.7: 4.28.7 @@ -5056,6 +5056,14 @@ packages: outvariant@1.4.0: resolution: {integrity: sha512-AlWY719RF02ujitly7Kk/0QlV+pXGFDHrHf9O2OKqyqgBieaPOIeuSkL8sRK6j2WK+/ZAURq2kZsY0d8JapUiw==} + ox@0.14.30: + resolution: {integrity: sha512-LI11uu+8iiM1B3CLckgd++YF1a0A2k5wDoM9ZeQMiL21BOzQs6L//BLS6hb1HSEKCyycdDIQLsVQx9MjpcC0hA==} + peerDependencies: + typescript: '>=5.4.0' + peerDependenciesMeta: + typescript: + optional: true + ox@0.14.33: resolution: {integrity: sha512-rooA/4o7bBof4Ge2VH/eovfNPb/AEEYyrNj03wggc55g5HZD8Pjs/OeWhttgjic3dDcqn0r29bDuvQEdTiUemQ==} peerDependencies: @@ -5081,7 +5089,7 @@ packages: optional: true ox@https://pkg.pr.new/ox@bf010ee: - resolution: {integrity: sha512-CSWABGIgNHezjt0UVCh4Rn0UCfTv9SdHvO9BpZ6WYogVIuW/D/bCjHRK6ELMnT2aQBWo2rtI7gb8GZQfHJ1vjA==, tarball: https://pkg.pr.new/ox@bf010ee} + resolution: {tarball: https://pkg.pr.new/ox@bf010ee} version: 0.14.57-755f436.0 peerDependencies: typescript: '>=5.4.0' @@ -11345,6 +11353,21 @@ snapshots: outvariant@1.4.0: {} + ox@0.14.30(typescript@6.0.3)(zod@4.6.5): + dependencies: + '@adraffy/ens-normalize': 1.11.1 + '@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.4(typescript@6.0.3)(zod@4.6.5) + eventemitter3: 5.0.1 + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - zod + ox@0.14.33(typescript@6.0.3)(zod@4.6.5): dependencies: '@adraffy/ens-normalize': 1.11.1 @@ -12614,7 +12637,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.6.5) isows: 1.0.7(ws@8.21.0) - ox: https://pkg.pr.new/ox@bf010ee(typescript@6.0.3)(zod@4.6.5) + ox: 0.14.30(typescript@6.0.3)(zod@4.6.5) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 @@ -12631,7 +12654,7 @@ snapshots: '@scure/bip39': 1.6.0 abitype: 1.2.3(typescript@6.0.3)(zod@4.6.5) isows: 1.0.7(ws@8.21.0) - ox: https://pkg.pr.new/ox@bf010ee(typescript@6.0.3)(zod@4.6.5) + ox: 0.14.45(typescript@6.0.3)(zod@4.6.5) ws: 8.21.0 optionalDependencies: typescript: 6.0.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 2acef8a1f..807714c72 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -32,7 +32,7 @@ onlyBuiltDependencies: overrides: vocs: https://pkg.pr.new/vocs@1c023ba # Configurable account hash domains matching the t14-checkpoint devnet (wevm/ox#519). - 'viem>ox': https://pkg.pr.new/ox@bf010ee + 'viem@2.57.5>ox': https://pkg.pr.new/ox@bf010ee # accounts 0.18.5 was published with unresolved catalog dependencies. 'tapimo>accounts': 0.18.4 'baseline-browser-mapping@<2.11.0': 2.11.0