fixed: modify keytool to comply to eth-lib

@types
neeboo 6 years ago
parent 51eb43237f
commit 72a1442ec5
  1. 4
      .tsconfig.json
  2. 1
      examples/temp.html
  3. 23
      examples/testNode.js
  4. 7
      package.json
  5. 11
      packages/harmony-account/package.json
  6. 55
      packages/harmony-account/src/account.ts
  7. 1
      packages/harmony-account/src/index.ts
  8. 0
      packages/harmony-account/src/types.ts
  9. 14
      packages/harmony-account/tsconfig.json
  10. 12
      packages/harmony-crypto/package.json
  11. 43
      packages/harmony-crypto/src/bytes.ts
  12. 12
      packages/harmony-crypto/src/errors.ts
  13. 6
      packages/harmony-crypto/src/keccak256.ts
  14. 21
      packages/harmony-crypto/src/keyTool.ts
  15. 0
      packages/harmony-crypto/src/types.ts
  16. 4
      packages/harmony-crypto/tsconfig.json
  17. 9
      packages/harmony-utils/package.json
  18. 1
      packages/harmony-utils/src/index.ts
  19. 15
      packages/harmony-utils/src/validators.ts
  20. 8
      packages/harmony-utils/tsconfig.json
  21. 4
      scripts/packages.js
  22. 2
      scripts/packagesList.js
  23. 8
      scripts/packagesTs.ts
  24. 5
      scripts/rollup/bundleBrowser.js
  25. 2
      scripts/rollup/getDependencies.js
  26. 8
      scripts/tsconfig.json
  27. 49
      scripts/typings/schema.ts
  28. 0
      tsconfig.base.json
  29. 8
      tsconfig.json
  30. 0
      tsconfig.test.json
  31. 2
      webpack.config.js

@ -1,4 +0,0 @@
{
"files": [],
"references": []
}

@ -34,6 +34,7 @@
<div id="root"> <div id="root">
</div> </div>
<script src="../dist/HarmonyAccount.browser.js"></script>
<script src="../dist/HarmonyCrypto.browser.js"></script> <script src="../dist/HarmonyCrypto.browser.js"></script>

@ -0,0 +1,23 @@
const { Account } = require('../packages/harmony-account/lib/index.js');
const {
getAddressFromPublicKey,
} = require('../packages/harmony-crypto/lib/index.js');
const {
isAddress,
isPrivateKey,
} = require('../packages/harmony-utils/lib/index.js');
// const a = Account.new();
// console.log(isAddress(a.checksumAddress));
const importKey =
'0x87b3ec80f36f9553fb63624d0805d87cfe461145c7be972d23db95fb1a53b1e7';
const c = Account.add(importKey);
// console.log(isPrivateKey(importKey));
console.log(c);
console.log(getAddressFromPublicKey(c.publicKey));

@ -13,7 +13,7 @@
"build:ts": "tsc -b tsconfig.json", "build:ts": "tsc -b tsconfig.json",
"bundle": "ts-node -P scripts/tsconfig.json scripts/bundle.ts umd,esm", "bundle": "ts-node -P scripts/tsconfig.json scripts/bundle.ts umd,esm",
"clean": "lerna clean --yes && lerna run clean && rimraf includes", "clean": "lerna clean --yes && lerna run clean && rimraf includes",
"schema": "ts-node -P scripts/tsconfig.json scripts/schema.ts core", "schema": "ts-node -P scripts/tsconfig.json scripts/typings/schema.ts core",
"test": "cross-env TEST_ENV=unit jest -c jest.config.js --rootDir=.", "test": "cross-env TEST_ENV=unit jest -c jest.config.js --rootDir=.",
"test:build": "cross-env TEST_ENV=unit jest -c jest.build.config.js", "test:build": "cross-env TEST_ENV=unit jest -c jest.build.config.js",
"test:integration": "cross-env TEST_ENV=integration jest -c jest.iconfig.js --runInBand --verbose --collectCoverage=false", "test:integration": "cross-env TEST_ENV=integration jest -c jest.iconfig.js --runInBand --verbose --collectCoverage=false",
@ -93,12 +93,11 @@
"tslint": "^5.11.0", "tslint": "^5.11.0",
"tslint-config-prettier": "^1.15.0", "tslint-config-prettier": "^1.15.0",
"typescript": "^3.2", "typescript": "^3.2",
"typescript-json-schema": "^0.32.0", "typescript-json-schema": "^0.36.0",
"uglifyjs-webpack-plugin": "^2.1.2", "uglifyjs-webpack-plugin": "^2.1.2",
"webpack": "^4.20.2", "webpack": "^4.20.2",
"webpack-command": "^0.4.1", "webpack-command": "^0.4.1",
"webpack-node-externals": "^1.7.2" "webpack-node-externals": "^1.7.2"
}, },
"dependencies": { "dependencies": {}
}
} }

@ -1,11 +1,16 @@
{ {
"name": "harmony-account", "name": "@harmony/account",
"version": "0.0.1", "version": "0.0.1",
"description": "account and wallet for harmony", "description": "account and wallet for harmony",
"main": "index.js", "main": "lib/index.js",
"typings":"lib/index.d.ts",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"author": "neeboo@firestack.one", "author": "neeboo@firestack.one",
"license": "ISC" "license": "ISC",
"dependencies": {
"@harmony/crypto": "^0.0.1",
"@harmony/utils": "^0.0.1"
}
} }

@ -0,0 +1,55 @@
import {
generatePrivateKey,
getAddressFromPrivateKey,
getPubkeyFromPrivateKey,
toChecksumAddress,
} from '@harmony/crypto';
import { isPrivateKey } from '@harmony/utils';
class Account {
static new(): Account {
const newAcc = new Account()._new();
return newAcc;
}
static add(key: string): Account {
const newAcc = new Account()._import(key);
return newAcc;
}
privateKey?: string;
publicKey?: string;
address?: string;
get checksumAddress(): string {
return this.address ? toChecksumAddress(this.address) : '';
}
constructor(key?: string) {
if (key === null) {
this._new();
}
}
private _new(): Account {
const prv = generatePrivateKey();
if (!isPrivateKey(prv)) {
throw new Error('key gen failed');
}
this.privateKey = prv;
this.publicKey = getPubkeyFromPrivateKey(this.privateKey);
this.address = getAddressFromPrivateKey(this.privateKey);
return this;
}
private _import(key: string): Account {
if (!isPrivateKey(key)) {
throw new Error(`${key} is not PrivateKey`);
}
this.privateKey = key;
this.publicKey = getPubkeyFromPrivateKey(this.privateKey);
this.address = getAddressFromPrivateKey(this.privateKey);
return this;
}
}
export { Account };

@ -0,0 +1 @@
export * from './account';

@ -0,0 +1,14 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"baseUrl": ".",
"paths": { "*": ["types/*"] },
"outDir": "lib",
"rootDir": "src"
},
"include": ["src", "../../typings/**/*.d.ts"],
"references": [
{ "path": "../harmony-crypto" },
{ "path": "../harmony-utils" }
]
}

@ -1,12 +1,20 @@
{ {
"name": "harmony-crypto", "name": "@harmony/crypto",
"version": "0.0.1", "version": "0.0.1",
"description": "crypto libraries for harmony", "description": "crypto libraries for harmony",
"main": "index.js", "main": "lib/index.js",
"node": "lib/index.js",
"browser": "dist/index.js",
"module": "dist/index.js",
"jsnext:main": "dist/index.js",
"typings":"lib/index.d.ts",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },
"author": "neeboo@firestack.one", "author": "neeboo@firestack.one",
"publishConfig": {
"access": "public"
},
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"aes-js": "^3.1.2", "aes-js": "^3.1.2",

@ -31,7 +31,9 @@ function addSlice(array: Uint8Array): Uint8Array {
// tslint:disable-next-line: only-arrow-functions // tslint:disable-next-line: only-arrow-functions
array.slice = function() { array.slice = function() {
const args = Array.prototype.slice.call(arguments); const args = Array.prototype.slice.call(arguments);
return addSlice(new Uint8Array(Array.prototype.slice.apply(array, args))); return addSlice(
new Uint8Array(Array.prototype.slice.apply(array, [args[0], args[1]])),
);
}; };
return array; return array;
@ -59,7 +61,7 @@ export function isArrayish(value: any): value is Arrayish {
return true; return true;
} }
export function arrayify(value: Arrayish | Hexable): Uint8Array { export function arrayify(value: Arrayish | Hexable): Uint8Array | null {
if (value == null) { if (value == null) {
errors.throwError( errors.throwError(
'cannot convert null value to array', 'cannot convert null value to array',
@ -82,7 +84,7 @@ export function arrayify(value: Arrayish | Hexable): Uint8Array {
}); });
} }
if (match[1] !== '0x') { if (match !== null && match[1] !== '0x') {
errors.throwError( errors.throwError(
'hex string must have 0x prefix', 'hex string must have 0x prefix',
errors.INVALID_ARGUMENT, errors.INVALID_ARGUMENT,
@ -116,11 +118,17 @@ export function arrayify(value: Arrayish | Hexable): Uint8Array {
} }
export function concat(objects: Arrayish[]): Uint8Array { export function concat(objects: Arrayish[]): Uint8Array {
if (objects === null) {
throw new Error(`concat objects is null`);
}
const arrays = []; const arrays = [];
let length = 0; let length = 0;
// tslint:disable-next-line: prefer-for-of // tslint:disable-next-line: prefer-for-of
for (let i = 0; i < objects.length; i++) { for (let i = 0; i < objects.length; i++) {
const object = arrayify(objects[i]); const object = arrayify(objects[i]);
if (object == null) {
throw new Error('arrayify failed');
}
arrays.push(object); arrays.push(object);
length += object.length; length += object.length;
} }
@ -137,7 +145,11 @@ export function concat(objects: Arrayish[]): Uint8Array {
} }
export function stripZeros(value: Arrayish): Uint8Array { export function stripZeros(value: Arrayish): Uint8Array {
let result: Uint8Array = arrayify(value); let result: Uint8Array | null = arrayify(value);
if (result === null) {
throw new Error('arrayify failed');
}
if (result.length === 0) { if (result.length === 0) {
return result; return result;
@ -158,14 +170,16 @@ export function stripZeros(value: Arrayish): Uint8Array {
} }
export function padZeros(value: Arrayish, length: number): Uint8Array { export function padZeros(value: Arrayish, length: number): Uint8Array {
value = arrayify(value); const arrayifyValue = arrayify(value);
if (arrayifyValue === null) {
if (length < value.length) { throw new Error('arrayify failed');
}
if (length < arrayifyValue.length) {
throw new Error('cannot pad'); throw new Error('cannot pad');
} }
const result = new Uint8Array(length); const result = new Uint8Array(length);
result.set(value, length - value.length); result.set(arrayifyValue, length - arrayifyValue.length);
return addSlice(result); return addSlice(result);
} }
@ -230,7 +244,7 @@ export function hexlify(value: Arrayish | Hexable | number): string {
}); });
} }
if (match[1] !== '0x') { if (match !== null && match[1] !== '0x') {
errors.throwError( errors.throwError(
'hex string must have 0x prefix', 'hex string must have 0x prefix',
errors.INVALID_ARGUMENT, errors.INVALID_ARGUMENT,
@ -326,7 +340,7 @@ function isSignature(value: any): value is Signature {
} }
export function splitSignature(signature: Arrayish | Signature): Signature { export function splitSignature(signature: Arrayish | Signature): Signature {
let v = 0; let v: number | undefined = 0;
let r = '0x'; let r = '0x';
let s = '0x'; let s = '0x';
@ -346,13 +360,16 @@ export function splitSignature(signature: Arrayish | Signature): Signature {
v = parseInt(v, 16); v = parseInt(v, 16);
} }
let recoveryParam = signature.recoveryParam; let recoveryParam = signature.recoveryParam || 1;
if (recoveryParam == null && signature.v != null) { if (recoveryParam == null && signature.v != null) {
recoveryParam = 1 - (v % 2); recoveryParam = 1 - (typeof v !== 'number' ? 0 : v % 2);
} }
v = 27 + recoveryParam; v = 27 + recoveryParam;
} else { } else {
const bytes: Uint8Array = arrayify(signature); const bytes: Uint8Array | null = arrayify(signature);
if (bytes === null) {
throw new Error('arrayify failed');
}
if (bytes.length !== 65) { if (bytes.length !== 65) {
throw new Error('invalid signature'); throw new Error('invalid signature');
} }

@ -62,7 +62,11 @@ let _permanentCensorErrors = false;
let _censorErrors = false; let _censorErrors = false;
// @TODO: Enum // @TODO: Enum
export function throwError(message: string, code: string, params: any): never { export function throwError(
message: string,
code: string | null | undefined,
params: any,
): never {
if (_censorErrors) { if (_censorErrors) {
throw new Error('unknown error'); throw new Error('unknown error');
} }
@ -185,17 +189,17 @@ export function setLogLevel(logLevel: string): void {
LogLevel = level; LogLevel = level;
} }
function log(logLevel: string, args: any[]): void { function log(logLevel: string, args: [any?, ...any[]]): void {
if (LogLevel > LogLevels[logLevel]) { if (LogLevel > LogLevels[logLevel]) {
return; return;
} }
console.log.apply(console, args); console.log.apply(console, args);
} }
export function warn(...args: any[]): void { export function warn(...args: [any?, ...any[]]): void {
log('warn', args); log('warn', args);
} }
export function info(...args: any[]): void { export function info(...args: [any?, ...any[]]): void {
log('info', args); log('info', args);
} }

@ -3,5 +3,9 @@ import * as sha3 from 'js-sha3';
import { arrayify, Arrayish } from './bytes'; import { arrayify, Arrayish } from './bytes';
export function keccak256(data: Arrayish): string { export function keccak256(data: Arrayish): string {
return '0x' + sha3.keccak_256(arrayify(data)); const arrayified = arrayify(data);
if (arrayified) {
return '0x' + sha3.keccak_256(arrayified);
}
throw new Error('arrayify failed');
} }

@ -1,11 +1,11 @@
import elliptic from 'elliptic'; import elliptic from 'elliptic';
import * as bytes from './bytes'; import * as bytes from './bytes';
import * as errors from './errors'; import * as errors from './errors';
import { keccak256 } from './keccak256'; import { keccak256 } from './keccak256';
import { randomBytes } from './random'; import { randomBytes } from './random';
const secp256k1 = elliptic.ec('secp256k1'); const secp256k1 = elliptic.ec('secp256k1');
// const { curve } = secp256k1;
/** /**
* @function generatePrivateKey * @function generatePrivateKey
@ -32,10 +32,7 @@ export const generatePrivateKey = (): string => {
* @return {string} * @return {string}
*/ */
export const getPubkeyFromPrivateKey = (privateKey: string): string => { export const getPubkeyFromPrivateKey = (privateKey: string): string => {
const buffer = new Buffer(privateKey.slice(2), 'hex'); return '0x' + getPublic(privateKey, true);
const ecKey = secp256k1.keyFromPrivate(buffer);
const publicKey = '0x' + ecKey.getPublic(true, 'hex');
return publicKey;
}; };
/** /**
@ -44,18 +41,26 @@ export const getPubkeyFromPrivateKey = (privateKey: string): string => {
* @return {string} address with `length = 40` * @return {string} address with `length = 40`
*/ */
export const getAddressFromPrivateKey = (privateKey: string): string => { export const getAddressFromPrivateKey = (privateKey: string): string => {
const publicKey = getPubkeyFromPrivateKey(privateKey); const publicHash = '0x' + getPublic(privateKey).slice(2);
const publicKey = keccak256(publicHash);
const address = '0x' + publicKey.slice(-40); const address = '0x' + publicKey.slice(-40);
return address; return address;
}; };
export const getPublic = (privateKey: string, compress?: boolean): string => {
const ecKey = secp256k1.keyFromPrivate(privateKey.slice(2), 'hex');
return ecKey.getPublic(compress || false, 'hex');
};
/** /**
* @function getAddressFromPublicKey * @function getAddressFromPublicKey
* @param {string} publicKey - public key string * @param {string} publicKey - public key string
* @return {string} address with `length = 40` * @return {string} address with `length = 40`
*/ */
export const getAddressFromPublicKey = (publicKey: string): string => { export const getAddressFromPublicKey = (publicKey: string): string => {
const address = '0x' + publicKey.slice(-40); const ecKey = secp256k1.keyFromPublic(publicKey.slice(2), 'hex');
const publickHash = ecKey.getPublic(false, 'hex');
const address = '0x' + keccak256('0x' + publickHash.slice(2)).slice(-40);
return address; return address;
}; };
@ -80,7 +85,7 @@ export const toChecksumAddress = (address: string): string => {
for (let i = 0; i < 40; i++) { for (let i = 0; i < 40; i++) {
hashed[i] = chars[i].charCodeAt(0); hashed[i] = chars[i].charCodeAt(0);
} }
hashed = bytes.arrayify(keccak256(hashed)); hashed = bytes.arrayify(keccak256(hashed)) || hashed;
for (let i = 0; i < 40; i += 2) { for (let i = 0; i < 40; i += 2) {
if (hashed[i >> 1] >> 4 >= 8) { if (hashed[i >> 1] >> 4 >= 8) {

@ -1,4 +1,8 @@
{ {
"extends": "../../tsconfig.base.json", "extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": ["src", "../../typings/**/*.d.ts"] "include": ["src", "../../typings/**/*.d.ts"]
} }

@ -1,8 +1,13 @@
{ {
"name": "harmony-utils", "name": "@harmony/utils",
"version": "0.0.1", "version": "0.0.1",
"description": "utils for harmony", "description": "utils for harmony",
"main": "index.js", "main": "lib/index.js",
"node": "lib/index.js",
"browser": "dist/index.js",
"module": "dist/index.js",
"jsnext:main": "dist/index.js",
"typings":"lib/index.d.ts",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1"
}, },

@ -0,0 +1 @@
export * from './validators';

@ -0,0 +1,15 @@
export const isKeyString = (keyString: string, lengh: number): boolean => {
return !!keyString.replace('0x', '').match(`^[0-9a-fA-F]{${lengh}}$`);
};
export const isAddress = (address: string): boolean => {
return isKeyString(address, 40);
};
export const isPrivateKey = (privateKey: string): boolean => {
return isKeyString(privateKey, 64);
};
export const isPublicKey = (publicKey: string): boolean => {
return isKeyString(publicKey, 66);
};

@ -0,0 +1,8 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"outDir": "lib",
"rootDir": "src"
},
"include": ["src", "../../typings/**/*.d.ts"]
}

@ -1,6 +1,6 @@
export default [ export default [
// 'harmony-account, 'harmony-utils',
'harmony-crypto', 'harmony-crypto',
'harmony-account',
// 'harmony-network', // 'harmony-network',
// 'harmony-utils',
]; ];

@ -5,5 +5,7 @@ module.exports = [
// { name: 'LaksaWallet', dest: 'laksa-wallet' }, // { name: 'LaksaWallet', dest: 'laksa-wallet' },
// { name: 'LaksaHDWallet', dest: 'laksa-hd-wallet' }, // { name: 'LaksaHDWallet', dest: 'laksa-hd-wallet' },
// { name: 'LaksaContract', dest: 'laksa-core-contract' }, // { name: 'LaksaContract', dest: 'laksa-core-contract' },
{ name: 'HarmonyUtils', dest: 'harmony-utils' },
{ name: 'HarmonyCrypto', dest: 'harmony-crypto' }, { name: 'HarmonyCrypto', dest: 'harmony-crypto' },
{ name: 'HarmonyAccount', dest: 'harmony-account' },
]; ];

@ -0,0 +1,8 @@
const packages = [
'harmony-utils',
'harmony-crypto',
'harmony-account',
// 'harmony-network',
];
export { packages };

@ -72,10 +72,9 @@ async function bundles() {
const external = getKeys(p); const external = getKeys(p);
const externalSetting = getKeys(p).length > 0 ? { external } : {}; const externalSetting = getKeys(p).length > 0 ? { external } : {};
const externalObject = external.reduce((g, pkg) => { const externalObject = external.reduce((g, pkg) => {
g[`${pkg}`] = camelCase(pkg); g[`${pkg}`] = pkg.startsWith('@harmony') ? pkg : camelCase(pkg);
return g; return g;
}, {}); }, {});
const normal = { const normal = {
input: `packages/${p}/src/index.ts`, input: `packages/${p}/src/index.ts`,
plugins: [ plugins: [
@ -112,7 +111,7 @@ async function bundles() {
}), }),
], ],
output: { output: {
file: `packages/${p}/lib/index.js`, file: `packages/${p}/dist/index.js`,
exports: 'named', exports: 'named',
format: 'umd', format: 'umd',
sourcemap: true, sourcemap: true,

@ -7,7 +7,7 @@ export function getKeys(p) {
const { dependencies } = JSON.parse(data); const { dependencies } = JSON.parse(data);
const keys = dependencies const keys = dependencies
? Object.keys(dependencies).filter((d) => !/harmony/.test(d)) ? Object.keys(dependencies) //.filter((d) => !/harmony/.test(d))
: []; : [];
return keys; return keys;
} }

@ -0,0 +1,8 @@
{
"compilerOptions": {
"esModuleInterop": true,
"module": "commonjs",
"target": "es2015",
"resolveJsonModule": true
}
}

@ -0,0 +1,49 @@
import * as fs from 'fs';
import * as path from 'path';
// tslint:disable-next-line: no-implicit-dependencies
import * as schemas from 'typescript-json-schema';
import { packages } from '../packagesTs';
import tsConfig from '../../tsconfig.base.json';
const outputs = process.argv.slice(2)[0].split(',');
const rootPath = path.resolve(__dirname, '../..');
const includesPath = path.join(rootPath, 'includes');
const packagesPath = path.join(rootPath, 'packages');
async function generateSchemas() {
packages
// @ts-ignore
.filter((pkg) => {
return (
pkg !== 'harmony-' &&
outputs.indexOf(pkg.replace('harmony-', '')) !== -1
);
})
.forEach((pkg) => {
const pkgPath = path.join(packagesPath, pkg);
const pkgSrc = path.join(pkgPath, 'src');
const settings = {
ref: false,
};
// tslint:disable-next-line: no-shadowed-variable
const tsConfig: schemas.CompilerOptions = {
lib: ['es2015'],
};
const prog = schemas.getProgramFromFiles(
[path.resolve(path.join(pkgSrc, 'types.ts'))],
tsConfig,
);
const schema = schemas.generateSchema(prog, '*', settings);
fs.writeFileSync(
path.join(pkgPath, 'test', 'schema.json'),
JSON.stringify(schema, undefined, 2),
);
});
}
generateSchemas();

@ -0,0 +1,8 @@
{
"files": [],
"references": [
{ "path": "packages/harmony-account" },
{ "path": "packages/harmony-crypto" }
{ "path": "packages/harmony-utils" }
]
}

@ -5,7 +5,7 @@ const packagesSettings = require('./scripts/packagesList');
function createBatchConfig(list) { function createBatchConfig(list) {
return list.map((l) => { return list.map((l) => {
const entryBase = {}; const entryBase = {};
entryBase[l.name] = [`./packages/${l.dest}/lib/index.js`]; entryBase[l.name] = [`./packages/${l.dest}/dist/index.js`];
const batchBaseConfig = { const batchBaseConfig = {
entry: entryBase, entry: entryBase,

Loading…
Cancel
Save