Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run inlineClient in REPL #3776

Open
acolytec3 opened this issue Oct 29, 2024 · 4 comments
Open

Run inlineClient in REPL #3776

acolytec3 opened this issue Oct 29, 2024 · 4 comments

Comments

@acolytec3
Copy link
Contributor

One thing that might make troubleshooting the client on devnets and the like easier would be to be able to run it in a REPL so we can have direct access to the client object as its running, similarly to how geth has their javascript console.

We already have a createInlineClient function available to us that accepts the entire configuration object available to the client so it shouldn't be too hard to expand this a bit to allow a user to pass in a geth genesis.json and start a client entirely within a REPL.

The piece that isn't built yet would be hooking it up to the RPC. We have a startRPCServers function that we could pass the instantiated "inline" client to and then just grab a reference to it in the REPL so we can be sure to not lose it.

This could also be an interesting "community showcase" idea.

@acolytec3
Copy link
Contributor Author

acolytec3 commented Oct 29, 2024

This script is a working proof of concept.

const { readFileSync } = await import('fs')

const { createCommonFromGethGenesis, parseGethGenesis } = await import('@ethereumjs/common')
const { createInlineClient } = await import('./test/sim/simutils.ts')
const { Config } = await import('./src/config.ts')
const { getLogger } = await import('./src/logging.ts')
const { startRPCServers } = await import('./bin/startRPC.ts')
const genesisFile = JSON.parse(readFileSync('./genesis.json', 'utf-8'))
const chainName = 'pectra'
const common = createCommonFromGethGenesis(genesisFile, {
  chain: chainName,
})
const config = new Config({ common, logger: getLogger({ logLevel: 'debug' }), saveReceipts: true, enableSnapSync: true })
const client = await createInlineClient(config, common, {}, '', true)
const servers = startRPCServers(client, {
  rpc: true,
  rpcAddr: '0.0.0.0',
  rpcPort: 8545,
  ws: false,
  wsPort: 0,
  wsAddr: '0.0.0.0',
  rpcEngine: true,
  rpcEngineAddr: '0.0.0.0',
  rpcEnginePort: 8551,
  wsEngineAddr: '0.0.0.0',
  wsEnginePort: 8552,
  rpcDebug: 'eth',
  rpcDebugVerbose: 'false',
  helpRPC: false,
  jwtSecret: '',
  rpcEngineAuth: false,
  rpcCors: '',
})

To see in action:

  1. Copy the above snippet into script.ts
  2. Run npx tsx in the same directory where script.ts is
  3. Type .load script.ts (this runs the script as though you were typing it in directly)

Behold your inline client.

Uploading Screencast from 10-29-2024 04:01:37 PM.webm…

@acolytec3
Copy link
Contributor Author

And if you want to create an actual custom javascript console for our client, here's another variant.

import repl from 'repl'

const setupClient = async () => {
  const { readFileSync } = await import('fs')

  const { createCommonFromGethGenesis, parseGethGenesis } = await import('@ethereumjs/common')
  const { createInlineClient } = await import('./test/sim/simutils.ts')
  const { Config } = await import('./src/config.ts')
  const { getLogger } = await import('./src/logging.ts')
  const { startRPCServers } = await import('./bin/startRPC.ts')
  const genesisFile = JSON.parse(readFileSync('./genesis.json', 'utf-8'))
  const chainName = 'pectra'
  const common = createCommonFromGethGenesis(genesisFile, {
    chain: chainName,
  })
  const config = new Config({
    common,
    logger: getLogger({ logLevel: 'info' }),
    saveReceipts: true,
    enableSnapSync: true,
  })
  const client = await createInlineClient(config, common, {}, '', true)
  const servers = startRPCServers(client, {
    rpc: true,
    rpcAddr: '0.0.0.0',
    rpcPort: 8545,
    ws: false,
    wsPort: 0,
    wsAddr: '0.0.0.0',
    rpcEngine: true,
    rpcEngineAddr: '0.0.0.0',
    rpcEnginePort: 8551,
    wsEngineAddr: '0.0.0.0',
    wsEnginePort: 8552,
    rpcDebug: 'eth',
    rpcDebugVerbose: 'false',
    helpRPC: false,
    jwtSecret: '',
    rpcEngineAuth: false,
    rpcCors: '',
  })
  return client
}

const client = await setupClient()

const replServer = repl.start({
  prompt: 'EthJS > ',
  ignoreUndefined: true,
})

replServer.context.client = client

console.log('Custom console started. Type .help for available commands.')

Just run npx tsx script.ts and away we go.

@holgerd77
Copy link
Member

Interesting. 👀

Thanks for the write up, super helpful! 🙂🙏

@holgerd77
Copy link
Member

(guess a lot of API work still to be done though…)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants