Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v4

- name: Cache Gradle dependencies
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.gradle/caches
key: gradle-deps-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
Expand All @@ -38,5 +38,7 @@ jobs:
./gradlew clean build --no-daemon

- name: Run Tests
env:
TEST_CONCURRENCY: 4
run: |
./gradlew test --no-daemon
./gradlew test --no-daemon --info
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ hs_err_pid*
*.ipr
*.iws
/out/

/local.properties
16 changes: 14 additions & 2 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 13 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
# 🍴 PokeFork: Seamless integration of Hardhat and Foundry Anvil with your Java/Kotlin app
# 🍴 LocalNode: get Hardhat and Foundry Anvil integrated in your Java/Kotlin app

![build status](https://github.com/ruXlab/pokefork/actions/workflows/tests.yml/badge.svg)
[![build status](https://github.com/ruXlab/localnode/actions/workflows/tests.yml/badge.svg)](https://github.com/ruXlab/localnode/actions)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Maven Central](https://img.shields.io/maven-central/v/vc.rux.pokefork/ktx-module.svg)](https://search.maven.org/artifact/vc.rux.localnode/localnode)


LocalNode allows to run a local development or forked node of the Ethereum-like network
using **Hardhat or Foundry Anvil** and interact with it from your Java/Kotlin/Scala code.
Thanks to docker there won't be a port conflict and you can run multiple nodes at the same time.

PokeFork is an open-source library project designed to empower
developers working with Ethereum Virtual Machine (EVM) based networks.
It allows to run a local development or forked node of the Ethereum-like network
using **Hardhat or Foundry Anvil** and interact with it from your Java/Kotlin/Scala code.
Developer gets full control over the management of the local node via the extended (see the table below) web3j interface.

## Motivation

Expand Down Expand Up @@ -72,15 +73,14 @@ Seriously, Java devs deserve it.

## Getting Started

Clone and build the PokeFork project:
Add dependency to your project:

```bash
git clone
cd pokefork
./gradlew test build
```kotlin
implementation("vc.rux.localnodee:web3j:0.1.0")
implementation("org.web3j:core:4.10.3")
```

TBD
And off you go! Check [examples](examples) folder to get idea how to use this library.

## Contributing

Expand All @@ -98,10 +98,6 @@ EVM network interactions.
Seriously, it's clear that number of bad actors in blockchain
space is crazy. Trust no one.

## Punning Around

We couldn't resist the opportunity for some wordplay with "PokeFork."
Just like a fork in the road, we're here to help you choose the
path that leads to success in EVM network development.
------------------------

Happy forking!
6 changes: 3 additions & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
plugins {
kotlin("jvm") version "1.9.0" apply false
application
kotlin("jvm") version "1.9.20" apply false
id("publication")
}

group = "vc.rux.pokefork"
group = "vc.rux.localnode"
version = "0.0-SNAPSHOT"
5 changes: 5 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Examples for the pokefork
===========================


You'll find here some examples of how to use the pokefork. They're self-contained, therefore they can be run directly from the IDE.
26 changes: 26 additions & 0 deletions examples/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
plugins {
kotlin("jvm")
}

group = "vc.rux.localnode.examples"
version = "0.0-SNAPSHOT"

repositories {
mavenCentral()
// maven(url = "https://s01.oss.sonatype.org/content/repositories/releases/") // optional for releases
// maven(url = "https://s01.oss.sonatype.org/content/repositories/snapshots/") // optional for snapshots
// maven(url = "https://s01.oss.sonatype.org/content/groups/staging/") // optional for staging
}

dependencies {
implementation("vc.rux.localnode:localnode:0.1.0")
implementation("org.web3j:core:4.10.3")
}


kotlin {

}



30 changes: 30 additions & 0 deletions examples/src/main/kotlin/QueryBalanceApp.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import misc.addresses
import misc.archiveNodeUrl
import org.web3j.protocol.core.DefaultBlockParameter
import org.web3j.utils.Convert.Unit
import org.web3j.utils.Convert.fromWei
import vc.rux.localnode.anvil.AnvilNode
import vc.rux.localnode.anvil.AnvilNodeConfig
import vc.rux.localnode.web3j.LocalWeb3jNode

object QueryBalanceApp {
@JvmStatic
fun main(vararg args: String) {
// Start the forked local node
val pokefork = AnvilNode.start(AnvilNodeConfig.fork(archiveNodeUrl, chainId = 1))
val web3j = LocalWeb3jNode.from(pokefork)

println("Checking the amount of ETH locked in Arbitrum Native bridge (portal) at ${addresses.arbitrumEthBridge}")
println()
println("block number\t | balance")
// Check the balances
for (block in 15500000..18600000 step 300000) {
val balance = web3j.ethGetBalance(
addresses.arbitrumEthBridge, DefaultBlockParameter.valueOf(block.toBigInteger())
).send().balance

println("$block \t\t | ${fromWei(balance.toString(), Unit.ETHER)} ETH")
}
}

}
10 changes: 10 additions & 0 deletions examples/src/main/kotlin/misc/constants.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package misc

val archiveNodeUrl by lazy {
System.getenv("ARCHIVE_NODE_URL_ETHEREUM") ?: "https://rpc.ankr.com/eth"
}

object addresses {
const val optimismPortal = "0xbEb5Fc579115071764c7423A4f12eDde41f106Ed"
const val arbitrumEthBridge = "0x8315177ab297ba92a06054ce80a67ed4dbd7ed3a"
}
9 changes: 9 additions & 0 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
kotlin.code.style=official


artifactName=localnode
artifactDesc=Run local node or fork Ethereum-like blockchains from your Kotlin/Java app using Hardhat or Foundry Anvil
artifactUrl=https://github.com/ruXlab/localnode
artifactScm=git@github.com:ruXlab/localnode.git
artifactLicenseName=MIT License
artifactLicenseUrl=http://www.opensource.org/licenses/mit-license.php
artifactPublishVersion=0.1.0
6 changes: 6 additions & 0 deletions localnode/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
LocalNode library module
=========

This is a library module, please refer to the
[parent README](../README.md) to learn more about
the project and how to use it.
16 changes: 15 additions & 1 deletion core/build.gradle.kts → localnode/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import org.gradle.api.tasks.testing.logging.TestLogEvent

plugins {
kotlin("jvm")
id("publication")
`maven-publish`
signing
}

group = "vc.rux.pokefork.core"
group = "vc.rux.localnode"
version = "0.0-SNAPSHOT"

repositories {
Expand All @@ -15,13 +18,21 @@ dependencies {
implementation(libs.dockerjava)
implementation(libs.bundles.logging)

implementation(libs.web3j)

testImplementation(kotlin("test"))
testImplementation(platform(testlibs.junit.bom))
testImplementation(testlibs.junit.api)
testImplementation(testlibs.junit.params)
testRuntimeOnly(testlibs.junit.engine)
testImplementation(testlibs.assertk)
testImplementation(libs.web3j.contracts)
}


java {
withJavadocJar()
withSourcesJar()
}


Expand All @@ -32,4 +43,7 @@ tasks.test {
TestLogEvent.PASSED, TestLogEvent.SKIPPED, TestLogEvent.FAILED
)
}
System.getenv("TEST_CONCURRENCY")?.toIntOrNull()?.let {
maxParallelForks = it
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
package vc.rux.pokefork

import vc.rux.pokefork.ILocalNode
package vc.rux.localnode

interface IForkNode : ILocalNode {
fun forkBlock(blockNumber: Long)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork
package vc.rux.localnode

import java.math.BigInteger

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork
package vc.rux.localnode

/**
* NodeMode is a sealed interface with two implementations:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork.anvil
package vc.rux.localnode.anvil

import com.github.dockerjava.api.DockerClient
import com.github.dockerjava.api.command.CreateContainerResponse
Expand All @@ -7,12 +7,12 @@ import com.github.dockerjava.api.model.ExposedPort
import com.github.dockerjava.api.model.HostConfig
import com.github.dockerjava.api.model.PullResponseItem
import org.slf4j.LoggerFactory
import vc.rux.pokefork.NodeMode
import vc.rux.pokefork.common.idPrefix
import vc.rux.pokefork.common.waitForRpcToBoot
import vc.rux.pokefork.defaultDockerClient
import vc.rux.pokefork.hardhat.HardhatNode
import vc.rux.pokefork.hardhat.IEthereumLikeNode
import vc.rux.localnode.NodeMode
import vc.rux.localnode.common.idPrefix
import vc.rux.localnode.common.waitForRpcToBoot
import vc.rux.localnode.defaultDockerClient
import vc.rux.localnode.hardhat.HardhatNode
import vc.rux.localnode.hardhat.IEthereumLikeNode
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package vc.rux.pokefork.anvil
package vc.rux.localnode.anvil

import vc.rux.pokefork.NodeMode
import vc.rux.localnode.NodeMode

data class AnvilNodeConfig(
val nodeMode: NodeMode,
val blockNumber: Long? = null,
val imageName: String = "pokefork",
val imageName: String = "localnode",
val imageTag: String? = null,
val foundryImage: String = "ghcr.io/foundry-rs/foundry:latest"
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork.anvil.internal
package vc.rux.localnode.anvil.internal

internal data class AnvilDockerfile(
val commandLineParams: List<String>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package vc.rux.pokefork.common
package vc.rux.localnode.common

import vc.rux.pokefork.NodeMode
import vc.rux.localnode.NodeMode

internal val NodeMode.idPrefix
get() = when (this) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork.common
package vc.rux.localnode.common

import org.slf4j.LoggerFactory
import java.net.HttpURLConnection
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork
package vc.rux.localnode

import com.github.dockerjava.core.DockerClientBuilder

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
package vc.rux.pokefork.errors

import javax.ws.rs.core.Response
package vc.rux.localnode.errors

open class PokeForkError : RuntimeException {
constructor(message: String) : super(message)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package vc.rux.pokefork.hardhat
package vc.rux.localnode.hardhat

import vc.rux.pokefork.NodeMode
import vc.rux.localnode.NodeMode

data class HardHatNodeConfig(
val nodeMode: NodeMode,
val blockNumber: Long? = null,
val imageName: String = "pokefork",
val imageName: String = "localnode",
val imageTag: String? = null,
val hardhatVersion: String = "2.17.3"
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vc.rux.pokefork.hardhat
package vc.rux.localnode.hardhat

import com.github.dockerjava.api.DockerClient
import com.github.dockerjava.api.async.ResultCallback
Expand All @@ -7,12 +7,12 @@ import com.github.dockerjava.api.command.CreateContainerResponse
import com.github.dockerjava.api.model.BuildResponseItem
import com.github.dockerjava.api.model.HostConfig
import org.slf4j.LoggerFactory
import vc.rux.pokefork.NodeMode
import vc.rux.pokefork.common.idPrefix
import vc.rux.pokefork.common.waitForRpcToBoot
import vc.rux.pokefork.defaultDockerClient
import vc.rux.pokefork.hardhat.internal.HardHatConfigJs
import vc.rux.pokefork.hardhat.internal.HardHatDockerfile
import vc.rux.localnode.NodeMode
import vc.rux.localnode.common.idPrefix
import vc.rux.localnode.common.waitForRpcToBoot
import vc.rux.localnode.defaultDockerClient
import vc.rux.localnode.hardhat.internal.HardHatConfigJs
import vc.rux.localnode.hardhat.internal.HardHatDockerfile
import java.nio.file.Files
import kotlin.time.Duration.Companion.seconds

Expand Down
Loading