diff --git a/e2e/deposit-to-a-zone.test.ts b/e2e/deposit-to-a-zone.test.ts
index 56b2e73e..a57f5847 100644
--- a/e2e/deposit-to-a-zone.test.ts
+++ b/e2e/deposit-to-a-zone.test.ts
@@ -25,11 +25,8 @@ test('prepare zone access and deposit to Zone A', async ({ page }) => {
timeout: 30000,
})
- const authorizeButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
- .first()
+ const authorizeButton = page.getByRole('button', { name: 'Authorize Zone A reads' }).first()
await expect(authorizeButton).toBeVisible({ timeout: 30000 })
- await expect(authorizeButton).toBeEnabled({ timeout: 90000 })
await authorizeButton.click()
const getFundsButton = page.getByRole('button', { name: /^Get testnet pathUSD$/i }).first()
diff --git a/e2e/send-tokens-across-zones.test.ts b/e2e/send-tokens-across-zones.test.ts
index 5a88b4a2..7e1ea954 100644
--- a/e2e/send-tokens-across-zones.test.ts
+++ b/e2e/send-tokens-across-zones.test.ts
@@ -25,19 +25,14 @@ test('send pathUSD from Zone A into Zone B', async ({ page }) => {
timeout: 30000,
})
- const authorizeSourceButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
- .first()
+ const authorizeSourceButton = page.getByRole('button', { name: 'Authorize Zone A reads' }).first()
await expect(authorizeSourceButton).toBeVisible({ timeout: 30000 })
- await expect(authorizeSourceButton).toBeEnabled({ timeout: 90000 })
await authorizeSourceButton.click()
const getFundsButton = page.getByRole('button', { name: /^Get testnet pathUSD$/i }).first()
const topUpButton = page.getByRole('button', { name: /^Approve \+ top up Zone A$/i }).first()
const sendButton = page.getByRole('button', { name: /^Send 25 pathUSD into Zone B$/i }).first()
- const authorizeTargetButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone B reads$/i })
- .first()
+ const authorizeTargetButton = page.getByRole('button', { name: 'Authorize Zone B reads' }).first()
await expect
.poll(
@@ -66,7 +61,6 @@ test('send pathUSD from Zone A into Zone B', async ({ page }) => {
await sendButton.click()
await expect(authorizeTargetButton).toBeVisible({ timeout: 120000 })
- await expect(authorizeTargetButton).toBeEnabled({ timeout: 90000 })
await authorizeTargetButton.click()
await expect(
diff --git a/e2e/send-tokens-within-a-zone.test.ts b/e2e/send-tokens-within-a-zone.test.ts
index a8b9a743..f656dabe 100644
--- a/e2e/send-tokens-within-a-zone.test.ts
+++ b/e2e/send-tokens-within-a-zone.test.ts
@@ -25,11 +25,8 @@ test('prepare zone balance and send tokens within Zone A', async ({ page }) => {
timeout: 30000,
})
- const authorizeButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
- .first()
+ const authorizeButton = page.getByRole('button', { name: 'Authorize Zone A reads' }).first()
await expect(authorizeButton).toBeVisible({ timeout: 30000 })
- await expect(authorizeButton).toBeEnabled({ timeout: 90000 })
await authorizeButton.click()
const getFundsButton = page.getByRole('button', { name: /^Get testnet pathUSD$/i }).first()
diff --git a/e2e/swap-across-zones.test.ts b/e2e/swap-across-zones.test.ts
index 2cf3edcf..c6db47bb 100644
--- a/e2e/swap-across-zones.test.ts
+++ b/e2e/swap-across-zones.test.ts
@@ -25,11 +25,8 @@ test('swap pathUSD from Zone A into betaUSD on Zone B', async ({ page }) => {
timeout: 30000,
})
- const authorizeSourceButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
- .first()
+ const authorizeSourceButton = page.getByRole('button', { name: 'Authorize Zone A reads' }).first()
await expect(authorizeSourceButton).toBeVisible({ timeout: 30000 })
- await expect(authorizeSourceButton).toBeEnabled({ timeout: 90000 })
await authorizeSourceButton.click()
const getFundsButton = page.getByRole('button', { name: /^Get testnet pathUSD$/i }).first()
@@ -37,9 +34,7 @@ test('swap pathUSD from Zone A into betaUSD on Zone B', async ({ page }) => {
const swapButton = page
.getByRole('button', { name: /^Swap 25 pathUSD into Zone B betaUSD$/i })
.first()
- const authorizeTargetButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone B reads$/i })
- .first()
+ const authorizeTargetButton = page.getByRole('button', { name: 'Authorize Zone B reads' }).first()
await expect
.poll(
@@ -68,7 +63,6 @@ test('swap pathUSD from Zone A into betaUSD on Zone B', async ({ page }) => {
await swapButton.click()
await expect(authorizeTargetButton).toBeVisible({ timeout: 120000 })
- await expect(authorizeTargetButton).toBeEnabled({ timeout: 90000 })
await authorizeTargetButton.click()
await expect(
diff --git a/e2e/withdraw-from-a-zone.test.ts b/e2e/withdraw-from-a-zone.test.ts
index 3f07c303..38741e9e 100644
--- a/e2e/withdraw-from-a-zone.test.ts
+++ b/e2e/withdraw-from-a-zone.test.ts
@@ -27,11 +27,8 @@ test('prepare zone balance and withdraw from Zone A', async ({ page }) => {
timeout: 20000,
})
- const authorizeButton = page
- .getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
- .first()
+ const authorizeButton = page.getByRole('button', { name: 'Authorize Zone A reads' }).first()
await expect(authorizeButton).toBeVisible({ timeout: 30000 })
- await expect(authorizeButton).toBeEnabled({ timeout: 90000 })
await authorizeButton.click()
const getFundsButton = page.getByRole('button', { name: /^Get testnet pathUSD$/i }).first()
diff --git a/src/components/guides/Demo.tsx b/src/components/guides/Demo.tsx
index 6c21f5ce..ceb60a3c 100644
--- a/src/components/guides/Demo.tsx
+++ b/src/components/guides/Demo.tsx
@@ -598,8 +598,6 @@ export function Button(
) {
const { className, disabled, render, size, static: static_, variant, ...rest } = props
const Element = render ? (p: typeof props) => React.cloneElement(render, p) : 'button'
- const accessibilityProps = render ? { 'aria-disabled': disabled || undefined } : { disabled }
-
return (
)
diff --git a/src/components/guides/zones/SendTokensAcrossZones.tsx b/src/components/guides/zones/SendTokensAcrossZones.tsx
index 7841ed48..89f13bf7 100644
--- a/src/components/guides/zones/SendTokensAcrossZones.tsx
+++ b/src/components/guides/zones/SendTokensAcrossZones.tsx
@@ -19,8 +19,7 @@ import {
} from '../../../lib/private-zones.ts'
import { useRootWebAuthnAccount } from '../../../lib/useRootWebAuthnAccount.ts'
import { useZoneAuthorization, type ZoneAuthClientLike } from '../../../lib/useZoneAuthorization.ts'
-import { Button, ExplorerLink, Logout, ReceiptHash, Step } from '../Demo'
-import { SignInButtons } from '../EmbedPasskeys'
+import { Button, ExplorerLink, Login, Logout, ReceiptHash, Step } from '../Demo'
import { pathUsd } from '../tokens'
import { useStickyStepCompletion } from './useStickyStepCompletion.ts'
@@ -78,7 +77,7 @@ export function SendTokensAcrossZones() {
: }
+ actions={connected ? : }
error={undefined}
number={1}
title="Create or use a passkey account on the public chain."
diff --git a/src/lib/useRootWebAuthnAccount.ts b/src/lib/useRootWebAuthnAccount.ts
index bdd661db..2ca157d4 100644
--- a/src/lib/useRootWebAuthnAccount.ts
+++ b/src/lib/useRootWebAuthnAccount.ts
@@ -3,31 +3,24 @@
import { useQuery } from '@tanstack/react-query'
import { Account } from 'viem/tempo'
import { useConnection } from 'wagmi'
+import { config, webAuthnRpId } from '../wagmi.config.ts'
-type RootWebAuthnAccount = ReturnType
-type RootWebAuthnAccountProvider = {
- getAccount: (options: {
- accessKey?: boolean | undefined
- address?: `0x${string}` | undefined
- signable?: boolean | undefined
- }) => RootWebAuthnAccount
-}
+type RootWebAuthnCredential = Parameters[0]
export function useRootWebAuthnAccount() {
const { address, connector } = useConnection()
return useQuery({
- enabled: Boolean(address && connector?.id === 'webAuthn'),
- queryKey: ['root-webauthn-account', address],
+ enabled: Boolean(address && connector?.id === 'webAuthn' && webAuthnRpId),
+ queryKey: ['root-webauthn-account', address, webAuthnRpId],
queryFn: async () => {
- if (!address) throw new Error('account address not ready')
- if (!connector) throw new Error('connector not ready')
+ if (!webAuthnRpId) throw new Error('webauthn RP ID is not configured')
+
+ const credential = await config.storage?.getItem('webAuthn.activeCredential')
+ if (!credential) throw new Error('webauthn credential not available')
- const provider = (await connector.getProvider()) as RootWebAuthnAccountProvider
- return provider.getAccount({
- accessKey: false,
- address: address as `0x${string}`,
- signable: true,
+ return Account.fromWebAuthnP256(credential as RootWebAuthnCredential, {
+ rpId: webAuthnRpId,
})
},
refetchOnReconnect: false,
diff --git a/src/lib/useZoneAuthorization.ts b/src/lib/useZoneAuthorization.ts
index e236c7d6..b41d1e7f 100644
--- a/src/lib/useZoneAuthorization.ts
+++ b/src/lib/useZoneAuthorization.ts
@@ -4,8 +4,6 @@ import { useMutation, useQuery } from '@tanstack/react-query'
import type { Hex } from 'viem'
import { Storage as ZoneStorage } from 'viem/tempo'
-const zoneAuthorizationInfoTimeoutMs = 5_000
-
export type ZoneAuthClientLike = {
zone: {
getAuthorizationTokenInfo: () => Promise<{
@@ -46,10 +44,7 @@ export function useZoneAuthorization(parameters: {
if (accountToken) await storage.setItem(chainStorageKey, accountToken)
try {
- const info = await withTimeout(
- zoneClient.zone.getAuthorizationTokenInfo(),
- zoneAuthorizationInfoTimeoutMs,
- )
+ const info = await zoneClient.zone.getAuthorizationTokenInfo()
const expired = info.expiresAt <= BigInt(Math.floor(Date.now() / 1000))
const matchesAccount = info.account.toLowerCase() === lowerAddress
@@ -99,27 +94,12 @@ export function useZoneAuthorization(parameters: {
}
}
-function withTimeout(promise: Promise, timeoutMs: number) {
- return Promise.race([
- promise,
- new Promise((_, reject) => {
- const timeout = setTimeout(() => {
- const error = new Error('zone authorization info request timed out')
- error.name = 'TimeoutError'
- reject(error)
- }, timeoutMs)
-
- promise.finally(() => clearTimeout(timeout))
- }),
- ])
-}
-
function isZoneAuthorizationError(error: unknown) {
const status = getErrorStatus(error)
if (status === 401 || status === 403) return true
const name = getErrorName(error)
- if (name === 'HttpRequestError' || name === 'TimeoutError') return true
+ if (name === 'HttpRequestError') return true
const message = getErrorMessage(error)
return /authorization token/i.test(message)
diff --git a/src/pages/protocol/zones/proving.mdx b/src/pages/protocol/zones/proving.mdx
index d20ac4e6..a63e39b4 100644
--- a/src/pages/protocol/zones/proving.mdx
+++ b/src/pages/protocol/zones/proving.mdx
@@ -3,8 +3,6 @@ title: Zone Proving
description: Batch submission and proof verification for Tempo zones, including the state transition function, ZK and TEE deployment modes, and ancestry proofs.
---
-import { StaticMermaidDiagram } from '../../../components/StaticMermaidDiagram'
-
# Zone Proving
:::info
@@ -73,22 +71,23 @@ pub fn prove_zone_batch(witness: BatchWitness) -> Result
### Execution Flow
- B["Verify Tempo state proofs"]
- B --> C["Initialize zone state from previous block hash"]
- C --> D{"Next zone block"}
- D --> E["Check parent hash and block number"]
- E --> F["Verify beneficiary is the sequencer"]
- F --> G["Execute advanceTempo system transaction if present"]
- G --> H["Execute user transactions via revm"]
- H --> I{"Final block in batch?"}
- I -- No --> J["Compute simplified zone block hash"]
+```mermaid
+flowchart TD
+ A[Batch witness] --> B[Verify Tempo state proofs]
+ B --> C[Initialize zone state from previous block hash]
+ C --> D{Next zone block}
+ D --> E[Check parent hash and block number]
+ E --> F[Verify beneficiary is the sequencer]
+ F --> G[Execute advanceTempo system transaction if present]
+ G --> H[Execute user transactions via revm]
+ H --> I{Final block in batch?}
+ I -- No --> J[Compute simplified zone block hash]
J --> D
- I -- Yes --> K["Execute finalizeWithdrawalBatch"]
- K --> L["Compute simplified zone block hash"]
- L --> M["Extract output commitments"]
- M --> N["Return batch output for verification"]
-`} />
+ I -- Yes --> K[Execute finalizeWithdrawalBatch]
+ K --> L[Compute simplified zone block hash]
+ L --> M[Extract output commitments]
+ M --> N[Return batch output for verification]
+```
1. **Verify Tempo state proofs.** Validate MPT proofs for all Tempo storage reads against Tempo state roots.
2. **Initialize zone state.** Load the zone state from the witness, binding the initial state root to the previous block hash.