diff --git a/README.md b/README.md index 4861d7ac5..fc5cd9762 100644 --- a/README.md +++ b/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] [![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] [![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! diff --git a/js/src/api/README.md b/js/src/api/README.md index 691a24cca..e28c6c2a1 100644 --- a/js/src/api/README.md +++ b/js/src/api/README.md @@ -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) diff --git a/js/src/api/api.js b/js/src/api/api.js index 9768b9acb..75d4392d0 100644 --- a/js/src/api/api.js +++ b/js/src/api/api.js @@ -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; } diff --git a/js/src/api/contract/contract.js b/js/src/api/contract/contract.js index cef75eda7..bb6c15d8d 100644 --- a/js/src/api/contract/contract.js +++ b/js/src/api/contract/contract.js @@ -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)); }; diff --git a/js/src/api/contract/contract.spec.js b/js/src/api/contract/contract.spec.js index 0d6169e26..9065b4fad 100644 --- a/js/src/api/contract/contract.spec.js +++ b/js/src/api/contract/contract.spec.js @@ -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 diff --git a/js/src/api/rpc/eth/eth.js b/js/src/api/rpc/eth/eth.js index 703f3ed11..43f8025e1 100644 --- a/js/src/api/rpc/eth/eth.js +++ b/js/src/api/rpc/eth/eth.js @@ -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'); diff --git a/js/src/api/rpc/ethcore/ethcore.js b/js/src/api/rpc/ethcore/ethcore.js deleted file mode 100644 index e21c83193..000000000 --- a/js/src/api/rpc/ethcore/ethcore.js +++ /dev/null @@ -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 . - -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); - } -} diff --git a/js/src/api/rpc/index.js b/js/src/api/rpc/index.js index e7e94b9ed..7961da81c 100644 --- a/js/src/api/rpc/index.js +++ b/js/src/api/rpc/index.js @@ -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'; diff --git a/js/src/api/rpc/ethcore/index.js b/js/src/api/rpc/parity/index.js similarity index 95% rename from js/src/api/rpc/ethcore/index.js rename to js/src/api/rpc/parity/index.js index 2372a2171..38f08f725 100644 --- a/js/src/api/rpc/ethcore/index.js +++ b/js/src/api/rpc/parity/index.js @@ -14,4 +14,4 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -export default from './ethcore'; +export default from './parity'; diff --git a/js/src/api/rpc/ethcore/ethcore.e2e.js b/js/src/api/rpc/parity/parity.e2e.js similarity index 82% rename from js/src/api/rpc/ethcore/ethcore.e2e.js rename to js/src/api/rpc/parity/parity.e2e.js index aae7108e7..91e01ab6a 100644 --- a/js/src/api/rpc/ethcore/ethcore.e2e.js +++ b/js/src/api/rpc/parity/parity.e2e.js @@ -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; }); }); diff --git a/js/src/api/rpc/parity/parity.js b/js/src/api/rpc/parity/parity.js new file mode 100644 index 000000000..f1739f848 --- /dev/null +++ b/js/src/api/rpc/parity/parity.js @@ -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 . + +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); + } +} diff --git a/js/src/api/rpc/ethcore/ethcore.spec.js b/js/src/api/rpc/parity/parity.spec.js similarity index 66% rename from js/src/api/rpc/ethcore/ethcore.spec.js rename to js/src/api/rpc/parity/parity.spec.js index fd34550a7..ea0dd8d8c 100644 --- a/js/src/api/rpc/ethcore/ethcore.spec.js +++ b/js/src/api/rpc/parity/parity.spec.js @@ -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; diff --git a/js/src/api/rpc/personal/personal.js b/js/src/api/rpc/personal/personal.js index ca7dbce9b..db9a71d23 100644 --- a/js/src/api/rpc/personal/personal.js +++ b/js/src/api/rpc/personal/personal.js @@ -14,113 +14,31 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -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)); diff --git a/js/src/api/rpc/personal/personal.spec.js b/js/src/api/rpc/personal/personal.spec.js index 70734c7ee..a9bf4f644 100644 --- a/js/src/api/rpc/personal/personal.spec.js +++ b/js/src/api/rpc/personal/personal.spec.js @@ -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] } }]); diff --git a/js/src/api/rpc/signer/index.js b/js/src/api/rpc/signer/index.js new file mode 100644 index 000000000..6426bdc06 --- /dev/null +++ b/js/src/api/rpc/signer/index.js @@ -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 . + +export default from './signer'; diff --git a/js/src/api/rpc/signer/signer.js b/js/src/api/rpc/signer/signer.js new file mode 100644 index 000000000..7f905cf50 --- /dev/null +++ b/js/src/api/rpc/signer/signer.js @@ -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 . + +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'); + } +} diff --git a/js/src/api/subscriptions/manager.js b/js/src/api/subscriptions/manager.js index 61e06499e..08f1a9e53 100644 --- a/js/src/api/subscriptions/manager.js +++ b/js/src/api/subscriptions/manager.js @@ -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 { diff --git a/js/src/api/subscriptions/personal.js b/js/src/api/subscriptions/personal.js index d65419962..58428895b 100644 --- a/js/src/api/subscriptions/personal.js +++ b/js/src/api/subscriptions/personal.js @@ -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; } diff --git a/js/src/api/subscriptions/personal.spec.js b/js/src/api/subscriptions/personal.spec.js index 1a77b5f61..d6fd2b203 100644 --- a/js/src/api/subscriptions/personal.spec.js +++ b/js/src/api/subscriptions/personal.spec.js @@ -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); }); }); diff --git a/js/src/api/subscriptions/signer.js b/js/src/api/subscriptions/signer.js index af745261b..4413fe432 100644 --- a/js/src/api/subscriptions/signer.js +++ b/js/src/api/subscriptions/signer.js @@ -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); diff --git a/js/src/api/transport/http/http.js b/js/src/api/transport/http/http.js index 65ba089cc..08d9422f8 100644 --- a/js/src/api/transport/http/http.js +++ b/js/src/api/transport/http/http.js @@ -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)); diff --git a/js/src/api/transport/ws/ws.js b/js/src/api/transport/ws/ws.js index 119f4ba76..d608426b0 100644 --- a/js/src/api/transport/ws/ws.js +++ b/js/src/api/transport/ws/ws.js @@ -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; } diff --git a/js/src/contracts/registry.js b/js/src/contracts/registry.js index 85b9d6bb5..9853c0df9 100644 --- a/js/src/contracts/registry.js +++ b/js/src/contracts/registry.js @@ -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; diff --git a/js/src/dapps/basiccoin/Application/application.js b/js/src/dapps/basiccoin/Application/application.js index 4ab97ab6c..abe0c90c5 100644 --- a/js/src/dapps/basiccoin/Application/application.js +++ b/js/src/dapps/basiccoin/Application/application.js @@ -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 || {}; diff --git a/js/src/dapps/basiccoin/Deploy/Deployment/deployment.js b/js/src/dapps/basiccoin/Deploy/Deployment/deployment.js index f9232789b..0fa7dc863 100644 --- a/js/src/dapps/basiccoin/Deploy/Deployment/deployment.js +++ b/js/src/dapps/basiccoin/Deploy/Deployment/deployment.js @@ -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' }); diff --git a/js/src/dapps/basiccoin/Transfer/Send/send.js b/js/src/dapps/basiccoin/Transfer/Send/send.js index aee860fe2..a9c05a228 100644 --- a/js/src/dapps/basiccoin/Transfer/Send/send.js +++ b/js/src/dapps/basiccoin/Transfer/Send/send.js @@ -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' }); diff --git a/js/src/dapps/basiccoin/services.js b/js/src/dapps/basiccoin/services.js index 28cc662a7..4aed4199f 100644 --- a/js/src/dapps/basiccoin/services.js +++ b/js/src/dapps/basiccoin/services.js @@ -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; diff --git a/js/src/dapps/githubhint.html b/js/src/dapps/githubhint.html index 631182fcb..746c7f466 100644 --- a/js/src/dapps/githubhint.html +++ b/js/src/dapps/githubhint.html @@ -11,7 +11,6 @@
- diff --git a/js/src/dapps/githubhint/Application/application.js b/js/src/dapps/githubhint/Application/application.js index 4a25d3855..5a7494928 100644 --- a/js/src/dapps/githubhint/Application/application.js +++ b/js/src/dapps/githubhint/Application/application.js @@ -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); diff --git a/js/src/dapps/githubhint/parity.js b/js/src/dapps/githubhint/parity.js index f6d59f44d..acee4dee0 100644 --- a/js/src/dapps/githubhint/parity.js +++ b/js/src/dapps/githubhint/parity.js @@ -14,7 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -const { api } = window.parity; +const api = window.parent.secureApi; export { api diff --git a/js/src/dapps/githubhint/services.js b/js/src/dapps/githubhint/services.js index b7676d5f5..c9d260b73 100644 --- a/js/src/dapps/githubhint/services.js +++ b/js/src/dapps/githubhint/services.js @@ -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]) => { diff --git a/js/src/dapps/registry/actions.js b/js/src/dapps/registry/actions.js index 882af0360..b1390926b 100644 --- a/js/src/dapps/registry/actions.js +++ b/js/src/dapps/registry/actions.js @@ -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)); diff --git a/js/src/dapps/registry/addresses/actions.js b/js/src/dapps/registry/addresses/actions.js index 17975f9e6..2341d716c 100644 --- a/js/src/dapps/registry/addresses/actions.js +++ b/js/src/dapps/registry/addresses/actions.js @@ -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 || {}; diff --git a/js/src/dapps/signaturereg/services.js b/js/src/dapps/signaturereg/services.js index cab324f7e..54394c4b8 100644 --- a/js/src/dapps/signaturereg/services.js +++ b/js/src/dapps/signaturereg/services.js @@ -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]) => { diff --git a/js/src/dapps/tokenreg/Accounts/actions.js b/js/src/dapps/tokenreg/Accounts/actions.js index f501399c2..58a74dfd8 100644 --- a/js/src/dapps/tokenreg/Accounts/actions.js +++ b/js/src/dapps/tokenreg/Accounts/actions.js @@ -38,7 +38,7 @@ export const loadAccounts = () => (dispatch) => { Promise .all([ api.eth.accounts(), - api.personal.accountsInfo() + api.parity.accounts() ]) .then(([ accounts, accountsInfo ]) => { accountsInfo = accountsInfo || {}; diff --git a/js/src/dapps/tokenreg/Status/actions.js b/js/src/dapps/tokenreg/Status/actions.js index b7de9c108..e9e217d6a 100644 --- a/js/src/dapps/tokenreg/Status/actions.js +++ b/js/src/dapps/tokenreg/Status/actions.js @@ -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}`); diff --git a/js/src/index.js b/js/src/index.js index a8cb8ac96..966e2708e 100644 --- a/js/src/index.js +++ b/js/src/index.js @@ -74,7 +74,7 @@ ReactDOM.render( - + diff --git a/js/src/jsonrpc/index.js b/js/src/jsonrpc/index.js index 18bd4302d..9e9692279 100644 --- a/js/src/jsonrpc/index.js +++ b/js/src/jsonrpc/index.js @@ -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 }; diff --git a/js/src/jsonrpc/interfaces/eth.js b/js/src/jsonrpc/interfaces/eth.js index f1c8fb86f..d5ff471fb 100644 --- a/js/src/jsonrpc/interfaces/eth.js +++ b/js/src/jsonrpc/interfaces/eth.js @@ -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: [], diff --git a/js/src/jsonrpc/interfaces/ethcore.js b/js/src/jsonrpc/interfaces/parity.js similarity index 66% rename from js/src/jsonrpc/interfaces/ethcore.js rename to js/src/jsonrpc/interfaces/parity.js index 310276cc8..66a8ea962 100644 --- a/js/src/jsonrpc/interfaces/ethcore.js +++ b/js/src/jsonrpc/interfaces/parity.js @@ -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: [ diff --git a/js/src/jsonrpc/interfaces/personal.js b/js/src/jsonrpc/interfaces/personal.js index 2a9ce7c19..eb7e5fc0f 100644 --- a/js/src/jsonrpc/interfaces/personal.js +++ b/js/src/jsonrpc/interfaces/personal.js @@ -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: [ diff --git a/js/src/jsonrpc/interfaces/signer.js b/js/src/jsonrpc/interfaces/signer.js new file mode 100644 index 000000000..f394dbb61 --- /dev/null +++ b/js/src/jsonrpc/interfaces/signer.js @@ -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 . + +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' + } + } +}; diff --git a/js/src/modals/AddAddress/addAddress.js b/js/src/modals/AddAddress/addAddress.js index ebcf78815..c8845aa13 100644 --- a/js/src/modals/AddAddress/addAddress.js +++ b/js/src/modals/AddAddress/addAddress.js @@ -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 diff --git a/js/src/modals/AddContract/addContract.js b/js/src/modals/AddContract/addContract.js index ad7345430..418378136 100644 --- a/js/src/modals/AddContract/addContract.js +++ b/js/src/modals/AddContract/addContract.js @@ -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(), diff --git a/js/src/modals/CreateAccount/NewAccount/newAccount.js b/js/src/modals/CreateAccount/NewAccount/newAccount.js index b05a6db75..2fde79ca6 100644 --- a/js/src/modals/CreateAccount/NewAccount/newAccount.js +++ b/js/src/modals/CreateAccount/NewAccount/newAccount.js @@ -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 = {}; diff --git a/js/src/modals/CreateAccount/NewGeth/newGeth.js b/js/src/modals/CreateAccount/NewGeth/newGeth.js index 8853a671b..4b6cc2c96 100644 --- a/js/src/modals/CreateAccount/NewGeth/newGeth.js +++ b/js/src/modals/CreateAccount/NewGeth/newGeth.js @@ -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]); diff --git a/js/src/modals/CreateAccount/createAccount.js b/js/src/modals/CreateAccount/createAccount.js index aacc91d5e..283e91531 100644 --- a/js/src/modals/CreateAccount/createAccount.js +++ b/js/src/modals/CreateAccount/createAccount.js @@ -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 })); diff --git a/js/src/modals/DeployContract/deployContract.js b/js/src/modals/DeployContract/deployContract.js index 8dd57ffd1..588d16f6a 100644 --- a/js/src/modals/DeployContract/deployContract.js +++ b/js/src/modals/DeployContract/deployContract.js @@ -213,8 +213,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(), diff --git a/js/src/modals/EditMeta/editMeta.js b/js/src/modals/EditMeta/editMeta.js index b2ba89d61..ad893aa17 100644 --- a/js/src/modals/EditMeta/editMeta.js +++ b/js/src/modals/EditMeta/editMeta.js @@ -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) => { diff --git a/js/src/modals/ExecuteContract/executeContract.js b/js/src/modals/ExecuteContract/executeContract.js index e0462982d..b45cf6875 100644 --- a/js/src/modals/ExecuteContract/executeContract.js +++ b/js/src/modals/ExecuteContract/executeContract.js @@ -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' }); diff --git a/js/src/modals/FirstRun/firstRun.js b/js/src/modals/FirstRun/firstRun.js index ea49e852e..3a676fc3b 100644 --- a/js/src/modals/FirstRun/firstRun.js +++ b/js/src/modals/FirstRun/firstRun.js @@ -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(); }) diff --git a/js/src/modals/PasswordManager/passwordManager.js b/js/src/modals/PasswordManager/passwordManager.js index 368664a71..aabf691ef 100644 --- a/js/src/modals/PasswordManager/passwordManager.js +++ b/js/src/modals/PasswordManager/passwordManager.js @@ -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(() => { diff --git a/js/src/modals/Transfer/transfer.js b/js/src/modals/Transfer/transfer.js index b505ad0ae..506e91930 100644 --- a/js/src/modals/Transfer/transfer.js +++ b/js/src/modals/Transfer/transfer.js @@ -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]) => { diff --git a/js/src/redux/providers/balances.js b/js/src/redux/providers/balances.js index fa60e4310..b80fad28f 100644 --- a/js/src/redux/providers/balances.js +++ b/js/src/redux/providers/balances.js @@ -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); diff --git a/js/src/redux/providers/personal.js b/js/src/redux/providers/personal.js index e75b4082b..fd67ab5f7 100644 --- a/js/src/redux/providers/personal.js +++ b/js/src/redux/providers/personal.js @@ -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; } diff --git a/js/src/redux/providers/signer.js b/js/src/redux/providers/signer.js index 92f80d51e..5ece371c2 100644 --- a/js/src/redux/providers/signer.js +++ b/js/src/redux/providers/signer.js @@ -14,22 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -// 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 . - 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; } diff --git a/js/src/redux/providers/signerMiddleware.js b/js/src/redux/providers/signerMiddleware.js index 53144e454..6d09eeb4e 100644 --- a/js/src/redux/providers/signerMiddleware.js +++ b/js/src/redux/providers/signerMiddleware.js @@ -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 })); diff --git a/js/src/redux/providers/status.js b/js/src/redux/providers/status.js index 21712f2a9..0e2bf6866 100644 --- a/js/src/redux/providers/status.js +++ b/js/src/redux/providers/status.js @@ -31,8 +31,8 @@ export default class Status { } _fetchEnode () { - this._api - .ethcore.enode() + this._api.parity + .enode() .then((enode) => { this._store.dispatch(statusCollection({ enode })); }) @@ -101,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() ]) @@ -153,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({ diff --git a/js/src/secureApi.js b/js/src/secureApi.js index d577e7185..2f03d62e9 100644 --- a/js/src/secureApi.js +++ b/js/src/secureApi.js @@ -62,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); @@ -96,8 +96,8 @@ export default class SecureApi extends Api { Promise .all([ - this.ethcore.dappsPort(), - this.ethcore.signerPort() + this.parity.dappsPort(), + this.parity.signerPort() ]) .then(([dappsPort, signerPort]) => { this._dappsPort = dappsPort.toNumber(); diff --git a/js/src/views/Account/Header/header.js b/js/src/views/Account/Header/header.js index 2e7d5ae77..d4b01cf56 100644 --- a/js/src/views/Account/Header/header.js +++ b/js/src/views/Account/Header/header.js @@ -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); diff --git a/js/src/views/Address/Delete/delete.js b/js/src/views/Address/Delete/delete.js index 66e6edb95..8aeaf48e2 100644 --- a/js/src/views/Address/Delete/delete.js +++ b/js/src/views/Address/Delete/delete.js @@ -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); diff --git a/js/src/views/Application/application.js b/js/src/views/Application/application.js index 6b38f90d8..d49aa5d90 100644 --- a/js/src/views/Application/application.js +++ b/js/src/views/Application/application.js @@ -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 diff --git a/js/src/views/Dapp/dapp.js b/js/src/views/Dapp/dapp.js index b5d396735..7f5f36d1d 100644 --- a/js/src/views/Dapp/dapp.js +++ b/js/src/views/Dapp/dapp.js @@ -16,6 +16,9 @@ import React, { Component, PropTypes } from 'react'; +import Contracts from '../../contracts'; +import { fetchAvailable } from '../Dapps/registry'; + import styles from './dapp.css'; export default class Dapp extends Component { @@ -27,16 +30,39 @@ export default class Dapp extends Component { params: PropTypes.object }; + state = { + app: null + } + + componentWillMount () { + this.lookup(); + } + render () { - const { name, type } = this.props.params; + const { app } = this.state; const { dappsUrl } = this.context.api; - let src = `${dappsUrl}/${name}/`; - if (type === 'builtin') { - const dapphost = process.env.NODE_ENV === 'production' - ? `${dappsUrl}/ui` - : ''; - src = `${dapphost}/${name}.html`; + 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 ( @@ -50,4 +76,30 @@ export default class Dapp extends Component { ); } + + 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 }); + }); + } } diff --git a/js/src/views/Dapps/Summary/summary.js b/js/src/views/Dapps/Summary/summary.js index b4d2bb4cb..1140bb7b9 100644 --- a/js/src/views/Dapps/Summary/summary.js +++ b/js/src/views/Dapps/Summary/summary.js @@ -39,16 +39,7 @@ export default class Summary extends Component { return null; } - let type = 'builtin'; - if (app.network) { - type = 'network'; - } else if (app.local) { - type = 'local'; - } - - const url = `/app/${type}/${app.url || app.contentHash || app.id}`; let image =
 
; - if (app.image) { image = ; } else if (app.iconUrl) { @@ -61,7 +52,7 @@ export default class Summary extends Component {
{ app.name } } + title={ { app.name } } byline={ app.description } />
{ app.author }, v{ app.version }
{ this.props.children } diff --git a/js/src/views/Dapps/registry.js b/js/src/views/Dapps/registry.js index 8975f2091..5502bd3ff 100644 --- a/js/src/views/Dapps/registry.js +++ b/js/src/views/Dapps/registry.js @@ -55,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 ', - version: '1.0.0' + version: '1.0.0', + secure: true } ]; @@ -81,13 +82,6 @@ function getHost (api) { } 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); - // }); return fetch(`${getHost(api)}/api/apps`) .then((response) => { return response.ok @@ -102,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)) { @@ -115,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); diff --git a/js/src/views/Settings/Parity/parity.js b/js/src/views/Settings/Parity/parity.js index 6a3ba631f..abec8cc8a 100644 --- a/js/src/views/Settings/Parity/parity.js +++ b/js/src/views/Settings/Parity/parity.js @@ -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 }); diff --git a/js/src/views/Signer/components/SignRequest/SignRequest.js b/js/src/views/Signer/components/SignRequest/SignRequest.js index 25b3dd77d..395bc2c7f 100644 --- a/js/src/views/Signer/components/SignRequest/SignRequest.js +++ b/js/src/views/Signer/components/SignRequest/SignRequest.js @@ -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 }); }) diff --git a/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js b/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js index b781adb6d..08ed1f7ed 100644 --- a/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js +++ b/js/src/views/Signer/components/TransactionFinished/TransactionFinished.js @@ -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 }); }) diff --git a/js/src/views/Signer/components/TransactionPending/TransactionPending.js b/js/src/views/Signer/components/TransactionPending/TransactionPending.js index 3ca078b83..77d02d0b1 100644 --- a/js/src/views/Signer/components/TransactionPending/TransactionPending.js +++ b/js/src/views/Signer/components/TransactionPending/TransactionPending.js @@ -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 }); }) diff --git a/js/src/views/Status/components/MiningSettings/MiningSettings.js b/js/src/views/Status/components/MiningSettings/MiningSettings.js index 086d54be1..163c103f5 100644 --- a/js/src/views/Status/components/MiningSettings/MiningSettings.js +++ b/js/src/views/Status/components/MiningSettings/MiningSettings.js @@ -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)); }; } diff --git a/parity/cli/config.full.toml b/parity/cli/config.full.toml index 520adef4b..dcba8dbee 100644 --- a/parity/cli/config.full.toml +++ b/parity/cli/config.full.toml @@ -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 diff --git a/parity/cli/mod.rs b/parity/cli/mod.rs index ad9e8dd8b..12536e444 100644 --- a/parity/cli/mod.rs +++ b/parity/cli/mod.rs @@ -143,7 +143,7 @@ usage! { or |c: &Config| otry!(c.rpc).interface.clone(), flag_jsonrpc_cors: Option = 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, diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index b8734f7c2..8f453d874 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -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. diff --git a/parity/configuration.rs b/parity/configuration.rs index b71404339..0617e76f3 100644 --- a/parity/configuration.rs +++ b/parity/configuration.rs @@ -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> { @@ -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) diff --git a/parity/rpc_apis.rs b/parity/rpc_apis.rs index d725b9b08..9ffd8e0dd 100644 --- a/parity/rpc_apis.rs +++ b/parity/rpc_apis.rs @@ -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 { 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 { impl ApiSet { pub fn list_apis(&self) -> HashSet { + 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(server: T, deps: Arc, apis: ApiSet) -> T { use ethcore_rpc::v1::*; @@ -183,39 +206,39 @@ pub fn setup_rpc(server: T, deps: Arc, 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::().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); } } diff --git a/rpc/src/v1/impls/mod.rs b/rpc/src/v1/impls/mod.rs index c108f0b6b..e4083ca95 100644 --- a/rpc/src/v1/impls/mod.rs +++ b/rpc/src/v1/impls/mod.rs @@ -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; diff --git a/rpc/src/v1/impls/ethcore.rs b/rpc/src/v1/impls/parity.rs similarity index 74% rename from rpc/src/v1/impls/ethcore.rs rename to rpc/src/v1/impls/parity.rs index 84d159f80..b9c19f667 100644 --- a/rpc/src/v1/impls/ethcore.rs +++ b/rpc/src/v1/impls/parity.rs @@ -14,16 +14,15 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! 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 where +/// Parity implementation. +pub struct ParityClient where C: MiningBlockChainClient, M: MinerService, S: SyncProvider, - F: Fetch { - +{ client: Weak, miner: Weak, sync: Weak, net: Weak, + accounts: Weak, logger: Arc, settings: Arc, signer: Option>, - fetch: Mutex, dapps_port: Option, } -impl EthcoreClient where +impl ParityClient where C: MiningBlockChainClient, M: MinerService, - S: SyncProvider, { - /// Creates new `EthcoreClient` with default `Fetch`. + S: SyncProvider, +{ + /// Creates new `ParityClient`. pub fn new( client: &Arc, miner: &Arc, sync: &Arc, net: &Arc, + store: &Arc, logger: Arc, settings: Arc, signer: Option>, dapps_port: Option, ) -> Self { - Self::with_fetch(client, miner, sync, net, logger, settings, signer, dapps_port) - } -} - -impl EthcoreClient where - C: MiningBlockChainClient, - M: MinerService, - S: SyncProvider, - F: Fetch, { - - /// Creates new `EthcoreClient` with customizable `Fetch`. - pub fn with_fetch( - client: &Arc, - miner: &Arc, - sync: &Arc, - net: &Arc, - logger: Arc, - settings: Arc, - signer: Option>, - dapps_port: Option, - ) -> 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 EthcoreClient where } } -impl Ethcore for EthcoreClient where +impl Parity for ParityClient where M: MinerService + 'static, C: MiningBlockChainClient + 'static, - S: SyncProvider + 'static, - F: Fetch + 'static { + S: SyncProvider + 'static { fn transactions_limit(&self) -> Result { try!(self.active()); @@ -278,48 +256,6 @@ impl Ethcore for EthcoreClient where Ok(take_weak!(self.miner).all_transactions().into_iter().map(Into::into).collect::>()) } - fn hash_content(&self, ready: Ready, 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 = 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 { try!(self.active()); @@ -361,4 +297,22 @@ impl Ethcore for EthcoreClient where fn enode(&self) -> Result { take_weak!(self.sync).enode().ok_or_else(errors::network_disabled) } + + fn accounts(&self) -> Result>, 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()) + } } diff --git a/rpc/src/v1/impls/personal_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs similarity index 68% rename from rpc/src/v1/impls/personal_accounts.rs rename to rpc/src/v1/impls/parity_accounts.rs index 56c92fc64..2644c59e3 100644 --- a/rpc/src/v1/impls/personal_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -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 where C: MiningBlockChainClient, M: MinerService { +pub struct ParityAccountsClient where C: MiningBlockChainClient { accounts: Weak, client: Weak, - miner: Weak, - allow_perm_unlock: bool, } -impl PersonalAccountsClient where C: MiningBlockChainClient, M: MinerService { +impl ParityAccountsClient where C: MiningBlockChainClient { /// Creates new PersonalClient - pub fn new(store: &Arc, client: &Arc, miner: &Arc, allow_perm_unlock: bool) -> Self { - PersonalAccountsClient { + pub fn new(store: &Arc, client: &Arc) -> 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 PersonalAccountsClient where C: MiningBlockChainClient, M: Mine } } -impl PersonalAccounts for PersonalAccountsClient where C: MiningBlockChainClient, M: MinerService { - - fn new_account(&self, pass: String) -> Result { +impl ParityAccounts for ParityAccountsClient where C: MiningBlockChainClient { + fn accounts_info(&self) -> Result, 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 { @@ -92,24 +99,6 @@ impl PersonalAccounts for PersonalAccountsClient w .map_err(|e| errors::account("Could not create account.", e)) } - fn unlock_account(&self, account: RpcH160, account_pass: String, duration: Option) -> Result { - 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 { try!(self.active()); let account: Address = account.into(); @@ -128,18 +117,6 @@ impl PersonalAccounts for PersonalAccountsClient w .map_err(|e| errors::account("Could not fetch account info.", e)) } - fn sign_and_send_transaction(&self, request: TransactionRequest, password: String) -> Result { - 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 { try!(self.active()); let store = take_weak!(self.accounts); @@ -162,6 +139,10 @@ impl PersonalAccounts for PersonalAccountsClient w Ok(true) } + fn set_account_visibility(&self, _address: RpcH160, _dapp: RpcH256, _visible: bool) -> Result { + Ok(false) + } + fn import_geth_accounts(&self, addresses: Vec) -> Result, Error> { let store = take_weak!(self.accounts); diff --git a/rpc/src/v1/impls/ethcore_set.rs b/rpc/src/v1/impls/parity_set.rs similarity index 62% rename from rpc/src/v1/impls/ethcore_set.rs rename to rpc/src/v1/impls/parity_set.rs index 8889ffa44..47634d518 100644 --- a/rpc/src/v1/impls/ethcore_set.rs +++ b/rpc/src/v1/impls/parity_set.rs @@ -14,36 +14,57 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -/// 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 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 where C: MiningBlockChainClient, - M: MinerService + M: MinerService, + F: Fetch, { client: Weak, miner: Weak, net: Weak, + fetch: Mutex, } -impl EthcoreSetClient where +impl ParitySetClient where C: MiningBlockChainClient, - M: MinerService { - /// Creates new `EthcoreSetClient`. + M: MinerService +{ + /// Creates new `ParitySetClient` with default `FetchClient`. pub fn new(client: &Arc, miner: &Arc, net: &Arc) -> Self { - EthcoreSetClient { + Self::with_fetch(client, miner, net) + } +} + +impl ParitySetClient where + C: MiningBlockChainClient, + M: MinerService, + F: Fetch, +{ + /// Creates new `ParitySetClient` with default `FetchClient`. + pub fn with_fetch(client: &Arc, miner: &Arc, net: &Arc) -> Self { + ParitySetClient { client: Arc::downgrade(client), miner: Arc::downgrade(miner), net: Arc::downgrade(net), + fetch: Mutex::new(F::default()), } } @@ -54,9 +75,11 @@ impl EthcoreSetClient where } } -impl EthcoreSet for EthcoreSetClient where +impl ParitySet for ParitySetClient where C: MiningBlockChainClient + 'static, - M: MinerService + 'static { + M: MinerService + 'static, + F: Fetch + 'static, +{ fn set_min_gas_price(&self, gas_price: U256) -> Result { try!(self.active()); @@ -159,4 +182,46 @@ impl EthcoreSet for EthcoreSetClient where }); Ok(true) } + + fn hash_content(&self, ready: Ready, 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 = 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" + ); + } + } + } + } } diff --git a/rpc/src/v1/impls/personal.rs b/rpc/src/v1/impls/personal.rs index bace56db1..ffb20610c 100644 --- a/rpc/src/v1/impls/personal.rs +++ b/rpc/src/v1/impls/personal.rs @@ -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 where C: MiningBlockChainClient { +pub struct PersonalClient where C: MiningBlockChainClient, M: MinerService { accounts: Weak, client: Weak, + miner: Weak, + allow_perm_unlock: bool, } -impl PersonalClient where C: MiningBlockChainClient { +impl PersonalClient where C: MiningBlockChainClient, M: MinerService { /// Creates new PersonalClient - pub fn new(store: &Arc, client: &Arc) -> Self { + pub fn new(store: &Arc, client: &Arc, miner: &Arc, 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 PersonalClient where C: MiningBlockChainClient { } } -impl Personal for PersonalClient where C: MiningBlockChainClient { - +impl Personal for PersonalClient where C: MiningBlockChainClient, M: MinerService { fn accounts(&self) -> Result, Error> { try!(self.active()); @@ -56,23 +63,42 @@ impl Personal for PersonalClient where C: MiningBlockChainClient Ok(accounts.into_iter().map(Into::into).collect::>()) } - fn accounts_info(&self) -> Result, Error> { + fn new_account(&self, pass: String) -> Result { 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) -> Result { + 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 { + try!(self.active()); + + sign_and_dispatch( + &*take_weak!(self.client), + &*take_weak!(self.miner), + &*take_weak!(self.accounts), + request.into(), + Some(password) + ) } } diff --git a/rpc/src/v1/impls/personal_signer.rs b/rpc/src/v1/impls/signer.rs similarity index 94% rename from rpc/src/v1/impls/personal_signer.rs rename to rpc/src/v1/impls/signer.rs index 95db21e9f..61453e02b 100644 --- a/rpc/src/v1/impls/personal_signer.rs +++ b/rpc/src/v1/impls/signer.rs @@ -14,14 +14,14 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! 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 SignerClient where C: MiningBlockChainClient, } } -impl PersonalSigner for SignerClient where C: MiningBlockChainClient, M: MinerService { +impl Signer for SignerClient where C: MiningBlockChainClient, M: MinerService { fn requests_to_confirm(&self) -> Result, Error> { try!(self.active()); diff --git a/rpc/src/v1/impls/eth_signing.rs b/rpc/src/v1/impls/signing.rs similarity index 72% rename from rpc/src/v1/impls/eth_signing.rs rename to rpc/src/v1/impls/signing.rs index dd71af6a5..f54847757 100644 --- a/rpc/src/v1/impls/eth_signing.rs +++ b/rpc/src/v1/impls/signing.rs @@ -14,43 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! 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(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 where C: MiningBlockChainClient, M: MinerService { - signer: Weak, - accounts: Weak, - client: Weak, - miner: Weak, - - pending: Mutex>, -} - const MAX_PENDING_DURATION: u64 = 60 * 60; pub enum DispatchResult { @@ -58,10 +37,23 @@ pub enum DispatchResult { Value(Value), } -impl EthSigningQueueClient where C: MiningBlockChainClient, M: MinerService { +/// Implementation of functions that require signing when no trusted signer is used. +pub struct SigningQueueClient where C: MiningBlockChainClient, M: MinerService { + signer: Weak, + accounts: Weak, + client: Weak, + miner: Weak, + + pending: Mutex>, +} + +impl SigningQueueClient where + C: MiningBlockChainClient, + M: MinerService, +{ /// Creates a new signing queue client given shared signing queue. pub fn new(signer: &Arc, client: &Arc, miner: &Arc, accounts: &Arc) -> Self { - EthSigningQueueClient { + SigningQueueClient { signer: Arc::downgrade(signer), accounts: Arc::downgrade(accounts), client: Arc::downgrade(client), @@ -132,10 +124,10 @@ impl EthSigningQueueClient where C: MiningBlockChainClient, M: Miner } } -impl EthSigning for EthSigningQueueClient - where C: MiningBlockChainClient + 'static, M: MinerService + 'static +impl ParitySigning for SigningQueueClient where + C: MiningBlockChainClient, + M: MinerService, { - fn post_sign(&self, params: Params) -> Result { try!(self.active()); self.dispatch_sign(params).map(|result| match result { @@ -178,16 +170,6 @@ impl EthSigning for EthSigningQueueClient }) } - 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 EthSigning for EthSigningQueueClient } } -/// Implementation of functions that require signing when no trusted signer is used. -pub struct EthSigningUnsafeClient where +impl EthSigning for SigningQueueClient where C: MiningBlockChainClient, - M: MinerService { - client: Weak, - accounts: Weak, - miner: Weak, -} - -impl EthSigningUnsafeClient where - C: MiningBlockChainClient, - M: MinerService { - - /// Creates new EthClient. - pub fn new(client: &Arc, accounts: &Arc, miner: &Arc) - -> 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 EthSigning for EthSigningUnsafeClient 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 { - // We don't support this in non-signer mode. - Err(errors::signer_disabled()) - } - - fn post_transaction(&self, _: Params) -> Result { - // We don't support this in non-signer mode. - Err(errors::signer_disabled()) - } - - fn check_request(&self, _: Params) -> Result { - // 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(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), } } diff --git a/rpc/src/v1/impls/signing_unsafe.rs b/rpc/src/v1/impls/signing_unsafe.rs new file mode 100644 index 000000000..251ce9329 --- /dev/null +++ b/rpc/src/v1/impls/signing_unsafe.rs @@ -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 . + +//! 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 where + C: MiningBlockChainClient, + M: MinerService, +{ + accounts: Weak, + client: Weak, + miner: Weak, +} + +impl SigningUnsafeClient where + C: MiningBlockChainClient, + M: MinerService, +{ + + /// Creates new SigningUnsafeClient. + pub fn new(client: &Arc, accounts: &Arc, miner: &Arc) + -> 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 EthSigning for SigningUnsafeClient 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 ParitySigning for SigningUnsafeClient 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 { + // We don't support this in non-signer mode. + Err(errors::signer_disabled()) + } + + fn post_transaction(&self, _: Params) -> Result { + // We don't support this in non-signer mode. + Err(errors::signer_disabled()) + } + + fn check_request(&self, _: Params) -> Result { + // We don't support this in non-signer mode. + Err(errors::signer_disabled()) + } +} diff --git a/rpc/src/v1/mod.rs b/rpc/src/v1/mod.rs index 24560160c..966a87f26 100644 --- a/rpc/src/v1/mod.rs +++ b/rpc/src/v1/mod.rs @@ -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}; diff --git a/rpc/src/v1/tests/eth.rs b/rpc/src/v1/tests/eth.rs index a458a0570..2f5131f32 100644 --- a/rpc/src/v1/tests/eth.rs +++ b/rpc/src/v1/tests/eth.rs @@ -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 diff --git a/rpc/src/v1/tests/mocked/eth.rs b/rpc/src/v1/tests/mocked/eth.rs index d324715d6..9f654e7e0 100644 --- a/rpc/src/v1/tests/mocked/eth.rs +++ b/rpc/src/v1/tests/mocked/eth.rs @@ -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); diff --git a/rpc/src/v1/tests/mocked/mod.rs b/rpc/src/v1/tests/mocked/mod.rs index cc54555b7..a7d7156b4 100644 --- a/rpc/src/v1/tests/mocked/mod.rs +++ b/rpc/src/v1/tests/mocked/mod.rs @@ -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; diff --git a/rpc/src/v1/tests/mocked/ethcore.rs b/rpc/src/v1/tests/mocked/parity.rs similarity index 73% rename from rpc/src/v1/tests/mocked/ethcore.rs rename to rpc/src/v1/tests/mocked/parity.rs index a64f133bf..8baecbd90 100644 --- a/rpc/src/v1/tests/mocked/ethcore.rs +++ b/rpc/src/v1/tests/mocked/parity.rs @@ -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; +pub type TestParityClient = ParityClient; pub struct Dependencies { pub miner: Arc, @@ -37,6 +37,7 @@ pub struct Dependencies { pub logger: Arc, pub settings: Arc, pub network: Arc, + pub accounts: Arc, pub dapps_port: Option, } @@ -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>) -> TestEthcoreClient { - EthcoreClient::with_fetch( + pub fn client(&self, signer: Option>) -> 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 }"#; diff --git a/rpc/src/v1/tests/mocked/parity_accounts.rs b/rpc/src/v1/tests/mocked/parity_accounts.rs new file mode 100644 index 000000000..272c55f6d --- /dev/null +++ b/rpc/src/v1/tests/mocked/parity_accounts.rs @@ -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 . + +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, + io: IoHandler, + // these unused fields are necessary to keep the data alive + // as the handler has only weak pointers. + _client: Arc, +} + +fn blockchain_client() -> Arc { + let client = TestBlockChainClient::new(); + Arc::new(client) +} + +fn accounts_provider() -> Arc { + 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)); +} + diff --git a/rpc/src/v1/tests/mocked/ethcore_set.rs b/rpc/src/v1/tests/mocked/parity_set.rs similarity index 57% rename from rpc/src/v1/tests/mocked/ethcore_set.rs rename to rpc/src/v1/tests/mocked/parity_set.rs index e87d49b8c..3202374a7 100644 --- a/rpc/src/v1/tests/mocked/ethcore_set.rs +++ b/rpc/src/v1/tests/mocked/parity_set.rs @@ -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 { Arc::new(TestMinerService::default()) } @@ -38,19 +40,21 @@ fn network_service() -> Arc { Arc::new(TestManageNetwork) } -fn ethcore_set_client(client: &Arc, miner: &Arc, net: &Arc) -> EthcoreSetClient { - EthcoreSetClient::new(client, miner, &(net.clone() as Arc)) +pub type TestParitySetClient = ParitySetClient; + +fn parity_set_client(client: &Arc, miner: &Arc, net: &Arc) -> TestParitySetClient { + ParitySetClient::with_fetch(client, miner, &(net.clone() as Arc)) } #[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); -} \ No newline at end of file +} + +#[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())); +} + diff --git a/rpc/src/v1/tests/mocked/personal.rs b/rpc/src/v1/tests/mocked/personal.rs index 511f23415..6e2de1e2e 100644 --- a/rpc/src/v1/tests/mocked/personal.rs +++ b/rpc/src/v1/tests/mocked/personal.rs @@ -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(); diff --git a/rpc/src/v1/tests/mocked/personal_signer.rs b/rpc/src/v1/tests/mocked/signer.rs similarity index 91% rename from rpc/src/v1/tests/mocked/personal_signer.rs rename to rpc/src/v1/tests/mocked/signer.rs index ffcc47432..92e20676f 100644 --- a/rpc/src/v1/tests/mocked/personal_signer.rs +++ b/rpc/src/v1/tests/mocked/signer.rs @@ -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, accounts: Arc, io: IoHandler, @@ -48,7 +48,7 @@ fn miner_service() -> Arc { 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 }"#; diff --git a/rpc/src/v1/tests/mocked/eth_signing.rs b/rpc/src/v1/tests/mocked/signing.rs similarity index 90% rename from rpc/src/v1/tests/mocked/eth_signing.rs rename to rpc/src/v1/tests/mocked/signing.rs index 0f0125f87..fc460409c 100644 --- a/rpc/src/v1/tests/mocked/eth_signing.rs +++ b/rpc/src/v1/tests/mocked/signing.rs @@ -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, pub client: Arc, pub miner: Arc, @@ -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 diff --git a/rpc/src/v1/traits/eth_signing.rs b/rpc/src/v1/traits/eth_signing.rs index 1d6f6e501..80979a7db 100644 --- a/rpc/src/v1/traits/eth_signing.rs +++ b/rpc/src/v1/traits/eth_signing.rs @@ -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; - /// 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; - - /// 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; - - /// 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 { 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 } } diff --git a/rpc/src/v1/traits/mod.rs b/rpc/src/v1/traits/mod.rs index ea0834463..86b55b7c0 100644 --- a/rpc/src/v1/traits/mod.rs +++ b/rpc/src/v1/traits/mod.rs @@ -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; diff --git a/rpc/src/v1/traits/ethcore.rs b/rpc/src/v1/traits/parity.rs similarity index 74% rename from rpc/src/v1/traits/ethcore.rs rename to rpc/src/v1/traits/parity.rs index b7ef2d151..23cf50ed3 100644 --- a/rpc/src/v1/traits/ethcore.rs +++ b/rpc/src/v1/traits/parity.rs @@ -14,128 +14,129 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Ethcore-specific rpc interface. +//! Parity-specific rpc interface. use jsonrpc_core::Error; -use v1::helpers::auto_args::{Wrap, WrapAsync, Ready}; +use std::collections::BTreeMap; +use v1::helpers::auto_args::Wrap; use v1::types::{H160, H256, H512, U256, Bytes, Peers, Transaction, RpcSettings, Histogram}; build_rpc_trait! { - /// Ethcore-specific rpc interface. - pub trait Ethcore { + /// Parity-specific rpc interface. + pub trait Parity { /// Returns current transactions limit. - #[rpc(name = "ethcore_transactionsLimit")] + #[rpc(name = "parity_transactionsLimit")] fn transactions_limit(&self) -> Result; /// Returns mining extra data. - #[rpc(name = "ethcore_extraData")] + #[rpc(name = "parity_extraData")] fn extra_data(&self) -> Result; /// Returns mining gas floor target. - #[rpc(name = "ethcore_gasFloorTarget")] + #[rpc(name = "parity_gasFloorTarget")] fn gas_floor_target(&self) -> Result; /// Returns mining gas floor cap. - #[rpc(name = "ethcore_gasCeilTarget")] + #[rpc(name = "parity_gasCeilTarget")] fn gas_ceil_target(&self) -> Result; /// Returns minimal gas price for transaction to be included in queue. - #[rpc(name = "ethcore_minGasPrice")] + #[rpc(name = "parity_minGasPrice")] fn min_gas_price(&self) -> Result; /// Returns latest logs - #[rpc(name = "ethcore_devLogs")] + #[rpc(name = "parity_devLogs")] fn dev_logs(&self) -> Result, Error>; /// Returns logs levels - #[rpc(name = "ethcore_devLogsLevels")] + #[rpc(name = "parity_devLogsLevels")] fn dev_logs_levels(&self) -> Result; /// Returns chain name - #[rpc(name = "ethcore_netChain")] + #[rpc(name = "parity_netChain")] fn net_chain(&self) -> Result; /// Returns peers details - #[rpc(name = "ethcore_netPeers")] + #[rpc(name = "parity_netPeers")] fn net_peers(&self) -> Result; /// Returns network port - #[rpc(name = "ethcore_netPort")] + #[rpc(name = "parity_netPort")] fn net_port(&self) -> Result; /// Returns rpc settings - #[rpc(name = "ethcore_rpcSettings")] + #[rpc(name = "parity_rpcSettings")] fn rpc_settings(&self) -> Result; /// Returns node name - #[rpc(name = "ethcore_nodeName")] + #[rpc(name = "parity_nodeName")] fn node_name(&self) -> Result; /// Returns default extra data - #[rpc(name = "ethcore_defaultExtraData")] + #[rpc(name = "parity_defaultExtraData")] fn default_extra_data(&self) -> Result; /// Returns distribution of gas price in latest blocks. - #[rpc(name = "ethcore_gasPriceHistogram")] + #[rpc(name = "parity_gasPriceHistogram")] fn gas_price_histogram(&self) -> Result; /// Returns number of unsigned transactions waiting in the signer queue (if signer enabled) /// Returns error when signer is disabled - #[rpc(name = "ethcore_unsignedTransactionsCount")] + #[rpc(name = "parity_unsignedTransactionsCount")] fn unsigned_transactions_count(&self) -> Result; /// Returns a cryptographically random phrase sufficient for securely seeding a secret key. - #[rpc(name = "ethcore_generateSecretPhrase")] + #[rpc(name = "parity_generateSecretPhrase")] fn generate_secret_phrase(&self) -> Result; /// Returns whatever address would be derived from the given phrase if it were to seed a brainwallet. - #[rpc(name = "ethcore_phraseToAddress")] + #[rpc(name = "parity_phraseToAddress")] fn phrase_to_address(&self, String) -> Result; /// Returns the value of the registrar for this network. - #[rpc(name = "ethcore_registryAddress")] + #[rpc(name = "parity_registryAddress")] fn registry_address(&self) -> Result, Error>; /// Returns all addresses if Fat DB is enabled (`--fat-db`), or null if not. - #[rpc(name = "ethcore_listAccounts")] + #[rpc(name = "parity_listAccounts")] fn list_accounts(&self) -> Result>, Error>; /// Returns all storage keys of the given address (first parameter) if Fat DB is enabled (`--fat-db`), /// or null if not. - #[rpc(name = "ethcore_listStorageKeys")] + #[rpc(name = "parity_listStorageKeys")] fn list_storage_keys(&self, H160) -> Result>, Error>; /// Encrypt some data with a public key under ECIES. /// First parameter is the 512-byte destination public key, second is the message. - #[rpc(name = "ethcore_encryptMessage")] + #[rpc(name = "parity_encryptMessage")] fn encrypt_message(&self, H512, Bytes) -> Result; /// Returns all pending transactions from transaction queue. - #[rpc(name = "ethcore_pendingTransactions")] + #[rpc(name = "parity_pendingTransactions")] fn pending_transactions(&self) -> Result, Error>; - /// Hash a file content under given URL. - #[rpc(async, name = "ethcore_hashContent")] - fn hash_content(&self, Ready, String); - /// Returns current Trusted Signer port or an error if signer is disabled. - #[rpc(name = "ethcore_signerPort")] + #[rpc(name = "parity_signerPort")] fn signer_port(&self) -> Result; /// Returns current Dapps Server port or an error if dapps server is disabled. - #[rpc(name = "ethcore_dappsPort")] + #[rpc(name = "parity_dappsPort")] fn dapps_port(&self) -> Result; /// Returns next nonce for particular sender. Should include all transactions in the queue. - #[rpc(name = "ethcore_nextNonce")] + #[rpc(name = "parity_nextNonce")] fn next_nonce(&self, H160) -> Result; /// Get the mode. Results one of: "active", "passive", "dark", "offline". - #[rpc(name = "ethcore_mode")] + #[rpc(name = "parity_mode")] fn mode(&self) -> Result; /// Get the enode of this node. - #[rpc(name = "ethcore_enode")] + #[rpc(name = "parity_enode")] fn enode(&self) -> Result; + + /// Returns accounts information. + #[rpc(name = "parity_accounts")] + fn accounts(&self) -> Result>, Error>; } } diff --git a/rpc/src/v1/traits/parity_accounts.rs b/rpc/src/v1/traits/parity_accounts.rs new file mode 100644 index 000000000..0f62f59d1 --- /dev/null +++ b/rpc/src/v1/traits/parity_accounts.rs @@ -0,0 +1,77 @@ +// 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 . + +//! Parity Accounts-related rpc interface. +use std::collections::BTreeMap; +use jsonrpc_core::{Value, Error}; + +use v1::helpers::auto_args::Wrap; +use v1::types::{H160, H256}; + +build_rpc_trait! { + /// Personal Parity rpc interface. + pub trait ParityAccounts { + /// Returns accounts information. + #[rpc(name = "parity_accountsInfo")] + fn accounts_info(&self) -> Result, Error>; + + /// Creates new account from the given phrase using standard brainwallet mechanism. + /// Second parameter is password for the new account. + #[rpc(name = "parity_newAccountFromPhrase")] + fn new_account_from_phrase(&self, String, String) -> Result; + + /// Creates new account from the given JSON wallet. + /// Second parameter is password for the wallet and the new account. + #[rpc(name = "parity_newAccountFromWallet")] + fn new_account_from_wallet(&self, String, String) -> Result; + + /// Creates new account from the given raw secret. + /// Second parameter is password for the new account. + #[rpc(name = "parity_newAccountFromSecret")] + fn new_account_from_secret(&self, H256, String) -> Result; + + /// Returns true if given `password` would unlock given `account`. + /// Arguments: `account`, `password`. + #[rpc(name = "parity_testPassword")] + fn test_password(&self, H160, String) -> Result; + + /// Changes an account's password. + /// Arguments: `account`, `password`, `new_password`. + #[rpc(name = "parity_changePassword")] + fn change_password(&self, H160, String, String) -> Result; + + /// Set an account's name. + #[rpc(name = "parity_setAccountName")] + fn set_account_name(&self, H160, String) -> Result; + + /// Set an account's metadata string. + #[rpc(name = "parity_setAccountMeta")] + fn set_account_meta(&self, H160, String) -> Result; + + /// Returns accounts information. + #[rpc(name = "parity_setAccountVisiblity")] + fn set_account_visibility(&self, H160, H256, bool) -> Result; + + /// Imports a number of Geth accounts, with the list provided as the argument. + #[rpc(name = "parity_importGethAccounts")] + fn import_geth_accounts(&self, Vec) -> Result, Error>; + + /// Returns the accounts available for importing from Geth. + #[rpc(name = "parity_listGethAccounts")] + fn geth_accounts(&self) -> Result, Error>; + } +} + diff --git a/rpc/src/v1/traits/ethcore_set.rs b/rpc/src/v1/traits/parity_set.rs similarity index 70% rename from rpc/src/v1/traits/ethcore_set.rs rename to rpc/src/v1/traits/parity_set.rs index ad31a6e64..c83eff022 100644 --- a/rpc/src/v1/traits/ethcore_set.rs +++ b/rpc/src/v1/traits/parity_set.rs @@ -14,74 +14,78 @@ // You should have received a copy of the GNU General Public License // along with Parity. If not, see . -//! Ethcore-specific rpc interface for operations altering the settings. +//! Parity-specific rpc interface for operations altering the settings. use jsonrpc_core::Error; -use v1::helpers::auto_args::Wrap; -use v1::types::{Bytes, H160, U256}; +use v1::helpers::auto_args::{Wrap, WrapAsync, Ready}; +use v1::types::{Bytes, H160, H256, U256}; build_rpc_trait! { - /// Ethcore-specific rpc interface for operations altering the settings. - pub trait EthcoreSet { + /// Parity-specific rpc interface for operations altering the settings. + pub trait ParitySet { /// Sets new minimal gas price for mined blocks. - #[rpc(name = "ethcore_setMinGasPrice")] + #[rpc(name = "parity_setMinGasPrice")] fn set_min_gas_price(&self, U256) -> Result; /// Sets new gas floor target for mined blocks. - #[rpc(name = "ethcore_setGasFloorTarget")] + #[rpc(name = "parity_setGasFloorTarget")] fn set_gas_floor_target(&self, U256) -> Result; /// Sets new gas ceiling target for mined blocks. - #[rpc(name = "ethcore_setGasCeilTarget")] + #[rpc(name = "parity_setGasCeilTarget")] fn set_gas_ceil_target(&self, U256) -> Result; /// Sets new extra data for mined blocks. - #[rpc(name = "ethcore_setExtraData")] + #[rpc(name = "parity_setExtraData")] fn set_extra_data(&self, Bytes) -> Result; /// Sets new author for mined block. - #[rpc(name = "ethcore_setAuthor")] + #[rpc(name = "parity_setAuthor")] fn set_author(&self, H160) -> Result; /// Sets the limits for transaction queue. - #[rpc(name = "ethcore_setTransactionsLimit")] + #[rpc(name = "parity_setTransactionsLimit")] fn set_transactions_limit(&self, usize) -> Result; /// Sets the maximum amount of gas a single transaction may consume. - #[rpc(name = "ethcore_setMaxTransactionGas")] + #[rpc(name = "parity_setMaxTransactionGas")] fn set_tx_gas_limit(&self, U256) -> Result; /// Add a reserved peer. - #[rpc(name = "ethcore_addReservedPeer")] + #[rpc(name = "parity_addReservedPeer")] fn add_reserved_peer(&self, String) -> Result; /// Remove a reserved peer. - #[rpc(name = "ethcore_removeReservedPeer")] + #[rpc(name = "parity_removeReservedPeer")] fn remove_reserved_peer(&self, String) -> Result; /// Drop all non-reserved peers. - #[rpc(name = "ethcore_dropNonReservedPeers")] + #[rpc(name = "parity_dropNonReservedPeers")] fn drop_non_reserved_peers(&self) -> Result; /// Accept non-reserved peers (default behavior) - #[rpc(name = "ethcore_acceptNonReservedPeers")] + #[rpc(name = "parity_acceptNonReservedPeers")] fn accept_non_reserved_peers(&self) -> Result; /// Start the network. - /// + /// /// Deprecated. Use `set_mode("active")` instead. - #[rpc(name = "ethcore_startNetwork")] + #[rpc(name = "parity_startNetwork")] fn start_network(&self) -> Result; /// Stop the network. /// /// Deprecated. Use `set_mode("offline")` instead. - #[rpc(name = "ethcore_stopNetwork")] + #[rpc(name = "parity_stopNetwork")] fn stop_network(&self) -> Result; /// Set the mode. Argument must be one of: "active", "passive", "dark", "offline". - #[rpc(name = "ethcore_setMode")] + #[rpc(name = "parity_setMode")] fn set_mode(&self, String) -> Result; + + /// Hash a file content under given URL. + #[rpc(async, name = "parity_hashContent")] + fn hash_content(&self, Ready, String); } -} \ No newline at end of file +} diff --git a/rpc/src/v1/traits/parity_signing.rs b/rpc/src/v1/traits/parity_signing.rs new file mode 100644 index 000000000..1c2778b31 --- /dev/null +++ b/rpc/src/v1/traits/parity_signing.rs @@ -0,0 +1,52 @@ +// 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 . + +//! ParitySigning rpc interface. +use std::sync::Arc; +use jsonrpc_core::*; + +/// Signing methods implementation relying on unlocked accounts. +pub trait ParitySigning: Sized + Send + Sync + 'static { + /// Posts sign request asynchronously. + /// Will return a confirmation ID for later use with check_transaction. + fn post_sign(&self, _: Params) -> Result; + + /// Posts transaction asynchronously. + /// Will return a transaction ID for later use with check_transaction. + fn post_transaction(&self, _: Params) -> Result; + + /// 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; + + /// 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 { + let mut delegate = IoDelegate::new(Arc::new(self)); + delegate.add_method("parity_postSign", ParitySigning::post_sign); + delegate.add_method("parity_postTransaction", ParitySigning::post_transaction); + delegate.add_method("parity_checkRequest", ParitySigning::check_request); + delegate.add_async_method("parity_decryptMessage", ParitySigning::decrypt_message); + + delegate + } +} diff --git a/rpc/src/v1/traits/personal.rs b/rpc/src/v1/traits/personal.rs index fe5c3cb02..42e61839e 100644 --- a/rpc/src/v1/traits/personal.rs +++ b/rpc/src/v1/traits/personal.rs @@ -15,11 +15,10 @@ // along with Parity. If not, see . //! Personal rpc interface. -use std::collections::BTreeMap; -use jsonrpc_core::{Value, Error}; +use jsonrpc_core::Error; use v1::helpers::auto_args::Wrap; -use v1::types::{H160, H256, U256, TransactionRequest, TransactionModification, ConfirmationRequest}; +use v1::types::{H160, H256, TransactionRequest}; build_rpc_trait! { /// Personal rpc interface. Safe (read-only) functions. @@ -28,91 +27,17 @@ build_rpc_trait! { #[rpc(name = "personal_listAccounts")] fn accounts(&self) -> Result, Error>; - /// Returns accounts information. - #[rpc(name = "personal_accountsInfo")] - fn accounts_info(&self) -> Result, Error>; - } -} - -build_rpc_trait! { - /// Personal rpc methods altering stored accounts or their settings. - pub trait PersonalAccounts { - /// Creates new account (it becomes new current unlocked account) /// Param is the password for the account. #[rpc(name = "personal_newAccount")] fn new_account(&self, String) -> Result; - /// Creates new account from the given phrase using standard brainwallet mechanism. - /// Second parameter is password for the new account. - #[rpc(name = "personal_newAccountFromPhrase")] - fn new_account_from_phrase(&self, String, String) -> Result; - - /// Creates new account from the given JSON wallet. - /// Second parameter is password for the wallet and the new account. - #[rpc(name = "personal_newAccountFromWallet")] - fn new_account_from_wallet(&self, String, String) -> Result; - - /// Creates new account from the given raw secret. - /// Second parameter is password for the new account. - #[rpc(name = "personal_newAccountFromSecret")] - fn new_account_from_secret(&self, H256, String) -> Result; - /// Unlocks specified account for use (can only be one unlocked account at one moment) #[rpc(name = "personal_unlockAccount")] fn unlock_account(&self, H160, String, Option) -> Result; - /// Returns true if given `password` would unlock given `account`. - /// Arguments: `account`, `password`. - #[rpc(name = "personal_testPassword")] - fn test_password(&self, H160, String) -> Result; - - /// Changes an account's password. - /// Arguments: `account`, `password`, `new_password`. - #[rpc(name = "personal_changePassword")] - fn change_password(&self, H160, String, String) -> Result; - /// Sends transaction and signs it in single call. The account is not unlocked in such case. #[rpc(name = "personal_signAndSendTransaction")] fn sign_and_send_transaction(&self, TransactionRequest, String) -> Result; - - /// Set an account's name. - #[rpc(name = "personal_setAccountName")] - fn set_account_name(&self, H160, String) -> Result; - - /// Set an account's metadata string. - #[rpc(name = "personal_setAccountMeta")] - fn set_account_meta(&self, H160, String) -> Result; - - /// Imports a number of Geth accounts, with the list provided as the argument. - #[rpc(name = "personal_importGethAccounts")] - fn import_geth_accounts(&self, Vec) -> Result, Error>; - - /// Returns the accounts available for importing from Geth. - #[rpc(name = "personal_listGethAccounts")] - fn geth_accounts(&self) -> Result, Error>; } } - -build_rpc_trait! { - /// Personal extension for confirmations rpc interface. - pub trait PersonalSigner { - - /// Returns a list of items to confirm. - #[rpc(name = "personal_requestsToConfirm")] - fn requests_to_confirm(&self) -> Result, Error>; - - /// Confirm specific request. - #[rpc(name = "personal_confirmRequest")] - fn confirm_request(&self, U256, TransactionModification, String) -> Result; - - /// Reject the confirmation request. - #[rpc(name = "personal_rejectRequest")] - fn reject_request(&self, U256) -> Result; - - /// Generates new authorization token. - #[rpc(name = "personal_generateAuthorizationToken")] - fn generate_token(&self) -> Result; - } -} - diff --git a/rpc/src/v1/traits/signer.rs b/rpc/src/v1/traits/signer.rs new file mode 100644 index 000000000..d80c6f1a6 --- /dev/null +++ b/rpc/src/v1/traits/signer.rs @@ -0,0 +1,44 @@ +// 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 . + +//! Parity Signer-related rpc interface. +use jsonrpc_core::{Value, Error}; + +use v1::helpers::auto_args::Wrap; +use v1::types::{U256, TransactionModification, ConfirmationRequest}; + + +build_rpc_trait! { + /// Signer extension for confirmations rpc interface. + pub trait Signer { + + /// Returns a list of items to confirm. + #[rpc(name = "signer_requestsToConfirm")] + fn requests_to_confirm(&self) -> Result, Error>; + + /// Confirm specific request. + #[rpc(name = "signer_confirmRequest")] + fn confirm_request(&self, U256, TransactionModification, String) -> Result; + + /// Reject the confirmation request. + #[rpc(name = "signer_rejectRequest")] + fn reject_request(&self, U256) -> Result; + + /// Generates new authorization token. + #[rpc(name = "signer_generateAuthorizationToken")] + fn generate_token(&self) -> Result; + } +}