Refactor API.

This commit is contained in:
Richard Moore 2018-06-15 04:18:17 -04:00
parent 7391cf8d19
commit efbfed0d40
No known key found for this signature in database
GPG Key ID: 525F70A6FCABC295
57 changed files with 997 additions and 763 deletions

189
dist/ethers.d.ts vendored

File diff suppressed because one or more lines are too long

466
dist/ethers.js vendored

File diff suppressed because one or more lines are too long

2
dist/ethers.min.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -46,7 +46,7 @@
"fs": "./tests/browser-fs.js",
"zlib": "browserify-zlib",
"./src.ts/utils/base64.ts": "./src.browser/base64.ts",
"./src.ts/utils/random-bytes.js": "./src.browser/random-bytes.js",
"./src.ts/utils/random-bytes.ts": "./src.browser/random-bytes.ts",
"./providers/ipc-provider.js": "./utils/empty.js",
"xmlhttprequest": "./src.browser/xmlhttprequest.ts"
},

View File

@ -1,22 +1,21 @@
'use strict';
import convert = require('./convert');
import properties = require('./properties');
var defineProperty = properties.defineProperty;
import { arrayify } from '../src.ts/utils/convert';
import { defineReadOnly } from '../src.ts/utils/properties';
var crypto = global.crypto || global.msCrypto;
let crypto: any = global['crypto'] || global['msCrypto'];
if (!crypto || !crypto.getRandomValues) {
console.log('WARNING: Missing strong random number source; using weak randomBytes');
crypto = {
getRandomValues: function(buffer) {
getRandomValues: function(buffer: Uint8Array) {
for (var round = 0; round < 20; round++) {
for (var i = 0; i < buffer.length; i++) {
if (round) {
buffer[i] ^= parseInt(256 * Math.random());
buffer[i] ^= Math.trunc(256 * Math.random());
} else {
buffer[i] = parseInt(256 * Math.random());
buffer[i] = Math.trunc(256 * Math.random());
}
}
}
@ -27,18 +26,16 @@ if (!crypto || !crypto.getRandomValues) {
};
}
function randomBytes(length) {
export function randomBytes(length) {
if (length <= 0 || length > 1024 || parseInt(length) != length) {
throw new Error('invalid length');
}
var result = new Uint8Array(length);
crypto.getRandomValues(result);
return convert.arrayify(result);
return arrayify(result);
};
if (crypto._weakCrypto === true) {
defineProperty(randomBytes, '_weakCrypto', true);
defineReadOnly(randomBytes, '_weakCrypto', true);
}
module.exports = randomBytes;

View File

@ -41,8 +41,7 @@ function parseParams(params: Array<ParamType>): { names: Array<any>, types: Arra
export class Indexed {
readonly hash: string;
constructor(value) {
defineReadOnly(this, 'indexed', true);
constructor(value: string) {
defineReadOnly(this, 'hash', value);
}
}
@ -325,7 +324,7 @@ function addMethod(method: any): void {
}
export class Interface {
readonly _abi: Array<any>;
readonly abi: Array<any>;
readonly functions: Array<FunctionDescription>;
readonly events: Array<EventDescription>;
readonly deployFunction: DeployDescription;
@ -354,15 +353,17 @@ export class Interface {
defineReadOnly(this, 'events', { });
// Convert any supported ABI format into a standard ABI format
this._abi = [];
let _abi = [];
abi.forEach((fragment) => {
if (typeof(fragment) === 'string') {
fragment = parseSignature(fragment);
}
this._abi.push(fragment);
_abi.push(fragment);
});
this._abi.forEach(addMethod, this);
defineFrozen(this, 'abi', _abi);
_abi.forEach(addMethod, this);
// If there wasn't a constructor, create the default constructor
if (!this.deployFunction) {
@ -388,6 +389,7 @@ export class Interface {
}
return null;
}
// @TODO:
//parseEvent(log: { }): Lo
}

View File

@ -3,6 +3,7 @@
import { Contract, Interface } from './contracts';
import * as providers from './providers';
import * as errors from './utils/errors';
import { networks } from './providers/networks';
import utils from './utils';
import { HDNode, SigningKey, Wallet } from './wallet';
@ -19,6 +20,7 @@ export {
Contract,
Interface,
networks,
providers,
errors,

View File

@ -36,7 +36,7 @@ export class InfuraProvider extends JsonRpcProvider {
this.apiAccessToken = (apiAccessToken || null);
}
_startPending() {
_startPending(): void {
console.log('WARNING: INFURA does not support pending filters');
}
@ -49,7 +49,7 @@ export class InfuraProvider extends JsonRpcProvider {
return null;
}
listAccounts() {
listAccounts(): Promise<Array<string>> {
return Promise.resolve([]);
}
}

View File

@ -21,7 +21,7 @@ export class IpcProvider extends JsonRpcProvider {
// @TODO: Create a connection to the IPC path and use filters instead of polling for block
send(method, params) {
send(method: string, params: any): Promise<any> {
// This method is very simple right now. We create a new socket
// connection each time, which may be slower, but the main
// advantage we are aiming for now is security. This simplifies

View File

@ -206,27 +206,28 @@ export class JsonRpcProvider extends Provider {
}
}
getSigner(address) {
getSigner(address: string): JsonRpcSigner {
return new JsonRpcSigner(this, address);
}
listAccounts() {
listAccounts(): Promise<Array<string>> {
return this.send('eth_accounts', []).then((accounts) => {
return accounts.map((a) => getAddress(a));
});
}
send(method, params) {
send(method: string, params: any): Promise<any> {
var request = {
method: method,
params: params,
id: 42,
jsonrpc: "2.0"
};
return fetchJson(this.connection, JSON.stringify(request), getResult);
}
perform(method, params) {
perform(method: string, params: any): Promise<any> {
switch (method) {
case 'getBlockNumber':
return this.send('eth_blockNumber', []);
@ -283,7 +284,7 @@ export class JsonRpcProvider extends Provider {
return null;
}
_startPending() {
_startPending(): void {
if (this._pendingFilter != null) { return; }
var self = this;
@ -322,7 +323,7 @@ export class JsonRpcProvider extends Provider {
});
}
_stopPending() {
_stopPending(): void {
this._pendingFilter = null;
}
}

View File

@ -58,6 +58,7 @@ export type TransactionRequest = {
export type TransactionResponse = {
blockNumber?: number,
blockHash?: string,
timestamp?: number,
hash: string,
@ -291,7 +292,7 @@ var formatTransaction = {
raw: allowNull(hexlify),
};
export function checkTransactionResponse(transaction) {
export function checkTransactionResponse(transaction: any): TransactionResponse {
// Rename gas to gasLimit
if (transaction.gas != null && transaction.gasLimit == null) {
@ -632,7 +633,7 @@ export class Provider {
this._emitted = { block: this._lastBlockNumber };
}
private _doPoll() {
private _doPoll(): void {
this.getBlockNumber().then((blockNumber) => {
// If the block hasn't changed, meh.
@ -706,12 +707,12 @@ export class Provider {
this.doPoll();
}
resetEventsBlock(blockNumber) {
resetEventsBlock(blockNumber: number): void {
this._lastBlockNumber = this.blockNumber;
this._doPoll();
}
get network() {
get network(): Network {
return this._network;
}
@ -724,11 +725,11 @@ export class Provider {
return this._lastBlockNumber;
}
get polling() {
get polling(): boolean {
return (this._poller != null);
}
set polling(value) {
set polling(value: boolean) {
setTimeout(() => {
if (value && !this._poller) {
this._poller = setInterval(this._doPoll.bind(this), this.pollingInterval);
@ -740,7 +741,7 @@ export class Provider {
}, 0);
}
get pollingInterval() {
get pollingInterval(): number {
return this._pollingInterval;
}
@ -992,7 +993,7 @@ export class Provider {
});
}
_resolveNames(object, keys) {
_resolveNames(object: any, keys: Array<string>): Promise<any> {
var promises = [];
var result = copyObject(object);
@ -1007,7 +1008,7 @@ export class Provider {
return Promise.all(promises).then(function() { return result; });
}
_getResolver(name) {
_getResolver(name: string): Promise<string> {
// Get the resolver from the blockchain
return this.getNetwork().then((network) => {
@ -1115,7 +1116,7 @@ export class Provider {
});
}
doPoll() {
doPoll(): void {
}
perform(method: string, params: any): Promise<any> {

View File

@ -13,6 +13,7 @@ utils.defineProperty(Web3Signer, 'onchange', {
*/
export type Callback = (error: any, response: any) => void;
export type AsyncProvider = {
isMetaMask: boolean;
host?: string;
@ -42,7 +43,7 @@ export class Web3Provider extends JsonRpcProvider {
this._web3Provider = web3Provider;
}
send(method, params) {
send(method: string, params: any): Promise<any> {
// Metamask complains about eth_sign (and on some versions hangs)
if (method == 'eth_sign' && this._web3Provider.isMetaMask) {

View File

@ -6,6 +6,7 @@ import { getAddress } from './address';
import { bigNumberify, BigNumberish } from './bignumber';
import { arrayify, Arrayish, concat, hexlify, padZeros } from './convert';
import { toUtf8Bytes, toUtf8String } from './utf8';
import { defineReadOnly, jsonCopy } from './properties';
import * as errors from './errors';
@ -17,7 +18,7 @@ const paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
export type CoerceFunc = (type: string, value: any) => any;
export type ParamType = { name?: string, type: string, indexed?: boolean, components?: Array<any> };
export function defaultCoerceFunc(type: string, value: any): any {
export const defaultCoerceFunc: CoerceFunc = function(type: string, value: any): any {
var match = type.match(paramTypeNumber)
if (match && parseInt(match[2]) <= 48) { return value.toNumber(); }
return value;
@ -173,8 +174,32 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType {
return (<ParamType>parent);
}
// @TODO: should this just be a combined Fragment?
export type EventFragment = {
type: string
name: string,
anonymous: boolean,
inputs: Array<ParamType>,
};
export type FunctionFragment = {
type: string
name: string,
constant: boolean,
inputs: Array<ParamType>,
outputs: Array<ParamType>,
payable: boolean,
stateMutability: string,
};
// @TODO: Better return type
function parseSignatureEvent(fragment: string): any {
function parseSignatureEvent(fragment: string): EventFragment {
var abi = {
anonymous: false,
@ -213,7 +238,7 @@ function parseSignatureEvent(fragment: string): any {
return abi;
}
function parseSignatureFunction(fragment: string): any {
function parseSignatureFunction(fragment: string): FunctionFragment {
var abi = {
constant: false,
inputs: [],
@ -276,7 +301,7 @@ function parseSignatureFunction(fragment: string): any {
}
export function parseSignature(fragment: string): any {
export function parseSignature(fragment: string): EventFragment | FunctionFragment {
if(typeof(fragment) === 'string') {
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
fragment = fragment.replace(/\(/g, ' (').replace(/\)/g, ') ').replace(/\s+/g, ' ');
@ -293,7 +318,7 @@ export function parseSignature(fragment: string): any {
}
}
throw new Error('unknown fragment');
throw new Error('unknown signature');
}
@ -908,10 +933,10 @@ function getParamCoder(coerceFunc: CoerceFunc, param: ParamType): Coder {
export class AbiCoder {
readonly coerceFunc: CoerceFunc;
constructor(coerceFunc?: CoerceFunc) {
//if (!(this instanceof Coder)) { throw new Error('missing new'); }
errors.checkNew(this, AbiCoder);
if (!coerceFunc) { coerceFunc = defaultCoerceFunc; }
// @TODO: readonly
this.coerceFunc = coerceFunc;
defineReadOnly(this, 'coerceFunc', coerceFunc);
}
encode(types: Array<string | ParamType>, values: Array<any>): string {
@ -928,11 +953,16 @@ export class AbiCoder {
// Convert types to type objects
// - "uint foo" => { type: "uint", name: "foo" }
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
let typeObject: ParamType = null;
if (typeof(type) === 'string') {
type = parseParam(type);
typeObject = parseParam(type);
} else {
typeObject = jsonCopy(type);
}
coders.push(getParamCoder(this.coerceFunc, type));
coders.push(getParamCoder(this.coerceFunc, typeObject));
}, this);
return hexlify(new CoderTuple(this.coerceFunc, coders, '_').encode(values));
@ -944,11 +974,14 @@ export class AbiCoder {
types.forEach(function(type) {
// See encode for details
let typeObject: ParamType = null;
if (typeof(type) === 'string') {
type = parseParam(type);
typeObject = parseParam(type);
} else {
typeObject = jsonCopy(type);
}
coders.push(getParamCoder(this.coerceFunc, type));
coders.push(getParamCoder(this.coerceFunc, typeObject));
}, this);
return new CoderTuple(this.coerceFunc, coders, '_').decode(arrayify(data), 0).value;

View File

@ -82,7 +82,7 @@ export type BigNumberish = BigNumber | string | number | Arrayish;
export class BigNumber {
readonly _bn: _BN.BN;
constructor(value: BigNumberish) {
if (!(this instanceof BigNumber)) { throw new Error('missing new'); }
errors.checkNew(this, BigNumber);
if (typeof(value) === 'string') {
if (isHexString(value)) {

View File

@ -51,3 +51,13 @@ export function resolveProperties(object: any) {
return object;
});
}
export function shallowCopy(object: any): any {
let result = {};
for (var key in object) { result[key] = object[key]; }
return result;
}
export function jsonCopy(object: any): any {
return JSON.parse(JSON.stringify(object));
}

View File

@ -2,30 +2,11 @@
import { arrayify } from './convert';
//import * as crypto from 'crypto';
import { randomBytes as _randomBytes } from 'crypto';
//@TODO: Figure out how to fix crypto
function getRandomValues(buffer) {
for (var round = 0; round < 20; round++) {
for (var i = 0; i < buffer.length; i++) {
if (round) {
buffer[i] ^= Math.trunc(256 * Math.random());
} else {
buffer[i] = Math.trunc(256 * Math.random());
}
}
//function _randomBytes(length) { return "0x00"; }
export function randomBytes(length: number): Uint8Array {
return arrayify(_randomBytes(length));
}
return buffer;
}
export function randomBytes(length) {
if (length <= 0 || length > 1024 || parseInt(length) != length) {
throw new Error('invalid length');
}
var result = new Uint8Array(length);
getRandomValues(result);
return arrayify(result);
};

View File

@ -2,7 +2,7 @@
import * as _hash from 'hash.js';
import { arrayify } from './convert';
import { arrayify, Arrayish } from './convert';
interface HashFunc {
@ -15,10 +15,10 @@ const _sha256: HashFunc = _hash['sha256'];
const _sha512: HashFunc = _hash['sha512'];
export function sha256(data: any): string {
export function sha256(data: Arrayish): string {
return '0x' + (_sha256().update(arrayify(data)).digest('hex'));
}
export function sha512(data: any): string {
export function sha512(data: Arrayish): string {
return '0x' + (_sha512().update(arrayify(data)).digest('hex'));
}

View File

@ -1,6 +1,6 @@
'use strict';
import { bigNumberify, ConstantZero, ConstantNegativeOne } from './bignumber';
import { BigNumber, bigNumberify, BigNumberish, ConstantZero, ConstantNegativeOne } from './bignumber';
import * as errors from './errors';
@ -56,7 +56,7 @@ var getUnitInfo = (function() {
}
})();
export function formatUnits(value: any, unitType: string | number, options?: any): string {
export function formatUnits(value: BigNumberish, unitType?: string | number, options?: any): string {
/*
if (typeof(unitType) === 'object' && !options) {
options = unitType;
@ -75,7 +75,7 @@ export function formatUnits(value: any, unitType: string | number, options?: any
var negative = value.lt(ConstantZero);
if (negative) { value = value.mul(ConstantNegativeOne); }
var fraction = value.mod(unitInfo.tenPower).toString(10);
var fraction = value.mod(unitInfo.tenPower).toString();
while (fraction.length < unitInfo.decimals) { fraction = '0' + fraction; }
// Strip off trailing zeros (but keep one if would otherwise be bare decimal point)
@ -83,7 +83,7 @@ export function formatUnits(value: any, unitType: string | number, options?: any
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];
}
var whole = value.div(unitInfo.tenPower).toString(10);
var whole = value.div(unitInfo.tenPower).toString();
if (options.commify) {
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
@ -96,7 +96,7 @@ export function formatUnits(value: any, unitType: string | number, options?: any
return value;
}
export function parseUnits(value, unitType) {
export function parseUnits(value: string, unitType?: string | number): BigNumber {
if (unitType == null) { unitType = 18; }
var unitInfo = getUnitInfo(unitType);
@ -116,12 +116,12 @@ export function parseUnits(value, unitType) {
}
// Split it into a whole and fractional part
var comps = value.split('.');
let comps = value.split('.');
if (comps.length > 2) {
errors.throwError('too many decimal points', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
}
var whole = comps[0], fraction = comps[1];
let whole = comps[0], fraction = comps[1];
if (!whole) { whole = '0'; }
if (!fraction) { fraction = '0'; }
@ -137,21 +137,21 @@ export function parseUnits(value, unitType) {
// Fully pad the string with zeros to get to wei
while (fraction.length < unitInfo.decimals) { fraction += '0'; }
whole = bigNumberify(whole);
fraction = bigNumberify(fraction);
let wholeValue = bigNumberify(whole);
let fractionValue = bigNumberify(fraction);
var wei = (whole.mul(unitInfo.tenPower)).add(fraction);
let wei = (wholeValue.mul(unitInfo.tenPower)).add(fractionValue);
if (negative) { wei = wei.mul(ConstantNegativeOne); }
return wei;
}
export function formatEther(wei, options) {
export function formatEther(wei: BigNumberish, options: any): string {
return formatUnits(wei, 18, options);
}
export function parseEther(ether) {
export function parseEther(ether: string): BigNumber {
return parseUnits(ether, 18);
}

View File

@ -3,12 +3,11 @@
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
import * as secp256k1 from './secp256k1';
import { KeyPair, N } from './secp256k1';
import words from './words';
var wordlist: Array<string> = words.replace(/([A-Z])/g, ' $1').toLowerCase().substring(1).split(' ');
import { getWord, getWordIndex } from './words';
import { arrayify, hexlify } from '../utils/convert';
import { arrayify, Arrayish, hexlify } from '../utils/convert';
import { bigNumberify } from '../utils/bignumber';
import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
import { pbkdf2 } from '../utils/pbkdf2';
@ -33,7 +32,7 @@ function getLowerMask(bits: number): number {
}
export class HDNode {
private readonly keyPair: secp256k1.KeyPair;
private readonly keyPair: KeyPair;
readonly privateKey: string;
readonly publicKey: string;
@ -47,13 +46,13 @@ export class HDNode {
readonly depth: number;
// @TODO: Private constructor?
constructor(keyPair: secp256k1.KeyPair, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string) {
constructor(keyPair: KeyPair, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string) {
errors.checkNew(this, HDNode);
this.keyPair = keyPair;
this.privateKey = hexlify(keyPair.priv.toArray('be', 32));
this.publicKey = '0x' + keyPair.getPublic(true, 'hex');
this.privateKey = keyPair.privateKey;
this.publicKey = keyPair.compressedPublicKey;
this.chainCode = hexlify(chainCode);
@ -88,7 +87,7 @@ export class HDNode {
} else {
// Data = ser_p(point(k_par))
data.set(this.keyPair.getPublic().encode(null, true));
data.set(this.keyPair.publicKeyBytes);
}
// Data += ser_32(i)
@ -98,9 +97,9 @@ export class HDNode {
var IL = bigNumberify(I.slice(0, 32));
var IR = I.slice(32);
var ki = IL.add('0x' + this.keyPair.getPrivate('hex')).mod('0x' + secp256k1.curve.n.toString(16));
var ki = IL.add(this.keyPair.privateKey).mod(N);
return new HDNode(secp256k1.curve.keyFromPrivate(arrayify(ki)), IR, index, this.depth + 1, mnemonic, path);
return new HDNode(new KeyPair(arrayify(ki)), IR, index, this.depth + 1, mnemonic, path);
}
derivePath(path: string): HDNode {
@ -132,13 +131,13 @@ export class HDNode {
}
}
function _fromSeed(seed: any, mnemonic: string): HDNode {
seed = arrayify(seed);
if (seed.length < 16 || seed.length > 64) { throw new Error('invalid seed'); }
function _fromSeed(seed: Arrayish, mnemonic: string): HDNode {
let seedArray: Uint8Array = arrayify(seed);
if (seedArray.length < 16 || seedArray.length > 64) { throw new Error('invalid seed'); }
var I = arrayify(createSha512Hmac(MasterSecret).update(seed).digest());
var I: Uint8Array = arrayify(createSha512Hmac(MasterSecret).update(seedArray).digest());
return new HDNode(secp256k1.curve.keyFromPrivate(I.slice(0, 32)), I.slice(32), 0, 0, mnemonic, 'm');
return new HDNode(new KeyPair(I.slice(0, 32)), I.slice(32), 0, 0, mnemonic, 'm');
}
export function fromMnemonic(mnemonic: string): HDNode {
@ -148,7 +147,7 @@ export function fromMnemonic(mnemonic: string): HDNode {
return _fromSeed(mnemonicToSeed(mnemonic), mnemonic);
}
export function fromSeed(seed: any): HDNode {
export function fromSeed(seed: Arrayish): HDNode {
return _fromSeed(seed, null);
}
@ -180,7 +179,7 @@ export function mnemonicToEntropy(mnemonic: string): string {
var offset = 0;
for (var i = 0; i < words.length; i++) {
var index = wordlist.indexOf(words[i]);
var index = getWordIndex(words[i]);
if (index === -1) { throw new Error('invalid mnemonic'); }
for (var bit = 0; bit < 11; bit++) {
@ -206,32 +205,32 @@ export function mnemonicToEntropy(mnemonic: string): string {
return hexlify(entropy.slice(0, entropyBits / 8));
}
export function entropyToMnemonic(entropy: any): string {
export function entropyToMnemonic(entropy: Arrayish): string {
entropy = arrayify(entropy);
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
throw new Error('invalid entropy');
}
var words: Array<number> = [ 0 ];
var indices: Array<number> = [ 0 ];
var remainingBits = 11;
for (var i = 0; i < entropy.length; i++) {
// Consume the whole byte (with still more to go)
if (remainingBits > 8) {
words[words.length - 1] <<= 8;
words[words.length - 1] |= entropy[i];
indices[indices.length - 1] <<= 8;
indices[indices.length - 1] |= entropy[i];
remainingBits -= 8;
// This byte will complete an 11-bit index
} else {
words[words.length - 1] <<= remainingBits;
words[words.length - 1] |= entropy[i] >> (8 - remainingBits);
indices[indices.length - 1] <<= remainingBits;
indices[indices.length - 1] |= entropy[i] >> (8 - remainingBits);
// Start the next word
words.push(entropy[i] & getLowerMask(8 - remainingBits));
indices.push(entropy[i] & getLowerMask(8 - remainingBits));
remainingBits += 3;
}
@ -243,16 +242,10 @@ export function entropyToMnemonic(entropy: any): string {
checksum &= getUpperMask(checksumBits);
// Shift the checksum into the word indices
words[words.length - 1] <<= checksumBits;
words[words.length - 1] |= (checksum >> (8 - checksumBits));
indices[indices.length - 1] <<= checksumBits;
indices[indices.length - 1] |= (checksum >> (8 - checksumBits));
// Convert indices into words
var result = [];
for (var i = 0; i < words.length; i++) {
result.push(wordlist[words[i]]);
}
return result.join(' ');
return indices.map((index) => getWord(index)).join(' ');
}
export function isValidMnemonic(mnemonic: string): boolean {
@ -262,22 +255,3 @@ export function isValidMnemonic(mnemonic: string): boolean {
} catch (error) { }
return false;
}
// Exporting
/*
const exporting = {
HDNode: HDNode,
fromMnemonic: fromMnemonic,
fromSeed: fromSeed,
mnemonicToSeed: mnemonicToSeed,
mnemonicToEntropy: mnemonicToEntropy,
entropyToMnemonic: entropyToMnemonic,
isValidMnemonic: isValidMnemonic
}
*/
// Default TypeScript
//export default exporting;
// Node exports
//declare var module: any;
//(module).exports = exporting;

View File

@ -1,38 +1,113 @@
'use strict';
export interface BN {
import { arrayify, Arrayish, hexlify } from '../utils/convert';
import { defineReadOnly } from '../utils/properties';
import * as errors from '../utils/errors';
interface _BN {
toString(radix: number): string;
encode(encoding: string, compact: boolean): Uint8Array;
toArray(endian: string, width: number): Uint8Array;
}
export interface Signature {
r: BN,
s: BN,
interface _Signature {
r: _BN,
s: _BN,
recoveryParam: number
}
export interface KeyPair {
sign(message: Uint8Array, options: { canonical?: boolean }): Signature;
interface _KeyPair {
sign(message: Uint8Array, options: { canonical?: boolean }): _Signature;
getPublic(compressed: boolean, encoding?: string): string;
getPublic(): BN;
getPublic(): _BN;
getPrivate(encoding?: string): string;
encode(encoding: string, compressed: boolean): string;
priv: BN;
priv: _BN;
}
export interface EC {
interface _EC {
constructor(curve: string);
n: BN;
n: _BN;
keyFromPublic(publicKey: string | Uint8Array): KeyPair;
keyFromPrivate(privateKey: string | Uint8Array): KeyPair;
recoverPubKey(data: Uint8Array, signature: { r: Uint8Array, s: Uint8Array }, recoveryParam: number): KeyPair;
keyFromPublic(publicKey: string | Uint8Array): _KeyPair;
keyFromPrivate(privateKey: string | Uint8Array): _KeyPair;
recoverPubKey(data: Uint8Array, signature: { r: Uint8Array, s: Uint8Array }, recoveryParam: number): _KeyPair;
}
import * as elliptic from 'elliptic';
export const curve:EC = new elliptic.ec('secp256k1');
const curve:_EC = new elliptic.ec('secp256k1');
//export default secp256k1;
export type Signature = {
r: string;
s: string;
recoveryParam: number;
}
export class KeyPair {
readonly privateKey: string;
readonly publicKey: string;
readonly compressedPublicKey: string;
readonly publicKeyBytes: Uint8Array;
constructor(privateKey: Arrayish) {
let keyPair: _KeyPair = curve.keyFromPrivate(arrayify(privateKey));
defineReadOnly(this, 'privateKey', hexlify(keyPair.priv.toArray('be', 32)));
defineReadOnly(this, 'publicKey', '0x' + keyPair.getPublic(false, 'hex'));
defineReadOnly(this, 'compressedPublicKey', '0x' + keyPair.getPublic(true, 'hex'));
defineReadOnly(this, 'publicKeyBytes', keyPair.getPublic().encode(null, true));
}
sign(digest: Arrayish): Signature {
let keyPair: _KeyPair = curve.keyFromPrivate(arrayify(this.privateKey));
let signature = keyPair.sign(arrayify(digest), {canonical: true});
return {
recoveryParam: signature.recoveryParam,
r: '0x' + signature.r.toString(16),
s: '0x' + signature.s.toString(16)
}
}
}
export function recoverPublicKey(digest: Arrayish, signature: Signature): string {
let sig = {
r: arrayify(signature.r),
s: arrayify(signature.s)
};
return '0x' + curve.recoverPubKey(arrayify(digest), sig, signature.recoveryParam).getPublic(false, 'hex');
}
export function computePublicKey(key: Arrayish, compressed?: boolean): string {
let bytes = arrayify(key);
if (bytes.length === 32) {
let keyPair: KeyPair = new KeyPair(bytes);
if (compressed) {
return keyPair.compressedPublicKey;
}
return keyPair.publicKey;
} else if (bytes.length === 33) {
if (compressed) { return hexlify(bytes); }
return '0x' + curve.keyFromPublic(bytes).getPublic(false, 'hex');
} else if (bytes.length === 65) {
if (!compressed) { return hexlify(bytes); }
return '0x' + curve.keyFromPublic(bytes).getPublic(true, 'hex');
}
errors.throwError('invalid public or private key', errors.INVALID_ARGUMENT, { arg: 'key', value: '[REDACTED]' });
return null;
}
export const N = '0x' + curve.n.toString(16);

View File

@ -292,7 +292,7 @@ export function decrypt(json: string, password: any, progressCallback?: Progress
}
// @TOOD: Options
export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish | string, options?: any, progressCallback?: ProgressCallback) {
export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish | string, options?: any, progressCallback?: ProgressCallback): Promise<string> {
// the options are optional, so adjust the call as needed
if (typeof(options) === 'function' && !progressCallback) {
@ -302,11 +302,13 @@ export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish |
if (!options) { options = {}; }
// Check the private key
let privateKeyBytes = null;
if (privateKey instanceof SigningKey) {
privateKey = privateKey.privateKey;
privateKeyBytes = arrayify(privateKey.privateKey);
} else {
privateKeyBytes = arrayify(privateKey);
}
privateKey = arrayify(privateKey);
if (privateKey.length !== 32) { throw new Error('invalid private key'); }
if (privateKeyBytes.length !== 32) { throw new Error('invalid private key'); }
password = getPassword(password);
@ -387,12 +389,12 @@ export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish |
var mnemonicKey = key.slice(32, 64);
// Get the address for this private key
var address = (new SigningKey(privateKey)).address;
var address = (new SigningKey(privateKeyBytes)).address;
// Encrypt the private key
var counter = new aes.Counter(iv);
var aesCtr = new aes.ModeOfOperation.ctr(derivedKey, counter);
var ciphertext = arrayify(aesCtr.encrypt(privateKey));
var ciphertext = arrayify(aesCtr.encrypt(privateKeyBytes));
// Compute the message authentication code, used to check the password
var mac = keccak256(concat([macPrefix, ciphertext]))

View File

@ -6,15 +6,16 @@
*
*/
import * as secp256k1 from './secp256k1';
import { computePublicKey, KeyPair, recoverPublicKey, Signature } from './secp256k1';
import { getAddress } from '../utils/address';
import { arrayify, hexlify } from '../utils/convert';
import { arrayify, Arrayish, hexlify } from '../utils/convert';
import { HDNode } from './hdnode';
import { keccak256 } from '../utils/keccak256';
import { defineReadOnly } from '../utils/properties';
import errors = require('../utils/errors');
export class SigningKey {
readonly privateKey: string;
@ -24,20 +25,23 @@ export class SigningKey {
readonly mnemonic: string;
readonly path: string;
private readonly keyPair: secp256k1.KeyPair;
private readonly keyPair: KeyPair;
constructor(privateKey: any) {
constructor(privateKey: Arrayish | HDNode) {
errors.checkNew(this, SigningKey);
if (privateKey.privateKey) {
this.mnemonic = privateKey.mnemonic;
this.path = privateKey.path;
privateKey = privateKey.privateKey;
let privateKeyBytes = null;
if (privateKey instanceof HDNode) {
defineReadOnly(this, 'mnemonic', privateKey.mnemonic);
defineReadOnly(this, 'path', privateKey.path);
privateKeyBytes = arrayify(privateKey.privateKey);
} else {
privateKeyBytes = arrayify(privateKey);
}
try {
privateKey = arrayify(privateKey);
if (privateKey.length !== 32) {
if (privateKeyBytes.length !== 32) {
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
}
} catch(error) {
@ -51,59 +55,23 @@ export class SigningKey {
errors.throwError('invalid private key', error.code, params);
}
this.privateKey = hexlify(privateKey);
this.keyPair = secp256k1.curve.keyFromPrivate(privateKey);
//utils.defineProperty(this, 'publicKey', '0x' + keyPair.getPublic(true, 'hex'))
this.publicKey = '0x' + this.keyPair.getPublic(true, 'hex');
this.address = SigningKey.publicKeyToAddress('0x' + this.keyPair.getPublic(false, 'hex'));
defineReadOnly(this, 'privateKey', hexlify(privateKeyBytes));
defineReadOnly(this, 'keyPair', new KeyPair(privateKeyBytes));
defineReadOnly(this, 'publicKey', this.keyPair.publicKey);
defineReadOnly(this, 'address', computeAddress(this.keyPair.publicKey));
}
signDigest(digest) {
var signature = this.keyPair.sign(arrayify(digest), {canonical: true});
return {
recoveryParam: signature.recoveryParam,
r: '0x' + signature.r.toString(16),
s: '0x' + signature.s.toString(16)
signDigest(digest: Arrayish): Signature {
return this.keyPair.sign(digest);
}
}
static recover(digest, r, s, recoveryParam) {
var signature = {
r: arrayify(r),
s: arrayify(s)
};
var publicKey = secp256k1.curve.recoverPubKey(arrayify(digest), signature, recoveryParam);
return SigningKey.publicKeyToAddress('0x' + publicKey.encode('hex', false));
export function recoverAddress(digest: Arrayish, signature: Signature): string {
return computeAddress(recoverPublicKey(digest, signature));
}
static getPublicKey(value, compressed) {
value = arrayify(value);
compressed = !!compressed;
if (value.length === 32) {
var keyPair = secp256k1.curve.keyFromPrivate(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
} else if (value.length === 33) {
var keyPair = secp256k1.curve.keyFromPublic(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
} else if (value.length === 65) {
var keyPair = secp256k1.curve.keyFromPublic(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
}
throw new Error('invalid value');
}
static publicKeyToAddress(publicKey) {
publicKey = '0x' + SigningKey.getPublicKey(publicKey, false).slice(4);
export function computeAddress(key: string): string {
// Strip off the leading "0x04"
let publicKey = '0x' + computePublicKey(key).slice(4);
return getAddress('0x' + keccak256(publicKey).substring(26));
}
}
//export default SigningKey;

View File

@ -2,8 +2,15 @@
import scrypt from 'scrypt-js';
import { entropyToMnemonic, fromMnemonic, HDNode } from './hdnode';
import * as secretStorage from './secret-storage';
import { ProgressCallback } from './secret-storage';
import { recoverAddress, SigningKey } from './signing-key';
import { BlockTag } from '../providers/provider';
import { getAddress } from '../utils/address';
import { BigNumber, bigNumberify, ConstantZero } from '../utils/bignumber';
import { BigNumber, bigNumberify, BigNumberish, ConstantZero } from '../utils/bignumber';
import { arrayify, Arrayish, concat, hexlify, stripZeros, hexZeroPad } from '../utils/convert';
import { keccak256 } from '../utils/keccak256';
import { randomBytes } from '../utils/random-bytes';
@ -12,9 +19,6 @@ import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
import * as errors from '../utils/errors';
import { entropyToMnemonic, fromMnemonic, HDNode } from './hdnode';
import * as secretStorage from './secret-storage';
import { SigningKey } from './signing-key';
// This ensures we inject a setImmediate into the global space, which
// dramatically improves the performance of the scrypt PBKDF.
@ -113,7 +117,7 @@ export class Wallet {
});
}
sign(transaction: TransactionRequest) {
sign(transaction: TransactionRequest): string {
var chainId = transaction.chainId;
if (chainId == null && this.provider) { chainId = this.provider.chainId; }
if (!chainId) { chainId = 0; }
@ -238,7 +242,7 @@ export class Wallet {
var digest = keccak256(RLP.encode(raw));
try {
transaction.from = SigningKey.recover(digest, r, s, recoveryParam);
transaction.from = recoverAddress(digest, { r: hexlify(r), s: hexlify(s), recoveryParam });
} catch (error) {
console.log(error);
}
@ -247,21 +251,21 @@ export class Wallet {
return transaction;
}
getAddress() {
getAddress(): Promise<string> {
return Promise.resolve(this.address);
}
getBalance(blockTag) {
getBalance(blockTag: BlockTag): Promise<BigNumber> {
if (!this.provider) { throw new Error('missing provider'); }
return this.provider.getBalance(this.address, blockTag);
}
getTransactionCount(blockTag) {
getTransactionCount(blockTag: BlockTag): Promise<number> {
if (!this.provider) { throw new Error('missing provider'); }
return this.provider.getTransactionCount(this.address, blockTag);
}
estimateGas(transaction: TransactionRequest) {
estimateGas(transaction: TransactionRequest): Promise<BigNumber> {
if (!this.provider) { throw new Error('missing provider'); }
var calculate: TransactionRequest = {};
@ -275,7 +279,7 @@ export class Wallet {
return this.provider.estimateGas(calculate);
}
sendTransaction(transaction) {
sendTransaction(transaction: any): Promise<TransactionResponse> {
if (!this.provider) { throw new Error('missing provider'); }
if (!transaction || typeof(transaction) !== 'object') {
@ -335,7 +339,7 @@ export class Wallet {
});
}
send(addressOrName, amountWei, options) {
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse> {
if (!options) { options = {}; }
return this.sendTransaction({
@ -348,7 +352,7 @@ export class Wallet {
}
static hashMessage(message) {
static hashMessage(message: Arrayish | string): string {
var payload = concat([
toUtf8Bytes('\x19Ethereum Signed Message:\n'),
toUtf8Bytes(String(message.length)),
@ -357,14 +361,14 @@ export class Wallet {
return keccak256(payload);
}
signMessage(message) {
signMessage(message: Arrayish | string): string {
var signingKey = new SigningKey(this.privateKey);
var sig = signingKey.signDigest(Wallet.hashMessage(message));
return (hexZeroPad(sig.r, 32) + hexZeroPad(sig.s, 32).substring(2) + (sig.recoveryParam ? '1c': '1b'));
}
static verifyMessage(message, signature) {
static verifyMessage(message: Arrayish | string, signature: string): string {
signature = hexlify(signature);
if (signature.length != 132) { throw new Error('invalid signature'); }
var digest = Wallet.hashMessage(message);
@ -373,15 +377,17 @@ export class Wallet {
if (recoveryParam >= 27) { recoveryParam -= 27; }
if (recoveryParam < 0) { throw new Error('invalid signature'); }
return SigningKey.recover(
return recoverAddress(
digest,
signature.substring(0, 66),
'0x' + signature.substring(66, 130),
recoveryParam
{
r: signature.substring(0, 66),
s: '0x' + signature.substring(66, 130),
recoveryParam: recoveryParam
}
);
}
encrypt(password, options, progressCallback) {
encrypt(password: Arrayish | string, options: any, progressCallback: ProgressCallback): Promise<string> {
if (typeof(options) === 'function' && !progressCallback) {
progressCallback = options;
options = {};
@ -408,7 +414,7 @@ export class Wallet {
}
static createRandom(options) {
static createRandom(options: any): Wallet {
var entropy: Uint8Array = randomBytes(16);
if (!options) { options = { }; }
@ -422,12 +428,12 @@ export class Wallet {
}
static isEncryptedWallet(json: string) {
static isEncryptedWallet(json: string): boolean {
return (secretStorage.isValidWallet(json) || secretStorage.isCrowdsaleWallet(json));
}
static fromEncryptedWallet(json, password, progressCallback) {
static fromEncryptedWallet(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet> {
if (progressCallback && typeof(progressCallback) !== 'function') {
throw new Error('invalid callback');
}
@ -463,13 +469,13 @@ export class Wallet {
});
}
static fromMnemonic(mnemonic: string, path?: string) {
static fromMnemonic(mnemonic: string, path?: string): Wallet {
if (!path) { path = defaultPath; }
return new Wallet(fromMnemonic(mnemonic).derivePath(path));
}
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback) {
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback: ProgressCallback): Promise<Wallet> {
if (progressCallback && typeof(progressCallback) !== 'function') {
throw new Error('invalid callback');
}

File diff suppressed because one or more lines are too long

View File

@ -2,7 +2,7 @@ import { ParamType } from '../utils/abi-coder';
import { BigNumber, BigNumberish } from '../utils/bignumber';
export declare class Indexed {
readonly hash: string;
constructor(value: any);
constructor(value: string);
}
export declare class Description {
readonly type: string;
@ -37,7 +37,7 @@ export declare class EventDescription extends Description {
decode(data: string, topics?: Array<string>): any;
}
export declare class Interface {
readonly _abi: Array<any>;
readonly abi: Array<any>;
readonly functions: Array<FunctionDescription>;
readonly events: Array<EventDescription>;
readonly deployFunction: DeployDescription;

View File

@ -54,7 +54,6 @@ function parseParams(params) {
}
var Indexed = /** @class */ (function () {
function Indexed(value) {
properties_1.defineReadOnly(this, 'indexed', true);
properties_1.defineReadOnly(this, 'hash', value);
}
return Indexed;
@ -302,7 +301,6 @@ function addMethod(method) {
}
var Interface = /** @class */ (function () {
function Interface(abi) {
var _this = this;
errors.checkNew(this, Interface);
if (typeof (abi) === 'string') {
try {
@ -323,14 +321,15 @@ var Interface = /** @class */ (function () {
properties_1.defineReadOnly(this, 'functions', {});
properties_1.defineReadOnly(this, 'events', {});
// Convert any supported ABI format into a standard ABI format
this._abi = [];
var _abi = [];
abi.forEach(function (fragment) {
if (typeof (fragment) === 'string') {
fragment = abi_coder_1.parseSignature(fragment);
}
_this._abi.push(fragment);
_abi.push(fragment);
});
this._abi.forEach(addMethod, this);
properties_1.defineFrozen(this, 'abi', _abi);
_abi.forEach(addMethod, this);
// If there wasn't a constructor, create the default constructor
if (!this.deployFunction) {
addMethod.call(this, { type: 'constructor', inputs: [] });

3
src/index.d.ts vendored
View File

@ -1,6 +1,7 @@
import { Contract, Interface } from './contracts';
import * as providers from './providers';
import * as errors from './utils/errors';
import { networks } from './providers/networks';
import utils from './utils';
import { HDNode, SigningKey, Wallet } from './wallet';
export { Wallet, HDNode, SigningKey, Contract, Interface, providers, errors, utils, };
export { Wallet, HDNode, SigningKey, Contract, Interface, networks, providers, errors, utils, };

View File

@ -17,6 +17,8 @@ var providers = __importStar(require("./providers"));
exports.providers = providers;
var errors = __importStar(require("./utils/errors"));
exports.errors = errors;
var networks_1 = require("./providers/networks");
exports.networks = networks_1.networks;
var utils_1 = __importDefault(require("./utils"));
exports.utils = utils_1.default;
var wallet_1 = require("./wallet");

View File

@ -5,5 +5,5 @@ export declare class InfuraProvider extends JsonRpcProvider {
constructor(network?: Network | string, apiAccessToken?: string);
_startPending(): void;
getSigner(address?: string): JsonRpcSigner;
listAccounts(): Promise<any[]>;
listAccounts(): Promise<Array<string>>;
}

View File

@ -3,5 +3,5 @@ import { Network } from './networks';
export declare class IpcProvider extends JsonRpcProvider {
readonly path: string;
constructor(path: string, network?: Network | string);
send(method: any, params: any): Promise<{}>;
send(method: string, params: any): Promise<any>;
}

View File

@ -20,10 +20,10 @@ export declare class JsonRpcProvider extends Provider {
readonly connection: ConnectionInfo;
private _pendingFilter;
constructor(url?: ConnectionInfo | string, network?: Network | string);
getSigner(address: any): JsonRpcSigner;
listAccounts(): Promise<any>;
send(method: any, params: any): Promise<any>;
perform(method: any, params: any): Promise<any>;
getSigner(address: string): JsonRpcSigner;
listAccounts(): Promise<Array<string>>;
send(method: string, params: any): Promise<any>;
perform(method: string, params: any): Promise<any>;
_startPending(): void;
_stopPending(): void;
}

View File

@ -28,6 +28,7 @@ export declare type TransactionRequest = {
export declare type TransactionResponse = {
blockNumber?: number;
blockHash?: string;
timestamp?: number;
hash: string;
to?: string;
from?: string;
@ -72,7 +73,7 @@ export declare type Log = {
transactionHash?: string;
logIndex?: number;
};
export declare function checkTransactionResponse(transaction: any): any;
export declare function checkTransactionResponse(transaction: any): TransactionResponse;
export declare class Provider {
private _network;
protected ready: Promise<Network>;
@ -89,7 +90,7 @@ export declare class Provider {
*/
constructor(network: string | Network);
private _doPoll;
resetEventsBlock(blockNumber: any): void;
resetEventsBlock(blockNumber: number): void;
readonly network: Network;
getNetwork(): Promise<Network>;
readonly blockNumber: number;
@ -110,8 +111,8 @@ export declare class Provider {
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
getLogs(filter: Filter): Promise<Array<Log>>;
getEtherPrice(): Promise<number>;
_resolveNames(object: any, keys: any): Promise<{}>;
_getResolver(name: any): Promise<string>;
_resolveNames(object: any, keys: Array<string>): Promise<any>;
_getResolver(name: string): Promise<string>;
resolveName(name: string | Promise<string>): Promise<string>;
lookupAddress(address: string | Promise<string>): Promise<string>;
doPoll(): void;

View File

@ -10,5 +10,5 @@ export declare type AsyncProvider = {
export declare class Web3Provider extends JsonRpcProvider {
readonly _web3Provider: AsyncProvider;
constructor(web3Provider: AsyncProvider, network?: Network | string);
send(method: any, params: any): Promise<{}>;
send(method: string, params: any): Promise<any>;
}

View File

@ -6,8 +6,23 @@ export declare type ParamType = {
indexed?: boolean;
components?: Array<any>;
};
export declare function defaultCoerceFunc(type: string, value: any): any;
export declare function parseSignature(fragment: string): any;
export declare const defaultCoerceFunc: CoerceFunc;
export declare type EventFragment = {
type: string;
name: string;
anonymous: boolean;
inputs: Array<ParamType>;
};
export declare type FunctionFragment = {
type: string;
name: string;
constant: boolean;
inputs: Array<ParamType>;
outputs: Array<ParamType>;
payable: boolean;
stateMutability: string;
};
export declare function parseSignature(fragment: string): EventFragment | FunctionFragment;
export declare class AbiCoder {
readonly coerceFunc: CoerceFunc;
constructor(coerceFunc?: CoerceFunc);

View File

@ -22,18 +22,18 @@ var address_1 = require("./address");
var bignumber_1 = require("./bignumber");
var convert_1 = require("./convert");
var utf8_1 = require("./utf8");
var properties_1 = require("./properties");
var errors = __importStar(require("./errors"));
var paramTypeBytes = new RegExp(/^bytes([0-9]*)$/);
var paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/);
var paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
function defaultCoerceFunc(type, value) {
exports.defaultCoerceFunc = function (type, value) {
var match = type.match(paramTypeNumber);
if (match && parseInt(match[2]) <= 48) {
return value.toNumber();
}
return value;
}
exports.defaultCoerceFunc = defaultCoerceFunc;
};
///////////////////////////////////
// Parsing for Solidity Signatures
var regexParen = new RegExp("^([^)(]*)\\((.*)\\)([^)(]*)$");
@ -259,7 +259,7 @@ function parseSignature(fragment) {
return parseSignatureFunction(fragment.trim());
}
}
throw new Error('unknown fragment');
throw new Error('unknown signature');
}
exports.parseSignature = parseSignature;
var Coder = /** @class */ (function () {
@ -837,12 +837,11 @@ function getParamCoder(coerceFunc, param) {
}
var AbiCoder = /** @class */ (function () {
function AbiCoder(coerceFunc) {
//if (!(this instanceof Coder)) { throw new Error('missing new'); }
errors.checkNew(this, AbiCoder);
if (!coerceFunc) {
coerceFunc = defaultCoerceFunc;
coerceFunc = exports.defaultCoerceFunc;
}
// @TODO: readonly
this.coerceFunc = coerceFunc;
properties_1.defineReadOnly(this, 'coerceFunc', coerceFunc);
}
AbiCoder.prototype.encode = function (types, values) {
if (types.length !== values.length) {
@ -856,10 +855,14 @@ var AbiCoder = /** @class */ (function () {
// Convert types to type objects
// - "uint foo" => { type: "uint", name: "foo" }
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
var typeObject = null;
if (typeof (type) === 'string') {
type = parseParam(type);
typeObject = parseParam(type);
}
coders.push(getParamCoder(this.coerceFunc, type));
else {
typeObject = properties_1.jsonCopy(type);
}
coders.push(getParamCoder(this.coerceFunc, typeObject));
}, this);
return convert_1.hexlify(new CoderTuple(this.coerceFunc, coders, '_').encode(values));
};
@ -867,10 +870,14 @@ var AbiCoder = /** @class */ (function () {
var coders = [];
types.forEach(function (type) {
// See encode for details
var typeObject = null;
if (typeof (type) === 'string') {
type = parseParam(type);
typeObject = parseParam(type);
}
coders.push(getParamCoder(this.coerceFunc, type));
else {
typeObject = properties_1.jsonCopy(type);
}
coders.push(getParamCoder(this.coerceFunc, typeObject));
}, this);
return new CoderTuple(this.coerceFunc, coders, '_').decode(convert_1.arrayify(data), 0).value;
};

View File

@ -56,9 +56,7 @@ function _isBigNumber(value) {
}
var BigNumber = /** @class */ (function () {
function BigNumber(value) {
if (!(this instanceof BigNumber)) {
throw new Error('missing new');
}
errors.checkNew(this, BigNumber);
if (typeof (value) === 'string') {
if (convert_1.isHexString(value)) {
if (value == '0x') {

View File

@ -5,11 +5,6 @@
*/
Object.defineProperty(exports, "__esModule", { value: true });
var errors = require("./errors");
/*
declare class BigNumber {
toHexString(): string;
}
*/
function isBigNumber(value) {
return !!value._bn;
}

View File

@ -3,3 +3,5 @@ export declare function defineFrozen(object: any, name: any, value: any): void;
export declare type DeferredSetter = (value: any) => void;
export declare function defineDeferredReadOnly(object: any, name: any, value: any): DeferredSetter;
export declare function resolveProperties(object: any): Promise<any>;
export declare function shallowCopy(object: any): any;
export declare function jsonCopy(object: any): any;

View File

@ -46,3 +46,15 @@ function resolveProperties(object) {
});
}
exports.resolveProperties = resolveProperties;
function shallowCopy(object) {
var result = {};
for (var key in object) {
result[key] = object[key];
}
return result;
}
exports.shallowCopy = shallowCopy;
function jsonCopy(object) {
return JSON.parse(JSON.stringify(object));
}
exports.jsonCopy = jsonCopy;

View File

@ -1 +1 @@
export declare function randomBytes(length: any): Uint8Array;
export declare function randomBytes(length: number): Uint8Array;

View File

@ -1,28 +1,8 @@
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
var convert_1 = require("./convert");
//import * as crypto from 'crypto';
//@TODO: Figure out how to fix crypto
function getRandomValues(buffer) {
for (var round = 0; round < 20; round++) {
for (var i = 0; i < buffer.length; i++) {
if (round) {
buffer[i] ^= Math.trunc(256 * Math.random());
}
else {
buffer[i] = Math.trunc(256 * Math.random());
}
}
}
return buffer;
}
var crypto_1 = require("crypto");
function randomBytes(length) {
if (length <= 0 || length > 1024 || parseInt(length) != length) {
throw new Error('invalid length');
}
var result = new Uint8Array(length);
getRandomValues(result);
return convert_1.arrayify(result);
return convert_1.arrayify(crypto_1.randomBytes(length));
}
exports.randomBytes = randomBytes;
;

5
src/utils/sha2.d.ts vendored
View File

@ -1,2 +1,3 @@
export declare function sha256(data: any): string;
export declare function sha512(data: any): string;
import { Arrayish } from './convert';
export declare function sha256(data: Arrayish): string;
export declare function sha512(data: Arrayish): string;

View File

@ -1,4 +1,5 @@
export declare function formatUnits(value: any, unitType: string | number, options?: any): string;
export declare function parseUnits(value: any, unitType: any): any;
export declare function formatEther(wei: any, options: any): string;
export declare function parseEther(ether: any): any;
import { BigNumber, BigNumberish } from './bignumber';
export declare function formatUnits(value: BigNumberish, unitType?: string | number, options?: any): string;
export declare function parseUnits(value: string, unitType?: string | number): BigNumber;
export declare function formatEther(wei: BigNumberish, options: any): string;
export declare function parseEther(ether: string): BigNumber;

View File

@ -69,7 +69,7 @@ function formatUnits(value, unitType, options) {
if (negative) {
value = value.mul(bignumber_1.ConstantNegativeOne);
}
var fraction = value.mod(unitInfo.tenPower).toString(10);
var fraction = value.mod(unitInfo.tenPower).toString();
while (fraction.length < unitInfo.decimals) {
fraction = '0' + fraction;
}
@ -77,7 +77,7 @@ function formatUnits(value, unitType, options) {
if (!options.pad) {
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];
}
var whole = value.div(unitInfo.tenPower).toString(10);
var whole = value.div(unitInfo.tenPower).toString();
if (options.commify) {
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
@ -126,9 +126,9 @@ function parseUnits(value, unitType) {
while (fraction.length < unitInfo.decimals) {
fraction += '0';
}
whole = bignumber_1.bigNumberify(whole);
fraction = bignumber_1.bigNumberify(fraction);
var wei = (whole.mul(unitInfo.tenPower)).add(fraction);
var wholeValue = bignumber_1.bigNumberify(whole);
var fractionValue = bignumber_1.bigNumberify(fraction);
var wei = (wholeValue.mul(unitInfo.tenPower)).add(fractionValue);
if (negative) {
wei = wei.mul(bignumber_1.ConstantNegativeOne);
}

View File

@ -1,4 +1,5 @@
import * as secp256k1 from './secp256k1';
import { KeyPair } from './secp256k1';
import { Arrayish } from '../utils/convert';
export declare class HDNode {
private readonly keyPair;
readonly privateKey: string;
@ -8,13 +9,13 @@ export declare class HDNode {
readonly chainCode: string;
readonly index: number;
readonly depth: number;
constructor(keyPair: secp256k1.KeyPair, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string);
constructor(keyPair: KeyPair, chainCode: Uint8Array, index: number, depth: number, mnemonic: string, path: string);
private _derive;
derivePath(path: string): HDNode;
}
export declare function fromMnemonic(mnemonic: string): HDNode;
export declare function fromSeed(seed: any): HDNode;
export declare function fromSeed(seed: Arrayish): HDNode;
export declare function mnemonicToSeed(mnemonic: string, password?: string): string;
export declare function mnemonicToEntropy(mnemonic: string): string;
export declare function entropyToMnemonic(entropy: any): string;
export declare function entropyToMnemonic(entropy: Arrayish): string;
export declare function isValidMnemonic(mnemonic: string): boolean;

View File

@ -6,15 +6,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
result["default"] = mod;
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
// See: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
var secp256k1 = __importStar(require("./secp256k1"));
var words_1 = __importDefault(require("./words"));
var wordlist = words_1.default.replace(/([A-Z])/g, ' $1').toLowerCase().substring(1).split(' ');
var secp256k1_1 = require("./secp256k1");
var words_1 = require("./words");
var convert_1 = require("../utils/convert");
var bignumber_1 = require("../utils/bignumber");
var utf8_1 = require("../utils/utf8");
@ -38,8 +34,8 @@ var HDNode = /** @class */ (function () {
function HDNode(keyPair, chainCode, index, depth, mnemonic, path) {
errors.checkNew(this, HDNode);
this.keyPair = keyPair;
this.privateKey = convert_1.hexlify(keyPair.priv.toArray('be', 32));
this.publicKey = '0x' + keyPair.getPublic(true, 'hex');
this.privateKey = keyPair.privateKey;
this.publicKey = keyPair.compressedPublicKey;
this.chainCode = convert_1.hexlify(chainCode);
this.index = index;
this.depth = depth;
@ -71,7 +67,7 @@ var HDNode = /** @class */ (function () {
}
else {
// Data = ser_p(point(k_par))
data.set(this.keyPair.getPublic().encode(null, true));
data.set(this.keyPair.publicKeyBytes);
}
// Data += ser_32(i)
for (var i = 24; i >= 0; i -= 8) {
@ -80,8 +76,8 @@ var HDNode = /** @class */ (function () {
var I = convert_1.arrayify(hmac_1.createSha512Hmac(this.chainCode).update(data).digest());
var IL = bignumber_1.bigNumberify(I.slice(0, 32));
var IR = I.slice(32);
var ki = IL.add('0x' + this.keyPair.getPrivate('hex')).mod('0x' + secp256k1.curve.n.toString(16));
return new HDNode(secp256k1.curve.keyFromPrivate(convert_1.arrayify(ki)), IR, index, this.depth + 1, mnemonic, path);
var ki = IL.add(this.keyPair.privateKey).mod(secp256k1_1.N);
return new HDNode(new secp256k1_1.KeyPair(convert_1.arrayify(ki)), IR, index, this.depth + 1, mnemonic, path);
};
HDNode.prototype.derivePath = function (path) {
var components = path.split('/');
@ -118,12 +114,12 @@ var HDNode = /** @class */ (function () {
}());
exports.HDNode = HDNode;
function _fromSeed(seed, mnemonic) {
seed = convert_1.arrayify(seed);
if (seed.length < 16 || seed.length > 64) {
var seedArray = convert_1.arrayify(seed);
if (seedArray.length < 16 || seedArray.length > 64) {
throw new Error('invalid seed');
}
var I = convert_1.arrayify(hmac_1.createSha512Hmac(MasterSecret).update(seed).digest());
return new HDNode(secp256k1.curve.keyFromPrivate(I.slice(0, 32)), I.slice(32), 0, 0, mnemonic, 'm');
var I = convert_1.arrayify(hmac_1.createSha512Hmac(MasterSecret).update(seedArray).digest());
return new HDNode(new secp256k1_1.KeyPair(I.slice(0, 32)), I.slice(32), 0, 0, mnemonic, 'm');
}
function fromMnemonic(mnemonic) {
// Check that the checksum s valid (will throw an error)
@ -162,7 +158,7 @@ function mnemonicToEntropy(mnemonic) {
var entropy = convert_1.arrayify(new Uint8Array(Math.ceil(11 * words.length / 8)));
var offset = 0;
for (var i = 0; i < words.length; i++) {
var index = wordlist.indexOf(words[i]);
var index = words_1.getWordIndex(words[i]);
if (index === -1) {
throw new Error('invalid mnemonic');
}
@ -189,21 +185,21 @@ function entropyToMnemonic(entropy) {
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
throw new Error('invalid entropy');
}
var words = [0];
var indices = [0];
var remainingBits = 11;
for (var i = 0; i < entropy.length; i++) {
// Consume the whole byte (with still more to go)
if (remainingBits > 8) {
words[words.length - 1] <<= 8;
words[words.length - 1] |= entropy[i];
indices[indices.length - 1] <<= 8;
indices[indices.length - 1] |= entropy[i];
remainingBits -= 8;
// This byte will complete an 11-bit index
}
else {
words[words.length - 1] <<= remainingBits;
words[words.length - 1] |= entropy[i] >> (8 - remainingBits);
indices[indices.length - 1] <<= remainingBits;
indices[indices.length - 1] |= entropy[i] >> (8 - remainingBits);
// Start the next word
words.push(entropy[i] & getLowerMask(8 - remainingBits));
indices.push(entropy[i] & getLowerMask(8 - remainingBits));
remainingBits += 3;
}
}
@ -212,14 +208,9 @@ function entropyToMnemonic(entropy) {
var checksumBits = entropy.length / 4;
checksum &= getUpperMask(checksumBits);
// Shift the checksum into the word indices
words[words.length - 1] <<= checksumBits;
words[words.length - 1] |= (checksum >> (8 - checksumBits));
// Convert indices into words
var result = [];
for (var i = 0; i < words.length; i++) {
result.push(wordlist[words[i]]);
}
return result.join(' ');
indices[indices.length - 1] <<= checksumBits;
indices[indices.length - 1] |= (checksum >> (8 - checksumBits));
return indices.map(function (index) { return words_1.getWord(index); }).join(' ');
}
exports.entropyToMnemonic = entropyToMnemonic;
function isValidMnemonic(mnemonic) {

View File

@ -1,31 +1,17 @@
export interface BN {
toString(radix: number): string;
encode(encoding: string, compact: boolean): Uint8Array;
toArray(endian: string, width: number): Uint8Array;
}
export interface Signature {
r: BN;
s: BN;
import { Arrayish } from '../utils/convert';
export declare type Signature = {
r: string;
s: string;
recoveryParam: number;
};
export declare class KeyPair {
readonly privateKey: string;
readonly publicKey: string;
readonly compressedPublicKey: string;
readonly publicKeyBytes: Uint8Array;
constructor(privateKey: Arrayish);
sign(digest: Arrayish): Signature;
}
export interface KeyPair {
sign(message: Uint8Array, options: {
canonical?: boolean;
}): Signature;
getPublic(compressed: boolean, encoding?: string): string;
getPublic(): BN;
getPrivate(encoding?: string): string;
encode(encoding: string, compressed: boolean): string;
priv: BN;
}
export interface EC {
constructor(curve: string): any;
n: BN;
keyFromPublic(publicKey: string | Uint8Array): KeyPair;
keyFromPrivate(privateKey: string | Uint8Array): KeyPair;
recoverPubKey(data: Uint8Array, signature: {
r: Uint8Array;
s: Uint8Array;
}, recoveryParam: number): KeyPair;
}
export declare const curve: EC;
export declare function recoverPublicKey(digest: Arrayish, signature: Signature): string;
export declare function computePublicKey(key: Arrayish, compressed?: boolean): string;
export declare const N: string;

View File

@ -7,5 +7,62 @@ var __importStar = (this && this.__importStar) || function (mod) {
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
var convert_1 = require("../utils/convert");
var properties_1 = require("../utils/properties");
var errors = __importStar(require("../utils/errors"));
var elliptic = __importStar(require("elliptic"));
exports.curve = new elliptic.ec('secp256k1');
var curve = new elliptic.ec('secp256k1');
var KeyPair = /** @class */ (function () {
function KeyPair(privateKey) {
var keyPair = curve.keyFromPrivate(convert_1.arrayify(privateKey));
properties_1.defineReadOnly(this, 'privateKey', convert_1.hexlify(keyPair.priv.toArray('be', 32)));
properties_1.defineReadOnly(this, 'publicKey', '0x' + keyPair.getPublic(false, 'hex'));
properties_1.defineReadOnly(this, 'compressedPublicKey', '0x' + keyPair.getPublic(true, 'hex'));
properties_1.defineReadOnly(this, 'publicKeyBytes', keyPair.getPublic().encode(null, true));
}
KeyPair.prototype.sign = function (digest) {
var keyPair = curve.keyFromPrivate(convert_1.arrayify(this.privateKey));
var signature = keyPair.sign(convert_1.arrayify(digest), { canonical: true });
return {
recoveryParam: signature.recoveryParam,
r: '0x' + signature.r.toString(16),
s: '0x' + signature.s.toString(16)
};
};
return KeyPair;
}());
exports.KeyPair = KeyPair;
function recoverPublicKey(digest, signature) {
var sig = {
r: convert_1.arrayify(signature.r),
s: convert_1.arrayify(signature.s)
};
return '0x' + curve.recoverPubKey(convert_1.arrayify(digest), sig, signature.recoveryParam).getPublic(false, 'hex');
}
exports.recoverPublicKey = recoverPublicKey;
function computePublicKey(key, compressed) {
var bytes = convert_1.arrayify(key);
if (bytes.length === 32) {
var keyPair = new KeyPair(bytes);
if (compressed) {
return keyPair.compressedPublicKey;
}
return keyPair.publicKey;
}
else if (bytes.length === 33) {
if (compressed) {
return convert_1.hexlify(bytes);
}
return '0x' + curve.keyFromPublic(bytes).getPublic(false, 'hex');
}
else if (bytes.length === 65) {
if (!compressed) {
return convert_1.hexlify(bytes);
}
return '0x' + curve.keyFromPublic(bytes).getPublic(true, 'hex');
}
errors.throwError('invalid public or private key', errors.INVALID_ARGUMENT, { arg: 'key', value: '[REDACTED]' });
return null;
}
exports.computePublicKey = computePublicKey;
exports.N = '0x' + curve.n.toString(16);

View File

@ -7,4 +7,4 @@ export declare function isCrowdsaleWallet(json: string): boolean;
export declare function isValidWallet(json: string): boolean;
export declare function decryptCrowdsale(json: string, password: Arrayish | string): SigningKey;
export declare function decrypt(json: string, password: any, progressCallback?: ProgressCallback): Promise<SigningKey>;
export declare function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish | string, options?: any, progressCallback?: ProgressCallback): Promise<{}>;
export declare function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish | string, options?: any, progressCallback?: ProgressCallback): Promise<string>;

View File

@ -262,11 +262,14 @@ function encrypt(privateKey, password, options, progressCallback) {
options = {};
}
// Check the private key
var privateKeyBytes = null;
if (privateKey instanceof signing_key_1.SigningKey) {
privateKey = privateKey.privateKey;
privateKeyBytes = convert_1.arrayify(privateKey.privateKey);
}
privateKey = convert_1.arrayify(privateKey);
if (privateKey.length !== 32) {
else {
privateKeyBytes = convert_1.arrayify(privateKey);
}
if (privateKeyBytes.length !== 32) {
throw new Error('invalid private key');
}
password = getPassword(password);
@ -353,11 +356,11 @@ function encrypt(privateKey, password, options, progressCallback) {
// This will be used to encrypt the mnemonic phrase (if any)
var mnemonicKey = key.slice(32, 64);
// Get the address for this private key
var address = (new signing_key_1.SigningKey(privateKey)).address;
var address = (new signing_key_1.SigningKey(privateKeyBytes)).address;
// Encrypt the private key
var counter = new aes.Counter(iv);
var aesCtr = new aes.ModeOfOperation.ctr(derivedKey, counter);
var ciphertext = convert_1.arrayify(aesCtr.encrypt(privateKey));
var ciphertext = convert_1.arrayify(aesCtr.encrypt(privateKeyBytes));
// Compute the message authentication code, used to check the password
var mac = keccak256_1.keccak256(convert_1.concat([macPrefix, ciphertext]));
// See: https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition

View File

@ -1,3 +1,11 @@
/**
* SigningKey
*
*
*/
import { Signature } from './secp256k1';
import { Arrayish } from '../utils/convert';
import { HDNode } from './hdnode';
export declare class SigningKey {
readonly privateKey: string;
readonly publicKey: string;
@ -5,13 +13,8 @@ export declare class SigningKey {
readonly mnemonic: string;
readonly path: string;
private readonly keyPair;
constructor(privateKey: any);
signDigest(digest: any): {
recoveryParam: number;
r: string;
s: string;
};
static recover(digest: any, r: any, s: any, recoveryParam: any): string;
static getPublicKey(value: any, compressed: any): string;
static publicKeyToAddress(publicKey: any): string;
constructor(privateKey: Arrayish | HDNode);
signDigest(digest: Arrayish): Signature;
}
export declare function recoverAddress(digest: Arrayish, signature: Signature): string;
export declare function computeAddress(key: string): string;

View File

@ -1,33 +1,31 @@
'use strict';
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
result["default"] = mod;
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
/**
* SigningKey
*
*
*/
var secp256k1 = __importStar(require("./secp256k1"));
var secp256k1_1 = require("./secp256k1");
var address_1 = require("../utils/address");
var convert_1 = require("../utils/convert");
var hdnode_1 = require("./hdnode");
var keccak256_1 = require("../utils/keccak256");
var properties_1 = require("../utils/properties");
var errors = require("../utils/errors");
var SigningKey = /** @class */ (function () {
function SigningKey(privateKey) {
errors.checkNew(this, SigningKey);
if (privateKey.privateKey) {
this.mnemonic = privateKey.mnemonic;
this.path = privateKey.path;
privateKey = privateKey.privateKey;
var privateKeyBytes = null;
if (privateKey instanceof hdnode_1.HDNode) {
properties_1.defineReadOnly(this, 'mnemonic', privateKey.mnemonic);
properties_1.defineReadOnly(this, 'path', privateKey.path);
privateKeyBytes = convert_1.arrayify(privateKey.privateKey);
}
else {
privateKeyBytes = convert_1.arrayify(privateKey);
}
try {
privateKey = convert_1.arrayify(privateKey);
if (privateKey.length !== 32) {
if (privateKeyBytes.length !== 32) {
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
}
}
@ -41,49 +39,24 @@ var SigningKey = /** @class */ (function () {
}
errors.throwError('invalid private key', error.code, params);
}
this.privateKey = convert_1.hexlify(privateKey);
this.keyPair = secp256k1.curve.keyFromPrivate(privateKey);
//utils.defineProperty(this, 'publicKey', '0x' + keyPair.getPublic(true, 'hex'))
this.publicKey = '0x' + this.keyPair.getPublic(true, 'hex');
this.address = SigningKey.publicKeyToAddress('0x' + this.keyPair.getPublic(false, 'hex'));
properties_1.defineReadOnly(this, 'privateKey', convert_1.hexlify(privateKeyBytes));
properties_1.defineReadOnly(this, 'keyPair', new secp256k1_1.KeyPair(privateKeyBytes));
properties_1.defineReadOnly(this, 'publicKey', this.keyPair.publicKey);
properties_1.defineReadOnly(this, 'address', computeAddress(this.keyPair.publicKey));
}
SigningKey.prototype.signDigest = function (digest) {
var signature = this.keyPair.sign(convert_1.arrayify(digest), { canonical: true });
return {
recoveryParam: signature.recoveryParam,
r: '0x' + signature.r.toString(16),
s: '0x' + signature.s.toString(16)
};
};
SigningKey.recover = function (digest, r, s, recoveryParam) {
var signature = {
r: convert_1.arrayify(r),
s: convert_1.arrayify(s)
};
var publicKey = secp256k1.curve.recoverPubKey(convert_1.arrayify(digest), signature, recoveryParam);
return SigningKey.publicKeyToAddress('0x' + publicKey.encode('hex', false));
};
SigningKey.getPublicKey = function (value, compressed) {
value = convert_1.arrayify(value);
compressed = !!compressed;
if (value.length === 32) {
var keyPair = secp256k1.curve.keyFromPrivate(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
}
else if (value.length === 33) {
var keyPair = secp256k1.curve.keyFromPublic(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
}
else if (value.length === 65) {
var keyPair = secp256k1.curve.keyFromPublic(value);
return '0x' + keyPair.getPublic(compressed, 'hex');
}
throw new Error('invalid value');
};
SigningKey.publicKeyToAddress = function (publicKey) {
publicKey = '0x' + SigningKey.getPublicKey(publicKey, false).slice(4);
return address_1.getAddress('0x' + keccak256_1.keccak256(publicKey).substring(26));
return this.keyPair.sign(digest);
};
return SigningKey;
}());
exports.SigningKey = SigningKey;
function recoverAddress(digest, signature) {
return computeAddress(secp256k1_1.recoverPublicKey(digest, signature));
}
exports.recoverAddress = recoverAddress;
function computeAddress(key) {
// Strip off the leading "0x04"
var publicKey = '0x' + secp256k1_1.computePublicKey(key).slice(4);
return address_1.getAddress('0x' + keccak256_1.keccak256(publicKey).substring(26));
}
exports.computeAddress = computeAddress;

View File

@ -1,7 +1,9 @@
import { BigNumber } from '../utils/bignumber';
import { Arrayish } from '../utils/convert';
import { HDNode } from './hdnode';
import { ProgressCallback } from './secret-storage';
import { SigningKey } from './signing-key';
import { BlockTag } from '../providers/provider';
import { BigNumber, BigNumberish } from '../utils/bignumber';
import { Arrayish } from '../utils/convert';
interface Provider {
chainId: number;
getBalance(address: string, blockTag: number | string): Promise<BigNumber>;
@ -43,19 +45,19 @@ export declare class Wallet {
sign(transaction: TransactionRequest): string;
static parseTransaction(rawTransaction: Arrayish): TransactionRequest;
getAddress(): Promise<string>;
getBalance(blockTag: any): any;
getTransactionCount(blockTag: any): any;
estimateGas(transaction: TransactionRequest): any;
sendTransaction(transaction: any): Promise<any>;
send(addressOrName: any, amountWei: any, options: any): Promise<any>;
static hashMessage(message: any): string;
signMessage(message: any): string;
static verifyMessage(message: any, signature: any): string;
encrypt(password: any, options: any, progressCallback: any): Promise<{}>;
getBalance(blockTag: BlockTag): Promise<BigNumber>;
getTransactionCount(blockTag: BlockTag): Promise<number>;
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
sendTransaction(transaction: any): Promise<TransactionResponse>;
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse>;
static hashMessage(message: Arrayish | string): string;
signMessage(message: Arrayish | string): string;
static verifyMessage(message: Arrayish | string, signature: string): string;
encrypt(password: Arrayish | string, options: any, progressCallback: ProgressCallback): Promise<string>;
static createRandom(options: any): Wallet;
static isEncryptedWallet(json: string): boolean;
static fromEncryptedWallet(json: any, password: any, progressCallback: any): Promise<{}>;
static fromEncryptedWallet(json: string, password: Arrayish, progressCallback: ProgressCallback): Promise<Wallet>;
static fromMnemonic(mnemonic: string, path?: string): Wallet;
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback: any): Promise<{}>;
static fromBrainWallet(username: Arrayish | string, password: Arrayish | string, progressCallback: ProgressCallback): Promise<Wallet>;
}
export {};

View File

@ -11,6 +11,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
var scrypt_js_1 = __importDefault(require("scrypt-js"));
var hdnode_1 = require("./hdnode");
var secretStorage = __importStar(require("./secret-storage"));
var signing_key_1 = require("./signing-key");
var address_1 = require("../utils/address");
var bignumber_1 = require("../utils/bignumber");
var convert_1 = require("../utils/convert");
@ -19,9 +22,6 @@ var random_bytes_1 = require("../utils/random-bytes");
var RLP = __importStar(require("../utils/rlp"));
var utf8_1 = require("../utils/utf8");
var errors = __importStar(require("../utils/errors"));
var hdnode_1 = require("./hdnode");
var secretStorage = __importStar(require("./secret-storage"));
var signing_key_1 = require("./signing-key");
// This ensures we inject a setImmediate into the global space, which
// dramatically improves the performance of the scrypt PBKDF.
console.log("Fix this! Setimmediate");
@ -177,7 +177,7 @@ var Wallet = /** @class */ (function () {
}
var digest = keccak256_1.keccak256(RLP.encode(raw));
try {
transaction.from = signing_key_1.SigningKey.recover(digest, r, s, recoveryParam);
transaction.from = signing_key_1.recoverAddress(digest, { r: convert_1.hexlify(r), s: convert_1.hexlify(s), recoveryParam: recoveryParam });
}
catch (error) {
console.log(error);
@ -310,7 +310,11 @@ var Wallet = /** @class */ (function () {
if (recoveryParam < 0) {
throw new Error('invalid signature');
}
return signing_key_1.SigningKey.recover(digest, signature.substring(0, 66), '0x' + signature.substring(66, 130), recoveryParam);
return signing_key_1.recoverAddress(digest, {
r: signature.substring(0, 66),
s: '0x' + signature.substring(66, 130),
recoveryParam: recoveryParam
});
};
Wallet.prototype.encrypt = function (password, options, progressCallback) {
if (typeof (options) === 'function' && !progressCallback) {

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long