├── .babelrc ├── .coveralls.yml ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── .istanbul.yml ├── .npmignore ├── .travis.yml ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── scripts └── travis.sh ├── src ├── api.js ├── api.spec.js ├── contract │ ├── contract.js │ ├── contract.spec.js │ └── index.js ├── format │ ├── input.js │ ├── input.spec.js │ ├── output.js │ └── output.spec.js ├── index.js ├── library.js ├── polyfill.js ├── provider │ ├── current.js │ ├── current.spec.js │ ├── http.js │ ├── http.spec.js │ ├── index.js │ ├── postMessage.js │ ├── postMessage.spec.js │ ├── promise.js │ ├── sendAsync.js │ ├── sendAsync.spec.js │ ├── ws.js │ └── ws.spec.js ├── pubsub │ ├── eth │ │ ├── eth.js │ │ └── index.js │ ├── index.js │ ├── net │ │ ├── index.js │ │ └── net.js │ ├── parity │ │ ├── index.js │ │ └── parity.js │ ├── pubsub.js │ ├── pubsub.spec.js │ ├── pubsubBase.js │ └── signer │ │ ├── index.js │ │ └── signer.js ├── rpc │ ├── db │ │ ├── db.js │ │ ├── db.spec.js │ │ └── index.js │ ├── eth │ │ ├── eth.e2e.js │ │ ├── eth.js │ │ ├── eth.spec.js │ │ └── index.js │ ├── index.js │ ├── net │ │ ├── index.js │ │ ├── net.e2e.js │ │ ├── net.js │ │ └── net.spec.js │ ├── parity │ │ ├── index.js │ │ ├── parity.e2e.js │ │ ├── parity.js │ │ └── parity.spec.js │ ├── personal │ │ ├── index.js │ │ ├── personal.e2e.js │ │ ├── personal.js │ │ └── personal.spec.js │ ├── shell │ │ ├── index.js │ │ └── shell.js │ ├── shh │ │ ├── index.js │ │ └── shh.js │ ├── signer │ │ ├── index.js │ │ └── signer.js │ ├── trace │ │ ├── index.js │ │ ├── trace.e2e.js │ │ ├── trace.js │ │ └── trace.spec.js │ └── web3 │ │ ├── index.js │ │ ├── web3.e2e.js │ │ ├── web3.js │ │ └── web3.spec.js ├── subscriptions │ ├── eth.js │ ├── eth.spec.js │ ├── index.js │ ├── logging.js │ ├── logging.spec.js │ ├── manager.js │ ├── manager.spec.js │ ├── personal.js │ ├── personal.spec.js │ └── signer.js ├── transport │ ├── error.js │ ├── error.spec.js │ ├── http │ │ ├── http.e2e.js │ │ ├── http.js │ │ ├── http.spec.js │ │ └── index.js │ ├── index.js │ ├── jsonRpcBase.js │ ├── jsonRpcBase.spec.js │ ├── jsonRpcEncoder.js │ ├── jsonRpcEncoder.spec.js │ ├── middleware.js │ ├── middleware.spec.js │ └── ws │ │ ├── index.js │ │ ├── polyfill.js │ │ ├── ws.e2e.js │ │ ├── ws.js │ │ └── ws.spec.js └── util │ ├── address.js │ ├── decode.js │ ├── decode.spec.js │ ├── encode.js │ ├── encode.spec.js │ ├── format.js │ ├── format.spec.js │ ├── identity.js │ ├── index.js │ ├── sha3.js │ ├── sha3.spec.js │ ├── types.js │ ├── types.spec.js │ ├── wei.js │ └── wei.spec.js └── test ├── mocha.config.js ├── mocha.opts ├── mockRpc.js └── types.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env", 4 | "stage-0" 5 | ], 6 | "plugins": [ 7 | "transform-class-properties", 8 | "transform-object-rest-spread" 9 | ], 10 | "retainLines": true 11 | } 12 | -------------------------------------------------------------------------------- /.coveralls.yml: -------------------------------------------------------------------------------- 1 | service_name: travis-pro 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style=space 4 | indent_size=2 5 | tab_width=2 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=120 10 | insert_final_newline=true 11 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["semistandard"], 3 | "env": { 4 | "browser": true, 5 | "mocha": true, 6 | "node": true 7 | }, 8 | "globals": { 9 | "expect": true, 10 | "FileReader": true 11 | }, 12 | "rules": { 13 | "curly": ["error", "all"], 14 | "newline-after-var": ["error", "always"], 15 | "no-alert": "error", 16 | "no-debugger": "error", 17 | "no-duplicate-imports": ["error", { 18 | "includeExports": true 19 | }], 20 | "object-curly-spacing": ["error", "always"], 21 | "object-property-newline": 0, 22 | "one-var-declaration-per-line": ["error", "always"], 23 | "padded-blocks": ["error", { 24 | "blocks": "never", 25 | "classes": "never", 26 | "switches": "never" 27 | }] 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | lib 3 | node_modules 4 | -------------------------------------------------------------------------------- /.istanbul.yml: -------------------------------------------------------------------------------- 1 | instrumentation: 2 | root: src 3 | extensions: 4 | - .js 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | coverage 2 | scripts 3 | src 4 | test 5 | .babelrc 6 | .coveralls.yml 7 | .editorconfig 8 | .eslintrc.json 9 | .gitignore 10 | .istanbul.yml 11 | .travis.yml 12 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "8" 4 | script: ./scripts/travis.sh 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @parity/api 2 | 3 | Parity.js is a thin, fast, Promise-based wrapper around the Ethereum APIs. 4 | 5 | [![Build Status](https://travis-ci.org/paritytech/js-api.svg?branch=master)](https://travis-ci.org/paritytech/js-api) 6 | [![Coverage Status](https://coveralls.io/repos/github/paritytech/js-api/badge.svg?branch=master)](https://coveralls.io/github/paritytech/js-api?branch=master) 7 | [![Dependency Status](https://david-dm.org/paritytech/js-api.svg)](https://david-dm.org/paritytech/js-api) 8 | [![devDependency Status](https://david-dm.org/paritytech/js-api/dev-status.svg)](https://david-dm.org/paritytech/js-api#info=devDependencies) 9 | 10 | ## installation 11 | 12 | Install the package with `npm install --save @parity/api` 13 | 14 | ## usage 15 | 16 | ### initialisation 17 | 18 | ```javascript 19 | // import the actual Api class 20 | import Api from '@parity/api'; 21 | 22 | // do the setup 23 | const provider = new Api.Provider.Http('http://localhost:8545'); 24 | const api = new Api(provider); 25 | ``` 26 | 27 | ### making calls 28 | 29 | perform a call 30 | 31 | ```javascript 32 | api.eth 33 | .coinbase() 34 | .then((coinbase) => { 35 | console.log(`The coinbase is ${coinbase}`); 36 | }); 37 | ``` 38 | 39 | multiple promises 40 | 41 | ```javascript 42 | Promise 43 | .all([ 44 | api.eth.coinbase(), 45 | api.net.listening() 46 | ]) 47 | .then(([coinbase, listening]) => { 48 | // do stuff here 49 | }); 50 | ``` 51 | 52 | chaining promises 53 | 54 | ```javascript 55 | api.eth 56 | .newFilter({...}) 57 | .then((filterId) => api.eth.getFilterChanges(filterId)) 58 | .then((changes) => { 59 | console.log(changes); 60 | }); 61 | ``` 62 | 63 | ### contracts 64 | 65 | attach contract 66 | 67 | ```javascript 68 | const abi = [{ name: 'callMe', inputs: [{ type: 'bool', ...}, { type: 'string', ...}]}, ...abi...]; 69 | const address = '0x123456...9abc'; 70 | const contract = api.newContract(abi, address); 71 | ``` 72 | 73 | find & call a function 74 | 75 | ```javascript 76 | contract.instance 77 | .callMe 78 | .call({ gas: 21000 }, [true, 'someString']) // or estimateGas or postTransaction 79 | .then((result) => { 80 | console.log(`the result was ${result}`); 81 | }); 82 | ``` 83 | 84 | ## apis 85 | 86 | APIs implement the calls as exposed in the [Ethcore JSON Ethereum RPC](https://github.com/paritytech/js-api) definitions. Mapping follows the naming conventions of the originals, i.e. `eth_call` becomes `eth.call`, `personal_accounts` becomes `personal.accounts`, etc. 87 | 88 | ## public node 89 | 90 | For operation within a public node, the following peerDependencies needs to be added (this functionality will be moved shortly) - 91 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@parity/api", 3 | "description": "The Parity Promise-based API library for interfacing with Ethereum over RPC", 4 | "version": "2.1.16", 5 | "main": "lib/index.js", 6 | "author": "Parity Team ", 7 | "maintainers": [ 8 | "Jaco Greeff", 9 | "Nicolas Gotchac" 10 | ], 11 | "contributors": [], 12 | "license": "GPL-3.0", 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/paritytech/js-api.git" 16 | }, 17 | "keywords": [ 18 | "Ethereum", 19 | "API", 20 | "RPC", 21 | "Parity", 22 | "Promise" 23 | ], 24 | "engines": { 25 | "node": ">=6.4" 26 | }, 27 | "scripts": { 28 | "build": "rimraf lib && babel src --out-dir lib --ignore *.spec.js", 29 | "ci:makeshift": "makeshift", 30 | "lint": "npm run lint:css && npm run lint:js", 31 | "lint:css": "echo \"WARN: npm run lint:css skipped\"", 32 | "lint:js": "eslint src", 33 | "test": "cross-env NODE_ENV=test mocha 'src/*.spec.js' 'src/**/*.spec.js'", 34 | "test:coverage": "cross-env NODE_ENV=test istanbul cover _mocha 'src/*.spec.js' 'src/**/*.spec.js' && coveralls < coverage/lcov.info" 35 | }, 36 | "publishConfig": { 37 | "access": "public" 38 | }, 39 | "devDependencies": { 40 | "babel-cli": "^6.26.0", 41 | "babel-core": "^6.26.0", 42 | "babel-plugin-transform-class-properties": "^6.24.1", 43 | "babel-plugin-transform-object-rest-spread": "^6.26.0", 44 | "babel-preset-env": "^1.6.1", 45 | "babel-preset-stage-0": "^6.24.1", 46 | "chai": "3.5.0", 47 | "chai-as-promised": "6.0.0", 48 | "coveralls": "^3.0.0", 49 | "cross-env": "^5.1.1", 50 | "eslint": "^4.4.0", 51 | "eslint-config-semistandard": "^11.0.0", 52 | "eslint-config-standard": "^10.2.1", 53 | "eslint-config-standard-react": "^5.0.0", 54 | "eslint-plugin-import": "^2.7.0", 55 | "eslint-plugin-node": "^5.1.1", 56 | "eslint-plugin-promise": "^3.5.0", 57 | "eslint-plugin-react": "^7.1.0", 58 | "eslint-plugin-standard": "^3.0.1", 59 | "istanbul": "^0.4.5", 60 | "jsdom": "^11.1.0", 61 | "makeshift": "^1.1.0", 62 | "mocha": "^3.4.2", 63 | "mock-local-storage": "1.0.2", 64 | "mock-socket": "6.0.4", 65 | "nock": "9.0.7", 66 | "rimraf": "^2.6.2", 67 | "sinon": "1.17.7", 68 | "sinon-as-promised": "4.0.2", 69 | "sinon-chai": "2.8.0" 70 | }, 71 | "dependencies": { 72 | "@parity/abi": "2.1.x", 73 | "@parity/jsonrpc": "2.1.x", 74 | "@parity/wordlist": "1.1.x", 75 | "bignumber.js": "3.0.1", 76 | "blockies": "0.0.2", 77 | "es6-error": "4.0.2", 78 | "es6-promise": "^4.1.1", 79 | "eventemitter3": "^2.0.2", 80 | "isomorphic-fetch": "^2.2.1", 81 | "js-sha3": "0.5.5", 82 | "lodash": "^4.17.4", 83 | "store": "^2.0.12", 84 | "websocket": "^1.0.25" 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /scripts/travis.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # ISC, Copyright 2017 Jaco Greeff 3 | 4 | set -e 5 | 6 | echo "Running code checks & build" 7 | 8 | npm run lint 9 | npm run build 10 | npm run test:coverage 11 | 12 | # Pull requests and commits to other branches shouldn't try to deploy, just build to verify 13 | if [ "$TRAVIS_PULL_REQUEST" != "false" -o "$TRAVIS_BRANCH" != "master" ]; then 14 | echo "Branch check completed" 15 | 16 | exit 0 17 | fi 18 | 19 | echo "Setting up GitHub config" 20 | 21 | git config push.default simple 22 | git config merge.ours.driver true 23 | git config user.name "Travis CI" 24 | git config user.email "$COMMIT_AUTHOR_EMAIL" 25 | git remote set-url origin https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git > /dev/null 2>&1 26 | 27 | if [ -n "$(git status --untracked-files=no --porcelain)" ]; then 28 | echo "Adding build artifacts" 29 | 30 | git add . 31 | git commit -m "[CI Skip] Build artifacts" 32 | fi 33 | 34 | echo "Publishing to npm" 35 | 36 | npm run ci:makeshift 37 | npm --no-git-tag-version version 38 | npm version patch -m "[CI Skip] %s" 39 | npm publish 40 | 41 | echo "Final push to GitHub" 42 | 43 | git push --quiet origin HEAD:refs/heads/$TRAVIS_BRANCH > /dev/null 2>&1 44 | 45 | echo "Release completed" 46 | 47 | exit 0 48 | -------------------------------------------------------------------------------- /src/api.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const util = require('./util'); 22 | const Api = require('./api'); 23 | 24 | describe('Api', () => { 25 | describe('constructor', () => { 26 | it('wraps a currentProvider when supplied', () => { 27 | const sendAsync = sinon.stub(); 28 | const currentProvider = { 29 | sendAsync 30 | }; 31 | const api = new Api(currentProvider); 32 | 33 | api.provider.send('method', [], () => {}); 34 | expect(sendAsync).to.have.been.called; 35 | }); 36 | }); 37 | 38 | it('exposes util as static property', () => { 39 | expect(Api.util).to.equal(util); 40 | }); 41 | }); 42 | -------------------------------------------------------------------------------- /src/contract/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Contract = require('./contract'); 18 | 19 | module.exports = Contract; 20 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | require('./polyfill'); 18 | 19 | const Api = require('./api'); 20 | 21 | module.exports = Api; 22 | -------------------------------------------------------------------------------- /src/library.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const es6Promise = require('es6-promise'); 18 | 19 | es6Promise.polyfill(); 20 | 21 | const isNode = typeof global !== 'undefined' && typeof global !== 'undefined'; 22 | const isBrowser = typeof self !== 'undefined' && typeof self.window !== 'undefined'; 23 | 24 | if (isBrowser) { 25 | require('whatwg-fetch'); 26 | } 27 | 28 | if (isNode) { 29 | global.fetch = require('node-fetch'); 30 | } 31 | 32 | const Abi = require('@parity/abi'); 33 | const Api = require('./index'); 34 | 35 | module.exports = { Api, Abi }; 36 | -------------------------------------------------------------------------------- /src/polyfill.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | if (typeof Promise === 'undefined') { 18 | require('es6-promise').polyfill(); 19 | } 20 | 21 | if (typeof fetch === 'undefined') { 22 | require('isomorphic-fetch'); 23 | } 24 | -------------------------------------------------------------------------------- /src/provider/current.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const JsonRpcEncoder = require('../transport/jsonRpcEncoder'); 18 | 19 | class Current extends JsonRpcEncoder { 20 | constructor (currentProvider) { 21 | super(); 22 | 23 | this._currentProvider = currentProvider; 24 | } 25 | 26 | send (method, params, callback) { 27 | this._currentProvider.sendAsync(this.encodeObject(method, params), (error, result) => { 28 | if (error) { 29 | callback(error); 30 | } else if (result && result.result) { 31 | callback(null, result.result); 32 | } else { 33 | callback(null, result); 34 | } 35 | }); 36 | } 37 | 38 | get isParity () { 39 | return !!this._currentProvider.isParity; 40 | } 41 | } 42 | 43 | module.exports = Current; 44 | -------------------------------------------------------------------------------- /src/provider/current.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const Current = require('./current'); 20 | 21 | function initProvider (sendAsync, isParity = false) { // eslint-disable-line standard/no-callback-literal 22 | return new Current({ 23 | sendAsync, 24 | isParity 25 | }); 26 | } 27 | 28 | describe('provider/Current', () => { 29 | describe('isParity', () => { 30 | it('returns the value of the embedded provider', () => { 31 | expect(initProvider(null, true).isParity).to.be.true; 32 | }); 33 | }); 34 | 35 | describe('send', () => { 36 | it('calls the sendAsync on the wrapped provider', (done) => { 37 | const sendAsync = (payload, callback) => { 38 | callback(null, { result: payload }); 39 | }; 40 | 41 | initProvider(sendAsync).send('method', ['params'], (error, payload) => { 42 | expect(error).not.to.be.ok; 43 | expect(payload).to.deep.equal({ 44 | id: 1, 45 | jsonrpc: '2.0', 46 | method: 'method', 47 | params: ['params'] 48 | }); 49 | done(); 50 | }); 51 | }); 52 | 53 | it('returns the embedded result object', (done) => { 54 | const sendAsync = (payload, callback) => callback(null, { 55 | result: 'xyz' 56 | }); 57 | 58 | initProvider(sendAsync).send('', [], (error, result) => { 59 | expect(error).not.to.be.ok; 60 | expect(result).to.equal('xyz'); 61 | done(); 62 | }); 63 | }); 64 | 65 | it('returns a non-embedded result (fallback)', (done) => { 66 | const sendAsync = (payload, callback) => callback(null, 'xyz'); 67 | 68 | initProvider(sendAsync).send('', [], (error, result) => { 69 | expect(error).not.to.be.ok; 70 | expect(result).to.equal('xyz'); 71 | done(); 72 | }); 73 | }); 74 | 75 | it('returns the error', (done) => { 76 | const sendAsync = (payload, callback) => { 77 | callback('error'); // eslint-disable-line 78 | }; 79 | 80 | initProvider(sendAsync).send('method', ['params'], (error, payload) => { 81 | expect(error).to.equal('error'); 82 | done(); 83 | }); 84 | }); 85 | }); 86 | }); 87 | -------------------------------------------------------------------------------- /src/provider/http.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Transport = require('../transport').Http; 18 | 19 | class Http extends Transport { 20 | constructor (url, connectTimeout) { 21 | super(url, connectTimeout); 22 | 23 | this.send = this.send.bind(this); 24 | } 25 | 26 | send (method, params, callback) { 27 | this 28 | ._execute(method, params) 29 | .then((result) => callback(null, result)) 30 | .catch((error) => callback(error)); 31 | } 32 | 33 | get isParity () { 34 | return true; 35 | } 36 | } 37 | 38 | module.exports = Http; 39 | -------------------------------------------------------------------------------- /src/provider/http.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const Http = require('./http'); 20 | 21 | let provider; 22 | 23 | function createProvider () { 24 | provider = new Http('http://test.com', -1); 25 | } 26 | 27 | describe('provider/Http', () => { 28 | beforeEach(() => { 29 | createProvider(); 30 | }); 31 | 32 | describe('isParity', () => { 33 | it('return true', () => { 34 | expect(provider.isParity).to.be.true; 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /src/provider/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Current = require('./current'); 18 | const Http = require('./http'); 19 | const PostMessage = require('./postMessage'); 20 | const PromiseProvider = require('./promise'); 21 | const SendAsync = require('./sendAsync'); 22 | const Ws = require('./ws'); 23 | 24 | const WsSecure = Ws; 25 | 26 | module.exports = { 27 | Current, 28 | Http, 29 | PostMessage, 30 | PromiseProvider, 31 | SendAsync, 32 | Ws, 33 | WsSecure 34 | }; 35 | -------------------------------------------------------------------------------- /src/provider/postMessage.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const EventEmitter = require('eventemitter3'); 18 | 19 | const METHOD_REQUEST_TOKEN = 'shell_requestNewToken'; 20 | 21 | class PostMessage extends EventEmitter { 22 | constructor (appId, destination, source) { 23 | super(); 24 | 25 | this._appId = appId; 26 | this._destination = destination || window.parent; 27 | 28 | this.id = 0; 29 | this._connected = false; 30 | this._messages = {}; 31 | this._queued = []; 32 | 33 | this._receiveMessage = this._receiveMessage.bind(this); 34 | this._send = this._send.bind(this); 35 | this.send = this.send.bind(this); 36 | this.subscribe = this.subscribe.bind(this); 37 | this.unsubscribe = this.unsubscribe.bind(this); 38 | 39 | (source || window).addEventListener('message', this._receiveMessage, false); 40 | } 41 | 42 | get isConnected () { 43 | return this._connected; 44 | } 45 | 46 | get isParity () { 47 | return true; 48 | } 49 | 50 | get queuedCount () { 51 | return this._queued.length; 52 | } 53 | 54 | setToken (token) { 55 | if (token) { 56 | this._connected = true; 57 | this._token = token; 58 | this.emit('connected'); 59 | this._sendQueued(); 60 | } 61 | } 62 | 63 | addMiddleware () { 64 | } 65 | 66 | requestNewToken () { 67 | return new Promise((resolve, reject) => { 68 | this.send(METHOD_REQUEST_TOKEN, [], (error, token) => { 69 | if (error) { 70 | reject(error); 71 | } else { 72 | this.setToken(token); 73 | resolve(token); 74 | } 75 | }); 76 | }); 77 | } 78 | 79 | _constructMessage (id, data) { 80 | return Object.assign({}, data, { 81 | id, 82 | to: 'shell', 83 | from: this._appId, 84 | token: this._token 85 | }); 86 | } 87 | 88 | _send (message) { 89 | if (!this._token && message.data.method !== METHOD_REQUEST_TOKEN) { 90 | this._queued.push(message); 91 | 92 | return; 93 | } 94 | 95 | const id = ++this.id; 96 | const postMessage = this._constructMessage(id, message.data); 97 | 98 | this._messages[id] = Object.assign({}, postMessage, message.options); 99 | this._destination.postMessage(postMessage, '*'); 100 | } 101 | 102 | send (method, params, callback) { 103 | this._send({ 104 | data: { 105 | method, 106 | params 107 | }, 108 | options: { 109 | callback 110 | } 111 | }); 112 | } 113 | 114 | _sendQueued () { 115 | if (!this._token) { 116 | return; 117 | } 118 | 119 | this._queued.forEach(this._send); 120 | this._queued = []; 121 | } 122 | 123 | subscribe (api, callback, params) { 124 | // console.log('paritySubscribe', JSON.stringify(params), api, callback); 125 | return new Promise((resolve, reject) => { 126 | this._send({ 127 | data: { 128 | api, 129 | params 130 | }, 131 | options: { 132 | callback, 133 | resolve, 134 | reject, 135 | subscription: true, 136 | initial: true 137 | } 138 | }); 139 | }); 140 | } 141 | 142 | // FIXME: Should return callback, not promise 143 | unsubscribe (subId) { 144 | return new Promise((resolve, reject) => { 145 | this._send({ 146 | data: { 147 | subId 148 | }, 149 | options: { 150 | callback: (error, result) => { 151 | error 152 | ? reject(error) 153 | : resolve(result); 154 | } 155 | } 156 | }); 157 | }); 158 | } 159 | 160 | unsubscribeAll () { 161 | return this.unsubscribe('*'); 162 | } 163 | 164 | _receiveMessage ({ data: { id, error, from, to, token, result }, origin, source }) { 165 | const isTokenValid = token 166 | ? token === this._token 167 | : true; 168 | 169 | if (from !== 'shell' || to !== this._appId || !isTokenValid) { 170 | return; 171 | } 172 | 173 | if (this._messages[id].subscription) { 174 | // console.log('subscription', result, 'initial?', this._messages[id].initial); 175 | this._messages[id].initial 176 | ? this._messages[id].resolve(result) 177 | : this._messages[id].callback(error && new Error(error), result); 178 | this._messages[id].initial = false; 179 | } else { 180 | this._messages[id].callback(error && new Error(error), result); 181 | this._messages[id] = null; 182 | } 183 | } 184 | } 185 | 186 | module.exports = PostMessage; 187 | -------------------------------------------------------------------------------- /src/provider/postMessage.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const PostMessage = require('./postMessage'); 22 | 23 | const APP_ID = 'xyz'; 24 | 25 | let destination; 26 | let provider; 27 | let source; 28 | 29 | function createDestination () { 30 | destination = { 31 | postMessage: sinon.stub() 32 | }; 33 | 34 | return destination; 35 | } 36 | 37 | function createSource () { 38 | source = { 39 | addEventListener: sinon.stub() 40 | }; 41 | 42 | return source; 43 | } 44 | 45 | function createProvider () { 46 | provider = new PostMessage(APP_ID, createDestination(), createSource()); 47 | 48 | return provider; 49 | } 50 | 51 | describe('provider/PostMessage', () => { 52 | beforeEach(() => { 53 | createProvider(); 54 | }); 55 | 56 | describe('constructor', () => { 57 | it('adds an event listener for message', () => { 58 | expect(source.addEventListener).to.have.been.calledWith('message', provider._receiveMessage); 59 | }); 60 | }); 61 | 62 | describe('getters', () => { 63 | describe('isParity', () => { 64 | it('returns true', () => { 65 | expect(provider.isParity).to.be.true; 66 | }); 67 | }); 68 | 69 | describe('isConnected', () => { 70 | it('returns the internal connected status', () => { 71 | provider._connected = 'connected'; 72 | 73 | expect(provider.isConnected).to.equal('connected'); 74 | }); 75 | }); 76 | }); 77 | 78 | describe('setToken', () => { 79 | beforeEach(() => { 80 | sinon.spy(provider, '_sendQueued'); 81 | }); 82 | 83 | afterEach(() => { 84 | provider._sendQueued.restore(); 85 | }); 86 | 87 | it('sets the connected status', () => { 88 | expect(provider.isConnected).to.be.false; 89 | 90 | provider.setToken('123'); 91 | 92 | expect(provider.isConnected).to.be.true; 93 | }); 94 | 95 | it('sends all queued messages', () => { 96 | expect(provider._sendQueued).not.to.have.beenCalled; 97 | 98 | provider.setToken('123'); 99 | 100 | expect(provider._sendQueued).to.have.been.called; 101 | }); 102 | 103 | it('emits a connected message', (done) => { 104 | provider.on('connected', done); 105 | provider.setToken('123'); 106 | }); 107 | }); 108 | 109 | describe('send', () => { 110 | it('queues messages before token is available', () => { 111 | expect(provider.queuedCount).to.equal(0); 112 | 113 | provider.send('method', 'params', () => {}); 114 | 115 | expect(destination.postMessage).not.to.have.been.called; 116 | expect(provider.queuedCount).to.equal(1); 117 | }); 118 | 119 | it('sends queued messages as token is available', () => { 120 | expect(provider.queuedCount).to.equal(0); 121 | 122 | provider.send('method', 'params', () => {}); 123 | provider.setToken('123'); 124 | 125 | expect(destination.postMessage).to.have.been.calledWith( 126 | provider._constructMessage(1, { 127 | method: 'method', 128 | params: 'params' 129 | }), '*' 130 | ); 131 | expect(provider.queuedCount).to.equal(0); 132 | }); 133 | }); 134 | }); 135 | -------------------------------------------------------------------------------- /src/provider/promise.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const EventEmitter = require('eventemitter3'); 18 | 19 | class PromiseProvider extends EventEmitter { 20 | constructor (provider) { 21 | super(); 22 | 23 | this.provider = provider; 24 | this.provider.on('connected', () => this.emit('connected')); 25 | this.provider.on('connecting', () => this.emit('connecting')); 26 | this.provider.on('disconnected', () => this.emit('disconnected')); 27 | 28 | this.send = this.send.bind(this); 29 | } 30 | 31 | get isConnected () { 32 | return this.provider.isConnected; 33 | } 34 | 35 | get isParity () { 36 | return !!this.provider.isParity; 37 | } 38 | 39 | send (method, ...params) { 40 | if (!this.provider.send) { 41 | // old-style transport interface for backwards compatibility 42 | return this.provider.execute(method, params); 43 | } 44 | 45 | return new Promise((resolve, reject) => { 46 | this.provider.send(method, params, (error, result) => { 47 | if (error) { 48 | reject(error); 49 | } else { 50 | resolve(result); 51 | } 52 | }); 53 | }); 54 | } 55 | } 56 | 57 | module.exports = PromiseProvider; 58 | -------------------------------------------------------------------------------- /src/provider/sendAsync.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | class SendAsync { 18 | constructor (provider) { 19 | this._provider = provider; 20 | } 21 | 22 | send () { 23 | throw new Error('Provider does not support the sync send(payload) method'); 24 | } 25 | 26 | sendAsync ({ method, params }, callback) { 27 | this._provider.send(method, params, (error, result) => { 28 | callback(error, { result }); 29 | }); 30 | } 31 | 32 | get isParity () { 33 | return !!this._provider.isParity; 34 | } 35 | } 36 | 37 | module.exports = SendAsync; 38 | -------------------------------------------------------------------------------- /src/provider/sendAsync.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const SendAsync = require('./sendAsync'); 20 | 21 | function initProvider () { 22 | return new SendAsync({ 23 | send: (method, params, callback) => { 24 | callback(null, { isStubbed: true, method, params }); 25 | } 26 | }); 27 | } 28 | 29 | describe('provider/SendAsync', () => { 30 | describe('send', () => { 31 | it('throws an expection', () => { 32 | expect(() => initProvider().send()).to.throw; 33 | }); 34 | }); 35 | 36 | describe('sendAsync', () => { 37 | it('calls into the supplied provider', (done) => { 38 | initProvider().sendAsync({ method: 'method', params: 'params' }, (error, data) => { // eslint-disable-line 39 | expect(data).to.deep.equal({ 40 | result: { 41 | isStubbed: true, 42 | method: 'method', 43 | params: 'params' 44 | } 45 | }); 46 | done(); 47 | }); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /src/provider/ws.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Transport = require('../transport').Ws; 18 | 19 | class Ws extends Transport { 20 | constructor (url, token, autoconnect) { 21 | super(url, token, autoconnect); 22 | 23 | this.send = this.send.bind(this); 24 | } 25 | 26 | send (method, params, callback) { 27 | this 28 | ._execute(method, params) 29 | .then((result) => callback(null, result)) 30 | .catch((error) => callback(error)); 31 | } 32 | 33 | get isParity () { 34 | return true; 35 | } 36 | } 37 | 38 | module.exports = Ws; 39 | -------------------------------------------------------------------------------- /src/provider/ws.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const Ws = require('./ws'); 20 | 21 | let provider; 22 | 23 | function createProvider () { 24 | provider = new Ws('ws://test.com', '123', false); 25 | } 26 | 27 | describe('provider/Ws', () => { 28 | beforeEach(() => { 29 | createProvider(); 30 | }); 31 | 32 | describe('isParity', () => { 33 | it('return true', () => { 34 | expect(provider.isParity).to.be.true; 35 | }); 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /src/pubsub/eth/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Eth = require('./eth'); 18 | 19 | module.exports = Eth; 20 | -------------------------------------------------------------------------------- /src/pubsub/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const PubSub = require('./pubsub'); 18 | 19 | module.exports = PubSub; 20 | -------------------------------------------------------------------------------- /src/pubsub/net/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Net = require('./net'); 18 | 19 | module.exports = Net; 20 | -------------------------------------------------------------------------------- /src/pubsub/net/net.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const PubsubBase = require('../pubsubBase'); 18 | 19 | const { outNumber } = require('../../format/output'); 20 | 21 | class Net extends PubsubBase { 22 | constructor (provider) { 23 | super(provider); 24 | this._api = 'parity'; 25 | } 26 | 27 | version (callback) { 28 | return this.addListener(this._api, 'net_version', callback); 29 | } 30 | 31 | peerCount (callback) { 32 | return this.addListener(this._api, 'net_peerCount', (error, data) => { 33 | error 34 | ? callback(error) 35 | : callback(null, outNumber(data)); 36 | }); 37 | } 38 | 39 | listening (callback) { 40 | return this.addListener(this._api, 'net_listening', callback); 41 | } 42 | } 43 | 44 | module.exports = Net; 45 | -------------------------------------------------------------------------------- /src/pubsub/parity/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Parity = require('./parity'); 18 | 19 | module.exports = Parity; 20 | -------------------------------------------------------------------------------- /src/pubsub/pubsub.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Eth = require('./eth'); 18 | const Parity = require('./parity'); 19 | const Net = require('./net'); 20 | const Signer = require('./signer'); 21 | 22 | const { isFunction } = require('../util/types'); 23 | 24 | class PubSub { 25 | constructor (provider) { 26 | if (!provider || !isFunction(provider.subscribe)) { 27 | throw new Error('Pubsub API needs transport with subscribe() function defined. (WebSocket)'); 28 | } 29 | 30 | this._eth = new Eth(provider); 31 | this._net = new Net(provider); 32 | this._parity = new Parity(provider); 33 | this._signer = new Signer(provider); 34 | } 35 | 36 | get net () { 37 | return this._net; 38 | } 39 | 40 | get eth () { 41 | return this._eth; 42 | } 43 | 44 | get parity () { 45 | return this._parity; 46 | } 47 | 48 | get signer () { 49 | return this._signer; 50 | } 51 | 52 | unsubscribe (subscriptionIds) { 53 | // subscriptions are namespace independent. Thus we can simply removeListener from any. 54 | return this._parity.removeListener(subscriptionIds); 55 | } 56 | 57 | subscribeAndGetResult (f, callback) { 58 | return new Promise((resolve, reject) => { 59 | let isFirst = true; 60 | let onSubscription = (error, data) => { 61 | const p1 = error ? Promise.reject(error) : Promise.resolve(data); 62 | const p2 = p1.then(callback); 63 | 64 | if (isFirst) { 65 | isFirst = false; 66 | p2 67 | .then(resolve) 68 | .catch(reject); 69 | } 70 | }; 71 | 72 | try { 73 | f.call(this, onSubscription).catch(reject); 74 | } catch (err) { 75 | reject(err); 76 | } 77 | }); 78 | } 79 | } 80 | 81 | module.exports = PubSub; 82 | -------------------------------------------------------------------------------- /src/pubsub/pubsubBase.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | class PubSubBase { 18 | // Provider for websocket pubsub transport 19 | constructor (provider) { 20 | this._provider = provider; 21 | } 22 | 23 | addListener (module, eventName, callback, eventParams = []) { 24 | if (eventName) { 25 | const params = eventParams 26 | ? [eventName, eventParams] 27 | : [eventName]; 28 | 29 | return this._provider.subscribe(module, callback, params); 30 | } 31 | 32 | return this._provider.subscribe(module, callback, eventParams); 33 | } 34 | 35 | removeListener (subscriptionIds) { 36 | return this._provider.unsubscribe(subscriptionIds); 37 | } 38 | 39 | unsubscribe (subscriptionIds) { 40 | return this.removeListener(subscriptionIds); 41 | } 42 | } 43 | 44 | module.exports = PubSubBase; 45 | -------------------------------------------------------------------------------- /src/pubsub/signer/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Signer = require('./signer'); 18 | 19 | module.exports = Signer; 20 | -------------------------------------------------------------------------------- /src/pubsub/signer/signer.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const PubsubBase = require('../pubsubBase'); 18 | const { outSignerRequest } = require('../../format/output'); 19 | 20 | class Signer extends PubsubBase { 21 | constructor (provider) { 22 | super(provider); 23 | 24 | this._api = { 25 | subscribe: 'signer_subscribePending', 26 | unsubscribe: 'signer_unsubscribePending', 27 | subscription: 'signer_pending' 28 | }; 29 | } 30 | 31 | pendingRequests (callback) { 32 | return this.addListener(this._api, null, (error, data) => { 33 | error 34 | ? callback(error) 35 | : callback(null, data.map(outSignerRequest)); 36 | }); 37 | } 38 | 39 | requestsToConfirm (callback) { 40 | return this.pendingRequests(callback); 41 | } 42 | } 43 | 44 | module.exports = Signer; 45 | -------------------------------------------------------------------------------- /src/rpc/db/db.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { inHex } = require('../../format/input'); 18 | 19 | class Db { 20 | constructor (transport) { 21 | this._transport = transport; 22 | } 23 | 24 | getHex (dbName, keyName) { 25 | return this._transport 26 | .send('db_getHex', dbName, keyName); 27 | } 28 | 29 | getString (dbName, keyName) { 30 | return this._transport 31 | .send('db_getString', dbName, keyName); 32 | } 33 | 34 | putHex (dbName, keyName, hexData) { 35 | return this._transport 36 | .send('db_putHex', dbName, keyName, inHex(hexData)); 37 | } 38 | 39 | putString (dbName, keyName, stringData) { 40 | return this._transport 41 | .send('db_putString', dbName, keyName, stringData); 42 | } 43 | } 44 | 45 | module.exports = Db; 46 | -------------------------------------------------------------------------------- /src/rpc/db/db.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 18 | 19 | const { Http, PromiseProvider } = require('../../provider'); 20 | const Db = require('./db'); 21 | 22 | const instance = new Db(new PromiseProvider(new Http(TEST_HTTP_URL, -1))); 23 | 24 | describe('rpc/Db', () => { 25 | let scope; 26 | 27 | describe('putHex', () => { 28 | beforeEach(() => { 29 | scope = mockHttp([{ method: 'db_putHex', reply: { result: [] } }]); 30 | }); 31 | 32 | it('formats the inputs correctly', () => { 33 | return instance.putHex('db', 'key', '1234').then(() => { 34 | expect(scope.body.db_putHex.params).to.deep.equal(['db', 'key', '0x1234']); 35 | }); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/rpc/db/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Db = require('./db'); 18 | 19 | module.exports = Db; 20 | -------------------------------------------------------------------------------- /src/rpc/eth/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Eth = require('./eth'); 18 | 19 | module.exports = Eth; 20 | -------------------------------------------------------------------------------- /src/rpc/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Db = require('./db'); 18 | const Eth = require('./eth'); 19 | const Parity = require('./parity'); 20 | const Net = require('./net'); 21 | const Personal = require('./personal'); 22 | const Shell = require('./shell'); 23 | const Shh = require('./shh'); 24 | const Signer = require('./signer'); 25 | const Trace = require('./trace'); 26 | const Web3 = require('./web3'); 27 | 28 | module.exports = { 29 | Db, 30 | Eth, 31 | Parity, 32 | Net, 33 | Personal, 34 | Shell, 35 | Shh, 36 | Signer, 37 | Trace, 38 | Web3 39 | }; 40 | -------------------------------------------------------------------------------- /src/rpc/net/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Net = require('./net'); 18 | 19 | module.exports = Net; 20 | -------------------------------------------------------------------------------- /src/rpc/net/net.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { createHttpApi } = require('../../test/e2e/ethapi'); 20 | const { isBoolean } = require('../../test/types'); 21 | 22 | describe('ethapi.net', () => { 23 | const ethapi = createHttpApi(); 24 | 25 | describe('listening', () => { 26 | it('returns the listening status', () => { 27 | return ethapi.net.listening().then((status) => { 28 | expect(isBoolean(status)).to.be.true; 29 | }); 30 | }); 31 | }); 32 | 33 | describe('peerCount', () => { 34 | it('returns the peer count', () => { 35 | return ethapi.net.peerCount().then((count) => { 36 | expect(count.gte(0)).to.be.true; 37 | }); 38 | }); 39 | }); 40 | 41 | describe('version', () => { 42 | it('returns the version', () => { 43 | return ethapi.net.version().then((version) => { 44 | expect(version).to.be.ok; 45 | }); 46 | }); 47 | }); 48 | }); 49 | -------------------------------------------------------------------------------- /src/rpc/net/net.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { outNumber } = require('../../format/output'); 18 | 19 | class Net { 20 | constructor (provider) { 21 | this._provider = provider; 22 | } 23 | 24 | listening () { 25 | return this._provider 26 | .send('net_listening'); 27 | } 28 | 29 | peerCount () { 30 | return this._provider 31 | .send('net_peerCount') 32 | .then(outNumber); 33 | } 34 | 35 | version () { 36 | return this._provider 37 | .send('net_version'); 38 | } 39 | } 40 | module.exports = Net; 41 | -------------------------------------------------------------------------------- /src/rpc/net/net.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 20 | const { isBigNumber } = require('../../../test/types'); 21 | 22 | const { Http, PromiseProvider } = require('../../provider'); 23 | const Net = require('./net'); 24 | 25 | const instance = new Net(new PromiseProvider(new Http(TEST_HTTP_URL, -1))); 26 | 27 | describe('rpc/Net', () => { 28 | describe('peerCount', () => { 29 | it('returns the connected peers, formatted', () => { 30 | mockHttp([{ method: 'net_peerCount', reply: { result: '0x123456' } }]); 31 | 32 | return instance.peerCount().then((count) => { 33 | expect(isBigNumber(count)).to.be.true; 34 | expect(count.eq(0x123456)).to.be.true; 35 | }); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/rpc/parity/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Parity = require('./parity'); 18 | 19 | module.exports = Parity; 20 | -------------------------------------------------------------------------------- /src/rpc/parity/parity.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { createHttpApi } = require('../../test/e2e/ethapi'); 20 | 21 | describe('ethapi.parity', () => { 22 | const ethapi = createHttpApi(); 23 | 24 | describe('chainStatus', () => { 25 | it('returns and translates the status', () => { 26 | return ethapi.parity.chainStatus().then((value) => { 27 | expect(value).to.be.ok; 28 | }); 29 | }); 30 | }); 31 | 32 | describe('gasFloorTarget', () => { 33 | it('returns and translates the target', () => { 34 | return ethapi.parity.gasFloorTarget().then((value) => { 35 | expect(value.gt(0)).to.be.true; 36 | }); 37 | }); 38 | }); 39 | 40 | describe('gasPriceHistogram', () => { 41 | it('returns and translates the target', () => { 42 | return ethapi.parity.gasPriceHistogram().then((result) => { 43 | expect(Object.keys(result)).to.deep.equal(['bucketBounds', 'counts']); 44 | expect(result.bucketBounds.length > 0).to.be.true; 45 | expect(result.counts.length > 0).to.be.true; 46 | }); 47 | }); 48 | }); 49 | 50 | describe('netChain', () => { 51 | it('returns and the chain', () => { 52 | return ethapi.parity.netChain().then((value) => { 53 | expect(value).to.equal('morden'); 54 | }); 55 | }); 56 | }); 57 | 58 | describe('netPort', () => { 59 | it('returns and translates the port', () => { 60 | return ethapi.parity.netPort().then((value) => { 61 | expect(value.gt(0)).to.be.true; 62 | }); 63 | }); 64 | }); 65 | 66 | describe('transactionsLimit', () => { 67 | it('returns and translates the limit', () => { 68 | return ethapi.parity.transactionsLimit().then((value) => { 69 | expect(value.gt(0)).to.be.true; 70 | }); 71 | }); 72 | }); 73 | 74 | describe('rpcSettings', () => { 75 | it('returns and translates the settings', () => { 76 | return ethapi.parity.rpcSettings().then((value) => { 77 | expect(value).to.be.ok; 78 | }); 79 | }); 80 | }); 81 | }); 82 | -------------------------------------------------------------------------------- /src/rpc/parity/parity.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const BigNumber = require('bignumber.js'); 20 | 21 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 22 | const { isBigNumber } = require('../../../test/types'); 23 | 24 | const { Http, PromiseProvider } = require('../../provider'); 25 | const Parity = require('./parity'); 26 | 27 | const instance = new Parity(new PromiseProvider(new Http(TEST_HTTP_URL, -1))); 28 | 29 | describe('rpc/parity', () => { 30 | describe('accountsInfo', () => { 31 | it('retrieves the available account info', () => { 32 | mockHttp([{ method: 'parity_accountsInfo', reply: { 33 | result: { 34 | '0x63cf90d3f0410092fc0fca41846f596223979195': { 35 | name: 'name', uuid: 'uuid', meta: '{"data":"data"}' 36 | } 37 | } 38 | } }]); 39 | 40 | return instance.accountsInfo().then((result) => { 41 | expect(result).to.deep.equal({ 42 | '0x63Cf90D3f0410092FC0fca41846f596223979195': { 43 | name: 'name', uuid: 'uuid', meta: { 44 | data: 'data' 45 | } 46 | } 47 | }); 48 | }); 49 | }); 50 | }); 51 | 52 | describe('chainStatus', () => { 53 | it('retrieves the chain status', () => { 54 | mockHttp([{ method: 'parity_chainStatus', reply: { 55 | result: { 56 | 'blockGap': [0x123, 0x456] 57 | } 58 | } }]); 59 | 60 | return instance.chainStatus().then((result) => { 61 | expect(result).to.deep.equal({ 62 | 'blockGap': [new BigNumber(0x123), new BigNumber(0x456)] 63 | }); 64 | }); 65 | }); 66 | }); 67 | 68 | describe('gasFloorTarget', () => { 69 | it('returns the gasfloor, formatted', () => { 70 | mockHttp([{ method: 'parity_gasFloorTarget', reply: { result: '0x123456' } }]); 71 | 72 | return instance.gasFloorTarget().then((count) => { 73 | expect(isBigNumber(count)).to.be.true; 74 | expect(count.eq(0x123456)).to.be.true; 75 | }); 76 | }); 77 | }); 78 | 79 | describe('importGethAccounts', () => { 80 | const ACCOUNTS = ['0x63cf90d3f0410092fc0fca41846f596223979195']; 81 | let scope; 82 | 83 | beforeEach(() => { 84 | scope = mockHttp([{ method: 'parity_importGethAccounts', reply: { result: ACCOUNTS } }]); 85 | }); 86 | 87 | it('passes the addresses through', () => { 88 | return instance.importGethAccounts(ACCOUNTS).then((result) => { 89 | expect(scope.body['parity_importGethAccounts'].params).to.deep.equal([ACCOUNTS]); 90 | }); 91 | }); 92 | }); 93 | 94 | describe('minGasPrice', () => { 95 | it('returns the min gasprice, formatted', () => { 96 | mockHttp([{ method: 'parity_minGasPrice', reply: { result: '0x123456' } }]); 97 | 98 | return instance.minGasPrice().then((count) => { 99 | expect(isBigNumber(count)).to.be.true; 100 | expect(count.eq(0x123456)).to.be.true; 101 | }); 102 | }); 103 | }); 104 | 105 | describe('netMaxPeers', () => { 106 | it('returns the max peers, formatted', () => { 107 | mockHttp([{ method: 'parity_netMaxPeers', reply: { result: 25 } }]); 108 | 109 | return instance.netMaxPeers().then((count) => { 110 | expect(isBigNumber(count)).to.be.true; 111 | expect(count.eq(25)).to.be.true; 112 | }); 113 | }); 114 | }); 115 | 116 | describe('netPeers', () => { 117 | it('returns the peer structure, formatted', () => { 118 | mockHttp([{ method: 'parity_netPeers', reply: { result: { active: 123, connected: 456, max: 789, peers: [] } } }]); 119 | 120 | return instance.netPeers().then((peers) => { 121 | expect(peers.active.eq(123)).to.be.true; 122 | expect(peers.connected.eq(456)).to.be.true; 123 | expect(peers.max.eq(789)).to.be.true; 124 | }); 125 | }); 126 | }); 127 | 128 | describe('netPort', () => { 129 | it('returns the connected port, formatted', () => { 130 | mockHttp([{ method: 'parity_netPort', reply: { result: 33030 } }]); 131 | 132 | return instance.netPort().then((count) => { 133 | expect(isBigNumber(count)).to.be.true; 134 | expect(count.eq(33030)).to.be.true; 135 | }); 136 | }); 137 | }); 138 | 139 | describe('transactionsLimit', () => { 140 | it('returns the tx limit, formatted', () => { 141 | mockHttp([{ method: 'parity_transactionsLimit', reply: { result: 1024 } }]); 142 | 143 | return instance.transactionsLimit().then((count) => { 144 | expect(isBigNumber(count)).to.be.true; 145 | expect(count.eq(1024)).to.be.true; 146 | }); 147 | }); 148 | }); 149 | }); 150 | -------------------------------------------------------------------------------- /src/rpc/personal/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Personal = require('./personal'); 18 | 19 | module.exports = Personal; 20 | -------------------------------------------------------------------------------- /src/rpc/personal/personal.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { createHttpApi } = require('../../test/e2e/ethapi'); 20 | const { isAddress, isBoolean } = require('../../test/types'); 21 | 22 | describe.skip('ethapi.personal', () => { 23 | const ethapi = createHttpApi(); 24 | const password = 'P@55word'; 25 | let address; 26 | 27 | describe('newAccount', () => { 28 | it('creates a new account', () => { 29 | return ethapi.personal.newAccount(password).then((_address) => { 30 | address = _address; 31 | expect(isAddress(address)).to.be.ok; 32 | }); 33 | }); 34 | }); 35 | 36 | describe('listAccounts', () => { 37 | it('has the newly-created account', () => { 38 | return ethapi.personal.listAccounts(password).then((accounts) => { 39 | expect(accounts.filter((_address) => _address === address)).to.deep.equal([address]); 40 | accounts.forEach((account) => { 41 | expect(isAddress(account)).to.be.true; 42 | }); 43 | }); 44 | }); 45 | }); 46 | 47 | describe('unlockAccount', () => { 48 | it('unlocks the newly-created account', () => { 49 | return ethapi.personal.unlockAccount(address, password).then((result) => { 50 | expect(isBoolean(result)).to.be.true; 51 | expect(result).to.be.true; 52 | }); 53 | }); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /src/rpc/personal/personal.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { inAddress, inNumber10, inOptions } = require('../../format/input'); 18 | const { outAddress } = require('../../format/output'); 19 | 20 | class Personal { 21 | constructor (provider) { 22 | this._provider = provider; 23 | } 24 | 25 | listAccounts () { 26 | return this._provider 27 | .send('personal_listAccounts') 28 | .then((accounts) => (accounts || []).map(outAddress)); 29 | } 30 | 31 | newAccount (password) { 32 | return this._provider 33 | .send('personal_newAccount', password) 34 | .then(outAddress); 35 | } 36 | 37 | sendTransaction (options, password) { 38 | return this._provider 39 | .send('personal_sendTransaction', inOptions(options), password); 40 | } 41 | 42 | unlockAccount (account, password, duration = 1) { 43 | return this._provider 44 | .send('personal_unlockAccount', inAddress(account), password, inNumber10(duration)); 45 | } 46 | } 47 | 48 | module.exports = Personal; 49 | -------------------------------------------------------------------------------- /src/rpc/personal/personal.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 18 | 19 | const { Http, PromiseProvider } = require('../../provider'); 20 | const Personal = require('./personal'); 21 | 22 | const instance = new Personal(new PromiseProvider(new Http(TEST_HTTP_URL, -1))); 23 | 24 | describe('rpc/Personal', () => { 25 | const account = '0x63cf90d3f0410092fc0fca41846f596223979195'; 26 | const checksum = '0x63Cf90D3f0410092FC0fca41846f596223979195'; 27 | let scope; 28 | 29 | describe('listAccounts', () => { 30 | it('retrieves a list of available accounts', () => { 31 | scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: [account] } }]); 32 | 33 | return instance.listAccounts().then((result) => { 34 | expect(result).to.deep.equal([checksum]); 35 | }); 36 | }); 37 | 38 | it('returns an empty list when none available', () => { 39 | scope = mockHttp([{ method: 'personal_listAccounts', reply: { result: null } }]); 40 | 41 | return instance.listAccounts().then((result) => { 42 | expect(result).to.deep.equal([]); 43 | }); 44 | }); 45 | }); 46 | 47 | describe('newAccount', () => { 48 | it('passes the password, returning the address', () => { 49 | scope = mockHttp([{ method: 'personal_newAccount', reply: { result: account } }]); 50 | 51 | return instance.newAccount('password').then((result) => { 52 | expect(scope.body.personal_newAccount.params).to.deep.equal(['password']); 53 | expect(result).to.equal(checksum); 54 | }); 55 | }); 56 | }); 57 | 58 | describe('unlockAccount', () => { 59 | beforeEach(() => { 60 | scope = mockHttp([{ method: 'personal_unlockAccount', reply: { result: [] } }]); 61 | }); 62 | 63 | it('passes account, password & duration', () => { 64 | return instance.unlockAccount(account, 'password', 0xf).then(() => { 65 | expect(scope.body.personal_unlockAccount.params).to.deep.equal([account, 'password', 15]); 66 | }); 67 | }); 68 | 69 | it('provides a default duration when not specified', () => { 70 | return instance.unlockAccount(account, 'password').then(() => { 71 | expect(scope.body.personal_unlockAccount.params).to.deep.equal([account, 'password', 1]); 72 | }); 73 | }); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /src/rpc/shell/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Shell = require('./shell'); 18 | 19 | module.exports = Shell; 20 | -------------------------------------------------------------------------------- /src/rpc/shell/shell.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | class Shell { 18 | constructor (provider) { 19 | this._provider = provider; 20 | } 21 | 22 | getApps (retrieveAll = false) { 23 | return this._provider 24 | .send('shell_getApps', retrieveAll); 25 | } 26 | 27 | getFilteredMethods () { 28 | return this._provider 29 | .send('shell_getFilteredMethods'); 30 | } 31 | 32 | getMethodGroups () { 33 | return this._provider 34 | .send('shell_getMethodGroups'); 35 | } 36 | 37 | getMethodPermissions () { 38 | return this._provider 39 | .send('shell_getMethodPermissions'); 40 | } 41 | 42 | loadApp (appId, params = null) { 43 | return this._provider 44 | .send('shell_loadApp', appId, params); 45 | } 46 | 47 | setMethodPermissions (permissions) { 48 | return this._provider 49 | .send('shell_setMethodPermissions', permissions); 50 | } 51 | 52 | setAppVisibility (appId, state) { 53 | return this._provider 54 | .send('shell_setAppVisibility', appId, state); 55 | } 56 | 57 | setAppPinned (appId, state) { 58 | return this._provider 59 | .send('shell_setAppPinned', appId, state); 60 | } 61 | } 62 | 63 | module.exports = Shell; 64 | -------------------------------------------------------------------------------- /src/rpc/shh/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Shh = require('./shh'); 18 | 19 | module.exports = Shh; 20 | -------------------------------------------------------------------------------- /src/rpc/shh/shh.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | class Shh { 18 | constructor (transport) { 19 | this._transport = transport; 20 | } 21 | 22 | info () { 23 | return this._transport 24 | .execute('shh_info'); 25 | } 26 | 27 | newKeyPair () { 28 | return this._transport 29 | .execute('shh_newKeyPair'); 30 | } 31 | 32 | addPrivateKey (privKey) { 33 | return this._transport 34 | .execute('shh_addPrivateKey', privKey); 35 | } 36 | 37 | newSymKey () { 38 | return this._transport 39 | .execute('shh_newSymKey'); 40 | } 41 | 42 | getPublicKey (identity) { 43 | return this._transport 44 | .execute('shh_getPublicKey', identity); 45 | } 46 | 47 | getPrivateKey (identity) { 48 | return this._transport 49 | .execute('shh_getPrivateKey', identity); 50 | } 51 | 52 | getSymKey (identity) { 53 | return this._transport 54 | .execute('shh_getSymKey', identity); 55 | } 56 | 57 | deleteKey (identity) { 58 | return this._transport 59 | .execute('shh_deleteKey', identity); 60 | } 61 | 62 | post (messageObj) { 63 | return this._transport 64 | .execute('shh_post', messageObj); 65 | } 66 | 67 | newMessageFilter (filterObj) { 68 | return this._transport 69 | .execute('shh_newMessageFilter', filterObj); 70 | } 71 | 72 | getFilterMessages (filterId) { 73 | return this._transport 74 | .execute('shh_getFilterMessages', filterId); 75 | } 76 | 77 | deleteMessageFilter (filterId) { 78 | return this._transport 79 | .execute('shh_deleteMessageFilter', filterId); 80 | } 81 | 82 | subscribe (filterObj, callback) { 83 | return this._transport 84 | .subscribe('shh', callback, filterObj); 85 | } 86 | 87 | unsubscribe (subscriptionId) { 88 | return this._transport 89 | .unsubscribe(subscriptionId); 90 | } 91 | } 92 | 93 | module.exports = Shh; 94 | -------------------------------------------------------------------------------- /src/rpc/signer/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Signer = require('./signer'); 18 | 19 | module.exports = Signer; 20 | -------------------------------------------------------------------------------- /src/rpc/signer/signer.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { inData, inNumber16, inOptions } = require('../../format/input'); 18 | const { outSignerRequest } = require('../../format/output'); 19 | 20 | class Signer { 21 | constructor (provider) { 22 | this._provider = provider; 23 | } 24 | 25 | confirmRequest (requestId, options, password) { 26 | return this._provider 27 | .send('signer_confirmRequest', inNumber16(requestId), inOptions(options), password); 28 | } 29 | 30 | confirmRequestRaw (requestId, data) { 31 | return this._provider 32 | .send('signer_confirmRequestRaw', inNumber16(requestId), inData(data)); 33 | } 34 | 35 | confirmRequestWithToken (requestId, options, password) { 36 | return this._provider 37 | .send('signer_confirmRequestWithToken', inNumber16(requestId), inOptions(options), password); 38 | } 39 | 40 | generateAuthorizationToken () { 41 | return this._provider 42 | .send('signer_generateAuthorizationToken'); 43 | } 44 | 45 | generateWebProxyAccessToken (domain) { 46 | return this._provider 47 | .execute('signer_generateWebProxyAccessToken', domain); 48 | } 49 | 50 | rejectRequest (requestId) { 51 | return this._provider 52 | .send('signer_rejectRequest', inNumber16(requestId)); 53 | } 54 | 55 | requestsToConfirm () { 56 | return this._provider 57 | .send('signer_requestsToConfirm') 58 | .then((requests) => (requests || []).map(outSignerRequest)); 59 | } 60 | 61 | signerEnabled () { 62 | return this._provider 63 | .send('signer_signerEnabled'); 64 | } 65 | } 66 | 67 | module.exports = Signer; 68 | -------------------------------------------------------------------------------- /src/rpc/trace/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Trace = require('./trace'); 18 | 19 | module.exports = Trace; 20 | -------------------------------------------------------------------------------- /src/rpc/trace/trace.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { createHttpApi } = require('../../test/e2e/ethapi'); 20 | 21 | describe('ethapi.trace', () => { 22 | const ethapi = createHttpApi(); 23 | 24 | describe('block', () => { 25 | it('returns the latest block traces', () => { 26 | return ethapi.trace.block().then((traces) => { 27 | expect(traces).to.be.ok; 28 | }); 29 | }); 30 | 31 | it('returns traces for a specified block', () => { 32 | return ethapi.trace.block('0x65432').then((traces) => { 33 | expect(traces).to.be.ok; 34 | }); 35 | }); 36 | }); 37 | 38 | describe('replayTransaction', () => { 39 | it('returns traces for a specific transaction', () => { 40 | return ethapi.eth.getBlockByNumber().then((latestBlock) => { 41 | return ethapi.trace.replayTransaction(latestBlock.transactions[0]).then((traces) => { 42 | expect(traces).to.be.ok; 43 | }); 44 | }); 45 | }); 46 | }); 47 | }); 48 | -------------------------------------------------------------------------------- /src/rpc/trace/trace.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { inBlockNumber, inData, inHex, inNumber16, inOptions, inTraceFilter, inTraceType } = require('../../format/input'); 18 | const { outTraces, outTraceReplay } = require('../../format/output'); 19 | 20 | class Trace { 21 | constructor (provider) { 22 | this._provider = provider; 23 | } 24 | 25 | block (blockNumber = 'latest') { 26 | return this._provider 27 | .send('trace_block', inBlockNumber(blockNumber)) 28 | .then(outTraces); 29 | } 30 | 31 | call (options, whatTrace = ['trace'], blockNumber = 'latest') { 32 | return this._provider 33 | .send('trace_call', inOptions(options), inTraceType(whatTrace), inBlockNumber(blockNumber)) 34 | .then(outTraceReplay); 35 | } 36 | 37 | filter (filterObj) { 38 | return this._provider 39 | .send('trace_filter', inTraceFilter(filterObj)) 40 | .then(outTraces); 41 | } 42 | 43 | get (txHash, position) { 44 | return this._provider 45 | .send('trace_get', inHex(txHash), inNumber16(position)) 46 | .then(outTraces); 47 | } 48 | 49 | rawTransaction (data, whatTrace = ['trace']) { 50 | return this._provider 51 | .send('trace_rawTransaction', inData(data), inTraceType(whatTrace)) 52 | .then(outTraceReplay); 53 | } 54 | 55 | replayTransaction (txHash, whatTrace = ['trace']) { 56 | return this._provider 57 | .send('trace_replayTransaction', txHash, inTraceType(whatTrace)) 58 | .then(outTraceReplay); 59 | } 60 | 61 | transaction (txHash) { 62 | return this._provider 63 | .send('trace_transaction', inHex(txHash)) 64 | .then(outTraces); 65 | } 66 | } 67 | 68 | module.exports = Trace; 69 | -------------------------------------------------------------------------------- /src/rpc/trace/trace.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 18 | 19 | const { Http, PromiseProvider } = require('../../provider'); 20 | const Trace = require('./trace'); 21 | 22 | const instance = new Trace(new PromiseProvider(new Http(TEST_HTTP_URL, -1))); 23 | 24 | describe('rpc/Trace', () => { 25 | let scope; 26 | 27 | describe('block', () => { 28 | beforeEach(() => { 29 | scope = mockHttp([{ method: 'trace_block', reply: { result: [] } }]); 30 | }); 31 | 32 | it('assumes latest blockNumber when not specified', () => { 33 | return instance.block().then(() => { 34 | expect(scope.body.trace_block.params).to.deep.equal(['latest']); 35 | }); 36 | }); 37 | 38 | it('passed specified blockNumber', () => { 39 | return instance.block(0x123).then(() => { 40 | expect(scope.body.trace_block.params).to.deep.equal(['0x123']); 41 | }); 42 | }); 43 | }); 44 | }); 45 | -------------------------------------------------------------------------------- /src/rpc/web3/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Web3 = require('./web3'); 18 | 19 | module.exports = Web3; 20 | -------------------------------------------------------------------------------- /src/rpc/web3/web3.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { createHttpApi } = require('../../test/e2e/ethapi'); 20 | const { isHexNumber } = require('../../test/types'); 21 | 22 | describe('ethapi.web3', () => { 23 | const ethapi = createHttpApi(); 24 | 25 | describe('clientVersion', () => { 26 | it('returns the client version', () => { 27 | return ethapi.web3.clientVersion().then((version) => { 28 | const [client] = version.split('/'); 29 | 30 | expect(client === 'Parity' || client === 'Geth').to.be.ok; 31 | }); 32 | }); 33 | }); 34 | 35 | describe('sha3', () => { 36 | it('returns a keccak256 sha', () => { 37 | const sha = '0xa7916fac4f538170f7cd12c148552e2cba9fcd72329a2dd5b07a6fa906488ddf'; 38 | const hexStr = 'baz()'.split('').map((char) => char.charCodeAt(0).toString(16)).join(''); 39 | 40 | return ethapi.web3.sha3(`0x${hexStr}`).then((hash) => { 41 | expect(isHexNumber(hash)).to.be.true; 42 | expect(hash).to.equal(sha); 43 | }); 44 | }); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /src/rpc/web3/web3.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { inHex } = require('../../format/input'); 18 | 19 | class Web3 { 20 | constructor (provider) { 21 | this._provider = provider; 22 | } 23 | 24 | clientVersion () { 25 | return this._provider 26 | .send('web3_clientVersion'); 27 | } 28 | 29 | sha3 (hexStr) { 30 | return this._provider 31 | .send('web3_sha3', inHex(hexStr)); 32 | } 33 | } 34 | 35 | module.exports = Web3; 36 | -------------------------------------------------------------------------------- /src/rpc/web3/web3.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 18 | 19 | const { Http, PromiseProvider } = require('../../provider'); 20 | const Web3 = require('./web3'); 21 | 22 | const instance = new Web3(new PromiseProvider(new Http(TEST_HTTP_URL, -1))); 23 | 24 | describe('rpc/Web3', () => { 25 | let scope; 26 | 27 | describe('sha3', () => { 28 | beforeEach(() => { 29 | scope = mockHttp([{ method: 'web3_sha3', reply: { result: [] } }]); 30 | }); 31 | 32 | it('formats the inputs correctly', () => { 33 | return instance.sha3('1234').then(() => { 34 | expect(scope.body.web3_sha3.params).to.deep.equal(['0x1234']); 35 | }); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /src/subscriptions/eth.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const BigNumber = require('bignumber.js'); 18 | 19 | class Eth { 20 | constructor (updateSubscriptions, api) { 21 | this._api = api; 22 | this._updateSubscriptions = updateSubscriptions; 23 | this._started = false; 24 | 25 | this._lastBlock = new BigNumber(-1); 26 | this._pollTimerId = null; 27 | this._pollBlockNumber = this._pollBlockNumber.bind(this); 28 | 29 | this._api.provider.on('close', () => { 30 | if (this.isStarted) { 31 | this.start(); 32 | } 33 | }); 34 | } 35 | 36 | get isStarted () { 37 | return this._started; 38 | } 39 | 40 | start () { 41 | this._started = true; 42 | 43 | if (this._api.isPubSub) { 44 | return Promise.all([ 45 | this._pollBlockNumber(false), 46 | this._api.pubsub 47 | .subscribeAndGetResult( 48 | (callback) => this._api.pubsub.eth.newHeads(callback), 49 | () => { 50 | return this._api.eth 51 | .blockNumber() 52 | .then((blockNumber) => { 53 | this.updateBlock(blockNumber); 54 | return blockNumber; 55 | }); 56 | } 57 | ) 58 | ]); 59 | } 60 | 61 | return this._pollBlockNumber(true); 62 | } 63 | 64 | _pollBlockNumber (doTimeout) { 65 | const nextTimeout = (timeout = 1000, forceTimeout = doTimeout) => { 66 | if (forceTimeout) { 67 | this._pollTimerId = setTimeout(() => { 68 | this._pollBlockNumber(doTimeout); 69 | }, timeout); 70 | } 71 | }; 72 | 73 | if (!this._api.provider.isConnected) { 74 | nextTimeout(500, true); 75 | return; 76 | } 77 | 78 | return this._api.eth 79 | .blockNumber() 80 | .then((blockNumber) => { 81 | this.updateBlock(blockNumber); 82 | 83 | nextTimeout(); 84 | }) 85 | .catch(() => nextTimeout()); 86 | } 87 | 88 | updateBlock (blockNumber) { 89 | if (!blockNumber.eq(this._lastBlock)) { 90 | this._lastBlock = blockNumber; 91 | this._updateSubscriptions('eth_blockNumber', null, blockNumber); 92 | } 93 | } 94 | } 95 | 96 | module.exports = Eth; 97 | -------------------------------------------------------------------------------- /src/subscriptions/eth.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const BigNumber = require('bignumber.js'); 20 | const sinon = require('sinon'); 21 | 22 | const Eth = require('./eth'); 23 | 24 | const START_BLOCK = 5000; 25 | 26 | function stubApi (blockNumber) { 27 | const _calls = { 28 | blockNumber: [] 29 | }; 30 | 31 | return { 32 | _calls, 33 | provider: { 34 | isConnected: true, 35 | on: () => {} 36 | }, 37 | eth: { 38 | blockNumber: () => { 39 | const stub = sinon.stub().resolves(new BigNumber(blockNumber || START_BLOCK))(); 40 | 41 | _calls.blockNumber.push(stub); 42 | return stub; 43 | } 44 | } 45 | }; 46 | } 47 | 48 | describe('subscriptions/eth', () => { 49 | let api; 50 | let eth; 51 | let cb; 52 | 53 | beforeEach(() => { 54 | api = stubApi(); 55 | cb = sinon.stub(); 56 | eth = new Eth(cb, api); 57 | }); 58 | 59 | describe('constructor', () => { 60 | it('starts the instance in a stopped state', () => { 61 | expect(eth.isStarted).to.be.false; 62 | }); 63 | }); 64 | 65 | describe('start', () => { 66 | describe('blockNumber available', () => { 67 | beforeEach(() => { 68 | return eth.start(); 69 | }); 70 | 71 | it('sets the started status', () => { 72 | expect(eth.isStarted).to.be.true; 73 | }); 74 | 75 | it('calls eth_blockNumber', () => { 76 | expect(api._calls.blockNumber.length).to.be.ok; 77 | }); 78 | 79 | it('updates subscribers', () => { 80 | expect(cb).to.have.been.calledWith('eth_blockNumber', null, new BigNumber(START_BLOCK)); 81 | }); 82 | }); 83 | 84 | describe('blockNumber not available', () => { 85 | beforeEach(() => { 86 | api = stubApi(-1); 87 | eth = new Eth(cb, api); 88 | return eth.start(); 89 | }); 90 | 91 | it('sets the started status', () => { 92 | expect(eth.isStarted).to.be.true; 93 | }); 94 | 95 | it('calls eth_blockNumber', () => { 96 | expect(api._calls.blockNumber.length).to.be.ok; 97 | }); 98 | 99 | it('does not update subscribers', () => { 100 | expect(cb).not.to.been.called; 101 | }); 102 | }); 103 | }); 104 | }); 105 | -------------------------------------------------------------------------------- /src/subscriptions/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Logging = require('./logging'); 18 | const Manager = require('./manager'); 19 | 20 | Manager.Logging = Logging; 21 | 22 | module.exports = Manager; 23 | -------------------------------------------------------------------------------- /src/subscriptions/logging.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | let instance = null; 18 | 19 | class Logging { 20 | constructor (updateSubscriptions) { 21 | this._updateSubscriptions = updateSubscriptions; 22 | 23 | instance = this; 24 | } 25 | 26 | get isStarted () { 27 | return true; 28 | } 29 | 30 | start () { 31 | } 32 | } 33 | 34 | Logging.send = function (method, params, json) { 35 | if (!instance) { 36 | return; 37 | } 38 | 39 | return instance._updateSubscriptions('logging', null, { 40 | method, 41 | params, 42 | json 43 | }); 44 | }; 45 | 46 | module.exports = Logging; 47 | -------------------------------------------------------------------------------- /src/subscriptions/logging.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const Logging = require('./logging'); 22 | 23 | describe('subscriptions/logging', () => { 24 | let cb; 25 | let logging; 26 | 27 | beforeEach(() => { 28 | cb = sinon.stub(); 29 | logging = new Logging(cb); 30 | }); 31 | 32 | describe('constructor', () => { 33 | it('starts the instance in a started state', () => { 34 | expect(logging.isStarted).to.be.true; 35 | }); 36 | }); 37 | 38 | describe('send', () => { 39 | const method = 'method'; 40 | const params = 'params'; 41 | const json = 'json'; 42 | 43 | beforeEach(() => { 44 | Logging.send(method, params, json); 45 | }); 46 | 47 | it('calls the subscription update', () => { 48 | expect(cb).to.have.been.calledWith('logging', null, { method, params, json }); 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /src/subscriptions/manager.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { isError } = require('../util/types'); 18 | 19 | const Eth = require('./eth'); 20 | const Logging = require('./logging'); 21 | const Personal = require('./personal'); 22 | const Signer = require('./signer'); 23 | 24 | const events = { 25 | 'logging': { module: 'logging' }, 26 | 'eth_blockNumber': { module: 'eth' }, 27 | 'parity_accountsInfo': { module: 'personal' }, 28 | 'parity_allAccountsInfo': { module: 'personal' }, 29 | 'parity_defaultAccount': { module: 'personal' }, 30 | 'parity_postTransaction': { module: 'signer' }, 31 | 'eth_accounts': { module: 'personal' }, 32 | 'signer_requestsToConfirm': { module: 'signer' } 33 | }; 34 | 35 | class Manager { 36 | constructor (api) { 37 | this._api = api; 38 | 39 | this.subscriptions = []; 40 | this.values = {}; 41 | 42 | Object.keys(events).forEach((subscriptionName) => { 43 | this.values[subscriptionName] = { 44 | error: null, 45 | data: null 46 | }; 47 | }); 48 | 49 | // in the case of a pubsub compliant, don't use the engines 50 | if (this._api.isPubSub) { 51 | return; 52 | } 53 | 54 | this._updateSubscriptions = this._updateSubscriptions.bind(this); 55 | 56 | this._logging = new Logging(this._updateSubscriptions); 57 | this._eth = new Eth(this._updateSubscriptions, api); 58 | this._personal = new Personal(this._updateSubscriptions, api, this); 59 | this._signer = new Signer(this._updateSubscriptions, api, this); 60 | } 61 | 62 | _validateType (subscriptionName) { 63 | const subscription = events[subscriptionName]; 64 | 65 | if (!subscription) { 66 | return new Error(`${subscriptionName} is not a valid interface, subscribe using one of ${Object.keys(events).join(', ')}`); 67 | } 68 | 69 | return subscription; 70 | } 71 | 72 | subscribe (subscriptionName, callback, autoRemove = false) { 73 | return new Promise((resolve, reject) => { 74 | const subscription = this._validateType(subscriptionName); 75 | 76 | if (isError(subscription)) { 77 | reject(subscription); 78 | return; 79 | } 80 | 81 | // use normal pub-sub as available 82 | if (this._api.isPubSub) { 83 | try { 84 | const [fnSection, fnName] = subscriptionName.split('_'); 85 | 86 | resolve(this._api.pubsub[fnSection][fnName](callback)); 87 | } catch (error) { 88 | console.error('Unable to find subscriptionName', subscriptionName); 89 | reject(error); 90 | } 91 | 92 | return; 93 | } 94 | 95 | const subscriptionId = this.subscriptions.length; 96 | const { error, data } = this.values[subscriptionName]; 97 | const engine = this[`_${subscription.module}`]; 98 | 99 | this.subscriptions[subscriptionId] = { 100 | name: subscriptionName, 101 | id: subscriptionId, 102 | autoRemove, 103 | callback 104 | }; 105 | 106 | if (!engine.isStarted) { 107 | engine.start(); 108 | } else if (error !== null || data !== null) { 109 | this._sendData(subscriptionId, error, data); 110 | } 111 | 112 | resolve(subscriptionId); 113 | }); 114 | } 115 | 116 | unsubscribe (subscriptionId) { 117 | if (this._api.isPubSub) { 118 | return this._api.pubsub.unsubscribe(subscriptionId); 119 | } 120 | 121 | return new Promise((resolve, reject) => { 122 | if (!this.subscriptions[subscriptionId]) { 123 | reject(new Error(`Cannot find subscription ${subscriptionId}`)); 124 | return; 125 | } 126 | 127 | delete this.subscriptions[subscriptionId]; 128 | resolve(); 129 | }); 130 | } 131 | 132 | _sendData (subscriptionId, error, data) { 133 | const { autoRemove, callback } = this.subscriptions[subscriptionId]; 134 | let result = true; 135 | 136 | try { 137 | result = callback(error, data); 138 | } catch (error) { 139 | console.error(`Unable to update callback for subscriptionId ${subscriptionId}`, error); 140 | } 141 | 142 | if (autoRemove && result && typeof result === 'boolean') { 143 | this.unsubscribe(subscriptionId); 144 | } 145 | } 146 | 147 | _updateSubscriptions (subscriptionName, error, data) { 148 | const subscriptions = this.subscriptions 149 | .filter(subscription => subscription.name === subscriptionName); 150 | 151 | this.values[subscriptionName] = { error, data }; 152 | 153 | subscriptions 154 | .forEach((subscription) => { 155 | this._sendData(subscription.id, error, data); 156 | }); 157 | } 158 | } 159 | 160 | Manager.events = events; 161 | 162 | module.exports = Manager; 163 | -------------------------------------------------------------------------------- /src/subscriptions/manager.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const Manager = require('./manager'); 22 | 23 | const events = Manager.events; 24 | 25 | function newStub () { 26 | const start = () => manager._updateSubscriptions(manager.__test, null, 'test'); 27 | 28 | const manager = new Manager({ 29 | provider: { 30 | isConnected: true, 31 | on: sinon.stub() 32 | } 33 | }); 34 | 35 | manager._eth = { 36 | isStarted: false, 37 | start 38 | }; 39 | 40 | manager._personal = { 41 | isStarted: false, 42 | start 43 | }; 44 | 45 | manager._signer = { 46 | isStarted: false, 47 | start 48 | }; 49 | 50 | return manager; 51 | } 52 | 53 | describe('subscriptions/manager', () => { 54 | let manager; 55 | 56 | beforeEach(() => { 57 | manager = newStub(); 58 | }); 59 | 60 | describe('constructor', () => { 61 | it('sets up the subscription types & defaults', () => { 62 | expect(manager.subscriptions).to.be.an.array; 63 | expect(Object.keys(manager.values)).to.deep.equal(Object.keys(events)); 64 | }); 65 | }); 66 | 67 | describe('subscriptions', () => { 68 | Object 69 | .keys(events) 70 | .filter((eventName) => eventName.indexOf('_') !== -1) 71 | .forEach((eventName) => { 72 | const { module } = events[eventName]; 73 | let engine; 74 | let cb; 75 | let subscriptionId; 76 | 77 | describe(eventName, () => { 78 | beforeEach(() => { 79 | engine = manager[`_${module}`]; 80 | manager.__test = eventName; 81 | cb = sinon.stub(); 82 | sinon.spy(engine, 'start'); 83 | 84 | return manager 85 | .subscribe(eventName, cb) 86 | .then((_subscriptionId) => { 87 | subscriptionId = _subscriptionId; 88 | }); 89 | }); 90 | 91 | it(`puts the ${module} engine in a started state`, () => { 92 | expect(engine.start).to.have.been.called; 93 | }); 94 | 95 | it('returns a subscriptionId', () => { 96 | expect(subscriptionId).to.be.a.number; 97 | }); 98 | 99 | it('calls the subscription callback with updated values', () => { 100 | expect(cb).to.have.been.calledWith(null, 'test'); 101 | }); 102 | }); 103 | }); 104 | }); 105 | 106 | describe('unsubscriptions', () => { 107 | Object 108 | .keys(events) 109 | .filter((eventName) => eventName.indexOf('_') !== -1) 110 | .forEach((eventName) => { 111 | const { module } = events[eventName]; 112 | let engine; 113 | let cb; 114 | 115 | describe(eventName, () => { 116 | beforeEach(() => { 117 | engine = manager[`_${module}`]; 118 | manager.__test = eventName; 119 | cb = sinon.stub(); 120 | sinon.spy(engine, 'start'); 121 | 122 | return manager 123 | .subscribe(eventName, cb) 124 | .then((_subscriptionId) => { 125 | manager.unsubscribe(_subscriptionId); 126 | }) 127 | .then(() => { 128 | manager._updateSubscriptions(manager.__test, null, 'test2'); 129 | }); 130 | }); 131 | 132 | it('does not call the callback after unsubscription', () => { 133 | expect(cb).to.have.been.calledWith(null, 'test'); 134 | expect(cb).to.not.have.been.calledWith(null, 'test2'); 135 | }); 136 | }); 137 | }); 138 | }); 139 | }); 140 | -------------------------------------------------------------------------------- /src/subscriptions/personal.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | class Personal { 18 | constructor (updateSubscriptions, api, subscriber) { 19 | this._subscriber = subscriber; 20 | this._api = api; 21 | this._updateSubscriptions = updateSubscriptions; 22 | this._started = false; 23 | 24 | this._lastDefaultAccount = '0x0'; 25 | this._pollTimerId = null; 26 | 27 | this._accountsInfo = this._accountsInfo.bind(this); 28 | this._defaultAccount = this._defaultAccount.bind(this); 29 | this._listAccounts = this._listAccounts.bind(this); 30 | 31 | this._api.provider.on('close', () => { 32 | if (this.isStarted) { 33 | this.start(); 34 | } 35 | }); 36 | } 37 | 38 | get isStarted () { 39 | return this._started; 40 | } 41 | 42 | start () { 43 | this._started = true; 44 | 45 | let defaultAccount = null; 46 | 47 | if (this._api.isPubSub) { 48 | defaultAccount = this._api.pubsub 49 | .subscribeAndGetResult( 50 | callback => this._api.pubsub.parity.defaultAccount(callback), 51 | (defaultAccount) => { 52 | this.updateDefaultAccount(defaultAccount); 53 | return defaultAccount; 54 | } 55 | ); 56 | } else { 57 | defaultAccount = this._defaultAccount(); 58 | } 59 | 60 | return Promise.all([ 61 | defaultAccount, 62 | this._listAccounts(), 63 | this._accountsInfo(), 64 | this._loggingSubscribe() 65 | ]); 66 | } 67 | 68 | updateDefaultAccount (defaultAccount) { 69 | if (this._lastDefaultAccount !== defaultAccount) { 70 | this._lastDefaultAccount = defaultAccount; 71 | this._updateSubscriptions('parity_defaultAccount', null, defaultAccount); 72 | } 73 | } 74 | 75 | // FIXME: Because of the different API instances, the "wait for valid changes" approach 76 | // doesn't work. Since the defaultAccount is critical to operation, we poll in exactly 77 | // same way we do in ../eth (ala eth_blockNumber) and update. This should be moved 78 | // to pub-sub as it becomes available 79 | _defaultAccount (timerDisabled = false) { 80 | const nextTimeout = (timeout = 3000) => { 81 | if (!timerDisabled) { 82 | this._pollTimerId = setTimeout(() => { 83 | this._defaultAccount(); 84 | }, timeout); 85 | } 86 | }; 87 | 88 | if (!this._api.isConnected) { 89 | nextTimeout(500); 90 | return; 91 | } 92 | 93 | return this._api.parity 94 | .defaultAccount() 95 | .then((defaultAccount) => { 96 | this.updateDefaultAccount(defaultAccount); 97 | nextTimeout(); 98 | }) 99 | .catch(() => nextTimeout()); 100 | } 101 | 102 | _listAccounts () { 103 | return this._api.eth 104 | .accounts() 105 | .then((accounts) => { 106 | this._updateSubscriptions('eth_accounts', null, accounts); 107 | }); 108 | } 109 | 110 | _accountsInfo () { 111 | return this._api.parity 112 | .accountsInfo() 113 | .then((info) => { 114 | this._updateSubscriptions('parity_accountsInfo', null, info); 115 | 116 | return this._api.parity 117 | .allAccountsInfo() 118 | .catch(() => { 119 | // NOTE: This fails on non-secure APIs, swallow error 120 | return {}; 121 | }) 122 | .then((allInfo) => { 123 | this._updateSubscriptions('parity_allAccountsInfo', null, allInfo); 124 | }); 125 | }); 126 | } 127 | 128 | _loggingSubscribe () { 129 | return this._subscriber.subscribe('logging', (error, data) => { 130 | if (error || !data) { 131 | return; 132 | } 133 | 134 | switch (data.method) { 135 | case 'parity_closeVault': 136 | case 'parity_openVault': 137 | case 'parity_killAccount': 138 | case 'parity_importGethAccounts': 139 | case 'parity_newAccountFromPhrase': 140 | case 'parity_newAccountFromWallet': 141 | case 'personal_newAccount': 142 | this._defaultAccount(true); 143 | this._listAccounts(); 144 | this._accountsInfo(); 145 | break; 146 | 147 | case 'parity_removeAddress': 148 | case 'parity_setAccountName': 149 | case 'parity_setAccountMeta': 150 | this._accountsInfo(); 151 | break; 152 | 153 | case 'parity_setDappAddresses': 154 | case 'parity_setDappDefaultAddress': 155 | case 'parity_setNewDappsAddresses': 156 | case 'parity_setNewDappsDefaultAddress': 157 | this._defaultAccount(true); 158 | this._listAccounts(); 159 | break; 160 | } 161 | }); 162 | } 163 | } 164 | 165 | module.exports = Personal; 166 | -------------------------------------------------------------------------------- /src/subscriptions/personal.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const Personal = require('./personal'); 22 | 23 | const TEST_DEFAULT = '0xfa64203C044691aA57251aF95f4b48d85eC00Dd5'; 24 | const TEST_INFO = { 25 | [TEST_DEFAULT]: { 26 | name: 'test' 27 | } 28 | }; 29 | const TEST_LIST = [TEST_DEFAULT]; 30 | 31 | function stubApi (accounts, info) { 32 | const _calls = { 33 | accountsInfo: [], 34 | allAccountsInfo: [], 35 | listAccounts: [], 36 | defaultAccount: [] 37 | }; 38 | 39 | return { 40 | _calls, 41 | isConnected: true, 42 | provider: { 43 | isConnected: true, 44 | on: sinon.stub() 45 | }, 46 | parity: { 47 | accountsInfo: () => { 48 | const stub = sinon.stub().resolves(info || TEST_INFO)(); 49 | 50 | _calls.accountsInfo.push(stub); 51 | return stub; 52 | }, 53 | allAccountsInfo: () => { 54 | const stub = sinon.stub().resolves(info || TEST_INFO)(); 55 | 56 | _calls.allAccountsInfo.push(stub); 57 | return stub; 58 | }, 59 | defaultAccount: () => { 60 | const stub = sinon.stub().resolves(Object.keys(info || TEST_INFO)[0])(); 61 | 62 | _calls.defaultAccount.push(stub); 63 | return stub; 64 | } 65 | }, 66 | eth: { 67 | accounts: () => { 68 | const stub = sinon.stub().resolves(accounts || TEST_LIST)(); 69 | 70 | _calls.listAccounts.push(stub); 71 | return stub; 72 | } 73 | } 74 | }; 75 | } 76 | 77 | function stubLogging () { 78 | return { 79 | subscribe: sinon.stub() 80 | }; 81 | } 82 | 83 | describe('subscriptions/personal', () => { 84 | let api; 85 | let cb; 86 | let logging; 87 | let personal; 88 | 89 | beforeEach(() => { 90 | api = stubApi(); 91 | cb = sinon.stub(); 92 | logging = stubLogging(); 93 | personal = new Personal(cb, api, logging); 94 | }); 95 | 96 | describe('constructor', () => { 97 | it('starts the instance in a stopped state', () => { 98 | expect(personal.isStarted).to.be.false; 99 | }); 100 | }); 101 | 102 | describe('start', () => { 103 | describe('info available', () => { 104 | beforeEach(() => { 105 | return personal.start(); 106 | }); 107 | 108 | it('sets the started status', () => { 109 | expect(personal.isStarted).to.be.true; 110 | }); 111 | 112 | it('calls parity_accountsInfo', () => { 113 | expect(api._calls.accountsInfo.length).to.be.ok; 114 | }); 115 | 116 | it('calls parity_allAccountsInfo', () => { 117 | expect(api._calls.allAccountsInfo.length).to.be.ok; 118 | }); 119 | 120 | it('calls eth_accounts', () => { 121 | expect(api._calls.listAccounts.length).to.be.ok; 122 | }); 123 | 124 | it('updates subscribers', () => { 125 | expect(cb).to.have.been.calledWith('parity_defaultAccount', null, TEST_DEFAULT); 126 | expect(cb).to.have.been.calledWith('eth_accounts', null, TEST_LIST); 127 | expect(cb).to.have.been.calledWith('parity_accountsInfo', null, TEST_INFO); 128 | expect(cb).to.have.been.calledWith('parity_allAccountsInfo', null, TEST_INFO); 129 | }); 130 | }); 131 | 132 | describe('info not available', () => { 133 | beforeEach(() => { 134 | api = stubApi([], {}); 135 | personal = new Personal(cb, api, logging); 136 | return personal.start(); 137 | }); 138 | 139 | it('sets the started status', () => { 140 | expect(personal.isStarted).to.be.true; 141 | }); 142 | 143 | it('calls parity_defaultAccount', () => { 144 | expect(api._calls.defaultAccount.length).to.be.ok; 145 | }); 146 | 147 | it('calls personal_accountsInfo', () => { 148 | expect(api._calls.accountsInfo.length).to.be.ok; 149 | }); 150 | 151 | it('calls personal_allAccountsInfo', () => { 152 | expect(api._calls.allAccountsInfo.length).to.be.ok; 153 | }); 154 | 155 | it('calls personal_listAccounts', () => { 156 | expect(api._calls.listAccounts.length).to.be.ok; 157 | }); 158 | }); 159 | }); 160 | }); 161 | -------------------------------------------------------------------------------- /src/subscriptions/signer.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { outTransaction } = require('../format/output'); 18 | 19 | class Signer { 20 | constructor (updateSubscriptions, api, subscriber) { 21 | this._subscriber = subscriber; 22 | this._api = api; 23 | this._updateSubscriptions = updateSubscriptions; 24 | this._started = false; 25 | 26 | this._listRequests = this._listRequests.bind(this); 27 | 28 | this._api.provider.on('close', () => { 29 | if (this.isStarted) { 30 | this.start(); 31 | } 32 | }); 33 | } 34 | 35 | get isStarted () { 36 | return this._started; 37 | } 38 | 39 | start () { 40 | this._started = true; 41 | 42 | if (this._api.isPubSub) { 43 | const subscription = this._api.pubsub 44 | .subscribeAndGetResult( 45 | callback => this._api.pubsub.signer.pendingRequests(callback), 46 | requests => { 47 | this.updateSubscriptions(requests); 48 | return requests; 49 | } 50 | ); 51 | 52 | return Promise.all([ 53 | this._listRequests(false), 54 | subscription 55 | ]); 56 | } 57 | 58 | return Promise.all([ 59 | this._listRequests(true), 60 | this._loggingSubscribe() 61 | ]); 62 | } 63 | 64 | updateSubscriptions (requests) { 65 | return this._updateSubscriptions('signer_requestsToConfirm', null, requests); 66 | } 67 | 68 | _listRequests (doTimeout) { 69 | const nextTimeout = (timeout = 1000, forceTimeout = doTimeout) => { 70 | if (forceTimeout) { 71 | setTimeout(() => { 72 | this._listRequests(doTimeout); 73 | }, timeout); 74 | } 75 | }; 76 | 77 | if (!this._api.isConnected) { 78 | nextTimeout(500, true); 79 | return; 80 | } 81 | 82 | return this._api.signer 83 | .requestsToConfirm() 84 | .then((requests) => { 85 | this.updateSubscriptions(requests); 86 | nextTimeout(); 87 | }) 88 | .catch(() => nextTimeout()); 89 | } 90 | 91 | _postTransaction (data) { 92 | const request = { 93 | transaction: outTransaction(data.params[0]), 94 | requestId: data.json.result.result 95 | }; 96 | 97 | this._updateSubscriptions('parity_postTransaction', null, request); 98 | } 99 | 100 | _loggingSubscribe () { 101 | return this._subscriber.subscribe('logging', (error, data) => { 102 | if (error || !data) { 103 | return; 104 | } 105 | 106 | switch (data.method) { 107 | case 'eth_sendTransaction': 108 | case 'eth_sendRawTransaction': 109 | this._listRequests(false); 110 | break; 111 | 112 | case 'parity_postTransaction': 113 | this._postTransaction(data); 114 | this._listRequests(false); 115 | break; 116 | } 117 | }); 118 | } 119 | } 120 | 121 | module.exports = Signer; 122 | -------------------------------------------------------------------------------- /src/transport/error.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const ExtendableError = require('es6-error'); 18 | 19 | const ERROR_CODES = { 20 | UNSUPPORTED_REQUEST: -32000, 21 | NO_WORK: -32001, 22 | NO_AUTHOR: -32002, 23 | NO_NEW_WORK: -32003, 24 | NO_WORK_REQUIRED: -32004, 25 | NOT_ENOUGH_DATA: -32006, 26 | UNKNOWN_ERROR: -32009, 27 | TRANSACTION_ERROR: -32010, 28 | EXECUTION_ERROR: -32015, 29 | EXCEPTION_ERROR: -32016, 30 | ACCOUNT_LOCKED: -32020, 31 | PASSWORD_INVALID: -32021, 32 | ACCOUNT_ERROR: -32023, 33 | SIGNER_DISABLED: -32030, 34 | DAPPS_DISABLED: -32031, 35 | NETWORK_DISABLED: -32035, 36 | REQUEST_REJECTED: -32040, 37 | REQUEST_REJECTED_LIMIT: -32041, 38 | REQUEST_NOT_FOUND: -32042, 39 | COMPILATION_ERROR: -32050, 40 | ENCRYPTION_ERROR: -32055, 41 | FETCH_ERROR: -32060, 42 | INVALID_PARAMS: -32602 43 | }; 44 | 45 | class TransportError extends ExtendableError { 46 | constructor (method, code, message) { 47 | const m = `${method}: ${code}: ${message}`; 48 | 49 | super(m); 50 | 51 | this.code = code; 52 | this.type = Object 53 | .keys(ERROR_CODES) 54 | .find((key) => ERROR_CODES[key] === code) || ''; 55 | 56 | this.method = method; 57 | this.text = message; 58 | } 59 | } 60 | 61 | TransportError.ERROR_CODES = ERROR_CODES; 62 | 63 | TransportError.requestRejected = function (method = null) { 64 | return new TransportError(method, ERROR_CODES.REQUEST_REJECTED, 'Request has been rejected.'); 65 | }; 66 | 67 | module.exports = TransportError; 68 | -------------------------------------------------------------------------------- /src/transport/error.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const TransportError = require('./error'); 18 | 19 | describe('transport/Error', () => { 20 | describe('requestRejected', () => { 21 | it('creates a Request Rejected error', () => { 22 | const error = TransportError.requestRejected('method'); 23 | 24 | expect(error.code).to.equal(TransportError.ERROR_CODES.REQUEST_REJECTED); 25 | expect(error.message).to.match(/been rejected/); 26 | expect(error.method).to.equal('method'); 27 | }); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /src/transport/http/http.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const Http = require('./http'); 20 | 21 | const http = new Http('http://localhost:8545'); 22 | 23 | describe('transport/Http', () => { 24 | it('connects and makes a call to web3_clientVersion', () => { 25 | return http.execute('web3_clientVersion').then((version) => { 26 | const [client] = version.split('/'); 27 | 28 | expect(client === 'Geth' || client === 'Parity').to.be.ok; 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/transport/http/http.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { Logging } = require('../../subscriptions'); 18 | const JsonRpcBase = require('../jsonRpcBase'); 19 | const TransportError = require('../error'); 20 | 21 | /* global fetch */ 22 | class Http extends JsonRpcBase { 23 | constructor (url, connectTimeout = 1000) { 24 | super(); 25 | 26 | this._connected = true; 27 | this._url = url; 28 | this._connectTimeout = connectTimeout; 29 | 30 | this._pollConnection = this._pollConnection.bind(this); 31 | this._pollConnection(); 32 | } 33 | 34 | _encodeOptions (method, params) { 35 | const json = this.encode(method, params); 36 | 37 | this.log(json); 38 | 39 | return { 40 | method: 'POST', 41 | headers: { 42 | 'Accept': 'application/json', 43 | 'Content-Type': 'application/json', 44 | 'Content-Length': json.length 45 | }, 46 | body: json 47 | }; 48 | } 49 | 50 | _execute (method, params) { 51 | const request = this._encodeOptions(method, params); 52 | 53 | return fetch(this._url, request) 54 | .catch((error) => { 55 | this._setDisconnected(); 56 | throw error; 57 | }) 58 | .then((response) => { 59 | this._setConnected(); 60 | 61 | if (response.status !== 200) { 62 | this._setDisconnected(); 63 | this.error(JSON.stringify({ status: response.status, statusText: response.statusText })); 64 | console.error(`${method}(${JSON.stringify(params)}): ${response.status}: ${response.statusText}`); 65 | 66 | throw new Error(`${response.status}: ${response.statusText}`); 67 | } 68 | 69 | return response.json(); 70 | }) 71 | .then((response) => { 72 | Logging.send(method, params, { request, response }); 73 | 74 | if (response.error) { 75 | this.error(JSON.stringify(response)); 76 | console.error(`${method}(${JSON.stringify(params)}): ${response.error.code}: ${response.error.message}`); 77 | 78 | const error = new TransportError(method, response.error.code, response.error.message); 79 | 80 | throw error; 81 | } 82 | 83 | this.log(JSON.stringify(response)); 84 | return response.result; 85 | }); 86 | } 87 | 88 | _pollConnection () { 89 | if (this._connectTimeout <= 0) { 90 | return; 91 | } 92 | 93 | const nextTimeout = () => setTimeout(this._pollConnection, this._connectTimeout); 94 | 95 | this 96 | .execute('net_listening') 97 | .then(() => nextTimeout()) 98 | .catch(() => nextTimeout()); 99 | } 100 | 101 | set url (url) { 102 | this._url = url; 103 | } 104 | } 105 | 106 | module.exports = Http; 107 | -------------------------------------------------------------------------------- /src/transport/http/http.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { TEST_HTTP_URL, mockHttp } = require('../../../test/mockRpc'); 20 | const Http = require('./http'); 21 | 22 | const transport = new Http(TEST_HTTP_URL, -1); 23 | 24 | describe('transport/Http', () => { 25 | describe('instance', () => { 26 | it('encodes the options correctly', () => { 27 | const opt = transport._encodeOptions('someMethod', ['param']); 28 | const enc = { 29 | method: 'POST', 30 | headers: { 31 | 'Accept': 'application/json', 32 | 'Content-Type': 'application/json', 33 | 'Content-Length': 65 34 | }, 35 | body: `{"id":${transport._id - 1},"jsonrpc":"2.0","method":"someMethod","params":["param"]}` 36 | }; 37 | 38 | expect(opt).to.deep.equal(enc); 39 | }); 40 | }); 41 | 42 | describe('transport emitter', () => { 43 | it('emits close event', (done) => { 44 | transport.once('close', () => { 45 | done(); 46 | }); 47 | 48 | transport.execute('eth_call'); 49 | }); 50 | 51 | it('emits open event', (done) => { 52 | mockHttp([{ method: 'eth_call', reply: { result: '' } }]); 53 | 54 | transport.once('open', () => { 55 | done(); 56 | }); 57 | 58 | transport.execute('eth_call'); 59 | }); 60 | }); 61 | 62 | describe('transport', () => { 63 | const RESULT = ['this is some result']; 64 | 65 | let scope; 66 | let result; 67 | 68 | beforeEach(() => { 69 | scope = mockHttp([{ method: 'eth_call', reply: { result: RESULT } }]); 70 | 71 | return transport 72 | .execute('eth_call', [1, 2, 3, 'test']) 73 | .then((_result) => { 74 | result = _result; 75 | }); 76 | }); 77 | 78 | it('makes POST', () => { 79 | expect(scope.isDone()).to.be.true; 80 | }); 81 | 82 | it('sets jsonrpc', () => { 83 | expect(scope.body.eth_call.jsonrpc).to.equal('2.0'); 84 | }); 85 | 86 | it('sets the method', () => { 87 | expect(scope.body.eth_call.method).to.equal('eth_call'); 88 | }); 89 | 90 | it('passes the params', () => { 91 | expect(scope.body.eth_call.params).to.deep.equal([1, 2, 3, 'test']); 92 | }); 93 | 94 | it('increments the id', () => { 95 | expect(scope.body.eth_call.id).not.to.equal(0); 96 | }); 97 | 98 | it('passes the actual result back', () => { 99 | expect(result).to.deep.equal(RESULT); 100 | }); 101 | }); 102 | 103 | describe('HTTP errors', () => { 104 | let scope; 105 | let error; 106 | 107 | beforeEach(() => { 108 | scope = mockHttp([{ method: 'eth_call', reply: {}, code: 500 }]); 109 | 110 | return transport 111 | .execute('eth_call') 112 | .catch((_error) => { 113 | error = _error; 114 | }); 115 | }); 116 | 117 | it('returns HTTP errors as throws', () => { 118 | expect(scope.isDone()).to.be.true; 119 | expect(error.message).to.match(/Internal Server Error/); 120 | }); 121 | }); 122 | 123 | describe('RPC errors', () => { 124 | const ERROR = { code: -1, message: 'ERROR: RPC failure' }; 125 | 126 | let scope; 127 | let error; 128 | 129 | beforeEach(() => { 130 | scope = mockHttp([{ method: 'eth_call', reply: { error: ERROR } }]); 131 | 132 | return transport 133 | .execute('eth_call') 134 | .catch((_error) => { 135 | error = _error; 136 | }); 137 | }); 138 | 139 | it('returns RPC errors as throws', () => { 140 | expect(scope.isDone()).to.be.true; 141 | expect(error.message).to.match(/RPC failure/); 142 | }); 143 | }); 144 | }); 145 | -------------------------------------------------------------------------------- /src/transport/http/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Http = require('./http'); 18 | 19 | module.exports = Http; 20 | -------------------------------------------------------------------------------- /src/transport/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Ws = require('./ws'); 18 | 19 | const Http = require('./http'); 20 | const TransportError = require('./error'); 21 | const Middleware = require('./middleware'); 22 | 23 | const WsSecure = Ws; 24 | 25 | module.exports = { 26 | Http, 27 | Middleware, 28 | TransportError, 29 | Ws, 30 | WsSecure 31 | }; 32 | -------------------------------------------------------------------------------- /src/transport/jsonRpcBase.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const JsonRpcEncoder = require('./jsonRpcEncoder'); 18 | const { Logging } = require('../subscriptions'); 19 | 20 | class JsonRpcBase extends JsonRpcEncoder { 21 | constructor () { 22 | super(); 23 | 24 | this._debug = false; 25 | this._connected = false; 26 | this._middlewareList = Promise.resolve([]); 27 | } 28 | 29 | addMiddleware (Middleware) { 30 | this._middlewareList = Promise 31 | .all([ 32 | Middleware, 33 | this._middlewareList 34 | ]) 35 | .then(([Middleware, middlewareList]) => { 36 | // Do nothing if `handlerPromise` resolves to a null-y value. 37 | if (!Middleware) { 38 | return middlewareList; 39 | } 40 | 41 | // don't mutate the original array 42 | return middlewareList.concat([new Middleware(this)]); 43 | }); 44 | } 45 | 46 | _wrapSuccessResult (result) { 47 | return { 48 | id: this._id, 49 | jsonrpc: '2.0', 50 | result 51 | }; 52 | } 53 | 54 | _wrapErrorResult (error) { 55 | return { 56 | id: this._id, 57 | jsonrpc: '2.0', 58 | error: { 59 | code: error.code, 60 | message: error.text 61 | } 62 | }; 63 | } 64 | 65 | execute (method, params) { 66 | return this._middlewareList.then((middlewareList) => { 67 | for (const middleware of middlewareList) { 68 | const res = middleware.handle(method, params); 69 | 70 | if (res != null) { 71 | return Promise 72 | .resolve(res) 73 | .then((res) => { 74 | const result = this._wrapSuccessResult(res); 75 | const json = this.encode(method, params); 76 | 77 | Logging.send(method, params, { json, result }); 78 | 79 | return res; 80 | }); 81 | } 82 | } 83 | 84 | return this._execute(method, params); 85 | }); 86 | } 87 | 88 | _execute () { 89 | throw new Error('Missing implementation of JsonRpcBase#_execute'); 90 | } 91 | 92 | _setConnected () { 93 | if (!this._connected) { 94 | this._connected = true; 95 | this.emit('open'); 96 | } 97 | } 98 | 99 | _setDisconnected () { 100 | if (this._connected) { 101 | this._connected = false; 102 | this.emit('close'); 103 | } 104 | } 105 | 106 | get isDebug () { 107 | return this._debug; 108 | } 109 | 110 | get isConnected () { 111 | return this._connected; 112 | } 113 | 114 | setDebug (flag) { 115 | this._debug = flag; 116 | } 117 | 118 | error (error) { 119 | if (this.isDebug) { 120 | console.error(error); 121 | } 122 | } 123 | 124 | log (log) { 125 | if (this.isDebug) { 126 | console.log(log); 127 | } 128 | } 129 | } 130 | 131 | module.exports = JsonRpcBase; 132 | -------------------------------------------------------------------------------- /src/transport/jsonRpcBase.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const { isInstanceOf } = require('../util/types'); 22 | 23 | const JsonRpcBase = require('./jsonRpcBase'); 24 | 25 | const base = new JsonRpcBase(); 26 | 27 | describe('transport/JsonRpcBase', () => { 28 | describe('addMiddleware', () => { 29 | it('checks for Middleware null', (done) => { 30 | const base2 = new JsonRpcBase(); 31 | 32 | base2.addMiddleware(null); 33 | base2._middlewareList.then((list) => { 34 | expect(list).to.deep.equal([]); 35 | done(); 36 | }); 37 | }); 38 | 39 | it('intialises Middleware added', (done) => { 40 | const base2 = new JsonRpcBase(); 41 | 42 | class Middleware { 43 | constructor (parent) { 44 | expect(parent).to.equal(base2); 45 | } 46 | } 47 | 48 | base2.addMiddleware(Middleware); 49 | base2._middlewareList.then((list) => { 50 | expect(list.length).to.equal(1); 51 | expect(isInstanceOf(list[0], Middleware)).to.be.true; 52 | done(); 53 | }); 54 | }); 55 | }); 56 | 57 | describe('setDebug', () => { 58 | it('starts with disabled flag', () => { 59 | expect(base.isDebug).to.be.false; 60 | }); 61 | 62 | it('true flag switches on', () => { 63 | base.setDebug(true); 64 | expect(base.isDebug).to.be.true; 65 | }); 66 | 67 | it('false flag switches off', () => { 68 | base.setDebug(true); 69 | expect(base.isDebug).to.be.true; 70 | base.setDebug(false); 71 | expect(base.isDebug).to.be.false; 72 | }); 73 | 74 | describe('logging', () => { 75 | beforeEach(() => { 76 | sinon.spy(console, 'log'); 77 | sinon.spy(console, 'error'); 78 | }); 79 | 80 | afterEach(() => { 81 | console.log.restore(); 82 | console.error.restore(); 83 | }); 84 | 85 | it('does not log errors with flag off', () => { 86 | base.setDebug(false); 87 | base.log('error'); 88 | expect(console.log).to.not.be.called; 89 | }); 90 | 91 | it('does not log errors with flag off', () => { 92 | base.setDebug(false); 93 | base.error('error'); 94 | expect(console.error).to.not.be.called; 95 | }); 96 | 97 | it('does log errors with flag on', () => { 98 | base.setDebug(true); 99 | base.log('error'); 100 | expect(console.log).to.be.called; 101 | }); 102 | 103 | it('does log errors with flag on', () => { 104 | base.setDebug(true); 105 | base.error('error'); 106 | expect(console.error).to.be.called; 107 | }); 108 | }); 109 | }); 110 | }); 111 | -------------------------------------------------------------------------------- /src/transport/jsonRpcEncoder.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const EventEmitter = require('eventemitter3'); 18 | 19 | class JsonRpcEncoder extends EventEmitter { 20 | constructor () { 21 | super(); 22 | 23 | this._id = 1; 24 | } 25 | 26 | encodeObject (method, params) { 27 | return { 28 | id: this._id++, 29 | jsonrpc: '2.0', 30 | method: method, 31 | params: params 32 | }; 33 | } 34 | 35 | encode (method, params) { 36 | return JSON.stringify(this.encodeObject(method, params)); 37 | } 38 | 39 | get id () { 40 | return this._id; 41 | } 42 | } 43 | 44 | module.exports = JsonRpcEncoder; 45 | -------------------------------------------------------------------------------- /src/transport/jsonRpcEncoder.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const JsonRpcEncoder = require('./jsonRpcEncoder'); 20 | 21 | const encoder = new JsonRpcEncoder(); 22 | 23 | describe('transport/JsonRpcEncoder', () => { 24 | describe('encodeObject', () => { 25 | it('encodes the body correctly, incrementing id', () => { 26 | const id = encoder.id; 27 | const bdy = encoder.encodeObject('someMethod', ['param1', 'param2']); 28 | const enc = { 29 | id, 30 | jsonrpc: '2.0', 31 | method: 'someMethod', 32 | params: ['param1', 'param2'] 33 | }; 34 | 35 | expect(bdy).to.deep.equal(enc); 36 | expect(encoder.id - id).to.equal(1); 37 | }); 38 | }); 39 | 40 | describe('encode', () => { 41 | it('encodes the body correctly, incrementing id', () => { 42 | const id = encoder.id; 43 | const bdy = encoder.encode('someMethod', ['param1', 'param2']); 44 | const enc = `{"id":${id},"jsonrpc":"2.0","method":"someMethod","params":["param1","param2"]}`; 45 | 46 | expect(bdy).to.equal(enc); 47 | expect(encoder.id - id).to.equal(1); 48 | }); 49 | }); 50 | }); 51 | -------------------------------------------------------------------------------- /src/transport/middleware.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | class Middleware { 18 | constructor (transport) { 19 | this._transport = transport; 20 | this._subscribe = transport.subscribe; 21 | 22 | transport.subscribe = this.handleSubscribe.bind(this); 23 | 24 | this._handlers = {}; 25 | this._subHandlers = {}; 26 | } 27 | 28 | registerSubscribe (method, handler) { 29 | if (method in this._subHandlers) { 30 | throw new Error(`${method} is already defined in the middleware!`); 31 | } 32 | 33 | this._subHandlers[method] = handler; 34 | } 35 | 36 | register (method, handler) { 37 | if (method in this._handlers) { 38 | throw new Error(`${method} is already defined in the middleware!`); 39 | } 40 | 41 | this._handlers[method] = handler; 42 | } 43 | 44 | handleSubscribe (api, callback, event) { 45 | // Don't ask 46 | const method = api.subscribe ? api.subscribe : event[0]; 47 | const params = event.length === 2 ? event[1] : event; 48 | 49 | const handler = this._subHandlers[method]; 50 | 51 | if (handler) { 52 | return handler(params, callback); 53 | } 54 | 55 | this._subscribe.call(this._transport, api, callback, event); 56 | } 57 | 58 | handle (method, params) { 59 | const handler = this._handlers[method]; 60 | 61 | if (handler) { 62 | return handler(params); 63 | } 64 | 65 | return null; 66 | } 67 | 68 | rpcRequest (method, params) { 69 | return this._transport._execute(method, params); 70 | } 71 | } 72 | 73 | module.exports = Middleware; 74 | -------------------------------------------------------------------------------- /src/transport/middleware.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Middleware = require('./middleware'); 18 | const JsonRpcBase = require('./jsonRpcBase'); 19 | 20 | const MOCKED = 'mocked!'; 21 | 22 | class MockTransport extends JsonRpcBase { 23 | _execute () { 24 | return Promise.resolve(MOCKED); 25 | } 26 | } 27 | 28 | class MockMiddleware extends Middleware { 29 | constructor (transport) { 30 | super(transport); 31 | 32 | this.register('mock_rpc', ([num]) => num); 33 | this.register('mock_null', () => null); 34 | } 35 | } 36 | 37 | describe('transport/Middleware', () => { 38 | let transport; 39 | 40 | beforeEach(() => { 41 | transport = new MockTransport(); 42 | transport.addMiddleware(MockMiddleware); 43 | }); 44 | 45 | it('Routes requests to middleware', () => { 46 | return transport.execute('mock_rpc', [100]).then((num) => { 47 | expect(num).to.be.equal(100); 48 | }); 49 | }); 50 | 51 | it('Passes non-mocked requests through', () => { 52 | return transport.execute('not_moced', [200]).then((result) => { 53 | expect(result).to.be.equal(MOCKED); 54 | }); 55 | }); 56 | 57 | it('Passes mocked requests through, if middleware returns null', () => { 58 | return transport.execute('mock_null', [300]).then((result) => { 59 | expect(result).to.be.equal(MOCKED); 60 | }); 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /src/transport/ws/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Ws = require('./ws'); 18 | 19 | module.exports = Ws; 20 | -------------------------------------------------------------------------------- /src/transport/ws/polyfill.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | if (typeof WebSocket === 'undefined') { 18 | global.WebSocket = require('websocket').w3cwebsocket; 19 | } 20 | -------------------------------------------------------------------------------- /src/transport/ws/ws.e2e.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const Ws = require('./ws'); 20 | 21 | const ws = new Ws('ws://localhost:8546/'); 22 | 23 | describe('transport/WsSecure', () => { 24 | it('connects and makes a call to web3_clientVersion', () => { 25 | return ws.execute('web3_clientVersion').then((version) => { 26 | const [client] = version.split('/'); 27 | 28 | expect(client === 'Geth' || client === 'Parity').to.be.ok; 29 | }); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /src/transport/ws/ws.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { TEST_WS_URL, mockWs } = require('../../../test/mockRpc'); 20 | const Ws = require('./ws'); 21 | 22 | describe('transport/ws', () => { 23 | let transport; 24 | let scope; 25 | 26 | describe('transport emitter', () => { 27 | const connect = () => { 28 | const scope = mockWs(); 29 | const transport = new Ws(TEST_WS_URL); 30 | 31 | return { transport, scope }; 32 | }; 33 | 34 | it('emits open event', (done) => { 35 | const { transport, scope } = connect(); 36 | 37 | transport.once('open', () => { 38 | done(); 39 | }); 40 | 41 | scope.stop(); 42 | }); 43 | 44 | it('emits close event', (done) => { 45 | const { transport, scope } = connect(); 46 | 47 | transport.once('open', () => { 48 | scope.server.close(); 49 | }); 50 | 51 | transport.once('close', () => { 52 | done(); 53 | }); 54 | }); 55 | }); 56 | 57 | describe('transport', () => { 58 | let result; 59 | 60 | beforeEach(() => { 61 | scope = mockWs([{ method: 'test_anyCall', reply: 'TestResult' }]); 62 | transport = new Ws(TEST_WS_URL); 63 | 64 | return transport 65 | .execute('test_anyCall', [1, 2, 3]) 66 | .then((_result) => { 67 | result = _result; 68 | }); 69 | }); 70 | 71 | afterEach(() => { 72 | scope.stop(); 73 | }); 74 | 75 | it('makes call', () => { 76 | expect(scope.isDone()).to.be.true; 77 | }); 78 | 79 | it('sets jsonrpc', () => { 80 | expect(scope.body.test_anyCall.jsonrpc).to.equal('2.0'); 81 | }); 82 | 83 | it('sets the method', () => { 84 | expect(scope.body.test_anyCall.method).to.equal('test_anyCall'); 85 | }); 86 | 87 | it('passes the params', () => { 88 | expect(scope.body.test_anyCall.params).to.deep.equal([1, 2, 3]); 89 | }); 90 | 91 | it('increments the id', () => { 92 | expect(scope.body.test_anyCall.id).not.to.equal(0); 93 | }); 94 | 95 | it('passes the actual result back', () => { 96 | expect(result).to.equal('TestResult'); 97 | }); 98 | }); 99 | 100 | describe('errors', () => { 101 | beforeEach(() => { 102 | scope = mockWs([{ method: 'test_anyCall', reply: { error: { code: 1, message: 'TestError' } } }]); 103 | transport = new Ws(TEST_WS_URL); 104 | }); 105 | 106 | afterEach(() => { 107 | scope.stop(); 108 | }); 109 | 110 | it('returns RPC errors when encountered', () => { 111 | return transport 112 | .execute('test_anyCall') 113 | .catch((error) => { 114 | expect(error).to.match(/TestError/); 115 | }); 116 | }); 117 | }); 118 | }); 119 | -------------------------------------------------------------------------------- /src/util/address.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { isAddress, toChecksumAddress } = require('@parity/abi/lib/util/address'); 18 | 19 | module.exports = { 20 | isAddress, 21 | toChecksumAddress 22 | }; 23 | -------------------------------------------------------------------------------- /src/util/decode.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { isHex } = require('./types'); 18 | 19 | const Func = require('@parity/abi/lib/spec/function'); 20 | const { fromParamType, toParamType } = require('@parity/abi/lib/spec/paramType/format'); 21 | 22 | function decodeCallData (data) { 23 | if (!isHex(data)) { 24 | throw new Error('Input to decodeCallData should be a hex value'); 25 | } 26 | 27 | if (data.substr(0, 2) === '0x') { 28 | return decodeCallData(data.slice(2)); 29 | } 30 | 31 | if (data.length < 8) { 32 | throw new Error('Input to decodeCallData should be method signature + data'); 33 | } 34 | 35 | const signature = data.substr(0, 8); 36 | const paramdata = data.substr(8); 37 | 38 | return { 39 | signature: `0x${signature}`, 40 | paramdata: `0x${paramdata}` 41 | }; 42 | } 43 | 44 | function decodeMethodInput (methodAbi, paramdata) { 45 | if (!methodAbi) { 46 | throw new Error('decodeMethodInput should receive valid method-specific ABI'); 47 | } 48 | 49 | if (paramdata && paramdata.length) { 50 | if (!isHex(paramdata)) { 51 | throw new Error('Input to decodeMethodInput should be a hex value'); 52 | } 53 | 54 | if (paramdata.substr(0, 2) === '0x') { 55 | return decodeMethodInput(methodAbi, paramdata.slice(2)); 56 | } 57 | } 58 | 59 | return new Func(methodAbi).decodeInput(paramdata).map((decoded) => decoded.value); 60 | } 61 | 62 | // takes a method in form name(...,types) and returns the inferred abi definition 63 | function methodToAbi (method) { 64 | const length = method.length; 65 | const typesStart = method.indexOf('('); 66 | const typesEnd = method.indexOf(')'); 67 | 68 | if (typesStart === -1) { 69 | throw new Error(`Missing start ( in call to decodeMethod with ${method}`); 70 | } else if (typesEnd === -1) { 71 | throw new Error(`Missing end ) in call to decodeMethod with ${method}`); 72 | } else if (typesEnd < typesStart) { 73 | throw new Error(`End ) is before start ( in call to decodeMethod with ${method}`); 74 | } else if (typesEnd !== length - 1) { 75 | throw new Error(`Extra characters after end ) in call to decodeMethod with ${method}`); 76 | } 77 | 78 | const name = method.substr(0, typesStart); 79 | const types = method.substr(typesStart + 1, length - (typesStart + 1) - 1).split(','); 80 | const inputs = types.filter((_type) => _type.length).map((_type) => { 81 | const type = fromParamType(toParamType(_type)); 82 | 83 | return { type }; 84 | }); 85 | 86 | return { type: 'function', name, inputs }; 87 | } 88 | 89 | function abiDecode (inputTypes, data) { 90 | return decodeMethodInput({ 91 | inputs: inputTypes.map((type) => { 92 | return { type }; 93 | }) 94 | }, data); 95 | } 96 | 97 | module.exports = { 98 | decodeCallData, 99 | decodeMethodInput, 100 | methodToAbi, 101 | abiDecode 102 | }; 103 | -------------------------------------------------------------------------------- /src/util/decode.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const BigNumber = require('bignumber.js'); 18 | const { abiDecode, decodeCallData, decodeMethodInput, methodToAbi } = require('./decode'); 19 | 20 | describe('util/decode', () => { 21 | const METH = '0x70a08231'; 22 | const ENCO = '0x70a082310000000000000000000000005A5eFF38DA95b0D58b6C616f2699168B480953C9'; 23 | const DATA = '0x0000000000000000000000005A5eFF38DA95b0D58b6C616f2699168B480953C9'; 24 | 25 | describe('decodeCallData', () => { 26 | it('throws on non-hex inputs', () => { 27 | expect(() => decodeCallData('invalid')).to.throw(/should be a hex value/); 28 | }); 29 | 30 | it('throws when invalid signature length', () => { 31 | expect(() => decodeCallData(METH.slice(-6))).to.throw(/should be method signature/); 32 | }); 33 | 34 | it('splits valid inputs properly', () => { 35 | expect(decodeCallData(ENCO)).to.deep.equal({ 36 | signature: METH, 37 | paramdata: DATA 38 | }); 39 | }); 40 | }); 41 | 42 | describe('decodeMethodInput', () => { 43 | it('expects a valid ABI', () => { 44 | expect(() => decodeMethodInput(null, null)).to.throw(/should receive valid method/); 45 | }); 46 | 47 | it('expects valid hex parameter data', () => { 48 | expect(() => decodeMethodInput({}, 'invalid')).to.throw(/should be a hex value/); 49 | }); 50 | 51 | it('correct decodes null inputs', () => { 52 | expect(decodeMethodInput({}, null)).to.deep.equal([]); 53 | }); 54 | 55 | it('correct decodes empty inputs', () => { 56 | expect(decodeMethodInput({}, '')).to.deep.equal([]); 57 | }); 58 | 59 | it('correctly decodes valid inputs', () => { 60 | expect( 61 | decodeMethodInput({ 62 | type: 'function', 63 | inputs: [ 64 | { type: 'uint' } 65 | ] 66 | }, DATA) 67 | ).to.deep.equal( 68 | [ new BigNumber('0x5a5eff38da95b0d58b6c616f2699168b480953c9') ] 69 | ); 70 | }); 71 | }); 72 | 73 | describe('methodToAbi', () => { 74 | it('throws when no start ( specified', () => { 75 | expect(() => methodToAbi('invalid,uint,bool)')).to.throw(/Missing start \(/); 76 | }); 77 | 78 | it('throws when no end ) specified', () => { 79 | expect(() => methodToAbi('invalid(uint,bool')).to.throw(/Missing end \)/); 80 | }); 81 | 82 | it('throws when end ) is not in the last position', () => { 83 | expect(() => methodToAbi('invalid(uint,bool)2')).to.throw(/Extra characters after end \)/); 84 | }); 85 | 86 | it('throws when start ( is after end )', () => { 87 | expect(() => methodToAbi('invalid)uint,bool(')).to.throw(/End \) is before start \(/); 88 | }); 89 | 90 | it('throws when invalid types are present', () => { 91 | expect(() => methodToAbi('method(invalidType,bool,uint)')).to.throw(/Cannot convert invalidType/); 92 | }); 93 | 94 | it('returns a valid methodabi for a valid method', () => { 95 | expect(methodToAbi('valid(uint,bool)')).to.deep.equals({ 96 | type: 'function', 97 | name: 'valid', 98 | inputs: [ 99 | { type: 'uint256' }, 100 | { type: 'bool' } 101 | ] 102 | }); 103 | }); 104 | }); 105 | 106 | describe('abiDecode', () => { 107 | it('correctly decodes valid inputs', () => { 108 | expect(abiDecode(['uint'], DATA)).to.deep.equal( 109 | [ new BigNumber('0x5a5eff38da95b0d58b6c616f2699168b480953c9') ] 110 | ); 111 | }); 112 | }); 113 | }); 114 | -------------------------------------------------------------------------------- /src/util/encode.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const Abi = require('@parity/abi'); 18 | const Func = require('@parity/abi/lib/spec/function'); 19 | 20 | const { abiDecode } = require('./decode'); 21 | const { cleanupValue } = require('./format'); 22 | const { sha3 } = require('./sha3'); 23 | 24 | function encodeMethodCallAbi (methodAbi = {}, values = []) { 25 | const func = new Func(methodAbi); 26 | const tokens = Abi.encodeTokens(func.inputParamTypes(), values); 27 | const call = func.encodeCall(tokens); 28 | 29 | return `0x${call}`; 30 | } 31 | 32 | function abiEncode (methodName, inputTypes, data) { 33 | const result = encodeMethodCallAbi({ 34 | name: methodName || '', 35 | type: 'function', 36 | inputs: inputTypes.map((type) => { 37 | return { type }; 38 | }) 39 | }, data); 40 | 41 | return result; 42 | } 43 | 44 | function abiUnencode (abi, data) { 45 | const callsig = data.substr(2, 8); 46 | const op = abi.find((field) => { 47 | return field.type === 'function' && 48 | abiSignature(field.name, field.inputs.map((input) => input.type)).substr(2, 8) === callsig; 49 | }); 50 | 51 | if (!op) { 52 | console.warn(`Unknown function ID: ${callsig}`); 53 | return null; 54 | } 55 | 56 | let argsByIndex = abiDecode(op.inputs.map((field) => field.type), '0x' + data.substr(10)) 57 | .map((value, index) => cleanupValue(value, op.inputs[index].type)); 58 | const argsByName = op.inputs.reduce((result, field, index) => { 59 | result[field.name] = argsByIndex[index]; 60 | 61 | return result; 62 | }, {}); 63 | 64 | return [op.name, argsByName, argsByIndex]; 65 | } 66 | 67 | function abiSignature (name, inputs) { 68 | return sha3(`${name}(${inputs.join()})`); 69 | } 70 | 71 | module.exports = { 72 | abiEncode, 73 | abiSignature, 74 | abiUnencode, 75 | encodeMethodCallAbi 76 | }; 77 | -------------------------------------------------------------------------------- /src/util/encode.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const { abiEncode, abiUnencode, abiSignature, encodeMethodCallAbi } = require('./encode'); 20 | 21 | const ABI = { 22 | type: 'function', 23 | name: 'valid', 24 | inputs: [ 25 | { type: 'uint256' }, 26 | { type: 'bool' } 27 | ] 28 | }; 29 | 30 | const RESULT = [ 31 | 'f87fa141', 32 | '0000000000000000000000000000000000000000000000000000000000000123', 33 | '0000000000000000000000000000000000000000000000000000000000000001' 34 | ].join(''); 35 | const VARIABLE = [ 36 | '5a6fbce0', 37 | 'c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 38 | '0000000000000000000000000000000000000000000000000000000000000040', 39 | '000000000000000000000000000000000000000000000000000000000000000f', 40 | '687474703a2f2f666f6f2e6261722f0000000000000000000000000000000000' 41 | ].join(''); 42 | 43 | describe('util/encode', () => { 44 | describe('encodeMethodCallAbi', () => { 45 | it('encodes calls with the correct result', () => { 46 | expect(encodeMethodCallAbi(ABI, [0x123, true])).to.equal(`0x${RESULT}`); 47 | }); 48 | }); 49 | 50 | describe('abiEncode', () => { 51 | it('encodes calls with the correct result', () => { 52 | expect(abiEncode('valid', ['uint256', 'bool'], [0x123, true])).to.equal(`0x${RESULT}`); 53 | }); 54 | 55 | it('encodes variable values', () => { 56 | expect( 57 | abiEncode( 58 | 'hintUrl', ['bytes32', 'string'], ['0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470', 'http://foo.bar/'] 59 | ) 60 | ).to.equal(`0x${VARIABLE}`); 61 | }); 62 | 63 | it('encodes only the data with null name', () => { 64 | expect( 65 | abiEncode(null, ['uint256', 'bool'], [0x123, true]) 66 | ).to.equal(`0x${RESULT.substr(8)}`); 67 | }); 68 | }); 69 | 70 | describe('abiUnencode', () => { 71 | it('decodes data correctly from abi', () => { 72 | expect( 73 | abiUnencode([{ 74 | name: 'test', 75 | type: 'function', 76 | inputs: [ 77 | { type: 'uint', name: 'arga' } 78 | ] 79 | }], '0x1acb6f7700000000000000000000000000000038') 80 | ).to.deep.equal(['test', { arga: 56 }, [56]]); 81 | }); 82 | 83 | it('returns null when function not found', () => { 84 | expect(abiUnencode([], '0x12345678')).to.be.null; 85 | }); 86 | }); 87 | 88 | // Same example as in abi/util/signature.spec.js 89 | describe('abiSignature', () => { 90 | it('encodes baz(uint32,bool) correctly', () => { 91 | expect( 92 | abiSignature('baz', ['uint32', 'bool']) 93 | ).to.equal('0xcdcd77c0992ec5bbfc459984220f8c45084cc24d9b6efed1fae540db8de801d2'); 94 | }); 95 | }); 96 | }); 97 | -------------------------------------------------------------------------------- /src/util/format.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { range } = require('lodash'); 18 | 19 | function bytesToHex (bytes) { 20 | return '0x' + Buffer.from(bytes).toString('hex'); 21 | } 22 | 23 | function cleanupValue (value, type) { 24 | // TODO: make work with arbitrary depth arrays 25 | if (value instanceof Array && type.match(/bytes[0-9]+/)) { 26 | // figure out if it's an ASCII string hiding in there: 27 | let ascii = ''; 28 | 29 | for (let index = 0, ended = false; index < value.length && ascii !== null; ++index) { 30 | const val = value[index]; 31 | 32 | if (val === 0) { 33 | ended = true; 34 | } else { 35 | ascii += String.fromCharCode(val); 36 | } 37 | 38 | if ((ended && val !== 0) || (!ended && (val < 32 || val >= 128))) { 39 | ascii = null; 40 | } 41 | } 42 | 43 | value = ascii === null 44 | ? bytesToHex(value) 45 | : ascii; 46 | } 47 | 48 | if (type.substr(0, 4) === 'uint' && +type.substr(4) <= 48) { 49 | value = +value; 50 | } 51 | 52 | return value; 53 | } 54 | 55 | function hexToBytes (hex) { 56 | const raw = toHex(hex).slice(2); 57 | const bytes = []; 58 | 59 | for (let i = 0; i < raw.length; i += 2) { 60 | bytes.push(parseInt(raw.substr(i, 2), 16)); 61 | } 62 | 63 | return bytes; 64 | } 65 | 66 | function hexToAscii (hex) { 67 | const bytes = hexToBytes(hex); 68 | const str = bytes.map((byte) => String.fromCharCode(byte)).join(''); 69 | 70 | return str; 71 | } 72 | 73 | function bytesToAscii (bytes) { 74 | return bytes.map((b) => String.fromCharCode(b % 512)).join(''); 75 | } 76 | 77 | function asciiToHex (string) { 78 | let result = '0x'; 79 | 80 | for (let i = 0; i < string.length; ++i) { 81 | result += ('0' + string.charCodeAt(i).toString(16)).substr(-2); 82 | } 83 | 84 | return result; 85 | } 86 | 87 | function padRight (input, length) { 88 | const hexLength = length * 2; 89 | const value = toHex(input).substr(2, hexLength); 90 | 91 | return '0x' + value + range(hexLength - value.length).map(() => '0').join(''); 92 | } 93 | 94 | function padLeft (input, length) { 95 | const hexLength = length * 2; 96 | const value = toHex(input).substr(2, hexLength); 97 | 98 | return '0x' + range(hexLength - value.length).map(() => '0').join('') + value; 99 | } 100 | 101 | function toHex (str) { 102 | if (str && str.toString) { 103 | str = str.toString(16); 104 | } 105 | 106 | if (str && str.substr(0, 2) === '0x') { 107 | return str.toLowerCase(); 108 | } 109 | 110 | return `0x${(str || '').toLowerCase()}`; 111 | } 112 | 113 | module.exports = { 114 | asciiToHex, 115 | bytesToAscii, 116 | bytesToHex, 117 | cleanupValue, 118 | hexToAscii, 119 | hexToBytes, 120 | padLeft, 121 | padRight, 122 | toHex 123 | }; 124 | -------------------------------------------------------------------------------- /src/util/format.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { bytesToHex, cleanupValue, hexToBytes, hexToAscii, bytesToAscii, asciiToHex, padLeft, padRight } = require('./format'); 18 | 19 | describe('util/format', () => { 20 | describe('bytesToHex', () => { 21 | it('correctly converts an empty array', () => { 22 | expect(bytesToHex([])).to.equal('0x'); 23 | }); 24 | 25 | it('correctly converts a non-empty array', () => { 26 | expect(bytesToHex([0, 15, 16])).to.equal('0x000f10'); 27 | }); 28 | }); 29 | 30 | describe('cleanupValue', () => { 31 | it('returns unknown values as the original', () => { 32 | expect(cleanupValue('original', 'unknown')).to.equal('original'); 33 | }); 34 | 35 | it('returns ascii arrays as ascii', () => { 36 | expect(cleanupValue([97, 115, 99, 105, 105, 0], 'bytes32')).to.equal('ascii'); 37 | }); 38 | 39 | it('returns non-ascii arrays as hex strings', () => { 40 | expect(cleanupValue([97, 200, 0, 0], 'bytes4')).to.equal('0x61c80000'); 41 | }); 42 | 43 | it('returns uint (>48) as the original', () => { 44 | expect(cleanupValue('original', 'uint49')).to.equal('original'); 45 | }); 46 | 47 | it('returns uint (<=48) as the number value', () => { 48 | expect(cleanupValue('12345', 'uint48')).to.equal(12345); 49 | }); 50 | }); 51 | 52 | describe('hexToBytes', () => { 53 | it('correctly converts an empty string', () => { 54 | expect(hexToBytes('')).to.deep.equal([]); 55 | expect(hexToBytes('0x')).to.deep.equal([]); 56 | }); 57 | 58 | it('correctly converts a non-empty string', () => { 59 | expect(hexToBytes('0x000f10')).to.deep.equal([0, 15, 16]); 60 | }); 61 | }); 62 | 63 | describe('asciiToHex', () => { 64 | it('correctly converts an empty string', () => { 65 | expect(asciiToHex('')).to.equal('0x'); 66 | }); 67 | 68 | it('correctly converts a non-empty string', () => { 69 | expect(asciiToHex('abc')).to.equal('0x616263'); 70 | expect(asciiToHex('a\nb')).to.equal('0x610a62'); 71 | }); 72 | 73 | it('correctly converts where charCode < 0x10', () => { 74 | expect( 75 | asciiToHex( 76 | [32, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0].map((v) => String.fromCharCode(v)).join('') 77 | ) 78 | ).to.equal('0x20100f0e0d0c0b0a09080706050403020100'); 79 | }); 80 | }); 81 | 82 | describe('hexToAscii', () => { 83 | it('correctly converts an empty string', () => { 84 | expect(hexToAscii('')).to.equal(''); 85 | expect(hexToAscii('0x')).to.equal(''); 86 | }); 87 | 88 | it('correctly converts a non-empty string', () => { 89 | expect(hexToAscii('0x616263')).to.equal('abc'); 90 | }); 91 | }); 92 | 93 | describe('bytesToAscii', () => { 94 | it('correctly converts an empty string', () => { 95 | expect(bytesToAscii([])).to.equal(''); 96 | }); 97 | 98 | it('correctly converts a non-empty string', () => { 99 | expect(bytesToAscii([97, 98, 99])).to.equal('abc'); 100 | }); 101 | }); 102 | 103 | describe('padLeft', () => { 104 | it('correctly pads to the number of hex digits', () => { 105 | expect(padLeft('ab', 4)).to.equal('0x000000ab'); 106 | }); 107 | }); 108 | 109 | describe('padRight', () => { 110 | it('correctly pads to the number of hex digits', () => { 111 | expect(padRight('ab', 4)).to.equal('0xab000000'); 112 | }); 113 | }); 114 | }); 115 | -------------------------------------------------------------------------------- /src/util/identity.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const blockies = require('blockies'); 18 | 19 | // jsdom doesn't have all the browser features, blockies fail 20 | const TEST_ENV = process.env.NODE_ENV === 'test'; 21 | 22 | function createIdentityImg (address, scale = 8) { 23 | return TEST_ENV 24 | ? 'test-createIdentityImg' 25 | : blockies({ 26 | seed: (address || '').toLowerCase(), 27 | size: 8, 28 | scale 29 | }).toDataURL(); 30 | } 31 | 32 | module.exports = { 33 | createIdentityImg 34 | }; 35 | -------------------------------------------------------------------------------- /src/util/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { isAddress, toChecksumAddress } = require('./address'); 18 | const { abiDecode, decodeCallData, decodeMethodInput, methodToAbi } = require('./decode'); 19 | const { abiEncode, abiUnencode, abiSignature, encodeMethodCallAbi } = require('./encode'); 20 | const { bytesToHex, hexToAscii, asciiToHex, cleanupValue, hexToBytes } = require('./format'); 21 | const { fromWei, toWei } = require('./wei'); 22 | const { sha3 } = require('./sha3'); 23 | const { isArray, isFunction, isHex, isInstanceOf, isString } = require('./types'); 24 | const { createIdentityImg } = require('./identity'); 25 | 26 | module.exports = { 27 | abiDecode, 28 | abiEncode, 29 | abiUnencode, 30 | abiSignature, 31 | cleanupValue, 32 | isAddressValid: isAddress, 33 | isArray, 34 | isFunction, 35 | isHex, 36 | isInstanceOf, 37 | isString, 38 | bytesToHex, 39 | hexToAscii, 40 | hexToBytes, 41 | asciiToHex, 42 | createIdentityImg, 43 | decodeCallData, 44 | decodeMethodInput, 45 | encodeMethodCallAbi, 46 | methodToAbi, 47 | fromWei, 48 | toChecksumAddress, 49 | toWei, 50 | sha3 51 | }; 52 | -------------------------------------------------------------------------------- /src/util/sha3.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { keccak_256 } = require('js-sha3'); // eslint-disable-line 18 | 19 | const { hexToBytes } = require('./format'); 20 | const { isHex } = require('./types'); 21 | 22 | function sha3 (value, options) { 23 | const forceHex = options && options.encoding === 'hex'; 24 | 25 | if (forceHex || (!options && isHex(value))) { 26 | const bytes = hexToBytes(value); 27 | 28 | return sha3(bytes); 29 | } 30 | 31 | const hash = keccak_256(value); 32 | 33 | return `0x${hash}`; 34 | } 35 | 36 | sha3.text = (val) => sha3(val, { encoding: 'raw' }); 37 | 38 | module.exports = { 39 | sha3 40 | }; 41 | -------------------------------------------------------------------------------- /src/util/sha3.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { sha3 } = require('./sha3'); 18 | 19 | describe('util/sha3', () => { 20 | describe('sha3', () => { 21 | it('constructs a correct sha3 value', () => { 22 | expect(sha3('jacogr')).to.equal('0x2f4ff4b5a87abbd2edfed699db48a97744e028c7f7ce36444d40d29d792aa4dc'); 23 | }); 24 | 25 | it('constructs a correct sha3 encoded as hex', () => { 26 | const key = '000000000000000000000000391694e7e0b0cce554cb130d723a9d27458f9298' + '0000000000000000000000000000000000000000000000000000000000000001'; 27 | 28 | expect(sha3(key, { encoding: 'hex' })).to.equal('0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9'); 29 | expect(sha3(`0x${key}`, { encoding: 'hex' })).to.equal('0x6661e9d6d8b923d5bbaab1b96e1dd51ff6ea2a93520fdc9eb75d059238b8c5e9'); 30 | }); 31 | 32 | it('constructs a correct sha3 from Uint8Array', () => { 33 | expect(sha3('01020304', { encoding: 'hex' })).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); 34 | expect(sha3(Uint8Array.from([1, 2, 3, 4]))).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); 35 | }); 36 | 37 | it('should interpret as bytes by default', () => { 38 | expect(sha3('0x01020304')).to.equal('0xa6885b3731702da62e8e4a8f584ac46a7f6822f4e2ba50fba902f67b1588d23b'); 39 | }); 40 | 41 | it('should force text if option is passed', () => { 42 | expect(sha3('0x01020304', { encoding: 'raw' })).to.equal('0x16bff43de576d28857dcba65a56fc17c5e93c09bd6a709268eff8e62025ae869'); 43 | expect(sha3.text('0x01020304')).to.equal('0x16bff43de576d28857dcba65a56fc17c5e93c09bd6a709268eff8e62025ae869'); 44 | }); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /src/util/types.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const HEXDIGITS = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f']; 18 | 19 | function isArray (test) { 20 | return Object.prototype.toString.call(test) === '[object Array]'; 21 | } 22 | 23 | function isError (test) { 24 | return Object.prototype.toString.call(test) === '[object Error]'; 25 | } 26 | 27 | function isFunction (test) { 28 | return Object.prototype.toString.call(test) === '[object Function]'; 29 | } 30 | 31 | function isHex (_test) { 32 | if (!isString(_test)) { 33 | return false; 34 | } 35 | 36 | if (_test.substr(0, 2) === '0x') { 37 | return isHex(_test.slice(2)); 38 | } 39 | 40 | const test = _test.toLowerCase(); 41 | let hex = true; 42 | 43 | for (let index = 0; hex && index < test.length; index++) { 44 | hex = HEXDIGITS.includes(test[index]); 45 | } 46 | 47 | return hex; 48 | } 49 | 50 | function isObject (test) { 51 | return Object.prototype.toString.call(test) === '[object Object]'; 52 | } 53 | 54 | function isString (test) { 55 | return Object.prototype.toString.call(test) === '[object String]'; 56 | } 57 | 58 | function isInstanceOf (test, clazz) { 59 | return test instanceof clazz; 60 | } 61 | 62 | module.exports = { 63 | isArray, 64 | isError, 65 | isFunction, 66 | isHex, 67 | isInstanceOf, 68 | isObject, 69 | isString 70 | }; 71 | -------------------------------------------------------------------------------- /src/util/types.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const sinon = require('sinon'); 20 | 21 | const { isArray, isError, isFunction, isHex, isInstanceOf, isObject, isString } = require('./types'); 22 | const Eth = require('../rpc/eth'); 23 | 24 | describe('util/types', () => { 25 | describe('isArray', () => { 26 | it('correctly identifies null as false', () => { 27 | expect(isArray(null)).to.be.false; 28 | }); 29 | 30 | it('correctly identifies empty array as true', () => { 31 | expect(isArray([])).to.be.true; 32 | }); 33 | 34 | it('correctly identifies array as true', () => { 35 | expect(isArray([1, 2, 3])).to.be.true; 36 | }); 37 | }); 38 | 39 | describe('isError', () => { 40 | it('correctly identifies null as false', () => { 41 | expect(isError(null)).to.be.false; 42 | }); 43 | 44 | it('correctly identifies Error as true', () => { 45 | expect(isError(new Error('an error'))).to.be.true; 46 | }); 47 | }); 48 | 49 | describe('isFunction', () => { 50 | it('correctly identifies null as false', () => { 51 | expect(isFunction(null)).to.be.false; 52 | }); 53 | 54 | it('correctly identifies function as true', () => { 55 | expect(isFunction(sinon.stub())).to.be.true; 56 | }); 57 | }); 58 | 59 | describe('isHex', () => { 60 | it('correctly identifies hex by leading 0x', () => { 61 | expect(isHex('0x123')).to.be.true; 62 | }); 63 | 64 | it('correctly identifies hex without leading 0x', () => { 65 | expect(isHex('123')).to.be.true; 66 | }); 67 | 68 | it('correctly identifies non-hex values', () => { 69 | expect(isHex('123j')).to.be.false; 70 | }); 71 | 72 | it('correctly indentifies non-string values', () => { 73 | expect(isHex(false)).to.be.false; 74 | expect(isHex()).to.be.false; 75 | expect(isHex([1, 2, 3])).to.be.false; 76 | }); 77 | }); 78 | 79 | describe('isInstanceOf', () => { 80 | it('correctly identifies build-in instanceof', () => { 81 | expect(isInstanceOf(new String('123'), String)).to.be.true; // eslint-disable-line no-new-wrappers 82 | }); 83 | 84 | it('correctly identifies own instanceof', () => { 85 | expect(isInstanceOf(new Eth({}), Eth)).to.be.true; 86 | }); 87 | 88 | it('correctly reports false for own', () => { 89 | expect(isInstanceOf({}, Eth)).to.be.false; 90 | }); 91 | }); 92 | 93 | describe('isObject', () => { 94 | it('correctly identifies empty object as object', () => { 95 | expect(isObject({})).to.be.true; 96 | }); 97 | 98 | it('correctly identifies non-empty object as object', () => { 99 | expect(isObject({ data: '123' })).to.be.true; 100 | }); 101 | 102 | it('correctly identifies Arrays as non-objects', () => { 103 | expect(isObject([1, 2, 3])).to.be.false; 104 | }); 105 | 106 | it('correctly identifies Strings as non-objects', () => { 107 | expect(isObject('123')).to.be.false; 108 | }); 109 | }); 110 | 111 | describe('isString', () => { 112 | it('correctly identifies empty string as string', () => { 113 | expect(isString('')).to.be.true; 114 | }); 115 | 116 | it('correctly identifies string as string', () => { 117 | expect(isString('123')).to.be.true; 118 | }); 119 | }); 120 | }); 121 | -------------------------------------------------------------------------------- /src/util/wei.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const BigNumber = require('bignumber.js'); 18 | 19 | const UNITS = ['wei', 'ada', 'babbage', 'shannon', 'szabo', 'finney', 'ether', 'kether', 'mether', 'gether', 'tether']; 20 | 21 | function _getUnitMultiplier (unit) { 22 | const position = UNITS.indexOf(unit.toLowerCase()); 23 | 24 | if (position === -1) { 25 | throw new Error(`Unknown unit ${unit} passed to wei formatter`); 26 | } 27 | 28 | return Math.pow(10, position * 3); 29 | } 30 | 31 | function fromWei (value, unit = 'ether') { 32 | return new BigNumber(value).div(_getUnitMultiplier(unit)); 33 | } 34 | 35 | function toWei (value, unit = 'ether') { 36 | return new BigNumber(value).mul(_getUnitMultiplier(unit)); 37 | } 38 | 39 | module.exports = { 40 | _getUnitMultiplier, 41 | fromWei, 42 | toWei 43 | }; 44 | -------------------------------------------------------------------------------- /src/util/wei.spec.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const { _getUnitMultiplier, fromWei, toWei } = require('./wei'); 18 | 19 | describe('util/wei', () => { 20 | describe('_getUnitMultiplier', () => { 21 | it('returns 10^0 for wei', () => { 22 | expect(_getUnitMultiplier('wei')).to.equal(Math.pow(10, 0)); 23 | }); 24 | 25 | it('returns 10^15 for finney', () => { 26 | expect(_getUnitMultiplier('finney')).to.equal(Math.pow(10, 15)); 27 | }); 28 | 29 | it('returns 10^18 for ether', () => { 30 | expect(_getUnitMultiplier('ether')).to.equal(Math.pow(10, 18)); 31 | }); 32 | 33 | it('throws an error on invalid units', () => { 34 | expect(() => _getUnitMultiplier('invalid')).to.throw(/passed to wei formatter/); 35 | }); 36 | }); 37 | 38 | describe('fromWei', () => { 39 | it('formats into ether when nothing specified', () => { 40 | expect(fromWei('1230000000000000000').toString()).to.equal('1.23'); 41 | }); 42 | 43 | it('formats into finney when specified', () => { 44 | expect(fromWei('1230000000000000000', 'finney').toString()).to.equal('1230'); 45 | }); 46 | }); 47 | 48 | describe('toWei', () => { 49 | it('formats from ether when nothing specified', () => { 50 | expect(toWei(1.23).toString()).to.equal('1230000000000000000'); 51 | }); 52 | 53 | it('formats from finney when specified', () => { 54 | expect(toWei(1230, 'finney').toString()).to.equal('1230000000000000000'); 55 | }); 56 | }); 57 | }); 58 | -------------------------------------------------------------------------------- /test/mocha.config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | require('mock-local-storage'); 18 | require('isomorphic-fetch'); 19 | 20 | const es6Promise = require('es6-promise'); 21 | 22 | es6Promise.polyfill(); 23 | 24 | const chai = require('chai'); 25 | const chaiAsPromised = require('chai-as-promised'); 26 | 27 | require('sinon-as-promised'); 28 | 29 | const sinonChai = require('sinon-chai'); 30 | const { JSDOM } = require('jsdom'); 31 | const { WebSocket } = require('mock-socket'); 32 | 33 | chai.use(chaiAsPromised); 34 | chai.use(sinonChai); 35 | 36 | const jsdom = new JSDOM(''); 37 | 38 | global.expect = chai.expect; 39 | global.WebSocket = WebSocket; 40 | 41 | global.document = jsdom.window.document; 42 | global.window = jsdom.window; 43 | global.window.localStorage = global.localStorage; 44 | global.navigator = global.window.navigator; 45 | global.location = global.window.location; 46 | 47 | module.exports = {}; 48 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | -r ./test/mocha.config 2 | -------------------------------------------------------------------------------- /test/mockRpc.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | /* eslint-disable no-unused-expressions */ 18 | 19 | const nock = require('nock'); 20 | const MockWsServer = require('mock-socket').Server; 21 | 22 | const TEST_HTTP_URL = 'http://localhost:6688'; 23 | const TEST_WS_URL = 'ws://localhost:8866'; 24 | 25 | function mockHttp (requests) { 26 | nock.cleanAll(); 27 | let scope = nock(TEST_HTTP_URL); 28 | 29 | requests.forEach((request, index) => { 30 | scope = scope 31 | .post('/') 32 | .reply(request.code || 200, (uri, body) => { 33 | if (body.method !== request.method) { 34 | return { 35 | error: `Invalid method ${body.method}, expected ${request.method}` 36 | }; 37 | } 38 | 39 | scope.body = scope.body || {}; 40 | scope.body[request.method] = body; 41 | 42 | return request.reply; 43 | }); 44 | }); 45 | 46 | return scope; 47 | } 48 | 49 | function mockWs (requests) { 50 | let mockServer = new MockWsServer(TEST_WS_URL); 51 | const scope = { requests: 0, body: {}, server: mockServer }; 52 | 53 | scope.isDone = () => scope.requests === requests.length; 54 | scope.stop = () => { 55 | if (mockServer) { 56 | mockServer.stop(); 57 | mockServer = null; 58 | } 59 | }; 60 | 61 | mockServer.on('message', (_body) => { 62 | const body = JSON.parse(_body); 63 | const request = requests[scope.requests]; 64 | const reply = request.reply; 65 | const response = reply.error 66 | ? { id: body.id, error: { code: reply.error.code, message: reply.error.message } } 67 | : { id: body.id, result: reply }; 68 | 69 | scope.body[request.method] = body; 70 | scope.requests++; 71 | 72 | mockServer.send(JSON.stringify(response)); 73 | 74 | if (request.method.match('subscribe') && request.subscription) { 75 | mockServer.send(JSON.stringify(request.subscription)); 76 | } 77 | }); 78 | 79 | return scope; 80 | } 81 | 82 | module.exports = { 83 | TEST_HTTP_URL, 84 | TEST_WS_URL, 85 | mockHttp, 86 | mockWs 87 | }; 88 | -------------------------------------------------------------------------------- /test/types.js: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies (UK) Ltd. 2 | // This file is part of Parity. 3 | 4 | // Parity is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Parity is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Parity. If not, see . 16 | 17 | const BigNumber = require('bignumber.js'); 18 | 19 | const { isFunction, isInstanceOf } = require('../src/util/types'); 20 | const { isAddress } = require('../src/util/address'); 21 | 22 | const ZEROS = '000000000000000000000000000000000000000000000000000000000000'; 23 | 24 | function isBigNumber (test) { 25 | return isInstanceOf(test, BigNumber); 26 | } 27 | 28 | function isBoolean (test) { 29 | return Object.prototype.toString.call(test) === '[object Boolean]'; 30 | } 31 | 32 | function isHexNumber (_test) { 33 | if (_test.substr(0, 2) !== '0x') { 34 | return false; 35 | } 36 | 37 | const test = _test.substr(2); 38 | const hex = `${ZEROS}${(new BigNumber(_test, 16)).toString(16)}`.slice(-1 * test.length); 39 | 40 | return hex === test; 41 | } 42 | 43 | module.exports = { 44 | isAddress, 45 | isBigNumber, 46 | isBoolean, 47 | isFunction, 48 | isHexNumber, 49 | isInstanceOf 50 | }; 51 | --------------------------------------------------------------------------------