Commit 52fb08f0 authored by SilentCicero's avatar SilentCicero

version 0.1.0 -- docs, dist, package, coverage

parent 1856be48
# Don't check auto-generated stuff into git
node_modules
coverage
lib
# Cruft
.DS_Store
......
......@@ -51,7 +51,7 @@ npm install --save ethjs-provider-signer
const SignerProvider = require('ethjs-provider-signer');
const Eth = require('ethjs-query');
const provider = new SignerProvider('http://ropsten.infura.io', {
privateKey: (account, cb) => cb(null, '0x...privateKey...'),
signTransaction: (rawTx, cb) => cb(null, SignerProvider.sign(rawTx, '0x...privateKey...')),
});
const eth = new Eth(provider);
......@@ -68,7 +68,11 @@ eth.sendTransaction({
A simple wrapper module for `ethjs-provider-http` which allows you to sign sendTransaction payloads. It simply takes the sendTransaction data, signs it, and changes the payload method from `eth_sendTransaction` to `eth_sendRawTransaction`, then sends the payload.
The `privateKey` method is called everytime a payload must be signed. It provides the account address in question. The return should be a single privateKey string.
The `signTransaction` method is called everytime a payload must be signed. It provides the raw transaction data, a handy raw transaction signing method and a callback to be fired. The callback must return a single signed alphanumeric hex data payload of the signed raw transaction.
The optionally required signing method `SignerProvider.sign` will sign the raw transaction with your specified private key.
The provided `SignerProvider.sign` method intakes the `rawTx` transaction data and the `privateKey` hex for signing. It returns the hexified string data of the signed transaction.
## Contributing
......
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -17,7 +17,7 @@ should not need to be touched.
For more in-depth structure, see the developer-guide.md.
*(If they do have to be changed, please [submit an issue](https://github.com/ethjs/ethjs-provider-http/issues)!)*
*(If they do have to be changed, please [submit an issue](https://github.com/ethjs/ethjs-provider-signer/issues)!)*
### Testing
......
......@@ -3,6 +3,7 @@
All information regarding contributing to and progressing `ethjs-provider-signer` module can be found in this document.
## Install
```
npm install --save ethjs-provider-signer
```
......@@ -15,18 +16,46 @@ npm install
```
## Test
```
npm test
```
## Build
```
npm run build
```
## Linting
```
npm run lint
```
## Travis-ci and Coveralls Testing
Note, this will generate the coveralls report locally.
Note, this will generate a `coveralls` report locally.
```
npm run test-travis
```
You can find the coveralls report and view the percentages and stats, by going to the [index.html](coverage/lcov-report/index.html) file generated after running the `test-travis` script. Open this in Chrome to see the generated report. Travis will run mocha as usual, but collect information about the testing coverage. This report will be sent by TravisCI during the automated build process.
## Build Staging
The build staging for this module is as follows:
1. Cleanup
2. Linting
3. Testing
4. Babel processing (output to lib)
5. Webpack (output to dist)
6. Webpack production (output to dist)
7. Retest lib folder for babel processing solidity
8. Report build stats
## Folder Structure
All module source code is found in the `src` directory. All module helper scripts can be found in the `scripts` folder. These will not need to be touched, and are purely configuration for this repository.
......@@ -34,21 +63,34 @@ All module source code is found in the `src` directory. All module helper script
```
./ethjs-provider-signer
./.github
./dist
./lib
./tests
./internals
./webpack
./coverage
./docs
./src
./tests
```
## Dependancies
- "xhr2": "0.1.3" -- https://www.npmjs.com/package/xhr2
Note, the `./lib` dir is generated from the babel build staging. `./coverage` is generated from the `npm run test-travis` script. All internals and helper scripts (i.e. `webpack`) are in `./internals`. All distribution builds are in `./dist` (usually a minified and unminified production build of the package).
## NPM Practice
Across all `ethjs-` repos, we enforce version hardening (i.e. "0.0.3" not "^0.0.3"). We want to reduce potential hazardous install changes from dependancies as much as possible to ensure package preformace, testing, security and design. Please make sure all your commits and PR's are version hardend if you are installing or removing new packages.
## Chanelog
After build staging it is the `lib` folder which actually gets published to NPM. This allows for easy inclusion into other modules which may not use babel transpiling or which may not support es2015+.
## NPM/Node Version Requirements
`ethjs` requires you have:
- `nodejs` -v 6.5.0+
- `npm` -v 3.0+
This is a requirement to run, test, lint and build this module.
## Changelog
All relevant changes are notated in the `CHANGELOG.md` file, moniter this file for changes to this repository.
......@@ -58,8 +100,8 @@ Across all `ethjs-` repos, we enforce mandatory travis-ci and coveralls testing.
## Contributing
Please help better the ecosystem by submitting issues and pull requests to default. We need all the help we can get to build the absolute best linting standards and utilities. We follow the AirBNB linting standard. Please read more about contributing to `ethjs-provider-signer` in the `.github/CONTRIBUTING.md`.
Please help better the ecosystem by submitting issues and pull requests. We need all the help we can get to build the absolute best linting standards and utilities. We follow the AirBNB linting standard. Please read more about contributing to `ethjs-provider-signer` in the `.github/CONTRIBUTING.md`.
## Licence
This project is licensed under the MIT license, Copyright (c) 2016 weifund. For more information see LICENSE.
This project is licensed under the MIT license, Copyright (c) 2016 Nick Dodson. For more information see LICENSE.
......@@ -38,15 +38,15 @@ Intakes a `provider` URL specified as a string, and an options object where the
**Parameters**
- `provider` **String** the URL path to your local Http RPC enabled Ethereum node (e.g. `http://localhost:8545`) or a service node system like [Infura.io](http://infura.io) (e.g. `http://ropsten.infura.io`).
- `options` **Object** the options object where the `privateKey` method and `timeout` property is specified.
- `options` **Object** the options object where the `signTransaction` method and `timeout` property is specified.
Example options **Object**:
```js
const options = {
privateKey: (account, cb) => {
if (account) {
cb(null, '0x...privateKey...');
signTransaction: (rawTx, cb) => {
if (rawTx.from === '0x...') {
cb(null, SignerProvider.sign(rawTx, '0x...privateKey...'));
} else {
cb('some error');
}
......@@ -60,10 +60,9 @@ Result `SignerProvider` **Object**.
```js
const SignerProvider = require('ethjs-provider-signer');
const Eth = require('ethjs-query');
const provider = new SignerProvider('http://ropsten.infura.io', {
privateKey: (account, cb) => cb(null, '0x...privateKey...'),
});
const eth = new Eth(provider);
const eth = new Eth(new SignerProvider('http://ropsten.infura.io', {
signTransaction: (rawTx, cb) => cb(null, SignerProvider.sign(rawTx, '0x...privateKey...')),
}));
eth.sendTransaction({
from: '0x407d73d8a49eeb85d32cf465507dd71d507100c1',
......@@ -74,6 +73,47 @@ eth.sendTransaction({
// results null 0x... (transaction hash)
```
### SignerProvider.sign
[index.js:ethjs-provider-signer](../../../blob/master/src/index.js "Source code on GitHub")
Intakes an Ethereum RPC standard raw transaction object and Ethereum standard private key as a hexified alphanumeric string. Outputs signed transaction data as a hex string.
**Parameters**
- `rawTx` **Object** the raw transaction object (i.e. `{ from: '0x..', to: '0x..', data: '0x', gas: 300000 }`)
- `privateKey` **String** the options object where the `signTransaction` method and `timeout` property is specified.
Result signed transaction data **String**
```js
const SignerProvider = require('ethjs-provider-signer');
const signedHexData = SignerProvider.sign({
from: '0x407d73d8a49eeb85d32cf465507dd71d507100c1',
gas: 300000,
data: '0x',
}, '0xd35c58355a1sc095c7074837467382924180748768s2258ef5f7fa384e6fcb3s');
// result '0xbd685c98ec39490f50d15c67ba2a8e9b5b1d6d7601fca80b295e7d717446bd8b7127ea4871e996cdc8cae7690408b4e800f60ddac49d2ad34180e68f1da0aaf001';
```
## Browser Builds
`ethjs` provides production distributions for all of its modules that are ready for use in the browser right away. Simply include either `dist/ethjs-provider-signer.js` or `dist/ethjs-provider-signer.min.js` directly into an HTML file to start using this module. Note, an `SignerProvider` object is made available globally.
```html
<script type="text/javascript" src="ethjs-provider-signer.min.js"></script>
<script type="text/javascript">
new SignerProvider(...);
</script>
```
Note, even though `ethjs` should have transformed and polyfilled most of the requirements to run this module across most modern browsers. You may want to look at an additional polyfill for extra support.
Use a polyfill service such as `Polyfill.io` to ensure complete cross-browser support:
https://polyfill.io/
## Other Awesome Modules, Tools and Frameworks
- [web3.js](https://github.com/ethereum/web3.js) -- the original Ethereum swiss army knife **Ethereum Foundation**
......
var webpack = require('webpack'); // eslint-disable-line
var path = require('path'); // eslint-disable-line
var env = process.env.NODE_ENV; // eslint-disable-line
var filename = 'ethjs-provider-signer'; // eslint-disable-line
var library = 'SignerProvider'; // eslint-disable-line
var config = { // eslint-disable-line
entry: [
'babel-polyfill',
'./lib/index.js',
],
module: {
loaders: [
{
test: /\.js$/,
loaders: ['babel-loader'],
include: /src|node_modules\/ethereumjs-tx/,
},
{
test: /\.json$/,
loader: 'json',
},
],
},
devtool: 'cheap-module-source-map',
output: {
path: 'dist',
filename: filename + '.js', // eslint-disable-line
library: library, // eslint-disable-line
libraryTarget: 'umd',
umdNamedDefine: true,
},
plugins: [
new webpack.BannerPlugin({ banner: ' /* eslint-disable */ ', raw: true, entryOnly: true }),
new webpack.BannerPlugin({ banner: ' /* eslint-disable */ ', raw: true }),
new webpack.optimize.OccurrenceOrderPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(env),
}),
],
};
if (env === 'production') {
config.output.filename = filename + '.min.js'; // eslint-disable-line
config.plugins
.push(new webpack.optimize.UglifyJsPlugin({
compressor: {
pure_getters: true,
unsafe: true,
unsafe_comps: true,
warnings: false,
screw_ie8: false,
},
mangle: {
screw_ie8: false,
},
output: {
screw_ie8: false,
},
}));
config.plugins.push(new webpack.optimize.DedupePlugin());
}
module.exports = config;
{
"name": "ethjs-provider-signer",
"version": "0.0.2",
"version": "0.1.0",
"description": "A simple web3 standard provider object that signs raw transactions.",
"main": "src/index.js",
"main": "lib/index.js",
"browser": "dist/ethjs-provider-signer.js",
"files": [
"dist",
"internals",
"lib",
"src"
],
"scripts": {
"start": "npm test",
"test": "mocha src/tests/**/*.js -R spec --timeout 2000000",
"release": "npmpub",
"pretest": "npm run lint",
"prepublish": "npm run build",
"prebuild": "npm run build:clean && npm run test",
"build:clean": "npm run test:clean && rimraf ./dist",
"build:commonjs": "cross-env BABEL_ENV=commonjs babel src --out-dir lib --copy-files",
"build:umd": "cross-env BABEL_ENV=commonjs NODE_ENV=development webpack --config ./internals/webpack/webpack.config.js --progress",
"build:umd:min": "cross-env BABEL_ENV=commonjs NODE_ENV=production webpack --config ./internals/webpack/webpack.config.js --progress --profile",
"build": "npm run build:commonjs && npm run test:lib && npm run build:umd && npm run build:umd:min",
"lint": "npm run lint:js",
"lint:eslint": "eslint --ignore-path .gitignore",
"lint:eslint": "eslint --ignore-path .gitignore --ignore-pattern **/**.min.js",
"lint:js": "npm run lint:eslint -- . ",
"lint:staged": "lint-staged",
"test:clean": "rimraf ./coverage",
"test": "mocha ./src/tests/**/*.js -R spec --timeout 2000000",
"test:lib": "mocha ./lib/tests/**/*.js -R spec --timeout 2000000",
"test-travis": "node ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha -- src/tests/**/*.js -R spec --timeout 2000000",
"coveralls": "npm run test-travis && cat ./coverage/lcov.info | coveralls"
},
......@@ -19,30 +35,129 @@
"type": "git",
"url": "git+ssh://[email protected]/ethjs/ethjs-provider-signer.git"
},
"babel": {
"plugins": [
[
"transform-es2015-template-literals",
{
"loose": true
}
],
"transform-es2015-literals",
"transform-es2015-function-name",
"transform-es2015-arrow-functions",
"transform-es2015-block-scoped-functions",
[
"transform-es2015-classes",
{
"loose": true
}
],
"transform-es2015-object-super",
"transform-es2015-shorthand-properties",
[
"transform-es2015-computed-properties",
{
"loose": true
}
],
[
"transform-es2015-for-of",
{
"loose": true
}
],
"transform-es2015-sticky-regex",
"transform-es2015-unicode-regex",
"check-es2015-constants",
[
"transform-es2015-spread",
{
"loose": true
}
],
"transform-es2015-parameters",
[
"transform-es2015-destructuring",
{
"loose": true
}
],
"transform-es2015-block-scoping",
"transform-object-rest-spread",
"transform-es3-member-expression-literals",
"transform-es3-property-literals"
],
"env": {
"commonjs": {
"plugins": [
[
"transform-es2015-modules-commonjs",
{
"loose": true
}
]
]
}
}
},
"dependencies": {
"ethereumjs-tx": "1.1.4",
"ethjs-util": "0.0.4",
"ethjs-provider-http": "0.0.1"
"ethjs-provider-http": "^0.1.2",
"ethjs-util": "^0.1.1"
},
"devDependencies": {
"web3": "0.17.0-beta",
"ethereumjs-testrpc": "3.0.2",
"ethjs-contract": "0.1.0",
"ethjs-query": "0.0.5",
"babel-core": "6.18.2",
"babel-cli": "6.18.0",
"babel-eslint": "7.1.0",
"babel-loader": "6.2.8",
"babel-polyfill": "6.16.0",
"babel-plugin-transform-runtime": "^6.15.0",
"babel-plugin-check-es2015-constants": "6.8.0",
"babel-plugin-transform-class-properties": "6.18.0",
"babel-plugin-transform-es2015-arrow-functions": "6.8.0",
"babel-plugin-transform-es2015-block-scoped-functions": "6.8.0",
"babel-plugin-transform-es2015-block-scoping": "6.18.0",
"babel-plugin-transform-es2015-classes": "6.18.0",
"babel-plugin-transform-es2015-computed-properties": "6.8.0",
"babel-plugin-transform-es2015-destructuring": "6.19.0",
"babel-plugin-transform-es2015-for-of": "6.18.0",
"babel-plugin-transform-es2015-function-name": "6.9.0",
"babel-plugin-transform-es2015-literals": "6.8.0",
"babel-plugin-transform-es2015-modules-commonjs": "6.18.0",
"babel-plugin-transform-es2015-object-super": "6.8.0",
"babel-plugin-transform-es2015-parameters": "6.18.0",
"babel-plugin-transform-es2015-shorthand-properties": "6.18.0",
"babel-plugin-transform-es2015-spread": "6.8.0",
"babel-plugin-transform-es2015-sticky-regex": "6.8.0",
"babel-plugin-transform-es2015-template-literals": "6.8.0",
"babel-plugin-transform-es2015-unicode-regex": "6.11.0",
"babel-plugin-transform-es3-member-expression-literals": "6.5.0",
"babel-plugin-transform-es3-property-literals": "6.5.0",
"babel-plugin-transform-object-rest-spread": "6.19.0",
"babel-register": "6.18.0",
"chai": "3.5.0",
"check-es3-syntax-cli": "0.1.3",
"coveralls": "2.11.9",
"cross-env": "1.0.7",
"eslint": "2.10.1",
"eslint-config-airbnb": "9.0.1",
"eslint-import-resolver-webpack": "0.2.4",
"eslint-plugin-import": "1.8.0",
"eslint-plugin-jsx-a11y": "1.2.0",
"eslint-plugin-react": "5.1.1",
"ethereumjs-testrpc": "3.0.2",
"ethjs-contract": "0.1.0",
"ethjs-query": "0.0.5",
"eventsource-polyfill": "0.9.6",
"istanbul": "0.4.5",
"json-loader": "0.5.4",
"lint-staged": "1.0.1",
"mocha": "3.1.2",
"pre-commit": "1.1.3"
"pre-commit": "1.1.3",
"rimraf": "2.3.4",
"web3": "0.17.0-beta",
"webpack": "2.1.0-beta.15"
},
"engines": {
"npm": ">=3",
......@@ -59,21 +174,6 @@
"url": "https://github.com/ethjs/ethjs-provider-signer/issues"
},
"homepage": "https://github.com/ethjs/ethjs-provider-signer#readme",
"babel": {
"presets": [
"es2015"
],
"plugins": [
[
"module-resolver",
{
"root": [
"./src"
]
}
]
]
},
"lint-staged": {
"lint:eslint": "*.js"
},
......@@ -113,5 +213,5 @@
]
}
},
"pre-commit": "lint:staged"
"pre-commit": "build"
}
......@@ -7,7 +7,7 @@ module.exports = SignerProvider;
function SignerProvider(path, options) {
if (!(this instanceof SignerProvider)) { throw new Error('[ethjs-provider-signer] the SignerProvider instance requires the "new" flag in order to function normally (e.g. `const eth = new Eth(new SignerProvider(...));`).'); }
if (typeof options !== 'object') { throw new Error(`[ethjs-provider-signer] the SignerProvider requires an options object be provided with the 'privateKey' property specified, you provided type ${typeof options}.`); }
if (typeof options.privateKey !== 'function') { throw new Error(`[ethjs-provider-signer] the SignerProvider requires an options object be provided with the 'privateKey' property specified, you provided type ${typeof options.privateKey} (e.g. 'const eth = new Eth(new SignerProvider("http://ropsten.infura.io", { privateKey: (account, cb) => cb(null, 'some private key') }));').`); }
if (typeof options.signTransaction !== 'function') { throw new Error(`[ethjs-provider-signer] the SignerProvider requires an options object be provided with the 'signTransaction' property specified, you provided type ${typeof options.privateKey} (e.g. 'const eth = new Eth(new SignerProvider("http://ropsten.infura.io", { privateKey: (account, cb) => cb(null, 'some private key') }));').`); }
const self = this;
self.options = options;
......@@ -29,35 +29,33 @@ function shimEthereumJSTxObject(rawTx) {
return rawTxMutation;
}
SignerProvider.sign = function signTx(rawTx, privateKey) {
// format raw tx data
const shimmedRawTx = Object.assign({}, shimEthereumJSTxObject(rawTx));
// sign tx object, serilize, convert to hex, privateKey not stored in temp data
const signedHexPayload = new Tx(shimmedRawTx);
signedHexPayload.sign(new Buffer(ethUtil.stripHexPrefix(privateKey), 'hex'));
// ensure hex is prefixed
return `0x${signedHexPayload.serialize().toString('hex')}`;
};
SignerProvider.prototype.sendAsync = function (payload, callback) { // eslint-disable-line
const self = this;
if (payload.method === 'eth_sendTransaction') {
self.options.privateKey(payload.params[0].from, (keyError, privateKey) => { // eslint-disable-line
self.options.signTransaction(payload.params[0], (keyError, signedHexPayload) => { // eslint-disable-line
if (!keyError) {
try {
// create new output payload
const outputPayload = Object.assign({}, {
id: payload.id,
jsonrpc: payload.jsonrpc,
method: 'eth_sendRawTransaction',
params: [],
});
// format raw tx data
const rawTx = Object.assign({}, shimEthereumJSTxObject(payload.params[0]));
// sign tx object, serilize, convert to hex, privateKey not stored in temp data
const signedHexPayload = new Tx(rawTx);
signedHexPayload.sign(new Buffer(ethUtil.stripHexPrefix(privateKey), 'hex'));
// ensure hex is prefixed
outputPayload.params = [`0x${signedHexPayload.serialize().toString('hex')}`];
// create new output payload
const outputPayload = Object.assign({}, {
id: payload.id,
jsonrpc: payload.jsonrpc,
method: 'eth_sendRawTransaction',
params: [signedHexPayload],
});
// send payload
self.provider.sendAsync(outputPayload, callback);
} catch (errorWhileSigning) {
return callback(new Error(`[ethjs-provider-signer] while signing your sendTransaction payload: ${JSON.stringify(errorWhileSigning)}`), null);
}
// send payload
self.provider.sendAsync(outputPayload, callback);
} else {
return callback(new Error(`[ethjs-provider-signer] while signing your sendTransaction payload: ${JSON.stringify(keyError)}`), null);
}
......
......@@ -16,12 +16,13 @@ describe('SignerProvider', () => {
describe('constructor', () => {
it('should construct properly', (done) => {
const provider = new SignerProvider('http://localhost:5001', {
privateKey: (account, cb) => cb(null, '0xc55c58355a32c095c7074837467382924180748768422589f5f75a384e6f3b33'),
signTransaction: (rawTx, cb) => cb(null, SignerProvider.sign(rawTx, '0xc55c58355a32c095c7074837467382924180748768422589f5f75a384e6f3b33')),
});
assert.equal(typeof provider, 'object');
assert.equal(typeof SignerProvider.sign, 'function');
assert.equal(typeof provider.options, 'object');
assert.equal(typeof provider.options.privateKey, 'function');
assert.equal(typeof provider.options.signTransaction, 'function');
assert.equal(provider.timeout, 0);
setTimeout(() => {
......@@ -40,7 +41,7 @@ describe('SignerProvider', () => {
describe('functionality', () => {
it('should perform normally for calls', (done) => {
const provider = new SignerProvider('http://localhost:5001', {
privateKey: (account, cb) => cb(null, '0xc55c58355a32c095c7074837467382924180748768422589f5f75a384e6f3b33'),
signTransaction: (rawTx, cb) => cb(null, SignerProvider.sign(rawTx, '0xc55c58355a32c095c7074837467382924180748768422589f5f75a384e6f3b33')),
});
const eth = new Eth(provider);
......@@ -60,7 +61,7 @@ describe('SignerProvider', () => {
it('should reconstruct sendTransaction as sendRawTransaction', (done) => {
const provider = new SignerProvider('http://localhost:5001', {
privateKey: (account, cb) => cb(null, '0xc55c58355a32c095c7074837467382924180748768422589f5f75a384e6f3b33'),
signTransaction: (rawTx, cb) => cb(null, SignerProvider.sign(rawTx, '0xc55c58355a32c095c7074837467382924180748768422589f5f75a384e6f3b33')),
});
const eth = new Eth(provider);
......@@ -72,6 +73,7 @@ describe('SignerProvider', () => {
from: accounts[0],
to: '0xc55c58355a32c095c70748374673829241807487',
data: '0x',
value: 5000,
gas: 300000,
}, (txError, txHash) => {
assert.equal(txError, null);
......@@ -81,6 +83,7 @@ describe('SignerProvider', () => {
eth.getBalance('0xc55c58355a32c095c70748374673829241807487')
.then((balanceResult) => {
assert.equal(typeof balanceResult, 'object');
assert.equal(balanceResult.toNumber(10), 5000);
done();
});
......@@ -91,7 +94,7 @@ describe('SignerProvider', () => {
it('should throw an error when key is invalid', (done) => {
const provider = new SignerProvider('http://localhost:5001', {
privateKey: (account, cb) => cb(null, '0xc23c58355132c025c707483746738294180748768422589f5f75a384e6f3b33'),
signTransaction: (rawTx, cb) => cb(null, SignerProvider.sign(rawTx, '0xc55c58355a32c095c70748s746738d92d180748768422589f5f75a384e6f3b33')),
});
const eth = new Eth(provider);
......@@ -103,6 +106,7 @@ describe('SignerProvider', () => {
from: accounts[0],
to: '0xc55c58355a32c095c70748374673829241807487',
data: '0x',
value: 5000,
gas: 300000,
}).catch((txError) => {
assert.equal(typeof txError, 'object');
......@@ -114,7 +118,7 @@ describe('SignerProvider', () => {
it('should throw an error when key error is provided', (done) => {
const provider = new SignerProvider('http://localhost:5001', {
privateKey: (account, cb) => cb(new Error('account does not have permission')),
signTransaction: (rawTx, cb) => cb(new Error('account does not have permission')),
});
const eth = new Eth(provider);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment