Skip to content

Commit b359007

Browse files
Run interpreter in nodejs env in the playground (#255)
1 parent 081a88e commit b359007

File tree

11 files changed

+75
-220
lines changed

11 files changed

+75
-220
lines changed

apps/web/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"dependencies": {
1212
"@3loop/transaction-decoder": "workspace:*",
1313
"@3loop/transaction-interpreter": "workspace:*",
14-
"@jitl/quickjs-singlefile-browser-release-sync": "^0.31.0",
14+
"@jitl/quickjs-singlefile-cjs-release-sync": "^0.31.0",
1515
"@monaco-editor/react": "^4.6.0",
1616
"@radix-ui/react-collapsible": "^1.1.2",
1717
"@radix-ui/react-dialog": "^1.1.4",
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { NextRequest, NextResponse } from 'next/server'
2+
import { applyInterpreterServer } from '@/lib/interpreter-server'
3+
import type { DecodedTransaction } from '@3loop/transaction-decoder'
4+
5+
export const runtime = 'nodejs'
6+
export const dynamic = 'force-dynamic'
7+
8+
interface InterpretRequest {
9+
decodedTx: DecodedTransaction
10+
interpreter: {
11+
id: string
12+
schema: string
13+
}
14+
interpretAsUserAddress?: string
15+
}
16+
17+
export const POST = async (request: NextRequest) => {
18+
try {
19+
const body: InterpretRequest = await request.json()
20+
21+
const { decodedTx, interpreter, interpretAsUserAddress } = body
22+
23+
if (!decodedTx || !interpreter) {
24+
return NextResponse.json(
25+
{ error: 'Missing required fields: decodedTx and interpreter are required' },
26+
{ status: 400 },
27+
)
28+
}
29+
30+
const result = await applyInterpreterServer(decodedTx, interpreter, interpretAsUserAddress)
31+
32+
return NextResponse.json(result)
33+
} catch (error) {
34+
console.error('Interpreter API error:', error)
35+
return NextResponse.json(
36+
{
37+
error: error instanceof Error ? error.message : 'Failed to interpret transaction',
38+
},
39+
{ status: 500 },
40+
)
41+
}
42+
}

apps/web/src/app/contract/[contract]/loading.tsx

Lines changed: 0 additions & 47 deletions
This file was deleted.

apps/web/src/app/contract/[contract]/page.tsx

Lines changed: 0 additions & 44 deletions
This file was deleted.

apps/web/src/app/contract/[contract]/table.tsx

Lines changed: 0 additions & 51 deletions
This file was deleted.

apps/web/src/app/interpret/[chainID]/[hash]/form.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { Input } from '@/components/ui/input'
88
import { Button } from '@/components/ui/button'
99
import { useRouter } from 'next/navigation'
1010
import { DecodedTransaction } from '@3loop/transaction-decoder'
11-
import { Interpretation, applyInterpreter } from '@/lib/interpreter'
11+
import type { Interpretation } from '@/lib/interpreter-server'
1212
import CodeBlock from '@/components/ui/code-block'
1313
import { NetworkSelect } from '@/components/ui/network-select'
1414
import { fallbackInterpreter, getInterpreter } from '@3loop/transaction-interpreter'
@@ -65,10 +65,29 @@ export default function DecodingForm({ decoded, currentHash, chainID, error }: F
6565
setIsInterpreting(true)
6666
setResult(undefined)
6767

68-
applyInterpreter(decoded, newInterpreter, userAddress || undefined)
68+
// Call server-side API to run interpreter (avoids CORS issues)
69+
fetch('/api/interpret', {
70+
method: 'POST',
71+
headers: {
72+
'Content-Type': 'application/json',
73+
},
74+
body: JSON.stringify({
75+
decodedTx: decoded,
76+
interpreter: newInterpreter,
77+
interpretAsUserAddress: userAddress || undefined,
78+
}),
79+
})
80+
.then((response) => response.json())
6981
.then((res) => {
7082
setResult(res)
7183
})
84+
.catch((error) => {
85+
setResult({
86+
tx: decoded,
87+
interpretation: null,
88+
error: error.message || 'Failed to interpret transaction',
89+
})
90+
})
7291
.finally(() => {
7392
setIsInterpreting(false)
7493
})

apps/web/src/app/layout.tsx

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import type { Metadata } from 'next'
44
import { Inter } from 'next/font/google'
55
import { MainNav } from '@/components/ui/main-nav'
66
import { Analytics } from '@vercel/analytics/react'
7-
import { aaveV2 } from '../app/data'
87
import {
98
DropdownMenu,
109
DropdownMenuContent,
@@ -33,11 +32,6 @@ const navLinks = [
3332
match: 'interpret',
3433
title: 'Transaction Interpreter',
3534
},
36-
{
37-
href: `/contract/${aaveV2}`,
38-
match: 'contract',
39-
title: 'Test contract',
40-
},
4135
]
4236

4337
const SOCIAL_LINKS = [

apps/web/src/lib/etherscan.ts

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import {
44
QuickjsInterpreterLive,
55
QuickjsConfig,
66
TransactionInterpreter,
7-
fallbackInterpreter,
8-
getInterpreter,
97
} from '@3loop/transaction-interpreter'
108
import { Effect, Layer } from 'effect'
11-
import variant from '@jitl/quickjs-singlefile-browser-release-sync'
9+
import variant from '@jitl/quickjs-singlefile-cjs-release-sync'
1210

11+
// Server-side interpreter configuration using Node.js QuickJS variant
12+
// This runs in Node.js context where CORS restrictions don't apply
1313
const config = Layer.succeed(QuickjsConfig, {
1414
variant: variant,
1515
runtimeConfig: {
16-
timeout: 1000,
16+
timeout: 5000,
1717
useFetch: true,
1818
},
1919
})
@@ -26,11 +26,11 @@ export interface Interpretation {
2626
error?: string
2727
}
2828

29-
export async function applyInterpreter(
29+
export const applyInterpreterServer = async (
3030
decodedTx: DecodedTransaction,
3131
interpreter: Interpreter,
3232
interpretAsUserAddress?: string,
33-
): Promise<Interpretation> {
33+
): Promise<Interpretation> => {
3434
const runnable = Effect.gen(function* () {
3535
const interpreterService = yield* TransactionInterpreter
3636
const interpretation = yield* interpreterService.interpretTransaction(decodedTx, interpreter, {
@@ -54,18 +54,3 @@ export async function applyInterpreter(
5454
}
5555
})
5656
}
57-
58-
export async function findAndRunInterpreter(decodedTx: DecodedTransaction): Promise<Interpretation> {
59-
let interpreter = getInterpreter(decodedTx)
60-
61-
if (!interpreter) {
62-
interpreter = fallbackInterpreter
63-
}
64-
65-
const res = await applyInterpreter(decodedTx, {
66-
id: 'default',
67-
schema: interpreter,
68-
})
69-
70-
return res
71-
}

packages/transaction-interpreter/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const runnable = Effect.gen(function* () {
4040
// NOTE: Search the interpreter in the default interpreters
4141
const interpreter = interpreterService.findInterpreter(decodedTx)
4242

43-
const interpretation = yield* interpreterService.interpretTx(decodedTx, interpreter)
43+
const interpretation = yield* interpreterService.interpretTransaction(decodedTx, interpreter)
4444

4545
return interpretation
4646
}).pipe(Effect.provide(layer))

0 commit comments

Comments
 (0)