Skip to content
Open
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
4 changes: 3 additions & 1 deletion 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.9",
"cva": "1.0.0-beta.4",
"mermaid": "^11.12.2",
"monaco-editor": "^0.55.1",
Expand Down Expand Up @@ -54,7 +55,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
765 changes: 664 additions & 101 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
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
})
}
49 changes: 47 additions & 2 deletions src/wagmi.config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,20 @@
import { QueryClient } from '@tanstack/react-query'
import { Expiry } from 'accounts'
import { tempoWallet } from 'accounts/wagmi'
import * as React from 'react'
import { parseUnits } from 'viem'
import { tempoDevnet, tempoLocalnet, tempoModerato } from 'viem/chains'
import { withFeePayer } from 'viem/tempo'
import { type CreateConfigParameters, createConfig, createStorage, http, webSocket } from 'wagmi'
import {
type CreateConfigParameters,
createConfig,
createStorage,
http,
useConnectors,
webSocket,
} from 'wagmi'
import { KeyManager, webAuthn } from 'wagmi/tempo'
import { alphaUsd, betaUsd, pathUsd, thetaUsd } from './components/guides/tokens'

const feeToken = '0x20c0000000000000000000000000000000000001'

Expand All @@ -28,8 +40,23 @@ export function getConfig(options: getConfig.Options = {}) {
},
chains: [chain],
connectors: [
tempoWallet({
authorizeAccessKey: () => ({
expiry: Expiry.days(1),
limits: [
{ token: pathUsd, limit: parseUnits('500', 6) },
{ token: alphaUsd, limit: parseUnits('500', 6) },
{ token: betaUsd, limit: parseUnits('500', 6) },
{ token: thetaUsd, limit: parseUnits('500', 6) },
],
}),
feePayerUrl: 'https://sponsor.moderato.tempo.xyz',
}),
webAuthn({
grantAccessKey: { chainId: BigInt(chain.id) } as any,
grantAccessKey: {
// @ts-expect-error - TODO: migrate to webAuthn on Accounts SDK
chainId: BigInt(chain.id),
},
keyManager: KeyManager.http('https://keys.tempo.xyz'),
rpId,
}),
Expand Down Expand Up @@ -67,6 +94,24 @@ export const config = getConfig()

export const queryClient = new QueryClient()

export function useTempoWalletConnector() {
const connectors = useConnectors()
return React.useMemo(
// biome-ignore lint/style/noNonNullAssertion: _
() => connectors.find((connector) => connector.id === 'xyz.tempo')!,
[connectors],
)
}

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

declare module 'wagmi' {
interface Register {
config: typeof config
Expand Down
3 changes: 2 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as path from 'node:path'
import react from '@vitejs/plugin-react'
import { Instance } from 'prool'
import { defineConfig, loadEnv, type Plugin } from 'vite'
import mkcert from 'vite-plugin-mkcert'
import { vocs } from 'vocs/vite'

// https://vite.dev/config/
Expand All @@ -12,7 +13,7 @@ export default defineConfig(({ mode }) => {
if (!(key in process.env)) process.env[key] = env[key]
}
return {
plugins: [syncTips(), vocs(), react(), tempoNode()],
plugins: [syncTips(), vocs(), react(), mkcert(), tempoNode()],
}
})

Expand Down
Loading