Tests still warn because of old provider in some tests
This commit is contained in:
commit
76f0247f5d
@ -22,6 +22,7 @@ import { Http as HttpTransport, WsSecure as WsSecureTransport } from './transpor
|
||||
|
||||
import { Db, Eth, Parity, Net, Personal, Shh, Signer, Trace, Web3 } from './rpc';
|
||||
import Subscriptions from './subscriptions';
|
||||
import Pubsub from './pubsub';
|
||||
import util from './util';
|
||||
import { isFunction } from './util/types';
|
||||
|
||||
@ -32,9 +33,15 @@ export default class Api extends EventEmitter {
|
||||
super();
|
||||
|
||||
if (!provider || !isFunction(provider.send)) {
|
||||
console.log(provider);
|
||||
console.warn(new Error('deprecated: Api needs provider with send() function, old-style Transport found instead'));
|
||||
}
|
||||
|
||||
// does use new provider interface (not promiseProvider)
|
||||
if (provider && isFunction(provider.subscribe)) {
|
||||
this._pubsub = new Pubsub(provider);
|
||||
}
|
||||
|
||||
this._provider = new PromiseProvider(provider);
|
||||
|
||||
this._db = new Db(this._provider);
|
||||
@ -50,7 +57,6 @@ export default class Api extends EventEmitter {
|
||||
if (allowSubscriptions) {
|
||||
this._subscriptions = new Subscriptions(this);
|
||||
}
|
||||
|
||||
// Doing a request here in test env would cause an error
|
||||
if (LocalAccountsMiddleware && process.env.NODE_ENV !== 'test') {
|
||||
const middleware = this.parity
|
||||
@ -68,6 +74,13 @@ export default class Api extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
get pubsub () {
|
||||
if (!this._pubsub) {
|
||||
throw Error('Pubsub is only available with a subscribing-supported transport injected!');
|
||||
}
|
||||
return this._pubsub;
|
||||
}
|
||||
|
||||
get db () {
|
||||
return this._db;
|
||||
}
|
||||
|
227
js/src/api/pubsub/eth/eth.js
Normal file
227
js/src/api/pubsub/eth/eth.js
Normal file
@ -0,0 +1,227 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
import PubsubBase from '../pubsubBase';
|
||||
|
||||
import { inAddress, inBlockNumber, inHex, inNumber16, inOptions, inFilter } from '../../format/input';
|
||||
import { outAddress, outBlock, outNumber, outTransaction, outSyncing, outReceipt, outLog } from '../../format/output';
|
||||
|
||||
export default class Eth extends PubsubBase {
|
||||
constructor (provider) {
|
||||
super(provider);
|
||||
this._api = 'parity';
|
||||
}
|
||||
|
||||
newHeads (callback) {
|
||||
return this.addListener('eth', 'newHeads', callback);
|
||||
}
|
||||
|
||||
logs (callback) {
|
||||
throw Error('not supported yet');
|
||||
}
|
||||
|
||||
// eth API
|
||||
protocolVersion (callback) {
|
||||
return this.addListener(this._api, 'eth_protocolVersion', callback);
|
||||
}
|
||||
|
||||
syncing (callback) {
|
||||
return this.addListener(this._api, 'eth_syncing', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outSyncing(data));
|
||||
});
|
||||
}
|
||||
|
||||
hashrate (callback) {
|
||||
return this.addListener(this._api, 'eth_hashrate', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
coinbase (callback) {
|
||||
return this.addListener(this._api, 'eth_coinbase', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
});
|
||||
}
|
||||
|
||||
mining (callback) {
|
||||
return this.addListener(this._api, 'eth_mining', callback);
|
||||
}
|
||||
|
||||
gasPrice (callback) {
|
||||
return this.addListener(this._api, 'eth_gasPrice', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
accounts (callback) {
|
||||
return this.addListener(this._api, 'eth_accounts', (error, accounts) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, (accounts || []).map(outAddress));
|
||||
});
|
||||
}
|
||||
|
||||
blockNumber (callback) {
|
||||
return this.addListener(this._api, 'eth_blockNumber', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
getBalance (callback, address, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_getBalance', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inAddress(address), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
getStorageAt (callback, address, index = 0, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_getStorageAt', callback, [inAddress(address), inNumber16(index), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
getBlockByHash (callback, hash, full = false) {
|
||||
return this.addListener(this._api, 'eth_getBlockByHash', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outBlock(data));
|
||||
}, [inHex(hash), full]);
|
||||
}
|
||||
|
||||
getBlockByNumber (callback, blockNumber = 'latest', full = false) {
|
||||
return this.addListener(this._api, 'eth_getBlockByNumber', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outBlock(data));
|
||||
}, [inBlockNumber(blockNumber), full]);
|
||||
}
|
||||
|
||||
getTransactionCount (callback, address, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_getTransactionCount', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inAddress(address), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
getBlockTransactionCountByHash (callback, hash) {
|
||||
return this.addListener(this._api, 'eth_getBlockTransactionCountByHash', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inHex(hash)]);
|
||||
}
|
||||
|
||||
getBlockTransactionCountByNumber (callback, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_getBlockTransactionCountByNumber', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
getUncleCountByBlockHash (callback, hash) {
|
||||
return this.addListener(this._api, 'eth_getUncleCountByBlockHash', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inHex(hash)]);
|
||||
}
|
||||
|
||||
getUncleCountByBlockNumber (callback, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_getUncleCountByBlockNumber', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
getCode (callback, address, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_getCode', callback, [inAddress(address), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
call (callback, options, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'eth_call', callback, [inOptions(options), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
estimateGas (callback, options) {
|
||||
return this.addListener(this._api, 'eth_estimateGas', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inOptions(options)]);
|
||||
}
|
||||
|
||||
getTransactionByHash (callback, hash) {
|
||||
return this.addListener(this._api, 'eth_getTransactionByHash', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outTransaction(data));
|
||||
}, [inHex(hash)]);
|
||||
}
|
||||
|
||||
getTransactionByBlockHashAndIndex (callback, hash, index = 0) {
|
||||
return this.addListener(this._api, 'eth_getTransactionByBlockHashAndIndex', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outTransaction(data));
|
||||
}, [inHex(hash), inNumber16(index)]);
|
||||
}
|
||||
|
||||
getTransactionByBlockNumberAndIndex (callback, blockNumber = 'latest', index = 0) {
|
||||
return this.addListener(this._api, 'eth_getTransactionByBlockNumberAndIndex', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outTransaction(data));
|
||||
}, [inBlockNumber(blockNumber), inNumber16(index)]);
|
||||
}
|
||||
|
||||
getTransactionReceipt (callback, txhash) {
|
||||
return this.addListener(this._api, 'eth_getTransactionReceipt', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outReceipt(data));
|
||||
}, [inHex(txhash)]);
|
||||
}
|
||||
|
||||
getUncleByBlockHashAndIndex (callback, hash, index = 0) {
|
||||
return this.addListener(this._api, 'eth_getUncleByBlockHashAndIndex', callback, [inHex(hash), inNumber16(index)]);
|
||||
}
|
||||
|
||||
getUncleByBlockNumberAndIndex (callback, blockNumber = 'latest', index = 0) {
|
||||
return this.addListener(this._api, 'eth_getUncleByBlockNumberAndIndex', callback, [inBlockNumber(blockNumber), inNumber16(index)]);
|
||||
}
|
||||
|
||||
getLogs (callback, options) {
|
||||
return this.addListener(this._api, 'eth_getLogs', (error, logs) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, (logs) => logs.map(outLog));
|
||||
}, [inFilter(options)]);
|
||||
}
|
||||
|
||||
getWork (callback) {
|
||||
return this.addListener(this._api, 'eth_getWork', callback);
|
||||
}
|
||||
}
|
16
js/src/api/pubsub/eth/index.js
Normal file
16
js/src/api/pubsub/eth/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
export default from './eth';
|
16
js/src/api/pubsub/index.js
Normal file
16
js/src/api/pubsub/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
export default from './pubsub';
|
16
js/src/api/pubsub/net/index.js
Normal file
16
js/src/api/pubsub/net/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
export default from './net';
|
42
js/src/api/pubsub/net/net.js
Normal file
42
js/src/api/pubsub/net/net.js
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
import PubsubBase from '../pubsubBase';
|
||||
|
||||
import { outNumber } from '../../format/output';
|
||||
|
||||
export default class Net extends PubsubBase {
|
||||
constructor (provider) {
|
||||
super(provider);
|
||||
this._api = 'parity';
|
||||
}
|
||||
|
||||
// net API
|
||||
version (callback) {
|
||||
return this.addListener(this._api, 'net_version', callback);
|
||||
}
|
||||
|
||||
peerCount (callback) {
|
||||
return this.addListener(this._api, 'net_peerCount', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
listening (callback) {
|
||||
return this.addListener(this._api, 'net_listening', callback);
|
||||
}
|
||||
}
|
16
js/src/api/pubsub/parity/index.js
Normal file
16
js/src/api/pubsub/parity/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
export default from './parity';
|
355
js/src/api/pubsub/parity/parity.js
Normal file
355
js/src/api/pubsub/parity/parity.js
Normal file
@ -0,0 +1,355 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
|
||||
import PubsubBase from '../pubsubBase';
|
||||
import { inAddress, inBlockNumber, inData, inHex, inDeriveHash, inDeriveIndex } from '../../format/input';
|
||||
import { outAccountInfo, outAddress, outBlock, outChainStatus, outHistogram, outHwAccountInfo, outNodeKind, outNumber, outPeers, outTransaction, outAddresses, outRecentDapps, outVaultMeta } from '../../format/output';
|
||||
|
||||
export default class Parity extends PubsubBase {
|
||||
constructor (provider) {
|
||||
super(provider);
|
||||
this._api = 'parity';
|
||||
}
|
||||
|
||||
// parity API
|
||||
accountsInfo (callback) {
|
||||
return this.addListener(this._api, 'parity_accountsInfo', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAccountInfo(data));
|
||||
});
|
||||
}
|
||||
|
||||
hardwareAccountsInfo (callback) {
|
||||
return this.addListener(this._api, 'parity_hardwareAccountsInfo', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outHwAccountInfo(data));
|
||||
});
|
||||
}
|
||||
|
||||
defaultAccount (callback) {
|
||||
return this.addListener(this._api, 'parity_defaultAccount', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
});
|
||||
}
|
||||
|
||||
transactionsLimit (callback) {
|
||||
return this.addListener(this._api, 'parity_transactionsLimit', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
extraData (callback) {
|
||||
return this.addListener(this._api, 'parity_extraData', callback);
|
||||
}
|
||||
|
||||
gasFloorTarget (callback) {
|
||||
return this.addListener(this._api, 'parity_gasFloorTarget', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
gasCeilTarget (callback) {
|
||||
return this.addListener(this._api, 'parity_gasCeilTarget', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
minGasPrice (callback) {
|
||||
return this.addListener(this._api, 'parity_minGasPrice', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
devLogs (callback) {
|
||||
return this.addListener(this._api, 'parity_devLogs', callback);
|
||||
}
|
||||
|
||||
devLogsLevels (callback) {
|
||||
return this.addListener(this._api, 'parity_devLogsLevels', callback);
|
||||
}
|
||||
|
||||
netChain (callback) {
|
||||
return this.addListener(this._api, 'parity_netChain', callback);
|
||||
}
|
||||
|
||||
netPeers (callback) {
|
||||
return this.addListener(this._api, 'parity_netPeers', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outPeers(data));
|
||||
});
|
||||
}
|
||||
|
||||
netPort (callback) {
|
||||
return this.addListener(this._api, 'parity_netPort', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
rpcSettings (callback) {
|
||||
return this.addListener(this._api, 'parity_rpcSettings', callback);
|
||||
}
|
||||
|
||||
nodeName (callback) {
|
||||
return this.addListener(this._api, 'parity_nodeName', callback);
|
||||
}
|
||||
|
||||
defaultExtraData (callback) {
|
||||
return this.addListener(this._api, 'parity_defaultExtraData', callback);
|
||||
}
|
||||
|
||||
gasPriceHistogram (callback) {
|
||||
return this.addListener(this._api, 'parity_gasPriceHistogram', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outHistogram(data));
|
||||
});
|
||||
}
|
||||
|
||||
unsignedTransactionsCount (callback) {
|
||||
return this.addListener(this._api, 'parity_unsignedTransactionsCount', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
});
|
||||
}
|
||||
|
||||
registryAddress (callback) {
|
||||
return this.addListener(this._api, 'parity_registryAddress', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
});
|
||||
}
|
||||
|
||||
listAccounts (callback, count, offset = null, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'parity_listAccounts', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, (data) => (data || []).map(outAddress));
|
||||
}, [count, inAddress(offset), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
listStorageKeys (callback, address, count, hash = null, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'parity_listStorageKeys', callback, [inAddress(address), count, inHex(hash), inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
pendingTransactions (callback) {
|
||||
return this.addListener(this._api, 'parity_pendingTransactions', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outTransaction(data));
|
||||
});
|
||||
}
|
||||
|
||||
futureTransactions (callback) {
|
||||
return this.addListener(this._api, 'parity_futureTransactions', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outTransaction(data));
|
||||
});
|
||||
}
|
||||
|
||||
pendingTransactionsStats (callback) {
|
||||
return this.addListener(this._api, 'parity_pendingTransactionsStats', callback);
|
||||
}
|
||||
|
||||
localTransactions (callback) {
|
||||
return this.addListener(this._api, 'parity_localTransactions', (error, transactions) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, transactions => {
|
||||
Object.values(transactions)
|
||||
.filter(tx => tx.transaction)
|
||||
.map(tx => {
|
||||
tx.transaction = outTransaction(tx.transaction);
|
||||
});
|
||||
return transactions;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
dappsUrl (callback) {
|
||||
return this.addListener(this._api, 'parity_dappsUrl', callback);
|
||||
}
|
||||
|
||||
wsUrl (callback) {
|
||||
return this.addListener(this._api, 'parity_wsUrl', callback);
|
||||
}
|
||||
|
||||
nextNonce (callback, account) {
|
||||
return this.addListener(this._api, 'parity_nextNonce', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNumber(data));
|
||||
}, [inAddress(account)]);
|
||||
}
|
||||
|
||||
mode (callback) {
|
||||
return this.addListener(this._api, 'parity_mode', callback);
|
||||
}
|
||||
|
||||
chain (callback) {
|
||||
return this.addListener(this._api, 'parity_chain', callback);
|
||||
}
|
||||
|
||||
enode (callback) {
|
||||
return this.addListener(this._api, 'parity_enode', callback);
|
||||
}
|
||||
|
||||
consensusCapability (callback) {
|
||||
return this.addListener(this._api, 'parity_consensusCapability', callback);
|
||||
}
|
||||
|
||||
versionInfo (callback) {
|
||||
return this.addListener(this._api, 'parity_versionInfo', callback);
|
||||
}
|
||||
|
||||
releasesInfo (callback) {
|
||||
return this.addListener(this._api, 'parity_releasesInfo', callback);
|
||||
}
|
||||
|
||||
chainStatus (callback) {
|
||||
return this.addListener(this._api, 'parity_chainStatus', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outChainStatus(data));
|
||||
});
|
||||
}
|
||||
|
||||
nodeKind (callback) {
|
||||
return this.addListener(this._api, 'parity_nodeKind', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outNodeKind(data));
|
||||
});
|
||||
}
|
||||
|
||||
getBlockHeaderByNumber (callback, blockNumber = 'latest') {
|
||||
return this.addListener(this._api, 'parity_getBlockHeaderByNumber', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outBlock(data));
|
||||
}, [inBlockNumber(blockNumber)]);
|
||||
}
|
||||
|
||||
cidV0 (callback, data) {
|
||||
return this.addListener(this._api, 'parity_cidV0', callback, [inData(data)]);
|
||||
}
|
||||
|
||||
// parity accounts API (only secure API or configured to be exposed)
|
||||
allAccountsInfo (callback) {
|
||||
return this._addListener(this._api, 'parity_allAccountsInfo', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAccountInfo(data));
|
||||
});
|
||||
}
|
||||
|
||||
getDappAddresses (callback, dappId) {
|
||||
return this._addListener(this._api, 'parity_getDappAddresses', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddresses(data));
|
||||
}, [dappId]);
|
||||
}
|
||||
|
||||
getDappDefaultAddress (callback, dappId) {
|
||||
return this._addListener(this._api, 'parity_getDappDefaultAddress', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
}, [dappId]);
|
||||
}
|
||||
|
||||
getNewDappsAddresses (callback) {
|
||||
return this._addListener(this._api, 'parity_getDappDefaultAddress', (error, addresses) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, addresses ? addresses.map(outAddress) : null);
|
||||
});
|
||||
}
|
||||
|
||||
getNewDappsDefaultAddress (callback) {
|
||||
return this._addListener(this._api, 'parity_getNewDappsDefaultAddress', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
});
|
||||
}
|
||||
|
||||
listRecentDapps (callback) {
|
||||
return this._addListener(this._api, 'parity_listRecentDapps', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outRecentDapps(data));
|
||||
});
|
||||
}
|
||||
|
||||
listGethAccounts (callback) {
|
||||
return this._addListener(this._api, 'parity_listGethAccounts', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddresses(data));
|
||||
});
|
||||
}
|
||||
|
||||
listVaults (callback) {
|
||||
return this._addListener(this._api, 'parity_listVaults', callback);
|
||||
}
|
||||
|
||||
listOpenedVaults (callback) {
|
||||
return this._addListener(this._api, 'parity_listOpenedVaults', callback);
|
||||
}
|
||||
|
||||
getVaultMeta (callback, vaultName) {
|
||||
return this._addListener(this._api, 'parity_getVaultMeta', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outVaultMeta(data));
|
||||
}, [vaultName]);
|
||||
}
|
||||
|
||||
deriveAddressHash (callback, address, password, hash, shouldSave) {
|
||||
return this._addListener(this._api, 'parity_deriveAddressHash', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
}, [inAddress(address), password, inDeriveHash(hash), !!shouldSave]);
|
||||
}
|
||||
|
||||
deriveAddressIndex (callback, address, password, index, shouldSave) {
|
||||
return this._addListener(this._api, 'parity_deriveAddressIndex', (error, data) => {
|
||||
error
|
||||
? callback(error)
|
||||
: callback(null, outAddress(data));
|
||||
}, [inAddress(address), password, inDeriveIndex(index), !!shouldSave]);
|
||||
}
|
||||
}
|
50
js/src/api/pubsub/pubsub.js
Normal file
50
js/src/api/pubsub/pubsub.js
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
|
||||
import Eth from './eth';
|
||||
import Parity from './parity';
|
||||
import Net from './net';
|
||||
|
||||
import { isFunction } from '../util/types';
|
||||
|
||||
export default class Pubsub {
|
||||
constructor (provider) {
|
||||
if (!provider || !isFunction(provider.subscribe)) {
|
||||
throw new Error('Pubsub API needs transport with subscribe() function defined. (WebSocket)');
|
||||
}
|
||||
|
||||
this._eth = new Eth(provider);
|
||||
this._net = new Net(provider);
|
||||
this._parity = new Parity(provider);
|
||||
}
|
||||
|
||||
get net () {
|
||||
return this._net;
|
||||
}
|
||||
|
||||
get eth () {
|
||||
return this._eth;
|
||||
}
|
||||
|
||||
get parity () {
|
||||
return this._parity;
|
||||
}
|
||||
|
||||
unsubscribe (subscriptionIds) {
|
||||
// subscriptions are namespace independent. Thus we can simply removeListener from any.
|
||||
return this._parity.removeListener(subscriptionIds);
|
||||
}
|
||||
}
|
613
js/src/api/pubsub/pubsub.spec.js
Normal file
613
js/src/api/pubsub/pubsub.spec.js
Normal file
@ -0,0 +1,613 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { TEST_WS_URL, mockWs } from '../../../test/mockRpc';
|
||||
import { isBigNumber } from '../../../test/types';
|
||||
|
||||
import { WsSecure } from '../provider';
|
||||
import Pubsub from './pubsub';
|
||||
|
||||
describe('api/pubsub/Pubsub', () => {
|
||||
let scope;
|
||||
let instance;
|
||||
const address = '0x63Cf90D3f0410092FC0fca41846f596223979195';
|
||||
|
||||
describe('accountsInfo', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: {
|
||||
'0x63cf90d3f0410092fc0fca41846f596223979195': {
|
||||
name: 'name', uuid: 'uuid', meta: '{"data":"data"}'
|
||||
}
|
||||
},
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('retrieves the available account info', (done) => {
|
||||
instance.parity.accountsInfo((error, result) => {
|
||||
expect(error).to.be.null;
|
||||
expect(result).to.deep.equal({
|
||||
'0x63Cf90D3f0410092FC0fca41846f596223979195': {
|
||||
name: 'name', uuid: 'uuid', meta: {
|
||||
data: 'data'
|
||||
}
|
||||
}
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Unsubscribe', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2 },
|
||||
{ method: 'parity_unsubscribe', reply: true }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('Promise gets resolved on success.', (done) => {
|
||||
instance.parity.accountsInfo().then(s => {
|
||||
instance.parity.unsubscribe(s).then(b => {
|
||||
expect(b).to.be.true;
|
||||
});
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('chainStatus', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: {
|
||||
'blockGap': [0x123, 0x456]
|
||||
},
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('retrieves the chain status', (done) => {
|
||||
instance.parity.chainStatus((error, result) => {
|
||||
expect(error).to.be.null;
|
||||
expect(result).to.deep.equal({
|
||||
'blockGap': [new BigNumber(0x123), new BigNumber(0x456)]
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('gasFloorTarget', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123456',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the gasfloor, formatted', (done) => {
|
||||
instance.parity.gasFloorTarget((error, result) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(result)).to.be.true;
|
||||
expect(result.eq(0x123456)).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('transactionsLimit', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: 1024,
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the tx limit, formatted', (done) => {
|
||||
instance.parity.transactionsLimit((error, result) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(result)).to.be.true;
|
||||
expect(result.eq(1024)).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('minGasPrice', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123456',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the min gasprice, formatted', (done) => {
|
||||
instance.parity.minGasPrice((error, result) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(result)).to.be.true;
|
||||
expect(result.eq(0x123456)).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('netPeers', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: { active: 123, connected: 456, max: 789, peers: [] },
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the peer structure, formatted', (done) => {
|
||||
instance.parity.netPeers((error, peers) => {
|
||||
expect(error).to.be.null;
|
||||
expect(peers.active.eq(123)).to.be.true;
|
||||
expect(peers.connected.eq(456)).to.be.true;
|
||||
expect(peers.max.eq(789)).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('netPort', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: 33030,
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the connected port, formatted', (done) => {
|
||||
instance.parity.netPort((error, count) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(count)).to.be.true;
|
||||
expect(count.eq(33030)).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Eth API
|
||||
describe('accounts', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: [address.toLowerCase()],
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns a list of accounts, formatted', (done) => {
|
||||
instance.eth.accounts((error, accounts) => {
|
||||
expect(error).to.be.null;
|
||||
expect(accounts).to.deep.equal([address]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('newHeads', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'eth_subscribe', reply: 2, subscription: {
|
||||
method: 'eth_subscription',
|
||||
params: {
|
||||
result: '0x123456',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns newHeads for eth_subscribe', (done) => {
|
||||
instance.eth.newHeads((error, blockNumber) => {
|
||||
expect(error).to.be.null;
|
||||
expect(blockNumber).to.equal('0x123456');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('blockNumber', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123456',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the current blockNumber, formatted', (done) => {
|
||||
instance.eth.blockNumber((error, blockNumber) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(blockNumber)).to.be.true;
|
||||
expect(blockNumber.toString(16)).to.equal('123456');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('call', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: [],
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('formats the input options & blockNumber', (done) => {
|
||||
instance.eth.call((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_call', [{ data: '0x12345678' }, 'earliest']]);
|
||||
done();
|
||||
}, { data: '12345678' }, 'earliest');
|
||||
});
|
||||
|
||||
it('provides a latest blockNumber when not specified', (done) => {
|
||||
instance.eth.call((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_call', [{ data: '0x12345678' }, 'latest']]);
|
||||
done();
|
||||
}, { data: '12345678' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('coinbase', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: address.toLowerCase(),
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the coinbase, formatted', (done) => {
|
||||
instance.eth.coinbase((error, account) => {
|
||||
expect(error).to.be.null;
|
||||
expect(account).to.deep.equal(address);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('estimateGas', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('converts the options correctly', (done) => {
|
||||
instance.eth.estimateGas((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_estimateGas', [{ gas: '0x5208' }]]);
|
||||
done();
|
||||
}, { gas: 21000 });
|
||||
});
|
||||
|
||||
it('returns the gas used, formatted', (done) => {
|
||||
instance.eth.estimateGas((error, gas) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(gas)).to.be.true;
|
||||
expect(gas.toString(16)).to.deep.equal('123');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('gasPrice', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('returns the gas price, formatted', (done) => {
|
||||
instance.eth.gasPrice((error, price) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(price)).to.be.true;
|
||||
expect(price.toString(16)).to.deep.equal('123');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBalance', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('passes in the address (default blockNumber)', (done) => {
|
||||
instance.eth.getBalance((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBalance', [address.toLowerCase(), 'latest']]);
|
||||
done();
|
||||
}, address);
|
||||
});
|
||||
|
||||
it('passes in the address & blockNumber', (done) => {
|
||||
instance.eth.getBalance((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBalance', [address.toLowerCase(), '0x456']]);
|
||||
done();
|
||||
}, address, 0x456);
|
||||
});
|
||||
|
||||
it('returns the balance', (done) => {
|
||||
instance.eth.getBalance((error, balance) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(balance)).to.be.true;
|
||||
expect(balance.toString(16)).to.deep.equal('123');
|
||||
done();
|
||||
}, address);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBlockByHash', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: { miner: address.toLowerCase() },
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('formats the input hash as a hash, default full', (done) => {
|
||||
instance.eth.getBlockByHash((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByHash', ['0x1234', false]]);
|
||||
done();
|
||||
}, '1234');
|
||||
});
|
||||
|
||||
it('formats the input hash as a hash, full true', (done) => {
|
||||
instance.eth.getBlockByHash((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByHash', ['0x1234', true]]);
|
||||
done();
|
||||
}, '1234', true);
|
||||
});
|
||||
|
||||
it('formats the output into block', (done) => {
|
||||
instance.eth.getBlockByHash((error, block) => {
|
||||
expect(error).to.be.null;
|
||||
expect(block.miner).to.equal(address);
|
||||
done();
|
||||
}, '1234');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getBlockByNumber', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: { miner: address.toLowerCase() },
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('assumes blockNumber latest & full false', (done) => {
|
||||
instance.eth.getBlockByNumber((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByNumber', ['latest', false]]);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('uses input blockNumber & full false', (done) => {
|
||||
instance.eth.getBlockByNumber((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByNumber', ['0x1234', false]]);
|
||||
done();
|
||||
}, '0x1234');
|
||||
});
|
||||
|
||||
it('formats the input blockNumber, full true', (done) => {
|
||||
instance.eth.getBlockByNumber((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getBlockByNumber', ['0x1234', true]]);
|
||||
done();
|
||||
}, 0x1234, true);
|
||||
});
|
||||
|
||||
it('formats the output into block', (done) => {
|
||||
instance.eth.getBlockByNumber((error, block) => {
|
||||
expect(error).to.be.null;
|
||||
expect(block.miner).to.equal(address);
|
||||
done();
|
||||
}, 0x1234);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTransactionCount', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockWs([{ method: 'parity_subscribe', reply: 2, subscription: {
|
||||
method: 'parity_subscription',
|
||||
params: {
|
||||
result: '0x123',
|
||||
subscription: 2
|
||||
}
|
||||
} }]);
|
||||
instance = new Pubsub(new WsSecure(TEST_WS_URL));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
scope.stop();
|
||||
});
|
||||
|
||||
it('passes in the address (default blockNumber)', (done) => {
|
||||
instance.eth.getTransactionCount((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getTransactionCount', [address.toLowerCase(), 'latest']]);
|
||||
done();
|
||||
}, address);
|
||||
});
|
||||
|
||||
it('passes in the address & blockNumber', (done) => {
|
||||
instance.eth.getTransactionCount((error) => {
|
||||
expect(error).to.be.null;
|
||||
expect(scope.body.parity_subscribe.params).to.deep.equal(['eth_getTransactionCount', [address.toLowerCase(), '0x456']]);
|
||||
done();
|
||||
}, address, 0x456);
|
||||
});
|
||||
|
||||
it('returns the count, formatted', (done) => {
|
||||
instance.eth.getTransactionCount((error, count) => {
|
||||
expect(error).to.be.null;
|
||||
expect(isBigNumber(count)).to.be.true;
|
||||
expect(count.toString(16)).to.equal('123');
|
||||
done();
|
||||
}, address, 0x456);
|
||||
});
|
||||
});
|
||||
});
|
37
js/src/api/pubsub/pubsubBase.js
Normal file
37
js/src/api/pubsub/pubsubBase.js
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2015-2017 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/>.
|
||||
|
||||
export default class PubsubBase {
|
||||
// Provider for websocket pubsub transport
|
||||
constructor (provider) {
|
||||
this._provider = provider;
|
||||
}
|
||||
|
||||
addListener (module, eventName, callback, eventParams) {
|
||||
return eventParams
|
||||
? this._provider.subscribe(module, callback, [eventName, eventParams])
|
||||
: this._provider.subscribe(module, callback, [eventName, []]);
|
||||
// this._transport.subscribe(module, callback, eventName); After Patch from tomac is merged to master! => eth_subscribe does not support empty array as params
|
||||
}
|
||||
|
||||
removeListener (subscriptionIds) {
|
||||
return this._provider.unsubscribe(subscriptionIds);
|
||||
}
|
||||
|
||||
unsubscribe (subscriptionIds) {
|
||||
return this.removeListener(subscriptionIds);
|
||||
}
|
||||
}
|
@ -110,7 +110,7 @@ describe('api/rpc/parity', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('newPeers', () => {
|
||||
describe('netPeers', () => {
|
||||
it('returns the peer structure, formatted', () => {
|
||||
mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789, peers: [] } } }]);
|
||||
|
||||
|
@ -28,9 +28,9 @@ export default class Trace {
|
||||
.then(outTraces);
|
||||
}
|
||||
|
||||
call (options, blockNumber = 'latest', whatTrace = ['trace']) {
|
||||
return this._provider
|
||||
.send('trace_call', inOptions(options), inBlockNumber(blockNumber), inTraceType(whatTrace))
|
||||
call (options, whatTrace = ['trace'], blockNumber = 'latest') {
|
||||
return this._transport
|
||||
.execute('trace_call', inOptions(options), inTraceType(whatTrace), inBlockNumber(blockNumber))
|
||||
.then(outTraceReplay);
|
||||
}
|
||||
|
||||
|
@ -22,12 +22,14 @@ import TransportError from '../error';
|
||||
|
||||
/* global WebSocket */
|
||||
export default class WsSecure extends JsonRpcBase {
|
||||
constructor (url, token, autoconnect = true) {
|
||||
// token is optional (secure API)
|
||||
constructor (url, token = null, autoconnect = true) {
|
||||
super();
|
||||
|
||||
this._url = url;
|
||||
this._token = token;
|
||||
this._messages = {};
|
||||
this._subscriptions = { 'eth_subscription': [], 'parity_subscription': [] };
|
||||
this._sessionHash = null;
|
||||
|
||||
this._connecting = false;
|
||||
@ -68,10 +70,6 @@ export default class WsSecure extends JsonRpcBase {
|
||||
this._reconnectTimeoutId = null;
|
||||
}
|
||||
|
||||
const time = parseInt(new Date().getTime() / 1000, 10);
|
||||
const sha3 = keccak_256(`${this._token}:${time}`);
|
||||
const hash = `${sha3}_${time}`;
|
||||
|
||||
if (this._ws) {
|
||||
this._ws.onerror = null;
|
||||
this._ws.onopen = null;
|
||||
@ -81,13 +79,23 @@ export default class WsSecure extends JsonRpcBase {
|
||||
this._ws = null;
|
||||
this._sessionHash = null;
|
||||
}
|
||||
|
||||
this._connecting = true;
|
||||
this._connected = false;
|
||||
this._lastError = null;
|
||||
|
||||
// rpc secure API
|
||||
if (this._token) {
|
||||
const time = parseInt(new Date().getTime() / 1000, 10);
|
||||
const sha3 = keccak_256(`${this._token}:${time}`);
|
||||
const hash = `${sha3}_${time}`;
|
||||
|
||||
this._sessionHash = sha3;
|
||||
this._ws = new WebSocket(this._url, hash);
|
||||
// non-secure API
|
||||
} else {
|
||||
this._ws = new WebSocket(this._url);
|
||||
}
|
||||
|
||||
this._ws.onerror = this._onError;
|
||||
this._ws.onopen = this._onOpen;
|
||||
this._ws.onclose = this._onClose;
|
||||
@ -194,13 +202,48 @@ export default class WsSecure extends JsonRpcBase {
|
||||
}, 50);
|
||||
}
|
||||
|
||||
_extract = (result) => {
|
||||
const { result: res, id, method, params } = result;
|
||||
const msg = this._messages[id];
|
||||
|
||||
// initial pubsub ACK
|
||||
if (id && msg.subscription) {
|
||||
// save subscription to map subId -> messageId
|
||||
this._subscriptions[msg.subscription][res] = id;
|
||||
// resolve promise with messageId because subId's can collide (eth/parity)
|
||||
msg.resolve(id);
|
||||
// save subId for unsubscribing later
|
||||
msg.subId = res;
|
||||
return msg;
|
||||
}
|
||||
|
||||
// normal message
|
||||
if (id) {
|
||||
return msg;
|
||||
}
|
||||
|
||||
// pubsub format
|
||||
if (method.includes('subscription')) {
|
||||
const messageId = this._messages[this._subscriptions[method][params.subscription]];
|
||||
|
||||
if (messageId) {
|
||||
return messageId;
|
||||
} else {
|
||||
throw Error(`Received Subscription which is already unsubscribed ${JSON.stringify(result)}`);
|
||||
}
|
||||
}
|
||||
|
||||
throw Error(`Unknown message format: No ID or subscription ${JSON.stringify(result)}`);
|
||||
}
|
||||
|
||||
_onMessage = (event) => {
|
||||
try {
|
||||
const result = JSON.parse(event.data);
|
||||
const { method, params, json, resolve, reject } = this._messages[result.id];
|
||||
const { method, params, json, resolve, reject, callback, subscription } = this._extract(result);
|
||||
|
||||
Logging.send(method, params, { json, result });
|
||||
|
||||
result.error = (result.params && result.params.error) || result.error;
|
||||
if (result.error) {
|
||||
this.error(event.data);
|
||||
|
||||
@ -211,14 +254,23 @@ export default class WsSecure extends JsonRpcBase {
|
||||
|
||||
const error = new TransportError(method, result.error.code, result.error.message);
|
||||
|
||||
if (result.id) {
|
||||
reject(error);
|
||||
} else {
|
||||
callback(error);
|
||||
}
|
||||
|
||||
delete this._messages[result.id];
|
||||
return;
|
||||
}
|
||||
|
||||
// if not initial subscription message resolve & delete
|
||||
if (result.id && !subscription) {
|
||||
resolve(result.result);
|
||||
delete this._messages[result.id];
|
||||
} else if (result.params) {
|
||||
callback(null, result.params.result);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('ws::_onMessage', event.data, e);
|
||||
}
|
||||
@ -249,6 +301,43 @@ export default class WsSecure extends JsonRpcBase {
|
||||
});
|
||||
}
|
||||
|
||||
_methodsFromApi (api) {
|
||||
const method = `${api}_subscribe`;
|
||||
const uMethod = `${api}_unsubscribe`;
|
||||
const subscription = `${api}_subscription`;
|
||||
|
||||
return { method, uMethod, subscription };
|
||||
}
|
||||
|
||||
subscribe (api, callback, params) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = this.id;
|
||||
const { method, uMethod, subscription } = this._methodsFromApi(api);
|
||||
const json = this.encode(method, params);
|
||||
|
||||
this._messages[id] = { id, method, uMethod, params, json, resolve, reject, callback, subscription };
|
||||
|
||||
this._send(id);
|
||||
});
|
||||
}
|
||||
|
||||
unsubscribe (messageId) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const id = this.id;
|
||||
const { subId, uMethod, subscription } = this._messages[messageId];
|
||||
const params = [subId];
|
||||
const json = this.encode(uMethod, params);
|
||||
const uResolve = (v) => {
|
||||
delete this._messages[messageId];
|
||||
delete this._subscriptions[subscription][subId];
|
||||
resolve(v);
|
||||
};
|
||||
|
||||
this._messages[id] = { id, method: uMethod, params, json, resolve: uResolve, reject };
|
||||
this._send(id);
|
||||
});
|
||||
}
|
||||
|
||||
set url (url) {
|
||||
this._url = url;
|
||||
}
|
||||
|
@ -545,6 +545,39 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
input: {
|
||||
type: Data,
|
||||
desc: 'the data send along with the transaction.'
|
||||
},
|
||||
v: {
|
||||
type: Quantity,
|
||||
desc: 'the standardised V field of the signature.'
|
||||
},
|
||||
standard_v: {
|
||||
type: Quantity,
|
||||
desc: 'the standardised V field of the signature (0 or 1).'
|
||||
},
|
||||
r: {
|
||||
type: Quantity,
|
||||
desc: 'the R field of the signature.'
|
||||
},
|
||||
raw: {
|
||||
type: Data,
|
||||
desc: 'raw transaction data'
|
||||
},
|
||||
publicKey: {
|
||||
type: Hash,
|
||||
desc: 'public key of the signer.'
|
||||
},
|
||||
networkId: {
|
||||
type: Quantity,
|
||||
desc: 'the network id of the transaction, if any.'
|
||||
},
|
||||
creates: {
|
||||
type: Hash,
|
||||
desc: 'creates contract hash'
|
||||
},
|
||||
condition: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
desc: 'conditional submission, Block number in `block` or timestamp in `time` or `null`. (parity-feature)'
|
||||
}
|
||||
},
|
||||
example: {
|
||||
@ -1057,6 +1090,39 @@ The following options are possible for the \`defaultBlock\` parameter:
|
||||
input: {
|
||||
type: Data,
|
||||
desc: 'the data send along with the transaction.'
|
||||
},
|
||||
v: {
|
||||
type: Quantity,
|
||||
desc: 'the standardised V field of the signature.'
|
||||
},
|
||||
standard_v: {
|
||||
type: Quantity,
|
||||
desc: 'the standardised V field of the signature (0 or 1).'
|
||||
},
|
||||
r: {
|
||||
type: Quantity,
|
||||
desc: 'the R field of the signature.'
|
||||
},
|
||||
raw: {
|
||||
type: Data,
|
||||
desc: 'raw transaction data'
|
||||
},
|
||||
publicKey: {
|
||||
type: Hash,
|
||||
desc: 'public key of the signer.'
|
||||
},
|
||||
networkId: {
|
||||
type: Quantity,
|
||||
desc: 'the network id of the transaction, if any.'
|
||||
},
|
||||
creates: {
|
||||
type: Hash,
|
||||
desc: 'creates contract hash'
|
||||
},
|
||||
condition: {
|
||||
type: Object,
|
||||
optional: true,
|
||||
desc: 'conditional submission, Block number in `block` or timestamp in `time` or `null`. (parity-feature)'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,10 @@ export function mockWs (requests) {
|
||||
scope.requests++;
|
||||
|
||||
mockServer.send(JSON.stringify(response));
|
||||
|
||||
if (request.method.match('subscribe') && request.subscription) {
|
||||
mockServer.send(JSON.stringify(request.subscription));
|
||||
}
|
||||
});
|
||||
|
||||
return scope;
|
||||
|
Loading…
Reference in New Issue
Block a user