Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@vercel/analytics": "^1.6.1",
"@vercel/speed-insights": "^1.3.1",
"abitype": "^1.2.3",
"accounts": "^0.4.23",
"cva": "1.0.0-beta.4",
"mermaid": "^11.12.2",
"monaco-editor": "^0.55.1",
Expand All @@ -33,10 +34,9 @@
"sql-formatter": "^15.7.0",
"tailwind-merge": "^3.4.0",
"tailwindcss": "^4.1.18",
"tempo.ts": "^0.14.0",
"unplugin-auto-import": "^21.0.0",
"unplugin-icons": "^23.0.1",
"viem": "^2.47.5",
"viem": "^2.47.10",
"vocs": "https://pkg.pr.new/vocs@70a7c8c",
"wagmi": "^3.5.0",
"waku": "1.0.0-alpha.4",
Expand All @@ -54,7 +54,8 @@
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"use-sync-external-store": "^1.6.0",
"vite": "^7.3.1"
"vite": "^7.3.1",
"vite-plugin-mkcert": "^1.17.10"
},
"devEngines": {
"runtime": {
Expand Down
821 changes: 613 additions & 208 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions pnpm-workspace.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ patchedDependencies:
dayjs@1.11.19: patches/dayjs@1.11.19.patch

minimumReleaseAge: 1440
minimumReleaseAgeExclude:
- accounts
41 changes: 41 additions & 0 deletions src/components/guides/AccountsSignIn.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
'use client'
import { useConnect, useConnection, useConnectors, useDisconnect } from 'wagmi'
import { Button } from './Demo'

export function AccountsSignIn() {
const account = useConnection()
const connect = useConnect()
const disconnect = useDisconnect()
const connector = useTempoWalletConnector()

if (!connector) return null

if (account.address)
return (
<div className="flex items-center gap-2">
<Button onClick={() => disconnect.disconnect()} variant="destructive">
Sign out
</Button>
</div>
)

if (connect.isPending)
return (
<div>
<Button disabled>Check prompt</Button>
</div>
)

return (
<div className="flex gap-1">
<Button variant="accent" onClick={() => connect.connect({ connector })} type="button">
Sign in
</Button>
</div>
)
}

function useTempoWalletConnector() {
const connectors = useConnectors()
return connectors.find((c) => c.id === 'xyz.tempo')
}
90 changes: 0 additions & 90 deletions src/components/guides/CreatePasskeyAccount.tsx

This file was deleted.

56 changes: 17 additions & 39 deletions src/components/guides/Demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as React from 'react'
import type { Address, BaseError } from 'viem'
import { formatUnits } from 'viem'
import { tempoModerato } from 'viem/chains'
import { useAccount, useConnect, useConnections, useConnectors, useDisconnect } from 'wagmi'
import { useAccount, useConnect, useConnections, useDisconnect } from 'wagmi'
import { Hooks } from 'wagmi/tempo'
import LucideCheck from '~icons/lucide/check'
import LucideCopy from '~icons/lucide/copy'
Expand All @@ -15,6 +15,7 @@ import LucideRotateCcw from '~icons/lucide/rotate-ccw'
import LucideWalletCards from '~icons/lucide/wallet-cards'
import { cva, cx } from '../../../cva.config'
import { usePostHogTracking } from '../../lib/posthog'
import { useTempoWalletConnector } from '../../wagmi.config'
import { Container as ParentContainer } from '../Container'
import { alphaUsd } from './tokens'

Expand All @@ -23,15 +24,6 @@ export { alphaUsd, betaUsd, pathUsd, thetaUsd } from './tokens'
export const FAKE_RECIPIENT = '0xbeefcafe54750903ac1c8909323af7beb21ea2cb'
export const FAKE_RECIPIENT_2 = '0xdeadbeef54750903ac1c8909323af7beb21ea2cb'

export function useWebAuthnConnector() {
const connectors = useConnectors()
return React.useMemo(
// biome-ignore lint/style/noNonNullAssertion: webAuthn connector always defined in wagmi.config.ts
() => connectors.find((connector) => connector.id === 'webAuthn')!,
[connectors],
)
}

function getExplorerHost() {
const { VITE_TEMPO_ENV, VITE_EXPLORER_OVERRIDE } = import.meta.env

Expand Down Expand Up @@ -117,12 +109,16 @@ export function Container(
if (!source) return address

if (source === 'webAuthn') {
const webAuthnConnection = connections.find((c) => c.connector.id === 'webAuthn')
const webAuthnConnection = connections.find(
(c) => c.connector.id === 'webAuthn' || c.connector.id === 'xyz.tempo',
)
return webAuthnConnection?.accounts[0]
}

if (source === 'wallet') {
const walletConnection = connections.find((c) => c.connector.id !== 'webAuthn')
const walletConnection = connections.find(
(c) => c.connector.id !== 'webAuthn' && c.connector.id !== 'xyz.tempo',
)
return walletConnection?.accounts[0]
}

Expand Down Expand Up @@ -363,7 +359,7 @@ export namespace StringFormatter {

export function Login() {
const connect = useConnect()
const connector = useWebAuthnConnector()
const connector = useTempoWalletConnector()

return (
<div>
Expand All @@ -373,32 +369,14 @@ export function Login() {
Check prompt
</Button>
) : (
<div className="flex gap-1">
<Button
variant="accent"
className="font-normal text-[14px] -tracking-[2%]"
onClick={() => connect.connect({ connector })}
type="button"
>
Sign in
</Button>
<Button
variant="default"
className="font-normal text-[14px] -tracking-[2%]"
onClick={() =>
connect.connect({
connector,
capabilities: {
label: 'Tempo Docs',
type: 'sign-up',
},
})
}
type="button"
>
Sign up
</Button>
</div>
<Button
variant="accent"
className="font-normal text-[14px] -tracking-[2%]"
onClick={() => connect.connect({ connector })}
type="button"
>
Sign in
</Button>
)}
</div>
)
Expand Down
3 changes: 2 additions & 1 deletion src/components/guides/EmbedPasskeys.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use client'
import { useAccount, useConnect, useDisconnect } from 'wagmi'
import { Button, useWebAuthnConnector } from './Demo'
import { useWebAuthnConnector } from '../../wagmi.config'
import { Button } from './Demo'

export function EmbedPasskeys() {
const account = useAccount()
Expand Down
4 changes: 3 additions & 1 deletion src/components/guides/steps/wallet/AddFundsToWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import type { DemoStepProps } from '../types'
export function AddFundsToWallet(props: DemoStepProps) {
const { stepNumber = 2, last = false } = props
const { address, connector } = useConnection()
const hasNonWebAuthnWallet = Boolean(address && connector?.id !== 'webAuthn')
const hasNonWebAuthnWallet = Boolean(
address && connector?.id !== 'webAuthn' && connector?.id !== 'xyz.tempo',
)
const queryClient = useQueryClient()

const { data: balance, refetch: balanceRefetch } = Hooks.token.useGetBalance({
Expand Down
4 changes: 3 additions & 1 deletion src/components/guides/steps/wallet/AddTokensToWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ function AddTokenButton(props: {
export function AddTokensToWallet(props: DemoStepProps) {
const { stepNumber = 3, last = false } = props
const { address, connector } = useConnection()
const hasNonWebAuthnWallet = Boolean(address && connector?.id !== 'webAuthn')
const hasNonWebAuthnWallet = Boolean(
address && connector?.id !== 'webAuthn' && connector?.id !== 'xyz.tempo',
)

const [addedTokens, setAddedTokens] = React.useState<Set<string>>(new Set())
const [expanded, setExpanded] = React.useState(false)
Expand Down
4 changes: 3 additions & 1 deletion src/components/guides/steps/wallet/SetFeeToken.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ const DEFAULT_FEE_TOKEN_OPTION = FEE_TOKEN_OPTIONS[0]
export function SetFeeToken(props: DemoStepProps) {
const { stepNumber = 1 } = props
const { address, connector } = useConnection()
const hasNonWebAuthnWallet = Boolean(address && connector?.id !== 'webAuthn')
const hasNonWebAuthnWallet = Boolean(
address && connector?.id !== 'webAuthn' && connector?.id !== 'xyz.tempo',
)
const chainId = useChainId()
const config = useConfig()

Expand Down
15 changes: 9 additions & 6 deletions src/components/lib/wallets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@ const UNSUPPORTED_WALLET_IDS = new Set(['app.phantom'])
const UNSUPPORTED_WALLET_NAMES = new Set(['Phantom'])

export function filterSupportedInjectedConnectors(connectors: readonly Connector[]) {
return connectors.filter(
(connector) =>
connector.id !== 'webAuthn' &&
!UNSUPPORTED_WALLET_IDS.has(connector.id) &&
!UNSUPPORTED_WALLET_NAMES.has(connector.name),
)
const seen = new Set<string>()
return connectors.filter((connector) => {
if (connector.id === 'webAuthn') return false
if (UNSUPPORTED_WALLET_IDS.has(connector.id)) return false
if (UNSUPPORTED_WALLET_NAMES.has(connector.name)) return false
if (seen.has(connector.id)) return false
seen.add(connector.id)
return true
})
}
39 changes: 39 additions & 0 deletions src/pages/accounts/api/adapters.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
title: Adapters
description: Pluggable adapters for the Tempo Accounts SDK Provider.
---

import { Cards, Card } from 'vocs'

# Adapters

Adapters control how accounts are created and managed. Pass an adapter to `Provider.create()` to configure the account management strategy.

| Adapter | Uses | Best for |
| --- | --- | --- |
| [`dialog`](/accounts/api/dialog) (default) | Hosted dialog | Apps wanting a universal account experience |
| [`webAuthn`](/accounts/api/webAuthn) | Domain-bound passkeys | Wallets integrating Passkey accounts, or Apps wanting to host and manage their own Passkey accounts |
| [`local`](/accounts/api/local) | Arbitrary keys | Custom signing and key management |

---

<Cards>
<Card
description="Embeds a universal Tempo Wallet dialog into your app"
icon="lucide:wallet"
to="/accounts/api/dialog"
title="dialog"
/>
<Card
description="Embeds domain-bound passkey accounts into your app"
icon="lucide:fingerprint"
to="/accounts/api/webAuthn"
title="webAuthn"
/>
<Card
description="Uses arbitrary keys for account management"
icon="lucide:key"
to="/accounts/api/local"
title="local"
/>
</Cards>
20 changes: 20 additions & 0 deletions src/pages/accounts/api/dialog.iframe.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
title: Dialog.iframe
description: Embed the Tempo Wallet auth UI in an iframe dialog element.
---

# `Dialog.iframe`

Creates an iframe dialog that embeds the auth app in a `<dialog>` element. This is the default on most browsers in secure (HTTPS) contexts.

Falls back to a popup on Safari (which does not support WebAuthn in cross-origin iframes) and insecure (HTTP) origins.

## Usage

```ts
import { dialog, Dialog, Provider } from 'accounts'

const provider = Provider.create({
adapter: dialog({ dialog: Dialog.iframe() }),
})
```
Loading
Loading