npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

edemux

v4.0.2

Published

Deterministic event-sourced state and side effect handling for blockchain applications

Downloads

2

Readme

demux-js Build Status

Demux is a backend infrastructure pattern for sourcing blockchain events to deterministically update queryable datastores and trigger side effects. This library serves as a reference implementation of that pattern for use with Node applications.

Installation

# Using yarn
yarn add demux

# Using npm
npm install demux --save

Overview

Taking inspiration from the Flux Architecture pattern and Redux, Demux was born out of the following qualifications:

  1. A separation of concerns between how state exists on the blockchain and how it is queried by the client front-end
  2. Client front-end not solely responsible for determining derived, reduced, and/or accumulated state
  3. Ability for blockchain events to trigger new transactions, as well as other side effects outside of the blockchain
  4. The blockchain as the single source of truth for all application state

Separated Persistence Layer

Storing data in indexed state on blockchains can be useful for three reasons: decentralized consensus of computation results, usage of state from within other blockchain computations, and for retrieval of state for use in client front-ends. When building more complicated front-ends, you run into a few problems when retrieving directly from indexed blockchain state:

  • The query interface used to retrieve the indexed data is limited. Complex data requirements can mean you either have to make an excess number of queries and process the data on the client, or you must store additional derivative data on the blockchain itself.
  • Scaling your query load means creating more blockchain endpoint nodes, which can be very expensive.

Demux solves these problems by off-loading queries to any persistence layer that you want. As blockchain events happen, your chosen persistence layer is updated by updater functions, which deterministically process an array of Action objects. The persistence layer can then be queried by your front-end through a suitable API (for example, REST or GraphQL).

This means that we can separate our concerns: for data that needs decentralized consensus of computation or access from other blockchain events, we can still store the data in indexed blockchain state, without having to worry about tailoring to front-end queries. For data required by our front-end, we can pre-process and index data in a way that makes it easy for it to be queried, in a horizontally scalable persistence layer of our choice. The end result is that both systems can serve their purpose more effectively.

Side Effects

Since we have a system for acting upon specific blockchain events deterministically, we can utilize this system to manage non-deterministic events as well. These effect functions work almost exactly the same as updater functions, except they run asynchronously, are not run during replays, and modifying the deterministic datastore is off-limits. Examples include: signing and broadcasting a transaction, sending an email, and initiating a traditional fiat payment.

Single Source of Truth

There are other solutions to the above problems that involve legacy persistence layers that are their own sources of truth. By deriving all state from the blockchain, however, we gain the following benefits:

  • If the accumulated datastore is lost or deleted, it may be regenerated by replaying blockchain actions
  • As long as application code is open source, and the blockchain is public, all application state can be audited
  • No need to maintain multiple ways of updating state (submitting transactions is the sole way)

Data Flow

  1. Client sends transaction to blockchain
  2. Action Watcher invokes Action Reader to check for new blocks
  3. Action Reader sees transaction in new block, parses actions
  4. Action Watcher sends actions to Action Handler
  5. Action Handler processes actions through Updaters and Effects
  6. Actions run their corresponding Updaters, updating the state of the Datastore
  7. Actions run their corresponding Effects, triggering external events
  8. Client queries API for updated data

Class Implementations

Repository | Description ---|--- EOSIO / demux-js-eos * | Action Reader implementations for EOSIO blockchains EOSIO / demux-js-postgres * | Action Handler implementation for Postgres databases Zapata / demux-js-bitshares | Action Reader implementations for BitShares blockchain

* Officially supported by Block.one

To get your project listed, add it here and submit a PR!

Usage

This library provides the following classes:

In order to process actions, we need the following things:

  • An implementation of an AbstractActionReader
  • An implementation of an AbstractActionHandler
  • At least one HandlerVersion, which contain Updater and Effect arrays

After we have these things, we need to:

  • Instantiate the implemented AbstractActionReader with any needed configuration
  • Instantiate the implemented AbstractActionHandler, passing in the HandlerVersion and any other needed configuration
  • Instantiate the BaseActionWatcher (or a subclass), passing in the Action Handler and Action Watcher instances
  • Start indexing via the Action Watcher's watch() method (by either calling it directly or otherwise)

Example

const { BaseActionWatcher, ExpressActionWatcher } = require("demux")
const { MyActionReader } = require("./MyActionReader")
const { MyActionHandler } = require("./MyActionHandler")
const { handlerVersions } = require("./handlerVersions")
const { readerConfig, handlerConfig, pollInterval, portNumber } = require("./config")

const actionReader = new MyActionReader(readerConfig)
const actioHandler = new MyActionHandler(handlerVersions, handlerConfig)

Then, either

const watcher = new BaseActionWatcher(
  actionReader,
  actionHandler,
  pollInterval,
)

watcher.watch()

Or,

const expressWatcher = new ExpressActionWatcher(
  actionReader,
  actionHandler,
  pollInterval,
  portNumber,
)

expressWatcher.listen()

// You can then make a POST request to `/start` on your configured endpoint

API documentation

Learn from a full example