Skip to content
Merged

zones #305

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
3ce5a91
docs: add Zones protocol documentation (#49)
decofe Apr 7, 2026
894e816
feat: add zone demos (#59)
Zygimantass Apr 7, 2026
cbc7b52
fix: types
Zygimantass Apr 7, 2026
bef22c4
chore: add banner
Zygimantass Apr 7, 2026
5042a81
fix: refactor with latest viem
Zygimantass Apr 7, 2026
b76061a
feat: add send across zones
Zygimantass Apr 7, 2026
78615b7
feat: reuse auth token
Zygimantass Apr 7, 2026
b8e3b0b
fix: suppress spurious zone auth error
snario Apr 9, 2026
8ad3f43
fix: widen zone settlement detection
snario Apr 9, 2026
12f5c64
fix: stop linking zone receipts to explorer
snario Apr 9, 2026
caca40c
docs: reorder zones security sections
dankrad Apr 9, 2026
a23fe3a
docs: merge zone RPC method tables
dankrad Apr 9, 2026
c62f3be
docs: add zone execution flow diagram
dankrad Apr 9, 2026
037a25b
feat: add StaticMermaidDiagram component for consistent diagram styli…
brendanjryan Apr 9, 2026
a6dab22
docs: move execution flow diagram to proving
dankrad Apr 10, 2026
70e9691
feat: add connect-to-a-zone page
Zygimantass Apr 10, 2026
b4f2d6b
fix: bump viem
Zygimantass Apr 13, 2026
23e55a9
fix: withdraws
Zygimantass Apr 13, 2026
fe846dc
docs: add zone architecture diagrams with descriptive names (#61)
achalvs Apr 13, 2026
47a57e1
fix: zone renamings
Zygimantass Apr 14, 2026
d062060
feat: cleanup
Zygimantass Apr 15, 2026
cfdfc8f
fix: rebase
Zygimantass Apr 15, 2026
7f88a87
fix: unblock CI for custom viem build
Zygimantass Apr 15, 2026
a98ca3e
fix: deps
Zygimantass Apr 16, 2026
bba04e1
fix: correctness
Zygimantass Apr 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions e2e/deposit-to-a-zone.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { expect, test } from '@playwright/test'

test('prepare zone access and deposit to Zone A', async ({ page }) => {
test.setTimeout(180000)

const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/private-zones/deposit-to-a-zone')

const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

const authorizeButton = page
.getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
.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()
const depositButton = page.getByRole('button', { name: /^Deposit 100 pathUSD$/i }).first()

if (await getFundsButton.isVisible()) {
await getFundsButton.click()
await expect(depositButton).toBeVisible({ timeout: 90000 })
}

await depositButton.click()

await expect(
page
.locator('div[data-completed="true"]', {
has: page.getByText('Wait for Zone A to credit the deposit.'),
})
.first(),
).toBeVisible({ timeout: 120000 })

await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
81 changes: 81 additions & 0 deletions e2e/send-tokens-across-zones.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { expect, test } from '@playwright/test'

test('send pathUSD from Zone A into Zone B', async ({ page }) => {
test.setTimeout(240000)

const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/private-zones/send-tokens-across-zones')

const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

const authorizeSourceButton = page
.getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
.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()

await expect
.poll(
async () =>
(await getFundsButton.isVisible()) ||
(await topUpButton.isVisible()) ||
(await sendButton.isVisible()),
{ timeout: 90000 },
)
.toBe(true)

if (await getFundsButton.isVisible()) {
await getFundsButton.click()
await expect
.poll(async () => (await topUpButton.isVisible()) || (await sendButton.isVisible()), {
timeout: 90000,
})
.toBe(true)
}

if (await topUpButton.isVisible()) {
await topUpButton.click()
}

await expect(sendButton).toBeVisible({ timeout: 120000 })
await sendButton.click()

await expect(authorizeTargetButton).toBeVisible({ timeout: 120000 })
await expect(authorizeTargetButton).toBeEnabled({ timeout: 90000 })
await authorizeTargetButton.click()

await expect(
page
.locator('div[data-completed="true"]', {
has: page.getByText('Authorize private reads in Zone B and confirm the pathUSD balance.'),
})
.first(),
).toBeVisible({ timeout: 120000 })

await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
68 changes: 68 additions & 0 deletions e2e/send-tokens-within-a-zone.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { expect, test } from '@playwright/test'

test('prepare zone balance and send tokens within Zone A', async ({ page }) => {
test.setTimeout(180000)

const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/private-zones/send-tokens-within-a-zone')

const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

const authorizeButton = page
.getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
.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()
const topUpButton = page.getByRole('button', { name: /^Approve \+ top up Zone A$/i }).first()
const sendButton = page.getByRole('button', { name: /^Send 25 pathUSD$/i }).first()

await expect
.poll(
async () =>
(await getFundsButton.isVisible()) ||
(await topUpButton.isVisible()) ||
(await sendButton.isVisible()),
{ timeout: 90000 },
)
.toBe(true)

if (await getFundsButton.isVisible()) {
await getFundsButton.click()
await expect(topUpButton).toBeVisible({ timeout: 90000 })
}

if (await topUpButton.isVisible()) await topUpButton.click()
await expect(sendButton).toBeVisible({ timeout: 120000 })

await sendButton.click()

await expect(
page
.locator('div[data-completed="true"]', {
has: page.getByText('Wait for Zone A to show the updated private balance.'),
})
.first(),
).toBeVisible({ timeout: 120000 })

await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
83 changes: 83 additions & 0 deletions e2e/swap-across-zones.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { expect, test } from '@playwright/test'

test('swap pathUSD from Zone A into betaUSD on Zone B', async ({ page }) => {
test.setTimeout(240000)

const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/private-zones/swap-across-zones')

const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 90000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 30000,
})

const authorizeSourceButton = page
.getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
.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 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()

await expect
.poll(
async () =>
(await getFundsButton.isVisible()) ||
(await topUpButton.isVisible()) ||
(await swapButton.isVisible()),
{ timeout: 90000 },
)
.toBe(true)

if (await getFundsButton.isVisible()) {
await getFundsButton.click()
await expect
.poll(async () => (await topUpButton.isVisible()) || (await swapButton.isVisible()), {
timeout: 90000,
})
.toBe(true)
}

if (await topUpButton.isVisible()) {
await topUpButton.click()
}

await expect(swapButton).toBeVisible({ timeout: 120000 })
await swapButton.click()

await expect(authorizeTargetButton).toBeVisible({ timeout: 120000 })
await expect(authorizeTargetButton).toBeEnabled({ timeout: 90000 })
await authorizeTargetButton.click()

await expect(
page
.locator('div[data-completed="true"]', {
has: page.getByText('Authorize private reads in Zone B and confirm the betaUSD balance.'),
})
.first(),
).toBeVisible({ timeout: 120000 })

await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
79 changes: 79 additions & 0 deletions e2e/withdraw-from-a-zone.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { expect, test } from '@playwright/test'

test.describe.configure({ retries: 0, timeout: 120000 })

test('prepare zone balance and withdraw from Zone A', async ({ page }) => {
test.setTimeout(180000)

const client = await page.context().newCDPSession(page)
await client.send('WebAuthn.enable')
const { authenticatorId } = await client.send('WebAuthn.addVirtualAuthenticator', {
options: {
protocol: 'ctap2',
transport: 'internal',
hasResidentKey: true,
hasUserVerification: true,
isUserVerified: true,
},
})

await page.goto('/guide/private-zones/withdraw-from-a-zone')

const signUpButton = page.getByRole('button', { name: 'Sign up' }).first()
await expect(signUpButton).toBeVisible({ timeout: 45000 })
await signUpButton.click()

await expect(page.getByRole('button', { name: 'Sign out' }).first()).toBeVisible({
timeout: 20000,
})

const authorizeButton = page
.getByRole('button', { name: /^Authoriz(?:e|ing) Zone A reads$/i })
.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()
const topUpButton = page.getByRole('button', { name: /^Approve \+ top up Zone A$/i }).first()
const withdrawButton = page.getByRole('button', { name: /^Withdraw 100 pathUSD$/i }).first()

await expect
.poll(
async () =>
(await getFundsButton.isVisible()) ||
(await topUpButton.isVisible()) ||
(await withdrawButton.isVisible()),
{ timeout: 90000 },
)
.toBe(true)

if (await getFundsButton.isVisible()) {
await getFundsButton.click()
await expect
.poll(async () => (await topUpButton.isVisible()) || (await withdrawButton.isVisible()), {
timeout: 90000,
})
.toBe(true)
}

if (await topUpButton.isVisible()) {
await topUpButton.click()
}

await expect(withdrawButton).toBeVisible({ timeout: 90000 })

await withdrawButton.click()

await expect(
page
.locator('div[data-completed="true"]', {
has: page.getByText('Wait for pathUSD to settle back to your public balance.'),
})
.first(),
).toBeVisible({
timeout: 120000,
})

await client.send('WebAuthn.removeVirtualAuthenticator', { authenticatorId })
})
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"tailwindcss": "^4.2.2",
"unplugin-auto-import": "^21.0.0",
"unplugin-icons": "^23.0.1",
"viem": "^2.47.18",
"viem": "2.48.0",
"vocs": "https://pkg.pr.new/wevm/vocs@2fb25c2",
"wagmi": "^3.6.1",
"waku": "1.0.0-alpha.4",
Expand Down
Loading
Loading