Join our webinar on Wednesday, June 26, at 1pm EDTHow Chia Mitigates Risk in the Crypto Industry.Register
Socket
Socket
Sign inDemoInstall

@bitski/provider-engine

Package Overview
Dependencies
126
Maintainers
3
Versions
29
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.4.2 to 0.5.0

dist/util/block-tracker.d.ts

14

dist/provider-engine.d.ts

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

import PollingBlockTracker from 'eth-block-tracker';
import BaseProvider, { JSONRPCRequest, JSONRPCResponse, JSONRPCResponseHandler } from './base-provider';
import { default as Subprovider } from './subprovider';
import BlockTracker, { BufferBlock } from './util/block-tracker';
import Stoplight from './util/stoplight';

@@ -11,10 +11,7 @@ export interface ProviderEngineOptions {

export default class Web3ProviderEngine extends BaseProvider {
currentBlock: any;
currentBlockNumber?: string;
protected _blockTracker: PollingBlockTracker;
currentBlock?: BufferBlock;
protected _blockTracker: BlockTracker;
protected _ready: Stoplight;
protected _providers: Subprovider[];
protected _running: boolean;
private blockTimeout;
private maxBlockRetries;
constructor(opts?: ProviderEngineOptions);

@@ -28,6 +25,3 @@ isRunning(): boolean;

protected sendPayload(payload: JSONRPCRequest): Promise<JSONRPCResponse>;
protected loadBlock(blockNumber: string, callCount?: number): void;
protected updateBlock(block: any): void;
protected _getBlockByNumber(blockNumber: any): Promise<JSONRPCResponse>;
protected _setCurrentBlock(block: any): void;
protected _setCurrentBlock(bufferBlock: BufferBlock): void;
}

@@ -20,6 +20,4 @@ "use strict";

var eachSeries_1 = __importDefault(require("async/eachSeries"));
var eth_block_tracker_1 = __importDefault(require("eth-block-tracker"));
var base_provider_1 = __importDefault(require("./base-provider"));
var create_payload_1 = require("./util/create-payload");
var eth_util_1 = require("./util/eth-util");
var block_tracker_1 = __importDefault(require("./util/block-tracker"));
var stoplight_1 = __importDefault(require("./util/stoplight"));

@@ -31,6 +29,2 @@ var Web3ProviderEngine = /** @class */ (function (_super) {

_this._running = false;
// Number of milliseconds to wait before retrying
_this.blockTimeout = 300;
// Maximum attempts to load a block
_this.maxBlockRetries = 3;
_this.setMaxListeners(30);

@@ -50,11 +44,14 @@ // parse options

var blockTrackerProvider = opts.blockTrackerProvider || directProvider;
_this._blockTracker = opts.blockTracker || new eth_block_tracker_1.default({
_this._blockTracker = new block_tracker_1.default({
provider: blockTrackerProvider,
blockTracker: opts.blockTracker,
pollingInterval: opts.pollingInterval || 4000,
setSkipCacheFlag: true,
});
_this._blockTracker.on('block', _this._setCurrentBlock.bind(_this));
_this._blockTracker.on('sync', _this.emit.bind(_this, 'sync'));
_this._blockTracker.on('rawBlock', _this.emit.bind(_this, 'rawBlock'));
_this._blockTracker.on('latest', _this.emit.bind(_this, 'latest'));
_this._blockTracker.on('error', _this.emit.bind(_this, 'error'));
// set initialization blocker
_this._ready = new stoplight_1.default();
// local state
_this.currentBlock = null;
_this._providers = [];

@@ -67,13 +64,6 @@ return _this;

Web3ProviderEngine.prototype.start = function () {
var _this = this;
// trigger start
this._ready.go();
// on new block, request block body and emit as events
this._blockTracker.on('latest', function (blockNumber) {
_this.currentBlockNumber = blockNumber;
_this.loadBlock(blockNumber);
});
// forward other events
this._blockTracker.on('sync', this.emit.bind(this, 'sync'));
this._blockTracker.on('error', this.emit.bind(this, 'error'));
// start tracking blocks
this._blockTracker.start();
// update state

@@ -85,4 +75,4 @@ this._running = true;

Web3ProviderEngine.prototype.stop = function () {
// stop block polling by removing event listeners
this._blockTracker.removeAllListeners();
// stop block tracking
this._blockTracker.stop();
// update state

@@ -177,68 +167,8 @@ this._running = false;

};
// Tries to get the block payload recursively
Web3ProviderEngine.prototype.loadBlock = function (blockNumber, callCount) {
var _this = this;
if (callCount === void 0) { callCount = 0; }
this._getBlockByNumber(blockNumber).then(function (blockResponse) {
// Result can be null if the block hasn't fully propagated to the nodes
if (blockResponse.result) {
_this.updateBlock(blockResponse.result);
}
else if (callCount < _this.maxBlockRetries && blockNumber === _this.currentBlockNumber) {
// Only call recursively if the current block number is still the same
// and if we are under the retry limit.
setTimeout(function () {
_this.loadBlock(blockNumber, callCount + 1);
}, _this.blockTimeout);
}
else {
throw new Error("Could not load block " + blockNumber + " after 3 tries");
}
}).catch(function (err) {
_this.emit('error', err);
});
Web3ProviderEngine.prototype._setCurrentBlock = function (bufferBlock) {
this.currentBlock = bufferBlock;
this.emit('block', bufferBlock);
};
// Parse the block into a buffer representation and update subscribers.
Web3ProviderEngine.prototype.updateBlock = function (block) {
var bufferBlock = toBufferBlock(block);
// set current + emit "block" event
this._setCurrentBlock(bufferBlock);
// emit other events
this.emit('rawBlock', block);
this.emit('latest', block);
};
Web3ProviderEngine.prototype._getBlockByNumber = function (blockNumber) {
var req = create_payload_1.createPayload({ method: 'eth_getBlockByNumber', params: [blockNumber, false], skipCache: true });
return this.sendPayload(req);
};
Web3ProviderEngine.prototype._setCurrentBlock = function (block) {
this.currentBlock = block;
this.emit('block', block);
};
return Web3ProviderEngine;
}(base_provider_1.default));
exports.default = Web3ProviderEngine;
// util
function toBufferBlock(jsonBlock) {
return {
number: eth_util_1.toBuffer(jsonBlock.number),
hash: eth_util_1.toBuffer(jsonBlock.hash),
parentHash: eth_util_1.toBuffer(jsonBlock.parentHash),
nonce: eth_util_1.toBuffer(jsonBlock.nonce),
mixHash: eth_util_1.toBuffer(jsonBlock.mixHash),
sha3Uncles: eth_util_1.toBuffer(jsonBlock.sha3Uncles),
logsBloom: eth_util_1.toBuffer(jsonBlock.logsBloom),
transactionsRoot: eth_util_1.toBuffer(jsonBlock.transactionsRoot),
stateRoot: eth_util_1.toBuffer(jsonBlock.stateRoot),
receiptsRoot: eth_util_1.toBuffer(jsonBlock.receiptRoot || jsonBlock.receiptsRoot),
miner: eth_util_1.toBuffer(jsonBlock.miner),
difficulty: eth_util_1.toBuffer(jsonBlock.difficulty),
totalDifficulty: eth_util_1.toBuffer(jsonBlock.totalDifficulty),
size: eth_util_1.toBuffer(jsonBlock.size),
extraData: eth_util_1.toBuffer(jsonBlock.extraData),
gasLimit: eth_util_1.toBuffer(jsonBlock.gasLimit),
gasUsed: eth_util_1.toBuffer(jsonBlock.gasUsed),
timestamp: eth_util_1.toBuffer(jsonBlock.timestamp),
transactions: jsonBlock.transactions,
};
}

@@ -5,2 +5,3 @@ /// <reference types="node" />

import { default as Web3ProviderEngine } from './provider-engine';
import { BufferBlock } from './util/block-tracker';
export declare type NextHandler = (cb?: SubproviderNextCallback) => void;

@@ -11,3 +12,3 @@ export declare type CompletionHandler = (error: Error | null, result?: any) => void;

protected engine?: Web3ProviderEngine;
protected currentBlock?: any;
protected currentBlock?: BufferBlock;
setEngine(engine: Web3ProviderEngine): void;

@@ -14,0 +15,0 @@ abstract handleRequest(payload: JSONRPCRequest, next: NextHandler, end: CompletionHandler): void;

{
"name": "@bitski/provider-engine",
"version": "0.4.2",
"version": "0.5.0",
"description": "",

@@ -5,0 +5,0 @@ "repository": "https://github.com/BitskiCo/provider-engine",

@@ -1,8 +0,28 @@

# Web3 ProviderEngine
# Bitski ProviderEngine
[![Greenkeeper badge](https://badges.greenkeeper.io/MetaMask/provider-engine.svg)](https://greenkeeper.io/)
Bitski's ProviderEngine is a refactored version of Metamask's original provider engine library. This is the base of the Bitski Javascript SDKs (both browser and node).
Web3 ProviderEngine is a tool for composing your own [web3 providers](https://github.com/ethereum/wiki/wiki/JavaScript-API#web3).
### Installation
`npm install @bitski/provider-engine`
### Differences from original package
- Written in Typescript
- Standard ES6 modules, designed for the browser first
- Designed to be extended with a properly exported Subprovider interface
- Base class implements new EthereumProvider standard
- Compatible with latest versions of web3.js
- Heavier dependencies removed to keep base package light (primarily all dependencies that rely on elliptic)
- Many small bug fixes and improvements
### To Do
- Reimplement HookedWalletSubprovider as a separate package
- Reimplement VmSubprovider as a separate package
- Reimplement NonceTracker as a separate package
- Improve test coverage
---
### Composable

@@ -16,13 +36,12 @@

```js
const ProviderEngine = require('web3-provider-engine')
const CacheSubprovider = require('web3-provider-engine/subproviders/cache.js')
const FixtureSubprovider = require('web3-provider-engine/subproviders/fixture.js')
const FilterSubprovider = require('web3-provider-engine/subproviders/filters.js')
const VmSubprovider = require('web3-provider-engine/subproviders/vm.js')
const HookedWalletSubprovider = require('web3-provider-engine/subproviders/hooked-wallet.js')
const NonceSubprovider = require('web3-provider-engine/subproviders/nonce-tracker.js')
const RpcSubprovider = require('web3-provider-engine/subproviders/rpc.js')
import {
default as ProviderEngine,
CacheSubprovider,
FixtureSubprovider,
FilterSubprovider,
FetchSubprovider
} from '@bitski/provider-engine';
var engine = new ProviderEngine()
var web3 = new Web3(engine)
const engine = new ProviderEngine();
const web3 = new Web3(engine);

@@ -36,176 +55,61 @@ // static results

eth_syncing: true,
}))
}));
// cache layer
engine.addProvider(new CacheSubprovider())
engine.addProvider(new CacheSubprovider());
// filters
engine.addProvider(new FilterSubprovider())
engine.addProvider(new FilterSubprovider());
// pending nonce
engine.addProvider(new NonceSubprovider())
// vm
engine.addProvider(new VmSubprovider())
// id mgmt
engine.addProvider(new HookedWalletSubprovider({
getAccounts: function(cb){ ... },
approveTransaction: function(cb){ ... },
signTransaction: function(cb){ ... },
}))
// data source
engine.addProvider(new RpcSubprovider({
engine.addProvider(new FetchSubprovider({
rpcUrl: 'https://testrpc.metamask.io/',
}))
}));
// log new blocks
engine.on('block', function(block){
engine.on('block', (block) => {
console.log('================================')
console.log('BLOCK CHANGED:', '#'+block.number.toString('hex'), '0x'+block.hash.toString('hex'))
console.log('================================')
})
});
// network connectivity error
engine.on('error', function(err){
engine.on('error', (err) => {
// report connectivity errors
console.error(err.stack)
})
console.error(err.stack);
});
// start polling for blocks
engine.start()
engine.start();
```
When importing in webpack:
```js
import * as Web3ProviderEngine from 'web3-provider-engine';
import * as RpcSource from 'web3-provider-engine/subproviders/rpc';
import * as HookedWalletSubprovider from 'web3-provider-engine/subproviders/hooked-wallet';
```
### Built For Zero-Clients
### Writing your own Subprovider
The [Ethereum JSON RPC](https://github.com/ethereum/wiki/wiki/JSON-RPC) was not designed to have one node service many clients.
However a smaller, lighter subset of the JSON RPC can be used to provide the blockchain data that an Ethereum 'zero-client' node would need to function.
We handle as many types of requests locally as possible, and just let data lookups fallback to some data source ( hosted rpc, blockchain api, etc ).
Categorically, we don’t want / can’t have the following types of RPC calls go to the network:
* id mgmt + tx signing (requires private data)
* filters (requires a stateful data api)
* vm (expensive, hard to scale)
It's easy to extend the functionality of this module by writing your own Subprovider instance.
### Change Log
See [src/subprovider.ts](/src/subprovider.ts) for the full interface.
##### 14.0.0
```typescript
import { Subprovider } from '@bitski/provider-engine';
- default dataProvider for zero is Infura mainnet REST api
- websocket support
- subscriptions support
- remove solc subprovider
- removed `dist` from git (but published in npm module)
- es5 builds in `dist/es5`
- zero + ProviderEngine bundles are es5
- web3 subprovider renamed to provider subprovider
- error if provider subprovider is missing a proper provider
- removed need to supply getAccounts hook
- fixed `hooked-wallet-ethtx` message signing
- fixed `hooked-wallet` default txParams
export default class MySubprovider extends Subprovider {
##### 13.0.0
// Only requirement is to implement handleRequest
public handleRequest(payload, next, end) {
// The payload includes the original JSON RPC request
if (payload.method === 'eth_helloWorld') {
// Call end() to handle the request in this subprovider
end('hello world!');
} else {
// Call next() to fall-through to the next request in the stack
next();
}
}
- txs included in blocks via [`eth-block-tracker`](https://github.com/kumavis/eth-block-tracker)@2.0.0
}
```
##### 12.0.0
### Acknowlegements
- moved block polling to [`eth-block-tracker`](https://github.com/kumavis/eth-block-tracker).
##### 11.0.0
- zero.js - replaced http subprovider with fetch provider (includes polyfill for node).
##### 10.0.0
- renamed HookedWalletSubprovider `personalRecoverSigner` to `recoverPersonalSignature`
##### 9.0.0
- `pollingShouldUnref` option now defaults to false
### Current RPC method support:
##### static
- [x] web3_clientVersion
- [x] net_version
- [x] net_listening
- [x] net_peerCount
- [x] eth_protocolVersion
- [x] eth_hashrate
- [x] eth_mining
- [x] eth_syncing
##### filters
- [x] eth_newBlockFilter
- [x] eth_newPendingTransactionFilter
- [x] eth_newFilter
- [x] eth_uninstallFilter
- [x] eth_getFilterLogs
- [x] eth_getFilterChanges
##### accounts manager
- [x] eth_coinbase
- [x] eth_accounts
- [x] eth_sendTransaction
- [x] eth_sign
- [x] [eth_signTypedData](https://github.com/ethereum/EIPs/pull/712)
##### vm
- [x] eth_call
- [x] eth_estimateGas
##### db source
- [ ] db_putString
- [ ] db_getString
- [ ] db_putHex
- [ ] db_getHex
##### compiler
- [ ] eth_getCompilers
- [ ] eth_compileLLL
- [ ] eth_compileSerpent
- [ ] eth_compileSolidity
##### shh gateway
- [ ] shh_version
- [ ] shh_post
- [ ] shh_newIdentity
- [ ] shh_hasIdentity
- [ ] shh_newGroup
- [ ] shh_addToGroup
##### data source ( fallback to rpc )
* eth_gasPrice
* eth_blockNumber
* eth_getBalance
* eth_getBlockByHash
* eth_getBlockByNumber
* eth_getBlockTransactionCountByHash
* eth_getBlockTransactionCountByNumber
* eth_getCode
* eth_getStorageAt
* eth_getTransactionByBlockHashAndIndex
* eth_getTransactionByBlockNumberAndIndex
* eth_getTransactionByHash
* eth_getTransactionCount
* eth_getTransactionReceipt
* eth_getUncleByBlockHashAndIndex
* eth_getUncleByBlockNumberAndIndex
* eth_getUncleCountByBlockHash
* eth_getUncleCountByBlockNumber
* eth_sendRawTransaction
* eth_getLogs ( not used in web3.js )
##### ( not supported )
* eth_getWork
* eth_submitWork
* eth_submitHashrate ( not used in web3.js )
A special thanks to the folks at Metamask who conceived and wrote the original library.
import eachSeries from 'async/eachSeries';
import PollingBlockTracker from 'eth-block-tracker';
import BaseProvider, { JSONRPCRequest, JSONRPCResponse, JSONRPCResponseHandler } from './base-provider';
import { default as Subprovider, SubproviderNextCallback } from './subprovider';
import { createPayload } from './util/create-payload';
import { toBuffer } from './util/eth-util';
import BlockTracker, { BufferBlock } from './util/block-tracker';
import Stoplight from './util/stoplight';

@@ -17,8 +15,5 @@

public currentBlock: any;
public currentBlock?: BufferBlock;
// The latest block number we have received
public currentBlockNumber?: string;
protected _blockTracker: PollingBlockTracker;
protected _blockTracker: BlockTracker;
protected _ready: Stoplight;

@@ -28,8 +23,2 @@ protected _providers: Subprovider[];

// Number of milliseconds to wait before retrying
private blockTimeout = 300;
// Maximum attempts to load a block
private maxBlockRetries = 3;
constructor(opts?: ProviderEngineOptions) {

@@ -40,2 +29,3 @@ super();

opts = opts || {};
// block polling

@@ -51,14 +41,18 @@ const directProvider = {

};
const blockTrackerProvider = opts.blockTrackerProvider || directProvider;
this._blockTracker = opts.blockTracker || new PollingBlockTracker({
this._blockTracker = new BlockTracker({
provider: blockTrackerProvider,
blockTracker: opts.blockTracker,
pollingInterval: opts.pollingInterval || 4000,
setSkipCacheFlag: true,
});
this._blockTracker.on('block', this._setCurrentBlock.bind(this));
this._blockTracker.on('sync', this.emit.bind(this, 'sync'));
this._blockTracker.on('rawBlock', this.emit.bind(this, 'rawBlock'));
this._blockTracker.on('latest', this.emit.bind(this, 'latest'));
this._blockTracker.on('error', this.emit.bind(this, 'error'));
// set initialization blocker
this._ready = new Stoplight();
// local state
this.currentBlock = null;
this._providers = [];

@@ -74,13 +68,4 @@ }

this._ready.go();
// on new block, request block body and emit as events
this._blockTracker.on('latest', (blockNumber) => {
this.currentBlockNumber = blockNumber;
this.loadBlock(blockNumber);
});
// forward other events
this._blockTracker.on('sync', this.emit.bind(this, 'sync'));
this._blockTracker.on('error', this.emit.bind(this, 'error'));
// start tracking blocks
this._blockTracker.start();
// update state

@@ -93,4 +78,4 @@ this._running = true;

public stop() {
// stop block polling by removing event listeners
this._blockTracker.removeAllListeners();
// stop block tracking
this._blockTracker.stop();
// update state

@@ -192,68 +177,7 @@ this._running = false;

// Tries to get the block payload recursively
protected loadBlock(blockNumber: string, callCount: number = 0) {
this._getBlockByNumber(blockNumber).then((blockResponse) => {
// Result can be null if the block hasn't fully propagated to the nodes
if (blockResponse.result) {
this.updateBlock(blockResponse.result);
} else if (callCount < this.maxBlockRetries && blockNumber === this.currentBlockNumber) {
// Only call recursively if the current block number is still the same
// and if we are under the retry limit.
setTimeout(() => {
this.loadBlock(blockNumber, callCount + 1);
}, this.blockTimeout);
} else {
throw new Error(`Could not load block ${blockNumber} after 3 tries`);
}
}).catch((err) => {
this.emit('error', err);
});
protected _setCurrentBlock(bufferBlock: BufferBlock) {
this.currentBlock = bufferBlock;
this.emit('block', bufferBlock);
}
// Parse the block into a buffer representation and update subscribers.
protected updateBlock(block: any) {
const bufferBlock = toBufferBlock(block);
// set current + emit "block" event
this._setCurrentBlock(bufferBlock);
// emit other events
this.emit('rawBlock', block);
this.emit('latest', block);
}
protected _getBlockByNumber(blockNumber): Promise<JSONRPCResponse> {
const req = createPayload({ method: 'eth_getBlockByNumber', params: [blockNumber, false], skipCache: true });
return this.sendPayload(req);
}
protected _setCurrentBlock(block) {
this.currentBlock = block;
this.emit('block', block);
}
}
// util
function toBufferBlock(jsonBlock) {
return {
number: toBuffer(jsonBlock.number),
hash: toBuffer(jsonBlock.hash),
parentHash: toBuffer(jsonBlock.parentHash),
nonce: toBuffer(jsonBlock.nonce),
mixHash: toBuffer(jsonBlock.mixHash),
sha3Uncles: toBuffer(jsonBlock.sha3Uncles),
logsBloom: toBuffer(jsonBlock.logsBloom),
transactionsRoot: toBuffer(jsonBlock.transactionsRoot),
stateRoot: toBuffer(jsonBlock.stateRoot),
receiptsRoot: toBuffer(jsonBlock.receiptRoot || jsonBlock.receiptsRoot),
miner: toBuffer(jsonBlock.miner),
difficulty: toBuffer(jsonBlock.difficulty),
totalDifficulty: toBuffer(jsonBlock.totalDifficulty),
size: toBuffer(jsonBlock.size),
extraData: toBuffer(jsonBlock.extraData),
gasLimit: toBuffer(jsonBlock.gasLimit),
gasUsed: toBuffer(jsonBlock.gasUsed),
timestamp: toBuffer(jsonBlock.timestamp),
transactions: jsonBlock.transactions,
};
}
import { EventEmitter } from 'events';
import { JSONRPCRequest, JSONRPCResponseHandler } from '.';
import { default as Web3ProviderEngine } from './provider-engine';
import { BufferBlock } from './util/block-tracker';
import { createPayload } from './util/create-payload';

@@ -21,3 +22,3 @@

protected engine?: Web3ProviderEngine;
protected currentBlock?: any;
protected currentBlock?: BufferBlock;

@@ -24,0 +25,0 @@ public setEngine(engine: Web3ProviderEngine) {

@@ -160,3 +160,3 @@ // tslint:disable: max-line-length

// This is necessary to ensure we get the block we just created above
testMeta.engine._blockTracker.checkForLatestBlock().then(() => {
testMeta.engine._blockTracker.fetchLatest().then(() => {
cb();

@@ -163,0 +163,0 @@ });

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc