Skip to content

Commit 6a38dd2

Browse files
authored
fix: /tx trace tab loading (#331)
`traceQueryOptions()` now calls the RPC directly rather than via the API, which was failing during SSR because of `__BASE_URL__`.
1 parent 1dd1d32 commit 6a38dd2

File tree

2 files changed

+67
-76
lines changed

2 files changed

+67
-76
lines changed
Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,64 @@
11
import { queryOptions } from '@tanstack/react-query'
2-
import type { TraceData } from '#routes/api/tx/trace/$hash'
2+
import type { Address, Hex } from 'ox'
3+
import { getConfig } from '#wagmi.config'
34

4-
export type {
5-
AccountState,
6-
CallTrace,
7-
PrestateDiff,
8-
TraceData,
9-
} from '#routes/api/tx/trace/$hash'
5+
export interface CallTrace {
6+
type: 'CALL' | 'DELEGATECALL' | 'STATICCALL' | 'CREATE' | 'CREATE2'
7+
from: Address.Address
8+
to?: Address.Address
9+
gas: Hex.Hex
10+
gasUsed: Hex.Hex
11+
input: Hex.Hex
12+
output?: Hex.Hex
13+
value?: Hex.Hex
14+
error?: string
15+
revertReason?: string
16+
calls?: CallTrace[]
17+
}
18+
19+
export interface AccountState {
20+
balance?: Hex.Hex
21+
nonce?: number
22+
code?: Hex.Hex
23+
storage?: Record<Hex.Hex, Hex.Hex>
24+
}
25+
26+
export interface PrestateDiff {
27+
pre: Record<Address.Address, AccountState>
28+
post: Record<Address.Address, AccountState>
29+
}
30+
31+
export interface TraceData {
32+
trace: CallTrace | null
33+
prestate: PrestateDiff | null
34+
}
35+
36+
export async function fetchTraceData(hash: Hex.Hex): Promise<TraceData> {
37+
const client = getConfig().getClient()
38+
const [trace, prestate] = await Promise.all([
39+
(
40+
client.request({
41+
method: 'debug_traceTransaction',
42+
params: [hash, { tracer: 'callTracer' }],
43+
} as Parameters<typeof client.request>[0]) as Promise<CallTrace>
44+
).catch(() => null),
45+
(
46+
client.request({
47+
method: 'debug_traceTransaction',
48+
params: [
49+
hash,
50+
{ tracer: 'prestateTracer', tracerConfig: { diffMode: true } },
51+
],
52+
} as Parameters<typeof client.request>[0]) as Promise<PrestateDiff>
53+
).catch(() => null),
54+
])
55+
return { trace, prestate }
56+
}
1057

1158
export function traceQueryOptions(params: { hash: string }) {
1259
return queryOptions({
1360
queryKey: ['trace', params.hash],
14-
queryFn: async (): Promise<TraceData> => {
15-
const url = `${__BASE_URL__}/api/tx/trace/${params.hash}`
16-
const response = await fetch(url)
17-
const data: TraceData & { error?: string } = await response.json()
18-
if (data.error) throw new Error(data.error)
19-
return data
20-
},
61+
queryFn: () => fetchTraceData(params.hash as Hex.Hex),
2162
staleTime: Infinity,
2263
})
2364
}

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

Lines changed: 12 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,26 @@
11
import { createFileRoute } from '@tanstack/react-router'
22
import { json } from '@tanstack/react-start'
3-
import type { Address, Hex } from 'ox'
4-
import type { Chain, Client, Transport } from 'viem'
3+
import {
4+
fetchTraceData,
5+
type TraceData,
6+
} from '#lib/queries/trace'
57
import { zHash } from '#lib/zod'
6-
import { getConfig } from '#wagmi.config'
78

8-
export interface CallTrace {
9-
type: 'CALL' | 'DELEGATECALL' | 'STATICCALL' | 'CREATE' | 'CREATE2'
10-
from: Address.Address
11-
to?: Address.Address
12-
gas: Hex.Hex
13-
gasUsed: Hex.Hex
14-
input: Hex.Hex
15-
output?: Hex.Hex
16-
value?: Hex.Hex
17-
error?: string
18-
revertReason?: string
19-
calls?: CallTrace[]
20-
}
21-
22-
export interface AccountState {
23-
balance?: Hex.Hex
24-
nonce?: number
25-
code?: Hex.Hex
26-
storage?: Record<Hex.Hex, Hex.Hex>
27-
}
28-
29-
export interface PrestateDiff {
30-
pre: Record<Address.Address, AccountState>
31-
post: Record<Address.Address, AccountState>
32-
}
33-
34-
export interface TraceData {
35-
trace: CallTrace | null
36-
prestate: PrestateDiff | null
37-
}
38-
39-
async function traceTransaction(
40-
client: Client<Transport, Chain>,
41-
hash: Hex.Hex,
42-
): Promise<CallTrace | null> {
43-
return client.request({
44-
method: 'debug_traceTransaction',
45-
params: [hash, { tracer: 'callTracer' }],
46-
} as Parameters<typeof client.request>[0])
47-
}
48-
49-
async function tracePrestate(
50-
client: Client<Transport, Chain>,
51-
hash: Hex.Hex,
52-
): Promise<PrestateDiff | null> {
53-
return client.request({
54-
method: 'debug_traceTransaction',
55-
params: [
56-
hash,
57-
{ tracer: 'prestateTracer', tracerConfig: { diffMode: true } },
58-
],
59-
} as Parameters<typeof client.request>[0])
60-
}
9+
export type {
10+
AccountState,
11+
CallTrace,
12+
PrestateDiff,
13+
TraceData,
14+
} from '#lib/queries/trace'
6115

6216
export const Route = createFileRoute('/api/tx/trace/$hash')({
6317
server: {
6418
handlers: {
6519
GET: async ({ params }) => {
6620
try {
67-
const client = getConfig().getClient()
6821
const hash = zHash().parse(params.hash)
69-
const [trace, prestate] = await Promise.all([
70-
traceTransaction(client, hash).catch(() => null),
71-
tracePrestate(client, hash).catch(() => null),
72-
])
73-
return json<TraceData>({ trace, prestate })
22+
const traceData = await fetchTraceData(hash)
23+
return json<TraceData>(traceData)
7424
} catch (error) {
7525
console.error('Trace error:', error)
7626
return json({ error: 'Failed to fetch trace' }, { status: 500 })

0 commit comments

Comments
 (0)