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",
|
"fs": "./tests/browser-fs.js",
|
||||||
"zlib": "browserify-zlib",
|
"zlib": "browserify-zlib",
|
||||||
"./src.ts/utils/base64.ts": "./src.browser/base64.ts",
|
"./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",
|
"./providers/ipc-provider.js": "./utils/empty.js",
|
||||||
"xmlhttprequest": "./src.browser/xmlhttprequest.ts"
|
"xmlhttprequest": "./src.browser/xmlhttprequest.ts"
|
||||||
},
|
},
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import convert = require('./convert');
|
import { arrayify } from '../src.ts/utils/convert';
|
||||||
import properties = require('./properties');
|
import { defineReadOnly } from '../src.ts/utils/properties';
|
||||||
var defineProperty = properties.defineProperty;
|
|
||||||
|
|
||||||
var crypto = global.crypto || global.msCrypto;
|
let crypto: any = global['crypto'] || global['msCrypto'];
|
||||||
if (!crypto || !crypto.getRandomValues) {
|
if (!crypto || !crypto.getRandomValues) {
|
||||||
|
|
||||||
console.log('WARNING: Missing strong random number source; using weak randomBytes');
|
console.log('WARNING: Missing strong random number source; using weak randomBytes');
|
||||||
|
|
||||||
crypto = {
|
crypto = {
|
||||||
getRandomValues: function(buffer) {
|
getRandomValues: function(buffer: Uint8Array) {
|
||||||
for (var round = 0; round < 20; round++) {
|
for (var round = 0; round < 20; round++) {
|
||||||
for (var i = 0; i < buffer.length; i++) {
|
for (var i = 0; i < buffer.length; i++) {
|
||||||
if (round) {
|
if (round) {
|
||||||
buffer[i] ^= parseInt(256 * Math.random());
|
buffer[i] ^= Math.trunc(256 * Math.random());
|
||||||
} else {
|
} 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) {
|
if (length <= 0 || length > 1024 || parseInt(length) != length) {
|
||||||
throw new Error('invalid length');
|
throw new Error('invalid length');
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = new Uint8Array(length);
|
var result = new Uint8Array(length);
|
||||||
crypto.getRandomValues(result);
|
crypto.getRandomValues(result);
|
||||||
return convert.arrayify(result);
|
return arrayify(result);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (crypto._weakCrypto === true) {
|
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 {
|
export class Indexed {
|
||||||
readonly hash: string;
|
readonly hash: string;
|
||||||
constructor(value) {
|
constructor(value: string) {
|
||||||
defineReadOnly(this, 'indexed', true);
|
|
||||||
defineReadOnly(this, 'hash', value);
|
defineReadOnly(this, 'hash', value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -325,7 +324,7 @@ function addMethod(method: any): void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class Interface {
|
export class Interface {
|
||||||
readonly _abi: Array<any>;
|
readonly abi: Array<any>;
|
||||||
readonly functions: Array<FunctionDescription>;
|
readonly functions: Array<FunctionDescription>;
|
||||||
readonly events: Array<EventDescription>;
|
readonly events: Array<EventDescription>;
|
||||||
readonly deployFunction: DeployDescription;
|
readonly deployFunction: DeployDescription;
|
||||||
@ -354,15 +353,17 @@ export class Interface {
|
|||||||
defineReadOnly(this, 'events', { });
|
defineReadOnly(this, 'events', { });
|
||||||
|
|
||||||
// Convert any supported ABI format into a standard ABI format
|
// Convert any supported ABI format into a standard ABI format
|
||||||
this._abi = [];
|
let _abi = [];
|
||||||
abi.forEach((fragment) => {
|
abi.forEach((fragment) => {
|
||||||
if (typeof(fragment) === 'string') {
|
if (typeof(fragment) === 'string') {
|
||||||
fragment = parseSignature(fragment);
|
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 there wasn't a constructor, create the default constructor
|
||||||
if (!this.deployFunction) {
|
if (!this.deployFunction) {
|
||||||
@ -388,6 +389,7 @@ export class Interface {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @TODO:
|
||||||
|
//parseEvent(log: { }): Lo
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
import { Contract, Interface } from './contracts';
|
import { Contract, Interface } from './contracts';
|
||||||
import * as providers from './providers';
|
import * as providers from './providers';
|
||||||
import * as errors from './utils/errors';
|
import * as errors from './utils/errors';
|
||||||
|
import { networks } from './providers/networks';
|
||||||
import utils from './utils';
|
import utils from './utils';
|
||||||
import { HDNode, SigningKey, Wallet } from './wallet';
|
import { HDNode, SigningKey, Wallet } from './wallet';
|
||||||
|
|
||||||
@ -19,6 +20,7 @@ export {
|
|||||||
Contract,
|
Contract,
|
||||||
Interface,
|
Interface,
|
||||||
|
|
||||||
|
networks,
|
||||||
providers,
|
providers,
|
||||||
|
|
||||||
errors,
|
errors,
|
||||||
|
@ -36,7 +36,7 @@ export class InfuraProvider extends JsonRpcProvider {
|
|||||||
this.apiAccessToken = (apiAccessToken || null);
|
this.apiAccessToken = (apiAccessToken || null);
|
||||||
}
|
}
|
||||||
|
|
||||||
_startPending() {
|
_startPending(): void {
|
||||||
console.log('WARNING: INFURA does not support pending filters');
|
console.log('WARNING: INFURA does not support pending filters');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export class InfuraProvider extends JsonRpcProvider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
listAccounts() {
|
listAccounts(): Promise<Array<string>> {
|
||||||
return Promise.resolve([]);
|
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
|
// @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
|
// This method is very simple right now. We create a new socket
|
||||||
// connection each time, which may be slower, but the main
|
// connection each time, which may be slower, but the main
|
||||||
// advantage we are aiming for now is security. This simplifies
|
// 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);
|
return new JsonRpcSigner(this, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
listAccounts() {
|
listAccounts(): Promise<Array<string>> {
|
||||||
return this.send('eth_accounts', []).then((accounts) => {
|
return this.send('eth_accounts', []).then((accounts) => {
|
||||||
return accounts.map((a) => getAddress(a));
|
return accounts.map((a) => getAddress(a));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
send(method, params) {
|
send(method: string, params: any): Promise<any> {
|
||||||
var request = {
|
var request = {
|
||||||
method: method,
|
method: method,
|
||||||
params: params,
|
params: params,
|
||||||
id: 42,
|
id: 42,
|
||||||
jsonrpc: "2.0"
|
jsonrpc: "2.0"
|
||||||
};
|
};
|
||||||
|
|
||||||
return fetchJson(this.connection, JSON.stringify(request), getResult);
|
return fetchJson(this.connection, JSON.stringify(request), getResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
perform(method, params) {
|
perform(method: string, params: any): Promise<any> {
|
||||||
switch (method) {
|
switch (method) {
|
||||||
case 'getBlockNumber':
|
case 'getBlockNumber':
|
||||||
return this.send('eth_blockNumber', []);
|
return this.send('eth_blockNumber', []);
|
||||||
@ -283,7 +284,7 @@ export class JsonRpcProvider extends Provider {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_startPending() {
|
_startPending(): void {
|
||||||
if (this._pendingFilter != null) { return; }
|
if (this._pendingFilter != null) { return; }
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
@ -322,7 +323,7 @@ export class JsonRpcProvider extends Provider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_stopPending() {
|
_stopPending(): void {
|
||||||
this._pendingFilter = null;
|
this._pendingFilter = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,6 +58,7 @@ export type TransactionRequest = {
|
|||||||
export type TransactionResponse = {
|
export type TransactionResponse = {
|
||||||
blockNumber?: number,
|
blockNumber?: number,
|
||||||
blockHash?: string,
|
blockHash?: string,
|
||||||
|
timestamp?: number,
|
||||||
|
|
||||||
hash: string,
|
hash: string,
|
||||||
|
|
||||||
@ -291,7 +292,7 @@ var formatTransaction = {
|
|||||||
raw: allowNull(hexlify),
|
raw: allowNull(hexlify),
|
||||||
};
|
};
|
||||||
|
|
||||||
export function checkTransactionResponse(transaction) {
|
export function checkTransactionResponse(transaction: any): TransactionResponse {
|
||||||
|
|
||||||
// Rename gas to gasLimit
|
// Rename gas to gasLimit
|
||||||
if (transaction.gas != null && transaction.gasLimit == null) {
|
if (transaction.gas != null && transaction.gasLimit == null) {
|
||||||
@ -632,7 +633,7 @@ export class Provider {
|
|||||||
this._emitted = { block: this._lastBlockNumber };
|
this._emitted = { block: this._lastBlockNumber };
|
||||||
}
|
}
|
||||||
|
|
||||||
private _doPoll() {
|
private _doPoll(): void {
|
||||||
this.getBlockNumber().then((blockNumber) => {
|
this.getBlockNumber().then((blockNumber) => {
|
||||||
|
|
||||||
// If the block hasn't changed, meh.
|
// If the block hasn't changed, meh.
|
||||||
@ -706,12 +707,12 @@ export class Provider {
|
|||||||
this.doPoll();
|
this.doPoll();
|
||||||
}
|
}
|
||||||
|
|
||||||
resetEventsBlock(blockNumber) {
|
resetEventsBlock(blockNumber: number): void {
|
||||||
this._lastBlockNumber = this.blockNumber;
|
this._lastBlockNumber = this.blockNumber;
|
||||||
this._doPoll();
|
this._doPoll();
|
||||||
}
|
}
|
||||||
|
|
||||||
get network() {
|
get network(): Network {
|
||||||
return this._network;
|
return this._network;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -724,11 +725,11 @@ export class Provider {
|
|||||||
return this._lastBlockNumber;
|
return this._lastBlockNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
get polling() {
|
get polling(): boolean {
|
||||||
return (this._poller != null);
|
return (this._poller != null);
|
||||||
}
|
}
|
||||||
|
|
||||||
set polling(value) {
|
set polling(value: boolean) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (value && !this._poller) {
|
if (value && !this._poller) {
|
||||||
this._poller = setInterval(this._doPoll.bind(this), this.pollingInterval);
|
this._poller = setInterval(this._doPoll.bind(this), this.pollingInterval);
|
||||||
@ -740,7 +741,7 @@ export class Provider {
|
|||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
get pollingInterval() {
|
get pollingInterval(): number {
|
||||||
return this._pollingInterval;
|
return this._pollingInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -992,7 +993,7 @@ export class Provider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
_resolveNames(object, keys) {
|
_resolveNames(object: any, keys: Array<string>): Promise<any> {
|
||||||
var promises = [];
|
var promises = [];
|
||||||
|
|
||||||
var result = copyObject(object);
|
var result = copyObject(object);
|
||||||
@ -1007,7 +1008,7 @@ export class Provider {
|
|||||||
return Promise.all(promises).then(function() { return result; });
|
return Promise.all(promises).then(function() { return result; });
|
||||||
}
|
}
|
||||||
|
|
||||||
_getResolver(name) {
|
_getResolver(name: string): Promise<string> {
|
||||||
// Get the resolver from the blockchain
|
// Get the resolver from the blockchain
|
||||||
return this.getNetwork().then((network) => {
|
return this.getNetwork().then((network) => {
|
||||||
|
|
||||||
@ -1115,7 +1116,7 @@ export class Provider {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
doPoll() {
|
doPoll(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
perform(method: string, params: any): Promise<any> {
|
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 Callback = (error: any, response: any) => void;
|
||||||
|
|
||||||
export type AsyncProvider = {
|
export type AsyncProvider = {
|
||||||
isMetaMask: boolean;
|
isMetaMask: boolean;
|
||||||
host?: string;
|
host?: string;
|
||||||
@ -42,7 +43,7 @@ export class Web3Provider extends JsonRpcProvider {
|
|||||||
this._web3Provider = web3Provider;
|
this._web3Provider = web3Provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
send(method, params) {
|
send(method: string, params: any): Promise<any> {
|
||||||
|
|
||||||
// Metamask complains about eth_sign (and on some versions hangs)
|
// Metamask complains about eth_sign (and on some versions hangs)
|
||||||
if (method == 'eth_sign' && this._web3Provider.isMetaMask) {
|
if (method == 'eth_sign' && this._web3Provider.isMetaMask) {
|
||||||
|
@ -6,6 +6,7 @@ import { getAddress } from './address';
|
|||||||
import { bigNumberify, BigNumberish } from './bignumber';
|
import { bigNumberify, BigNumberish } from './bignumber';
|
||||||
import { arrayify, Arrayish, concat, hexlify, padZeros } from './convert';
|
import { arrayify, Arrayish, concat, hexlify, padZeros } from './convert';
|
||||||
import { toUtf8Bytes, toUtf8String } from './utf8';
|
import { toUtf8Bytes, toUtf8String } from './utf8';
|
||||||
|
import { defineReadOnly, jsonCopy } from './properties';
|
||||||
|
|
||||||
import * as errors from './errors';
|
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 CoerceFunc = (type: string, value: any) => any;
|
||||||
export type ParamType = { name?: string, type: string, indexed?: boolean, components?: Array<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)
|
var match = type.match(paramTypeNumber)
|
||||||
if (match && parseInt(match[2]) <= 48) { return value.toNumber(); }
|
if (match && parseInt(match[2]) <= 48) { return value.toNumber(); }
|
||||||
return value;
|
return value;
|
||||||
@ -173,8 +174,32 @@ function parseParam(param: string, allowIndexed?: boolean): ParamType {
|
|||||||
return (<ParamType>parent);
|
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
|
// @TODO: Better return type
|
||||||
function parseSignatureEvent(fragment: string): any {
|
function parseSignatureEvent(fragment: string): EventFragment {
|
||||||
|
|
||||||
var abi = {
|
var abi = {
|
||||||
anonymous: false,
|
anonymous: false,
|
||||||
@ -213,7 +238,7 @@ function parseSignatureEvent(fragment: string): any {
|
|||||||
return abi;
|
return abi;
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseSignatureFunction(fragment: string): any {
|
function parseSignatureFunction(fragment: string): FunctionFragment {
|
||||||
var abi = {
|
var abi = {
|
||||||
constant: false,
|
constant: false,
|
||||||
inputs: [],
|
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') {
|
if(typeof(fragment) === 'string') {
|
||||||
// Make sure the "returns" is surrounded by a space and all whitespace is exactly one space
|
// 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, ' ');
|
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 {
|
export class AbiCoder {
|
||||||
readonly coerceFunc: CoerceFunc;
|
readonly coerceFunc: CoerceFunc;
|
||||||
constructor(coerceFunc?: CoerceFunc) {
|
constructor(coerceFunc?: CoerceFunc) {
|
||||||
//if (!(this instanceof Coder)) { throw new Error('missing new'); }
|
errors.checkNew(this, AbiCoder);
|
||||||
|
|
||||||
if (!coerceFunc) { coerceFunc = defaultCoerceFunc; }
|
if (!coerceFunc) { coerceFunc = defaultCoerceFunc; }
|
||||||
// @TODO: readonly
|
defineReadOnly(this, 'coerceFunc', coerceFunc);
|
||||||
this.coerceFunc = coerceFunc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encode(types: Array<string | ParamType>, values: Array<any>): string {
|
encode(types: Array<string | ParamType>, values: Array<any>): string {
|
||||||
@ -928,11 +953,16 @@ export class AbiCoder {
|
|||||||
// Convert types to type objects
|
// Convert types to type objects
|
||||||
// - "uint foo" => { type: "uint", name: "foo" }
|
// - "uint foo" => { type: "uint", name: "foo" }
|
||||||
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
|
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
|
||||||
|
|
||||||
|
let typeObject: ParamType = null;
|
||||||
if (typeof(type) === 'string') {
|
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);
|
}, this);
|
||||||
|
|
||||||
return hexlify(new CoderTuple(this.coerceFunc, coders, '_').encode(values));
|
return hexlify(new CoderTuple(this.coerceFunc, coders, '_').encode(values));
|
||||||
@ -944,11 +974,14 @@ export class AbiCoder {
|
|||||||
types.forEach(function(type) {
|
types.forEach(function(type) {
|
||||||
|
|
||||||
// See encode for details
|
// See encode for details
|
||||||
|
let typeObject: ParamType = null;
|
||||||
if (typeof(type) === 'string') {
|
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);
|
}, this);
|
||||||
|
|
||||||
return new CoderTuple(this.coerceFunc, coders, '_').decode(arrayify(data), 0).value;
|
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 {
|
export class BigNumber {
|
||||||
readonly _bn: _BN.BN;
|
readonly _bn: _BN.BN;
|
||||||
constructor(value: BigNumberish) {
|
constructor(value: BigNumberish) {
|
||||||
if (!(this instanceof BigNumber)) { throw new Error('missing new'); }
|
errors.checkNew(this, BigNumber);
|
||||||
|
|
||||||
if (typeof(value) === 'string') {
|
if (typeof(value) === 'string') {
|
||||||
if (isHexString(value)) {
|
if (isHexString(value)) {
|
||||||
|
@ -51,3 +51,13 @@ export function resolveProperties(object: any) {
|
|||||||
return object;
|
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 { arrayify } from './convert';
|
||||||
|
|
||||||
//import * as crypto from 'crypto';
|
import { randomBytes as _randomBytes } from 'crypto';
|
||||||
|
|
||||||
//@TODO: Figure out how to fix crypto
|
//function _randomBytes(length) { return "0x00"; }
|
||||||
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;
|
export function randomBytes(length: number): Uint8Array {
|
||||||
}
|
return arrayify(_randomBytes(length));
|
||||||
|
}
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import * as _hash from 'hash.js';
|
import * as _hash from 'hash.js';
|
||||||
|
|
||||||
import { arrayify } from './convert';
|
import { arrayify, Arrayish } from './convert';
|
||||||
|
|
||||||
|
|
||||||
interface HashFunc {
|
interface HashFunc {
|
||||||
@ -15,10 +15,10 @@ const _sha256: HashFunc = _hash['sha256'];
|
|||||||
const _sha512: HashFunc = _hash['sha512'];
|
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'));
|
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'));
|
return '0x' + (_sha512().update(arrayify(data)).digest('hex'));
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
import { bigNumberify, ConstantZero, ConstantNegativeOne } from './bignumber';
|
import { BigNumber, bigNumberify, BigNumberish, ConstantZero, ConstantNegativeOne } from './bignumber';
|
||||||
|
|
||||||
import * as errors from './errors';
|
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) {
|
if (typeof(unitType) === 'object' && !options) {
|
||||||
options = unitType;
|
options = unitType;
|
||||||
@ -75,7 +75,7 @@ export function formatUnits(value: any, unitType: string | number, options?: any
|
|||||||
var negative = value.lt(ConstantZero);
|
var negative = value.lt(ConstantZero);
|
||||||
if (negative) { value = value.mul(ConstantNegativeOne); }
|
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; }
|
while (fraction.length < unitInfo.decimals) { fraction = '0' + fraction; }
|
||||||
|
|
||||||
// Strip off trailing zeros (but keep one if would otherwise be bare decimal point)
|
// 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];
|
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) {
|
if (options.commify) {
|
||||||
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
|
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
|
||||||
@ -96,7 +96,7 @@ export function formatUnits(value: any, unitType: string | number, options?: any
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseUnits(value, unitType) {
|
export function parseUnits(value: string, unitType?: string | number): BigNumber {
|
||||||
if (unitType == null) { unitType = 18; }
|
if (unitType == null) { unitType = 18; }
|
||||||
var unitInfo = getUnitInfo(unitType);
|
var unitInfo = getUnitInfo(unitType);
|
||||||
|
|
||||||
@ -116,12 +116,12 @@ export function parseUnits(value, unitType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Split it into a whole and fractional part
|
// Split it into a whole and fractional part
|
||||||
var comps = value.split('.');
|
let comps = value.split('.');
|
||||||
if (comps.length > 2) {
|
if (comps.length > 2) {
|
||||||
errors.throwError('too many decimal points', errors.INVALID_ARGUMENT, { arg: 'value', value: value });
|
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 (!whole) { whole = '0'; }
|
||||||
if (!fraction) { fraction = '0'; }
|
if (!fraction) { fraction = '0'; }
|
||||||
|
|
||||||
@ -137,21 +137,21 @@ export function parseUnits(value, unitType) {
|
|||||||
// Fully pad the string with zeros to get to wei
|
// Fully pad the string with zeros to get to wei
|
||||||
while (fraction.length < unitInfo.decimals) { fraction += '0'; }
|
while (fraction.length < unitInfo.decimals) { fraction += '0'; }
|
||||||
|
|
||||||
whole = bigNumberify(whole);
|
let wholeValue = bigNumberify(whole);
|
||||||
fraction = bigNumberify(fraction);
|
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); }
|
if (negative) { wei = wei.mul(ConstantNegativeOne); }
|
||||||
|
|
||||||
return wei;
|
return wei;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatEther(wei, options) {
|
export function formatEther(wei: BigNumberish, options: any): string {
|
||||||
return formatUnits(wei, 18, options);
|
return formatUnits(wei, 18, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseEther(ether) {
|
export function parseEther(ether: string): BigNumber {
|
||||||
return parseUnits(ether, 18);
|
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-0032.mediawiki
|
||||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.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';
|
import { getWord, getWordIndex } from './words';
|
||||||
var wordlist: Array<string> = words.replace(/([A-Z])/g, ' $1').toLowerCase().substring(1).split(' ');
|
|
||||||
|
|
||||||
import { arrayify, hexlify } from '../utils/convert';
|
import { arrayify, Arrayish, hexlify } from '../utils/convert';
|
||||||
import { bigNumberify } from '../utils/bignumber';
|
import { bigNumberify } from '../utils/bignumber';
|
||||||
import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
|
import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
|
||||||
import { pbkdf2 } from '../utils/pbkdf2';
|
import { pbkdf2 } from '../utils/pbkdf2';
|
||||||
@ -33,7 +32,7 @@ function getLowerMask(bits: number): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class HDNode {
|
export class HDNode {
|
||||||
private readonly keyPair: secp256k1.KeyPair;
|
private readonly keyPair: KeyPair;
|
||||||
|
|
||||||
readonly privateKey: string;
|
readonly privateKey: string;
|
||||||
readonly publicKey: string;
|
readonly publicKey: string;
|
||||||
@ -47,13 +46,13 @@ export class HDNode {
|
|||||||
readonly depth: number;
|
readonly depth: number;
|
||||||
|
|
||||||
// @TODO: Private constructor?
|
// @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);
|
errors.checkNew(this, HDNode);
|
||||||
|
|
||||||
this.keyPair = keyPair;
|
this.keyPair = keyPair;
|
||||||
|
|
||||||
this.privateKey = hexlify(keyPair.priv.toArray('be', 32));
|
this.privateKey = keyPair.privateKey;
|
||||||
this.publicKey = '0x' + keyPair.getPublic(true, 'hex');
|
this.publicKey = keyPair.compressedPublicKey;
|
||||||
|
|
||||||
this.chainCode = hexlify(chainCode);
|
this.chainCode = hexlify(chainCode);
|
||||||
|
|
||||||
@ -88,7 +87,7 @@ export class HDNode {
|
|||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Data = ser_p(point(k_par))
|
// Data = ser_p(point(k_par))
|
||||||
data.set(this.keyPair.getPublic().encode(null, true));
|
data.set(this.keyPair.publicKeyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data += ser_32(i)
|
// Data += ser_32(i)
|
||||||
@ -98,9 +97,9 @@ export class HDNode {
|
|||||||
var IL = bigNumberify(I.slice(0, 32));
|
var IL = bigNumberify(I.slice(0, 32));
|
||||||
var IR = I.slice(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 {
|
derivePath(path: string): HDNode {
|
||||||
@ -132,13 +131,13 @@ export class HDNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function _fromSeed(seed: any, mnemonic: string): HDNode {
|
function _fromSeed(seed: Arrayish, mnemonic: string): HDNode {
|
||||||
seed = arrayify(seed);
|
let seedArray: Uint8Array = arrayify(seed);
|
||||||
if (seed.length < 16 || seed.length > 64) { throw new Error('invalid 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 {
|
export function fromMnemonic(mnemonic: string): HDNode {
|
||||||
@ -148,7 +147,7 @@ export function fromMnemonic(mnemonic: string): HDNode {
|
|||||||
return _fromSeed(mnemonicToSeed(mnemonic), mnemonic);
|
return _fromSeed(mnemonicToSeed(mnemonic), mnemonic);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function fromSeed(seed: any): HDNode {
|
export function fromSeed(seed: Arrayish): HDNode {
|
||||||
return _fromSeed(seed, null);
|
return _fromSeed(seed, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +179,7 @@ export function mnemonicToEntropy(mnemonic: string): string {
|
|||||||
|
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
for (var i = 0; i < words.length; i++) {
|
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'); }
|
if (index === -1) { throw new Error('invalid mnemonic'); }
|
||||||
|
|
||||||
for (var bit = 0; bit < 11; bit++) {
|
for (var bit = 0; bit < 11; bit++) {
|
||||||
@ -206,32 +205,32 @@ export function mnemonicToEntropy(mnemonic: string): string {
|
|||||||
return hexlify(entropy.slice(0, entropyBits / 8));
|
return hexlify(entropy.slice(0, entropyBits / 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function entropyToMnemonic(entropy: any): string {
|
export function entropyToMnemonic(entropy: Arrayish): string {
|
||||||
entropy = arrayify(entropy);
|
entropy = arrayify(entropy);
|
||||||
|
|
||||||
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
|
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
|
||||||
throw new Error('invalid entropy');
|
throw new Error('invalid entropy');
|
||||||
}
|
}
|
||||||
|
|
||||||
var words: Array<number> = [ 0 ];
|
var indices: Array<number> = [ 0 ];
|
||||||
|
|
||||||
var remainingBits = 11;
|
var remainingBits = 11;
|
||||||
for (var i = 0; i < entropy.length; i++) {
|
for (var i = 0; i < entropy.length; i++) {
|
||||||
|
|
||||||
// Consume the whole byte (with still more to go)
|
// Consume the whole byte (with still more to go)
|
||||||
if (remainingBits > 8) {
|
if (remainingBits > 8) {
|
||||||
words[words.length - 1] <<= 8;
|
indices[indices.length - 1] <<= 8;
|
||||||
words[words.length - 1] |= entropy[i];
|
indices[indices.length - 1] |= entropy[i];
|
||||||
|
|
||||||
remainingBits -= 8;
|
remainingBits -= 8;
|
||||||
|
|
||||||
// This byte will complete an 11-bit index
|
// This byte will complete an 11-bit index
|
||||||
} else {
|
} else {
|
||||||
words[words.length - 1] <<= remainingBits;
|
indices[indices.length - 1] <<= remainingBits;
|
||||||
words[words.length - 1] |= entropy[i] >> (8 - remainingBits);
|
indices[indices.length - 1] |= entropy[i] >> (8 - remainingBits);
|
||||||
|
|
||||||
// Start the next word
|
// Start the next word
|
||||||
words.push(entropy[i] & getLowerMask(8 - remainingBits));
|
indices.push(entropy[i] & getLowerMask(8 - remainingBits));
|
||||||
|
|
||||||
remainingBits += 3;
|
remainingBits += 3;
|
||||||
}
|
}
|
||||||
@ -243,16 +242,10 @@ export function entropyToMnemonic(entropy: any): string {
|
|||||||
checksum &= getUpperMask(checksumBits);
|
checksum &= getUpperMask(checksumBits);
|
||||||
|
|
||||||
// Shift the checksum into the word indices
|
// Shift the checksum into the word indices
|
||||||
words[words.length - 1] <<= checksumBits;
|
indices[indices.length - 1] <<= checksumBits;
|
||||||
words[words.length - 1] |= (checksum >> (8 - checksumBits));
|
indices[indices.length - 1] |= (checksum >> (8 - checksumBits));
|
||||||
|
|
||||||
// Convert indices into words
|
return indices.map((index) => getWord(index)).join(' ');
|
||||||
var result = [];
|
|
||||||
for (var i = 0; i < words.length; i++) {
|
|
||||||
result.push(wordlist[words[i]]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.join(' ');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isValidMnemonic(mnemonic: string): boolean {
|
export function isValidMnemonic(mnemonic: string): boolean {
|
||||||
@ -262,22 +255,3 @@ export function isValidMnemonic(mnemonic: string): boolean {
|
|||||||
} catch (error) { }
|
} catch (error) { }
|
||||||
return false;
|
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';
|
'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;
|
toString(radix: number): string;
|
||||||
encode(encoding: string, compact: boolean): Uint8Array;
|
encode(encoding: string, compact: boolean): Uint8Array;
|
||||||
toArray(endian: string, width: number): Uint8Array;
|
toArray(endian: string, width: number): Uint8Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Signature {
|
interface _Signature {
|
||||||
r: BN,
|
r: _BN,
|
||||||
s: BN,
|
s: _BN,
|
||||||
recoveryParam: number
|
recoveryParam: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface KeyPair {
|
interface _KeyPair {
|
||||||
sign(message: Uint8Array, options: { canonical?: boolean }): Signature;
|
sign(message: Uint8Array, options: { canonical?: boolean }): _Signature;
|
||||||
getPublic(compressed: boolean, encoding?: string): string;
|
getPublic(compressed: boolean, encoding?: string): string;
|
||||||
getPublic(): BN;
|
getPublic(): _BN;
|
||||||
getPrivate(encoding?: string): string;
|
getPrivate(encoding?: string): string;
|
||||||
encode(encoding: string, compressed: boolean): string;
|
encode(encoding: string, compressed: boolean): string;
|
||||||
priv: BN;
|
priv: _BN;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EC {
|
interface _EC {
|
||||||
constructor(curve: string);
|
constructor(curve: string);
|
||||||
|
|
||||||
n: BN;
|
n: _BN;
|
||||||
|
|
||||||
keyFromPublic(publicKey: string | Uint8Array): KeyPair;
|
keyFromPublic(publicKey: string | Uint8Array): _KeyPair;
|
||||||
keyFromPrivate(privateKey: string | Uint8Array): KeyPair;
|
keyFromPrivate(privateKey: string | Uint8Array): _KeyPair;
|
||||||
recoverPubKey(data: Uint8Array, signature: { r: Uint8Array, s: Uint8Array }, recoveryParam: number): KeyPair;
|
recoverPubKey(data: Uint8Array, signature: { r: Uint8Array, s: Uint8Array }, recoveryParam: number): _KeyPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
import * as elliptic from 'elliptic';
|
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
|
// @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
|
// the options are optional, so adjust the call as needed
|
||||||
if (typeof(options) === 'function' && !progressCallback) {
|
if (typeof(options) === 'function' && !progressCallback) {
|
||||||
@ -302,11 +302,13 @@ export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish |
|
|||||||
if (!options) { options = {}; }
|
if (!options) { options = {}; }
|
||||||
|
|
||||||
// Check the private key
|
// Check the private key
|
||||||
|
let privateKeyBytes = null;
|
||||||
if (privateKey instanceof SigningKey) {
|
if (privateKey instanceof SigningKey) {
|
||||||
privateKey = privateKey.privateKey;
|
privateKeyBytes = arrayify(privateKey.privateKey);
|
||||||
|
} else {
|
||||||
|
privateKeyBytes = arrayify(privateKey);
|
||||||
}
|
}
|
||||||
privateKey = arrayify(privateKey);
|
if (privateKeyBytes.length !== 32) { throw new Error('invalid private key'); }
|
||||||
if (privateKey.length !== 32) { throw new Error('invalid private key'); }
|
|
||||||
|
|
||||||
password = getPassword(password);
|
password = getPassword(password);
|
||||||
|
|
||||||
@ -387,12 +389,12 @@ export function encrypt(privateKey: Arrayish | SigningKey, password: Arrayish |
|
|||||||
var mnemonicKey = key.slice(32, 64);
|
var mnemonicKey = key.slice(32, 64);
|
||||||
|
|
||||||
// Get the address for this private key
|
// Get the address for this private key
|
||||||
var address = (new SigningKey(privateKey)).address;
|
var address = (new SigningKey(privateKeyBytes)).address;
|
||||||
|
|
||||||
// Encrypt the private key
|
// Encrypt the private key
|
||||||
var counter = new aes.Counter(iv);
|
var counter = new aes.Counter(iv);
|
||||||
var aesCtr = new aes.ModeOfOperation.ctr(derivedKey, counter);
|
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
|
// Compute the message authentication code, used to check the password
|
||||||
var mac = keccak256(concat([macPrefix, ciphertext]))
|
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 { 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 { keccak256 } from '../utils/keccak256';
|
||||||
|
import { defineReadOnly } from '../utils/properties';
|
||||||
|
|
||||||
import errors = require('../utils/errors');
|
import errors = require('../utils/errors');
|
||||||
|
|
||||||
|
|
||||||
export class SigningKey {
|
export class SigningKey {
|
||||||
|
|
||||||
readonly privateKey: string;
|
readonly privateKey: string;
|
||||||
@ -24,20 +25,23 @@ export class SigningKey {
|
|||||||
readonly mnemonic: string;
|
readonly mnemonic: string;
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
|
|
||||||
private readonly keyPair: secp256k1.KeyPair;
|
private readonly keyPair: KeyPair;
|
||||||
|
|
||||||
constructor(privateKey: any) {
|
constructor(privateKey: Arrayish | HDNode) {
|
||||||
errors.checkNew(this, SigningKey);
|
errors.checkNew(this, SigningKey);
|
||||||
|
|
||||||
if (privateKey.privateKey) {
|
let privateKeyBytes = null;
|
||||||
this.mnemonic = privateKey.mnemonic;
|
|
||||||
this.path = privateKey.path;
|
if (privateKey instanceof HDNode) {
|
||||||
privateKey = privateKey.privateKey;
|
defineReadOnly(this, 'mnemonic', privateKey.mnemonic);
|
||||||
|
defineReadOnly(this, 'path', privateKey.path);
|
||||||
|
privateKeyBytes = arrayify(privateKey.privateKey);
|
||||||
|
} else {
|
||||||
|
privateKeyBytes = arrayify(privateKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
privateKey = arrayify(privateKey);
|
if (privateKeyBytes.length !== 32) {
|
||||||
if (privateKey.length !== 32) {
|
|
||||||
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
|
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
|
||||||
}
|
}
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
@ -51,59 +55,23 @@ export class SigningKey {
|
|||||||
errors.throwError('invalid private key', error.code, params);
|
errors.throwError('invalid private key', error.code, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.privateKey = hexlify(privateKey);
|
defineReadOnly(this, 'privateKey', hexlify(privateKeyBytes));
|
||||||
|
defineReadOnly(this, 'keyPair', new KeyPair(privateKeyBytes));
|
||||||
this.keyPair = secp256k1.curve.keyFromPrivate(privateKey);
|
defineReadOnly(this, 'publicKey', this.keyPair.publicKey);
|
||||||
|
defineReadOnly(this, 'address', computeAddress(this.keyPair.publicKey));
|
||||||
//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'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
signDigest(digest) {
|
signDigest(digest: Arrayish): Signature {
|
||||||
var signature = this.keyPair.sign(arrayify(digest), {canonical: true});
|
return this.keyPair.sign(digest);
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//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 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 { 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 { arrayify, Arrayish, concat, hexlify, stripZeros, hexZeroPad } from '../utils/convert';
|
||||||
import { keccak256 } from '../utils/keccak256';
|
import { keccak256 } from '../utils/keccak256';
|
||||||
import { randomBytes } from '../utils/random-bytes';
|
import { randomBytes } from '../utils/random-bytes';
|
||||||
@ -12,9 +19,6 @@ import { toUtf8Bytes, UnicodeNormalizationForm } from '../utils/utf8';
|
|||||||
|
|
||||||
import * as errors from '../utils/errors';
|
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
|
// This ensures we inject a setImmediate into the global space, which
|
||||||
// dramatically improves the performance of the scrypt PBKDF.
|
// 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;
|
var chainId = transaction.chainId;
|
||||||
if (chainId == null && this.provider) { chainId = this.provider.chainId; }
|
if (chainId == null && this.provider) { chainId = this.provider.chainId; }
|
||||||
if (!chainId) { chainId = 0; }
|
if (!chainId) { chainId = 0; }
|
||||||
@ -238,7 +242,7 @@ export class Wallet {
|
|||||||
|
|
||||||
var digest = keccak256(RLP.encode(raw));
|
var digest = keccak256(RLP.encode(raw));
|
||||||
try {
|
try {
|
||||||
transaction.from = SigningKey.recover(digest, r, s, recoveryParam);
|
transaction.from = recoverAddress(digest, { r: hexlify(r), s: hexlify(s), recoveryParam });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
@ -247,21 +251,21 @@ export class Wallet {
|
|||||||
return transaction;
|
return transaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
getAddress() {
|
getAddress(): Promise<string> {
|
||||||
return Promise.resolve(this.address);
|
return Promise.resolve(this.address);
|
||||||
}
|
}
|
||||||
|
|
||||||
getBalance(blockTag) {
|
getBalance(blockTag: BlockTag): Promise<BigNumber> {
|
||||||
if (!this.provider) { throw new Error('missing provider'); }
|
if (!this.provider) { throw new Error('missing provider'); }
|
||||||
return this.provider.getBalance(this.address, blockTag);
|
return this.provider.getBalance(this.address, blockTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
getTransactionCount(blockTag) {
|
getTransactionCount(blockTag: BlockTag): Promise<number> {
|
||||||
if (!this.provider) { throw new Error('missing provider'); }
|
if (!this.provider) { throw new Error('missing provider'); }
|
||||||
return this.provider.getTransactionCount(this.address, blockTag);
|
return this.provider.getTransactionCount(this.address, blockTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
estimateGas(transaction: TransactionRequest) {
|
estimateGas(transaction: TransactionRequest): Promise<BigNumber> {
|
||||||
if (!this.provider) { throw new Error('missing provider'); }
|
if (!this.provider) { throw new Error('missing provider'); }
|
||||||
|
|
||||||
var calculate: TransactionRequest = {};
|
var calculate: TransactionRequest = {};
|
||||||
@ -275,7 +279,7 @@ export class Wallet {
|
|||||||
return this.provider.estimateGas(calculate);
|
return this.provider.estimateGas(calculate);
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTransaction(transaction) {
|
sendTransaction(transaction: any): Promise<TransactionResponse> {
|
||||||
if (!this.provider) { throw new Error('missing provider'); }
|
if (!this.provider) { throw new Error('missing provider'); }
|
||||||
|
|
||||||
if (!transaction || typeof(transaction) !== 'object') {
|
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 = {}; }
|
if (!options) { options = {}; }
|
||||||
|
|
||||||
return this.sendTransaction({
|
return this.sendTransaction({
|
||||||
@ -348,7 +352,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static hashMessage(message) {
|
static hashMessage(message: Arrayish | string): string {
|
||||||
var payload = concat([
|
var payload = concat([
|
||||||
toUtf8Bytes('\x19Ethereum Signed Message:\n'),
|
toUtf8Bytes('\x19Ethereum Signed Message:\n'),
|
||||||
toUtf8Bytes(String(message.length)),
|
toUtf8Bytes(String(message.length)),
|
||||||
@ -357,14 +361,14 @@ export class Wallet {
|
|||||||
return keccak256(payload);
|
return keccak256(payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
signMessage(message) {
|
signMessage(message: Arrayish | string): string {
|
||||||
var signingKey = new SigningKey(this.privateKey);
|
var signingKey = new SigningKey(this.privateKey);
|
||||||
var sig = signingKey.signDigest(Wallet.hashMessage(message));
|
var sig = signingKey.signDigest(Wallet.hashMessage(message));
|
||||||
|
|
||||||
return (hexZeroPad(sig.r, 32) + hexZeroPad(sig.s, 32).substring(2) + (sig.recoveryParam ? '1c': '1b'));
|
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);
|
signature = hexlify(signature);
|
||||||
if (signature.length != 132) { throw new Error('invalid signature'); }
|
if (signature.length != 132) { throw new Error('invalid signature'); }
|
||||||
var digest = Wallet.hashMessage(message);
|
var digest = Wallet.hashMessage(message);
|
||||||
@ -373,15 +377,17 @@ export class Wallet {
|
|||||||
if (recoveryParam >= 27) { recoveryParam -= 27; }
|
if (recoveryParam >= 27) { recoveryParam -= 27; }
|
||||||
if (recoveryParam < 0) { throw new Error('invalid signature'); }
|
if (recoveryParam < 0) { throw new Error('invalid signature'); }
|
||||||
|
|
||||||
return SigningKey.recover(
|
return recoverAddress(
|
||||||
digest,
|
digest,
|
||||||
signature.substring(0, 66),
|
{
|
||||||
'0x' + signature.substring(66, 130),
|
r: signature.substring(0, 66),
|
||||||
recoveryParam
|
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) {
|
if (typeof(options) === 'function' && !progressCallback) {
|
||||||
progressCallback = options;
|
progressCallback = options;
|
||||||
options = {};
|
options = {};
|
||||||
@ -408,7 +414,7 @@ export class Wallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static createRandom(options) {
|
static createRandom(options: any): Wallet {
|
||||||
var entropy: Uint8Array = randomBytes(16);
|
var entropy: Uint8Array = randomBytes(16);
|
||||||
|
|
||||||
if (!options) { options = { }; }
|
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));
|
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') {
|
if (progressCallback && typeof(progressCallback) !== 'function') {
|
||||||
throw new Error('invalid callback');
|
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; }
|
if (!path) { path = defaultPath; }
|
||||||
return new Wallet(fromMnemonic(mnemonic).derivePath(path));
|
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') {
|
if (progressCallback && typeof(progressCallback) !== 'function') {
|
||||||
throw new Error('invalid callback');
|
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';
|
import { BigNumber, BigNumberish } from '../utils/bignumber';
|
||||||
export declare class Indexed {
|
export declare class Indexed {
|
||||||
readonly hash: string;
|
readonly hash: string;
|
||||||
constructor(value: any);
|
constructor(value: string);
|
||||||
}
|
}
|
||||||
export declare class Description {
|
export declare class Description {
|
||||||
readonly type: string;
|
readonly type: string;
|
||||||
@ -37,7 +37,7 @@ export declare class EventDescription extends Description {
|
|||||||
decode(data: string, topics?: Array<string>): any;
|
decode(data: string, topics?: Array<string>): any;
|
||||||
}
|
}
|
||||||
export declare class Interface {
|
export declare class Interface {
|
||||||
readonly _abi: Array<any>;
|
readonly abi: Array<any>;
|
||||||
readonly functions: Array<FunctionDescription>;
|
readonly functions: Array<FunctionDescription>;
|
||||||
readonly events: Array<EventDescription>;
|
readonly events: Array<EventDescription>;
|
||||||
readonly deployFunction: DeployDescription;
|
readonly deployFunction: DeployDescription;
|
||||||
|
@ -54,7 +54,6 @@ function parseParams(params) {
|
|||||||
}
|
}
|
||||||
var Indexed = /** @class */ (function () {
|
var Indexed = /** @class */ (function () {
|
||||||
function Indexed(value) {
|
function Indexed(value) {
|
||||||
properties_1.defineReadOnly(this, 'indexed', true);
|
|
||||||
properties_1.defineReadOnly(this, 'hash', value);
|
properties_1.defineReadOnly(this, 'hash', value);
|
||||||
}
|
}
|
||||||
return Indexed;
|
return Indexed;
|
||||||
@ -302,7 +301,6 @@ function addMethod(method) {
|
|||||||
}
|
}
|
||||||
var Interface = /** @class */ (function () {
|
var Interface = /** @class */ (function () {
|
||||||
function Interface(abi) {
|
function Interface(abi) {
|
||||||
var _this = this;
|
|
||||||
errors.checkNew(this, Interface);
|
errors.checkNew(this, Interface);
|
||||||
if (typeof (abi) === 'string') {
|
if (typeof (abi) === 'string') {
|
||||||
try {
|
try {
|
||||||
@ -323,14 +321,15 @@ var Interface = /** @class */ (function () {
|
|||||||
properties_1.defineReadOnly(this, 'functions', {});
|
properties_1.defineReadOnly(this, 'functions', {});
|
||||||
properties_1.defineReadOnly(this, 'events', {});
|
properties_1.defineReadOnly(this, 'events', {});
|
||||||
// Convert any supported ABI format into a standard ABI format
|
// Convert any supported ABI format into a standard ABI format
|
||||||
this._abi = [];
|
var _abi = [];
|
||||||
abi.forEach(function (fragment) {
|
abi.forEach(function (fragment) {
|
||||||
if (typeof (fragment) === 'string') {
|
if (typeof (fragment) === 'string') {
|
||||||
fragment = abi_coder_1.parseSignature(fragment);
|
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 there wasn't a constructor, create the default constructor
|
||||||
if (!this.deployFunction) {
|
if (!this.deployFunction) {
|
||||||
addMethod.call(this, { type: 'constructor', inputs: [] });
|
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 { Contract, Interface } from './contracts';
|
||||||
import * as providers from './providers';
|
import * as providers from './providers';
|
||||||
import * as errors from './utils/errors';
|
import * as errors from './utils/errors';
|
||||||
|
import { networks } from './providers/networks';
|
||||||
import utils from './utils';
|
import utils from './utils';
|
||||||
import { HDNode, SigningKey, Wallet } from './wallet';
|
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;
|
exports.providers = providers;
|
||||||
var errors = __importStar(require("./utils/errors"));
|
var errors = __importStar(require("./utils/errors"));
|
||||||
exports.errors = errors;
|
exports.errors = errors;
|
||||||
|
var networks_1 = require("./providers/networks");
|
||||||
|
exports.networks = networks_1.networks;
|
||||||
var utils_1 = __importDefault(require("./utils"));
|
var utils_1 = __importDefault(require("./utils"));
|
||||||
exports.utils = utils_1.default;
|
exports.utils = utils_1.default;
|
||||||
var wallet_1 = require("./wallet");
|
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);
|
constructor(network?: Network | string, apiAccessToken?: string);
|
||||||
_startPending(): void;
|
_startPending(): void;
|
||||||
getSigner(address?: string): JsonRpcSigner;
|
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 {
|
export declare class IpcProvider extends JsonRpcProvider {
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
constructor(path: string, network?: Network | 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;
|
readonly connection: ConnectionInfo;
|
||||||
private _pendingFilter;
|
private _pendingFilter;
|
||||||
constructor(url?: ConnectionInfo | string, network?: Network | string);
|
constructor(url?: ConnectionInfo | string, network?: Network | string);
|
||||||
getSigner(address: any): JsonRpcSigner;
|
getSigner(address: string): JsonRpcSigner;
|
||||||
listAccounts(): Promise<any>;
|
listAccounts(): Promise<Array<string>>;
|
||||||
send(method: any, params: any): Promise<any>;
|
send(method: string, params: any): Promise<any>;
|
||||||
perform(method: any, params: any): Promise<any>;
|
perform(method: string, params: any): Promise<any>;
|
||||||
_startPending(): void;
|
_startPending(): void;
|
||||||
_stopPending(): 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 = {
|
export declare type TransactionResponse = {
|
||||||
blockNumber?: number;
|
blockNumber?: number;
|
||||||
blockHash?: string;
|
blockHash?: string;
|
||||||
|
timestamp?: number;
|
||||||
hash: string;
|
hash: string;
|
||||||
to?: string;
|
to?: string;
|
||||||
from?: string;
|
from?: string;
|
||||||
@ -72,7 +73,7 @@ export declare type Log = {
|
|||||||
transactionHash?: string;
|
transactionHash?: string;
|
||||||
logIndex?: number;
|
logIndex?: number;
|
||||||
};
|
};
|
||||||
export declare function checkTransactionResponse(transaction: any): any;
|
export declare function checkTransactionResponse(transaction: any): TransactionResponse;
|
||||||
export declare class Provider {
|
export declare class Provider {
|
||||||
private _network;
|
private _network;
|
||||||
protected ready: Promise<Network>;
|
protected ready: Promise<Network>;
|
||||||
@ -89,7 +90,7 @@ export declare class Provider {
|
|||||||
*/
|
*/
|
||||||
constructor(network: string | Network);
|
constructor(network: string | Network);
|
||||||
private _doPoll;
|
private _doPoll;
|
||||||
resetEventsBlock(blockNumber: any): void;
|
resetEventsBlock(blockNumber: number): void;
|
||||||
readonly network: Network;
|
readonly network: Network;
|
||||||
getNetwork(): Promise<Network>;
|
getNetwork(): Promise<Network>;
|
||||||
readonly blockNumber: number;
|
readonly blockNumber: number;
|
||||||
@ -110,8 +111,8 @@ export declare class Provider {
|
|||||||
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
getTransactionReceipt(transactionHash: string): Promise<TransactionReceipt>;
|
||||||
getLogs(filter: Filter): Promise<Array<Log>>;
|
getLogs(filter: Filter): Promise<Array<Log>>;
|
||||||
getEtherPrice(): Promise<number>;
|
getEtherPrice(): Promise<number>;
|
||||||
_resolveNames(object: any, keys: any): Promise<{}>;
|
_resolveNames(object: any, keys: Array<string>): Promise<any>;
|
||||||
_getResolver(name: any): Promise<string>;
|
_getResolver(name: string): Promise<string>;
|
||||||
resolveName(name: string | Promise<string>): Promise<string>;
|
resolveName(name: string | Promise<string>): Promise<string>;
|
||||||
lookupAddress(address: string | Promise<string>): Promise<string>;
|
lookupAddress(address: string | Promise<string>): Promise<string>;
|
||||||
doPoll(): void;
|
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 {
|
export declare class Web3Provider extends JsonRpcProvider {
|
||||||
readonly _web3Provider: AsyncProvider;
|
readonly _web3Provider: AsyncProvider;
|
||||||
constructor(web3Provider: AsyncProvider, network?: Network | string);
|
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;
|
indexed?: boolean;
|
||||||
components?: Array<any>;
|
components?: Array<any>;
|
||||||
};
|
};
|
||||||
export declare function defaultCoerceFunc(type: string, value: any): any;
|
export declare const defaultCoerceFunc: CoerceFunc;
|
||||||
export declare function parseSignature(fragment: string): any;
|
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 {
|
export declare class AbiCoder {
|
||||||
readonly coerceFunc: CoerceFunc;
|
readonly coerceFunc: CoerceFunc;
|
||||||
constructor(coerceFunc?: CoerceFunc);
|
constructor(coerceFunc?: CoerceFunc);
|
||||||
|
@ -22,18 +22,18 @@ var address_1 = require("./address");
|
|||||||
var bignumber_1 = require("./bignumber");
|
var bignumber_1 = require("./bignumber");
|
||||||
var convert_1 = require("./convert");
|
var convert_1 = require("./convert");
|
||||||
var utf8_1 = require("./utf8");
|
var utf8_1 = require("./utf8");
|
||||||
|
var properties_1 = require("./properties");
|
||||||
var errors = __importStar(require("./errors"));
|
var errors = __importStar(require("./errors"));
|
||||||
var paramTypeBytes = new RegExp(/^bytes([0-9]*)$/);
|
var paramTypeBytes = new RegExp(/^bytes([0-9]*)$/);
|
||||||
var paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/);
|
var paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/);
|
||||||
var paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
|
var paramTypeArray = new RegExp(/^(.*)\[([0-9]*)\]$/);
|
||||||
function defaultCoerceFunc(type, value) {
|
exports.defaultCoerceFunc = function (type, value) {
|
||||||
var match = type.match(paramTypeNumber);
|
var match = type.match(paramTypeNumber);
|
||||||
if (match && parseInt(match[2]) <= 48) {
|
if (match && parseInt(match[2]) <= 48) {
|
||||||
return value.toNumber();
|
return value.toNumber();
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
};
|
||||||
exports.defaultCoerceFunc = defaultCoerceFunc;
|
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
// Parsing for Solidity Signatures
|
// Parsing for Solidity Signatures
|
||||||
var regexParen = new RegExp("^([^)(]*)\\((.*)\\)([^)(]*)$");
|
var regexParen = new RegExp("^([^)(]*)\\((.*)\\)([^)(]*)$");
|
||||||
@ -259,7 +259,7 @@ function parseSignature(fragment) {
|
|||||||
return parseSignatureFunction(fragment.trim());
|
return parseSignatureFunction(fragment.trim());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
throw new Error('unknown fragment');
|
throw new Error('unknown signature');
|
||||||
}
|
}
|
||||||
exports.parseSignature = parseSignature;
|
exports.parseSignature = parseSignature;
|
||||||
var Coder = /** @class */ (function () {
|
var Coder = /** @class */ (function () {
|
||||||
@ -837,12 +837,11 @@ function getParamCoder(coerceFunc, param) {
|
|||||||
}
|
}
|
||||||
var AbiCoder = /** @class */ (function () {
|
var AbiCoder = /** @class */ (function () {
|
||||||
function AbiCoder(coerceFunc) {
|
function AbiCoder(coerceFunc) {
|
||||||
//if (!(this instanceof Coder)) { throw new Error('missing new'); }
|
errors.checkNew(this, AbiCoder);
|
||||||
if (!coerceFunc) {
|
if (!coerceFunc) {
|
||||||
coerceFunc = defaultCoerceFunc;
|
coerceFunc = exports.defaultCoerceFunc;
|
||||||
}
|
}
|
||||||
// @TODO: readonly
|
properties_1.defineReadOnly(this, 'coerceFunc', coerceFunc);
|
||||||
this.coerceFunc = coerceFunc;
|
|
||||||
}
|
}
|
||||||
AbiCoder.prototype.encode = function (types, values) {
|
AbiCoder.prototype.encode = function (types, values) {
|
||||||
if (types.length !== values.length) {
|
if (types.length !== values.length) {
|
||||||
@ -856,10 +855,14 @@ var AbiCoder = /** @class */ (function () {
|
|||||||
// Convert types to type objects
|
// Convert types to type objects
|
||||||
// - "uint foo" => { type: "uint", name: "foo" }
|
// - "uint foo" => { type: "uint", name: "foo" }
|
||||||
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
|
// - "tuple(uint, uint)" => { type: "tuple", components: [ { type: "uint" }, { type: "uint" }, ] }
|
||||||
|
var typeObject = null;
|
||||||
if (typeof (type) === 'string') {
|
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);
|
}, this);
|
||||||
return convert_1.hexlify(new CoderTuple(this.coerceFunc, coders, '_').encode(values));
|
return convert_1.hexlify(new CoderTuple(this.coerceFunc, coders, '_').encode(values));
|
||||||
};
|
};
|
||||||
@ -867,10 +870,14 @@ var AbiCoder = /** @class */ (function () {
|
|||||||
var coders = [];
|
var coders = [];
|
||||||
types.forEach(function (type) {
|
types.forEach(function (type) {
|
||||||
// See encode for details
|
// See encode for details
|
||||||
|
var typeObject = null;
|
||||||
if (typeof (type) === 'string') {
|
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);
|
}, this);
|
||||||
return new CoderTuple(this.coerceFunc, coders, '_').decode(convert_1.arrayify(data), 0).value;
|
return new CoderTuple(this.coerceFunc, coders, '_').decode(convert_1.arrayify(data), 0).value;
|
||||||
};
|
};
|
||||||
|
@ -56,9 +56,7 @@ function _isBigNumber(value) {
|
|||||||
}
|
}
|
||||||
var BigNumber = /** @class */ (function () {
|
var BigNumber = /** @class */ (function () {
|
||||||
function BigNumber(value) {
|
function BigNumber(value) {
|
||||||
if (!(this instanceof BigNumber)) {
|
errors.checkNew(this, BigNumber);
|
||||||
throw new Error('missing new');
|
|
||||||
}
|
|
||||||
if (typeof (value) === 'string') {
|
if (typeof (value) === 'string') {
|
||||||
if (convert_1.isHexString(value)) {
|
if (convert_1.isHexString(value)) {
|
||||||
if (value == '0x') {
|
if (value == '0x') {
|
||||||
|
@ -5,11 +5,6 @@
|
|||||||
*/
|
*/
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
var errors = require("./errors");
|
var errors = require("./errors");
|
||||||
/*
|
|
||||||
declare class BigNumber {
|
|
||||||
toHexString(): string;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
function isBigNumber(value) {
|
function isBigNumber(value) {
|
||||||
return !!value._bn;
|
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 type DeferredSetter = (value: any) => void;
|
||||||
export declare function defineDeferredReadOnly(object: any, name: any, value: any): DeferredSetter;
|
export declare function defineDeferredReadOnly(object: any, name: any, value: any): DeferredSetter;
|
||||||
export declare function resolveProperties(object: any): Promise<any>;
|
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;
|
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';
|
'use strict';
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
var convert_1 = require("./convert");
|
var convert_1 = require("./convert");
|
||||||
//import * as crypto from 'crypto';
|
var crypto_1 = require("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;
|
|
||||||
}
|
|
||||||
function randomBytes(length) {
|
function randomBytes(length) {
|
||||||
if (length <= 0 || length > 1024 || parseInt(length) != length) {
|
return convert_1.arrayify(crypto_1.randomBytes(length));
|
||||||
throw new Error('invalid length');
|
|
||||||
}
|
|
||||||
var result = new Uint8Array(length);
|
|
||||||
getRandomValues(result);
|
|
||||||
return convert_1.arrayify(result);
|
|
||||||
}
|
}
|
||||||
exports.randomBytes = randomBytes;
|
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;
|
import { Arrayish } from './convert';
|
||||||
export declare function sha512(data: any): string;
|
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;
|
import { BigNumber, BigNumberish } from './bignumber';
|
||||||
export declare function parseUnits(value: any, unitType: any): any;
|
export declare function formatUnits(value: BigNumberish, unitType?: string | number, options?: any): string;
|
||||||
export declare function formatEther(wei: any, options: any): string;
|
export declare function parseUnits(value: string, unitType?: string | number): BigNumber;
|
||||||
export declare function parseEther(ether: any): any;
|
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) {
|
if (negative) {
|
||||||
value = value.mul(bignumber_1.ConstantNegativeOne);
|
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) {
|
while (fraction.length < unitInfo.decimals) {
|
||||||
fraction = '0' + fraction;
|
fraction = '0' + fraction;
|
||||||
}
|
}
|
||||||
@ -77,7 +77,7 @@ function formatUnits(value, unitType, options) {
|
|||||||
if (!options.pad) {
|
if (!options.pad) {
|
||||||
fraction = fraction.match(/^([0-9]*[1-9]|0)(0*)/)[1];
|
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) {
|
if (options.commify) {
|
||||||
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
whole = whole.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
|
||||||
}
|
}
|
||||||
@ -126,9 +126,9 @@ function parseUnits(value, unitType) {
|
|||||||
while (fraction.length < unitInfo.decimals) {
|
while (fraction.length < unitInfo.decimals) {
|
||||||
fraction += '0';
|
fraction += '0';
|
||||||
}
|
}
|
||||||
whole = bignumber_1.bigNumberify(whole);
|
var wholeValue = bignumber_1.bigNumberify(whole);
|
||||||
fraction = bignumber_1.bigNumberify(fraction);
|
var fractionValue = bignumber_1.bigNumberify(fraction);
|
||||||
var wei = (whole.mul(unitInfo.tenPower)).add(fraction);
|
var wei = (wholeValue.mul(unitInfo.tenPower)).add(fractionValue);
|
||||||
if (negative) {
|
if (negative) {
|
||||||
wei = wei.mul(bignumber_1.ConstantNegativeOne);
|
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 {
|
export declare class HDNode {
|
||||||
private readonly keyPair;
|
private readonly keyPair;
|
||||||
readonly privateKey: string;
|
readonly privateKey: string;
|
||||||
@ -8,13 +9,13 @@ export declare class HDNode {
|
|||||||
readonly chainCode: string;
|
readonly chainCode: string;
|
||||||
readonly index: number;
|
readonly index: number;
|
||||||
readonly depth: 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;
|
private _derive;
|
||||||
derivePath(path: string): HDNode;
|
derivePath(path: string): HDNode;
|
||||||
}
|
}
|
||||||
export declare function fromMnemonic(mnemonic: 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 mnemonicToSeed(mnemonic: string, password?: string): string;
|
||||||
export declare function mnemonicToEntropy(mnemonic: 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;
|
export declare function isValidMnemonic(mnemonic: string): boolean;
|
||||||
|
@ -6,15 +6,11 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
result["default"] = mod;
|
result["default"] = mod;
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
||||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
||||||
};
|
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
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-0032.mediawiki
|
||||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
// See: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
|
||||||
var secp256k1 = __importStar(require("./secp256k1"));
|
var secp256k1_1 = require("./secp256k1");
|
||||||
var words_1 = __importDefault(require("./words"));
|
var words_1 = require("./words");
|
||||||
var wordlist = words_1.default.replace(/([A-Z])/g, ' $1').toLowerCase().substring(1).split(' ');
|
|
||||||
var convert_1 = require("../utils/convert");
|
var convert_1 = require("../utils/convert");
|
||||||
var bignumber_1 = require("../utils/bignumber");
|
var bignumber_1 = require("../utils/bignumber");
|
||||||
var utf8_1 = require("../utils/utf8");
|
var utf8_1 = require("../utils/utf8");
|
||||||
@ -38,8 +34,8 @@ var HDNode = /** @class */ (function () {
|
|||||||
function HDNode(keyPair, chainCode, index, depth, mnemonic, path) {
|
function HDNode(keyPair, chainCode, index, depth, mnemonic, path) {
|
||||||
errors.checkNew(this, HDNode);
|
errors.checkNew(this, HDNode);
|
||||||
this.keyPair = keyPair;
|
this.keyPair = keyPair;
|
||||||
this.privateKey = convert_1.hexlify(keyPair.priv.toArray('be', 32));
|
this.privateKey = keyPair.privateKey;
|
||||||
this.publicKey = '0x' + keyPair.getPublic(true, 'hex');
|
this.publicKey = keyPair.compressedPublicKey;
|
||||||
this.chainCode = convert_1.hexlify(chainCode);
|
this.chainCode = convert_1.hexlify(chainCode);
|
||||||
this.index = index;
|
this.index = index;
|
||||||
this.depth = depth;
|
this.depth = depth;
|
||||||
@ -71,7 +67,7 @@ var HDNode = /** @class */ (function () {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Data = ser_p(point(k_par))
|
// Data = ser_p(point(k_par))
|
||||||
data.set(this.keyPair.getPublic().encode(null, true));
|
data.set(this.keyPair.publicKeyBytes);
|
||||||
}
|
}
|
||||||
// Data += ser_32(i)
|
// Data += ser_32(i)
|
||||||
for (var i = 24; i >= 0; i -= 8) {
|
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 I = convert_1.arrayify(hmac_1.createSha512Hmac(this.chainCode).update(data).digest());
|
||||||
var IL = bignumber_1.bigNumberify(I.slice(0, 32));
|
var IL = bignumber_1.bigNumberify(I.slice(0, 32));
|
||||||
var IR = I.slice(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(secp256k1_1.N);
|
||||||
return new HDNode(secp256k1.curve.keyFromPrivate(convert_1.arrayify(ki)), IR, index, this.depth + 1, mnemonic, path);
|
return new HDNode(new secp256k1_1.KeyPair(convert_1.arrayify(ki)), IR, index, this.depth + 1, mnemonic, path);
|
||||||
};
|
};
|
||||||
HDNode.prototype.derivePath = function (path) {
|
HDNode.prototype.derivePath = function (path) {
|
||||||
var components = path.split('/');
|
var components = path.split('/');
|
||||||
@ -118,12 +114,12 @@ var HDNode = /** @class */ (function () {
|
|||||||
}());
|
}());
|
||||||
exports.HDNode = HDNode;
|
exports.HDNode = HDNode;
|
||||||
function _fromSeed(seed, mnemonic) {
|
function _fromSeed(seed, mnemonic) {
|
||||||
seed = convert_1.arrayify(seed);
|
var seedArray = convert_1.arrayify(seed);
|
||||||
if (seed.length < 16 || seed.length > 64) {
|
if (seedArray.length < 16 || seedArray.length > 64) {
|
||||||
throw new Error('invalid seed');
|
throw new Error('invalid seed');
|
||||||
}
|
}
|
||||||
var I = convert_1.arrayify(hmac_1.createSha512Hmac(MasterSecret).update(seed).digest());
|
var I = convert_1.arrayify(hmac_1.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 secp256k1_1.KeyPair(I.slice(0, 32)), I.slice(32), 0, 0, mnemonic, 'm');
|
||||||
}
|
}
|
||||||
function fromMnemonic(mnemonic) {
|
function fromMnemonic(mnemonic) {
|
||||||
// Check that the checksum s valid (will throw an error)
|
// 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 entropy = convert_1.arrayify(new Uint8Array(Math.ceil(11 * words.length / 8)));
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
for (var i = 0; i < words.length; i++) {
|
for (var i = 0; i < words.length; i++) {
|
||||||
var index = wordlist.indexOf(words[i]);
|
var index = words_1.getWordIndex(words[i]);
|
||||||
if (index === -1) {
|
if (index === -1) {
|
||||||
throw new Error('invalid mnemonic');
|
throw new Error('invalid mnemonic');
|
||||||
}
|
}
|
||||||
@ -189,21 +185,21 @@ function entropyToMnemonic(entropy) {
|
|||||||
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
|
if ((entropy.length % 4) !== 0 || entropy.length < 16 || entropy.length > 32) {
|
||||||
throw new Error('invalid entropy');
|
throw new Error('invalid entropy');
|
||||||
}
|
}
|
||||||
var words = [0];
|
var indices = [0];
|
||||||
var remainingBits = 11;
|
var remainingBits = 11;
|
||||||
for (var i = 0; i < entropy.length; i++) {
|
for (var i = 0; i < entropy.length; i++) {
|
||||||
// Consume the whole byte (with still more to go)
|
// Consume the whole byte (with still more to go)
|
||||||
if (remainingBits > 8) {
|
if (remainingBits > 8) {
|
||||||
words[words.length - 1] <<= 8;
|
indices[indices.length - 1] <<= 8;
|
||||||
words[words.length - 1] |= entropy[i];
|
indices[indices.length - 1] |= entropy[i];
|
||||||
remainingBits -= 8;
|
remainingBits -= 8;
|
||||||
// This byte will complete an 11-bit index
|
// This byte will complete an 11-bit index
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
words[words.length - 1] <<= remainingBits;
|
indices[indices.length - 1] <<= remainingBits;
|
||||||
words[words.length - 1] |= entropy[i] >> (8 - remainingBits);
|
indices[indices.length - 1] |= entropy[i] >> (8 - remainingBits);
|
||||||
// Start the next word
|
// Start the next word
|
||||||
words.push(entropy[i] & getLowerMask(8 - remainingBits));
|
indices.push(entropy[i] & getLowerMask(8 - remainingBits));
|
||||||
remainingBits += 3;
|
remainingBits += 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -212,14 +208,9 @@ function entropyToMnemonic(entropy) {
|
|||||||
var checksumBits = entropy.length / 4;
|
var checksumBits = entropy.length / 4;
|
||||||
checksum &= getUpperMask(checksumBits);
|
checksum &= getUpperMask(checksumBits);
|
||||||
// Shift the checksum into the word indices
|
// Shift the checksum into the word indices
|
||||||
words[words.length - 1] <<= checksumBits;
|
indices[indices.length - 1] <<= checksumBits;
|
||||||
words[words.length - 1] |= (checksum >> (8 - checksumBits));
|
indices[indices.length - 1] |= (checksum >> (8 - checksumBits));
|
||||||
// Convert indices into words
|
return indices.map(function (index) { return words_1.getWord(index); }).join(' ');
|
||||||
var result = [];
|
|
||||||
for (var i = 0; i < words.length; i++) {
|
|
||||||
result.push(wordlist[words[i]]);
|
|
||||||
}
|
|
||||||
return result.join(' ');
|
|
||||||
}
|
}
|
||||||
exports.entropyToMnemonic = entropyToMnemonic;
|
exports.entropyToMnemonic = entropyToMnemonic;
|
||||||
function isValidMnemonic(mnemonic) {
|
function isValidMnemonic(mnemonic) {
|
||||||
|
44
src/wallet/secp256k1.d.ts
vendored
44
src/wallet/secp256k1.d.ts
vendored
@ -1,31 +1,17 @@
|
|||||||
export interface BN {
|
import { Arrayish } from '../utils/convert';
|
||||||
toString(radix: number): string;
|
export declare type Signature = {
|
||||||
encode(encoding: string, compact: boolean): Uint8Array;
|
r: string;
|
||||||
toArray(endian: string, width: number): Uint8Array;
|
s: string;
|
||||||
}
|
|
||||||
export interface Signature {
|
|
||||||
r: BN;
|
|
||||||
s: BN;
|
|
||||||
recoveryParam: number;
|
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 {
|
export declare function recoverPublicKey(digest: Arrayish, signature: Signature): string;
|
||||||
sign(message: Uint8Array, options: {
|
export declare function computePublicKey(key: Arrayish, compressed?: boolean): string;
|
||||||
canonical?: boolean;
|
export declare const N: string;
|
||||||
}): 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;
|
|
||||||
|
@ -7,5 +7,62 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
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"));
|
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 isValidWallet(json: string): boolean;
|
||||||
export declare function decryptCrowdsale(json: string, password: Arrayish | string): SigningKey;
|
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 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 = {};
|
options = {};
|
||||||
}
|
}
|
||||||
// Check the private key
|
// Check the private key
|
||||||
|
var privateKeyBytes = null;
|
||||||
if (privateKey instanceof signing_key_1.SigningKey) {
|
if (privateKey instanceof signing_key_1.SigningKey) {
|
||||||
privateKey = privateKey.privateKey;
|
privateKeyBytes = convert_1.arrayify(privateKey.privateKey);
|
||||||
}
|
}
|
||||||
privateKey = convert_1.arrayify(privateKey);
|
else {
|
||||||
if (privateKey.length !== 32) {
|
privateKeyBytes = convert_1.arrayify(privateKey);
|
||||||
|
}
|
||||||
|
if (privateKeyBytes.length !== 32) {
|
||||||
throw new Error('invalid private key');
|
throw new Error('invalid private key');
|
||||||
}
|
}
|
||||||
password = getPassword(password);
|
password = getPassword(password);
|
||||||
@ -353,11 +356,11 @@ function encrypt(privateKey, password, options, progressCallback) {
|
|||||||
// This will be used to encrypt the mnemonic phrase (if any)
|
// This will be used to encrypt the mnemonic phrase (if any)
|
||||||
var mnemonicKey = key.slice(32, 64);
|
var mnemonicKey = key.slice(32, 64);
|
||||||
// Get the address for this private key
|
// 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
|
// Encrypt the private key
|
||||||
var counter = new aes.Counter(iv);
|
var counter = new aes.Counter(iv);
|
||||||
var aesCtr = new aes.ModeOfOperation.ctr(derivedKey, counter);
|
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
|
// Compute the message authentication code, used to check the password
|
||||||
var mac = keccak256_1.keccak256(convert_1.concat([macPrefix, ciphertext]));
|
var mac = keccak256_1.keccak256(convert_1.concat([macPrefix, ciphertext]));
|
||||||
// See: https://github.com/ethereum/wiki/wiki/Web3-Secret-Storage-Definition
|
// 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 {
|
export declare class SigningKey {
|
||||||
readonly privateKey: string;
|
readonly privateKey: string;
|
||||||
readonly publicKey: string;
|
readonly publicKey: string;
|
||||||
@ -5,13 +13,8 @@ export declare class SigningKey {
|
|||||||
readonly mnemonic: string;
|
readonly mnemonic: string;
|
||||||
readonly path: string;
|
readonly path: string;
|
||||||
private readonly keyPair;
|
private readonly keyPair;
|
||||||
constructor(privateKey: any);
|
constructor(privateKey: Arrayish | HDNode);
|
||||||
signDigest(digest: any): {
|
signDigest(digest: Arrayish): Signature;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
export declare function recoverAddress(digest: Arrayish, signature: Signature): string;
|
||||||
|
export declare function computeAddress(key: string): string;
|
||||||
|
@ -1,33 +1,31 @@
|
|||||||
'use strict';
|
'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 });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
/**
|
/**
|
||||||
* SigningKey
|
* SigningKey
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
var secp256k1 = __importStar(require("./secp256k1"));
|
var secp256k1_1 = require("./secp256k1");
|
||||||
var address_1 = require("../utils/address");
|
var address_1 = require("../utils/address");
|
||||||
var convert_1 = require("../utils/convert");
|
var convert_1 = require("../utils/convert");
|
||||||
|
var hdnode_1 = require("./hdnode");
|
||||||
var keccak256_1 = require("../utils/keccak256");
|
var keccak256_1 = require("../utils/keccak256");
|
||||||
|
var properties_1 = require("../utils/properties");
|
||||||
var errors = require("../utils/errors");
|
var errors = require("../utils/errors");
|
||||||
var SigningKey = /** @class */ (function () {
|
var SigningKey = /** @class */ (function () {
|
||||||
function SigningKey(privateKey) {
|
function SigningKey(privateKey) {
|
||||||
errors.checkNew(this, SigningKey);
|
errors.checkNew(this, SigningKey);
|
||||||
if (privateKey.privateKey) {
|
var privateKeyBytes = null;
|
||||||
this.mnemonic = privateKey.mnemonic;
|
if (privateKey instanceof hdnode_1.HDNode) {
|
||||||
this.path = privateKey.path;
|
properties_1.defineReadOnly(this, 'mnemonic', privateKey.mnemonic);
|
||||||
privateKey = privateKey.privateKey;
|
properties_1.defineReadOnly(this, 'path', privateKey.path);
|
||||||
|
privateKeyBytes = convert_1.arrayify(privateKey.privateKey);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
privateKeyBytes = convert_1.arrayify(privateKey);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
privateKey = convert_1.arrayify(privateKey);
|
if (privateKeyBytes.length !== 32) {
|
||||||
if (privateKey.length !== 32) {
|
|
||||||
errors.throwError('exactly 32 bytes required', errors.INVALID_ARGUMENT, { value: privateKey });
|
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);
|
errors.throwError('invalid private key', error.code, params);
|
||||||
}
|
}
|
||||||
this.privateKey = convert_1.hexlify(privateKey);
|
properties_1.defineReadOnly(this, 'privateKey', convert_1.hexlify(privateKeyBytes));
|
||||||
this.keyPair = secp256k1.curve.keyFromPrivate(privateKey);
|
properties_1.defineReadOnly(this, 'keyPair', new secp256k1_1.KeyPair(privateKeyBytes));
|
||||||
//utils.defineProperty(this, 'publicKey', '0x' + keyPair.getPublic(true, 'hex'))
|
properties_1.defineReadOnly(this, 'publicKey', this.keyPair.publicKey);
|
||||||
this.publicKey = '0x' + this.keyPair.getPublic(true, 'hex');
|
properties_1.defineReadOnly(this, 'address', computeAddress(this.keyPair.publicKey));
|
||||||
this.address = SigningKey.publicKeyToAddress('0x' + this.keyPair.getPublic(false, 'hex'));
|
|
||||||
}
|
}
|
||||||
SigningKey.prototype.signDigest = function (digest) {
|
SigningKey.prototype.signDigest = function (digest) {
|
||||||
var signature = this.keyPair.sign(convert_1.arrayify(digest), { canonical: true });
|
return this.keyPair.sign(digest);
|
||||||
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 SigningKey;
|
return SigningKey;
|
||||||
}());
|
}());
|
||||||
exports.SigningKey = 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 { HDNode } from './hdnode';
|
||||||
|
import { ProgressCallback } from './secret-storage';
|
||||||
import { SigningKey } from './signing-key';
|
import { SigningKey } from './signing-key';
|
||||||
|
import { BlockTag } from '../providers/provider';
|
||||||
|
import { BigNumber, BigNumberish } from '../utils/bignumber';
|
||||||
|
import { Arrayish } from '../utils/convert';
|
||||||
interface Provider {
|
interface Provider {
|
||||||
chainId: number;
|
chainId: number;
|
||||||
getBalance(address: string, blockTag: number | string): Promise<BigNumber>;
|
getBalance(address: string, blockTag: number | string): Promise<BigNumber>;
|
||||||
@ -43,19 +45,19 @@ export declare class Wallet {
|
|||||||
sign(transaction: TransactionRequest): string;
|
sign(transaction: TransactionRequest): string;
|
||||||
static parseTransaction(rawTransaction: Arrayish): TransactionRequest;
|
static parseTransaction(rawTransaction: Arrayish): TransactionRequest;
|
||||||
getAddress(): Promise<string>;
|
getAddress(): Promise<string>;
|
||||||
getBalance(blockTag: any): any;
|
getBalance(blockTag: BlockTag): Promise<BigNumber>;
|
||||||
getTransactionCount(blockTag: any): any;
|
getTransactionCount(blockTag: BlockTag): Promise<number>;
|
||||||
estimateGas(transaction: TransactionRequest): any;
|
estimateGas(transaction: TransactionRequest): Promise<BigNumber>;
|
||||||
sendTransaction(transaction: any): Promise<any>;
|
sendTransaction(transaction: any): Promise<TransactionResponse>;
|
||||||
send(addressOrName: any, amountWei: any, options: any): Promise<any>;
|
send(addressOrName: string, amountWei: BigNumberish, options: any): Promise<TransactionResponse>;
|
||||||
static hashMessage(message: any): string;
|
static hashMessage(message: Arrayish | string): string;
|
||||||
signMessage(message: any): string;
|
signMessage(message: Arrayish | string): string;
|
||||||
static verifyMessage(message: any, signature: any): string;
|
static verifyMessage(message: Arrayish | string, signature: string): string;
|
||||||
encrypt(password: any, options: any, progressCallback: any): Promise<{}>;
|
encrypt(password: Arrayish | string, options: any, progressCallback: ProgressCallback): Promise<string>;
|
||||||
static createRandom(options: any): Wallet;
|
static createRandom(options: any): Wallet;
|
||||||
static isEncryptedWallet(json: string): boolean;
|
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 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 {};
|
export {};
|
||||||
|
@ -11,6 +11,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|||||||
};
|
};
|
||||||
Object.defineProperty(exports, "__esModule", { value: true });
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
var scrypt_js_1 = __importDefault(require("scrypt-js"));
|
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 address_1 = require("../utils/address");
|
||||||
var bignumber_1 = require("../utils/bignumber");
|
var bignumber_1 = require("../utils/bignumber");
|
||||||
var convert_1 = require("../utils/convert");
|
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 RLP = __importStar(require("../utils/rlp"));
|
||||||
var utf8_1 = require("../utils/utf8");
|
var utf8_1 = require("../utils/utf8");
|
||||||
var errors = __importStar(require("../utils/errors"));
|
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
|
// This ensures we inject a setImmediate into the global space, which
|
||||||
// dramatically improves the performance of the scrypt PBKDF.
|
// dramatically improves the performance of the scrypt PBKDF.
|
||||||
console.log("Fix this! Setimmediate");
|
console.log("Fix this! Setimmediate");
|
||||||
@ -177,7 +177,7 @@ var Wallet = /** @class */ (function () {
|
|||||||
}
|
}
|
||||||
var digest = keccak256_1.keccak256(RLP.encode(raw));
|
var digest = keccak256_1.keccak256(RLP.encode(raw));
|
||||||
try {
|
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) {
|
catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
@ -310,7 +310,11 @@ var Wallet = /** @class */ (function () {
|
|||||||
if (recoveryParam < 0) {
|
if (recoveryParam < 0) {
|
||||||
throw new Error('invalid signature');
|
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) {
|
Wallet.prototype.encrypt = function (password, options, progressCallback) {
|
||||||
if (typeof (options) === 'function' && !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