@parity/api
Version:
The Parity Promise-based API library for interfacing with Ethereum over RPC
231 lines (182 loc) • 5.6 kB
JavaScript
// Copyright 2015-2019 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
const EventEmitter = require('eventemitter3');
const Contract = require('./contract');
const Providers = require('./provider');
const Transports = require('./transport');
const { Db, Eth, Parity, Net, Personal, Private, Shell, Shh, Signer, Trace, Web3 } = require('./rpc');
const Subscriptions = require('./subscriptions');
const Pubsub = require('./pubsub');
const util = require('./util');
const { isFunction } = require('./util/types');
class Api extends EventEmitter {
constructor (provider, allowSubscriptions = true, middlewareClass) {
super();
if (!provider) {
throw new Error('Provider needs to be supplied to Api instance');
}
if (isFunction(provider.sendAsync)) {
provider = new Providers.Current(provider);
} else if (!isFunction(provider.send)) {
console.warn(
new Error('deprecated: Api needs provider with send() function, old-style Transport found instead'),
provider
);
}
this._provider = new Providers.PromiseProvider(provider);
this._provider.on('connected', () => this.emit('connected'));
this._provider.on('connecting', () => this.emit('connecting'));
this._provider.on('disconnected', () => this.emit('disconnected'));
this._db = new Db(this._provider);
this._eth = new Eth(this._provider);
this._net = new Net(this._provider);
this._parity = new Parity(this._provider);
this._personal = new Personal(this._provider);
this._private = new Private(this._provider);
this._shell = new Shell(this._provider);
this._shh = new Shh(this._provider);
this._signer = new Signer(this._provider);
this._trace = new Trace(this._provider);
this._web3 = new Web3(this._provider);
// FIXME: Remove, convert to shell
if (middlewareClass) {
const middleware = this.parity
.nodeKind()
.then(nodeKind => {
if (nodeKind.availability === 'public') {
return middlewareClass;
}
return null;
})
.catch(() => null);
provider.addMiddleware(middleware);
}
if (provider && isFunction(provider.subscribe)) {
this._pubsub = new Pubsub(provider);
}
if (allowSubscriptions) {
this._subscriptions = new Subscriptions(this);
}
}
get isConnected () {
const isConnected = this.provider.isConnected;
return isConnected || typeof isConnected === 'undefined';
}
get isPubSub () {
return !!this._pubsub;
}
get pubsub () {
if (!this.isPubSub) {
throw Error('Pubsub is only available with a subscribing-supported transport injected!');
}
return this._pubsub;
}
get db () {
return this._db;
}
get eth () {
return this._eth;
}
get parity () {
return this._parity;
}
get net () {
return this._net;
}
get personal () {
return this._personal;
}
get private () {
return this._private;
}
get provider () {
return this._provider.provider;
}
get shell () {
return this._shell;
}
get shh () {
return this._shh;
}
get signer () {
return this._signer;
}
get trace () {
return this._trace;
}
get transport () {
return this.provider;
}
get web3 () {
return this._web3;
}
get util () {
return util;
}
newContract (abi, address) {
return new Contract(this, abi).at(address);
}
subscribe (subscriptionName, callback) {
if (!this._subscriptions) {
return Promise.resolve(1);
}
return this._subscriptions.subscribe(subscriptionName, callback);
}
unsubscribe (subscriptionId) {
if (!this._subscriptions) {
return Promise.resolve(true);
}
return this._subscriptions.unsubscribe(subscriptionId);
}
pollMethod (method, input, validate) {
const [_group, endpoint] = method.split('_');
const group = `_${_group}`;
return new Promise((resolve, reject) => {
const timeout = () => {
this[group][endpoint](input)
.then(result => {
if (validate ? validate(result) : result) {
resolve(result);
} else {
setTimeout(timeout, 500);
}
})
.catch(error => {
// Don't print if the request is rejected: that's ok
if (error.type !== 'REQUEST_REJECTED') {
console.error('pollMethod', error);
}
reject(error);
});
};
timeout();
});
}
}
Api.util = util;
Api.Provider = {
Current: Providers.Current,
Ipc: Providers.Ipc,
Http: Providers.Http,
PostMessage: Providers.PostMessage,
SendAsync: Providers.SendAsync,
Ws: Providers.Ws,
WsSecure: Providers.WsSecure
};
// NOTE: kept for backwards compatibility
Api.Transport = {
Http: Transports.Http,
Ws: Transports.Ws,
WsSecure: Transports.WsSecure
};
module.exports = Api;