Repository navigation
feat(accounts): point the Accounts demos at the t14-checkpoint devnet #1047
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 | ||
|
|
@@ -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])) | ||
|
Comment on lines
266
to
+268
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Readers who follow the Accounts upgrade and watch-changes pages get a wrong upgraded config and an empty update list on the new devnet. The demos moved to Why this was flaggedsrc/pages/docs/accounts/account-configuration/account-upgrade.mdx:81 builds Verification: Trigger: a reader copies the account-upgrade or watch-changes sample after this merges. |
||
| } | ||
|
|
||
| /** | ||
|
|
@@ -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 | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<Response> { | |
| 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<string, unknown> | ||
| ;(call as { params: unknown[] }).params[0] = { | ||
| ...rest, | ||
| configurableAccountSimulation: multisigSimulation, | ||
| } | ||
| return true | ||
| } | ||
|
Comment on lines
+78
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Node readers of the Accounts snippets send a new account's first transaction without the renamed simulation hint, so it can run out of gas on t14-checkpoint. Only the browser proxy renames Why this was flaggedThe PR moves the snippet Verification: The rename covers only the browser proxy: |
||
|
|
||
| function failure(status: number, message: string) { | ||
| return Response.json( | ||
| { jsonrpc: '2.0', id: null, error: { code: -32000, message } }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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', { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔴 Readers who copy the Accounts docs samples now hit a devnet their code can't talk to. The samples break where they worked against multisig-1113 on base. This line points the shared Why this was flaggedThe Verification: The trigger is a reader who copies a docs sample and runs it with released viem/ox from npm. src/snippets/accounts-devnet.ts:14 now has |
||
| fetchOptions: { headers: { Authorization: `Basic ${btoa(`previews:${rpcKey}`)}` } }, | ||
| }), | ||
| }) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Production docs builds now install an ox preview tarball that the lockfile cannot integrity-check, and it ships in every page bundle that uses viem 2.57.5. The new lock entry at pnpm-lock.yaml:5092 records only
resolution: {tarball: https://pkg.pr.new/ox@ bf010ee}, with nointegrity. The vocs preview entry at pnpm-lock.yaml:6180 does carry one. Fix: regenerate the lock entry so it records an integrity hash for the ox tarball, or depend on an npm-published ox snapshot with an integrity hash.Why this was flagged
The override
'viem@ 2.57.5>ox': https://pkg.pr.new/ox@ bf010ee(pnpm-workspace.yaml:35) applies to every viem@ 2.57.5 instance in the tree. That covers the site's own viem plus wagmi, accounts@ 0.19.1 and mppx (pnpm-lock.yaml:12674), not only the devnet demos. The new lock entry at pnpm-lock.yaml:5091-5093 has no integrity hash. Itsversion: 0.14.57-755f436.0also names a different short sha than thebf010eein the URL. Sopnpm install --frozen-lockfiledownloads whatever bytes pkg.pr.new serves for that URL and has nothing to compare them against. Other bytes reach the production browser bundle unnoticed, including wallet and signing code on mainnet and testnet pages. On base, ox@ 0.14.56 came from npm withintegrity: sha512-…. The neighbouring vocs pkg.pr.new override shows the lockfile can record an integrity hash for these tarballs, so this missing hash is not inherent to pkg.pr.new.Verification: The trigger is pkg.pr.new serving different bytes at
https://pkg.pr.new/ox@ bf010eethan the ones the author tested. The lock entry at pnpm-lock.yaml:5091-5093 has nointegrityfield, while the vocs entry at pnpm-lock.yaml:6180 and the replacedox@ 0.14.56both had one. Sopnpm install --frozen-lockfileinstalls and bundles whatever the URL serves.