Skip to main content

Build smarter
applications on the blockchain

Build hassle-free on all EVM chains.
Build faster and better decentralized apps in no-time.

Deliver data to your users, FAST

Kenshi deep index allows retrieving, storing, and indexing blockchain events into Kenshi's geographically distributed data clusters for faster access.
Use your favorite GraphQL client to query the blockchain
import { ApolloClient, gql, InMemoryCache } from "@apollo/client/core/core.cjs";

const client = new ApolloClient({
  uri: "https://api.kenshi.io/index/graphql",
  cache: new InMemoryCache(),
});

const query = gql`
  {
    getEntries(blockchain: "binance-mainnet") {
      event {
        name
      }
    }
  }
`;

const { data } = client.query({ query });
See more examples on GitHub
Use MongoDB Query Language to run complex queries on the blockchain
import axios from "axios";

const request = {
  blockchain: "binance-mainnet",
  query: {
    "event.name": "Transfer",
    "block.number": { $gte: 20740000 },
  },
};

const data = await axios.post("https://api.kenshi.io/index/mql", request);
See more examples on GitHub
Use Webhooks to get push notifications from the blockchain
import express from "express";
import parser from "body-parser";

const app = express();
app.use(parser.json());

app.post("/", (req, res) => {
  console.dir(req.body, { depth: null });
  res.status(200).end("OK");
});

app.listen(8080);
See more examples on GitHub

Kenshi blockchain IoT SDK

From supply chain and vending machines that accept crypto, to smart home appliances and smart cities.
Kenshi IoT SDK enables you to connect your embedded devices to the blockchain. Have an idea and don't know where to start? Contact us and we will help bring your idea to life.

Automate the world, with blockchain

Connect your smart contract to the world! Kenshi R-API directly streams events from your smart contracts to already existing automation tools!

Connect your smart contract

Kenshi Oracle Network is a high-performance asynchronous oracle platform that allows creating and hosting of custom oracles.
Kenshi takes care of event sourcing, scheduling, security, error handling, and data delivery so you can focus on your business.

Get started

Use one of our Oracle blueprints or sample codes to get started in no time.

A very simple blueprint to start from. Extend this to create your custom functionality.

export const handler = async () => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      method: "setTime",
      args: [new Date().valueOf()],
      maxGas: "100000000000000", // 0.0001 ETH
      abort: false,
    }),
  };
};
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Time {
    uint256 timestamp;
    event TimeRequest();

    /**
     * Emit and event that will be picked up by the Kenshi
     * Oracle Network and sent to your oracle for processing
     */
    function requestTime() external {
        emit TimeRequest();
    }

    /**
     * This method will be called by the Kenshi Oracle Network
     * with the result returned from your oracle
     */
    function setTime(uint256 time) external {
        timestamp = time;
    }

    /**
     * Public function to display the last retrieved timestamp
     */
    function showTime() public view returns (uint256) {
        return timestamp;
    }
}

The following blueprint shows how to get price data from coingecko.com

.

import { ethers } from "ethers";
import fetch from "node-fetch";

const url =
  "https://api.coingecko.com/api/v3/coins/kenshi/market_chart?vs_currency=usd&days=1";

export const handler = async () => {
  const resp = await fetch(url);
  const { prices } = await resp.json();
  const average =
    prices
      .slice(-6) // last 30 minutes
      .map(([_, price]) => price)
      .reduce((a, b) => a + b) / 6;
  return {
    statusCode: 200,
    body: JSON.stringify({
      method: "setPrice",
      args: [ethers.utils.parseUnits(average.toFixed(18)).toString()],
      maxGas: "100000000000000", // 0.0001 ETH
      abort: false,
    }),
  };
};
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Price {
    event PriceRequest();
    event PriceRequestFulfilled(uint256 price);

    /**
     * Emit and event that will be picked up by the Kenshi
     * Oracle Network and sent to your oracle for processing
     */
    function requestPrice() external {
        emit PriceRequest();
    }

    /**
     * This method will be called by the Kenshi Oracle Network
     * with the result returned from your oracle
     */
    function setPrice(uint256 price) external {
        emit PriceRequestFulfilled(price);
    }
}

The following blueprint shows how to check if the user owns a specific amount of tokens or NFTs on another chain.

import { ethers } from "ethers";

const abi = ["function balanceOf(address) view returns (uint)"];

export const handler = async ({ body }) => {
  const { entry } = JSON.parse(body);
  const provider = new ethers.providers.JsonRpcProvider(process.env.RPC_ADDR);
  const contract = new ethers.Contract(entry.event.args.token, abi, provider);
  const balance = await contract.balanceOf(entry.event.args.user);
  return {
    statusCode: 200,
    body: JSON.stringify({
      method: "setBalance",
      args: [entry.event.args.user, entry.event.args.token, balance.toString()],
      maxGas: "100000000000000", // 0.0001 ETH
      abort: false,
    }),
  };
};
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Balance {
    event BalanceRequest(address user, address token);
    event BalanceRequestFulfilled(address user, address token, uint256 balance);

    /**
     * Emit and event that will be picked up by the Kenshi
     * Oracle Network and sent to your oracle for processing
     */
    function requestBalance(address user, address token) external {
        emit BalanceRequest(user, token);
    }

    /**
     * This method will be called by the Kenshi Oracle Network
     * with the result returned from your oracle
     */
    function setBalance(
        address user,
        address token,
        uint256 balance
    ) external {
        emit BalanceRequestFulfilled(user, token, balance);
    }
}

The following blueprint shows how to get weather data from brightsky.dev

.

import { ethers } from "ethers";
import fetch from "node-fetch";

export const handler = async ({ body }) => {
  const now = new Date();
  const { entry } = JSON.parse(body);
  // Solidity doesn't have floating point numbers;
  // We divide lat and long by 100 for 0.01 precision
  const lat = ethers.BigNumber.from(entry.event.args.lat).toNumber() / 100;
  const long = ethers.BigNumber.from(entry.event.args.long).toNumber() / 100;
  const url = `https://api.brightsky.dev/weather?lat=${lat}&lon=${long}&date=${now.toISOString()}`;
  const resp = await fetch(url);
  const { weather } = await resp.json();
  return {
    statusCode: 200,
    body: JSON.stringify({
      method: "setWeather",
      args: [
        entry.event.args.lat,
        entry.event.args.long,
        // Solidity doesn't have floating point numbers;
        // We multiply the temperature by 100 for 0.01 precision
        Math.round(weather[0].temperature * 100),
      ],
      maxGas: "100000000000000", // 0.0001 ETH
      abort: false,
    }),
  };
};
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Weather {
    event WeatherRequest(uint256 lat, uint256 long);
    event WeatherRequestFulfilled(
        uint256 lat,
        uint256 long,
        uint256 temperature
    );

    /**
     * Emit and event that will be picked up by the Kenshi
     * Oracle Network and sent to your oracle for processing
     *
     * Note: Solidity doesn't have floating point numbers,
     * we assume lat and long are multiplied by 100 to elliminate
     * the decimal part of them
     */
    function requestWeather(uint256 lat, uint256 long) external {
        emit WeatherRequest(lat, long);
    }

    /**
     * This method will be called by the Kenshi Oracle Network
     * with the result returned from your oracle
     */
    function setWeather(
        uint256 lat,
        uint256 long,
        uint256 temperature
    ) external {
        emit WeatherRequestFulfilled(lat, long, temperature);
    }
}

The following blueprint shows how to create your own VRF oracle. This example uses the Kenshi VRF libraries, which implement draft 10 of the IETF ECVRF.

import { decode, prove, getFastVerifyComponents } from "@kenshi.io/node-ecvrf";
import { createHash } from "crypto";
import Elliptic from "elliptic";

const EC = new Elliptic.ec("secp256k1");

export const getPublicKey = (privateKey) => {
  const key = EC.keyFromPrivate(privateKey);
  return {
    key: key.getPublic("hex"),
    compressed: key.getPublic(true, "hex"),
    x: key.getPublic().getX(),
    y: key.getPublic().getY(),
  };
};

const fromHex = (hex) => Buffer.from(hex.slice(2));

const hash = (...args) => {
  const sha256 = createHash("sha256");
  for (const arg of args) {
    sha256.update(arg);
  }
  return sha256.digest().toString("hex");
};

export const handler = async ({ body }) => {
  const { entry } = JSON.parse(body);

  // You can generate a private key using the `keygen` function
  // exported by the @kenshi.io/node-ecvrf library
  const publicKey = getPublicKey(process.env.VRF_PRIVATE_KEY);

  const alpha = hash(
    fromHex(entry.transaction.hash),
    fromHex(entry.log.index),
    fromHex(entry.block.address),
    fromHex(entry.event.args.requestId)
  );

  const proof = prove(process.env.VRF_PRIVATE_KEY, alpha);
  const fast = getFastVerifyComponents(publicKey.key, proof, alpha);
  const [Gamma, c, s] = decode(proof);

  return {
    statusCode: 200,
    body: JSON.stringify({
      method: "setRandomness",
      args: [
        [Gamma.x.toString(), Gamma.y.toString(), c.toString(), s.toString()],
        `0x${alpha}`,
        [fast.uX, fast.uY],
        [fast.sHX, fast.sHY, fast.cGX, fast.cGY],
        entry.event.args.requestId,
      ],
      maxGas: "100000000000000", // 0.0001 ETH
      abort: false,
    }),
  };
};
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "@kenshi.io/vrf-consumer/contracts/VRFUtils.sol";

contract VRFOracle {
    uint256 _requestId;
    mapping(uint256 => bool) alreadyFulfilled;

    event RandomnessRequest(uint256 requestId);
    event RandomnessRequestFulfilled(uint256 requestId, uint256 randomness);

    VRFUtils utils;

    constructor(bytes memory publicKey) {
        utils = new VRFUtils();
        utils.setPublicKey(publicKey);
    }

    /**
     * Emit and event that will be picked up by the Kenshi
     * Oracle Network and sent to your oracle for processing
     */
    function requestRandomness() external {
        emit RandomnessRequest(_requestId++);
    }

    /**
     * This method will be called by the Kenshi Oracle Network
     * with the result returned from your oracle
     *
     * Note: We encourage reading IETF ECVRF drafts to understand
     * what's going on: https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf
     */
    function setRandomness(
        uint256[4] memory proof,
        bytes memory message,
        uint256[2] memory uPoint,
        uint256[4] memory vComponents,
        uint256 requestId
    ) external {
        require(!alreadyFulfilled[requestId], "Already fulfilled");
        bool isValid = utils.fastVerify(proof, message, uPoint, vComponents);
        require(isValid, "Cannot verify VRF results");
        bytes32 beta = utils.gammaToHash(proof[0], proof[1]);
        uint256 randomness = uint256(beta);
        alreadyFulfilled[requestId] = true;
        emit RandomnessRequestFulfilled(requestId, randomness);
    }
}

Together, we drive forward!

Join Kenshi's network of partners to enjoy exclusive offers, volume discounts, premium support, and closer collaboration.

Influencers and Content Creators

Earn up to 20% commission by joining one of our referral programs. Curious? See who is eligible .

Partner to amazing businesses

We are on a constant lookout for collaborating with top-notch companies and industry leaders.

Supported blockchains

Reach out to us to launch Kenshi services on your blockchain.