New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

demux

Package Overview
Dependencies
Maintainers
3
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

demux - npm Package Compare versions

Comparing version 3.1.4-fd42365.0 to 4.0.0

dist/AbstractActionHandler.js.map

25

dist/AbstractActionHandler.d.ts

@@ -1,3 +0,3 @@

import * as Logger from "bunyan";
import { Block, HandlerVersion, IndexState, NextBlock, VersionedAction } from "./interfaces";
import * as Logger from 'bunyan';
import { Block, HandlerInfo, HandlerVersion, IndexState, NextBlock, VersionedAction } from './interfaces';
/**

@@ -11,6 +11,7 @@ * Takes `block`s output from implementations of `AbstractActionReader` and processes their actions through the

export declare abstract class AbstractActionHandler {
protected lastProcessedBlockNumber: number;
protected lastProcessedBlockHash: string;
protected handlerVersionName: string;
lastProcessedBlockNumber: number;
lastProcessedBlockHash: string;
handlerVersionName: string;
protected log: Logger;
protected initialized: boolean;
private deferredEffects;

@@ -28,2 +29,10 @@ private handlerVersionMap;

/**
* Information about the current state of the Action Handler
*/
readonly info: HandlerInfo;
/**
* Performs all required initialization for the handler.
*/
initialize(): Promise<void>;
/**
* Updates the `lastProcessedBlockNumber` and `lastProcessedBlockHash` meta state, coinciding with the block

@@ -47,2 +56,6 @@ * that has just been processed. These are the same values read by `updateIndexState()`.

/**
* Idempotently performs any required setup.
*/
protected abstract setup(): Promise<void>;
/**
* This method is used when matching the types of incoming actions against the types the `Updater`s and `Effect`s are

@@ -79,2 +92,3 @@ * subscribed to. When this returns true, their corresponding functions will run.

protected handleActions(state: any, context: any, nextBlock: NextBlock, isReplay: boolean): Promise<void>;
private handleRollback;
private range;

@@ -84,2 +98,3 @@ private runOrDeferEffect;

private getNextDeferredBlockNumber;
private rollbackDeferredEffects;
private initHandlerVersions;

@@ -86,0 +101,0 @@ private refreshIndexState;

85

dist/AbstractActionHandler.js

@@ -19,2 +19,3 @@ "use strict";

const Logger = __importStar(require("bunyan"));
const errors_1 = require("./errors");
/**

@@ -34,8 +35,9 @@ * Takes `block`s output from implementations of `AbstractActionReader` and processes their actions through the

this.lastProcessedBlockNumber = 0;
this.lastProcessedBlockHash = "";
this.handlerVersionName = "v1";
this.lastProcessedBlockHash = '';
this.handlerVersionName = 'v1';
this.initialized = false;
this.deferredEffects = {};
this.handlerVersionMap = {};
this.initHandlerVersions(handlerVersions);
this.log = Logger.createLogger({ name: "demux" });
this.log = Logger.createLogger({ name: 'demux' });
}

@@ -50,12 +52,7 @@ /**

const { isRollback, isEarliestBlock } = blockMeta;
if (isRollback || (isReplay && isEarliestBlock)) {
const rollbackBlockNumber = blockInfo.blockNumber - 1;
const rollbackCount = this.lastProcessedBlockNumber - rollbackBlockNumber;
this.log.info(`Rolling back ${rollbackCount} blocks to block ${rollbackBlockNumber}...`);
yield this.rollbackTo(rollbackBlockNumber);
yield this.refreshIndexState();
if (!this.initialized) {
yield this.initialize();
this.initialized = true;
}
else if (this.lastProcessedBlockNumber === 0 && this.lastProcessedBlockHash === "") {
yield this.refreshIndexState();
}
yield this.handleRollback(isRollback, blockInfo.blockNumber, isReplay, isEarliestBlock);
const nextBlockNeeded = this.lastProcessedBlockNumber + 1;

@@ -78,3 +75,4 @@ // Just processed this block; skip

if (blockInfo.previousBlockHash !== this.lastProcessedBlockHash) {
throw Error("Block hashes do not match; block not part of current chain.");
const err = new errors_1.MismatchedBlockHashError();
throw err;
}

@@ -90,2 +88,21 @@ }

/**
* Information about the current state of the Action Handler
*/
get info() {
return {
lastProcessedBlockNumber: this.lastProcessedBlockNumber,
lastProcessedBlockHash: this.lastProcessedBlockHash,
handlerVersionName: this.handlerVersionName,
};
}
/**
* Performs all required initialization for the handler.
*/
initialize() {
return __awaiter(this, void 0, void 0, function* () {
yield this.setup();
yield this.refreshIndexState();
});
}
/**
* This method is used when matching the types of incoming actions against the types the `Updater`s and `Effect`s are

@@ -169,2 +186,17 @@ * subscribed to. When this returns true, their corresponding functions will run.

}
handleRollback(isRollback, blockNumber, isReplay, isEarliestBlock) {
return __awaiter(this, void 0, void 0, function* () {
if (isRollback || (isReplay && isEarliestBlock)) {
const rollbackBlockNumber = blockNumber - 1;
const rollbackCount = this.lastProcessedBlockNumber - rollbackBlockNumber;
this.log.info(`Rolling back ${rollbackCount} blocks to block ${rollbackBlockNumber}...`);
yield this.rollbackTo(rollbackBlockNumber);
this.rollbackDeferredEffects(blockNumber);
yield this.refreshIndexState();
}
else if (this.lastProcessedBlockNumber === 0 && this.lastProcessedBlockHash === '') {
yield this.refreshIndexState();
}
});
}
range(start, end) {

@@ -175,2 +207,3 @@ return Array(end - start).fill(0).map((_, i) => i + start);

const { block, lastIrreversibleBlockNumber } = nextBlock;
const { blockNumber } = block.blockInfo;
const shouldRunImmediately = (!effect.deferUntilIrreversible || block.blockInfo.blockNumber <= lastIrreversibleBlockNumber);

@@ -180,7 +213,7 @@ if (shouldRunImmediately) {

}
else if (!this.deferredEffects[block.blockInfo.blockNumber]) {
this.deferredEffects[block.blockInfo.blockNumber] = [() => effect.run(payload, block, context)];
}
else {
this.deferredEffects[block.blockInfo.blockNumber].push(() => effect.run(payload, block, context));
if (!this.deferredEffects[blockNumber]) {
this.deferredEffects[blockNumber] = [];
}
this.deferredEffects[blockNumber].push(() => effect.run(payload, block, context));
}

@@ -195,3 +228,4 @@ }

if (this.deferredEffects[blockNumber]) {
for (const deferredEffect of this.deferredEffects[blockNumber]) {
const effects = this.deferredEffects[blockNumber];
for (const deferredEffect of effects) {
deferredEffect();

@@ -210,10 +244,16 @@ }

}
rollbackDeferredEffects(rollbackTo) {
const blockNumbers = Object.keys(this.deferredEffects).map((num) => parseInt(num, 10));
const toRollBack = blockNumbers.filter((bn) => bn >= rollbackTo);
for (const blockNumber of toRollBack) {
delete this.deferredEffects[blockNumber];
}
}
initHandlerVersions(handlerVersions) {
if (handlerVersions.length === 0) {
throw new Error("Must have at least one handler version.");
throw new errors_1.MissingHandlerVersionError();
}
for (const handlerVersion of handlerVersions) {
if (this.handlerVersionMap.hasOwnProperty(handlerVersion.versionName)) {
throw new Error(`Handler version name '${handlerVersion.versionName}' already exists. ` +
"Handler versions must have unique names.");
throw new errors_1.DuplicateHandlerVersionError(handlerVersion.versionName);
}

@@ -226,3 +266,3 @@ this.handlerVersionMap[handlerVersion.versionName] = handlerVersion;

}
else if (handlerVersions[0].versionName !== "v1") {
else if (handlerVersions[0].versionName !== 'v1') {
this.warnIncorrectFirstHandler(handlerVersions[0].versionName);

@@ -262,1 +302,2 @@ }

exports.AbstractActionHandler = AbstractActionHandler;
//# sourceMappingURL=AbstractActionHandler.js.map

@@ -1,3 +0,3 @@

import * as Logger from "bunyan";
import { ActionReaderOptions, Block, NextBlock } from "./interfaces";
import * as Logger from 'bunyan';
import { ActionReaderOptions, Block, NextBlock, ReaderInfo } from './interfaces';
/**

@@ -15,3 +15,3 @@ * Reads blocks from a blockchain, outputting normalized `Block` objects.

protected log: Logger;
private initialized;
protected initialized: boolean;
constructor(options?: ActionReaderOptions);

@@ -41,2 +41,6 @@ /**

/**
* Performs all required initialization for the reader.
*/
initialize(): Promise<void>;
/**
* Changes the state of the `AbstractActionReader` instance to have just processed the block at the given block

@@ -50,2 +54,10 @@ * number. If the block exists in its temporary block history, it will use this, otherwise it will fetch the block

/**
* Information about the current state of the Action Reader
*/
readonly info: ReaderInfo;
/**
* Idempotently performs any required setup.
*/
protected abstract setup(): Promise<void>;
/**
* Incrementally rolls back reader state one block at a time, comparing the blockHistory with

@@ -52,0 +64,0 @@ * newly fetched blocks. Fork resolution is finished when either the current block's previous hash

@@ -19,7 +19,8 @@ "use strict";

const Logger = __importStar(require("bunyan"));
const errors_1 = require("./errors");
const defaultBlock = {
blockInfo: {
blockNumber: 0,
blockHash: "",
previousBlockHash: "",
blockHash: '',
previousBlockHash: '',
timestamp: new Date(0),

@@ -43,3 +44,3 @@ },

this.onlyIrreversible = optionsWithDefaults.onlyIrreversible;
this.log = Logger.createLogger({ name: "demux" });
this.log = Logger.createLogger({ name: 'demux' });
}

@@ -60,6 +61,5 @@ /**

};
// TODO: Should this only be called when updating headBlockNumber?
this.lastIrreversibleBlockNumber = yield this.getLastIrreversibleBlockNumber();
if (!this.initialized) {
yield this.initBlockState();
yield this.initialize();
}

@@ -97,2 +97,12 @@ if (this.currentBlockNumber === this.headBlockNumber) {

/**
* Performs all required initialization for the reader.
*/
initialize() {
return __awaiter(this, void 0, void 0, function* () {
yield this.setup();
yield this.initBlockState();
this.initialized = true;
});
}
/**
* Changes the state of the `AbstractActionReader` instance to have just processed the block at the given block

@@ -108,6 +118,6 @@ * number. If the block exists in its temporary block history, it will use this, otherwise it will fetch the block

if (blockNumber < this.startAtBlock) {
throw new Error("Cannot seek to block before configured `startAtBlock` number.");
throw new errors_1.ImproperStartAtBlockError();
}
if (blockNumber > this.headBlockNumber) {
throw new Error(`Cannot seek to block number ${blockNumber} as it does not exist yet.`);
throw new errors_1.ImproperSeekToBlockError(blockNumber);
}

@@ -119,2 +129,14 @@ this.currentBlockNumber = blockNumber - 1;

/**
* Information about the current state of the Action Reader
*/
get info() {
return {
currentBlockNumber: this.currentBlockNumber,
startAtBlock: this.startAtBlock,
headBlockNumber: this.headBlockNumber,
onlyIrreversible: this.onlyIrreversible,
lastIrreversibleBlockNumber: this.lastIrreversibleBlockNumber,
};
}
/**
* Incrementally rolls back reader state one block at a time, comparing the blockHistory with

@@ -155,2 +177,3 @@ * newly fetched blocks. Fork resolution is finished when either the current block's previous hash

return __awaiter(this, void 0, void 0, function* () {
this.lastIrreversibleBlockNumber = yield this.getLastIrreversibleBlockNumber();
this.headBlockNumber = yield this.getLatestNeededBlockNumber();

@@ -162,3 +185,2 @@ if (this.currentBlockNumber < 0) {

yield this.reloadHistory();
this.initialized = true;
});

@@ -240,3 +262,3 @@ }

if (tryCount === maxTries) {
throw new Error("Could not reload history.");
throw new errors_1.ReloadHistoryError();
}

@@ -250,3 +272,3 @@ }

if (this.currentBlockData.blockInfo.blockNumber < this.lastIrreversibleBlockNumber && checkIrreversiblility) {
throw new Error("Last irreversible block has been passed without resolving fork");
throw new errors_1.UnresolvedForkError();
}

@@ -257,3 +279,3 @@ this.blockHistory.push(yield this.getBlock(this.currentBlockData.blockInfo.blockNumber - 1));

logForkDetected(unvalidatedBlockData, expectedHash, actualHash) {
this.log.info("!! FORK DETECTED !!");
this.log.info('!! FORK DETECTED !!');
this.log.info(` MISMATCH:`);

@@ -264,9 +286,9 @@ this.log.info(` ✓ NEW Block ${unvalidatedBlockData.blockInfo.blockNumber} previous: ${actualHash}`);

logForkResolved(currentBlockInfo, previousBlockInfo) {
this.log.info(" MATCH:");
this.log.info(' MATCH:');
this.log.info(` ✓ NEW Block ${currentBlockInfo.blockNumber} previous: ${currentBlockInfo.previousBlockHash}`); // tslint:disable-line
this.log.info(` ✓ OLD Block ${previousBlockInfo.blockNumber} id: ${previousBlockInfo.blockHash}`);
this.log.info("!! FORK RESOLVED !!");
this.log.info('!! FORK RESOLVED !!');
}
logForkMismatch(currentBlockInfo, previousBlockInfo) {
this.log.info(" MISMATCH:");
this.log.info(' MISMATCH:');
this.log.info(` ✓ NEW Block ${currentBlockInfo.blockNumber} previous: ${currentBlockInfo.previousBlockHash}`);

@@ -277,1 +299,2 @@ this.log.info(` ✕ OLD Block ${previousBlockInfo.blockNumber} id: ${previousBlockInfo.blockHash}`);

exports.AbstractActionReader = AbstractActionReader;
//# sourceMappingURL=AbstractActionReader.js.map

@@ -1,3 +0,5 @@

import { AbstractActionHandler } from "./AbstractActionHandler";
import { AbstractActionReader } from "./AbstractActionReader";
import * as Logger from 'bunyan';
import { AbstractActionHandler } from './AbstractActionHandler';
import { AbstractActionReader } from './AbstractActionReader';
import { DemuxInfo } from './interfaces';
/**

@@ -16,2 +18,7 @@ * Coordinates implementations of `AbstractActionReader`s and `AbstractActionHandler`s in

*/
protected log: Logger;
private running;
private shouldPause;
private error;
private clean;
constructor(actionReader: AbstractActionReader, actionHandler: AbstractActionHandler, pollInterval: number);

@@ -24,8 +31,25 @@ /**

* Start a polling loop
*
* @param isReplay Set to true to disable Effects from running until caught up with head block.
*/
watch(isReplay?: boolean): Promise<void>;
/**
* Start or resume indexing.
*/
start(): boolean;
/**
* Suspend indexing. Will go into effect after the currently-processing block.
*/
pause(): boolean;
/**
* Information about the current state of Demux
*/
readonly info: DemuxInfo;
/**
* Use the actionReader and actionHandler to process new blocks.
*
* @param isReplay Set to true to disable Effects from running until caught up with head block.
*/
protected checkForBlocks(isReplay?: boolean): Promise<void>;
private readonly status;
}

@@ -10,3 +10,12 @@ "use strict";

};
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
const Logger = __importStar(require("bunyan"));
const interfaces_1 = require("./interfaces");
/**

@@ -17,7 +26,2 @@ * Coordinates implementations of `AbstractActionReader`s and `AbstractActionHandler`s in

class BaseActionWatcher {
/**
* @param actionReader An instance of an implemented `AbstractActionReader`
* @param actionHandler An instance of an implemented `AbstractActionHandler`
* @param pollInterval Number of milliseconds between each polling loop iteration
*/
constructor(actionReader, actionHandler, pollInterval) {

@@ -27,2 +31,7 @@ this.actionReader = actionReader;

this.pollInterval = pollInterval;
this.running = false;
this.shouldPause = false;
this.error = null;
this.clean = true;
this.log = Logger.createLogger({ name: 'demux' });
}

@@ -39,8 +48,29 @@ /**

* Start a polling loop
*
* @param isReplay Set to true to disable Effects from running until caught up with head block.
*/
watch(isReplay = false) {
return __awaiter(this, void 0, void 0, function* () {
const startTime = new Date().getTime();
yield this.checkForBlocks(isReplay);
const endTime = new Date().getTime();
if (this.shouldPause) {
this.running = false;
this.shouldPause = false;
this.log.info('Indexing paused.');
return;
}
this.clean = false;
this.running = true;
this.error = null;
const startTime = Date.now();
try {
yield this.checkForBlocks(isReplay);
}
catch (err) {
this.running = false;
this.shouldPause = false;
this.log.error(err);
this.error = err;
this.log.info('Indexing unexpectedly paused due to an error.');
return;
}
const endTime = Date.now();
const duration = endTime - startTime;

@@ -55,3 +85,44 @@ let waitTime = this.pollInterval - duration;

/**
* Start or resume indexing.
*/
start() {
if (this.running) {
this.log.info('Cannot start; already indexing.');
return false;
}
this.log.info('Starting indexing.');
// tslint:disable-next-line:no-floating-promises
this.watch();
return true;
}
/**
* Suspend indexing. Will go into effect after the currently-processing block.
*/
pause() {
if (!this.running) {
this.log.info('Cannot pause; not currently indexing.');
return false;
}
this.log.info('Pausing indexing.');
this.shouldPause = true;
return true;
}
/**
* Information about the current state of Demux
*/
get info() {
const info = {
handler: this.actionHandler.info,
reader: this.actionReader.info,
indexingStatus: this.status,
};
if (this.error) {
info.error = this.error;
}
return info;
}
/**
* Use the actionReader and actionHandler to process new blocks.
*
* @param isReplay Set to true to disable Effects from running until caught up with head block.
*/

@@ -62,2 +133,5 @@ checkForBlocks(isReplay = false) {

while (!headBlockNumber || this.actionReader.currentBlockNumber < headBlockNumber) {
if (this.shouldPause) {
return;
}
const nextBlock = yield this.actionReader.getNextBlock();

@@ -69,3 +143,3 @@ if (!nextBlock.blockMeta.isNewBlock) {

if (nextBlockNumberNeeded) {
yield this.actionReader.seekToBlock(nextBlockNumberNeeded - 1);
yield this.actionReader.seekToBlock(nextBlockNumberNeeded);
}

@@ -76,3 +150,19 @@ headBlockNumber = this.actionReader.headBlockNumber;

}
get status() {
if (this.clean) {
return interfaces_1.IndexingStatus.Initial;
}
if (this.running && !this.shouldPause) {
return interfaces_1.IndexingStatus.Indexing;
}
if (this.running && this.shouldPause) {
return interfaces_1.IndexingStatus.Pausing;
}
if (this.error) {
return interfaces_1.IndexingStatus.Stopped;
}
return interfaces_1.IndexingStatus.Paused;
}
}
exports.BaseActionWatcher = BaseActionWatcher;
//# sourceMappingURL=BaseActionWatcher.js.map

@@ -1,4 +0,6 @@

export { Action, Block, BlockInfo, Effect, HandlerVersion, IndexState, Updater } from "./interfaces";
export { AbstractActionHandler } from "./AbstractActionHandler";
export { AbstractActionReader } from "./AbstractActionReader";
export { BaseActionWatcher } from "./BaseActionWatcher";
export { AbstractActionHandler } from './AbstractActionHandler';
export { AbstractActionReader } from './AbstractActionReader';
export { BaseActionWatcher } from './BaseActionWatcher';
export { ExpressActionWatcher } from './ExpressActionWatcher';
export * from './interfaces';
export * from './errors';
"use strict";
function __export(m) {
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];
}
Object.defineProperty(exports, "__esModule", { value: true });

@@ -9,1 +12,6 @@ var AbstractActionHandler_1 = require("./AbstractActionHandler");

exports.BaseActionWatcher = BaseActionWatcher_1.BaseActionWatcher;
var ExpressActionWatcher_1 = require("./ExpressActionWatcher");
exports.ExpressActionWatcher = ExpressActionWatcher_1.ExpressActionWatcher;
__export(require("./interfaces"));
__export(require("./errors"));
//# sourceMappingURL=index.js.map

@@ -15,7 +15,2 @@ export interface ActionReaderOptions {

onlyIrreversible?: boolean;
/**
* This determines how many blocks in the past are cached. This is used for determining
* block validity during both normal operation and when rolling back.
*/
maxHistoryLength?: number;
}

@@ -79,1 +74,26 @@ export interface Block {

}
export interface HandlerInfo {
lastProcessedBlockNumber: number;
lastProcessedBlockHash: string;
handlerVersionName: string;
}
export interface ReaderInfo {
currentBlockNumber: number;
startAtBlock: number;
headBlockNumber: number;
onlyIrreversible: boolean;
lastIrreversibleBlockNumber: number;
}
export declare enum IndexingStatus {
Initial = "initial",
Indexing = "indexing",
Pausing = "pausing",
Paused = "paused",
Stopped = "stopped"
}
export interface DemuxInfo {
indexingStatus: IndexingStatus;
error?: Error;
handler: HandlerInfo;
reader: ReaderInfo;
}
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var IndexingStatus;
(function (IndexingStatus) {
IndexingStatus["Initial"] = "initial";
IndexingStatus["Indexing"] = "indexing";
IndexingStatus["Pausing"] = "pausing";
IndexingStatus["Paused"] = "paused";
IndexingStatus["Stopped"] = "stopped";
})(IndexingStatus = exports.IndexingStatus || (exports.IndexingStatus = {}));
//# sourceMappingURL=interfaces.js.map
{
"name": "demux",
"version": "3.1.4-fd42365.0",
"version": "4.0.0",
"author": {

@@ -14,11 +14,15 @@ "name": "Julien Heller",

"devDependencies": {
"@blockone/tslint-config-blockone": "^2.0.0",
"@types/bunyan": "^1.8.5",
"@types/express": "^4.16.0",
"@types/jest": "^23.1.4",
"@types/node": "^10.5.1",
"@types/request-promise-native": "^1.0.15",
"@types/supertest": "^2.0.7",
"eslint": "^4.9.0",
"eslint-config-airbnb-base": "12.1.0",
"eslint-plugin-import": "^2.7.0",
"jest": "^22.4.3",
"jest": "^23.6.0",
"release-it": "^7.5.0",
"supertest": "^3.4.1",
"ts-jest": "^23.0.0",

@@ -30,10 +34,13 @@ "tslint": "^5.10.0",

},
"dependencies": {
"bunyan": "1.8.12",
"express": "4.16.4"
},
"scripts": {
"build": "tsc",
"compile": "tsc",
"watch": "tsc -w",
"example": "./run-example.sh",
"build": "rm -rf dist/* && tsc",
"build-docs": "./scripts/build-docs.sh",
"build-all": "rm -rf dist/* && tsc && ./scripts/build-docs.sh",
"example": "./scripts/run-example.sh",
"lint": "tslint -c tslint.json -p tsconfig.json",
"test": "jest",
"build-docs": "./build-docs.sh",
"test": "jest --detectOpenHandles --maxWorkers=2",
"current-version": "echo $npm_package_version"

@@ -57,6 +64,3 @@ },

"testEnvironment": "node"
},
"dependencies": {
"bunyan": "^1.8.12"
}
}

@@ -86,2 +86,4 @@ # demux-js [![Build Status](https://travis-ci.org/EOSIO/demux-js.svg?branch=develop)](https://travis-ci.org/EOSIO/demux-js)

* [**`ExpressActionWatcher`**](https://eosio.github.io/demux-js/classes/expressactionwatcher.html): Exposes the API methods from the BaseActionWatcher through an Express server
In order to process actions, we need the following things:

@@ -95,9 +97,46 @@

- Instantiate the implemented `AbstractActionReader` with any needed configuration
- Instantiate the implemented `AbstractActionHandler`, passing in the `HandlerVersion` and any other needed configuration
- Instantiate the implemented `AbstractActionReader` with any needed configuration
- Instantiate a `BaseActionWatcher`, passing in the above Handler and Reader instances
- Call `watch()` on the Watcher
- 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
```javascript
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
```javascript
const watcher = new BaseActionWatcher(
actionReader,
actionHandler,
pollInterval,
)
watcher.watch()
```
Or,
```javascript
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**](https://eosio.github.io/demux-js/)
### [Learn from a full example](examples/eos-transfers)
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc