From 0add2510d68f103870aa39588f0ae75f82250882 Mon Sep 17 00:00:00 2001 From: Alberto Lerda Date: Fri, 29 Sep 2023 10:44:06 +0100 Subject: [PATCH] ethereum connect For the moment I am using one file for each verb (e.g. read.ts and connect.ts). The result is that connect is a parser that matches only one sentence. --- pkg/ethereum/src/connect.ts | 96 +++++++++++++++++++++++++++++++++++++ pkg/ethereum/test/read.ts | 7 ++- 2 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 pkg/ethereum/src/connect.ts diff --git a/pkg/ethereum/src/connect.ts b/pkg/ethereum/src/connect.ts new file mode 100644 index 00000000..ba8c2da7 --- /dev/null +++ b/pkg/ethereum/src/connect.ts @@ -0,0 +1,96 @@ +import { createToken, Lexer, CstParser } from "@slangroom/deps/chevrotain"; +import { JsonableObject } from "@slangroom/shared"; +import { StmtContext } from "@slangroom/core/slangroom"; +import { Whitespace, Identifier } from "@slangroom/shared/tokens" +import { Web3 } from 'web3' + +type EthereumConnect = { + address: string +} + +const Ethereum = createToken({ + name: "Ethereum", + pattern: /ethereum/i, +}); +const The = createToken({ + name: "The", + pattern: /the/i, + group: Lexer.SKIPPED, +}); +const Provider = createToken({ + name: "Provider", + pattern: /Provider/i, +}); +const To = createToken({ + name: "To", + pattern: /To/i, +}); + +const allTokens = [ + Whitespace, + The, + To, + Ethereum, + Provider, + Identifier, +]; +const StatementLexer = new Lexer(allTokens); +// ----------------- parser ----------------- +class StatementParser extends CstParser { + constructor() { + super(allTokens); + + this.performSelfAnalysis(); + } + + public statement = this.RULE("statement", () => { + this.CONSUME(To); + this.CONSUME(Ethereum); + this.CONSUME(Provider); + this.CONSUME(Identifier); + }); +} + +const parser = new StatementParser(); +// ----------------- Interpreter ----------------- +const BaseCstVisitor = parser.getBaseCstVisitorConstructor(); + +class StatementInterpreter extends BaseCstVisitor { + constructor() { + super(); + this.validateVisitor(); + } + statement(ctx: any) { + return {address: ctx.Identifier[0].image.slice(1,-1)} + } +} + +// We only need a single interpreter instance because our interpreter has no state. +const interpreter = new StatementInterpreter(); + + +export const line2Ast = (text: string) => { + const lexResult = StatementLexer.tokenize(text); + parser.input = lexResult.tokens; + const cst = parser.statement(); + const value = interpreter.visit(cst); + return { + value: value, + lexResult: lexResult, + parseErrors: parser.errors, + }; +} + +type EthereumConnectResult = { + name: string, + value: Web3 +} + +export const evaluate = async (ast: EthereumConnect, + keys: JsonableObject, stmtCtx: StmtContext): Promise => { + const address = (keys[ast.address] || stmtCtx.data[ast.address] || ast.address) as string + return { + name: "web3", + value: new Web3(address) + } +} diff --git a/pkg/ethereum/test/read.ts b/pkg/ethereum/test/read.ts index 002f7fa6..6c688b92 100644 --- a/pkg/ethereum/test/read.ts +++ b/pkg/ethereum/test/read.ts @@ -4,9 +4,14 @@ import { Web3 } from 'web3' const test = anyTest as TestFn<{web3: Web3}>; import { EthereumRequestKind, line2Ast, evaluate } from '@slangroom/ethereum/read'; +import { line2Ast as line2AstConnect, evaluate as evaluateConnect } from '@slangroom/ethereum/connect'; test.before(async (t) => { - t.context.web3 = new Web3('http://78.47.38.223:9485') + const ast = line2AstConnect("to the ethereum provider 'foo'"); + t.deepEqual(ast.value, { address: 'foo' }) + const res = await evaluateConnect(ast.value, {}, {data: {foo: "http://78.47.38.223:9485"}, context: t.context}) + t.is(res.name, "web3") + t.context.web3 = res.value }); test("Ethereum nonce", async (t) => {