Backporting to beta (#3229)
* Use ethcore_dappsPort when constructing URLs (#3139) * Upon connect, retrieve the available api ports * Update dapps to load from dappsPort * Update dapps summary with dappsPort * Allow proxy to use dappsPort * Replace /api/ping with HEAD / * Dynamic port for available apps * Retrieve content images with dappsPort * Fix / * Transfer token dropdown image fix * IdentityIcon loads images via contentHash * Update apps fetch to cater for dev & prod * DRY up 127.0.0.1:${dappsPort} with ${dappsUrl} * Cleaning up polluted namespaces (#3143) * Renaming ethcore_ to parity_ * Renaming files * Renaming poluted EthSigning * Tidy up the namespaces * Renaming files to match new structure * Splitting EthSigning into separate traits * jsapi move ethcore.* -> parity.* * Move jsonrpc parity definitions * Update UI API calls for parity interfaces * Move jsapi signer interfaces from personal to signer * Update UI to use signer.* where applicable * Updsate jsapi subscriptions for signer * Fix dodgy merge. * Update README. * Fix some tests. * Move parity-only personal.* to parity.* * Update UI for personal -> parity API moves * Update subscription APIs after personal -> parity move * personal. generateAuthorizationToken -> parity. generateAuthorizationToken (UI) * enode, dappsPort & signerPort (UI) * Update subscription tests (accountsInfo) * subscription update * personal -> parity * Additional error logging on method failures * move postTransaction to parity * Additional debug info with method failures * Fix personal tests. * Console wrning shows parameters, error object does not * Include parity_ signing methods. * Console log http transport info * Fix failing tests * Add RPC stubs for parity_accounts. * Allow some secure built-in dapps * Use parity_accounts in place of accountsInfo * Improve error reporting * Cleanup GHH error handling Former-commit-id: 5a094ccb9f0596d0e07abc23504b80dc099ad584
This commit is contained in:
parent
aea995cf55
commit
043ca21863
22
README.md
22
README.md
@ -1,9 +1,12 @@
|
||||
# [Parity](https://ethcore.io/parity.html)
|
||||
### Fast, light, and robust Ethereum implementation
|
||||
|
||||
[![Join the chat at https://gitter.im/ethcore/parity.js](https://badges.gitter.im/ethcore/parity.js.svg)](https://gitter.im/ethcore/parity.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
[![Build Status][travis-image]][travis-url] [![build status](https://gitlab.ethcore.io/Mirrors/ethcore-parity/badges/master/build.svg)](https://gitlab.ethcore.io/Mirrors/ethcore-parity/commits/master) [![Coverage Status][coveralls-image]][coveralls-url] [![GPLv3][license-image]][license-url]
|
||||
|
||||
[![Build Status][travis-image]][travis-url] [![Coverage Status][coveralls-image]][coveralls-url] [![Join the chat at https://gitter.im/ethcore/parity][gitter-image]][gitter-url] [![GPLv3][license-image]][license-url]
|
||||
### Join the chat!
|
||||
|
||||
Parity [![Join the chat at https://gitter.im/ethcore/parity][gitter-image]][gitter-url] and
|
||||
parity.js [![Join the chat at https://gitter.im/ethcore/parity.js](https://badges.gitter.im/ethcore/parity.js.svg)](https://gitter.im/ethcore/parity.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
[Internal Documentation][doc-url]
|
||||
|
||||
@ -21,7 +24,7 @@ Be sure to check out [our wiki][wiki-url] for more information.
|
||||
[doc-url]: https://ethcore.github.io/parity/ethcore/index.html
|
||||
[wiki-url]: https://github.com/ethcore/parity/wiki
|
||||
|
||||
**Requires Rust version 1.12.0 to build**
|
||||
**Parity requires Rust version 1.12.0 to build**
|
||||
|
||||
----
|
||||
|
||||
@ -31,12 +34,15 @@ Be sure to check out [our wiki][wiki-url] for more information.
|
||||
Parity's goal is to be the fastest, lightest, and most secure Ethereum client. We are developing Parity using the sophisticated and
|
||||
cutting-edge Rust programming language. Parity is licensed under the GPLv3, and can be used for all your Ethereum needs.
|
||||
|
||||
By default, Parity will run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number
|
||||
of RPC APIs.
|
||||
Parity comes with a built-in wallet. To access [Parity Wallet](http://127.0.0.1:8080/) this simply go to http://127.0.0.1:8080/. It
|
||||
includes various functionality allowing you to:
|
||||
- create and manage your Ethereum accounts;
|
||||
- manage your Ether and any Ethereum tokens;
|
||||
- create and register your own tokens;
|
||||
- and much more.
|
||||
|
||||
Parity also runs a server for running decentralized apps, or "Dapps", on `http://127.0.0.1:8080`.
|
||||
This includes a few useful Dapps, including Ethereum Wallet, Maker OTC, and a node status page.
|
||||
In a near-future release, it will be easy to install Dapps and use them through this web interface.
|
||||
By default, Parity will also run a JSONRPC server on `127.0.0.1:8545`. This is fully configurable and supports a number
|
||||
of RPC APIs.
|
||||
|
||||
If you run into an issue while using parity, feel free to file one in this repository
|
||||
or hop on our [gitter chat room][gitter-url] to ask a question. We are glad to help!
|
||||
|
@ -135,10 +135,11 @@ APIs implement the calls as exposed in the [Ethcore JSON Ethereum RPC](https://g
|
||||
|
||||
- [ethapi.db](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#db)
|
||||
- [ethapi.eth](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#eth)
|
||||
- [ethapi.ethcore](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#ethcore)
|
||||
- [ethapi.parity](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#parity)
|
||||
- [ethapi.net](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#net)
|
||||
- [ethapi.personal](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#personal)
|
||||
- [ethapi.shh](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#shh)
|
||||
- [ethapi.signer](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#signer)
|
||||
- [ethapi.trace](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#trace)
|
||||
- [ethapi.web3](https://github.com/ethcore/ethereum-rpc-json/blob/master/interfaces.md#web3)
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
import { Http, Ws } from './transport';
|
||||
import Contract from './contract';
|
||||
|
||||
import { Db, Eth, Ethcore, Net, Personal, Shh, Trace, Web3 } from './rpc';
|
||||
import { Db, Eth, Parity, Net, Personal, Shh, Signer, Trace, Web3 } from './rpc';
|
||||
import Subscriptions from './subscriptions';
|
||||
import util from './util';
|
||||
import { isFunction } from './util/types';
|
||||
@ -32,10 +32,11 @@ export default class Api {
|
||||
|
||||
this._db = new Db(transport);
|
||||
this._eth = new Eth(transport);
|
||||
this._ethcore = new Ethcore(transport);
|
||||
this._net = new Net(transport);
|
||||
this._parity = new Parity(transport);
|
||||
this._personal = new Personal(transport);
|
||||
this._shh = new Shh(transport);
|
||||
this._signer = new Signer(transport);
|
||||
this._trace = new Trace(transport);
|
||||
this._web3 = new Web3(transport);
|
||||
|
||||
@ -50,8 +51,8 @@ export default class Api {
|
||||
return this._eth;
|
||||
}
|
||||
|
||||
get ethcore () {
|
||||
return this._ethcore;
|
||||
get parity () {
|
||||
return this._parity;
|
||||
}
|
||||
|
||||
get net () {
|
||||
@ -66,6 +67,10 @@ export default class Api {
|
||||
return this._shh;
|
||||
}
|
||||
|
||||
get signer () {
|
||||
return this._signer;
|
||||
}
|
||||
|
||||
get trace () {
|
||||
return this._trace;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ export default class Contract {
|
||||
options.gas = gas.toFixed(0);
|
||||
|
||||
setState({ state: 'postTransaction', gas });
|
||||
return this._api.eth.postTransaction(this._encodeOptions(this.constructors[0], options, values));
|
||||
return this._api.parity.postTransaction(this._encodeOptions(this.constructors[0], options, values));
|
||||
})
|
||||
.then((requestId) => {
|
||||
setState({ state: 'checkRequest', requestId });
|
||||
@ -166,7 +166,7 @@ export default class Contract {
|
||||
}
|
||||
|
||||
_pollCheckRequest = (requestId) => {
|
||||
return this._api.pollMethod('eth_checkRequest', requestId);
|
||||
return this._api.pollMethod('parity_checkRequest', requestId);
|
||||
}
|
||||
|
||||
_pollTransactionReceipt = (txhash, gas) => {
|
||||
@ -208,7 +208,7 @@ export default class Contract {
|
||||
|
||||
if (!func.constant) {
|
||||
func.postTransaction = (options, values = []) => {
|
||||
return this._api.eth
|
||||
return this._api.parity
|
||||
.postTransaction(this._encodeOptions(func, this._addOptionsTo(options), values));
|
||||
};
|
||||
|
||||
|
@ -249,9 +249,9 @@ describe('api/contract/Contract', () => {
|
||||
before(() => {
|
||||
scope = mockHttp([
|
||||
{ method: 'eth_estimateGas', reply: { result: 1000 } },
|
||||
{ method: 'eth_postTransaction', reply: { result: '0x678' } },
|
||||
{ method: 'eth_checkRequest', reply: { result: null } },
|
||||
{ method: 'eth_checkRequest', reply: { result: '0x890' } },
|
||||
{ method: 'parity_postTransaction', reply: { result: '0x678' } },
|
||||
{ method: 'parity_checkRequest', reply: { result: null } },
|
||||
{ method: 'parity_checkRequest', reply: { result: '0x890' } },
|
||||
{ method: 'eth_getTransactionReceipt', reply: { result: null } },
|
||||
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_PEND } },
|
||||
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } },
|
||||
@ -266,7 +266,7 @@ describe('api/contract/Contract', () => {
|
||||
});
|
||||
|
||||
it('passes the options through to postTransaction (incl. gas calculation)', () => {
|
||||
expect(scope.body.eth_postTransaction.params).to.deep.equal([
|
||||
expect(scope.body.parity_postTransaction.params).to.deep.equal([
|
||||
{ data: '0x123', gas: '0x4b0' }
|
||||
]);
|
||||
});
|
||||
@ -280,8 +280,8 @@ describe('api/contract/Contract', () => {
|
||||
it('fails when gasUsed == gas', () => {
|
||||
mockHttp([
|
||||
{ method: 'eth_estimateGas', reply: { result: 1000 } },
|
||||
{ method: 'eth_postTransaction', reply: { result: '0x678' } },
|
||||
{ method: 'eth_checkRequest', reply: { result: '0x789' } },
|
||||
{ method: 'parity_postTransaction', reply: { result: '0x678' } },
|
||||
{ method: 'parity_checkRequest', reply: { result: '0x789' } },
|
||||
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_EXCP } }
|
||||
]);
|
||||
|
||||
@ -295,8 +295,8 @@ describe('api/contract/Contract', () => {
|
||||
it('fails when no code was deployed', () => {
|
||||
mockHttp([
|
||||
{ method: 'eth_estimateGas', reply: { result: 1000 } },
|
||||
{ method: 'eth_postTransaction', reply: { result: '0x678' } },
|
||||
{ method: 'eth_checkRequest', reply: { result: '0x789' } },
|
||||
{ method: 'parity_postTransaction', reply: { result: '0x678' } },
|
||||
{ method: 'parity_checkRequest', reply: { result: '0x789' } },
|
||||
{ method: 'eth_getTransactionReceipt', reply: { result: RECEIPT_DONE } },
|
||||
{ method: 'eth_getCode', reply: { result: '0x' } }
|
||||
]);
|
||||
@ -360,15 +360,15 @@ describe('api/contract/Contract', () => {
|
||||
|
||||
describe('postTransaction', () => {
|
||||
beforeEach(() => {
|
||||
scope = mockHttp([{ method: 'eth_postTransaction', reply: { result: ['hashId'] } }]);
|
||||
scope = mockHttp([{ method: 'parity_postTransaction', reply: { result: ['hashId'] } }]);
|
||||
});
|
||||
|
||||
it('encodes options and mades an eth_postTransaction call', () => {
|
||||
it('encodes options and mades an parity_postTransaction call', () => {
|
||||
return func
|
||||
.postTransaction({ someExtras: 'foo' }, VALUES)
|
||||
.then(() => {
|
||||
expect(scope.isDone()).to.be.true;
|
||||
expect(scope.body.eth_postTransaction.params[0]).to.deep.equal({
|
||||
expect(scope.body.parity_postTransaction.params[0]).to.deep.equal({
|
||||
someExtras: 'foo',
|
||||
to: ADDR,
|
||||
data: ENCODED
|
||||
|
@ -39,11 +39,6 @@ export default class Eth {
|
||||
.execute('eth_call', inOptions(options), inBlockNumber(blockNumber));
|
||||
}
|
||||
|
||||
checkRequest (requestId) {
|
||||
return this._transport
|
||||
.execute('eth_checkRequest', inNumber16(requestId));
|
||||
}
|
||||
|
||||
coinbase () {
|
||||
return this._transport
|
||||
.execute('eth_coinbase')
|
||||
@ -267,11 +262,6 @@ export default class Eth {
|
||||
.execute('eth_pendingTransactions');
|
||||
}
|
||||
|
||||
postTransaction (options) {
|
||||
return this._transport
|
||||
.execute('eth_postTransaction', inOptions(options));
|
||||
}
|
||||
|
||||
protocolVersion () {
|
||||
return this._transport
|
||||
.execute('eth_protocolVersion');
|
||||
|
@ -1,201 +0,0 @@
|
||||
// Copyright 2015, 2016 Ethcore (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 { inAddress, inData, inNumber16 } from '../../format/input';
|
||||
import { outAddress, outHistogram, outNumber, outPeers } from '../../format/output';
|
||||
|
||||
export default class Ethcore {
|
||||
constructor (transport) {
|
||||
this._transport = transport;
|
||||
}
|
||||
|
||||
acceptNonReservedPeers () {
|
||||
return this._transport
|
||||
.execute('ethcore_acceptNonReservedPeers');
|
||||
}
|
||||
|
||||
addReservedPeer (encode) {
|
||||
return this._transport
|
||||
.execute('ethcore_addReservedPeer', encode);
|
||||
}
|
||||
|
||||
dappsPort () {
|
||||
return this._transport
|
||||
.execute('ethcore_dappsPort')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
defaultExtraData () {
|
||||
return this._transport
|
||||
.execute('ethcore_defaultExtraData');
|
||||
}
|
||||
|
||||
devLogs () {
|
||||
return this._transport
|
||||
.execute('ethcore_devLogs');
|
||||
}
|
||||
|
||||
devLogsLevels () {
|
||||
return this._transport
|
||||
.execute('ethcore_devLogsLevels');
|
||||
}
|
||||
|
||||
dropNonReservedPeers () {
|
||||
return this._transport
|
||||
.execute('ethcore_dropNonReservedPeers');
|
||||
}
|
||||
|
||||
enode () {
|
||||
return this._transport
|
||||
.execute('ethcore_enode');
|
||||
}
|
||||
|
||||
extraData () {
|
||||
return this._transport
|
||||
.execute('ethcore_extraData');
|
||||
}
|
||||
|
||||
gasFloorTarget () {
|
||||
return this._transport
|
||||
.execute('ethcore_gasFloorTarget')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
gasPriceHistogram () {
|
||||
return this._transport
|
||||
.execute('ethcore_gasPriceHistogram')
|
||||
.then(outHistogram);
|
||||
}
|
||||
|
||||
generateSecretPhrase () {
|
||||
return this._transport
|
||||
.execute('ethcore_generateSecretPhrase');
|
||||
}
|
||||
|
||||
hashContent (url) {
|
||||
return this._transport
|
||||
.execute('ethcore_hashContent', url);
|
||||
}
|
||||
|
||||
minGasPrice () {
|
||||
return this._transport
|
||||
.execute('ethcore_minGasPrice')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
mode () {
|
||||
return this._transport
|
||||
.execute('ethcore_mode');
|
||||
}
|
||||
|
||||
netChain () {
|
||||
return this._transport
|
||||
.execute('ethcore_netChain');
|
||||
}
|
||||
|
||||
netPeers () {
|
||||
return this._transport
|
||||
.execute('ethcore_netPeers')
|
||||
.then(outPeers);
|
||||
}
|
||||
|
||||
netMaxPeers () {
|
||||
return this._transport
|
||||
.execute('ethcore_netMaxPeers')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
netPort () {
|
||||
return this._transport
|
||||
.execute('ethcore_netPort')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
nodeName () {
|
||||
return this._transport
|
||||
.execute('ethcore_nodeName');
|
||||
}
|
||||
|
||||
phraseToAddress (phrase) {
|
||||
return this._transport
|
||||
.execute('ethcore_phraseToAddress', phrase)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
registryAddress () {
|
||||
return this._transport
|
||||
.execute('ethcore_registryAddress')
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
removeReservedPeer (encode) {
|
||||
return this._transport
|
||||
.execute('ethcore_removeReservedPeer', encode);
|
||||
}
|
||||
|
||||
rpcSettings () {
|
||||
return this._transport
|
||||
.execute('ethcore_rpcSettings');
|
||||
}
|
||||
|
||||
setAuthor (address) {
|
||||
return this._transport
|
||||
.execute('ethcore_setAuthor', inAddress(address));
|
||||
}
|
||||
|
||||
setExtraData (data) {
|
||||
return this._transport
|
||||
.execute('ethcore_setExtraData', inData(data));
|
||||
}
|
||||
|
||||
setGasFloorTarget (quantity) {
|
||||
return this._transport
|
||||
.execute('ethcore_setGasFloorTarget', inNumber16(quantity));
|
||||
}
|
||||
|
||||
setMinGasPrice (quantity) {
|
||||
return this._transport
|
||||
.execute('ethcore_setMinGasPrice', inNumber16(quantity));
|
||||
}
|
||||
|
||||
setMode (mode) {
|
||||
return this._transport
|
||||
.execute('ethcore_setMode', mode);
|
||||
}
|
||||
|
||||
setTransactionsLimit (quantity) {
|
||||
return this._transport
|
||||
.execute('ethcore_setTransactionsLimit', inNumber16(quantity));
|
||||
}
|
||||
|
||||
signerPort () {
|
||||
return this._transport
|
||||
.execute('ethcore_signerPort')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
transactionsLimit () {
|
||||
return this._transport
|
||||
.execute('ethcore_transactionsLimit')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
unsignedTransactionsCount () {
|
||||
return this._transport
|
||||
.execute('ethcore_unsignedTransactionsCount')
|
||||
.then(outNumber);
|
||||
}
|
||||
}
|
@ -16,9 +16,10 @@
|
||||
|
||||
export Db from './db';
|
||||
export Eth from './eth';
|
||||
export Ethcore from './ethcore';
|
||||
export Parity from './parity';
|
||||
export Net from './net';
|
||||
export Personal from './personal';
|
||||
export Shh from './shh';
|
||||
export Signer from './signer';
|
||||
export Trace from './trace';
|
||||
export Web3 from './web3';
|
||||
|
@ -14,4 +14,4 @@
|
||||
// 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 './ethcore';
|
||||
export default from './parity';
|
@ -16,12 +16,12 @@
|
||||
|
||||
import { createHttpApi } from '../../../../test/e2e/ethapi';
|
||||
|
||||
describe('ethapi.ethcore', () => {
|
||||
describe('ethapi.parity', () => {
|
||||
const ethapi = createHttpApi();
|
||||
|
||||
describe('gasFloorTarget', () => {
|
||||
it('returns and translates the target', () => {
|
||||
return ethapi.ethcore.gasFloorTarget().then((value) => {
|
||||
return ethapi.parity.gasFloorTarget().then((value) => {
|
||||
expect(value.gt(0)).to.be.true;
|
||||
});
|
||||
});
|
||||
@ -29,7 +29,7 @@ describe('ethapi.ethcore', () => {
|
||||
|
||||
describe('gasPriceHistogram', () => {
|
||||
it('returns and translates the target', () => {
|
||||
return ethapi.ethcore.gasPriceHistogram().then((result) => {
|
||||
return ethapi.parity.gasPriceHistogram().then((result) => {
|
||||
expect(Object.keys(result)).to.deep.equal(['bucketBounds', 'counts']);
|
||||
expect(result.bucketBounds.length > 0).to.be.true;
|
||||
expect(result.counts.length > 0).to.be.true;
|
||||
@ -39,7 +39,7 @@ describe('ethapi.ethcore', () => {
|
||||
|
||||
describe('netChain', () => {
|
||||
it('returns and the chain', () => {
|
||||
return ethapi.ethcore.netChain().then((value) => {
|
||||
return ethapi.parity.netChain().then((value) => {
|
||||
expect(value).to.equal('morden');
|
||||
});
|
||||
});
|
||||
@ -47,7 +47,7 @@ describe('ethapi.ethcore', () => {
|
||||
|
||||
describe('netPort', () => {
|
||||
it('returns and translates the port', () => {
|
||||
return ethapi.ethcore.netPort().then((value) => {
|
||||
return ethapi.parity.netPort().then((value) => {
|
||||
expect(value.gt(0)).to.be.true;
|
||||
});
|
||||
});
|
||||
@ -55,7 +55,7 @@ describe('ethapi.ethcore', () => {
|
||||
|
||||
describe('transactionsLimit', () => {
|
||||
it('returns and translates the limit', () => {
|
||||
return ethapi.ethcore.transactionsLimit().then((value) => {
|
||||
return ethapi.parity.transactionsLimit().then((value) => {
|
||||
expect(value.gt(0)).to.be.true;
|
||||
});
|
||||
});
|
||||
@ -63,7 +63,7 @@ describe('ethapi.ethcore', () => {
|
||||
|
||||
describe('rpcSettings', () => {
|
||||
it('returns and translates the settings', () => {
|
||||
return ethapi.ethcore.rpcSettings().then((value) => {
|
||||
return ethapi.parity.rpcSettings().then((value) => {
|
||||
expect(value).to.be.ok;
|
||||
});
|
||||
});
|
273
js/src/api/rpc/parity/parity.js
Normal file
273
js/src/api/rpc/parity/parity.js
Normal file
@ -0,0 +1,273 @@
|
||||
// Copyright 2015, 2016 Ethcore (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 { inAddress, inData, inHex, inNumber16, inOptions } from '../../format/input';
|
||||
import { outAccountInfo, outAddress, outHistogram, outNumber, outPeers } from '../../format/output';
|
||||
|
||||
export default class Parity {
|
||||
constructor (transport) {
|
||||
this._transport = transport;
|
||||
}
|
||||
|
||||
acceptNonReservedPeers () {
|
||||
return this._transport
|
||||
.execute('parity_acceptNonReservedPeers');
|
||||
}
|
||||
|
||||
accounts () {
|
||||
return this._transport
|
||||
.execute('parity_accounts')
|
||||
.then(outAccountInfo);
|
||||
}
|
||||
|
||||
accountsInfo () {
|
||||
return this._transport
|
||||
.execute('parity_accountsInfo')
|
||||
.then(outAccountInfo);
|
||||
}
|
||||
|
||||
addReservedPeer (encode) {
|
||||
return this._transport
|
||||
.execute('parity_addReservedPeer', encode);
|
||||
}
|
||||
|
||||
changePassword (account, password, newPassword) {
|
||||
return this._transport
|
||||
.execute('parity_changePassword', inAddress(account), password, newPassword);
|
||||
}
|
||||
|
||||
checkRequest (requestId) {
|
||||
return this._transport
|
||||
.execute('parity_checkRequest', inNumber16(requestId));
|
||||
}
|
||||
|
||||
dappsPort () {
|
||||
return this._transport
|
||||
.execute('parity_dappsPort')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
defaultExtraData () {
|
||||
return this._transport
|
||||
.execute('parity_defaultExtraData');
|
||||
}
|
||||
|
||||
devLogs () {
|
||||
return this._transport
|
||||
.execute('parity_devLogs');
|
||||
}
|
||||
|
||||
devLogsLevels () {
|
||||
return this._transport
|
||||
.execute('parity_devLogsLevels');
|
||||
}
|
||||
|
||||
dropNonReservedPeers () {
|
||||
return this._transport
|
||||
.execute('parity_dropNonReservedPeers');
|
||||
}
|
||||
|
||||
enode () {
|
||||
return this._transport
|
||||
.execute('parity_enode');
|
||||
}
|
||||
|
||||
extraData () {
|
||||
return this._transport
|
||||
.execute('parity_extraData');
|
||||
}
|
||||
|
||||
gasFloorTarget () {
|
||||
return this._transport
|
||||
.execute('parity_gasFloorTarget')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
gasPriceHistogram () {
|
||||
return this._transport
|
||||
.execute('parity_gasPriceHistogram')
|
||||
.then(outHistogram);
|
||||
}
|
||||
|
||||
generateSecretPhrase () {
|
||||
return this._transport
|
||||
.execute('parity_generateSecretPhrase');
|
||||
}
|
||||
|
||||
hashContent (url) {
|
||||
return this._transport
|
||||
.execute('parity_hashContent', url);
|
||||
}
|
||||
|
||||
listGethAccounts () {
|
||||
return this._transport
|
||||
.execute('parity_listGethAccounts')
|
||||
.then((accounts) => (accounts || []).map(outAddress));
|
||||
}
|
||||
|
||||
importGethAccounts (accounts) {
|
||||
return this._transport
|
||||
.execute('parity_importGethAccounts', (accounts || []).map(inAddress))
|
||||
.then((accounts) => (accounts || []).map(outAddress));
|
||||
}
|
||||
|
||||
minGasPrice () {
|
||||
return this._transport
|
||||
.execute('parity_minGasPrice')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
mode () {
|
||||
return this._transport
|
||||
.execute('parity_mode');
|
||||
}
|
||||
|
||||
netChain () {
|
||||
return this._transport
|
||||
.execute('parity_netChain');
|
||||
}
|
||||
|
||||
netPeers () {
|
||||
return this._transport
|
||||
.execute('parity_netPeers')
|
||||
.then(outPeers);
|
||||
}
|
||||
|
||||
netMaxPeers () {
|
||||
return this._transport
|
||||
.execute('parity_netMaxPeers')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
netPort () {
|
||||
return this._transport
|
||||
.execute('parity_netPort')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
newAccountFromPhrase (phrase, password) {
|
||||
return this._transport
|
||||
.execute('parity_newAccountFromPhrase', phrase, password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
newAccountFromSecret (secret, password) {
|
||||
return this._transport
|
||||
.execute('parity_newAccountFromSecret', inHex(secret), password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
newAccountFromWallet (json, password) {
|
||||
return this._transport
|
||||
.execute('parity_newAccountFromWallet', json, password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
nodeName () {
|
||||
return this._transport
|
||||
.execute('parity_nodeName');
|
||||
}
|
||||
|
||||
phraseToAddress (phrase) {
|
||||
return this._transport
|
||||
.execute('parity_phraseToAddress', phrase)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
postTransaction (options) {
|
||||
return this._transport
|
||||
.execute('parity_postTransaction', inOptions(options));
|
||||
}
|
||||
|
||||
registryAddress () {
|
||||
return this._transport
|
||||
.execute('parity_registryAddress')
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
removeReservedPeer (encode) {
|
||||
return this._transport
|
||||
.execute('parity_removeReservedPeer', encode);
|
||||
}
|
||||
|
||||
rpcSettings () {
|
||||
return this._transport
|
||||
.execute('parity_rpcSettings');
|
||||
}
|
||||
|
||||
setAccountName (address, name) {
|
||||
return this._transport
|
||||
.execute('parity_setAccountName', inAddress(address), name);
|
||||
}
|
||||
|
||||
setAccountMeta (address, meta) {
|
||||
return this._transport
|
||||
.execute('parity_setAccountMeta', inAddress(address), JSON.stringify(meta));
|
||||
}
|
||||
|
||||
setAuthor (address) {
|
||||
return this._transport
|
||||
.execute('parity_setAuthor', inAddress(address));
|
||||
}
|
||||
|
||||
setExtraData (data) {
|
||||
return this._transport
|
||||
.execute('parity_setExtraData', inData(data));
|
||||
}
|
||||
|
||||
setGasFloorTarget (quantity) {
|
||||
return this._transport
|
||||
.execute('parity_setGasFloorTarget', inNumber16(quantity));
|
||||
}
|
||||
|
||||
setMinGasPrice (quantity) {
|
||||
return this._transport
|
||||
.execute('parity_setMinGasPrice', inNumber16(quantity));
|
||||
}
|
||||
|
||||
setMode (mode) {
|
||||
return this._transport
|
||||
.execute('parity_setMode', mode);
|
||||
}
|
||||
|
||||
setTransactionsLimit (quantity) {
|
||||
return this._transport
|
||||
.execute('parity_setTransactionsLimit', inNumber16(quantity));
|
||||
}
|
||||
|
||||
signerPort () {
|
||||
return this._transport
|
||||
.execute('parity_signerPort')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
testPassword (account, password) {
|
||||
return this._transport
|
||||
.execute('parity_testPassword', inAddress(account), password);
|
||||
}
|
||||
|
||||
transactionsLimit () {
|
||||
return this._transport
|
||||
.execute('parity_transactionsLimit')
|
||||
.then(outNumber);
|
||||
}
|
||||
|
||||
unsignedTransactionsCount () {
|
||||
return this._transport
|
||||
.execute('parity_unsignedTransactionsCount')
|
||||
.then(outNumber);
|
||||
}
|
||||
}
|
@ -18,14 +18,36 @@ import { TEST_HTTP_URL, mockHttp } from '../../../../test/mockRpc';
|
||||
import { isBigNumber } from '../../../../test/types';
|
||||
|
||||
import Http from '../../transport/http';
|
||||
import Ethcore from './ethcore';
|
||||
import Parity from './parity';
|
||||
|
||||
const instance = new Ethcore(new Http(TEST_HTTP_URL));
|
||||
const instance = new Parity(new Http(TEST_HTTP_URL));
|
||||
|
||||
describe('api/rpc/parity', () => {
|
||||
describe('accountsInfo', () => {
|
||||
it('retrieves the available account info', () => {
|
||||
mockHttp([{ method: 'parity_accountsInfo', reply: {
|
||||
result: {
|
||||
'0x63cf90d3f0410092fc0fca41846f596223979195': {
|
||||
name: 'name', uuid: 'uuid', meta: '{"data":"data"}'
|
||||
}
|
||||
}
|
||||
} }]);
|
||||
|
||||
return instance.accountsInfo().then((result) => {
|
||||
expect(result).to.deep.equal({
|
||||
'0x63Cf90D3f0410092FC0fca41846f596223979195': {
|
||||
name: 'name', uuid: 'uuid', meta: {
|
||||
data: 'data'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('api/rpc/Ethcore', () => {
|
||||
describe('gasFloorTarget', () => {
|
||||
it('returns the gasfloor, formatted', () => {
|
||||
mockHttp([{ method: 'ethcore_gasFloorTarget', reply: { result: '0x123456' } }]);
|
||||
mockHttp([{ method: 'parity_gasFloorTarget', reply: { result: '0x123456' } }]);
|
||||
|
||||
return instance.gasFloorTarget().then((count) => {
|
||||
expect(isBigNumber(count)).to.be.true;
|
||||
@ -36,7 +58,7 @@ describe('api/rpc/Ethcore', () => {
|
||||
|
||||
describe('minGasPrice', () => {
|
||||
it('returns the min gasprice, formatted', () => {
|
||||
mockHttp([{ method: 'ethcore_minGasPrice', reply: { result: '0x123456' } }]);
|
||||
mockHttp([{ method: 'parity_minGasPrice', reply: { result: '0x123456' } }]);
|
||||
|
||||
return instance.minGasPrice().then((count) => {
|
||||
expect(isBigNumber(count)).to.be.true;
|
||||
@ -47,7 +69,7 @@ describe('api/rpc/Ethcore', () => {
|
||||
|
||||
describe('netMaxPeers', () => {
|
||||
it('returns the max peers, formatted', () => {
|
||||
mockHttp([{ method: 'ethcore_netMaxPeers', reply: { result: 25 } }]);
|
||||
mockHttp([{ method: 'parity_netMaxPeers', reply: { result: 25 } }]);
|
||||
|
||||
return instance.netMaxPeers().then((count) => {
|
||||
expect(isBigNumber(count)).to.be.true;
|
||||
@ -58,7 +80,7 @@ describe('api/rpc/Ethcore', () => {
|
||||
|
||||
describe('newPeers', () => {
|
||||
it('returns the peer structure, formatted', () => {
|
||||
mockHttp([{ method: 'ethcore_netPeers', reply: { result: { active: 123, connected: 456, max: 789 } } }]);
|
||||
mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789 } } }]);
|
||||
|
||||
return instance.netPeers().then((peers) => {
|
||||
expect(peers.active.eq(123)).to.be.true;
|
||||
@ -70,7 +92,7 @@ describe('api/rpc/Ethcore', () => {
|
||||
|
||||
describe('netPort', () => {
|
||||
it('returns the connected port, formatted', () => {
|
||||
mockHttp([{ method: 'ethcore_netPort', reply: { result: 33030 } }]);
|
||||
mockHttp([{ method: 'parity_netPort', reply: { result: 33030 } }]);
|
||||
|
||||
return instance.netPort().then((count) => {
|
||||
expect(isBigNumber(count)).to.be.true;
|
||||
@ -81,7 +103,7 @@ describe('api/rpc/Ethcore', () => {
|
||||
|
||||
describe('transactionsLimit', () => {
|
||||
it('returns the tx limit, formatted', () => {
|
||||
mockHttp([{ method: 'ethcore_transactionsLimit', reply: { result: 1024 } }]);
|
||||
mockHttp([{ method: 'parity_transactionsLimit', reply: { result: 1024 } }]);
|
||||
|
||||
return instance.transactionsLimit().then((count) => {
|
||||
expect(isBigNumber(count)).to.be.true;
|
@ -14,113 +14,31 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { inAddress, inHex, inNumber10, inNumber16, inOptions } from '../../format/input';
|
||||
import { outAccountInfo, outAddress, outSignerRequest } from '../../format/output';
|
||||
import { inAddress, inNumber10, inOptions } from '../../format/input';
|
||||
import { outAddress } from '../../format/output';
|
||||
|
||||
export default class Personal {
|
||||
constructor (transport) {
|
||||
this._transport = transport;
|
||||
}
|
||||
|
||||
accountsInfo () {
|
||||
return this._transport
|
||||
.execute('personal_accountsInfo')
|
||||
.then(outAccountInfo);
|
||||
}
|
||||
|
||||
confirmRequest (requestId, options, password) {
|
||||
return this._transport
|
||||
.execute('personal_confirmRequest', inNumber16(requestId), options, password);
|
||||
}
|
||||
|
||||
changePassword (account, password, newPassword) {
|
||||
return this._transport
|
||||
.execute('personal_changePassword', inAddress(account), password, newPassword);
|
||||
}
|
||||
|
||||
generateAuthorizationToken () {
|
||||
return this._transport
|
||||
.execute('personal_generateAuthorizationToken');
|
||||
}
|
||||
|
||||
listAccounts () {
|
||||
return this._transport
|
||||
.execute('personal_listAccounts')
|
||||
.then((accounts) => (accounts || []).map(outAddress));
|
||||
}
|
||||
|
||||
listGethAccounts () {
|
||||
return this._transport
|
||||
.execute('personal_listGethAccounts')
|
||||
.then((accounts) => (accounts || []).map(outAddress));
|
||||
}
|
||||
|
||||
importGethAccounts (accounts) {
|
||||
return this._transport
|
||||
.execute('personal_importGethAccounts', (accounts || []).map(inAddress))
|
||||
.then((accounts) => (accounts || []).map(outAddress));
|
||||
}
|
||||
|
||||
newAccount (password) {
|
||||
return this._transport
|
||||
.execute('personal_newAccount', password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
newAccountFromPhrase (phrase, password) {
|
||||
return this._transport
|
||||
.execute('personal_newAccountFromPhrase', phrase, password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
newAccountFromSecret (secret, password) {
|
||||
return this._transport
|
||||
.execute('personal_newAccountFromSecret', inHex(secret), password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
newAccountFromWallet (json, password) {
|
||||
return this._transport
|
||||
.execute('personal_newAccountFromWallet', json, password)
|
||||
.then(outAddress);
|
||||
}
|
||||
|
||||
rejectRequest (requestId) {
|
||||
return this._transport
|
||||
.execute('personal_rejectRequest', inNumber16(requestId));
|
||||
}
|
||||
|
||||
requestsToConfirm () {
|
||||
return this._transport
|
||||
.execute('personal_requestsToConfirm')
|
||||
.then((requests) => (requests || []).map(outSignerRequest));
|
||||
}
|
||||
|
||||
setAccountName (address, name) {
|
||||
return this._transport
|
||||
.execute('personal_setAccountName', inAddress(address), name);
|
||||
}
|
||||
|
||||
setAccountMeta (address, meta) {
|
||||
return this._transport
|
||||
.execute('personal_setAccountMeta', inAddress(address), JSON.stringify(meta));
|
||||
}
|
||||
|
||||
signAndSendTransaction (options, password) {
|
||||
return this._transport
|
||||
.execute('personal_signAndSendTransaction', inOptions(options), password);
|
||||
}
|
||||
|
||||
signerEnabled () {
|
||||
return this._transport
|
||||
.execute('personal_signerEnabled');
|
||||
}
|
||||
|
||||
testPassword (account, password) {
|
||||
return this._transport
|
||||
.execute('personal_testPassword', inAddress(account), password);
|
||||
}
|
||||
|
||||
unlockAccount (account, password, duration = 1) {
|
||||
return this._transport
|
||||
.execute('personal_unlockAccount', inAddress(account), password, inNumber10(duration));
|
||||
|
@ -26,28 +26,6 @@ describe('rpc/Personal', () => {
|
||||
const checksum = '0x63Cf90D3f0410092FC0fca41846f596223979195';
|
||||
let scope;
|
||||
|
||||
describe('accountsInfo', () => {
|
||||
it('retrieves the available account info', () => {
|
||||
scope = mockHttp([{ method: 'personal_accountsInfo', reply: {
|
||||
result: {
|
||||
'0x63cf90d3f0410092fc0fca41846f596223979195': {
|
||||
name: 'name', uuid: 'uuid', meta: '{"data":"data"}'
|
||||
}
|
||||
}
|
||||
} }]);
|
||||
|
||||
return instance.accountsInfo().then((result) => {
|
||||
expect(result).to.deep.equal({
|
||||
'0x63Cf90D3f0410092FC0fca41846f596223979195': {
|
||||
name: 'name', uuid: 'uuid', meta: {
|
||||
data: 'data'
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('listAccounts', () => {
|
||||
it('retrieves a list of available accounts', () => {
|
||||
scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: [account] } }]);
|
||||
|
17
js/src/api/rpc/signer/index.js
Normal file
17
js/src/api/rpc/signer/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2015, 2016 Ethcore (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 './signer';
|
50
js/src/api/rpc/signer/signer.js
Normal file
50
js/src/api/rpc/signer/signer.js
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright 2015, 2016 Ethcore (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 { inNumber16 } from '../../format/input';
|
||||
import { outSignerRequest } from '../../format/output';
|
||||
|
||||
export default class Signer {
|
||||
constructor (transport) {
|
||||
this._transport = transport;
|
||||
}
|
||||
|
||||
confirmRequest (requestId, options, password) {
|
||||
return this._transport
|
||||
.execute('signer_confirmRequest', inNumber16(requestId), options, password);
|
||||
}
|
||||
|
||||
generateAuthorizationToken () {
|
||||
return this._transport
|
||||
.execute('signer_generateAuthorizationToken');
|
||||
}
|
||||
|
||||
rejectRequest (requestId) {
|
||||
return this._transport
|
||||
.execute('signer_rejectRequest', inNumber16(requestId));
|
||||
}
|
||||
|
||||
requestsToConfirm () {
|
||||
return this._transport
|
||||
.execute('signer_requestsToConfirm')
|
||||
.then((requests) => (requests || []).map(outSignerRequest));
|
||||
}
|
||||
|
||||
signerEnabled () {
|
||||
return this._transport
|
||||
.execute('signer_signerEnabled');
|
||||
}
|
||||
}
|
@ -24,9 +24,9 @@ import Signer from './signer';
|
||||
const events = {
|
||||
'logging': { module: 'logging' },
|
||||
'eth_blockNumber': { module: 'eth' },
|
||||
'personal_accountsInfo': { module: 'personal' },
|
||||
'personal_listAccounts': { module: 'personal' },
|
||||
'personal_requestsToConfirm': { module: 'signer' }
|
||||
'parity_accountsInfo': { module: 'personal' },
|
||||
'eth_accounts': { module: 'personal' },
|
||||
'signer_requestsToConfirm': { module: 'signer' }
|
||||
};
|
||||
|
||||
export default class Manager {
|
||||
|
@ -37,18 +37,18 @@ export default class Personal {
|
||||
}
|
||||
|
||||
_listAccounts = () => {
|
||||
return this._api.personal
|
||||
.listAccounts()
|
||||
return this._api.eth
|
||||
.accounts()
|
||||
.then((accounts) => {
|
||||
this._updateSubscriptions('personal_listAccounts', null, accounts);
|
||||
this._updateSubscriptions('eth_accounts', null, accounts);
|
||||
});
|
||||
}
|
||||
|
||||
_accountsInfo = () => {
|
||||
return this._api.personal
|
||||
return this._api.parity
|
||||
.accountsInfo()
|
||||
.then((info) => {
|
||||
this._updateSubscriptions('personal_accountsInfo', null, info);
|
||||
this._updateSubscriptions('parity_accountsInfo', null, info);
|
||||
});
|
||||
}
|
||||
|
||||
@ -59,16 +59,16 @@ export default class Personal {
|
||||
}
|
||||
|
||||
switch (data.method) {
|
||||
case 'personal_importGethAccounts':
|
||||
case 'parity_importGethAccounts':
|
||||
case 'personal_newAccount':
|
||||
case 'personal_newAccountFromPhrase':
|
||||
case 'personal_newAccountFromWallet':
|
||||
case 'parity_newAccountFromPhrase':
|
||||
case 'parity_newAccountFromWallet':
|
||||
this._listAccounts();
|
||||
this._accountsInfo();
|
||||
return;
|
||||
|
||||
case 'personal_setAccountName':
|
||||
case 'personal_setAccountMeta':
|
||||
case 'parity_setAccountName':
|
||||
case 'parity_setAccountMeta':
|
||||
this._accountsInfo();
|
||||
return;
|
||||
}
|
||||
|
@ -34,14 +34,15 @@ function stubApi (accounts, info) {
|
||||
|
||||
return {
|
||||
_calls,
|
||||
personal: {
|
||||
parity: {
|
||||
accountsInfo: () => {
|
||||
const stub = sinon.stub().resolves(info || TEST_INFO)();
|
||||
_calls.accountsInfo.push(stub);
|
||||
return stub;
|
||||
},
|
||||
|
||||
listAccounts: () => {
|
||||
}
|
||||
},
|
||||
eth: {
|
||||
accounts: () => {
|
||||
const stub = sinon.stub().resolves(accounts || TEST_LIST)();
|
||||
_calls.listAccounts.push(stub);
|
||||
return stub;
|
||||
@ -85,17 +86,17 @@ describe('api/subscriptions/personal', () => {
|
||||
expect(personal.isStarted).to.be.true;
|
||||
});
|
||||
|
||||
it('calls personal_accountsInfo', () => {
|
||||
it('calls parity_accountsInfo', () => {
|
||||
expect(api._calls.accountsInfo.length).to.be.ok;
|
||||
});
|
||||
|
||||
it('calls personal_listAccounts', () => {
|
||||
it('calls eth_accounts', () => {
|
||||
expect(api._calls.listAccounts.length).to.be.ok;
|
||||
});
|
||||
|
||||
it('updates subscribers', () => {
|
||||
expect(cb.firstCall).to.have.been.calledWith('personal_listAccounts', null, TEST_LIST);
|
||||
expect(cb.secondCall).to.have.been.calledWith('personal_accountsInfo', null, TEST_INFO);
|
||||
expect(cb.firstCall).to.have.been.calledWith('eth_accounts', null, TEST_LIST);
|
||||
expect(cb.secondCall).to.have.been.calledWith('parity_accountsInfo', null, TEST_INFO);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -49,10 +49,10 @@ export default class Signer {
|
||||
return;
|
||||
}
|
||||
|
||||
return this._api.personal
|
||||
return this._api.signer
|
||||
.requestsToConfirm()
|
||||
.then((requests) => {
|
||||
this._updateSubscriptions('personal_requestsToConfirm', null, requests);
|
||||
this._updateSubscriptions('signer_requestsToConfirm', null, requests);
|
||||
nextTimeout();
|
||||
})
|
||||
.catch(nextTimeout);
|
||||
@ -65,7 +65,7 @@ export default class Signer {
|
||||
}
|
||||
|
||||
switch (data.method) {
|
||||
case 'eth_postTransaction':
|
||||
case 'parity_postTransaction':
|
||||
case 'eth_sendTranasction':
|
||||
case 'eth_sendRawTransaction':
|
||||
this._listRequests(false);
|
||||
|
@ -56,6 +56,8 @@ export default class Http extends JsonRpcBase {
|
||||
if (response.status !== 200) {
|
||||
this._connected = false;
|
||||
this.error(JSON.stringify({ status: response.status, statusText: response.statusText }));
|
||||
console.error(`${method}(${JSON.stringify(params)}): ${response.status}: ${response.statusText}`);
|
||||
|
||||
throw new Error(`${response.status}: ${response.statusText}`);
|
||||
}
|
||||
|
||||
@ -66,7 +68,9 @@ export default class Http extends JsonRpcBase {
|
||||
|
||||
if (response.error) {
|
||||
this.error(JSON.stringify(response));
|
||||
throw new Error(`${response.error.code}: ${response.error.message}`);
|
||||
console.error(`${method}(${JSON.stringify(params)}): ${response.error.code}: ${response.error.message}`);
|
||||
|
||||
throw new Error(`${method}: ${response.error.code}: ${response.error.message}`);
|
||||
}
|
||||
|
||||
this.log(JSON.stringify(response));
|
||||
|
@ -107,7 +107,9 @@ export default class Ws extends JsonRpcBase {
|
||||
if (result.error) {
|
||||
this.error(event.data);
|
||||
|
||||
reject(new Error(`${result.error.code}: ${result.error.message}`));
|
||||
console.error(`${method}(${JSON.stringify(params)}): ${result.error.code}: ${result.error.message}`);
|
||||
|
||||
reject(new Error(`${method}: ${result.error.code}: ${result.error.message}`));
|
||||
delete this._messages[result.id];
|
||||
return;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export default class Registry {
|
||||
return;
|
||||
}
|
||||
|
||||
this._api.ethcore
|
||||
this._api.parity
|
||||
.registryAddress()
|
||||
.then((address) => {
|
||||
this._instance = this._api.newContract(abis.registry, address).instance;
|
||||
|
@ -83,7 +83,7 @@ export default class Application extends Component {
|
||||
Promise
|
||||
.all([
|
||||
attachInstances(),
|
||||
api.personal.accountsInfo()
|
||||
api.parity.accounts()
|
||||
])
|
||||
.then(([{ managerInstance, registryInstance, tokenregInstance }, accountsInfo]) => {
|
||||
accountsInfo = accountsInfo || {};
|
||||
|
@ -296,7 +296,7 @@ export default class Deployment extends Component {
|
||||
.then((signerRequestId) => {
|
||||
this.setState({ signerRequestId, deployState: 'Transaction posted, Waiting for transaction authorization' });
|
||||
|
||||
return api.pollMethod('eth_checkRequest', signerRequestId);
|
||||
return api.pollMethod('parity_checkRequest', signerRequestId);
|
||||
})
|
||||
.then((txHash) => {
|
||||
this.setState({ txHash, deployState: 'Transaction authorized, Waiting for network confirmations' });
|
||||
|
@ -279,7 +279,7 @@ export default class Send extends Component {
|
||||
.then((signerRequestId) => {
|
||||
this.setState({ signerRequestId, sendState: 'Transaction posted, Waiting for transaction authorization' });
|
||||
|
||||
return api.pollMethod('eth_checkRequest', signerRequestId);
|
||||
return api.pollMethod('parity_checkRequest', signerRequestId);
|
||||
})
|
||||
.then((txHash) => {
|
||||
this.setState({ txHash, sendState: 'Transaction authorized, Waiting for network confirmations' });
|
||||
|
@ -100,8 +100,8 @@ export function attachInstances () {
|
||||
|
||||
return Promise
|
||||
.all([
|
||||
api.ethcore.registryAddress(),
|
||||
api.ethcore.netChain()
|
||||
api.parity.registryAddress(),
|
||||
api.parity.netChain()
|
||||
])
|
||||
.then(([registryAddress, netChain]) => {
|
||||
const registry = api.newContract(abis.registry, registryAddress).instance;
|
||||
|
@ -11,7 +11,6 @@
|
||||
<div id="container"></div>
|
||||
<script src="vendor.js"></script>
|
||||
<script src="commons.js"></script>
|
||||
<script src="/parity-utils/parity.js"></script>
|
||||
<script src="githubhint.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -41,7 +41,9 @@ export default class Application extends Component {
|
||||
registerBusy: false,
|
||||
registerError: null,
|
||||
registerState: '',
|
||||
registerType: 'file'
|
||||
registerType: 'file',
|
||||
repo: '',
|
||||
repoError: null
|
||||
}
|
||||
|
||||
componentDidMount () {
|
||||
@ -206,47 +208,64 @@ export default class Application extends Component {
|
||||
}
|
||||
|
||||
onChangeCommit = (event) => {
|
||||
const commit = event.target.value;
|
||||
let commit = event.target.value;
|
||||
const commitError = null;
|
||||
let hasContent = false;
|
||||
|
||||
// TODO: field validation
|
||||
this.setState({ commit, commitError, contentHashError: null }, () => {
|
||||
const { repo } = this.state || '';
|
||||
const parts = repo.split('/');
|
||||
|
||||
this.setState({ commit, commitError, contentHashError: 'hash lookup in progress' }, () => {
|
||||
const { repo } = this.state;
|
||||
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`);
|
||||
hasContent = commit.length !== 0 && parts.length === 2 && parts[0].length !== 0 && parts[1].length !== 0;
|
||||
if (!commitError && hasContent) {
|
||||
this.setState({ contentHashError: 'hash lookup in progress' });
|
||||
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onChangeRepo = (event) => {
|
||||
let repo = event.target.value;
|
||||
const repoError = null;
|
||||
let hasContent = false;
|
||||
|
||||
// TODO: field validation
|
||||
if (!repoError) {
|
||||
repo = repo.replace('https://github.com/', '');
|
||||
}
|
||||
|
||||
this.setState({ repo, repoError, contentHashError: 'hash lookup in progress' }, () => {
|
||||
const { commit } = this.state;
|
||||
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`);
|
||||
this.setState({ repo, repoError, contentHashError: null }, () => {
|
||||
const { commit } = this.state || '';
|
||||
const parts = repo.split('/');
|
||||
|
||||
hasContent = commit.length !== 0 && parts.length === 2 && parts[0].length !== 0 && parts[1].length !== 0;
|
||||
if (!repoError && hasContent) {
|
||||
this.setState({ contentHashError: 'hash lookup in progress' });
|
||||
this.lookupHash(`https://codeload.github.com/${repo}/zip/${commit}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onChangeUrl = (event) => {
|
||||
let url = event.target.value;
|
||||
const urlError = null;
|
||||
let hasContent = false;
|
||||
|
||||
// TODO: field validation
|
||||
if (!urlError) {
|
||||
const parts = url.split('/');
|
||||
hasContent = parts.length !== 0;
|
||||
|
||||
if (parts[2] === 'github.com' || parts[2] === 'raw.githubusercontent.com') {
|
||||
url = `https://raw.githubusercontent.com/${parts.slice(3).join('/')}`.replace('/blob/', '/');
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({ url, urlError, contentHashError: 'hash lookup in progress' }, () => {
|
||||
this.lookupHash(url);
|
||||
this.setState({ url, urlError, contentHashError: null }, () => {
|
||||
if (!urlError && hasContent) {
|
||||
this.setState({ contentHashError: 'hash lookup in progress' });
|
||||
this.lookupHash(url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -271,7 +290,7 @@ export default class Application extends Component {
|
||||
.then((signerRequestId) => {
|
||||
this.setState({ signerRequestId, registerState: 'Transaction posted, Waiting for transaction authorization' });
|
||||
|
||||
return api.pollMethod('eth_checkRequest', signerRequestId);
|
||||
return api.pollMethod('parity_checkRequest', signerRequestId);
|
||||
})
|
||||
.then((txHash) => {
|
||||
this.setState({ txHash, registerState: 'Transaction authorized, Waiting for network confirmations' });
|
||||
@ -285,7 +304,7 @@ export default class Application extends Component {
|
||||
});
|
||||
})
|
||||
.then((txReceipt) => {
|
||||
this.setState({ txReceipt, registerBusy: false, registerState: 'Network confirmed, Received transaction receipt', url: '', commit: '', commitError: null, contentHash: '', contentHashOwner: null, contentHashError: null });
|
||||
this.setState({ txReceipt, registerBusy: false, registerState: 'Network confirmed, Received transaction receipt', url: '', commit: '', repo: '', commitError: null, contentHash: '', contentHashOwner: null, contentHashError: null });
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('onSend', error);
|
||||
@ -298,7 +317,7 @@ export default class Application extends Component {
|
||||
|
||||
this.setState({ registerBusy: true, registerState: 'Estimating gas for the transaction' });
|
||||
|
||||
const values = [contentHash, repo, commit];
|
||||
const values = [contentHash, repo, commit.substr(0, 2) === '0x' ? commit : `0x${commit}`];
|
||||
const options = { from: fromAddress };
|
||||
|
||||
this.trackRequest(
|
||||
@ -367,7 +386,7 @@ export default class Application extends Component {
|
||||
|
||||
console.log(`lookupHash ${url}`);
|
||||
|
||||
api.ethcore
|
||||
api.parity
|
||||
.hashContent(url)
|
||||
.then((contentHash) => {
|
||||
console.log('lookupHash', contentHash);
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
const { api } = window.parity;
|
||||
const api = window.parent.secureApi;
|
||||
|
||||
export {
|
||||
api
|
||||
|
@ -18,7 +18,7 @@ import * as abis from '../../contracts/abi';
|
||||
import { api } from './parity';
|
||||
|
||||
export function attachInterface () {
|
||||
return api.ethcore
|
||||
return api.parity
|
||||
.registryAddress()
|
||||
.then((registryAddress) => {
|
||||
console.log(`the registry was found at ${registryAddress}`);
|
||||
@ -29,7 +29,7 @@ export function attachInterface () {
|
||||
.all([
|
||||
registry.getAddress.call({}, [api.util.sha3('githubhint'), 'A']),
|
||||
api.eth.accounts(),
|
||||
api.personal.accountsInfo()
|
||||
api.parity.accounts()
|
||||
]);
|
||||
})
|
||||
.then(([address, addresses, accountsInfo]) => {
|
||||
|
@ -29,7 +29,7 @@ export { addresses, accounts, lookup, events, names, records };
|
||||
export const setContract = (contract) => ({ type: 'set contract', contract });
|
||||
|
||||
export const fetchContract = () => (dispatch) =>
|
||||
api.ethcore.registryAddress()
|
||||
api.parity.registryAddress()
|
||||
.then((address) => {
|
||||
const contract = api.newContract(registryAbi, address);
|
||||
dispatch(setContract(contract));
|
||||
|
@ -22,7 +22,7 @@ export const fetch = () => (dispatch) => {
|
||||
return Promise
|
||||
.all([
|
||||
api.eth.accounts(),
|
||||
api.personal.accountsInfo()
|
||||
api.parity.accounts()
|
||||
])
|
||||
.then(([ accounts, data ]) => {
|
||||
data = data || {};
|
||||
|
@ -39,7 +39,7 @@ const logToEvent = (log) => {
|
||||
};
|
||||
|
||||
export function attachInterface (callback) {
|
||||
return api.ethcore
|
||||
return api.parity
|
||||
.registryAddress()
|
||||
.then((registryAddress) => {
|
||||
console.log(`the registry was found at ${registryAddress}`);
|
||||
@ -50,7 +50,7 @@ export function attachInterface (callback) {
|
||||
.all([
|
||||
registry.getAddress.call({}, [api.util.sha3('signaturereg'), 'A']),
|
||||
api.eth.accounts(),
|
||||
api.personal.accountsInfo()
|
||||
api.parity.accounts()
|
||||
]);
|
||||
})
|
||||
.then(([address, addresses, accountsInfo]) => {
|
||||
|
@ -38,7 +38,7 @@ export const loadAccounts = () => (dispatch) => {
|
||||
Promise
|
||||
.all([
|
||||
api.eth.accounts(),
|
||||
api.personal.accountsInfo()
|
||||
api.parity.accounts()
|
||||
])
|
||||
.then(([ accounts, accountsInfo ]) => {
|
||||
accountsInfo = accountsInfo || {};
|
||||
|
@ -34,7 +34,7 @@ export const FIND_CONTRACT = 'FIND_CONTRACT';
|
||||
export const loadContract = () => (dispatch) => {
|
||||
dispatch(setLoading(true));
|
||||
|
||||
api.ethcore
|
||||
api.parity
|
||||
.registryAddress()
|
||||
.then((registryAddress) => {
|
||||
console.log(`registry found at ${registryAddress}`);
|
||||
|
@ -72,7 +72,7 @@ ReactDOM.render(
|
||||
<Route path='addresses' component={ Addresses } />
|
||||
<Route path='address/:address' component={ Address } />
|
||||
<Route path='apps' component={ Dapps } />
|
||||
<Route path='app/:type/:name' component={ Dapp } />
|
||||
<Route path='app/:id' component={ Dapp } />
|
||||
<Route path='contracts' component={ Contracts } />
|
||||
<Route path='contract/:address' component={ Contract } />
|
||||
<Route path='settings' component={ Settings }>
|
||||
|
@ -16,20 +16,22 @@
|
||||
|
||||
import db from './interfaces/db';
|
||||
import eth from './interfaces/eth';
|
||||
import ethcore from './interfaces/ethcore';
|
||||
import net from './interfaces/net';
|
||||
import parity from './interfaces/parity';
|
||||
import personal from './interfaces/personal';
|
||||
import shh from './interfaces/shh';
|
||||
import signer from './interfaces/signer';
|
||||
import trace from './interfaces/trace';
|
||||
import web3 from './interfaces/web3';
|
||||
|
||||
export default {
|
||||
db: db,
|
||||
eth: eth,
|
||||
ethcore: ethcore,
|
||||
net: net,
|
||||
personal: personal,
|
||||
shh: shh,
|
||||
trace: trace,
|
||||
web3: web3
|
||||
db,
|
||||
eth,
|
||||
parity,
|
||||
net,
|
||||
personal,
|
||||
shh,
|
||||
signer,
|
||||
trace,
|
||||
web3
|
||||
};
|
||||
|
@ -86,20 +86,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
checkRequest: {
|
||||
desc: 'Returns the transactionhash of the requestId (received from eth_postTransaction) if the request was confirmed',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The requestId to check for'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Hash,
|
||||
desc: '32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available'
|
||||
}
|
||||
},
|
||||
|
||||
coinbase: {
|
||||
desc: 'Returns the client coinbase address.',
|
||||
params: [],
|
||||
@ -823,22 +809,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
postTransaction: {
|
||||
desc: 'Posts a transaction to the Signer.',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
desc: 'see [eth_sendTransaction](#eth_sendTransaction)',
|
||||
format: 'inputCallFormatter'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Quantity,
|
||||
desc: 'The id of the actual transaction',
|
||||
format: 'utils.toDecimal'
|
||||
}
|
||||
},
|
||||
|
||||
protocolVersion: {
|
||||
desc: 'Returns the current ethereum protocol version.',
|
||||
params: [],
|
||||
|
@ -26,6 +26,52 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
accounts: {
|
||||
desc: 'returns a map of accounts as an object',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Account metadata',
|
||||
details: {
|
||||
name: {
|
||||
type: String,
|
||||
desc: 'Account name'
|
||||
},
|
||||
meta: {
|
||||
type: String,
|
||||
desc: 'Encoded JSON string the defines additional account metadata'
|
||||
},
|
||||
uuid: {
|
||||
type: String,
|
||||
desc: 'The account UUID, or null if not available/unknown/not applicable.'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
accountsInfo: {
|
||||
desc: 'returns a map of accounts as an object',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Account metadata',
|
||||
details: {
|
||||
name: {
|
||||
type: String,
|
||||
desc: 'Account name'
|
||||
},
|
||||
meta: {
|
||||
type: String,
|
||||
desc: 'Encoded JSON string the defines additional account metadata'
|
||||
},
|
||||
uuid: {
|
||||
type: String,
|
||||
desc: 'The account UUID, or null if not available/unknown/not applicable.'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addReservedPeer: {
|
||||
desc: '?',
|
||||
params: [
|
||||
@ -40,6 +86,20 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
checkRequest: {
|
||||
desc: 'Returns the transactionhash of the requestId (received from parity_postTransaction) if the request was confirmed',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The requestId to check for'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Hash,
|
||||
desc: '32 Bytes - the transaction hash, or the zero hash if the transaction is not yet available'
|
||||
}
|
||||
},
|
||||
|
||||
dappsPort: {
|
||||
desc: 'Returns the port the dapps are running on, error if not enabled',
|
||||
params: [],
|
||||
@ -155,6 +215,29 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
listGethAccounts: {
|
||||
desc: 'Returns a list of the accounts available from Geth',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: '20 Bytes addresses owned by the client.'
|
||||
}
|
||||
},
|
||||
|
||||
importGethAccounts: {
|
||||
desc: 'Imports a list of accounts from geth',
|
||||
params: [
|
||||
{
|
||||
type: Array,
|
||||
desc: 'List of the geth addresses to import'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Array of the imported addresses'
|
||||
}
|
||||
},
|
||||
|
||||
minGasPrice: {
|
||||
desc: 'Returns currently set minimal gas price',
|
||||
params: [],
|
||||
@ -210,6 +293,60 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
newAccountFromPhrase: {
|
||||
desc: 'Creates a new account from a recovery passphrase',
|
||||
params: [
|
||||
{
|
||||
type: String,
|
||||
desc: 'Phrase'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
}
|
||||
},
|
||||
|
||||
newAccountFromSecret: {
|
||||
desc: 'Creates a new account from a private ethstore secret key',
|
||||
params: [
|
||||
{
|
||||
type: Data,
|
||||
desc: 'Secret, 32-byte hex'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
}
|
||||
},
|
||||
|
||||
newAccountFromWallet: {
|
||||
desc: 'Creates a new account from a JSON import',
|
||||
params: [
|
||||
{
|
||||
type: String,
|
||||
desc: 'JSON'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
}
|
||||
},
|
||||
|
||||
nodeName: {
|
||||
desc: 'Returns node name (identity)',
|
||||
params: [],
|
||||
@ -233,6 +370,22 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
postTransaction: {
|
||||
desc: 'Posts a transaction to the Signer.',
|
||||
params: [
|
||||
{
|
||||
type: Object,
|
||||
desc: 'see [eth_sendTransaction](#eth_sendTransaction)',
|
||||
format: 'inputCallFormatter'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Quantity,
|
||||
desc: 'The id of the actual transaction',
|
||||
format: 'utils.toDecimal'
|
||||
}
|
||||
},
|
||||
|
||||
removeReservedPeer: {
|
||||
desc: '?',
|
||||
params: [
|
||||
@ -265,6 +418,42 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
setAccountName: {
|
||||
desc: 'Sets a name for the account',
|
||||
params: [
|
||||
{
|
||||
type: Address,
|
||||
desc: 'Address'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Name'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Returns null in all cases'
|
||||
}
|
||||
},
|
||||
|
||||
setAccountMeta: {
|
||||
desc: 'Sets metadata for the account',
|
||||
params: [
|
||||
{
|
||||
type: Address,
|
||||
desc: 'Address'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Metadata (JSON encoded)'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Returns null in all cases'
|
||||
}
|
||||
},
|
||||
|
||||
setAuthor: {
|
||||
desc: 'Changes author (coinbase) for mined blocks.',
|
||||
params: [
|
@ -17,83 +17,6 @@
|
||||
import { Address, Data, Quantity } from '../types';
|
||||
|
||||
export default {
|
||||
accountsInfo: {
|
||||
desc: 'returns a map of accounts as an object',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Account metadata',
|
||||
details: {
|
||||
name: {
|
||||
type: String,
|
||||
desc: 'Account name'
|
||||
},
|
||||
meta: {
|
||||
type: String,
|
||||
desc: 'Encoded JSON string the defines additional account metadata'
|
||||
},
|
||||
uuid: {
|
||||
type: String,
|
||||
desc: 'The account UUID, or null if not available/unknown/not applicable.'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
generateAuthorizationToken: {
|
||||
desc: 'Generates a new authorization token',
|
||||
params: [],
|
||||
returns: {
|
||||
type: String,
|
||||
desc: 'The new authorization token'
|
||||
}
|
||||
},
|
||||
|
||||
requestsToConfirm: {
|
||||
desc: 'Returns a list of the transactions requiring authorization',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'A list of the outstanding transactions'
|
||||
}
|
||||
},
|
||||
|
||||
confirmRequest: {
|
||||
desc: 'Confirm a request in the signer queue',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The request id'
|
||||
},
|
||||
{
|
||||
type: Object,
|
||||
desc: 'The request options'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'The account password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'The status of the confirmation'
|
||||
}
|
||||
},
|
||||
|
||||
rejectRequest: {
|
||||
desc: 'Rejects a request in the signer queue',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The request id'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'The status of the rejection'
|
||||
}
|
||||
},
|
||||
|
||||
listAccounts: {
|
||||
desc: 'Returns a list of addresses owned by client.',
|
||||
params: [],
|
||||
@ -103,29 +26,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
listGethAccounts: {
|
||||
desc: 'Returns a list of the accounts available from Geth',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: '20 Bytes addresses owned by the client.'
|
||||
}
|
||||
},
|
||||
|
||||
importGethAccounts: {
|
||||
desc: 'Imports a list of accounts from geth',
|
||||
params: [
|
||||
{
|
||||
type: Array,
|
||||
desc: 'List of the geth addresses to import'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'Array of the imported addresses'
|
||||
}
|
||||
},
|
||||
|
||||
newAccount: {
|
||||
desc: 'Creates new account',
|
||||
params: [
|
||||
@ -140,96 +40,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
newAccountFromPhrase: {
|
||||
desc: 'Creates a new account from a recovery passphrase',
|
||||
params: [
|
||||
{
|
||||
type: String,
|
||||
desc: 'Phrase'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
}
|
||||
},
|
||||
|
||||
newAccountFromSecret: {
|
||||
desc: 'Creates a new account from a private ethstore secret key',
|
||||
params: [
|
||||
{
|
||||
type: Data,
|
||||
desc: 'Secret, 32-byte hex'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
}
|
||||
},
|
||||
|
||||
newAccountFromWallet: {
|
||||
desc: 'Creates a new account from a JSON import',
|
||||
params: [
|
||||
{
|
||||
type: String,
|
||||
desc: 'JSON'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Address,
|
||||
desc: 'The created address'
|
||||
}
|
||||
},
|
||||
|
||||
setAccountName: {
|
||||
desc: 'Sets a name for the account',
|
||||
params: [
|
||||
{
|
||||
type: Address,
|
||||
desc: 'Address'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Name'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Returns null in all cases'
|
||||
}
|
||||
},
|
||||
|
||||
setAccountMeta: {
|
||||
desc: 'Sets metadata for the account',
|
||||
params: [
|
||||
{
|
||||
type: Address,
|
||||
desc: 'Address'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'Metadata (JSON encoded)'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Object,
|
||||
desc: 'Returns null in all cases'
|
||||
}
|
||||
},
|
||||
|
||||
signAndSendTransaction: {
|
||||
desc: 'Sends and signs a transaction given account passphrase. Does not require the account to be unlocked nor unlocks the account for future transactions. ',
|
||||
params: [
|
||||
@ -284,15 +94,6 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
signerEnabled: {
|
||||
desc: 'Returns whether signer is enabled/disabled.',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'true when enabled, false when disabled'
|
||||
}
|
||||
},
|
||||
|
||||
unlockAccount: {
|
||||
desc: '?',
|
||||
params: [
|
||||
|
82
js/src/jsonrpc/interfaces/signer.js
Normal file
82
js/src/jsonrpc/interfaces/signer.js
Normal file
@ -0,0 +1,82 @@
|
||||
// Copyright 2015, 2016 Ethcore (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 { Quantity } from '../types';
|
||||
|
||||
export default {
|
||||
generateAuthorizationToken: {
|
||||
desc: 'Generates a new authorization token',
|
||||
params: [],
|
||||
returns: {
|
||||
type: String,
|
||||
desc: 'The new authorization token'
|
||||
}
|
||||
},
|
||||
|
||||
requestsToConfirm: {
|
||||
desc: 'Returns a list of the transactions requiring authorization',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Array,
|
||||
desc: 'A list of the outstanding transactions'
|
||||
}
|
||||
},
|
||||
|
||||
confirmRequest: {
|
||||
desc: 'Confirm a request in the signer queue',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The request id'
|
||||
},
|
||||
{
|
||||
type: Object,
|
||||
desc: 'The request options'
|
||||
},
|
||||
{
|
||||
type: String,
|
||||
desc: 'The account password'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'The status of the confirmation'
|
||||
}
|
||||
},
|
||||
|
||||
rejectRequest: {
|
||||
desc: 'Rejects a request in the signer queue',
|
||||
params: [
|
||||
{
|
||||
type: Quantity,
|
||||
desc: 'The request id'
|
||||
}
|
||||
],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'The status of the rejection'
|
||||
}
|
||||
},
|
||||
|
||||
signerEnabled: {
|
||||
desc: 'Returns whether signer is enabled/disabled.',
|
||||
params: [],
|
||||
returns: {
|
||||
type: Boolean,
|
||||
desc: 'true when enabled, false when disabled'
|
||||
}
|
||||
}
|
||||
};
|
@ -133,8 +133,8 @@ export default class AddAddress extends Component {
|
||||
const { address, name, description } = this.state;
|
||||
|
||||
Promise.all([
|
||||
api.personal.setAccountName(address, name),
|
||||
api.personal.setAccountMeta(address, {
|
||||
api.parity.setAccountName(address, name),
|
||||
api.parity.setAccountMeta(address, {
|
||||
description,
|
||||
timestamp: Date.now(),
|
||||
deleted: false
|
||||
|
@ -141,8 +141,8 @@ export default class AddContract extends Component {
|
||||
const { abiParsed, address, name, description } = this.state;
|
||||
|
||||
Promise.all([
|
||||
api.personal.setAccountName(address, name),
|
||||
api.personal.setAccountMeta(address, {
|
||||
api.parity.setAccountName(address, name),
|
||||
api.parity.setAccountMeta(address, {
|
||||
contract: true,
|
||||
deleted: false,
|
||||
timestamp: Date.now(),
|
||||
|
@ -173,15 +173,15 @@ export default class CreateAccount extends Component {
|
||||
|
||||
Promise
|
||||
.all([
|
||||
api.ethcore.generateSecretPhrase(),
|
||||
api.ethcore.generateSecretPhrase(),
|
||||
api.ethcore.generateSecretPhrase(),
|
||||
api.ethcore.generateSecretPhrase(),
|
||||
api.ethcore.generateSecretPhrase()
|
||||
api.parity.generateSecretPhrase(),
|
||||
api.parity.generateSecretPhrase(),
|
||||
api.parity.generateSecretPhrase(),
|
||||
api.parity.generateSecretPhrase(),
|
||||
api.parity.generateSecretPhrase()
|
||||
])
|
||||
.then((phrases) => {
|
||||
return Promise
|
||||
.all(phrases.map((phrase) => api.ethcore.phraseToAddress(phrase)))
|
||||
.all(phrases.map((phrase) => api.parity.phraseToAddress(phrase)))
|
||||
.then((addresses) => {
|
||||
const accounts = {};
|
||||
|
||||
|
@ -102,7 +102,7 @@ export default class NewGeth extends Component {
|
||||
const { api } = this.context;
|
||||
const { accounts } = this.props;
|
||||
|
||||
api.personal
|
||||
api.parity
|
||||
.listGethAccounts()
|
||||
.then((_addresses) => {
|
||||
const addresses = (addresses || []).filter((address) => !accounts[address]);
|
||||
|
@ -208,13 +208,13 @@ export default class CreateAccount extends Component {
|
||||
});
|
||||
|
||||
if (createType === 'fromNew' || createType === 'fromPhrase') {
|
||||
return api.personal
|
||||
return api.parity
|
||||
.newAccountFromPhrase(this.state.phrase, this.state.password)
|
||||
.then((address) => {
|
||||
this.setState({ address });
|
||||
return api.personal
|
||||
return api.parity
|
||||
.setAccountName(address, this.state.name)
|
||||
.then(() => api.personal.setAccountMeta(address, {
|
||||
.then(() => api.parity.setAccountMeta(address, {
|
||||
timestamp: Date.now(),
|
||||
passwordHint: this.state.passwordHint
|
||||
}));
|
||||
@ -233,13 +233,13 @@ export default class CreateAccount extends Component {
|
||||
this.newError(error);
|
||||
});
|
||||
} else if (createType === 'fromRaw') {
|
||||
return api.personal
|
||||
return api.parity
|
||||
.newAccountFromSecret(this.state.rawKey, this.state.password)
|
||||
.then((address) => {
|
||||
this.setState({ address });
|
||||
return api.personal
|
||||
return api.parity
|
||||
.setAccountName(address, this.state.name)
|
||||
.then(() => api.personal.setAccountMeta(address, {
|
||||
.then(() => api.parity.setAccountMeta(address, {
|
||||
timestamp: Date.now(),
|
||||
passwordHint: this.state.passwordHint
|
||||
}));
|
||||
@ -258,13 +258,13 @@ export default class CreateAccount extends Component {
|
||||
this.newError(error);
|
||||
});
|
||||
} else if (createType === 'fromGeth') {
|
||||
return api.personal
|
||||
return api.parity
|
||||
.importGethAccounts(this.state.gethAddresses)
|
||||
.then((result) => {
|
||||
console.log('result', result);
|
||||
|
||||
return Promise.all(this.state.gethAddresses.map((address) => {
|
||||
return api.personal.setAccountName(address, 'Geth Import');
|
||||
return api.parity.setAccountName(address, 'Geth Import');
|
||||
}));
|
||||
})
|
||||
.then(() => {
|
||||
@ -282,16 +282,16 @@ export default class CreateAccount extends Component {
|
||||
});
|
||||
}
|
||||
|
||||
return api.personal
|
||||
return api.parity
|
||||
.newAccountFromWallet(this.state.json, this.state.password)
|
||||
.then((address) => {
|
||||
this.setState({
|
||||
address: address
|
||||
});
|
||||
|
||||
return api.personal
|
||||
return api.parity
|
||||
.setAccountName(address, this.state.name)
|
||||
.then(() => api.personal.setAccountMeta(address, {
|
||||
.then(() => api.parity.setAccountMeta(address, {
|
||||
timestamp: Date.now(),
|
||||
passwordHint: this.state.passwordHint
|
||||
}));
|
||||
|
@ -212,8 +212,8 @@ export default class DeployContract extends Component {
|
||||
.deploy(options, params, this.onDeploymentState)
|
||||
.then((address) => {
|
||||
return Promise.all([
|
||||
api.personal.setAccountName(address, name),
|
||||
api.personal.setAccountMeta(address, {
|
||||
api.parity.setAccountName(address, name),
|
||||
api.parity.setAccountMeta(address, {
|
||||
abi: abiParsed,
|
||||
contract: true,
|
||||
timestamp: Date.now(),
|
||||
|
@ -139,8 +139,8 @@ export default class EditMeta extends Component {
|
||||
|
||||
Promise
|
||||
.all([
|
||||
api.personal.setAccountName(account.address, name),
|
||||
api.personal.setAccountMeta(account.address, Object.assign({}, account.meta, meta))
|
||||
api.parity.setAccountName(account.address, name),
|
||||
api.parity.setAccountMeta(account.address, Object.assign({}, account.meta, meta))
|
||||
])
|
||||
.then(() => this.props.onClose())
|
||||
.catch((error) => {
|
||||
|
@ -221,7 +221,7 @@ export default class ExecuteContract extends Component {
|
||||
})
|
||||
.then((requestId) => {
|
||||
this.setState({ busyState: 'Waiting for authorization in the Parity Signer' });
|
||||
return api.pollMethod('eth_checkRequest', requestId);
|
||||
return api.pollMethod('parity_checkRequest', requestId);
|
||||
})
|
||||
.then((txhash) => {
|
||||
this.setState({ sending: false, step: 2, txhash, busyState: 'Your transaction has been posted to the network' });
|
||||
|
@ -183,9 +183,9 @@ export default class FirstRun extends Component {
|
||||
canCreate: false
|
||||
});
|
||||
|
||||
return api.personal
|
||||
return api.parity
|
||||
.newAccountFromPhrase(phrase, password)
|
||||
.then((address) => api.personal.setAccountName(address, name))
|
||||
.then((address) => api.parity.setAccountName(address, name))
|
||||
.then(() => {
|
||||
this.onNext();
|
||||
})
|
||||
|
@ -317,7 +317,7 @@ export default class PasswordManager extends Component {
|
||||
this.setState({ waiting: true, showMessage: false });
|
||||
|
||||
this.context
|
||||
.api.personal
|
||||
.api.parity
|
||||
.testPassword(account.address, currentPass)
|
||||
.then(correct => {
|
||||
const message = correct
|
||||
@ -343,7 +343,7 @@ export default class PasswordManager extends Component {
|
||||
this.setState({ waiting: true, showMessage: false });
|
||||
|
||||
this.context
|
||||
.api.personal
|
||||
.api.parity
|
||||
.testPassword(account.address, currentPass)
|
||||
.then(correct => {
|
||||
if (!correct) {
|
||||
@ -363,11 +363,11 @@ export default class PasswordManager extends Component {
|
||||
|
||||
return Promise.all([
|
||||
this.context
|
||||
.api.personal
|
||||
.api.parity
|
||||
.setAccountMeta(account.address, meta),
|
||||
|
||||
this.context
|
||||
.api.personal
|
||||
.api.parity
|
||||
.changePassword(account.address, currentPass, newPass)
|
||||
])
|
||||
.then(() => {
|
||||
|
@ -123,7 +123,13 @@ export default class Details extends Component {
|
||||
.map((balance, index) => {
|
||||
const token = balance.token;
|
||||
const isEth = index === 0;
|
||||
const imagesrc = token.image || images[token.address] || imageUnknown;
|
||||
let imagesrc = token.image;
|
||||
if (!imagesrc) {
|
||||
imagesrc =
|
||||
images[token.address]
|
||||
? `${api.dappsUrl}${images[token.address]}`
|
||||
: imageUnknown;
|
||||
}
|
||||
let value = 0;
|
||||
|
||||
if (isEth) {
|
||||
|
@ -424,7 +424,7 @@ export default class Transfer extends Component {
|
||||
options.data = data;
|
||||
}
|
||||
|
||||
return api.eth.postTransaction(options);
|
||||
return api.parity.postTransaction(options);
|
||||
}
|
||||
|
||||
_sendToken () {
|
||||
@ -455,7 +455,7 @@ export default class Transfer extends Component {
|
||||
: this._sendToken()
|
||||
).then((requestId) => {
|
||||
this.setState({ busyState: 'Waiting for authorization in the Parity Signer' });
|
||||
return api.pollMethod('eth_checkRequest', requestId);
|
||||
return api.pollMethod('parity_checkRequest', requestId);
|
||||
})
|
||||
.then((txhash) => {
|
||||
this.onNext();
|
||||
@ -592,7 +592,7 @@ export default class Transfer extends Component {
|
||||
|
||||
Promise
|
||||
.all([
|
||||
api.ethcore.gasPriceHistogram(),
|
||||
api.parity.gasPriceHistogram(),
|
||||
api.eth.gasPrice()
|
||||
])
|
||||
.then(([gasPriceHistogram, gasPrice]) => {
|
||||
|
@ -42,7 +42,7 @@ export default class Balances {
|
||||
|
||||
_subscribeAccountsInfo () {
|
||||
this._api
|
||||
.subscribe('personal_accountsInfo', (error, accountsInfo) => {
|
||||
.subscribe('parity_accountsInfo', (error, accountsInfo) => {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
@ -76,7 +76,7 @@ export default class Balances {
|
||||
}
|
||||
|
||||
_retrieveTokens () {
|
||||
this._api.ethcore
|
||||
this._api.parity
|
||||
.registryAddress()
|
||||
.then((registryAddress) => {
|
||||
const registry = this._api.newContract(abis.registry, registryAddress);
|
||||
|
@ -17,8 +17,6 @@
|
||||
import { handleActions } from 'redux-actions';
|
||||
import { bytesToHex } from '../../api/util/format';
|
||||
|
||||
import { parityNode } from '../../environment';
|
||||
|
||||
const ZERO = '0x0000000000000000000000000000000000000000000000000000000000000000';
|
||||
|
||||
const initialState = {
|
||||
@ -28,7 +26,7 @@ const initialState = {
|
||||
export function hashToImageUrl (hashArray) {
|
||||
const hash = hashArray ? bytesToHex(hashArray) : ZERO;
|
||||
|
||||
return hash === ZERO ? null : `${parityNode}/api/content/${hash.substr(2)}`;
|
||||
return hash === ZERO ? null : `/api/content/${hash.substr(2)}`;
|
||||
}
|
||||
|
||||
export default handleActions({
|
||||
|
@ -28,9 +28,9 @@ export default class Personal {
|
||||
|
||||
_subscribeAccountsInfo () {
|
||||
this._api
|
||||
.subscribe('personal_accountsInfo', (error, accountsInfo) => {
|
||||
.subscribe('parity_accountsInfo', (error, accountsInfo) => {
|
||||
if (error) {
|
||||
console.error('personal_accountsInfo', error);
|
||||
console.error('parity_accountsInfo', error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -14,22 +14,6 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// Copyright 2015, 2016 Ethcore (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 { signerRequestsToConfirm } from './signerActions';
|
||||
|
||||
export default class Signer {
|
||||
@ -44,7 +28,7 @@ export default class Signer {
|
||||
|
||||
_subscribeRequestsToConfirm () {
|
||||
this._api
|
||||
.subscribe('personal_requestsToConfirm', (error, pending) => {
|
||||
.subscribe('signer_requestsToConfirm', (error, pending) => {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ export default class SignerMiddleware {
|
||||
onConfirmStart = (store, action) => {
|
||||
const { id, password } = action.payload;
|
||||
|
||||
this._api.personal
|
||||
this._api.signer
|
||||
.confirmRequest(id, {}, password)
|
||||
.then((txHash) => {
|
||||
console.log('confirmRequest', id, txHash);
|
||||
@ -71,7 +71,7 @@ export default class SignerMiddleware {
|
||||
onRejectStart = (store, action) => {
|
||||
const id = action.payload;
|
||||
|
||||
this._api.personal
|
||||
this._api.signer
|
||||
.rejectRequest(id)
|
||||
.then(() => {
|
||||
store.dispatch(actions.successRejectRequest({ id }));
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
import { statusBlockNumber, statusCollection, statusLogs } from './statusActions';
|
||||
|
||||
import { parityNode } from '../../environment';
|
||||
|
||||
export default class Status {
|
||||
constructor (store, api) {
|
||||
this._api = api;
|
||||
@ -33,8 +31,8 @@ export default class Status {
|
||||
}
|
||||
|
||||
_fetchEnode () {
|
||||
this._api
|
||||
.ethcore.enode()
|
||||
this._api.parity
|
||||
.enode()
|
||||
.then((enode) => {
|
||||
this._store.dispatch(statusCollection({ enode }));
|
||||
})
|
||||
@ -65,7 +63,7 @@ export default class Status {
|
||||
setTimeout(this._pollPing, timeout);
|
||||
};
|
||||
|
||||
fetch(`${parityNode}/api/ping`, { method: 'GET' })
|
||||
fetch('/', { method: 'HEAD' })
|
||||
.then((response) => dispatch(!!response.ok))
|
||||
.catch(() => dispatch(false));
|
||||
}
|
||||
@ -103,16 +101,16 @@ export default class Status {
|
||||
.all([
|
||||
this._api.web3.clientVersion(),
|
||||
this._api.eth.coinbase(),
|
||||
this._api.ethcore.defaultExtraData(),
|
||||
this._api.ethcore.extraData(),
|
||||
this._api.ethcore.gasFloorTarget(),
|
||||
this._api.parity.defaultExtraData(),
|
||||
this._api.parity.extraData(),
|
||||
this._api.parity.gasFloorTarget(),
|
||||
this._api.eth.hashrate(),
|
||||
this._api.ethcore.minGasPrice(),
|
||||
this._api.ethcore.netChain(),
|
||||
this._api.ethcore.netPeers(),
|
||||
this._api.ethcore.netPort(),
|
||||
this._api.ethcore.nodeName(),
|
||||
this._api.ethcore.rpcSettings(),
|
||||
this._api.parity.minGasPrice(),
|
||||
this._api.parity.netChain(),
|
||||
this._api.parity.netPeers(),
|
||||
this._api.parity.netPort(),
|
||||
this._api.parity.nodeName(),
|
||||
this._api.parity.rpcSettings(),
|
||||
this._api.eth.syncing(),
|
||||
this._pollTraceMode()
|
||||
])
|
||||
@ -155,8 +153,8 @@ export default class Status {
|
||||
|
||||
Promise
|
||||
.all([
|
||||
this._api.ethcore.devLogs(),
|
||||
this._api.ethcore.devLogsLevels()
|
||||
this._api.parity.devLogs(),
|
||||
this._api.parity.devLogsLevels()
|
||||
])
|
||||
.then(([devLogs, devLogsLevels]) => {
|
||||
this._store.dispatch(statusLogs({
|
||||
|
@ -25,6 +25,8 @@ export default class SecureApi extends Api {
|
||||
this._isConnecting = true;
|
||||
this._connectState = 0;
|
||||
this._needsToken = false;
|
||||
this._dappsPort = 8080;
|
||||
this._signerPort = 8180;
|
||||
|
||||
this._followConnection();
|
||||
}
|
||||
@ -50,7 +52,7 @@ export default class SecureApi extends Api {
|
||||
case 0:
|
||||
if (isConnected) {
|
||||
this._isConnecting = false;
|
||||
return this.setToken();
|
||||
return this.connectSuccess();
|
||||
} else if (lastError) {
|
||||
this.updateToken('initial', 1);
|
||||
}
|
||||
@ -60,7 +62,7 @@ export default class SecureApi extends Api {
|
||||
case 1:
|
||||
if (isConnected) {
|
||||
this._connectState = 2;
|
||||
this.personal
|
||||
this.parity
|
||||
.generateAuthorizationToken()
|
||||
.then((token) => {
|
||||
this.updateToken(token, 2);
|
||||
@ -79,7 +81,7 @@ export default class SecureApi extends Api {
|
||||
case 2:
|
||||
if (isConnected) {
|
||||
this._isConnecting = false;
|
||||
return this.setToken();
|
||||
return this.connectSuccess();
|
||||
} else if (lastError) {
|
||||
return setManual();
|
||||
}
|
||||
@ -89,12 +91,38 @@ export default class SecureApi extends Api {
|
||||
nextTick();
|
||||
}
|
||||
|
||||
connectSuccess () {
|
||||
this.setToken();
|
||||
|
||||
Promise
|
||||
.all([
|
||||
this.parity.dappsPort(),
|
||||
this.parity.signerPort()
|
||||
])
|
||||
.then(([dappsPort, signerPort]) => {
|
||||
this._dappsPort = dappsPort.toNumber();
|
||||
this._signerPort = signerPort.toNumber();
|
||||
});
|
||||
}
|
||||
|
||||
updateToken (token, connectedState = 0) {
|
||||
this._connectState = connectedState;
|
||||
this._transport.updateToken(token.replace(/[^a-zA-Z0-9]/g, ''));
|
||||
this._followConnection();
|
||||
}
|
||||
|
||||
get dappsPort () {
|
||||
return this._dappsPort;
|
||||
}
|
||||
|
||||
get dappsUrl () {
|
||||
return `http://127.0.0.1:${this._dappsPort}`;
|
||||
}
|
||||
|
||||
get signerPort () {
|
||||
return this._signerPort;
|
||||
}
|
||||
|
||||
get isConnecting () {
|
||||
return this._isConnecting;
|
||||
}
|
||||
|
@ -47,7 +47,13 @@ class Balance extends Component {
|
||||
const value = token.format
|
||||
? new BigNumber(balance.value).div(new BigNumber(token.format)).toFormat(3)
|
||||
: api.util.fromWei(balance.value).toFormat(3);
|
||||
const imagesrc = token.image || images[token.address] || unknownImage;
|
||||
let imagesrc = token.image;
|
||||
if (!imagesrc) {
|
||||
imagesrc =
|
||||
images[token.address]
|
||||
? `${api.dappsUrl}${images[token.address]}`
|
||||
: unknownImage;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -59,10 +59,9 @@ class IdentityIcon extends Component {
|
||||
updateIcon (_address, images) {
|
||||
const { api } = this.context;
|
||||
const { button, inline, tiny } = this.props;
|
||||
const iconsrc = images[_address];
|
||||
|
||||
if (iconsrc) {
|
||||
this.setState({ iconsrc });
|
||||
if (images[_address]) {
|
||||
this.setState({ iconsrc: `${api.dappsUrl}${images[_address]}` });
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ export default class Header extends Component {
|
||||
const { account } = this.props;
|
||||
|
||||
this.setState({ name }, () => {
|
||||
api.personal
|
||||
api.parity
|
||||
.setAccountName(account.address, name)
|
||||
.catch((error) => {
|
||||
console.error(error);
|
||||
|
@ -81,7 +81,7 @@ class Delete extends Component {
|
||||
|
||||
account.meta.deleted = true;
|
||||
|
||||
api.personal
|
||||
api.parity
|
||||
.setAccountMeta(account.address, account.meta)
|
||||
.then(() => {
|
||||
router.push(route);
|
||||
|
@ -104,8 +104,8 @@ class Application extends Component {
|
||||
checkAccounts () {
|
||||
const { api } = this.context;
|
||||
|
||||
api.personal
|
||||
.listAccounts()
|
||||
api.eth
|
||||
.accounts()
|
||||
.then((accounts) => {
|
||||
this.setState({
|
||||
showFirstRun: showFirstRun || accounts.length === 0
|
||||
|
@ -16,20 +16,54 @@
|
||||
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import Contracts from '../../contracts';
|
||||
import { fetchAvailable } from '../Dapps/registry';
|
||||
|
||||
import styles from './dapp.css';
|
||||
|
||||
const dapphost = process.env.NODE_ENV === 'production' ? 'http://127.0.0.1:8080/ui' : '';
|
||||
|
||||
export default class Dapp extends Component {
|
||||
static contextTypes = {
|
||||
api: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
params: PropTypes.object
|
||||
};
|
||||
|
||||
state = {
|
||||
app: null
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.lookup();
|
||||
}
|
||||
|
||||
render () {
|
||||
const { name, type } = this.props.params;
|
||||
const src = (type === 'builtin')
|
||||
? `${dapphost}/${name}.html`
|
||||
: `http://127.0.0.1:8080/${name}/`;
|
||||
const { app } = this.state;
|
||||
const { dappsUrl } = this.context.api;
|
||||
|
||||
if (!app) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let src = null;
|
||||
switch (app.type) {
|
||||
case 'builtin':
|
||||
const dapphost = process.env.NODE_ENV === 'production' && !app.secure
|
||||
? `${dappsUrl}/ui`
|
||||
: '';
|
||||
src = `${dapphost}/${app.url}.html`;
|
||||
break;
|
||||
case 'local':
|
||||
src = `${dappsUrl}/${app.id}/`;
|
||||
break;
|
||||
case 'network':
|
||||
src = `${dappsUrl}/${app.contentHash}/`;
|
||||
break;
|
||||
default:
|
||||
console.error('unknown type', app.type);
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<iframe
|
||||
@ -42,4 +76,30 @@ export default class Dapp extends Component {
|
||||
</iframe>
|
||||
);
|
||||
}
|
||||
|
||||
lookup () {
|
||||
const { api } = this.context;
|
||||
const { id } = this.props.params;
|
||||
const { dappReg } = Contracts.get();
|
||||
|
||||
fetchAvailable(api)
|
||||
.then((available) => {
|
||||
return available.find((app) => app.id === id);
|
||||
})
|
||||
.then((app) => {
|
||||
if (app.type !== 'network') {
|
||||
return app;
|
||||
}
|
||||
|
||||
return dappReg
|
||||
.getContent(app.id)
|
||||
.then((contentHash) => {
|
||||
app.contentHash = api.util.bytesToHex(contentHash).substr(2);
|
||||
return app;
|
||||
});
|
||||
})
|
||||
.then((app) => {
|
||||
this.setState({ app });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -32,31 +32,27 @@ export default class Summary extends Component {
|
||||
}
|
||||
|
||||
render () {
|
||||
const { dappsPort } = this.context.api;
|
||||
const { app } = this.props;
|
||||
|
||||
if (!app) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let type = 'builtin';
|
||||
if (app.network) {
|
||||
type = 'network';
|
||||
} else if (app.local) {
|
||||
type = 'local';
|
||||
let image = <div className={ styles.image }> </div>;
|
||||
if (app.image) {
|
||||
image = <img src={ `http://127.0.0.1:${dappsPort}${app.image}` } className={ styles.image } />;
|
||||
} else if (app.iconUrl) {
|
||||
image = <img src={ `http://127.0.0.1:${dappsPort}/${app.id}/${app.iconUrl}` } className={ styles.image } />;
|
||||
}
|
||||
|
||||
const url = `/app/${type}/${app.url || app.contentHash || app.id}`;
|
||||
const image = app.image || app.iconUrl
|
||||
? <img src={ app.image || `http://127.0.0.1:8080/${app.id}/${app.iconUrl}` } className={ styles.image } />
|
||||
: <div className={ styles.image }> </div>;
|
||||
|
||||
return (
|
||||
<Container className={ styles.container }>
|
||||
{ image }
|
||||
<div className={ styles.description }>
|
||||
<ContainerTitle
|
||||
className={ styles.title }
|
||||
title={ <Link to={ url }>{ app.name }</Link> }
|
||||
title={ <Link to={ `/app/${app.id}` }>{ app.name }</Link> }
|
||||
byline={ app.description } />
|
||||
<div className={ styles.author }>{ app.author }, v{ app.version }</div>
|
||||
{ this.props.children }
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
import { parityNode } from '../../environment';
|
||||
|
||||
const builtinApps = [
|
||||
{
|
||||
id: '0xf9f2d620c2e08f83e45555247146c62185e4ab7cf82a4b9002a265a0d020348f',
|
||||
@ -57,7 +55,8 @@ const builtinApps = [
|
||||
name: 'GitHub Hint',
|
||||
description: 'A mapping of GitHub URLs to hashes for use in contracts as references',
|
||||
author: 'Parity Team <admin@ethcore.io>',
|
||||
version: '1.0.0'
|
||||
version: '1.0.0',
|
||||
secure: true
|
||||
}
|
||||
];
|
||||
|
||||
@ -76,16 +75,14 @@ const networkApps = [
|
||||
}
|
||||
];
|
||||
|
||||
export function fetchAvailable (api) {
|
||||
// TODO: Since we don't have an extensive GithubHint app, get the value somehow
|
||||
// RESULT: 0x22cd66e1b05882c0fa17a16d252d3b3ee2238ccbac8153f69a35c83f02ca76ee
|
||||
// api.ethcore
|
||||
// .hashContent('https://codeload.github.com/gavofyork/gavcoin/zip/5a9f11ff2ad0d05c565a938ceffdfa0d23af9981')
|
||||
// .then((sha3) => {
|
||||
// console.log('archive', sha3);
|
||||
// });
|
||||
function getHost (api) {
|
||||
return process.env.NODE_ENV === 'production'
|
||||
? api.dappsUrl
|
||||
: '';
|
||||
}
|
||||
|
||||
return fetch(`${parityNode}/api/apps`)
|
||||
export function fetchAvailable (api) {
|
||||
return fetch(`${getHost(api)}/api/apps`)
|
||||
.then((response) => {
|
||||
return response.ok
|
||||
? response.json()
|
||||
@ -99,11 +96,11 @@ export function fetchAvailable (api) {
|
||||
const localApps = _localApps
|
||||
.filter((app) => !['ui'].includes(app.id))
|
||||
.map((app) => {
|
||||
app.local = true;
|
||||
app.type = 'local';
|
||||
return app;
|
||||
});
|
||||
|
||||
return api.ethcore
|
||||
return api.parity
|
||||
.registryAddress()
|
||||
.then((registryAddress) => {
|
||||
if (new BigNumber(registryAddress).eq(0)) {
|
||||
@ -112,13 +109,13 @@ export function fetchAvailable (api) {
|
||||
|
||||
const _builtinApps = builtinApps
|
||||
.map((app) => {
|
||||
app.builtin = true;
|
||||
app.type = 'builtin';
|
||||
return app;
|
||||
});
|
||||
|
||||
return networkApps
|
||||
.map((app) => {
|
||||
app.network = true;
|
||||
app.type = 'network';
|
||||
return app;
|
||||
})
|
||||
.concat(_builtinApps);
|
||||
@ -134,8 +131,8 @@ export function fetchAvailable (api) {
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchManifest (app, contentHash) {
|
||||
return fetch(`${parityNode}/${contentHash}/manifest.json`)
|
||||
export function fetchManifest (api, app, contentHash) {
|
||||
return fetch(`${getHost(api)}/${contentHash}/manifest.json`)
|
||||
.then((response) => {
|
||||
return response.ok
|
||||
? response.json()
|
||||
|
@ -89,7 +89,7 @@ export default class Parity extends Component {
|
||||
onChangeMode = (event, index, mode) => {
|
||||
const { api } = this.context;
|
||||
|
||||
api.ethcore
|
||||
api.parity
|
||||
.setMode(mode)
|
||||
.then((result) => {
|
||||
if (result) {
|
||||
@ -104,7 +104,7 @@ export default class Parity extends Component {
|
||||
loadMode () {
|
||||
const { api } = this.context;
|
||||
|
||||
api.ethcore
|
||||
api.parity
|
||||
.mode()
|
||||
.then((mode) => {
|
||||
this.setState({ mode });
|
||||
|
@ -14,7 +14,7 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
|
||||
import { Container, ContainerTitle } from '../../../ui';
|
||||
|
||||
@ -22,8 +22,13 @@ import layout from '../layout.css';
|
||||
import styles from './proxy.css';
|
||||
|
||||
export default class Proxy extends Component {
|
||||
static contextTypes = {
|
||||
api: PropTypes.object.isRequired
|
||||
}
|
||||
|
||||
render () {
|
||||
const proxyurl = 'http://127.0.0.1:8080/proxy/proxy.pac';
|
||||
const { dappsUrl } = this.context.api;
|
||||
const proxyurl = `${dappsUrl}/proxy/proxy.pac`;
|
||||
|
||||
return (
|
||||
<Container>
|
||||
|
@ -50,7 +50,7 @@ export default class SignRequest extends Component {
|
||||
}
|
||||
|
||||
componentWillMount () {
|
||||
this.context.api.ethcore.netChain()
|
||||
this.context.api.parity.netChain()
|
||||
.then((chain) => {
|
||||
this.setState({ chain });
|
||||
})
|
||||
|
@ -65,7 +65,7 @@ export default class TransactionFinished extends Component {
|
||||
const totalValue = tUtil.getTotalValue(fee, value);
|
||||
this.setState({ totalValue });
|
||||
|
||||
this.context.api.ethcore.netChain()
|
||||
this.context.api.parity.netChain()
|
||||
.then((chain) => {
|
||||
this.setState({ chain });
|
||||
})
|
||||
|
@ -64,7 +64,7 @@ export default class TransactionPending extends Component {
|
||||
const gasToDisplay = tUtil.getGasDisplay(gas);
|
||||
this.setState({ gasPriceEthmDisplay, totalValue, gasToDisplay });
|
||||
|
||||
this.context.api.ethcore.netChain()
|
||||
this.context.api.parity.netChain()
|
||||
.then((chain) => {
|
||||
this.setState({ chain });
|
||||
})
|
||||
|
@ -87,7 +87,7 @@ export default class MiningSettings extends Component {
|
||||
onMinGasPriceChange = (newVal) => {
|
||||
const { api } = this.context;
|
||||
|
||||
api.ethcore.setMinGasPrice(numberFromString(newVal));
|
||||
api.parity.setMinGasPrice(numberFromString(newVal));
|
||||
};
|
||||
|
||||
onExtraDataChange = (newVal, isResetToDefault) => {
|
||||
@ -97,18 +97,18 @@ export default class MiningSettings extends Component {
|
||||
// In case of resetting to default we are just using raw bytes from defaultExtraData
|
||||
// When user sets new value we can safely send a string that will be converted to hex by formatter.
|
||||
const val = isResetToDefault ? nodeStatus.defaultExtraData : newVal;
|
||||
api.ethcore.setExtraData(val);
|
||||
api.parity.setExtraData(val);
|
||||
};
|
||||
|
||||
onAuthorChange = (newVal) => {
|
||||
const { api } = this.context;
|
||||
|
||||
api.ethcore.setAuthor(newVal);
|
||||
api.parity.setAuthor(newVal);
|
||||
};
|
||||
|
||||
onGasFloorTargetChange = (newVal) => {
|
||||
const { api } = this.context;
|
||||
|
||||
api.ethcore.setGasFloorTarget(numberFromString(newVal));
|
||||
api.parity.setGasFloorTarget(numberFromString(newVal));
|
||||
};
|
||||
}
|
||||
|
@ -41,13 +41,13 @@ disable = false
|
||||
port = 8545
|
||||
interface = "local"
|
||||
cors = "null"
|
||||
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal_safe"]
|
||||
apis = ["web3", "eth", "net", "parity", "traces", "rpc"]
|
||||
hosts = ["none"]
|
||||
|
||||
[ipc]
|
||||
disable = false
|
||||
path = "$HOME/.parity/jsonrpc.ipc"
|
||||
apis = ["web3", "eth", "net", "ethcore", "traces", "rpc", "personal", "personal_safe"]
|
||||
apis = ["web3", "eth", "net", "parity", "parity_accounts", "personal", "traces", "rpc"]
|
||||
|
||||
[dapps]
|
||||
disable = false
|
||||
|
@ -143,7 +143,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.rpc).interface.clone(),
|
||||
flag_jsonrpc_cors: Option<String> = None,
|
||||
or |c: &Config| otry!(c.rpc).cors.clone().map(Some),
|
||||
flag_jsonrpc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal_safe",
|
||||
flag_jsonrpc_apis: String = "web3,eth,net,parity,traces,rpc",
|
||||
or |c: &Config| otry!(c.rpc).apis.clone().map(|vec| vec.join(",")),
|
||||
flag_jsonrpc_hosts: String = "none",
|
||||
or |c: &Config| otry!(c.rpc).hosts.clone().map(|vec| vec.join(",")),
|
||||
@ -153,7 +153,7 @@ usage! {
|
||||
or |c: &Config| otry!(c.ipc).disable.clone(),
|
||||
flag_ipc_path: String = "$HOME/.parity/jsonrpc.ipc",
|
||||
or |c: &Config| otry!(c.ipc).path.clone(),
|
||||
flag_ipc_apis: String = "web3,eth,net,ethcore,traces,rpc,personal,personal_safe",
|
||||
flag_ipc_apis: String = "web3,eth,net,parity,parity_accounts,traces,rpc",
|
||||
or |c: &Config| otry!(c.ipc).apis.clone().map(|vec| vec.join(",")),
|
||||
|
||||
// DAPPS
|
||||
@ -540,13 +540,13 @@ mod tests {
|
||||
flag_jsonrpc_port: 8545u16,
|
||||
flag_jsonrpc_interface: "local".into(),
|
||||
flag_jsonrpc_cors: Some("null".into()),
|
||||
flag_jsonrpc_apis: "web3,eth,net,ethcore,traces,rpc,personal_safe".into(),
|
||||
flag_jsonrpc_apis: "web3,eth,net,parity,traces,rpc".into(),
|
||||
flag_jsonrpc_hosts: "none".into(),
|
||||
|
||||
// IPC
|
||||
flag_no_ipc: false,
|
||||
flag_ipc_path: "$HOME/.parity/jsonrpc.ipc".into(),
|
||||
flag_ipc_apis: "web3,eth,net,ethcore,traces,rpc,personal,personal_safe".into(),
|
||||
flag_ipc_apis: "web3,eth,net,parity,parity_accounts,personal,traces,rpc".into(),
|
||||
|
||||
// DAPPS
|
||||
flag_no_dapps: false,
|
||||
|
@ -107,7 +107,7 @@ API and Console Options:
|
||||
--jsonrpc-apis APIS Specify the APIs available through the JSONRPC
|
||||
interface. APIS is a comma-delimited list of API
|
||||
name. Possible name are web3, eth, net, personal,
|
||||
ethcore, ethcore_set, traces, rpc, personal_safe.
|
||||
parity, parity_set, traces, rpc, parity_accounts.
|
||||
(default: {flag_jsonrpc_apis}).
|
||||
--jsonrpc-hosts HOSTS List of allowed Host header values. This option will
|
||||
validate the Host header sent by the browser, it
|
||||
@ -284,7 +284,7 @@ Legacy Options:
|
||||
--geth Run in Geth-compatibility mode. Sets the IPC path
|
||||
to be the same as Geth's. Overrides the --ipc-path
|
||||
and --ipcpath options. Alters RPCs to reflect Geth
|
||||
bugs.
|
||||
bugs. Includes the personal_ RPC by default.
|
||||
--testnet Geth-compatible testnet mode. Equivalent to --chain
|
||||
testnet --keys-path $HOME/parity/testnet-keys.
|
||||
Overrides the --keys-path option.
|
||||
|
@ -509,7 +509,11 @@ impl Configuration {
|
||||
}
|
||||
|
||||
fn rpc_apis(&self) -> String {
|
||||
self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone())
|
||||
let mut apis = self.args.flag_rpcapi.clone().unwrap_or(self.args.flag_jsonrpc_apis.clone());
|
||||
if self.args.flag_geth {
|
||||
apis.push_str(",personal");
|
||||
}
|
||||
apis
|
||||
}
|
||||
|
||||
fn rpc_cors(&self) -> Option<Vec<String>> {
|
||||
@ -541,7 +545,13 @@ impl Configuration {
|
||||
let conf = IpcConfiguration {
|
||||
enabled: !(self.args.flag_ipcdisable || self.args.flag_ipc_off || self.args.flag_no_ipc),
|
||||
socket_addr: self.ipc_path(),
|
||||
apis: try!(self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone()).parse()),
|
||||
apis: {
|
||||
let mut apis = self.args.flag_ipcapi.clone().unwrap_or(self.args.flag_ipc_apis.clone());
|
||||
if self.args.flag_geth {
|
||||
apis.push_str("personal");
|
||||
}
|
||||
try!(apis.parse())
|
||||
},
|
||||
};
|
||||
|
||||
Ok(conf)
|
||||
|
@ -31,15 +31,25 @@ pub use ethcore_rpc::SignerService;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Eq, Hash)]
|
||||
pub enum Api {
|
||||
/// Web3 (Safe)
|
||||
Web3,
|
||||
/// Net (Safe)
|
||||
Net,
|
||||
/// Eth (Safe)
|
||||
Eth,
|
||||
PersonalSafe,
|
||||
PersonalAccounts,
|
||||
/// Geth-compatible "personal" API (DEPRECATED; only used in `--geth` mode.)
|
||||
Personal,
|
||||
/// Signer - Confirm transactions in Signer (UNSAFE: Passwords, List of transactions)
|
||||
Signer,
|
||||
Ethcore,
|
||||
EthcoreSet,
|
||||
/// Parity - Custom extensions (Safe)
|
||||
Parity,
|
||||
/// Parity Accounts extensions (UNSAFE: Passwords, Side Effects (new account))
|
||||
ParityAccounts,
|
||||
/// Parity - Set methods (UNSAFE: Side Effects affecting node operation)
|
||||
ParitySet,
|
||||
/// Traces (Safe)
|
||||
Traces,
|
||||
/// Rpc (Safe)
|
||||
Rpc,
|
||||
}
|
||||
|
||||
@ -53,11 +63,11 @@ impl FromStr for Api {
|
||||
"web3" => Ok(Web3),
|
||||
"net" => Ok(Net),
|
||||
"eth" => Ok(Eth),
|
||||
"personal" => Ok(PersonalAccounts),
|
||||
"personal_safe" => Ok(PersonalSafe),
|
||||
"personal" => Ok(Personal),
|
||||
"signer" => Ok(Signer),
|
||||
"ethcore" => Ok(Ethcore),
|
||||
"ethcore_set" => Ok(EthcoreSet),
|
||||
"parity" => Ok(Parity),
|
||||
"parity_accounts" => Ok(ParityAccounts),
|
||||
"parity_set" => Ok(ParitySet),
|
||||
"traces" => Ok(Traces),
|
||||
"rpc" => Ok(Rpc),
|
||||
api => Err(format!("Unknown api: {}", api))
|
||||
@ -119,11 +129,11 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
|
||||
Api::Web3 => ("web3", "1.0"),
|
||||
Api::Net => ("net", "1.0"),
|
||||
Api::Eth => ("eth", "1.0"),
|
||||
Api::PersonalSafe => ("personal_safe", "1.0"),
|
||||
Api::PersonalAccounts => ("personal", "1.0"),
|
||||
Api::Personal => ("personal", "1.0"),
|
||||
Api::Signer => ("signer", "1.0"),
|
||||
Api::Ethcore => ("ethcore", "1.0"),
|
||||
Api::EthcoreSet => ("ethcore_set", "1.0"),
|
||||
Api::Parity => ("parity", "1.0"),
|
||||
Api::ParityAccounts => ("parity_accounts", "1.0"),
|
||||
Api::ParitySet => ("parity_set", "1.0"),
|
||||
Api::Traces => ("traces", "1.0"),
|
||||
Api::Rpc => ("rpc", "1.0"),
|
||||
};
|
||||
@ -134,24 +144,37 @@ fn to_modules(apis: &[Api]) -> BTreeMap<String, String> {
|
||||
|
||||
impl ApiSet {
|
||||
pub fn list_apis(&self) -> HashSet<Api> {
|
||||
let mut safe_list = vec![Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc]
|
||||
.into_iter().collect();
|
||||
match *self {
|
||||
ApiSet::List(ref apis) => apis.clone(),
|
||||
ApiSet::UnsafeContext => {
|
||||
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
|
||||
.into_iter().collect()
|
||||
},
|
||||
ApiSet::UnsafeContext => safe_list,
|
||||
ApiSet::IpcContext => {
|
||||
vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalAccounts, Api::PersonalSafe]
|
||||
.into_iter().collect()
|
||||
safe_list.insert(Api::ParityAccounts);
|
||||
safe_list
|
||||
},
|
||||
ApiSet::SafeContext => {
|
||||
vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
|
||||
.into_iter().collect()
|
||||
safe_list.insert(Api::ParityAccounts);
|
||||
safe_list.insert(Api::ParitySet);
|
||||
safe_list.insert(Api::Signer);
|
||||
safe_list
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! add_signing_methods {
|
||||
($namespace:ident, $server:expr, $deps:expr) => {
|
||||
let server = &$server;
|
||||
let deps = &$deps;
|
||||
if deps.signer_service.is_enabled() {
|
||||
server.add_delegate($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store)))
|
||||
} else {
|
||||
server.add_delegate($namespace::to_delegate(SigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet) -> T {
|
||||
use ethcore_rpc::v1::*;
|
||||
|
||||
@ -183,39 +206,39 @@ pub fn setup_rpc<T: Extendable>(server: T, deps: Arc<Dependencies>, apis: ApiSet
|
||||
let filter_client = EthFilterClient::new(&deps.client, &deps.miner);
|
||||
server.add_delegate(filter_client.to_delegate());
|
||||
|
||||
if deps.signer_service.is_enabled() {
|
||||
server.add_delegate(EthSigningQueueClient::new(&deps.signer_service, &deps.client, &deps.miner, &deps.secret_store).to_delegate());
|
||||
} else {
|
||||
server.add_delegate(EthSigningUnsafeClient::new(&deps.client, &deps.secret_store, &deps.miner).to_delegate());
|
||||
}
|
||||
add_signing_methods!(EthSigning, server, deps);
|
||||
},
|
||||
Api::PersonalAccounts => {
|
||||
server.add_delegate(PersonalAccountsClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
|
||||
},
|
||||
Api::PersonalSafe => {
|
||||
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client).to_delegate());
|
||||
Api::Personal => {
|
||||
server.add_delegate(PersonalClient::new(&deps.secret_store, &deps.client, &deps.miner, deps.geth_compatibility).to_delegate());
|
||||
},
|
||||
Api::Signer => {
|
||||
server.add_delegate(SignerClient::new(&deps.secret_store, &deps.client, &deps.miner, &deps.signer_service).to_delegate());
|
||||
},
|
||||
Api::Ethcore => {
|
||||
Api::Parity => {
|
||||
let signer = match deps.signer_service.is_enabled() {
|
||||
true => Some(deps.signer_service.clone()),
|
||||
false => None,
|
||||
};
|
||||
server.add_delegate(EthcoreClient::new(
|
||||
server.add_delegate(ParityClient::new(
|
||||
&deps.client,
|
||||
&deps.miner,
|
||||
&deps.sync,
|
||||
&deps.net_service,
|
||||
&deps.secret_store,
|
||||
deps.logger.clone(),
|
||||
deps.settings.clone(),
|
||||
signer,
|
||||
deps.dapps_port,
|
||||
).to_delegate())
|
||||
).to_delegate());
|
||||
|
||||
add_signing_methods!(EthSigning, server, deps);
|
||||
add_signing_methods!(ParitySigning, server, deps);
|
||||
},
|
||||
Api::EthcoreSet => {
|
||||
server.add_delegate(EthcoreSetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
|
||||
Api::ParityAccounts => {
|
||||
server.add_delegate(ParityAccountsClient::new(&deps.secret_store, &deps.client).to_delegate());
|
||||
},
|
||||
Api::ParitySet => {
|
||||
server.add_delegate(ParitySetClient::new(&deps.client, &deps.miner, &deps.net_service).to_delegate())
|
||||
},
|
||||
Api::Traces => {
|
||||
server.add_delegate(TracesClient::new(&deps.client, &deps.miner).to_delegate())
|
||||
@ -238,11 +261,11 @@ mod test {
|
||||
assert_eq!(Api::Web3, "web3".parse().unwrap());
|
||||
assert_eq!(Api::Net, "net".parse().unwrap());
|
||||
assert_eq!(Api::Eth, "eth".parse().unwrap());
|
||||
assert_eq!(Api::PersonalAccounts, "personal".parse().unwrap());
|
||||
assert_eq!(Api::PersonalSafe, "personal_safe".parse().unwrap());
|
||||
assert_eq!(Api::Personal, "personal".parse().unwrap());
|
||||
assert_eq!(Api::Signer, "signer".parse().unwrap());
|
||||
assert_eq!(Api::Ethcore, "ethcore".parse().unwrap());
|
||||
assert_eq!(Api::EthcoreSet, "ethcore_set".parse().unwrap());
|
||||
assert_eq!(Api::Parity, "parity".parse().unwrap());
|
||||
assert_eq!(Api::ParityAccounts, "parity_accounts".parse().unwrap());
|
||||
assert_eq!(Api::ParitySet, "parity_set".parse().unwrap());
|
||||
assert_eq!(Api::Traces, "traces".parse().unwrap());
|
||||
assert_eq!(Api::Rpc, "rpc".parse().unwrap());
|
||||
assert!("rp".parse::<Api>().is_err());
|
||||
@ -260,15 +283,34 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_api_set_unsafe_context() {
|
||||
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::Ethcore, Api::Traces, Api::Rpc, Api::PersonalSafe]
|
||||
.into_iter().collect();
|
||||
let expected = vec![
|
||||
// make sure this list contains only SAFE methods
|
||||
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc
|
||||
].into_iter().collect();
|
||||
assert_eq!(ApiSet::UnsafeContext.list_apis(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_api_set_ipc_context() {
|
||||
let expected = vec![
|
||||
// safe
|
||||
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
|
||||
// semi-safe
|
||||
Api::ParityAccounts
|
||||
].into_iter().collect();
|
||||
assert_eq!(ApiSet::IpcContext.list_apis(), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_api_set_safe_context() {
|
||||
let expected = vec![Api::Web3, Api::Net, Api::Eth, Api::PersonalAccounts, Api::PersonalSafe, Api::Signer, Api::Ethcore, Api::EthcoreSet, Api::Traces, Api::Rpc]
|
||||
.into_iter().collect();
|
||||
let expected = vec![
|
||||
// safe
|
||||
Api::Web3, Api::Net, Api::Eth, Api::Parity, Api::Traces, Api::Rpc,
|
||||
// semi-safe
|
||||
Api::ParityAccounts,
|
||||
// Unsafe
|
||||
Api::ParitySet, Api::Signer,
|
||||
].into_iter().collect();
|
||||
assert_eq!(ApiSet::SafeContext.list_apis(), expected);
|
||||
}
|
||||
}
|
||||
|
@ -27,13 +27,14 @@ macro_rules! take_weak {
|
||||
|
||||
mod eth;
|
||||
mod eth_filter;
|
||||
mod eth_signing;
|
||||
mod ethcore;
|
||||
mod ethcore_set;
|
||||
mod net;
|
||||
mod parity;
|
||||
mod parity_accounts;
|
||||
mod parity_set;
|
||||
mod personal;
|
||||
mod personal_accounts;
|
||||
mod personal_signer;
|
||||
mod signer;
|
||||
mod signing;
|
||||
mod signing_unsafe;
|
||||
mod rpc;
|
||||
mod traces;
|
||||
mod web3;
|
||||
@ -41,12 +42,13 @@ mod web3;
|
||||
pub use self::web3::Web3Client;
|
||||
pub use self::eth::{EthClient, EthClientOptions};
|
||||
pub use self::eth_filter::EthFilterClient;
|
||||
pub use self::eth_signing::{EthSigningUnsafeClient, EthSigningQueueClient};
|
||||
pub use self::net::NetClient;
|
||||
pub use self::parity::ParityClient;
|
||||
pub use self::parity_accounts::ParityAccountsClient;
|
||||
pub use self::parity_set::ParitySetClient;
|
||||
pub use self::personal::PersonalClient;
|
||||
pub use self::personal_accounts::PersonalAccountsClient;
|
||||
pub use self::personal_signer::SignerClient;
|
||||
pub use self::ethcore::EthcoreClient;
|
||||
pub use self::ethcore_set::EthcoreSetClient;
|
||||
pub use self::signer::SignerClient;
|
||||
pub use self::signing::SigningQueueClient;
|
||||
pub use self::signing_unsafe::SigningUnsafeClient;
|
||||
pub use self::traces::TracesClient;
|
||||
pub use self::rpc::RpcClient;
|
||||
|
@ -14,16 +14,15 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Ethcore-specific rpc implementation.
|
||||
use std::{fs, io};
|
||||
use std::sync::{mpsc, Arc, Weak};
|
||||
//! Parity-specific rpc implementation.
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::str::FromStr;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use util::{RotatingLogger, Address, Mutex, sha3};
|
||||
use util::{RotatingLogger, Address};
|
||||
use util::misc::version_data;
|
||||
|
||||
use crypto::ecies;
|
||||
use fetch::{Client as FetchClient, Fetch};
|
||||
use ethkey::{Brain, Generator};
|
||||
use ethstore::random_phrase;
|
||||
use ethsync::{SyncProvider, ManageNetwork};
|
||||
@ -31,77 +30,57 @@ use ethcore::miner::MinerService;
|
||||
use ethcore::client::{MiningBlockChainClient};
|
||||
use ethcore::ids::BlockID;
|
||||
use ethcore::mode::Mode;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
|
||||
use jsonrpc_core::Error;
|
||||
use v1::traits::Ethcore;
|
||||
use v1::traits::Parity;
|
||||
use v1::types::{Bytes, U256, H160, H256, H512, Peers, Transaction, RpcSettings, Histogram};
|
||||
use v1::helpers::{errors, SigningQueue, SignerService, NetworkSettings};
|
||||
use v1::helpers::dispatch::DEFAULT_MAC;
|
||||
use v1::helpers::auto_args::Ready;
|
||||
|
||||
/// Ethcore implementation.
|
||||
pub struct EthcoreClient<C, M, S: ?Sized, F=FetchClient> where
|
||||
/// Parity implementation.
|
||||
pub struct ParityClient<C, M, S: ?Sized> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
S: SyncProvider,
|
||||
F: Fetch {
|
||||
|
||||
{
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
sync: Weak<S>,
|
||||
net: Weak<ManageNetwork>,
|
||||
accounts: Weak<AccountProvider>,
|
||||
logger: Arc<RotatingLogger>,
|
||||
settings: Arc<NetworkSettings>,
|
||||
signer: Option<Arc<SignerService>>,
|
||||
fetch: Mutex<F>,
|
||||
dapps_port: Option<u16>,
|
||||
}
|
||||
|
||||
impl<C, M, S: ?Sized> EthcoreClient<C, M, S> where
|
||||
impl<C, M, S: ?Sized> ParityClient<C, M, S> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
S: SyncProvider, {
|
||||
/// Creates new `EthcoreClient` with default `Fetch`.
|
||||
S: SyncProvider,
|
||||
{
|
||||
/// Creates new `ParityClient`.
|
||||
pub fn new(
|
||||
client: &Arc<C>,
|
||||
miner: &Arc<M>,
|
||||
sync: &Arc<S>,
|
||||
net: &Arc<ManageNetwork>,
|
||||
store: &Arc<AccountProvider>,
|
||||
logger: Arc<RotatingLogger>,
|
||||
settings: Arc<NetworkSettings>,
|
||||
signer: Option<Arc<SignerService>>,
|
||||
dapps_port: Option<u16>,
|
||||
) -> Self {
|
||||
Self::with_fetch(client, miner, sync, net, logger, settings, signer, dapps_port)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M, S: ?Sized, F> EthcoreClient<C, M, S, F> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
S: SyncProvider,
|
||||
F: Fetch, {
|
||||
|
||||
/// Creates new `EthcoreClient` with customizable `Fetch`.
|
||||
pub fn with_fetch(
|
||||
client: &Arc<C>,
|
||||
miner: &Arc<M>,
|
||||
sync: &Arc<S>,
|
||||
net: &Arc<ManageNetwork>,
|
||||
logger: Arc<RotatingLogger>,
|
||||
settings: Arc<NetworkSettings>,
|
||||
signer: Option<Arc<SignerService>>,
|
||||
dapps_port: Option<u16>,
|
||||
) -> Self {
|
||||
EthcoreClient {
|
||||
ParityClient {
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
sync: Arc::downgrade(sync),
|
||||
net: Arc::downgrade(net),
|
||||
accounts: Arc::downgrade(store),
|
||||
logger: logger,
|
||||
settings: settings,
|
||||
signer: signer,
|
||||
fetch: Mutex::new(F::default()),
|
||||
dapps_port: dapps_port,
|
||||
}
|
||||
}
|
||||
@ -113,11 +92,10 @@ impl<C, M, S: ?Sized, F> EthcoreClient<C, M, S, F> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
|
||||
impl<C, M, S: ?Sized> Parity for ParityClient<C, M, S> where
|
||||
M: MinerService + 'static,
|
||||
C: MiningBlockChainClient + 'static,
|
||||
S: SyncProvider + 'static,
|
||||
F: Fetch + 'static {
|
||||
S: SyncProvider + 'static {
|
||||
|
||||
fn transactions_limit(&self) -> Result<usize, Error> {
|
||||
try!(self.active());
|
||||
@ -278,48 +256,6 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
|
||||
Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
fn hash_content(&self, ready: Ready<H256>, url: String) {
|
||||
let res = self.active();
|
||||
|
||||
let hash_content = |result| {
|
||||
let path = try!(result);
|
||||
let mut file = io::BufReader::new(try!(fs::File::open(&path)));
|
||||
// Try to hash
|
||||
let result = sha3(&mut file);
|
||||
// Remove file (always)
|
||||
try!(fs::remove_file(&path));
|
||||
// Return the result
|
||||
Ok(try!(result))
|
||||
};
|
||||
|
||||
match res {
|
||||
Err(e) => ready.ready(Err(e)),
|
||||
Ok(()) => {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let res = self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
|
||||
let result = hash_content(result)
|
||||
.map_err(errors::from_fetch_error)
|
||||
.map(Into::into);
|
||||
|
||||
// Receive ready and invoke with result.
|
||||
let ready: Ready<H256> = rx.recv().expect(
|
||||
"recv() fails when `tx` has been dropped, if this closure is invoked `tx` is not dropped (`res == Ok()`); qed"
|
||||
);
|
||||
ready.ready(result);
|
||||
}));
|
||||
|
||||
// Either invoke ready right away or transfer it to the closure.
|
||||
if let Err(e) = res {
|
||||
ready.ready(Err(errors::from_fetch_error(e)));
|
||||
} else {
|
||||
tx.send(ready).expect(
|
||||
"send() fails when `rx` end is dropped, if `res == Ok()`: `rx` is moved to the closure; qed"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn signer_port(&self) -> Result<u16, Error> {
|
||||
try!(self.active());
|
||||
|
||||
@ -361,4 +297,22 @@ impl<C, M, S: ?Sized, F> Ethcore for EthcoreClient<C, M, S, F> where
|
||||
fn enode(&self) -> Result<String, Error> {
|
||||
take_weak!(self.sync).enode().ok_or_else(errors::network_disabled)
|
||||
}
|
||||
|
||||
fn accounts(&self) -> Result<BTreeMap<String, BTreeMap<String, String>>, Error> {
|
||||
try!(self.active());
|
||||
let store = take_weak!(self.accounts);
|
||||
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
|
||||
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
|
||||
|
||||
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
|
||||
let mut m = map![
|
||||
"name".to_owned() => v.name,
|
||||
"meta".to_owned() => v.meta
|
||||
];
|
||||
if let &Some(ref uuid) = &v.uuid {
|
||||
m.insert("uuid".to_owned(), format!("{}", uuid));
|
||||
}
|
||||
(format!("0x{}", a.hex()), m)
|
||||
}).collect())
|
||||
}
|
||||
}
|
@ -16,33 +16,30 @@
|
||||
|
||||
//! Account management (personal) rpc implementation
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::collections::BTreeMap;
|
||||
use util::{Address};
|
||||
use jsonrpc_core::*;
|
||||
|
||||
use ethkey::{Brain, Generator};
|
||||
use v1::traits::PersonalAccounts;
|
||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, TransactionRequest};
|
||||
use v1::helpers::errors;
|
||||
use v1::helpers::dispatch::sign_and_dispatch;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::miner::MinerService;
|
||||
|
||||
use jsonrpc_core::{Value, Error, to_value};
|
||||
use v1::traits::ParityAccounts;
|
||||
use v1::types::{H160 as RpcH160, H256 as RpcH256};
|
||||
use v1::helpers::errors;
|
||||
|
||||
/// Account management (personal) rpc implementation.
|
||||
pub struct PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
pub struct ParityAccountsClient<C> where C: MiningBlockChainClient {
|
||||
accounts: Weak<AccountProvider>,
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
allow_perm_unlock: bool,
|
||||
}
|
||||
|
||||
impl<C, M> PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
impl<C> ParityAccountsClient<C> where C: MiningBlockChainClient {
|
||||
/// Creates new PersonalClient
|
||||
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
|
||||
PersonalAccountsClient {
|
||||
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>) -> Self {
|
||||
ParityAccountsClient {
|
||||
accounts: Arc::downgrade(store),
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
allow_perm_unlock: allow_perm_unlock,
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,15 +50,25 @@ impl<C, M> PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: Mine
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
|
||||
fn new_account(&self, pass: String) -> Result<RpcH160, Error> {
|
||||
impl<C: 'static> ParityAccounts for ParityAccountsClient<C> where C: MiningBlockChainClient {
|
||||
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error> {
|
||||
try!(self.active());
|
||||
let store = take_weak!(self.accounts);
|
||||
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
|
||||
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
|
||||
|
||||
store.new_account(&pass)
|
||||
.map(Into::into)
|
||||
.map_err(|e| errors::account("Could not create account.", e))
|
||||
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
|
||||
let m = map![
|
||||
"name".to_owned() => to_value(&v.name),
|
||||
"meta".to_owned() => to_value(&v.meta),
|
||||
"uuid".to_owned() => if let &Some(ref uuid) = &v.uuid {
|
||||
to_value(uuid)
|
||||
} else {
|
||||
Value::Null
|
||||
}
|
||||
];
|
||||
(format!("0x{}", a.hex()), Value::Object(m))
|
||||
}).collect())
|
||||
}
|
||||
|
||||
fn new_account_from_phrase(&self, phrase: String, pass: String) -> Result<RpcH160, Error> {
|
||||
@ -92,24 +99,6 @@ impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> w
|
||||
.map_err(|e| errors::account("Could not create account.", e))
|
||||
}
|
||||
|
||||
fn unlock_account(&self, account: RpcH160, account_pass: String, duration: Option<u64>) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
let account: Address = account.into();
|
||||
let store = take_weak!(self.accounts);
|
||||
|
||||
let r = match (self.allow_perm_unlock, duration) {
|
||||
(false, _) => store.unlock_account_temporarily(account, account_pass),
|
||||
(true, Some(0)) => store.unlock_account_permanently(account, account_pass),
|
||||
(true, Some(d)) => store.unlock_account_timed(account, account_pass, d as u32 * 1000),
|
||||
(true, None) => store.unlock_account_timed(account, account_pass, 300_000),
|
||||
};
|
||||
match r {
|
||||
Ok(_) => Ok(true),
|
||||
// TODO [ToDr] Proper error here?
|
||||
Err(_) => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn test_password(&self, account: RpcH160, password: String) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
let account: Address = account.into();
|
||||
@ -128,18 +117,6 @@ impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> w
|
||||
.map_err(|e| errors::account("Could not fetch account info.", e))
|
||||
}
|
||||
|
||||
fn sign_and_send_transaction(&self, request: TransactionRequest, password: String) -> Result<RpcH256, Error> {
|
||||
try!(self.active());
|
||||
|
||||
sign_and_dispatch(
|
||||
&*take_weak!(self.client),
|
||||
&*take_weak!(self.miner),
|
||||
&*take_weak!(self.accounts),
|
||||
request.into(),
|
||||
Some(password)
|
||||
)
|
||||
}
|
||||
|
||||
fn set_account_name(&self, addr: RpcH160, name: String) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
let store = take_weak!(self.accounts);
|
||||
@ -162,6 +139,10 @@ impl<C: 'static, M: 'static> PersonalAccounts for PersonalAccountsClient<C, M> w
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn set_account_visibility(&self, _address: RpcH160, _dapp: RpcH256, _visible: bool) -> Result<bool, Error> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
fn import_geth_accounts(&self, addresses: Vec<RpcH160>) -> Result<Vec<RpcH160>, Error> {
|
||||
let store = take_weak!(self.accounts);
|
||||
|
@ -14,36 +14,57 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/// Ethcore-specific rpc interface for operations altering the settings.
|
||||
use std::sync::{Arc, Weak};
|
||||
use jsonrpc_core::*;
|
||||
/// Parity-specific rpc interface for operations altering the settings.
|
||||
use std::{fs, io};
|
||||
use std::sync::{Arc, Weak, mpsc};
|
||||
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::mode::Mode;
|
||||
use ethsync::ManageNetwork;
|
||||
use v1::helpers::errors;
|
||||
use v1::traits::EthcoreSet;
|
||||
use v1::types::{Bytes, H160, U256};
|
||||
use fetch::{Client as FetchClient, Fetch};
|
||||
use util::{Mutex, sha3};
|
||||
|
||||
/// Ethcore-specific rpc interface for operations altering the settings.
|
||||
pub struct EthcoreSetClient<C, M> where
|
||||
use jsonrpc_core::Error;
|
||||
use v1::helpers::auto_args::Ready;
|
||||
use v1::helpers::errors;
|
||||
use v1::traits::ParitySet;
|
||||
use v1::types::{Bytes, H160, H256, U256};
|
||||
|
||||
/// Parity-specific rpc interface for operations altering the settings.
|
||||
pub struct ParitySetClient<C, M, F=FetchClient> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService
|
||||
M: MinerService,
|
||||
F: Fetch,
|
||||
{
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
net: Weak<ManageNetwork>,
|
||||
fetch: Mutex<F>,
|
||||
}
|
||||
|
||||
impl<C, M> EthcoreSetClient<C, M> where
|
||||
impl<C, M> ParitySetClient<C, M, FetchClient> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService {
|
||||
/// Creates new `EthcoreSetClient`.
|
||||
M: MinerService
|
||||
{
|
||||
/// Creates new `ParitySetClient` with default `FetchClient`.
|
||||
pub fn new(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
|
||||
EthcoreSetClient {
|
||||
Self::with_fetch(client, miner, net)
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M, F> ParitySetClient<C, M, F> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
F: Fetch,
|
||||
{
|
||||
/// Creates new `ParitySetClient` with default `FetchClient`.
|
||||
pub fn with_fetch(client: &Arc<C>, miner: &Arc<M>, net: &Arc<ManageNetwork>) -> Self {
|
||||
ParitySetClient {
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
net: Arc::downgrade(net),
|
||||
fetch: Mutex::new(F::default()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -54,9 +75,11 @@ impl<C, M> EthcoreSetClient<C, M> where
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where
|
||||
impl<C, M, F> ParitySet for ParitySetClient<C, M, F> where
|
||||
C: MiningBlockChainClient + 'static,
|
||||
M: MinerService + 'static {
|
||||
M: MinerService + 'static,
|
||||
F: Fetch + 'static,
|
||||
{
|
||||
|
||||
fn set_min_gas_price(&self, gas_price: U256) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
@ -159,4 +182,46 @@ impl<C, M> EthcoreSet for EthcoreSetClient<C, M> where
|
||||
});
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
fn hash_content(&self, ready: Ready<H256>, url: String) {
|
||||
let res = self.active();
|
||||
|
||||
let hash_content = |result| {
|
||||
let path = try!(result);
|
||||
let mut file = io::BufReader::new(try!(fs::File::open(&path)));
|
||||
// Try to hash
|
||||
let result = sha3(&mut file);
|
||||
// Remove file (always)
|
||||
try!(fs::remove_file(&path));
|
||||
// Return the result
|
||||
Ok(try!(result))
|
||||
};
|
||||
|
||||
match res {
|
||||
Err(e) => ready.ready(Err(e)),
|
||||
Ok(()) => {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let res = self.fetch.lock().request_async(&url, Default::default(), Box::new(move |result| {
|
||||
let result = hash_content(result)
|
||||
.map_err(errors::from_fetch_error)
|
||||
.map(Into::into);
|
||||
|
||||
// Receive ready and invoke with result.
|
||||
let ready: Ready<H256> = rx.recv().expect(
|
||||
"recv() fails when `tx` has been dropped, if this closure is invoked `tx` is not dropped (`res == Ok()`); qed"
|
||||
);
|
||||
ready.ready(result);
|
||||
}));
|
||||
|
||||
// Either invoke ready right away or transfer it to the closure.
|
||||
if let Err(e) = res {
|
||||
ready.ready(Err(errors::from_fetch_error(e)));
|
||||
} else {
|
||||
tx.send(ready).expect(
|
||||
"send() fails when `rx` end is dropped, if `res == Ok()`: `rx` is moved to the closure; qed"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -16,26 +16,34 @@
|
||||
|
||||
//! Account management (personal) rpc implementation
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::collections::{BTreeMap};
|
||||
use jsonrpc_core::*;
|
||||
use v1::traits::Personal;
|
||||
use v1::types::{H160 as RpcH160};
|
||||
use v1::helpers::errors;
|
||||
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::miner::MinerService;
|
||||
use util::Address;
|
||||
|
||||
use jsonrpc_core::Error;
|
||||
use v1::traits::Personal;
|
||||
use v1::types::{H160 as RpcH160, H256 as RpcH256, TransactionRequest};
|
||||
use v1::helpers::errors;
|
||||
use v1::helpers::dispatch::sign_and_dispatch;
|
||||
|
||||
/// Account management (personal) rpc implementation.
|
||||
pub struct PersonalClient<C> where C: MiningBlockChainClient {
|
||||
pub struct PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
accounts: Weak<AccountProvider>,
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
allow_perm_unlock: bool,
|
||||
}
|
||||
|
||||
impl<C> PersonalClient<C> where C: MiningBlockChainClient {
|
||||
impl<C, M> PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
/// Creates new PersonalClient
|
||||
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>) -> Self {
|
||||
pub fn new(store: &Arc<AccountProvider>, client: &Arc<C>, miner: &Arc<M>, allow_perm_unlock: bool) -> Self {
|
||||
PersonalClient {
|
||||
accounts: Arc::downgrade(store),
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
allow_perm_unlock: allow_perm_unlock,
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +54,7 @@ impl<C> PersonalClient<C> where C: MiningBlockChainClient {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: 'static> Personal for PersonalClient<C> where C: MiningBlockChainClient {
|
||||
|
||||
impl<C: 'static, M: 'static> Personal for PersonalClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
fn accounts(&self) -> Result<Vec<RpcH160>, Error> {
|
||||
try!(self.active());
|
||||
|
||||
@ -56,23 +63,42 @@ impl<C: 'static> Personal for PersonalClient<C> where C: MiningBlockChainClient
|
||||
Ok(accounts.into_iter().map(Into::into).collect::<Vec<RpcH160>>())
|
||||
}
|
||||
|
||||
fn accounts_info(&self) -> Result<BTreeMap<String, Value>, Error> {
|
||||
fn new_account(&self, pass: String) -> Result<RpcH160, Error> {
|
||||
try!(self.active());
|
||||
let store = take_weak!(self.accounts);
|
||||
let info = try!(store.accounts_info().map_err(|e| errors::account("Could not fetch account info.", e)));
|
||||
let other = store.addresses_info().expect("addresses_info always returns Ok; qed");
|
||||
|
||||
Ok(info.into_iter().chain(other.into_iter()).map(|(a, v)| {
|
||||
let m = map![
|
||||
"name".to_owned() => to_value(&v.name),
|
||||
"meta".to_owned() => to_value(&v.meta),
|
||||
"uuid".to_owned() => if let &Some(ref uuid) = &v.uuid {
|
||||
to_value(uuid)
|
||||
} else {
|
||||
Value::Null
|
||||
}
|
||||
];
|
||||
(format!("0x{}", a.hex()), Value::Object(m))
|
||||
}).collect())
|
||||
store.new_account(&pass)
|
||||
.map(Into::into)
|
||||
.map_err(|e| errors::account("Could not create account.", e))
|
||||
}
|
||||
|
||||
fn unlock_account(&self, account: RpcH160, account_pass: String, duration: Option<u64>) -> Result<bool, Error> {
|
||||
try!(self.active());
|
||||
let account: Address = account.into();
|
||||
let store = take_weak!(self.accounts);
|
||||
|
||||
let r = match (self.allow_perm_unlock, duration) {
|
||||
(false, _) => store.unlock_account_temporarily(account, account_pass),
|
||||
(true, Some(0)) => store.unlock_account_permanently(account, account_pass),
|
||||
(true, Some(d)) => store.unlock_account_timed(account, account_pass, d as u32 * 1000),
|
||||
(true, None) => store.unlock_account_timed(account, account_pass, 300_000),
|
||||
};
|
||||
match r {
|
||||
Ok(_) => Ok(true),
|
||||
// TODO [ToDr] Proper error here?
|
||||
Err(_) => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
fn sign_and_send_transaction(&self, request: TransactionRequest, password: String) -> Result<RpcH256, Error> {
|
||||
try!(self.active());
|
||||
|
||||
sign_and_dispatch(
|
||||
&*take_weak!(self.client),
|
||||
&*take_weak!(self.miner),
|
||||
&*take_weak!(self.accounts),
|
||||
request.into(),
|
||||
Some(password)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -14,14 +14,14 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Transactions Confirmations (personal) rpc implementation
|
||||
//! Transactions Confirmations rpc implementation
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
use jsonrpc_core::*;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use ethcore::miner::MinerService;
|
||||
use v1::traits::PersonalSigner;
|
||||
use v1::traits::Signer;
|
||||
use v1::types::{TransactionModification, ConfirmationRequest, U256};
|
||||
use v1::helpers::{errors, SignerService, SigningQueue, ConfirmationPayload};
|
||||
use v1::helpers::dispatch::{sign_and_dispatch, sign, decrypt};
|
||||
@ -58,7 +58,7 @@ impl<C: 'static, M: 'static> SignerClient<C, M> where C: MiningBlockChainClient,
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: 'static, M: 'static> PersonalSigner for SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
impl<C: 'static, M: 'static> Signer for SignerClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
|
||||
fn requests_to_confirm(&self) -> Result<Vec<ConfirmationRequest>, Error> {
|
||||
try!(self.active());
|
@ -14,43 +14,22 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Eth Signing RPC implementation.
|
||||
//! Signing RPC implementation.
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
use jsonrpc_core::*;
|
||||
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
use util::{U256, Address, H256, Mutex};
|
||||
use transient_hashmap::TransientHashMap;
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use util::{U256, Address, H256, Mutex};
|
||||
|
||||
use jsonrpc_core::*;
|
||||
use v1::helpers::{errors, SigningQueue, ConfirmationPromise, ConfirmationResult, ConfirmationPayload, TransactionRequest as TRequest, FilledTransactionRequest as FilledRequest, SignerService};
|
||||
use v1::helpers::dispatch::{default_gas_price, sign_and_dispatch, sign, decrypt};
|
||||
use v1::traits::EthSigning;
|
||||
use v1::traits::{EthSigning, ParitySigning};
|
||||
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, U256 as RpcU256, Bytes as RpcBytes};
|
||||
|
||||
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
|
||||
where C: MiningBlockChainClient, M: MinerService {
|
||||
FilledRequest {
|
||||
from: request.from,
|
||||
to: request.to,
|
||||
nonce: request.nonce,
|
||||
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
|
||||
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
|
||||
value: request.value.unwrap_or_else(|| 0.into()),
|
||||
data: request.data.unwrap_or_else(Vec::new),
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of functions that require signing when no trusted signer is used.
|
||||
pub struct EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
signer: Weak<SignerService>,
|
||||
accounts: Weak<AccountProvider>,
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
|
||||
pending: Mutex<TransientHashMap<U256, ConfirmationPromise>>,
|
||||
}
|
||||
|
||||
const MAX_PENDING_DURATION: u64 = 60 * 60;
|
||||
|
||||
pub enum DispatchResult {
|
||||
@ -58,10 +37,23 @@ pub enum DispatchResult {
|
||||
Value(Value),
|
||||
}
|
||||
|
||||
impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
/// Implementation of functions that require signing when no trusted signer is used.
|
||||
pub struct SigningQueueClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
signer: Weak<SignerService>,
|
||||
accounts: Weak<AccountProvider>,
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
|
||||
pending: Mutex<TransientHashMap<U256, ConfirmationPromise>>,
|
||||
}
|
||||
|
||||
impl<C, M> SigningQueueClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
/// Creates a new signing queue client given shared signing queue.
|
||||
pub fn new(signer: &Arc<SignerService>, client: &Arc<C>, miner: &Arc<M>, accounts: &Arc<AccountProvider>) -> Self {
|
||||
EthSigningQueueClient {
|
||||
SigningQueueClient {
|
||||
signer: Arc::downgrade(signer),
|
||||
accounts: Arc::downgrade(accounts),
|
||||
client: Arc::downgrade(client),
|
||||
@ -132,10 +124,10 @@ impl<C, M> EthSigningQueueClient<C, M> where C: MiningBlockChainClient, M: Miner
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M> EthSigning for EthSigningQueueClient<C, M>
|
||||
where C: MiningBlockChainClient + 'static, M: MinerService + 'static
|
||||
impl<C: 'static, M: 'static> ParitySigning for SigningQueueClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
|
||||
fn post_sign(&self, params: Params) -> Result<Value, Error> {
|
||||
try!(self.active());
|
||||
self.dispatch_sign(params).map(|result| match result {
|
||||
@ -178,16 +170,6 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
|
||||
})
|
||||
}
|
||||
|
||||
fn sign(&self, params: Params, ready: Ready) {
|
||||
let res = self.active().and_then(|_| self.dispatch_sign(params));
|
||||
self.handle_dispatch(res, ready);
|
||||
}
|
||||
|
||||
fn send_transaction(&self, params: Params, ready: Ready) {
|
||||
let res = self.active().and_then(|_| self.dispatch_transaction(params));
|
||||
self.handle_dispatch(res, ready);
|
||||
}
|
||||
|
||||
fn decrypt_message(&self, params: Params, ready: Ready) {
|
||||
let res = self.active()
|
||||
.and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
|
||||
@ -205,76 +187,30 @@ impl<C, M> EthSigning for EthSigningQueueClient<C, M>
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of functions that require signing when no trusted signer is used.
|
||||
pub struct EthSigningUnsafeClient<C, M> where
|
||||
impl<C: 'static, M: 'static> EthSigning for SigningQueueClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService {
|
||||
client: Weak<C>,
|
||||
accounts: Weak<AccountProvider>,
|
||||
miner: Weak<M>,
|
||||
}
|
||||
|
||||
impl<C, M> EthSigningUnsafeClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService {
|
||||
|
||||
/// Creates new EthClient.
|
||||
pub fn new(client: &Arc<C>, accounts: &Arc<AccountProvider>, miner: &Arc<M>)
|
||||
-> Self {
|
||||
EthSigningUnsafeClient {
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
accounts: Arc::downgrade(accounts),
|
||||
}
|
||||
}
|
||||
|
||||
fn active(&self) -> Result<(), Error> {
|
||||
// TODO: only call every 30s at most.
|
||||
take_weak!(self.client).keep_alive();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C, M> EthSigning for EthSigningUnsafeClient<C, M> where
|
||||
C: MiningBlockChainClient + 'static,
|
||||
M: MinerService + 'static {
|
||||
|
||||
M: MinerService,
|
||||
{
|
||||
fn sign(&self, params: Params, ready: Ready) {
|
||||
ready.ready(self.active()
|
||||
.and_then(|_| from_params::<(RpcH160, RpcH256)>(params))
|
||||
.and_then(|(address, msg)| {
|
||||
sign(&*take_weak!(self.accounts), address.into(), None, msg.into())
|
||||
}))
|
||||
let res = self.active().and_then(|_| self.dispatch_sign(params));
|
||||
self.handle_dispatch(res, ready);
|
||||
}
|
||||
|
||||
fn send_transaction(&self, params: Params, ready: Ready) {
|
||||
ready.ready(self.active()
|
||||
.and_then(|_| from_params::<(TransactionRequest, )>(params))
|
||||
.and_then(|(request, )| {
|
||||
sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), &*take_weak!(self.accounts), request.into(), None).map(to_value)
|
||||
}))
|
||||
}
|
||||
|
||||
fn decrypt_message(&self, params: Params, ready: Ready) {
|
||||
ready.ready(self.active()
|
||||
.and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
|
||||
.and_then(|(address, ciphertext)| {
|
||||
decrypt(&*take_weak!(self.accounts), address.into(), None, ciphertext.0)
|
||||
}))
|
||||
}
|
||||
|
||||
fn post_sign(&self, _: Params) -> Result<Value, Error> {
|
||||
// We don't support this in non-signer mode.
|
||||
Err(errors::signer_disabled())
|
||||
}
|
||||
|
||||
fn post_transaction(&self, _: Params) -> Result<Value, Error> {
|
||||
// We don't support this in non-signer mode.
|
||||
Err(errors::signer_disabled())
|
||||
}
|
||||
|
||||
fn check_request(&self, _: Params) -> Result<Value, Error> {
|
||||
// We don't support this in non-signer mode.
|
||||
Err(errors::signer_disabled())
|
||||
let res = self.active().and_then(|_| self.dispatch_transaction(params));
|
||||
self.handle_dispatch(res, ready);
|
||||
}
|
||||
}
|
||||
|
||||
fn fill_optional_fields<C, M>(request: TRequest, client: &C, miner: &M) -> FilledRequest
|
||||
where C: MiningBlockChainClient, M: MinerService {
|
||||
FilledRequest {
|
||||
from: request.from,
|
||||
to: request.to,
|
||||
nonce: request.nonce,
|
||||
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(client, miner)),
|
||||
gas: request.gas.unwrap_or_else(|| miner.sensible_gas_limit()),
|
||||
value: request.value.unwrap_or_else(|| 0.into()),
|
||||
data: request.data.unwrap_or_else(Vec::new),
|
||||
}
|
||||
}
|
110
rpc/src/v1/impls/signing_unsafe.rs
Normal file
110
rpc/src/v1/impls/signing_unsafe.rs
Normal file
@ -0,0 +1,110 @@
|
||||
// Copyright 2015, 2016 Ethcore (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/>.
|
||||
|
||||
//! Unsafe Signing RPC implementation.
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::MiningBlockChainClient;
|
||||
|
||||
use jsonrpc_core::*;
|
||||
use v1::helpers::errors;
|
||||
use v1::helpers::dispatch::{sign_and_dispatch, sign, decrypt};
|
||||
use v1::traits::{EthSigning, ParitySigning};
|
||||
use v1::types::{TransactionRequest, H160 as RpcH160, H256 as RpcH256, Bytes as RpcBytes};
|
||||
|
||||
/// Implementation of functions that require signing when no trusted signer is used.
|
||||
pub struct SigningUnsafeClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
accounts: Weak<AccountProvider>,
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
}
|
||||
|
||||
impl<C, M> SigningUnsafeClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
|
||||
/// Creates new SigningUnsafeClient.
|
||||
pub fn new(client: &Arc<C>, accounts: &Arc<AccountProvider>, miner: &Arc<M>)
|
||||
-> Self {
|
||||
SigningUnsafeClient {
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
accounts: Arc::downgrade(accounts),
|
||||
}
|
||||
}
|
||||
|
||||
fn active(&self) -> Result<(), Error> {
|
||||
// TODO: only call every 30s at most.
|
||||
take_weak!(self.client).keep_alive();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: 'static, M: 'static> EthSigning for SigningUnsafeClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
fn sign(&self, params: Params, ready: Ready) {
|
||||
ready.ready(self.active()
|
||||
.and_then(|_| from_params::<(RpcH160, RpcH256)>(params))
|
||||
.and_then(|(address, msg)| {
|
||||
sign(&*take_weak!(self.accounts), address.into(), None, msg.into())
|
||||
}))
|
||||
}
|
||||
|
||||
fn send_transaction(&self, params: Params, ready: Ready) {
|
||||
ready.ready(self.active()
|
||||
.and_then(|_| from_params::<(TransactionRequest, )>(params))
|
||||
.and_then(|(request, )| {
|
||||
sign_and_dispatch(&*take_weak!(self.client), &*take_weak!(self.miner), &*take_weak!(self.accounts), request.into(), None).map(to_value)
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<C: 'static, M: 'static> ParitySigning for SigningUnsafeClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService,
|
||||
{
|
||||
fn decrypt_message(&self, params: Params, ready: Ready) {
|
||||
ready.ready(self.active()
|
||||
.and_then(|_| from_params::<(RpcH160, RpcBytes)>(params))
|
||||
.and_then(|(address, ciphertext)| {
|
||||
decrypt(&*take_weak!(self.accounts), address.into(), None, ciphertext.0)
|
||||
}))
|
||||
}
|
||||
|
||||
fn post_sign(&self, _: Params) -> Result<Value, Error> {
|
||||
// We don't support this in non-signer mode.
|
||||
Err(errors::signer_disabled())
|
||||
}
|
||||
|
||||
fn post_transaction(&self, _: Params) -> Result<Value, Error> {
|
||||
// We don't support this in non-signer mode.
|
||||
Err(errors::signer_disabled())
|
||||
}
|
||||
|
||||
fn check_request(&self, _: Params) -> Result<Value, Error> {
|
||||
// We don't support this in non-signer mode.
|
||||
Err(errors::signer_disabled())
|
||||
}
|
||||
}
|
@ -26,6 +26,6 @@ pub mod traits;
|
||||
pub mod tests;
|
||||
pub mod types;
|
||||
|
||||
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Personal, PersonalAccounts, PersonalSigner, Net, Ethcore, EthcoreSet, Traces, Rpc};
|
||||
pub use self::traits::{Web3, Eth, EthFilter, EthSigning, Net, Parity, ParityAccounts, ParitySet, ParitySigning, Signer, Personal, Traces, Rpc};
|
||||
pub use self::impls::*;
|
||||
pub use self::helpers::{SigningQueue, SignerService, ConfirmationsQueue, NetworkSettings, block_import};
|
||||
|
@ -33,7 +33,7 @@ use util::{U256, H256, Uint, Address};
|
||||
use jsonrpc_core::IoHandler;
|
||||
use ethjson::blockchain::BlockChain;
|
||||
|
||||
use v1::impls::{EthClient, EthSigningUnsafeClient};
|
||||
use v1::impls::{EthClient, SigningUnsafeClient};
|
||||
use v1::types::U256 as NU256;
|
||||
use v1::traits::eth::Eth;
|
||||
use v1::traits::eth_signing::EthSigning;
|
||||
@ -140,7 +140,7 @@ impl EthTester {
|
||||
&external_miner,
|
||||
Default::default(),
|
||||
);
|
||||
let eth_sign = EthSigningUnsafeClient::new(
|
||||
let eth_sign = SigningUnsafeClient::new(
|
||||
&client,
|
||||
&account_provider,
|
||||
&miner_service
|
||||
|
@ -27,7 +27,7 @@ use ethcore::receipt::LocalizedReceipt;
|
||||
use ethcore::transaction::{Transaction, Action};
|
||||
use ethcore::miner::{ExternalMiner, MinerService};
|
||||
use ethsync::SyncState;
|
||||
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, EthSigningUnsafeClient};
|
||||
use v1::{Eth, EthClient, EthClientOptions, EthFilter, EthFilterClient, EthSigning, SigningUnsafeClient};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestSnapshotService};
|
||||
use rustc_serialize::hex::ToHex;
|
||||
use time::get_time;
|
||||
@ -83,7 +83,7 @@ impl EthTester {
|
||||
let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
|
||||
let eth = EthClient::new(&client, &snapshot, &sync, &ap, &miner, &external_miner, options).to_delegate();
|
||||
let filter = EthFilterClient::new(&client, &miner).to_delegate();
|
||||
let sign = EthSigningUnsafeClient::new(&client, &ap, &miner).to_delegate();
|
||||
let sign = SigningUnsafeClient::new(&client, &ap, &miner).to_delegate();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(eth);
|
||||
io.add_delegate(sign);
|
||||
|
@ -18,12 +18,13 @@
|
||||
//! method calls properly.
|
||||
|
||||
mod eth;
|
||||
mod eth_signing;
|
||||
mod net;
|
||||
mod web3;
|
||||
mod personal;
|
||||
mod personal_signer;
|
||||
mod ethcore;
|
||||
mod ethcore_set;
|
||||
mod parity;
|
||||
mod parity_accounts;
|
||||
mod parity_set;
|
||||
mod rpc;
|
||||
mod signer;
|
||||
mod signing;
|
||||
mod manage_network;
|
||||
|
@ -16,19 +16,19 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use util::log::RotatingLogger;
|
||||
use util::{Address};
|
||||
use util::Address;
|
||||
use ethsync::ManageNetwork;
|
||||
use ethcore::client::{TestBlockChainClient};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethstore::ethkey::{Generator, Random};
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use v1::{Ethcore, EthcoreClient};
|
||||
use v1::{Parity, ParityClient};
|
||||
use v1::helpers::{SignerService, NetworkSettings};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService, TestFetch};
|
||||
use v1::tests::helpers::{TestSyncProvider, Config, TestMinerService};
|
||||
use super::manage_network::TestManageNetwork;
|
||||
|
||||
|
||||
pub type TestEthcoreClient = EthcoreClient<TestBlockChainClient, TestMinerService, TestSyncProvider, TestFetch>;
|
||||
pub type TestParityClient = ParityClient<TestBlockChainClient, TestMinerService, TestSyncProvider>;
|
||||
|
||||
pub struct Dependencies {
|
||||
pub miner: Arc<TestMinerService>,
|
||||
@ -37,6 +37,7 @@ pub struct Dependencies {
|
||||
pub logger: Arc<RotatingLogger>,
|
||||
pub settings: Arc<NetworkSettings>,
|
||||
pub network: Arc<ManageNetwork>,
|
||||
pub accounts: Arc<AccountProvider>,
|
||||
pub dapps_port: Option<u16>,
|
||||
}
|
||||
|
||||
@ -59,16 +60,18 @@ impl Dependencies {
|
||||
rpc_port: 8545,
|
||||
}),
|
||||
network: Arc::new(TestManageNetwork),
|
||||
accounts: Arc::new(AccountProvider::transient_provider()),
|
||||
dapps_port: Some(18080),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn client(&self, signer: Option<Arc<SignerService>>) -> TestEthcoreClient {
|
||||
EthcoreClient::with_fetch(
|
||||
pub fn client(&self, signer: Option<Arc<SignerService>>) -> TestParityClient {
|
||||
ParityClient::new(
|
||||
&self.client,
|
||||
&self.miner,
|
||||
&self.sync,
|
||||
&self.network,
|
||||
&self.accounts,
|
||||
self.logger.clone(),
|
||||
self.settings.clone(),
|
||||
signer,
|
||||
@ -90,105 +93,105 @@ impl Dependencies {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_extra_data() {
|
||||
fn rpc_parity_extra_data() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_extraData", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x01020304","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_default_extra_data() {
|
||||
fn rpc_parity_default_extra_data() {
|
||||
use util::misc;
|
||||
use util::ToPretty;
|
||||
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_defaultExtraData", "params": [], "id": 1}"#;
|
||||
let response = format!(r#"{{"jsonrpc":"2.0","result":"0x{}","id":1}}"#, misc::version_data().to_hex());
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_gas_floor_target() {
|
||||
fn rpc_parity_gas_floor_target() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_gasFloorTarget", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x3039","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_min_gas_price() {
|
||||
fn rpc_parity_min_gas_price() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_minGasPrice", "params": [], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x1312d00","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_dev_logs() {
|
||||
fn rpc_parity_dev_logs() {
|
||||
let deps = Dependencies::new();
|
||||
deps.logger.append("a".to_owned());
|
||||
deps.logger.append("b".to_owned());
|
||||
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogs", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_devLogs", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":["b","a"],"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_dev_logs_levels() {
|
||||
fn rpc_parity_dev_logs_levels() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_devLogsLevels", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"rpc=trace","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_transactions_limit() {
|
||||
fn rpc_parity_transactions_limit() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_transactionsLimit", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":1024,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_net_chain() {
|
||||
fn rpc_parity_net_chain() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_netChain", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"testchain","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_net_peers() {
|
||||
fn rpc_parity_net_peers() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPeers", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_netPeers", "params":[], "id": 1}"#;
|
||||
let response = "{\"jsonrpc\":\"2.0\",\"result\":{\"active\":0,\"connected\":120,\"max\":50,\"peers\":[{\"caps\":[\"eth/62\",\"eth/63\"],\
|
||||
\"id\":\"node1\",\"name\":\"Parity/1\",\"network\":{\"localAddress\":\"127.0.0.1:8888\",\"remoteAddress\":\"127.0.0.1:7777\"}\
|
||||
,\"protocols\":{\"eth\":{\"difficulty\":\"0x28\",\"head\":\"0000000000000000000000000000000000000000000000000000000000000032\"\
|
||||
@ -200,101 +203,90 @@ fn rpc_ethcore_net_peers() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_net_port() {
|
||||
fn rpc_parity_net_port() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_netPort", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":30303,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_rpc_settings() {
|
||||
fn rpc_parity_rpc_settings() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_rpcSettings", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":{"enabled":true,"interface":"all","port":8545},"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_node_name() {
|
||||
fn rpc_parity_node_name() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_nodeName", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"mynode","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_unsigned_transactions_count() {
|
||||
fn rpc_parity_unsigned_transactions_count() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.with_signer(SignerService::new_test(Some(18180)));
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":0,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_unsigned_transactions_count_when_signer_disabled() {
|
||||
fn rpc_parity_unsigned_transactions_count_when_signer_disabled() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_unsignedTransactionsCount", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_unsignedTransactionsCount", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_hash_content() {
|
||||
fn rpc_parity_pending_transactions() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_pending_transactions() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_pendingTransactions", "params":[], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_pendingTransactions", "params":[], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":[],"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_encrypt() {
|
||||
fn rpc_parity_encrypt() {
|
||||
let deps = Dependencies::new();
|
||||
let io = deps.default_client();
|
||||
let key = format!("{:?}", Random.generate().unwrap().public());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_encryptMessage", "params":["0x"#.to_owned() + &key + r#"", "0x01"], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_encryptMessage", "params":["0x"#.to_owned() + &key + r#"", "0x01"], "id": 1}"#;
|
||||
assert!(io.handle_request_sync(&request).unwrap().contains("result"), "Should return success.");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_signer_port() {
|
||||
fn rpc_parity_signer_port() {
|
||||
// given
|
||||
let deps = Dependencies::new();
|
||||
let io1 = deps.with_signer(SignerService::new_test(Some(18180)));
|
||||
let io2 = deps.default_client();
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_signerPort", "params": [], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_signerPort", "params": [], "id": 1}"#;
|
||||
let response1 = r#"{"jsonrpc":"2.0","result":18180,"id":1}"#;
|
||||
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32030,"message":"Trusted Signer is disabled. This API is not available.","data":null},"id":1}"#;
|
||||
|
||||
@ -304,7 +296,7 @@ fn rpc_ethcore_signer_port() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_dapps_port() {
|
||||
fn rpc_parity_dapps_port() {
|
||||
// given
|
||||
let mut deps = Dependencies::new();
|
||||
let io1 = deps.default_client();
|
||||
@ -312,7 +304,7 @@ fn rpc_ethcore_dapps_port() {
|
||||
let io2 = deps.default_client();
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_dappsPort", "params": [], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_dappsPort", "params": [], "id": 1}"#;
|
||||
let response1 = r#"{"jsonrpc":"2.0","result":18080,"id":1}"#;
|
||||
let response2 = r#"{"jsonrpc":"2.0","error":{"code":-32031,"message":"Dapps Server is disabled. This API is not available.","data":null},"id":1}"#;
|
||||
|
||||
@ -322,7 +314,7 @@ fn rpc_ethcore_dapps_port() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_next_nonce() {
|
||||
fn rpc_parity_next_nonce() {
|
||||
let deps = Dependencies::new();
|
||||
let address = Address::default();
|
||||
let io1 = deps.default_client();
|
||||
@ -332,7 +324,7 @@ fn rpc_ethcore_next_nonce() {
|
||||
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "ethcore_nextNonce",
|
||||
"method": "parity_nextNonce",
|
||||
"params": [""#.to_owned() + &format!("0x{:?}", address) + r#""],
|
||||
"id": 1
|
||||
}"#;
|
118
rpc/src/v1/tests/mocked/parity_accounts.rs
Normal file
118
rpc/src/v1/tests/mocked/parity_accounts.rs
Normal file
@ -0,0 +1,118 @@
|
||||
// Copyright 2015, 2016 Ethcore (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/>.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::TestBlockChainClient;
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use v1::{ParityAccounts, ParityAccountsClient};
|
||||
|
||||
struct ParityAccountsTester {
|
||||
accounts: Arc<AccountProvider>,
|
||||
io: IoHandler,
|
||||
// these unused fields are necessary to keep the data alive
|
||||
// as the handler has only weak pointers.
|
||||
_client: Arc<TestBlockChainClient>,
|
||||
}
|
||||
|
||||
fn blockchain_client() -> Arc<TestBlockChainClient> {
|
||||
let client = TestBlockChainClient::new();
|
||||
Arc::new(client)
|
||||
}
|
||||
|
||||
fn accounts_provider() -> Arc<AccountProvider> {
|
||||
Arc::new(AccountProvider::transient_provider())
|
||||
}
|
||||
|
||||
fn setup() -> ParityAccountsTester {
|
||||
let accounts = accounts_provider();
|
||||
let client = blockchain_client();
|
||||
let parity_accounts = ParityAccountsClient::new(&accounts, &client);
|
||||
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_accounts.to_delegate());
|
||||
|
||||
let tester = ParityAccountsTester {
|
||||
accounts: accounts,
|
||||
io: io,
|
||||
_client: client,
|
||||
};
|
||||
|
||||
tester
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_get_account_info() {
|
||||
let tester = setup();
|
||||
tester.accounts.new_account("").unwrap();
|
||||
let accounts = tester.accounts.accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let address = accounts[0];
|
||||
|
||||
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
|
||||
tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
|
||||
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_set_name() {
|
||||
let tester = setup();
|
||||
tester.accounts.new_account("").unwrap();
|
||||
let accounts = tester.accounts.accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let address = accounts[0];
|
||||
|
||||
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_setAccountName", "params": ["0x{}", "Test"], "id": 1}}"#, address.hex());
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
let res = tester.io.handle_request_sync(&request);
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_set_meta() {
|
||||
let tester = setup();
|
||||
tester.accounts.new_account("").unwrap();
|
||||
let accounts = tester.accounts.accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let address = accounts[0];
|
||||
|
||||
let request = format!(r#"{{"jsonrpc": "2.0", "method": "parity_setAccountMeta", "params": ["0x{}", "{{foo: 69}}"], "id": 1}}"#, address.hex());
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
let res = tester.io.handle_request_sync(&request);
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_accountsInfo", "params": [], "id": 1}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"{}\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid, uuid);
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
@ -16,16 +16,18 @@
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
use jsonrpc_core::IoHandler;
|
||||
use v1::{EthcoreSet, EthcoreSetClient};
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use util::{U256, Address};
|
||||
|
||||
use ethcore::miner::MinerService;
|
||||
use ethcore::client::TestBlockChainClient;
|
||||
use v1::tests::helpers::TestMinerService;
|
||||
use util::{U256, Address};
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use super::manage_network::TestManageNetwork;
|
||||
use ethsync::ManageNetwork;
|
||||
|
||||
use jsonrpc_core::IoHandler;
|
||||
use v1::{ParitySet, ParitySetClient};
|
||||
use v1::tests::helpers::{TestMinerService, TestFetch};
|
||||
use super::manage_network::TestManageNetwork;
|
||||
|
||||
fn miner_service() -> Arc<TestMinerService> {
|
||||
Arc::new(TestMinerService::default())
|
||||
}
|
||||
@ -38,19 +40,21 @@ fn network_service() -> Arc<TestManageNetwork> {
|
||||
Arc::new(TestManageNetwork)
|
||||
}
|
||||
|
||||
fn ethcore_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, net: &Arc<TestManageNetwork>) -> EthcoreSetClient<TestBlockChainClient, TestMinerService> {
|
||||
EthcoreSetClient::new(client, miner, &(net.clone() as Arc<ManageNetwork>))
|
||||
pub type TestParitySetClient = ParitySetClient<TestBlockChainClient, TestMinerService, TestFetch>;
|
||||
|
||||
fn parity_set_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>, net: &Arc<TestManageNetwork>) -> TestParitySetClient {
|
||||
ParitySetClient::with_fetch(client, miner, &(net.clone() as Arc<ManageNetwork>))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_set_min_gas_price() {
|
||||
fn rpc_parity_set_min_gas_price() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
@ -58,14 +62,14 @@ fn rpc_ethcore_set_min_gas_price() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_set_gas_floor_target() {
|
||||
fn rpc_parity_set_gas_floor_target() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
@ -73,14 +77,14 @@ fn rpc_ethcore_set_gas_floor_target() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_set_extra_data() {
|
||||
fn rpc_parity_set_extra_data() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
@ -88,14 +92,14 @@ fn rpc_ethcore_set_extra_data() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_set_author() {
|
||||
fn rpc_parity_set_author() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
@ -103,16 +107,31 @@ fn rpc_ethcore_set_author() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_set_transactions_limit() {
|
||||
fn rpc_parity_set_transactions_limit() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_set_client(&client, &miner, &network).to_delegate());
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#;
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_setTransactionsLimit", "params":[10240240], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
assert_eq!(miner.transactions_limit(), 10_240_240);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_parity_set_hash_content() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let network = network_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(parity_set_client(&client, &miner, &network).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "parity_hashContent", "params":["https://ethcore.io/assets/images/ethcore-black-horizontal.png"], "id": 1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":"0x2be00befcf008bc0e7d9cdefc194db9c75352e8632f48498b5a6bfce9f02c88e","id":1}"#;
|
||||
|
||||
assert_eq!(io.handle_request_sync(request), Some(response.to_owned()));
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ use std::str::FromStr;
|
||||
use jsonrpc_core::IoHandler;
|
||||
use util::{U256, Uint, Address};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use v1::{PersonalClient, PersonalAccountsClient, PersonalAccounts, Personal};
|
||||
use v1::{PersonalClient, Personal};
|
||||
use v1::tests::helpers::TestMinerService;
|
||||
use ethcore::client::TestBlockChainClient;
|
||||
use ethcore::transaction::{Action, Transaction};
|
||||
@ -50,12 +50,10 @@ fn setup() -> PersonalTester {
|
||||
let accounts = accounts_provider();
|
||||
let client = blockchain_client();
|
||||
let miner = miner_service();
|
||||
let personal = PersonalClient::new(&accounts, &client);
|
||||
let personal_accounts = PersonalAccountsClient::new(&accounts, &client, &miner, false);
|
||||
let personal = PersonalClient::new(&accounts, &client, &miner, false);
|
||||
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(personal.to_delegate());
|
||||
io.add_delegate(personal_accounts.to_delegate());
|
||||
|
||||
let tester = PersonalTester {
|
||||
accounts: accounts,
|
||||
@ -92,66 +90,6 @@ fn new_account() {
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_get_account_info() {
|
||||
let tester = setup();
|
||||
tester.accounts.new_account("").unwrap();
|
||||
let accounts = tester.accounts.accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let address = accounts[0];
|
||||
|
||||
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
|
||||
tester.accounts.set_account_name(address.clone(), "Test".to_owned()).unwrap();
|
||||
tester.accounts.set_account_meta(address.clone(), "{foo: 69}".to_owned()).unwrap();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_set_name() {
|
||||
let tester = setup();
|
||||
tester.accounts.new_account("").unwrap();
|
||||
let accounts = tester.accounts.accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let address = accounts[0];
|
||||
|
||||
let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountName", "params": ["0x{}", "Test"], "id": 1}}"#, address.hex());
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
let res = tester.io.handle_request_sync(&request);
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{}}\",\"name\":\"Test\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid);
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_be_able_to_set_meta() {
|
||||
let tester = setup();
|
||||
tester.accounts.new_account("").unwrap();
|
||||
let accounts = tester.accounts.accounts().unwrap();
|
||||
assert_eq!(accounts.len(), 1);
|
||||
let address = accounts[0];
|
||||
|
||||
let request = format!(r#"{{"jsonrpc": "2.0", "method": "personal_setAccountMeta", "params": ["0x{}", "{{foo: 69}}"], "id": 1}}"#, address.hex());
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
let res = tester.io.handle_request_sync(&request);
|
||||
assert_eq!(res, Some(response.into()));
|
||||
|
||||
let uuid = tester.accounts.accounts_info().unwrap().get(&address).unwrap().uuid.as_ref().unwrap().clone();
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "personal_accountsInfo", "params": [], "id": 1}"#;
|
||||
let res = tester.io.handle_request_sync(request);
|
||||
let response = format!("{{\"jsonrpc\":\"2.0\",\"result\":{{\"0x{}\":{{\"meta\":\"{{foo: 69}}\",\"name\":\"{}\",\"uuid\":\"{}\"}}}},\"id\":1}}", address.hex(), uuid, uuid);
|
||||
assert_eq!(res, Some(response));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sign_and_send_transaction_with_invalid_password() {
|
||||
let tester = setup();
|
||||
|
@ -21,11 +21,11 @@ use util::{U256, Uint, Address};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
use ethcore::client::TestBlockChainClient;
|
||||
use ethcore::transaction::{Transaction, Action};
|
||||
use v1::{SignerClient, PersonalSigner};
|
||||
use v1::{SignerClient, Signer};
|
||||
use v1::tests::helpers::TestMinerService;
|
||||
use v1::helpers::{SigningQueue, SignerService, FilledTransactionRequest, ConfirmationPayload};
|
||||
|
||||
struct PersonalSignerTester {
|
||||
struct SignerTester {
|
||||
signer: Arc<SignerService>,
|
||||
accounts: Arc<AccountProvider>,
|
||||
io: IoHandler,
|
||||
@ -48,7 +48,7 @@ fn miner_service() -> Arc<TestMinerService> {
|
||||
Arc::new(TestMinerService::default())
|
||||
}
|
||||
|
||||
fn signer_tester() -> PersonalSignerTester {
|
||||
fn signer_tester() -> SignerTester {
|
||||
let signer = Arc::new(SignerService::new_test(None));
|
||||
let accounts = accounts_provider();
|
||||
let client = blockchain_client();
|
||||
@ -57,7 +57,7 @@ fn signer_tester() -> PersonalSignerTester {
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(SignerClient::new(&accounts, &client, &miner, &signer).to_delegate());
|
||||
|
||||
PersonalSignerTester {
|
||||
SignerTester {
|
||||
signer: signer,
|
||||
accounts: accounts,
|
||||
io: io,
|
||||
@ -83,7 +83,7 @@ fn should_return_list_of_items_to_confirm() {
|
||||
tester.signer.add_request(ConfirmationPayload::Sign(1.into(), 5.into())).unwrap();
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc":"2.0","method":"personal_requestsToConfirm","params":[],"id":1}"#;
|
||||
let request = r#"{"jsonrpc":"2.0","method":"signer_requestsToConfirm","params":[],"id":1}"#;
|
||||
let response = concat!(
|
||||
r#"{"jsonrpc":"2.0","result":["#,
|
||||
r#"{"id":"0x1","payload":{"transaction":{"data":"0x","from":"0x0000000000000000000000000000000000000001","gas":"0x989680","gasPrice":"0x2710","nonce":null,"to":"0xd46e8dd67c5d32be8058bb8eb970870f07244567","value":"0x1"}}},"#,
|
||||
@ -112,7 +112,7 @@ fn should_reject_transaction_from_queue_without_dispatching() {
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc":"2.0","method":"personal_rejectRequest","params":["0x1"],"id":1}"#;
|
||||
let request = r#"{"jsonrpc":"2.0","method":"signer_rejectRequest","params":["0x1"],"id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","result":true,"id":1}"#;
|
||||
|
||||
// then
|
||||
@ -137,7 +137,7 @@ fn should_not_remove_transaction_if_password_is_invalid() {
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc":"2.0","method":"personal_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
|
||||
let request = r#"{"jsonrpc":"2.0","method":"signer_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#;
|
||||
|
||||
// then
|
||||
@ -153,7 +153,7 @@ fn should_not_remove_sign_if_password_is_invalid() {
|
||||
assert_eq!(tester.signer.requests().len(), 1);
|
||||
|
||||
// when
|
||||
let request = r#"{"jsonrpc":"2.0","method":"personal_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
|
||||
let request = r#"{"jsonrpc":"2.0","method":"signer_confirmRequest","params":["0x1",{},"xxx"],"id":1}"#;
|
||||
let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidAccount)"},"id":1}"#;
|
||||
|
||||
// then
|
||||
@ -194,7 +194,7 @@ fn should_confirm_transaction_and_dispatch() {
|
||||
// when
|
||||
let request = r#"{
|
||||
"jsonrpc":"2.0",
|
||||
"method":"personal_confirmRequest",
|
||||
"method":"signer_confirmRequest",
|
||||
"params":["0x1", {"gasPrice":"0x1000"}, "test"],
|
||||
"id":1
|
||||
}"#;
|
||||
@ -214,7 +214,7 @@ fn should_generate_new_token() {
|
||||
// when
|
||||
let request = r#"{
|
||||
"jsonrpc":"2.0",
|
||||
"method":"personal_generateAuthorizationToken",
|
||||
"method":"signer_generateAuthorizationToken",
|
||||
"params":[],
|
||||
"id":1
|
||||
}"#;
|
@ -17,12 +17,12 @@
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use jsonrpc_core::{IoHandler, to_value, Success};
|
||||
use v1::impls::EthSigningQueueClient;
|
||||
use v1::traits::{EthSigning, Ethcore};
|
||||
use v1::impls::SigningQueueClient;
|
||||
use v1::traits::{EthSigning, ParitySigning, Parity};
|
||||
use v1::helpers::{SignerService, SigningQueue};
|
||||
use v1::types::{H256 as RpcH256, H520 as RpcH520, Bytes};
|
||||
use v1::tests::helpers::TestMinerService;
|
||||
use v1::tests::mocked::ethcore;
|
||||
use v1::tests::mocked::parity;
|
||||
|
||||
use util::{Address, FixedHash, Uint, U256, H256, H520};
|
||||
use ethcore::account_provider::AccountProvider;
|
||||
@ -31,7 +31,7 @@ use ethcore::transaction::{Transaction, Action};
|
||||
use ethstore::ethkey::{Generator, Random};
|
||||
use serde_json;
|
||||
|
||||
struct EthSigningTester {
|
||||
struct SigningTester {
|
||||
pub signer: Arc<SignerService>,
|
||||
pub client: Arc<TestBlockChainClient>,
|
||||
pub miner: Arc<TestMinerService>,
|
||||
@ -39,16 +39,19 @@ struct EthSigningTester {
|
||||
pub io: IoHandler,
|
||||
}
|
||||
|
||||
impl Default for EthSigningTester {
|
||||
impl Default for SigningTester {
|
||||
fn default() -> Self {
|
||||
let signer = Arc::new(SignerService::new_test(None));
|
||||
let client = Arc::new(TestBlockChainClient::default());
|
||||
let miner = Arc::new(TestMinerService::default());
|
||||
let accounts = Arc::new(AccountProvider::transient_provider());
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(EthSigningQueueClient::new(&signer, &client, &miner, &accounts).to_delegate());
|
||||
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
|
||||
io.add_delegate(EthSigning::to_delegate(rpc));
|
||||
let rpc = SigningQueueClient::new(&signer, &client, &miner, &accounts);
|
||||
io.add_delegate(ParitySigning::to_delegate(rpc));
|
||||
|
||||
EthSigningTester {
|
||||
SigningTester {
|
||||
signer: signer,
|
||||
client: client,
|
||||
miner: miner,
|
||||
@ -58,8 +61,8 @@ impl Default for EthSigningTester {
|
||||
}
|
||||
}
|
||||
|
||||
fn eth_signing() -> EthSigningTester {
|
||||
EthSigningTester::default()
|
||||
fn eth_signing() -> SigningTester {
|
||||
SigningTester::default()
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -101,7 +104,7 @@ fn should_post_sign_to_queue() {
|
||||
// when
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_postSign",
|
||||
"method": "parity_postSign",
|
||||
"params": [
|
||||
""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000005"
|
||||
@ -122,7 +125,7 @@ fn should_check_status_of_request() {
|
||||
let address = Address::random();
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_postSign",
|
||||
"method": "parity_postSign",
|
||||
"params": [
|
||||
""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000005"
|
||||
@ -134,7 +137,7 @@ fn should_check_status_of_request() {
|
||||
// when
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_checkRequest",
|
||||
"method": "parity_checkRequest",
|
||||
"params": ["0x1"],
|
||||
"id": 1
|
||||
}"#;
|
||||
@ -151,7 +154,7 @@ fn should_check_status_of_request_when_its_resolved() {
|
||||
let address = Address::random();
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_postSign",
|
||||
"method": "parity_postSign",
|
||||
"params": [
|
||||
""#.to_owned() + format!("0x{:?}", address).as_ref() + r#"",
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000005"
|
||||
@ -164,7 +167,7 @@ fn should_check_status_of_request_when_its_resolved() {
|
||||
// when
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "eth_checkRequest",
|
||||
"method": "parity_checkRequest",
|
||||
"params": ["0x1"],
|
||||
"id": 1
|
||||
}"#;
|
||||
@ -272,15 +275,15 @@ fn should_dispatch_transaction_if_account_is_unlock() {
|
||||
fn should_decrypt_message_if_account_is_unlocked() {
|
||||
// given
|
||||
let tester = eth_signing();
|
||||
let ethcore = ethcore::Dependencies::new();
|
||||
tester.io.add_delegate(ethcore.client(None).to_delegate());
|
||||
let parity = parity::Dependencies::new();
|
||||
tester.io.add_delegate(parity.client(None).to_delegate());
|
||||
let (address, public) = tester.accounts.new_account_and_public("test").unwrap();
|
||||
tester.accounts.unlock_account_permanently(address, "test".into()).unwrap();
|
||||
|
||||
|
||||
// First encrypt message
|
||||
let request = format!("{}0x{:?}{}",
|
||||
r#"{"jsonrpc": "2.0", "method": "ethcore_encryptMessage", "params":[""#,
|
||||
r#"{"jsonrpc": "2.0", "method": "parity_encryptMessage", "params":[""#,
|
||||
public,
|
||||
r#"", "0x01020304"], "id": 1}"#
|
||||
);
|
||||
@ -288,7 +291,7 @@ fn should_decrypt_message_if_account_is_unlocked() {
|
||||
|
||||
// then call decrypt
|
||||
let request = format!("{}{:?}{}{:?}{}",
|
||||
r#"{"jsonrpc": "2.0", "method": "ethcore_decryptMessage", "params":["0x"#,
|
||||
r#"{"jsonrpc": "2.0", "method": "parity_decryptMessage", "params":["0x"#,
|
||||
address,
|
||||
r#"","#,
|
||||
encrypted.result,
|
||||
@ -311,7 +314,7 @@ fn should_add_decryption_to_the_queue() {
|
||||
// when
|
||||
let request = r#"{
|
||||
"jsonrpc": "2.0",
|
||||
"method": "ethcore_decryptMessage",
|
||||
"method": "parity_decryptMessage",
|
||||
"params": ["0x"#.to_owned() + &format!("{:?}", acc.address()) + r#"",
|
||||
"0x012345"],
|
||||
"id": 1
|
@ -23,41 +23,18 @@ pub trait EthSigning: Sized + Send + Sync + 'static {
|
||||
/// Signs the data with given address signature.
|
||||
fn sign(&self, _: Params, _: Ready);
|
||||
|
||||
/// Posts sign request asynchronously.
|
||||
/// Will return a confirmation ID for later use with check_transaction.
|
||||
fn post_sign(&self, _: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Sends transaction; will block for 20s to try to return the
|
||||
/// transaction hash.
|
||||
/// If it cannot yet be signed, it will return a transaction ID for
|
||||
/// later use with check_transaction.
|
||||
fn send_transaction(&self, _: Params, _: Ready);
|
||||
|
||||
/// Posts transaction asynchronously.
|
||||
/// Will return a transaction ID for later use with check_transaction.
|
||||
fn post_transaction(&self, _: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Checks the progress of a previously posted request (transaction/sign).
|
||||
/// Should be given a valid send_transaction ID.
|
||||
/// Returns the transaction hash, the zero hash (not yet available),
|
||||
/// or the signature,
|
||||
/// or an error.
|
||||
fn check_request(&self, _: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Decrypt some ECIES-encrypted message.
|
||||
/// First parameter is the address with which it is encrypted, second is the ciphertext.
|
||||
fn decrypt_message(&self, _: Params, _: Ready);
|
||||
|
||||
/// Should be used to convert object to io delegate.
|
||||
fn to_delegate(self) -> IoDelegate<Self> {
|
||||
let mut delegate = IoDelegate::new(Arc::new(self));
|
||||
delegate.add_async_method("eth_sign", EthSigning::sign);
|
||||
delegate.add_async_method("eth_sendTransaction", EthSigning::send_transaction);
|
||||
delegate.add_async_method("ethcore_decryptMessage", EthSigning::decrypt_message);
|
||||
|
||||
delegate.add_method("eth_postSign", EthSigning::post_sign);
|
||||
delegate.add_method("eth_postTransaction", EthSigning::post_transaction);
|
||||
delegate.add_method("eth_checkRequest", EthSigning::check_request);
|
||||
delegate
|
||||
}
|
||||
}
|
||||
|
@ -20,9 +20,12 @@ pub mod web3;
|
||||
pub mod eth;
|
||||
pub mod eth_signing;
|
||||
pub mod net;
|
||||
pub mod parity;
|
||||
pub mod parity_accounts;
|
||||
pub mod parity_set;
|
||||
pub mod parity_signing;
|
||||
pub mod personal;
|
||||
pub mod ethcore;
|
||||
pub mod ethcore_set;
|
||||
pub mod signer;
|
||||
pub mod traces;
|
||||
pub mod rpc;
|
||||
|
||||
@ -30,9 +33,12 @@ pub use self::web3::Web3;
|
||||
pub use self::eth::{Eth, EthFilter};
|
||||
pub use self::eth_signing::EthSigning;
|
||||
pub use self::net::Net;
|
||||
pub use self::personal::{Personal, PersonalAccounts, PersonalSigner};
|
||||
pub use self::ethcore::Ethcore;
|
||||
pub use self::ethcore_set::EthcoreSet;
|
||||
pub use self::parity::Parity;
|
||||
pub use self::parity_accounts::ParityAccounts;
|
||||
pub use self::parity_set::ParitySet;
|
||||
pub use self::parity_signing::ParitySigning;
|
||||
pub use self::personal::Personal;
|
||||
pub use self::signer::Signer;
|
||||
pub use self::traces::Traces;
|
||||
pub use self::rpc::Rpc;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user