Skip to content

Commit 8230647

Browse files
committed
feat: passkey support in explorer
1 parent c0710b2 commit 8230647

File tree

8 files changed

+67
-70
lines changed

8 files changed

+67
-70
lines changed

apps/explorer/src/lib/queries/blocks.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { Block } from 'viem'
44
import { getBlock, getTransactionReceipt } from 'wagmi/actions'
55
import { type KnownEvent, parseKnownEvents } from '#lib/domain/known-events'
66
import * as Tip20 from '#lib/domain/tip20.ts'
7-
import { getConfig } from '#wagmi.config.ts'
7+
import { config as wagmiConfig } from '#wagmi.config.ts'
88

99
export const BLOCKS_PER_PAGE = 12
1010

@@ -19,8 +19,6 @@ export function blocksQueryOptions(page: number) {
1919
return queryOptions({
2020
queryKey: ['blocks-loader', page],
2121
queryFn: async () => {
22-
const wagmiConfig = getConfig()
23-
2422
const latestBlock = await getBlock(wagmiConfig)
2523
const latestBlockNumber = latestBlock.number
2624

@@ -57,7 +55,6 @@ export function blockDetailQueryOptions(
5755
return queryOptions({
5856
queryKey: ['block-detail', blockRef, page],
5957
queryFn: async () => {
60-
const wagmiConfig = getConfig()
6158
const block = await getBlock(wagmiConfig, {
6259
includeTransactions: true,
6360
...(blockRef.kind === 'hash'
@@ -72,10 +69,8 @@ export function blockDetailQueryOptions(
7269
startIndex + TRANSACTIONS_PER_PAGE,
7370
)
7471

75-
const knownEventsByHash = await fetchKnownEventsForTransactions(
76-
pageTransactions,
77-
wagmiConfig,
78-
)
72+
const knownEventsByHash =
73+
await fetchKnownEventsForTransactions(pageTransactions)
7974

8075
return {
8176
blockRef,
@@ -90,7 +85,6 @@ export function blockDetailQueryOptions(
9085

9186
async function fetchKnownEventsForTransactions(
9287
transactions: BlockTransaction[],
93-
wagmiConfig: ReturnType<typeof getConfig>,
9488
): Promise<Record<Hex.Hex, KnownEvent[]>> {
9589
const entries = await Promise.all(
9690
transactions.map(async (transaction) => {

apps/explorer/src/lib/queries/tx.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { getBlock, getTransaction, getTransactionReceipt } from 'wagmi/actions'
44
import { parseKnownEvent, parseKnownEvents } from '#lib/domain/known-events'
55
import { getFeeBreakdown } from '#lib/domain/receipt'
66
import * as Tip20 from '#lib/domain/tip20'
7-
import { getConfig } from '#wagmi.config'
7+
import { config } from '#wagmi.config'
88

99
export function txQueryOptions(params: { hash: Hex.Hex }) {
1010
return queryOptions({
@@ -14,7 +14,6 @@ export function txQueryOptions(params: { hash: Hex.Hex }) {
1414
}
1515

1616
async function fetchTxData(params: { hash: Hex.Hex }) {
17-
const config = getConfig()
1817
const receipt = await getTransactionReceipt(config, { hash: params.hash })
1918

2019
const [block, transaction, getTokenMetadata] = await Promise.all([

apps/explorer/src/routes/_layout/address/$address.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ import {
6666
type TransactionsData,
6767
transactionsQueryOptions,
6868
} from '#lib/queries/account.ts'
69-
import { config, getConfig } from '#wagmi.config.ts'
69+
import { config } from '#wagmi.config.ts'
7070

7171
async function fetchAddressTotalValue(address: Address.Address) {
7272
const response = await fetch(
@@ -107,10 +107,9 @@ function useBatchTransactionData(
107107
queries: hashes.map((hash) => ({
108108
queryKey: ['tx-data-batch', viewer, hash],
109109
queryFn: async (): Promise<TransactionData | null> => {
110-
const cfg = getConfig()
111-
const receipt = await getTransactionReceipt(cfg, { hash })
110+
const receipt = await getTransactionReceipt(config, { hash })
112111
const [block, transaction, getTokenMetadata] = await Promise.all([
113-
getBlock(cfg, { blockHash: receipt.blockHash }),
112+
getBlock(config, { blockHash: receipt.blockHash }),
114113
getTransaction(config, { hash: receipt.transactionHash }),
115114
Tip20.metadataFromLogs(receipt.logs),
116115
])

apps/explorer/src/routes/_layout/receipt/$hash.tsx

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,16 @@ import {
1717
formatEventForOgServer,
1818
OG_BASE_URL,
1919
} from '#lib/og'
20-
import { getConfig } from '#wagmi.config'
20+
import { config } from '#wagmi.config'
2121

22-
function receiptDetailQueryOptions(params: { hash: Hex.Hex; rpcUrl?: string }) {
22+
function receiptDetailQueryOptions(params: { hash: Hex.Hex }) {
2323
return queryOptions({
24-
queryKey: ['receipt-detail', params.hash, params.rpcUrl],
24+
queryKey: ['receipt-detail', params.hash],
2525
queryFn: () => fetchReceiptData(params),
2626
})
2727
}
2828

29-
async function fetchReceiptData(params: { hash: Hex.Hex; rpcUrl?: string }) {
30-
const config = getConfig({ rpcUrl: params.rpcUrl })
29+
async function fetchReceiptData(params: { hash: Hex.Hex }) {
3130
const receipt = await getTransactionReceipt(config, {
3231
hash: params.hash,
3332
})
@@ -142,12 +141,11 @@ export const Route = createFileRoute('/_layout/receipt/$hash')({
142141
return 'text/plain'
143142
})()
144143

145-
const rpcUrl = url.searchParams.get('r') ?? undefined
146144
const hash = parseHashFromParams(params)
147145

148146
if (type === 'text/plain') {
149147
if (!hash) return new Response('Not found', { status: 404 })
150-
const data = await fetchReceiptData({ hash, rpcUrl })
148+
const data = await fetchReceiptData({ hash })
151149
const text = TextRenderer.render(data)
152150
return new Response(text, {
153151
headers: {
@@ -166,10 +164,7 @@ export const Route = createFileRoute('/_layout/receipt/$hash')({
166164
if (type === 'application/json') {
167165
if (!hash)
168166
return Response.json({ error: 'Not found' }, { status: 404 })
169-
const { lineItems, receipt } = await fetchReceiptData({
170-
hash,
171-
rpcUrl,
172-
})
167+
const { lineItems, receipt } = await fetchReceiptData({ hash })
173168
return Response.json(
174169
JSON.parse(Json.stringify({ lineItems, receipt })),
175170
)

apps/explorer/src/routes/api/address/total-value/$address.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Abis } from 'viem/tempo'
88
import { readContract } from 'wagmi/actions'
99

1010
import { zAddress } from '#lib/zod.ts'
11-
import { config, getConfig } from '#wagmi.config.ts'
11+
import { config } from '#wagmi.config.ts'
1212

1313
const IS = IDX.IndexSupply.create({
1414
apiKey: env.INDEXER_API_KEY,
@@ -73,7 +73,7 @@ export const Route = createFileRoute('/api/address/total-value/$address')({
7373
(await Promise.all(
7474
tokensToFetch.map(
7575
(row) =>
76-
readContract(getConfig(), {
76+
readContract(config, {
7777
address: row.token_address as Address.Address,
7878
abi: Abis.tip20,
7979
functionName: 'decimals',

apps/explorer/src/routes/api/tx/balance-changes/$hash.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Abis } from 'viem/tempo'
88
import * as z from 'zod/mini'
99

1010
import { zHash } from '#lib/zod'
11-
import { getConfig } from '#wagmi.config'
11+
import { config } from '#wagmi.config'
1212

1313
const DEFAULT_LIMIT = 20
1414
const MAX_LIMIT = 100
@@ -74,7 +74,7 @@ function computeBalanceChanges(logs: Log[]) {
7474
}
7575

7676
async function getBalanceAtBlock(
77-
client: ReturnType<ReturnType<typeof getConfig>['getClient']>,
77+
client: ReturnType<typeof config.getClient>,
7878
token: Address.Address,
7979
account: Address.Address,
8080
blockNumber: bigint,
@@ -93,7 +93,7 @@ async function getBalanceAtBlock(
9393
}
9494

9595
async function getTokenMetadata(
96-
client: ReturnType<ReturnType<typeof getConfig>['getClient']>,
96+
client: ReturnType<typeof config.getClient>,
9797
token: Address.Address,
9898
) {
9999
const [decimals, symbol] = await Promise.all([
@@ -118,7 +118,6 @@ export async function fetchBalanceChanges(params: {
118118
offset: number
119119
}): Promise<BalanceChangesData> {
120120
const { hash, limit, offset } = params
121-
const config = getConfig()
122121
const client = config.getClient()
123122

124123
const receipt = await getTransactionReceipt(client, { hash })

apps/explorer/src/routes/api/tx/trace/$hash.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { json } from '@tanstack/react-start'
33
import type { Address, Hex } from 'ox'
44
import type { Chain, Client, Transport } from 'viem'
55
import { zHash } from '#lib/zod'
6-
import { getConfig } from '#wagmi.config'
6+
import { config } from '#wagmi.config'
77

88
export interface CallTrace {
99
type: 'CALL' | 'DELEGATECALL' | 'STATICCALL' | 'CREATE' | 'CREATE2'
@@ -64,7 +64,7 @@ export const Route = createFileRoute('/api/tx/trace/$hash')({
6464
handlers: {
6565
GET: async ({ params }) => {
6666
try {
67-
const client = getConfig().getClient()
67+
const client = config.getClient()
6868
const hash = zHash().parse(params.hash)
6969
const [trace, prestate] = await Promise.all([
7070
traceTransaction(client, hash).catch(() => null),

apps/explorer/src/wagmi.config.ts

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,68 @@
11
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'
2-
import { QueryClient } from '@tanstack/react-query'
3-
import type { OneOf } from 'viem'
4-
import { tempoLocalnet, tempoTestnet } from 'viem/chains'
2+
import { MutationCache, QueryCache, QueryClient } from '@tanstack/react-query'
3+
import { Json } from 'ox'
4+
import { KeyManager, webAuthn } from 'tempo.ts/wagmi'
55
import { createConfig, deserialize, http, serialize, webSocket } from 'wagmi'
6-
import { hashFn } from 'wagmi/query'
7-
8-
// biome-ignore lint/suspicious/noExplicitAny: TODO
9-
type TODO = any
6+
import { tempoLocalnet, tempoTestnet } from 'wagmi/chains'
107

118
const browser = typeof window !== 'undefined'
129

13-
export const DEFAULT_TESTNET_RPC_URL = 'https://rpc-orchestra.testnet.tempo.xyz'
1410
export const DEFAULT_TESTNET_WS_URL = 'wss://rpc-orchestra.testnet.tempo.xyz'
11+
export const DEFAULT_TESTNET_RPC_URL = 'https://rpc-orchestra.testnet.tempo.xyz'
1512

16-
export const queryClient = new QueryClient({
13+
export const queryClient: QueryClient = new QueryClient({
1714
defaultOptions: {
1815
queries: {
19-
staleTime: 60 * 1_000, // needed for SSR
20-
queryKeyHashFn: hashFn,
21-
refetchOnWindowFocus: false,
22-
gcTime: 1_000 * 60 * 60 * 24, // 24 hours
16+
gcTime: 1000 * 60 * 60 * 24, // 24 hours
17+
queryKeyHashFn: Json.stringify,
18+
refetchOnReconnect: () => !queryClient.isMutating(),
19+
retry: 0,
2320
},
2421
},
22+
mutationCache: new MutationCache({
23+
onError: (error) => {
24+
if (import.meta.env.MODE !== 'development') return
25+
console.error(error)
26+
},
27+
}),
28+
queryCache: new QueryCache({
29+
onError: (error, query) => {
30+
if (import.meta.env.MODE !== 'development') return
31+
if (query.state.data !== undefined) console.error('[tsq]', error)
32+
},
33+
}),
2534
})
2635

2736
export const persister = createAsyncStoragePersister({
2837
// Cache key includes build version - automatically invalidates on new deploys
29-
key: `tempo-query-cache-${__BUILD_VERSION__}`,
3038
serialize,
31-
storage: browser ? window.localStorage : undefined,
3239
deserialize,
40+
key: `tempo-query-cache-${__BUILD_VERSION__}`,
41+
storage: browser ? window.localStorage : undefined,
3342
})
3443

35-
const chain =
36-
import.meta.env.VITE_LOCALNET === 'true' ? tempoLocalnet : tempoTestnet
44+
export const config = createConfig({
45+
ssr: true,
46+
chains: [
47+
import.meta.env.VITE_LOCALNET === 'true' ? tempoLocalnet : tempoTestnet,
48+
],
49+
connectors: [
50+
webAuthn({
51+
keyManager: KeyManager.http('psstkey'),
52+
}),
53+
],
54+
batch: { multicall: false },
55+
multiInjectedProviderDiscovery: false,
56+
transports: {
57+
[tempoTestnet.id]: browser
58+
? webSocket(DEFAULT_TESTNET_WS_URL)
59+
: http(DEFAULT_TESTNET_RPC_URL),
60+
[tempoLocalnet.id]: http(undefined, { batch: true }),
61+
},
62+
})
3763

38-
export function getConfig(
39-
parameters: OneOf<{ rpcUrl?: string | undefined }> = {},
40-
) {
41-
const { rpcUrl } = parameters
42-
return createConfig({
43-
chains: [chain],
44-
ssr: true,
45-
batch: { multicall: false },
46-
transports: {
47-
[tempoTestnet.id]: browser
48-
? webSocket(DEFAULT_TESTNET_WS_URL)
49-
: http(rpcUrl ?? DEFAULT_TESTNET_RPC_URL),
50-
[tempoLocalnet.id]: http(undefined, {
51-
batch: true,
52-
}),
53-
},
54-
})
64+
declare module 'wagmi' {
65+
interface Register {
66+
config: typeof config
67+
}
5568
}
56-
57-
export const config = getConfig() as TODO

0 commit comments

Comments
 (0)