Refactor API.
This commit is contained in:
parent
7391cf8d19
commit
efbfed0d40
189
dist/ethers.d.ts
vendored
189
dist/ethers.d.ts
vendored
File diff suppressed because one or more lines are too long
460
dist/ethers.js
vendored
460
dist/ethers.js
vendored
File diff suppressed because one or more lines are too long
2
dist/ethers.min.js
vendored
2
dist/ethers.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/ethers.min.js.map
vendored
2
dist/ethers.min.js.map
vendored
File diff suppressed because one or more lines are too long
@ -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"
|
||||
},
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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([]);
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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> {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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)) {
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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"; }
|
||||
|
||||
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);
|
||||
};
|
||||
export function randomBytes(length: number): Uint8Array {
|
||||
return arrayify(_randomBytes(length));
|
||||
}
|
||||
|
||||
|
@ -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'));
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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]))
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
return getAddress('0x' + keccak256(publicKey).substring(26));
|
||||
signDigest(digest: Arrayish): Signature {
|
||||
return this.keyPair.sign(digest);
|
||||
}
|
||||
}
|
||||
|
||||
//export default SigningKey;
|
||||
export function recoverAddress(digest: Arrayish, signature: Signature): string {
|
||||
return computeAddress(recoverPublicKey(digest, signature));
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
@ -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
4
src/contracts/interface.d.ts
vendored
4
src/contracts/interface.d.ts
vendored
@ -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;
|
||||
|
@ -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
3
src/index.d.ts
vendored
@ -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, };
|
||||
|
@ -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");
|
||||
|
2
src/providers/infura-provider.d.ts
vendored
2
src/providers/infura-provider.d.ts
vendored
@ -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>>;
|
||||
}
|
||||
|
2
src/providers/ipc-provider.d.ts
vendored
2
src/providers/ipc-provider.d.ts
vendored
@ -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>;
|
||||
}
|
||||
|
8
src/providers/json-rpc-provider.d.ts
vendored
8
src/providers/json-rpc-provider.d.ts
vendored
@ -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;
|
||||
}
|
||||
|
9
src/providers/provider.d.ts
vendored
9
src/providers/provider.d.ts
vendored
@ -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;
|
||||
|
2
src/providers/web3-provider.d.ts
vendored
2
src/providers/web3-provider.d.ts
vendored
@ -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>;
|
||||
}
|
||||
|
19
src/utils/abi-coder.d.ts
vendored
19
src/utils/abi-coder.d.ts
vendored
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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') {
|
||||
|
@ -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;
|
||||
}
|
||||
|
2
src/utils/properties.d.ts
vendored
2
src/utils/properties.d.ts
vendored
@ -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;
|
||||
|
@ -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;
|
||||
|
2
src/utils/random-bytes.d.ts
vendored
2
src/utils/random-bytes.d.ts
vendored
@ -1 +1 @@
|
||||
export declare function randomBytes(length: any): Uint8Array;
|
||||
export declare function randomBytes(length: number): Uint8Array;
|
||||
|
@ -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
5
src/utils/sha2.d.ts
vendored
@ -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;
|
||||
|
9
src/utils/units.d.ts
vendored
9
src/utils/units.d.ts
vendored
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
9
src/wallet/hdnode.d.ts
vendored
9
src/wallet/hdnode.d.ts
vendored
@ -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;
|
||||
|
@ -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) {
|
||||
|
44
src/wallet/secp256k1.d.ts
vendored
44
src/wallet/secp256k1.d.ts
vendored
@ -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;
|
||||
|
@ -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);
|
||||
|
2
src/wallet/secret-storage.d.ts
vendored
2
src/wallet/secret-storage.d.ts
vendored
@ -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>;
|
||||
|
@ -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
|
||||
|
21
src/wallet/signing-key.d.ts
vendored
21
src/wallet/signing-key.d.ts
vendored
@ -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;
|
||||
|
@ -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;
|
||||
|
28
src/wallet/wallet.d.ts
vendored
28
src/wallet/wallet.d.ts
vendored
@ -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 {};
|
||||
|
@ -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) {
|
||||
|
4
src/wallet/words.d.ts
vendored
4
src/wallet/words.d.ts
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user