🚧 This project is a work in progress and not ready for production use.
Orakul is a complete oracle solution for Ethereum-compatible blockchains, addressing the challenge of connecting smart contracts with external data sources like APIs. Its main goal is to provide a simple and flexible way to achieve this with minimal effort and cost.
While third-party services like Chainlink and Gelato are powerful, they may not offer the level of control and customization you need. They can also be expensive or complex to use. Orakul is designed to be both simple and flexible, offering a free and open-source alternative that you can run on your own infrastructure and extend as needed.
- Request external data from smart contracts
- Develop custom jobs to process data
- Run on your own infrastructure
- Dashboard for monitoring and managing jobs
- Multi-node support for high availability
- ZK proofs for data verification
- Job scheduling and automation
- Randomness generation
- Price feeds
The solution consists of two main components:
- Oracle contract: Smart contract that acts as a bridge between the blockchain and the external world.
- Oracle node: Server application that listens for oracle request events and executes the corresponding jobs.
You first need to deploy the Oracle contract and develop a client contract that interacts with it. Afterward, you must run the node application, configured with the contract address and funded with enough tokens to cover gas fees. You can also create custom jobs that the node can execute. See the instructions below for more details.
- Node.js
- npm
- Docker
- Wallet
- RPC provider
Clone the repository:
git clone [email protected]:imollov/orakul.git
- In the
contracts
directory, install the dependencies:
npm install
- Build the contracts:
npx hardhat compile
- Create a
.env
file using the template and fill in the required values:
cp .env.example .env
- Deploy the contracts:
npx hardhat run scripts/deploy_oracle.js --network <NETWORK>
- Create a
.env
file using the template and fill in the required values:
cp .env.example .env
- Start the node:
docker compose up --build
- If everything is correct, you should see the following output:
🔗 Oracle contract...
👷🏼 Job registry...
🚀 Starting job client...
- Import the Oracle client interface in your contract:
import {IOracleClient} from "../interfaces/IOracleClient.sol";
- Implement the
IOracleClient
interface in your contract:
contract MyContract is IOracleClient {
// Contract code
}
- Set the Oracle contract address:
constructor(address _oracle) {
oracle = IOracle(_oracle);
}
- Implement the
fulfillOracleRequest
function:
function fulfillOracleRequest(bytes32 requestId, bytes32 data) external override {
// Process the data
}
- Request data from the Oracle contract:
function requestData(bytes32 jobId, uint256 arg) public {
bytes32 requestId = oracle.makeOracleRequest(jobId, abi.encode(arg));
requests[requestId] = msg.sender;
}
- After deploying the client contract, register it with the Oracle contract by calling the
authorizeRequester
from the Oracle contract owner account.
- In the
node
directory, install the dependencies:
npm install
- Create a new file in the
jobs
directory:
touch jobs/my-job.ts
- Export a function that uses the
asJob
builder:
import { asJob } from "../core/job";
export const myJob = asJob<bigint, bigint>({
name: 'My custom job',
inputTypes: ['uint256'],
outputTypes: ['uint256'],
fn: async (arg) => {
// Implement the job logic
}
Notes:
- The
arg
parameter is the data passed from the client contract. - The types of the arguments and return values can be customized by changing the generic types of the
asJob
function. - Input and output types specify the Solidity types that will be used for encoding and decoding the data.
- Add the job to the registry in the
jobs/index.ts
file:
export * from "./my-job";
- Contract: WeatherConsumer.sol
- Job: weather.ts
This example demonstrates how to request weather data from an external API and return the temperature to the client contract.
- Deploy the WeatherConsumer contract:
npx hardhat run scripts/deploy_weather_consumer.js --network <NETWORK>
-
Once deployed, call the
authorizeRequester
function from the Oracle contract owner account to authorize the WeatherConsumer contract. -
Call the
requestData
function from the WeatherConsumer contract to request weather data with specific coordinates. -
If the request is successful, the Oracle node will execute the
weatherJob
and return the temperature and you should see the following output:
📋 New OracleRequest event...
ℹ️ Getting weather data from API for lat: 51.5074 and long: 0.1278
ℹ️ Current temperature: 20.2
ℹ️ Fulfilling OracleRequest...
✅ OracleRequest fulfilled...
- The WeatherConsumer contract will receive the temperature and you can check it by calling the
getWeatherResult
function with the request ID.
-
Create a new EC2 instance.
-
Choose Amazon Linux as the OS and t2.micro as the instance type for free-tier eligibility.
-
Configure the security group to allow SSH access only.
-
In advanced details, add the following user data to install Docker, Git, and Docker Compose:
#!/bin/bash
# Install Docker
sudo yum install docker -y
sudo systemctl start docker
sudo systemctl enable docker
# Install Git
sudo yum install git -y
# Install Docker Compose
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
-
Launch the instance.
-
Connect to the instance using SSH from the console or your terminal.
-
Switch to root user:
sudo su
- Clone the repository and navigate to the node directory:
git clone [email protected]:imollov/orakul.git
cd orakul/node
- Create a .env file using the provided template:
cp .env.example .env
- Use a text editor like nano to edit the .env file:
nano .env
Fill in the required values, such as the RPC URL, Private key, and Oracle contract address.
- Deploy the Oracle node using Docker Compose:
docker-compose up --build -d
- Check if the Oracle node is running:
docker-compose ps
Open an issue or submit a pull request.
MIT