chain-syncer is a module which allows you to synchronize your app with any ethereum-compatible blockchain/contract state. Fast. Realtime. Reliable.

Overview

Chain Syncer

Chain Syncer is a JS module which allows you to synchronize your app with any ethereum-compatible blockchain/contract state. Fast. Realtime. Reliable.


Install

Works only with ethers package, so don't forget to install it:

$ npm i chain-syncer ethers

Example usage

Using Ethers package:

const { ChainSyncer, InMemoryAdapter } = require('chain-syncer');

const default_adapter_which_you_need_to_change_to_any_other = new InMemoryAdapter();

const ethersjs_provider = new Ethers.providers.JsonRpcProvider('https://data-seed-prebsc-1-s1.binance.org:8545'); // BSC testnet rpc

const contracts = {
  'Items': {
    abi: [ /* ... */ ],
    network: {
      address: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56', 
      deployed_transaction: '0x0f01fc521030f178115c880e200b09a40c9510f49de227aa880276f92670a3d6'
    }
  }
}

const syncer = new ChainSyncer(default_adapter_which_you_need_to_change_to_any_other, {

  tick_interval: 3000,
  
  query_block_limit: 1000,
  
  verbose: true,
  
  block_time: 3500,
  
  ethers_provider: ethersjs_provider,
  
  async contractsGetter(contract_name) {
    const contract = contracts[contract_name];
    return {
      inst: new Ethers.Contract(contract.network.address, contract.abi, ethersjs_provider),
      deployed_transaction_hash: contract.network.deployed_transaction,
    };
  },
});

syncer.start();

syncer.on('Items.Transfer#default-stream', async (
  from, 
  to, 
  token_id, 
  { global_index, from_address, block_number, block_timestamp, transaction_hash }
) => {

  // global_index is a uniq id of event which is created from block number and logIndex padded with zeros

  const item = await Item.findOne({ _id: token_id });

  if(!item) { // postpone until item created
    return false;
  }

  item.owner = to;
  item.updatedAt = new Date(block_timestamp * 1000);
  await item.save();
  
  // Best practise is doing something like that, so you are sure that you have the latest state of 'owner' field
  //
  // await Item.updateOne({
  //   _id: token_id,
  //   'syncdata.owner': { $lt: global_index }
  // }, {
  //   'syncdata.owner': global_index,
  //   owner: to,
  // })
  
  // you can notify user that he has new items
}));

API

constructor(adapter, options)

Name Description Required Example
adapter An adapter interface for storing event data. As a test you can use built-in InMemoryAdapter, but better build your own adapter to any DB. required new InMemoryAdapter()
options An options object required -
options.tick_interval determinates how often will process unprocessed events optional (default: 2000) 3000 (every 3 seconds)
options.query_block_limit Maximum amount of blocks that can be scanned per tick. For example official BSC RPC allows up to 2000 blocks per request. optional (default: 100) 2000
options.query_unprocessed_events_limit Maximum amount of events that can be scanned per tick optional (default: 100) 5000
options.verbose A flag which enables debug mode and logging optional (default: false) true
options.mode Module mode. Possible: 'events' or 'processing' or 'universal'. 'events' mode only scans events without processing. 'processing' mode is only processing new events. 'universal' doing both. optional (default: 'universal') 'processing'
options.block_time Block time of a network you are working with. For example 3500 for BSC. required 3500 (BSC network)
options.ethers_provider Ethers.js provider required new Ethers.providers.JsonRpcProvider('https://data-seed-prebsc-1-s1.binance.org:8545')
options.contractsGetter An async function that returns object with ethers.js contract instance and tx hash of its deploy required async () => ({ inst: new Ethers.Contract(contracts[contract_name].network.address, contracts[contract_name].abi, ethersjs_provider), deployed_transaction_hash: contracts[contract_name].network.deployed_transaction })

on(stream_name, listener)

Name Description Required Example
stream_name Steam name is a string which contains contract, event and stream id (actually just id of this listener if you have microservices for example) required 'Items.Transfer#default-stream'
listener Listener function, last argument is always object of event parameters. If false returned from listener - event will be postponed till next processing tick required async ({ global_index, from_address, block_number, block_timestamp, transaction_hash }) => { ... }

start()

Starts scanner and processor


License

Chain Syncer is released under the MIT license. © 2022 Miroslaw Shpak

You might also like...

A fast & reliable transaction API for web3 Games, Bridges and other projects

Gelato Relay SDK SDK to integrate into Gelato Multichain Relay Table of Contents Installation Introduction Quick Start Payment Types Request Types Sen

Dec 31, 2022

An ERC-721 like NFT contract with Plutus scripts and Lucid as off-chain framework

Gatsby minimal TypeScript starter 🚀 Quick start Create a Gatsby site. Use the Gatsby CLI to create a new site, specifying the minimal TypeScript star

Sep 23, 2022

Ethereum chain sniperbot for tokens. This bot sniffs the mempool for pending transactions for trading enabled and also liquidity add functions.

Ethereum chain sniperbot for tokens. This bot sniffs the mempool for pending transactions for trading enabled and also liquidity add functions.

Dec 5, 2022

A tiny JavaScript library to easily toggle the state of any HTML element in any contexts, and create UI components in no time.

A tiny JavaScript library to easily toggle the state of any HTML element in any contexts, and create UI components in no time.

A tiny JavaScript library to easily toggle the state of any HTML element in any contexts, and create UI components in no time. Dropdown, navigation bu

Nov 25, 2022

Your Ethereum control panel. Interact with smart contracts on Ethereum.

etherfunk Your Ethereum control panel. Interact with smart contracts on Ethereum. 👉 https://etherfunk.io 👈 Devleopment First, run the development se

Sep 24, 2022

This is a Blockchain contract app built with solidity, ethersjs, nodejs, and the hardhart library. Connects to metamask as well.

This is a Blockchain contract app built with solidity, ethersjs, nodejs, and the hardhart library. Connects to metamask as well.

Dribble - Hardtjs, Etherjs, Metamask Project About Dribble is my first blockchain, web 3.0 application that you could use to deposit ethereum into a w

Jun 17, 2022

This is a Blockchain contract app built with solidity, ethersjs, nodejs, and the hardhart library. Connects to metamask as well.

This is a Blockchain contract app built with solidity, ethersjs, nodejs, and the hardhart library. Connects to metamask as well.

Dribble - Hardtjs, Etherjs, Metamask Project About Dribble is my first blockchain, web 3.0 application that you could use to deposit ethereum into a w

May 9, 2022

Multi-chain sniper bot to buy and sell tokens on ETH compatible chains. Features include instant or mempool sniping, rug protection, and sell management.

Multi-chain sniper bot to buy and sell tokens on ETH compatible chains. Features include instant or mempool sniping, rug protection, and sell management.

An open-source defi sniper. defi-sniper is free to download. NEW Community telegram group: https://t.me/+aBLUmP1UnypiNTVh Premium Services Now Availab

May 3, 2022

zkPoB is a mobile compatible tool that lets anyone prove they own a Bufficorn (or any NFT) without revealing which Buffi they own or the address they are verifying themselves with

zkPoB is a mobile compatible tool that lets anyone prove they own a Bufficorn (or any NFT) without revealing which Buffi they own or the address they are verifying themselves with

zkPoB is a mobile compatible tool that lets anyone prove they own a Bufficorn (or any NFT) without revealing which Buffi they own or the address they are verifying themselves with

Aug 25, 2022
Comments
  • Error in safe tick TypeError: Cannot read properties of undefined

    Error in safe tick TypeError: Cannot read properties of undefined

    Little bit modified your example for readme:

    const { ChainSyncer, InMemoryAdapter } = require('chain-syncer');
    const ethers = require('ethers');
    const ERC20ABI = require('./ERC20ABI.json');
    
    const default_adapter_which_you_need_to_change_to_any_other = new InMemoryAdapter();
    
    // const ethersjs_provider = new ethers.providers.JsonRpcProvider('https://data-seed-prebsc-1-s1.binance.org:8545'); // BSC testnet rpc
    const ethersjs_provider = new ethers.providers.JsonRpcProvider('https://bsc-dataseed.binance.org/'); // BSC prod rpc
    
    const contracts = {
        'BUSD': {
            abi: ERC20ABI,
            network: {
                address: '0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56',
                deployed_transaction: '0x0f01fc521030f178115c880e200b09a40c9510f49de227aa880276f92670a3d6'
            }
        }
    }
    
    const syncer = new ChainSyncer(default_adapter_which_you_need_to_change_to_any_other, {
        tick_interval: 3000,
        query_block_limit: 1000,
        verbose: true,
        block_time: 3500,
        ethers_provider: ethersjs_provider,
        async contractsGetter(contract_name) {
            const contract = contracts[contract_name];
            return {
                inst: new ethers.Contract(contract.network.address, contract.abi, ethersjs_provider),
                deployed_transaction_hash: contract.network.deployed_transaction,
            };
        },
    });
    
    syncer.start();
    
    syncer.on('BUSD.Transfer#default-stream', async (
        from,
        to,
        token_id,
        { global_index, from_address, block_number, block_timestamp, transaction_hash }
    ) => {
        console.log(`${block_number} ${transaction_hash}`)
    }); 
    

    OUTPUT:

    $ node index.js
    [MAXBLOCK: 18309565] Defualt tick ...  7 events added
    124241 0x0f01fc521030f178115c880e200b09a40c9510f49de227aa880276f92670a3d6
    124446 0xacce20b2c723babf6a6fa760bf3b0cd980532b8d8c0c38388e52b08d13466d9f
    125086 0x02c23aabff5fcbf043992a50a2618e1c9182b02118b96378966746081d0c1dd1
    getTransaction error in 0x76c32a63ced1fdf09f2a8dd03495b3bf94d37951a46c22e7284d1ac916a1528c tx
    getTransaction error in 0x53753bef87dc1f8ca76de33de41ade5047e485694bed9076b48045e42dd25176 tx
    Event has no tx, trying to fetch again (problem with RPC)
    Error in safe tick TypeError: Cannot read properties of undefined (reading 'from')
        at O.v (/home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:7906)
        at /home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:9333
        at Array.map (<anonymous>)
        at /home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:9307
        at Array.map (<anonymous>)
        at O.<anonymous> (/home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:9274)
        at d (/home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:1230)
        at Generator._invoke (/home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:983)
        at Generator.next (/home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:1593)
        at u (/home/piron/Desktop/chain-syncer-app/node_modules/chain-syncer/dist/chain-syncer.umd.min.js:3:6468)
    
    opened by gfijrb 2
Owner
Miroslaw Shpak
CTO at @worldofdefish
Miroslaw Shpak
On-chain snapshots of the whole blockchain state

?? Snapshop ?? Snapshop is a tool for creating on-chain snapshots of the whole blockchain state. It lets your smart contracts read the storage of any

Igor Żuk 56 Sep 26, 2022
A module federation SDK which is unrelated to tool chain for module consumer.

hel-micro, 模块联邦sdk化,免构建、热更新、工具链无关的微模块方案 Demo hel-loadash codesandbox hel-loadash git Why hel-micro 如何使用远程模块 仅需要一句npm命令即可载入远程模块,查看下面例子线上示例 1 安装hel-micr

腾讯TNTWeb前端团队 319 Jan 3, 2023
An Ethereum-compatible blockchain with a giant capacity for storage

goliath The Goliath blockchain is an Ethereum L2 with a giant capacity. For devs, it means you'll never need another chain. No bridges, no new languag

Liam Zebedee 17 Dec 23, 2022
A small and simple stress testing tool for Ethereum-compatible blockchain networks

Overview pandoras-box is a small transaction stress testing tool, part of any Ethereum client developer's toolkit. It is made for Ethereum-compatible

Trapesys 6 Aug 30, 2022
Connect your Ethereum smart contract to any real world API using the oracle pattern!

Minimal Viable Oracle (MVO) - An effective way to Build your own oracle with Solidity Smart contracts cannot access off-chain data directly. This repo

Noah 9 Aug 25, 2022
Script to synchronize between a Notion database and Google Calendar both ways. Uses Google App Script.

Yet Another Two Way Notion-Google Calendar Sync Script A script to sync events between Google calendar and a Notion database. Features! Google App Scr

kat 41 Jan 7, 2023
Lucid is a library, which allows you to create Cardano transactions and off-chain code for your Plutus contracts in JavaScript and Node.js.

Lucid is a library, which allows you to create Cardano transactions and off-chain code for your Plutus contracts in JavaScript and Node.js.

Berry 243 Jan 8, 2023
Synchronize multiple Pi-hole instances

Orbital Sync Orbital Sync synchronizes multiple Pi-hole instances for high availability (HA) using the built-in "teleporter". In other words, it perfo

Matt Webb 32 Dec 30, 2022
The node module that allows you to control your Ethereum revocation lists & resolve revocation keys.

Ethereum Revocation Registry Controller The controller module for interacting with EIP-5539-compatible Ethereum revocation lists. Motivation The EIP-5

spherity 4 Sep 27, 2022
Pull a smart contract from mainnet onto your local chain.

hardhat-copy hardhat-copy helps you import an Ethereum mainnet smart contract onto your local Hardhat node, enabling you to rapidly experiment with pr

Alexander Thomas 6 Aug 21, 2022