-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathEvalInterpreter.ts
More file actions
69 lines (61 loc) · 2.51 KB
/
EvalInterpreter.ts
File metadata and controls
69 lines (61 loc) · 2.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import { stringify } from './helpers/stringify.js'
import type { DecodedTransaction } from '@3loop/transaction-decoder'
import { Effect, Layer } from 'effect'
import { Interpreter, InterpreterOptions } from './types.js'
import { getInterpreter } from './interpreters.js'
import { TransactionInterpreter } from './interpreter.js'
import { InterpreterError } from './quickjs.js'
async function localEval(code: string, input: string) {
const fn = new Function(`with(this) { ${code}; return transformEvent(${input}) }`)
const result = fn.call({})
// Check if result is a promise and await it
if (result && typeof result.then === 'function') {
return await result
}
return result
}
const make = {
// NOTE: We could export this separately to allow bundling the interpreters separately
findInterpreter: (decodedTx: DecodedTransaction) => {
if (!decodedTx.toAddress) return undefined
const code = getInterpreter(decodedTx)
if (!code) return undefined
return {
schema: code,
id: `${decodedTx.chainID}:${decodedTx.toAddress}`,
}
},
interpretTx: (
decodedTransaction: DecodedTransaction,
interpreter: Interpreter,
options?: {
interpretAsUserAddress?: string
},
) =>
Effect.tryPromise({
try: async () => {
// TODO: add ability to surpress warning on acknowledge
Effect.logWarning('Using eval in production can result in security vulnerabilities. Use at your own risk.')
const input = stringify(decodedTransaction) + (options ? `,${stringify(options)}` : '')
const result = await localEval(interpreter.schema, input)
return result
},
catch: (error) => new InterpreterError(error),
}).pipe(Effect.withSpan('TransactionInterpreter.interpretTx')),
interpretTransaction: (
decodedTransaction: DecodedTransaction,
interpreter: Interpreter,
options?: InterpreterOptions,
) =>
Effect.tryPromise({
try: async () => {
// TODO: add ability to surpress warning on acknowledge
Effect.logWarning('Using eval in production can result in security vulnerabilities. Use at your own risk.')
const input = stringify(decodedTransaction) + (options ? `,${stringify(options)}` : '')
const result = await localEval(interpreter.schema, input)
return result
},
catch: (error) => new InterpreterError(error),
}).pipe(Effect.withSpan('TransactionInterpreter.interpretTransaction')),
}
export const EvalInterpreterLive = Layer.scoped(TransactionInterpreter, Effect.succeed(make))