Skip to content
This repository was archived by the owner on Jun 14, 2024. It is now read-only.

Commit 273fd55

Browse files
committed
Adding first batch of helpers.
1 parent e6a9d3d commit 273fd55

14 files changed

+292
-2
lines changed

Diff for: .eslintrc

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
extends: "eslint:recommended"
2+
env:
3+
es6: true
4+
node: true
5+
browser: true
6+
parserOptions:
7+
ecmaVersion: 2017
8+
sourceType: module
9+
rules:
10+
no-console: off
11+
comma-dangle: [1, never]
12+
max-len: off
13+
no-mixed-spaces-and-tabs: error
14+
no-tabs: error
15+
no-use-before-define: [error, {functions: false, classes: true}]
16+
no-undefined: off
17+
object-curly-spacing: [0, never]
18+
semi: [error, never]
19+
space-before-function-paren: 0
20+
quotes: [error, single]
21+
globals:
22+
after: true
23+
afterEach: true
24+
artifacts: true
25+
before: true
26+
beforeEach: true
27+
console: true
28+
contract: true
29+
describe: true
30+
document: true
31+
expect: true
32+
fetch: true
33+
it: true
34+
navigator: true
35+
process: true
36+
URL: true
37+
window: true

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
package-lock.json

Diff for: derive.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
const secp256k1 = require('secp256k1')
3+
const toChecksumAddress = require('./to-checksum-address')
4+
const keccak256 = require('./keccak256')
5+
6+
function derive(privateKey) {
7+
8+
if (!secp256k1.privateKeyVerify(privateKey)) {
9+
throw new TypeError('Invalid private key.')
10+
}
11+
12+
const publicKey = secp256k1.publicKeyCreate(privateKey, false).slice(1)
13+
14+
const address = toChecksumAddress(keccak256(publicKey).slice(-20))
15+
16+
return {
17+
publicKey: '0x' + publicKey.toString('hex'),
18+
address
19+
}
20+
}
21+
22+
module.exports = derive

Diff for: is-promise.js

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
2+
const { isFunction } = require('lodash')
3+
const { get } = require('lodash')
4+
5+
/**
6+
* Check if `value` is Promise/A+.
7+
*
8+
* @param {any} value
9+
* @return {boolean}
10+
*/
11+
function isPromise(value) {
12+
return isFunction(get(value, 'then'))
13+
}
14+
15+
module.exports = isPromise

Diff for: keccak256.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
const createKeccakHash = require('keccak')
3+
4+
function keccak256(value) {
5+
return createKeccakHash('keccak256').update(value).digest()
6+
}
7+
8+
module.exports = keccak256

Diff for: make-ganeche-account.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
2+
const derive = require('./derive')
3+
4+
const DEFAULT_BALANCE = '00000000000000000000000000000000ffffffffffffffffffffffffffffffff'
5+
6+
function makeGenacheAccount(secretKey) {
7+
const { publicKey, address } = derive(secretKey)
8+
return { balance: DEFAULT_BALANCE, secretKey: '0x' + secretKey.toString('hex'), publicKey, address }
9+
}
10+
11+
module.exports = makeGenacheAccount

Diff for: make-solc.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
2+
const sh = require('./sh-sync')
3+
4+
const DEFAULT_SOLC = '/usr/local/bin/solc'
5+
6+
/**
7+
* Make solidity compiler for `root` base path with contracts.
8+
*
9+
* Usage:
10+
*
11+
* const solc = makeCompiler(`${__dirname}/../contracts`)
12+
* const { abi, bin } = solc('Foo.sol')
13+
*
14+
* @param {string} root Contracts' root directory.
15+
* @param {string} 1.solc = '/usr/local/bin/solc' Solidity compiler executable path.
16+
* @return {function} Compiler function.
17+
*/
18+
function makeSolc(root, { solc = DEFAULT_SOLC } = {}) {
19+
20+
function compile(name) {
21+
const { stdout, stderr } = sh(`${solc} --combined-json abi,bin ${root}/${name}`)
22+
if (stderr) {
23+
throw new Error('stderr', { stdout, stderr })
24+
}
25+
const parsed = JSON.parse(stdout)
26+
const r = {}
27+
for (const [key, { bin, abi }] of Object.entries(parsed.contracts)) {
28+
r[key.split(':')[1]] = { abi: JSON.parse(abi), bin: '0x' + bin }
29+
}
30+
return r
31+
}
32+
33+
return compile
34+
}
35+
36+
module.exports = makeSolc

Diff for: package.json

+15-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"private": true,
33
"name": "bmono",
44
"version": "0.0.1",
5-
"description": "",
5+
"description": "Blockchain monorepo/npm - all the little things to prototype blockchain based systems fast.",
66
"main": "index.js",
77
"scripts": {
88
"test": "mocha"
@@ -16,5 +16,18 @@
1616
"bugs": {
1717
"url": "https://github.com/appliedblockchain/bmono/issues"
1818
},
19-
"homepage": "https://github.com/appliedblockchain/bmono#readme"
19+
"homepage": "https://github.com/appliedblockchain/bmono#readme",
20+
"devDependencies": {
21+
"chai": "^4.1.2",
22+
"eslint": "^4.15.0",
23+
"mocha": "^5.0.0"
24+
},
25+
"dependencies": {
26+
"keccak": "^1.4.0",
27+
"lodash": "^4.17.4",
28+
"progress": "^2.0.0",
29+
"secp256k1": "^3.4.0",
30+
"sprintf": "^0.1.5",
31+
"web3": "^0.20.4"
32+
}
2033
}

Diff for: progress.js

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
2+
const sprintf = require('sprintf')
3+
const Progress = require('progress')
4+
5+
/**
6+
* Usage:
7+
*
8+
* const progress = makeProgress('foo', 100)
9+
* progress.tick()
10+
*
11+
* @param {string} name
12+
* @param {number} total
13+
* @return {Progress}
14+
*/
15+
function makeProgress(name, total) {
16+
return new Progress(sprintf('%20s [:bar] :percent :current/:total :rate/s :etas', name), {
17+
total, width: 20, incomplete: ' ', renderThrottle: 1000 / 12, clear: true
18+
})
19+
}
20+
21+
module.exports = makeProgress

Diff for: puts.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
2+
const sprintf = require('sprintf')
3+
4+
function puts(...args) {
5+
console.log(sprintf(...args))
6+
}
7+
8+
module.exports = puts

Diff for: sh-async.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
const { exec } = require('child_process')
3+
4+
/**
5+
* Execute simple shell command (async wrapper).
6+
*
7+
* @param {string} cmd
8+
* @return {{ stdout: string, stderr: string }}
9+
*/
10+
async function shAsync(cmd) {
11+
return new Promise(function (resolve, reject) {
12+
exec(cmd, (err, stdout, stderr) => {
13+
if (err) {
14+
reject(err)
15+
} else {
16+
resolve({ stdout, stderr })
17+
}
18+
})
19+
})
20+
}
21+
22+
module.exports = shAsync

Diff for: sh-sync.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
const { execSync } = require('child_process')
3+
const { Writable } = require('stream')
4+
5+
/**
6+
* Execute simple shell command (sync).
7+
*
8+
* @param {string} cmd
9+
* @return {object} { stdout: string, stderr: string }
10+
*/
11+
function shSync(cmd) {
12+
let stderr = ''
13+
const stdout = execSync(cmd, {
14+
stderr: (new Writable()).on('data', _1 => stderr += _1),
15+
encoding: 'utf8'
16+
})
17+
return { stdout, stderr }
18+
}
19+
20+
module.exports = shSync

Diff for: to-checksum-address.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
2+
const createKeccakHash = require('keccak')
3+
const { isBuffer } = require('lodash')
4+
const { isString } = require('lodash')
5+
6+
function toChecksumAddress(value) {
7+
8+
if (isBuffer(value)) {
9+
if (value.length !== 20) {
10+
throw new TypeError(`Expected buffer size 20, got ${value.length}.`)
11+
}
12+
return toChecksumAddress('0x' + value.toString('hex'))
13+
}
14+
15+
if (!isString(value)) {
16+
throw new TypeError(`Expected string, got ${typeof value}.`)
17+
}
18+
19+
if (value.length !== 2 + 20 * 2) {
20+
throw new TypeError(`Invalid input size ${value.length}, expected 2 + 20 * 2.`)
21+
}
22+
23+
const hex = value.slice(2).toLowerCase()
24+
const hash = createKeccakHash('keccak256').update(hex).digest('hex')
25+
return '0x' + hex
26+
.split('')
27+
.map((c, i) => parseInt(hash[i], 16) >= 8 ? c.toUpperCase() : c)
28+
.join('')
29+
}
30+
31+
module.exports = toChecksumAddress

Diff for: web3-compile-deploy.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
const assert = require('assert')
3+
const Web3 = require('web3')
4+
const { each, set } = require('lodash')
5+
6+
const nullAddress = '0x0000000000000000000000000000000000000000'
7+
8+
/**
9+
* Usage:
10+
*
11+
* const solc = require('bmono/make-solc')(`${__dirname}/../contracts`)
12+
* require('bmono/web3-compile-deploy')(solc)
13+
*
14+
* const Web3 = require('web3')
15+
* const web3 = new Web3(...)
16+
* web3.compile('Foo.sol')
17+
* const foo = await web3.deploy('Foo', [], { from, gas })
18+
*
19+
* @param {solc} solc
20+
*/
21+
function web3CompileDeploy(solc) {
22+
23+
Web3.prototype.require = function (filename, { from } = {}) {
24+
each(solc(filename), ({ abi, bin: data }, key) => {
25+
set(this, ['ctr', key], new this.eth.Contract(abi, { from, data }))
26+
})
27+
return this.ctr
28+
}
29+
30+
Web3.prototype.deploy = async function (name, args, { from, gas } = {}) {
31+
const result = await this.ctr[name]
32+
.deploy({ arguments: args })
33+
.send({
34+
from,
35+
gas
36+
})
37+
assert(result.options.address !== nullAddress, 'Expected deployed contract to have an address.')
38+
result.setProvider(this.currentProvider)
39+
return result
40+
}
41+
42+
}
43+
44+
module.exports = web3CompileDeploy

0 commit comments

Comments
 (0)