├── .npmignore ├── src ├── constants.ts ├── index.ts ├── wallets │ └── lightwallet │ │ ├── index.ts │ │ ├── LightWalletUtils.ts │ │ ├── LightWalletSigner.ts │ │ ├── LightWallet.ts │ │ └── LightWalletManager.ts ├── types.ts └── Store.ts ├── dist ├── constants.d.ts ├── index.d.ts ├── constants.js ├── wallets │ └── lightwallet │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── LightWalletUtils.d.ts │ │ ├── LightWalletSigner.d.ts │ │ ├── LightWallet.d.ts │ │ ├── LightWalletManager.d.ts │ │ ├── LightWalletUtils.js │ │ ├── LightWallet.js │ │ ├── LightWalletSigner.js │ │ └── LightWalletManager.js ├── index.js ├── Store.d.ts ├── types.js ├── types.d.ts └── Store.js ├── .gitignore ├── tsconfig.test.json ├── tsconfig.json ├── tslint.json ├── .vscode └── launch.json ├── LICENSE.md ├── .circleci └── config.yml ├── package.json ├── test └── wallets │ └── lightwallet │ ├── LightWalletSigner.test.ts │ ├── LightWallet.test.ts │ └── LightWalletManager.test.ts ├── CONTRIBUTING.md ├── README.md └── yarn.lock /.npmignore: -------------------------------------------------------------------------------- 1 | tsconfig.json 2 | src -------------------------------------------------------------------------------- /src/constants.ts: -------------------------------------------------------------------------------- 1 | export const DEFAULT_DERIVATION_PATH = `m/44'/60'/0'/0`; 2 | -------------------------------------------------------------------------------- /dist/constants.d.ts: -------------------------------------------------------------------------------- 1 | export declare const DEFAULT_DERIVATION_PATH = "m/44'/60'/0'/0"; 2 | -------------------------------------------------------------------------------- /dist/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './wallets/lightwallet'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export * from './wallets/lightwallet'; 2 | export * from './types'; 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | doc* 4 | .npmrc 5 | dist/**/*.map 6 | dist-test 7 | dist-example/example 8 | dist-example/src -------------------------------------------------------------------------------- /dist/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.DEFAULT_DERIVATION_PATH = "m/44'/60'/0'/0"; 4 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/index.d.ts: -------------------------------------------------------------------------------- 1 | export * from './LightWalletManager'; 2 | export * from './LightWallet'; 3 | export * from './LightWalletSigner'; 4 | export * from './LightWalletUtils'; 5 | -------------------------------------------------------------------------------- /src/wallets/lightwallet/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LightWalletManager'; 2 | export * from './LightWallet'; 3 | export * from './LightWalletSigner'; 4 | export * from './LightWalletUtils'; 5 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "outDir": "dist-test" 6 | }, 7 | "include": [ 8 | "test/**/*" 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./wallets/lightwallet")); 7 | __export(require("./types")); 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "lib": ["es2015", "dom"], 6 | "declaration": true, 7 | "outDir": "dist" 8 | }, 9 | "include": [ 10 | "src/**/*", 11 | "./node_modules/web3-typescript-typings/index.d.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | function __export(m) { 3 | for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; 4 | } 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | __export(require("./LightWalletManager")); 7 | __export(require("./LightWallet")); 8 | __export(require("./LightWalletSigner")); 9 | __export(require("./LightWalletUtils")); 10 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-0xproject" 4 | ], 5 | "rules": { 6 | "no-console": false, 7 | "no-shadowed-variable": false, 8 | "trailing-comma": false, 9 | "align": false, 10 | "curly": [true, "ignore-same-line"], 11 | "no-namespace": false, 12 | "no-submodule-imports": false, 13 | "no-implicit-dependencies": false, 14 | "class-name": false 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "node", 6 | "request": "launch", 7 | "name": "Mocha Tests", 8 | "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha", 9 | "args": [ 10 | "-u", 11 | "tdd", 12 | "--timeout", 13 | "999999", 14 | "--colors", 15 | "dist-test/test/*.test.js", 16 | "${workspaceFolder}/test", 17 | "--require mock-local-storage", 18 | 19 | ], 20 | "internalConsoleOptions": "openOnSessionStart" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWalletUtils.d.ts: -------------------------------------------------------------------------------- 1 | import { keystore } from 'eth-lightwallet'; 2 | export declare class LightWalletUtils { 3 | /** 4 | * Derives a symmetric key from the plaintext password and salt 5 | * 6 | * @param {keystore} keystore The wallet's keystore instance 7 | * @param {string} password The plaintext password 8 | */ 9 | static deriveKeyFromPasswordAsync(keystore: keystore, password: string): Promise; 10 | /** 11 | * Validate the pwDerivedKey or throw an InvalidPassword exception 12 | * 13 | * @param {Uint8Array} pwDerivedKey The password derived symmetric key 14 | * @param {keystore} keystore The lightwallet keystore 15 | */ 16 | static validatePwDerivedKeyOrThrow(pwDerivedKey: Uint8Array, keystore: keystore): void; 17 | } 18 | -------------------------------------------------------------------------------- /dist/Store.d.ts: -------------------------------------------------------------------------------- 1 | import { Wallet } from './types'; 2 | export declare class Store { 3 | /** 4 | * Check for any storage support 5 | */ 6 | static isStorageSupported(): boolean; 7 | /** 8 | * Check if local storage is supported 9 | * 10 | */ 11 | static isLocalStorageSupported(): boolean; 12 | /** 13 | * Check if file storage is supported 14 | */ 15 | static isFileStorageSupported(): boolean; 16 | /** 17 | * Save the encrypted wallet in local storage 18 | * 19 | * @param {Wallet} wallet The wallet to save 20 | * @param {string} [keyName='s-wallet'] The key identifier 21 | */ 22 | static saveWallet(wallet: Wallet, keyName?: string): boolean; 23 | /** 24 | * Load the encrypted wallet from local storage 25 | * 26 | * @param {string} [keyName='s-wallet'] The key identifier 27 | */ 28 | static loadWallet(keyName?: string): any; 29 | } 30 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Radar Relay, Inc. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:8 6 | steps: 7 | - checkout 8 | # - run: 9 | # name: Install sonarscanner 10 | # command: 'sudo npm install -g sonarqube-scanner' 11 | # - run: 12 | # name: Ensure sonar-scanner installed 13 | # command: sonar-scanner --help || sleep 2 && sonar-scanner --help || sleep 2 && sonar-scanner --help 14 | - run: 15 | name: Install libusb 16 | command: sudo apt install libusb-1.0-0-dev 17 | - run: 18 | name: Install typescript 19 | command: 'sudo npm install -g typescript' 20 | - restore_cache: 21 | key: dependency-cache-{{ checksum "package.json" }} 22 | - run: 23 | name: Install dependencies 24 | command: yarn install 25 | - save_cache: 26 | key: dependency-cache-{{ checksum "package.json" }} 27 | paths: 28 | - node_modules 29 | - run: 30 | name: Test 31 | command: npm test 32 | # - run: 33 | # name: Push test results 34 | # command: './runSonarCloudAnalysis.sh' -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWalletSigner.d.ts: -------------------------------------------------------------------------------- 1 | import * as lightwallet from 'eth-lightwallet'; 2 | import { PartialTxParams, Signer } from '../../types'; 3 | declare type SigningType = typeof lightwallet.signing; 4 | export declare class LightWalletSigner implements Signer { 5 | private _keystore; 6 | private _signing; 7 | private _pwDerivedKey; 8 | constructor(keystore: lightwallet.keystore, signing: SigningType, pwDerivedKey: Uint8Array); 9 | /** 10 | * Sign a personal message hash 11 | * 12 | * @param {string} account The account to sign with 13 | * @param {string} hash The hash to sign 14 | */ 15 | signPersonalMessageHashAsync(account: string, hash: string): Promise; 16 | /** 17 | * Sign a personal message 18 | * 19 | * @param {string} account The account to sign with 20 | * @param {string} message The message to sign 21 | */ 22 | signPersonalMessageAsync(account: string, message: string): Promise; 23 | /** 24 | * Sign a transaction 25 | * 26 | * @param {PartialTxParams} txParams The transaction parameters 27 | */ 28 | signTransactionAsync(txParams: PartialTxParams): Promise; 29 | } 30 | export {}; 31 | -------------------------------------------------------------------------------- /src/wallets/lightwallet/LightWalletUtils.ts: -------------------------------------------------------------------------------- 1 | import { keystore } from 'eth-lightwallet'; 2 | import { WalletError } from '../../types'; 3 | 4 | export class LightWalletUtils { 5 | 6 | /** 7 | * Derives a symmetric key from the plaintext password and salt 8 | * 9 | * @param {keystore} keystore The wallet's keystore instance 10 | * @param {string} password The plaintext password 11 | */ 12 | public static async deriveKeyFromPasswordAsync(keystore: keystore, password: string): Promise { 13 | return new Promise(resolve => { 14 | keystore.keyFromPassword(password, (err, pwDerivedKey: Uint8Array) => { 15 | resolve(pwDerivedKey); 16 | }); 17 | }); 18 | } 19 | 20 | /** 21 | * Validate the pwDerivedKey or throw an InvalidPassword exception 22 | * 23 | * @param {Uint8Array} pwDerivedKey The password derived symmetric key 24 | * @param {keystore} keystore The lightwallet keystore 25 | */ 26 | public static validatePwDerivedKeyOrThrow(pwDerivedKey: Uint8Array, keystore: keystore): void { 27 | const valid = keystore.isDerivedKeyCorrect(pwDerivedKey); 28 | 29 | if (!valid) { 30 | throw new Error(WalletError.InvalidPassword); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@radarrelay/wallet-manager", 3 | "version": "0.3.3", 4 | "description": "A library that simplifies Ethereum wallet creation.", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "test": "tsc -p tsconfig.test.json && mocha --require mock-local-storage dist-test/**/*.test.js", 9 | "build": "tsc", 10 | "lint": "tslint -p tsconfig.json", 11 | "prepublishOnly": "npm test && npm run lint" 12 | }, 13 | "keywords": [ 14 | "ethereum", 15 | "wallet" 16 | ], 17 | "author": "Radar Relay ", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "@types/chai": "^4.0.4", 21 | "@types/lodash": "^4.14.109", 22 | "@types/mocha": "^2.2.43", 23 | "@types/node": "^8.0.46", 24 | "@types/eth-lightwallet": "3.0.0", 25 | "chai": "^3.5.0", 26 | "mocha": "^3.1.2", 27 | "tslint": "^5.8.0", 28 | "tslint-config-0xproject": "0.0.2", 29 | "typescript": "^2.5.3", 30 | "mock-local-storage": "^1.0.5" 31 | }, 32 | "dependencies": { 33 | "eth-lightwallet": "^3.0.1", 34 | "lodash": "^4.17.10" 35 | }, 36 | "directories": { 37 | "test": "test" 38 | }, 39 | "repository": { 40 | "type": "git", 41 | "url": "git+https://github.com/RadarRelay/wallet-manager.git" 42 | }, 43 | "bugs": { 44 | "url": "https://github.com/RadarRelay/wallet-manager/issues" 45 | }, 46 | "homepage": "https://github.com/RadarRelay/wallet-manager#readme" 47 | } 48 | -------------------------------------------------------------------------------- /dist/types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var WalletError; 4 | (function (WalletError) { 5 | WalletError["StorageDisabled"] = "STORAGE_DISABLED"; 6 | WalletError["NoWalletFound"] = "NO_WALLET_FOUND"; 7 | WalletError["InvalidSeed"] = "INVALID_SEED"; 8 | WalletError["InvalidPassword"] = "INVALID_PASSWORD"; 9 | })(WalletError = exports.WalletError || (exports.WalletError = {})); 10 | var SigningError; 11 | (function (SigningError) { 12 | SigningError["UserDeclined"] = "USER_DECLINED"; 13 | })(SigningError = exports.SigningError || (exports.SigningError = {})); 14 | var WalletType; 15 | (function (WalletType) { 16 | WalletType[WalletType["LightWallet"] = 0] = "LightWallet"; 17 | })(WalletType = exports.WalletType || (exports.WalletType = {})); 18 | var NonceSubproviderErrors; 19 | (function (NonceSubproviderErrors) { 20 | NonceSubproviderErrors["EmptyParametersFound"] = "EMPTY_PARAMETERS_FOUND"; 21 | NonceSubproviderErrors["CannotDetermineAddressFromPayload"] = "CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD"; 22 | })(NonceSubproviderErrors = exports.NonceSubproviderErrors || (exports.NonceSubproviderErrors = {})); 23 | var InfuraNetwork; 24 | (function (InfuraNetwork) { 25 | InfuraNetwork["Mainnet"] = "mainnet"; 26 | InfuraNetwork["Kovan"] = "kovan"; 27 | InfuraNetwork["Rinkeby"] = "rinkeby"; 28 | InfuraNetwork["Ropsten"] = "ropsten"; 29 | })(InfuraNetwork = exports.InfuraNetwork || (exports.InfuraNetwork = {})); 30 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWallet.d.ts: -------------------------------------------------------------------------------- 1 | import { LightWalletSigner } from './LightWalletSigner'; 2 | import { Wallet, WalletType } from '../../types'; 3 | import { keystore, signing } from 'eth-lightwallet'; 4 | declare type SigningType = typeof signing; 5 | export declare class LightWallet implements Wallet { 6 | type: WalletType; 7 | signer: LightWalletSigner; 8 | keystore: keystore; 9 | signing: SigningType; 10 | pwDerivedKey: Uint8Array; 11 | constructor(keystore: keystore, signing: SigningType, pwDerivedKey: Uint8Array); 12 | /** 13 | * Adds one or more accounts to the wallet 14 | * 15 | * @param {number} [numberOfAccounts=1] The number of accounts to add 16 | */ 17 | addNewAccounts(numberOfAccounts?: number): void; 18 | /** 19 | * Gets all the accounts from the wallet 20 | * 21 | */ 22 | getAccounts(): string[]; 23 | /** 24 | * Serialize the wallet keystore 25 | * 26 | */ 27 | serialize(): string; 28 | /** 29 | * Exports the wallet's seed phrase 30 | * 31 | * @param {string} password The plaintext password 32 | */ 33 | exportSeedPhraseAsync(password: string): Promise; 34 | /** 35 | * Exports the private key for a single account 36 | * 37 | * @param {string} account The account used for the export 38 | * @param {string} password The plaintext password 39 | */ 40 | exportAccountPrivateKeyAsync(account: string, password: string): Promise; 41 | } 42 | export {}; 43 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWalletManager.d.ts: -------------------------------------------------------------------------------- 1 | import { LightWalletOptions } from '../../types'; 2 | import { LightWallet } from './LightWallet'; 3 | export declare class LightWalletManager { 4 | /** 5 | * Creates a new lightwallet and saves it in local storage 6 | * 7 | * @param options LightWallet initialization options 8 | */ 9 | static createWalletAsync(options: LightWalletOptions): Promise; 10 | /** 11 | * Save the wallet 12 | * 13 | * @param {LightWallet} wallet The wallet instance 14 | */ 15 | static saveWallet(wallet: LightWallet, keyName?: string): void; 16 | /** 17 | * Loads a wallet from local storage 18 | * 19 | * @param {string} password The plaintext password 20 | */ 21 | static loadWalletAsync(password: string, keyName?: string): Promise; 22 | /** 23 | * Initializes a new eth-lightwallet keystore 24 | * 25 | * @param {LightWalletOptions} options LightWallet initialization options 26 | */ 27 | private static initializeKeystoreAsync; 28 | /** 29 | * Populate the missing wallet options 30 | * 31 | * @param {LightWalletOptions} options LightWallet initialization options 32 | */ 33 | private static populateMissingOptions; 34 | /** 35 | * Throw the appropriate exception on error 36 | * 37 | * @param {WalletError[]} errors An array of possible WalletErrors 38 | */ 39 | private static throwOnError; 40 | /** 41 | * Validate the seed or throw an InvalidSeed exception 42 | * 43 | * @param {string} seed The seed to validate 44 | */ 45 | private static validateSeedPhraseOrThrow; 46 | } 47 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | export interface LightWalletOptions { 2 | password: string; 3 | seedPhrase?: string; 4 | salt?: string; 5 | hdPathString?: string; 6 | storageKeyName?: string; 7 | } 8 | 9 | export interface ECSignatureBuffer { 10 | v: number; 11 | r: Buffer; 12 | s: Buffer; 13 | } 14 | 15 | export interface PartialTxParams { 16 | nonce: string; 17 | gasPrice?: string; 18 | gas: string; 19 | to: string; 20 | from?: string; 21 | value?: string; 22 | data?: string; 23 | chainId: number; // EIP 155 chainId - mainnet: 1, ropsten: 3 24 | } 25 | 26 | export interface Signer { 27 | signPersonalMessageAsync(account: string, message: string): Promise; 28 | signPersonalMessageHashAsync(account: string, hash: string): Promise; 29 | signTransactionAsync(txParams: PartialTxParams): Promise; 30 | } 31 | 32 | export interface Wallet { 33 | type: WalletType; 34 | signer: Signer; 35 | getAccounts(): string[]; 36 | serialize(): string; 37 | } 38 | 39 | export enum WalletError { 40 | StorageDisabled = 'STORAGE_DISABLED', 41 | NoWalletFound = 'NO_WALLET_FOUND', 42 | InvalidSeed = 'INVALID_SEED', 43 | InvalidPassword = 'INVALID_PASSWORD', 44 | } 45 | 46 | export enum SigningError { 47 | UserDeclined = 'USER_DECLINED' 48 | } 49 | 50 | export enum WalletType { 51 | LightWallet 52 | } 53 | 54 | export type ErrorCallback = (err: Error | null, data?: any) => void; 55 | export type Callback = () => void; 56 | export type OnNextCompleted = (err: Error | null, result: any, cb: Callback) => void; 57 | export type NextCallback = (callback?: OnNextCompleted) => void; 58 | 59 | export enum NonceSubproviderErrors { 60 | EmptyParametersFound = 'EMPTY_PARAMETERS_FOUND', 61 | CannotDetermineAddressFromPayload = 'CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD', 62 | } 63 | 64 | export enum InfuraNetwork { 65 | Mainnet = 'mainnet', 66 | Kovan = 'kovan', 67 | Rinkeby = 'rinkeby', 68 | Ropsten = 'ropsten', 69 | } 70 | -------------------------------------------------------------------------------- /dist/types.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | export interface LightWalletOptions { 3 | password: string; 4 | seedPhrase?: string; 5 | salt?: string; 6 | hdPathString?: string; 7 | storageKeyName?: string; 8 | } 9 | export interface ECSignatureBuffer { 10 | v: number; 11 | r: Buffer; 12 | s: Buffer; 13 | } 14 | export interface PartialTxParams { 15 | nonce: string; 16 | gasPrice?: string; 17 | gas: string; 18 | to: string; 19 | from?: string; 20 | value?: string; 21 | data?: string; 22 | chainId: number; 23 | } 24 | export interface Signer { 25 | signPersonalMessageAsync(account: string, message: string): Promise; 26 | signPersonalMessageHashAsync(account: string, hash: string): Promise; 27 | signTransactionAsync(txParams: PartialTxParams): Promise; 28 | } 29 | export interface Wallet { 30 | type: WalletType; 31 | signer: Signer; 32 | getAccounts(): string[]; 33 | serialize(): string; 34 | } 35 | export declare enum WalletError { 36 | StorageDisabled = "STORAGE_DISABLED", 37 | NoWalletFound = "NO_WALLET_FOUND", 38 | InvalidSeed = "INVALID_SEED", 39 | InvalidPassword = "INVALID_PASSWORD" 40 | } 41 | export declare enum SigningError { 42 | UserDeclined = "USER_DECLINED" 43 | } 44 | export declare enum WalletType { 45 | LightWallet = 0 46 | } 47 | export declare type ErrorCallback = (err: Error | null, data?: any) => void; 48 | export declare type Callback = () => void; 49 | export declare type OnNextCompleted = (err: Error | null, result: any, cb: Callback) => void; 50 | export declare type NextCallback = (callback?: OnNextCompleted) => void; 51 | export declare enum NonceSubproviderErrors { 52 | EmptyParametersFound = "EMPTY_PARAMETERS_FOUND", 53 | CannotDetermineAddressFromPayload = "CANNOT_DETERMINE_ADDRESS_FROM_PAYLOAD" 54 | } 55 | export declare enum InfuraNetwork { 56 | Mainnet = "mainnet", 57 | Kovan = "kovan", 58 | Rinkeby = "rinkeby", 59 | Ropsten = "ropsten" 60 | } 61 | -------------------------------------------------------------------------------- /test/wallets/lightwallet/LightWalletSigner.test.ts: -------------------------------------------------------------------------------- 1 | import * as chai from 'chai'; 2 | import { PartialTxParams } from '../../../src/types'; 3 | import { LightWalletManager, LightWalletSigner } from '../../../src/wallets/lightwallet'; 4 | 5 | const expect = chai.expect; 6 | 7 | /* tslint:disable:no-unused-expression */ 8 | describe('LightWalletSigner', () => { 9 | const seedPhrase = 'dilemma hollow outer pony cube season start stereo surprise when edit blast'; 10 | const salt = 'kvODghzs7Ff1uqHyI0P3wI4Hso4w4iWT2e9qmrWz0y4'; 11 | const password = 'supersecretpassword99'; 12 | const storageKeyName = 'lightwallet'; 13 | const account = '0x44be42fd88e22387c43ba9b75941aa3e680dae25'; 14 | let signer: LightWalletSigner; 15 | 16 | before(async () => { 17 | const options = { 18 | password, 19 | seedPhrase, 20 | salt, 21 | storageKeyName, 22 | hdPathString: `m/44'/60'/0'` 23 | }; 24 | signer = (await LightWalletManager.createWalletAsync(options)).signer; 25 | }); 26 | 27 | it('can sign a personal message', async () => { 28 | const message = 'hello world'; 29 | 30 | // Sign the message 31 | const ecSignatureHex = await signer.signPersonalMessageAsync(account, message); 32 | 33 | expect(ecSignatureHex).to.be.equal( 34 | // tslint:disable-next-line:max-line-length 35 | '0xa46b696c1aa8f91dbb33d1a66f6440bf3cf334c9dc45dc389668c1e60e2db31e259400b41f31632fa994837054c5345c88dc455c13931332489029adee6fd24d1b', 36 | ); 37 | }); 38 | 39 | it('can sign a transaction', async () => { 40 | const tx: PartialTxParams = { 41 | to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66', 42 | value: '0x00', 43 | gasPrice: '0x00', 44 | nonce: '0x00', 45 | gas: '0x00', 46 | from: account, 47 | chainId: 42 48 | }; 49 | 50 | // Sign the transaction 51 | const signedTx = await signer.signTransactionAsync(tx); 52 | 53 | expect(signedTx.length).to.be.equal(192); 54 | expect(signedTx.substr(0, 2)).to.be.equal('0x'); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /src/wallets/lightwallet/LightWalletSigner.ts: -------------------------------------------------------------------------------- 1 | import * as EthereumTx from 'ethereumjs-tx'; 2 | import * as lightwallet from 'eth-lightwallet'; 3 | import { ECSignatureBuffer, PartialTxParams, Signer } from '../../types'; 4 | 5 | type SigningType = typeof lightwallet.signing; 6 | 7 | export class LightWalletSigner implements Signer { 8 | private _keystore: any; 9 | private _signing: any; 10 | private _pwDerivedKey: Uint8Array; 11 | 12 | constructor(keystore: lightwallet.keystore, signing: SigningType, pwDerivedKey: Uint8Array) { 13 | this._keystore = keystore; 14 | this._signing = signing; 15 | this._pwDerivedKey = pwDerivedKey; 16 | } 17 | 18 | /** 19 | * Sign a personal message hash 20 | * 21 | * @param {string} account The account to sign with 22 | * @param {string} hash The hash to sign 23 | */ 24 | public async signPersonalMessageHashAsync(account: string, hash: string): Promise { 25 | try { 26 | const result: ECSignatureBuffer = await this._signing.signMsgHash( 27 | this._keystore, this._pwDerivedKey, hash, account, this._keystore.hdPathString); 28 | 29 | const signature = this._signing.concatSig(result); 30 | 31 | return signature; 32 | } catch (err) { 33 | throw err; 34 | } 35 | } 36 | 37 | /** 38 | * Sign a personal message 39 | * 40 | * @param {string} account The account to sign with 41 | * @param {string} message The message to sign 42 | */ 43 | public async signPersonalMessageAsync(account: string, message: string): Promise { 44 | try { 45 | const result: ECSignatureBuffer = await this._signing.signMsg( 46 | this._keystore, this._pwDerivedKey, message, account, this._keystore.hdPathString); 47 | 48 | const signature = this._signing.concatSig(result); 49 | 50 | return signature; 51 | } catch (err) { 52 | throw err; 53 | } 54 | } 55 | 56 | /** 57 | * Sign a transaction 58 | * 59 | * @param {PartialTxParams} txParams The transaction parameters 60 | */ 61 | public async signTransactionAsync(txParams: PartialTxParams): Promise { 62 | try { 63 | const tx = new EthereumTx(txParams); 64 | const txHex = tx.serialize().toString('hex'); 65 | let signedTxHex: string = this._signing.signTx( 66 | this._keystore, this._pwDerivedKey, txHex, txParams.from, this._keystore.hdPathString); 67 | 68 | signedTxHex = `0x${signedTxHex}`; 69 | 70 | return signedTxHex; 71 | } catch (err) { 72 | throw err; 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/Store.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import { Wallet, WalletError } from './types'; 3 | 4 | export class Store { 5 | 6 | /** 7 | * Check for any storage support 8 | */ 9 | public static isStorageSupported(): boolean { 10 | return Store.isFileStorageSupported() || Store.isLocalStorageSupported(); 11 | } 12 | 13 | /** 14 | * Check if local storage is supported 15 | * 16 | */ 17 | public static isLocalStorageSupported(): boolean { 18 | if (typeof localStorage === 'undefined') { 19 | return false; 20 | } 21 | const lsSupportTest = 'lsSupportTest'; 22 | 23 | try { 24 | localStorage.setItem(lsSupportTest, lsSupportTest); 25 | localStorage.removeItem(lsSupportTest); 26 | return true; 27 | } catch (err) { 28 | return false; 29 | } 30 | } 31 | 32 | /** 33 | * Check if file storage is supported 34 | */ 35 | public static isFileStorageSupported(): boolean { 36 | if (typeof fs.writeFileSync === 'undefined') return false; 37 | 38 | try { 39 | fs.writeFileSync('.fsSupportTest', 'test'); 40 | fs.unlinkSync('.fsSupportTest'); 41 | return true; 42 | } catch (err) { 43 | return false; 44 | } 45 | } 46 | 47 | /** 48 | * Save the encrypted wallet in local storage 49 | * 50 | * @param {Wallet} wallet The wallet to save 51 | * @param {string} [keyName='s-wallet'] The key identifier 52 | */ 53 | public static saveWallet(wallet: Wallet, keyName: string = 's-wallet') { 54 | if (Store.isLocalStorageSupported()) { 55 | localStorage.setItem(keyName, wallet.serialize()); 56 | } else if (Store.isFileStorageSupported) { 57 | fs.writeFileSync('.' + keyName, wallet.serialize()); 58 | } else { 59 | return false; 60 | } 61 | 62 | return true; 63 | } 64 | 65 | /** 66 | * Load the encrypted wallet from local storage 67 | * 68 | * @param {string} [keyName='s-wallet'] The key identifier 69 | */ 70 | public static loadWallet(keyName: string = 's-wallet') { 71 | let serializedKeystore = null; 72 | if (Store.isLocalStorageSupported()) { 73 | serializedKeystore = localStorage.getItem(keyName); 74 | } else if (Store.isFileStorageSupported()) { 75 | try { 76 | serializedKeystore = fs.readFileSync('.' + keyName).toString(); 77 | } catch (err) { 78 | throw new Error(WalletError.NoWalletFound); 79 | } 80 | } 81 | 82 | if (!serializedKeystore) { 83 | throw new Error(WalletError.NoWalletFound); 84 | } 85 | 86 | return serializedKeystore; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /test/wallets/lightwallet/LightWallet.test.ts: -------------------------------------------------------------------------------- 1 | import * as chai from 'chai'; 2 | import { LightWallet, LightWalletManager } from '../../../src/wallets/lightwallet'; 3 | 4 | const expect = chai.expect; 5 | 6 | /* tslint:disable:no-unused-expression */ 7 | describe('LightWallet', () => { 8 | const password = 'supersecretpassword99'; 9 | const storageKeyName = 'lightwallet'; 10 | let lightWallet: LightWallet; 11 | 12 | beforeEach(async () => { 13 | lightWallet = await LightWalletManager.createWalletAsync({ password, storageKeyName }); 14 | }); 15 | 16 | it('can add a single account', async () => { 17 | const preAddCount = lightWallet.getAccounts().length; 18 | 19 | // Add a new account 20 | lightWallet.addNewAccounts(1); 21 | 22 | const numberOfAccountsAdded = lightWallet.getAccounts().length - preAddCount; 23 | 24 | // One account should have been added 25 | expect(numberOfAccountsAdded).to.equal(1); 26 | }); 27 | 28 | it('can add a multiple accounts', async () => { 29 | const preAddCount = lightWallet.getAccounts().length; 30 | 31 | // Add a new account 32 | lightWallet.addNewAccounts(3); 33 | 34 | const numberOfAccountsAdded = lightWallet.getAccounts().length - preAddCount; 35 | 36 | // Three accounts should have been added 37 | expect(numberOfAccountsAdded).to.equal(3); 38 | }); 39 | 40 | it('can export the private key of an account', async () => { 41 | // Export the private key of the first account 42 | const firstAccount = lightWallet.getAccounts()[0]; 43 | const privateKey = await lightWallet.exportAccountPrivateKeyAsync(firstAccount, password); 44 | 45 | // Private key should be 64 chars long 46 | expect(privateKey.length).to.equal(64); 47 | }); 48 | 49 | it('can export the seed phrase', async () => { 50 | // Export the seed phrase 51 | const seedPhrase = await lightWallet.exportSeedPhraseAsync(password); 52 | 53 | // Seed phrase should be 12 words 54 | expect(seedPhrase.split(' ').length).to.equal(12); 55 | }); 56 | 57 | it('can get all accounts', async () => { 58 | // Add new accounts 59 | lightWallet.addNewAccounts(10); 60 | 61 | // Get all accounts 62 | const accounts = lightWallet.getAccounts(); 63 | 64 | // There should be 11 accounts (Initial + 10 added) 65 | expect(accounts.length).to.equal(11); 66 | }); 67 | 68 | it('can serialize the wallet', async () => { 69 | // Serialize the wallet 70 | const serializedWallet = lightWallet.serialize(); 71 | 72 | // Serialized wallet should be a string 73 | expect(typeof serializedWallet).to.equal('string'); 74 | }); 75 | }); 76 | -------------------------------------------------------------------------------- /src/wallets/lightwallet/LightWallet.ts: -------------------------------------------------------------------------------- 1 | import { LightWalletSigner } from './LightWalletSigner'; 2 | import { Wallet, WalletType } from '../../types'; 3 | import { keystore, signing } from 'eth-lightwallet'; 4 | import { Store } from '../../Store'; 5 | import { LightWalletUtils } from './LightWalletUtils'; 6 | 7 | type SigningType = typeof signing; 8 | 9 | export class LightWallet implements Wallet { 10 | public type: WalletType; 11 | public signer: LightWalletSigner; 12 | public keystore: keystore; 13 | public signing: SigningType; 14 | public pwDerivedKey: Uint8Array; 15 | 16 | constructor(keystore: keystore, signing: SigningType, pwDerivedKey: Uint8Array) { 17 | this.keystore = keystore; 18 | this.signing = signing; 19 | this.pwDerivedKey = pwDerivedKey; 20 | this.type = WalletType.LightWallet; 21 | this.signer = new LightWalletSigner(keystore, signing, pwDerivedKey); 22 | } 23 | 24 | /** 25 | * Adds one or more accounts to the wallet 26 | * 27 | * @param {number} [numberOfAccounts=1] The number of accounts to add 28 | */ 29 | public addNewAccounts(numberOfAccounts: number = 1): void { 30 | this.keystore.generateNewAddress(this.pwDerivedKey, numberOfAccounts); 31 | Store.saveWallet(this); 32 | } 33 | 34 | /** 35 | * Gets all the accounts from the wallet 36 | * 37 | */ 38 | public getAccounts(): string[] { 39 | const accounts = this.keystore.getAddresses(); 40 | return accounts; 41 | } 42 | 43 | /** 44 | * Serialize the wallet keystore 45 | * 46 | */ 47 | public serialize(): string { 48 | return this.keystore.serialize(); 49 | } 50 | 51 | /** 52 | * Exports the wallet's seed phrase 53 | * 54 | * @param {string} password The plaintext password 55 | */ 56 | public async exportSeedPhraseAsync(password: string): Promise { 57 | const pwDerivedKey: Uint8Array = await LightWalletUtils.deriveKeyFromPasswordAsync(this.keystore, password); 58 | LightWalletUtils.validatePwDerivedKeyOrThrow(pwDerivedKey, this.keystore); 59 | 60 | return this.keystore.getSeed(pwDerivedKey); 61 | } 62 | 63 | /** 64 | * Exports the private key for a single account 65 | * 66 | * @param {string} account The account used for the export 67 | * @param {string} password The plaintext password 68 | */ 69 | public async exportAccountPrivateKeyAsync(account: string, password: string): Promise { 70 | const pwDerivedKey: Uint8Array = await LightWalletUtils.deriveKeyFromPasswordAsync(this.keystore, password); 71 | LightWalletUtils.validatePwDerivedKeyOrThrow(pwDerivedKey, this.keystore); 72 | 73 | return this.keystore.exportPrivateKey(account, pwDerivedKey); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /dist/Store.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | var fs = require("fs"); 4 | var types_1 = require("./types"); 5 | var Store = /** @class */ (function () { 6 | function Store() { 7 | } 8 | /** 9 | * Check for any storage support 10 | */ 11 | Store.isStorageSupported = function () { 12 | return Store.isFileStorageSupported() || Store.isLocalStorageSupported(); 13 | }; 14 | /** 15 | * Check if local storage is supported 16 | * 17 | */ 18 | Store.isLocalStorageSupported = function () { 19 | if (typeof localStorage === 'undefined') { 20 | return false; 21 | } 22 | var lsSupportTest = 'lsSupportTest'; 23 | try { 24 | localStorage.setItem(lsSupportTest, lsSupportTest); 25 | localStorage.removeItem(lsSupportTest); 26 | return true; 27 | } 28 | catch (err) { 29 | return false; 30 | } 31 | }; 32 | /** 33 | * Check if file storage is supported 34 | */ 35 | Store.isFileStorageSupported = function () { 36 | if (typeof fs.writeFileSync === 'undefined') 37 | return false; 38 | try { 39 | fs.writeFileSync('.fsSupportTest', 'test'); 40 | fs.unlinkSync('.fsSupportTest'); 41 | return true; 42 | } 43 | catch (err) { 44 | return false; 45 | } 46 | }; 47 | /** 48 | * Save the encrypted wallet in local storage 49 | * 50 | * @param {Wallet} wallet The wallet to save 51 | * @param {string} [keyName='s-wallet'] The key identifier 52 | */ 53 | Store.saveWallet = function (wallet, keyName) { 54 | if (keyName === void 0) { keyName = 's-wallet'; } 55 | if (Store.isLocalStorageSupported()) { 56 | localStorage.setItem(keyName, wallet.serialize()); 57 | } 58 | else if (Store.isFileStorageSupported) { 59 | fs.writeFileSync('.' + keyName, wallet.serialize()); 60 | } 61 | else { 62 | return false; 63 | } 64 | return true; 65 | }; 66 | /** 67 | * Load the encrypted wallet from local storage 68 | * 69 | * @param {string} [keyName='s-wallet'] The key identifier 70 | */ 71 | Store.loadWallet = function (keyName) { 72 | if (keyName === void 0) { keyName = 's-wallet'; } 73 | var serializedKeystore = null; 74 | if (Store.isLocalStorageSupported()) { 75 | serializedKeystore = localStorage.getItem(keyName); 76 | } 77 | else if (Store.isFileStorageSupported()) { 78 | try { 79 | serializedKeystore = fs.readFileSync('.' + keyName).toString(); 80 | } 81 | catch (err) { 82 | throw new Error(types_1.WalletError.NoWalletFound); 83 | } 84 | } 85 | if (!serializedKeystore) { 86 | throw new Error(types_1.WalletError.NoWalletFound); 87 | } 88 | return serializedKeystore; 89 | }; 90 | return Store; 91 | }()); 92 | exports.Store = Store; 93 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Radar Contribution Guide 2 | 3 | Thank you for your interest in contributing to Radar! We welcome contributions from anyone on the internet, and are grateful for even the smallest of fixes! 4 | 5 | ### How to contribute 6 | 7 | If you'd like to contribute, please fork the repo, fix, commit and send a pull request against the `beta` branch for the maintainers to review and merge into the main code base. If you wish to submit more complex changes, please check with a core dev first on [Radar Relay Slack](https://radarrelay.slack.com/) in the #dev channel to ensure those changes are in-line with the general philosophy of the project and/or to get some early feedback which can make both your efforts easier as well as our review and merge procedures quick and simple. 8 | 9 | We encourage a “PR early” approach so create the PR as early as possible even without the fix/feature ready, so that devs and other contributors know you have picked up the issue. These early PRs should indicate an 'in progress' status by adding the 'WIP' label to the PR. Please make sure your contributions adhere to our coding guidelines: 10 | 11 | * Pull requests adding features or refactoring should be opened against the `beta` branch 12 | * Pull requests fixing bugs in the latest release version should be opened against the `master` branch 13 | * Write [good commit messages](https://chris.beams.io/posts/git-commit/) 14 | 15 | ### Code quality 16 | 17 | Because our repositories are used by automated traders and other projects in production, we strive for exceptional code quality. Please follow the existing code standards and conventions – `tslint`. 18 | 19 | If you're adding functionality, please also add tests and make sure they pass. We have an automatic coverage reporting tool, so we'll see it if they are missing ;) 20 | If you're adding a new public function/member, make sure you document it with Java doc-style comments. We use typedoc to generate documentation from the comments within our source code. 21 | 22 | ### Styleguide 23 | 24 | We use [TSLint](https://palantir.github.io/tslint/) with [custom configs](https://github.com/0xProject/0x-monorepo/tree/development/packages/tslint-config) to keep our code style consistent. 25 | 26 | To lint your code just run: `yarn lint` 27 | 28 | If using the Atom text editor, we recommend you install the following packages: 29 | 30 | * [atom-typescript](https://atom.io/packages/atom-typescript) 31 | * [linter-tslint](https://atom.io/packages/linter-tslint) 32 | 33 | ### Branch structure & versioning 34 | 35 | We use [semantic versioning](http://semver.org/), but before a package reaches v1.0.0 all breaking changes as well as new features will be minor version bumps. 36 | 37 | We have two main branches: `master` and `beta`. 38 | 39 | `master` represents the most recent released (published on npm) version. 40 | 41 | `beta` represents the development state and is a default branch to which you will submit a PR. We use this structure so that we can push hotfixes to the currently released version without needing to publish all the changes made towards the next release. If a hotfix is implemented on `master`, it is back-ported to `beta`. -------------------------------------------------------------------------------- /test/wallets/lightwallet/LightWalletManager.test.ts: -------------------------------------------------------------------------------- 1 | import * as chai from 'chai'; 2 | import * as fs from 'fs'; 3 | import { Store } from '../../../src/Store'; 4 | import { WalletError } from '../../../src/types'; 5 | import { LightWalletManager } from '../../../src/wallets/lightwallet'; 6 | 7 | const expect = chai.expect; 8 | 9 | /* tslint:disable:no-unused-expression */ 10 | describe('LightWalletManager', () => { 11 | const password = 'supersecretpassword99'; 12 | const storageKeyName = 'lightwallet'; 13 | 14 | it('can create a new lightwallet', async () => { 15 | const lightWallet = await LightWalletManager.createWalletAsync({ password, storageKeyName }); 16 | 17 | // Export the seed phrase 18 | const seedPhrase = await lightWallet.exportSeedPhraseAsync(password); 19 | 20 | // Get Wallet Accounts 21 | const accounts = lightWallet.getAccounts(); 22 | 23 | // Seed phrase should be 12 words 24 | expect(seedPhrase.split(' ').length).to.equal(12); 25 | 26 | // Wallet should contain 1 account 27 | expect(accounts.length).to.equal(1); 28 | }); 29 | 30 | it('can save and load the wallet from local storage or filesystem', async () => { 31 | let lightWallet = await LightWalletManager.createWalletAsync({ password, storageKeyName }); 32 | 33 | // Remove the wallet from memory 34 | lightWallet = null; 35 | 36 | // Reload the wallet from local storage 37 | lightWallet = await LightWalletManager.loadWalletAsync(password, storageKeyName); 38 | 39 | // Export the seed phrase 40 | const seedPhrase = await lightWallet.exportSeedPhraseAsync(password); 41 | 42 | // Get Wallet Accounts 43 | const accounts = lightWallet.getAccounts(); 44 | 45 | // Seed phrase should be 12 words 46 | expect(seedPhrase.split(' ').length).to.equal(12); 47 | 48 | // Wallet should contain 1 account 49 | expect(accounts.length).to.equal(1); 50 | }); 51 | 52 | it('throws the correct exception when the supplied password is incorrect', async () => { 53 | const incorrectPassword = 'thewrongpassword99'; 54 | 55 | let errorMessage; 56 | try { 57 | // Attempt to load the wallet with an incorrect password 58 | const lightWallet = await LightWalletManager.loadWalletAsync(incorrectPassword, storageKeyName); 59 | } catch (err) { 60 | errorMessage = err.message; 61 | } 62 | 63 | expect(errorMessage).to.equal(WalletError.InvalidPassword); 64 | }); 65 | 66 | it('throws the correct exception when no wallet is found', async () => { 67 | 68 | // Remove from local storage 69 | if (Store.isLocalStorageSupported) { 70 | localStorage.removeItem(storageKeyName); 71 | } else { 72 | await new Promise(resolve => { 73 | fs.unlink('.' + storageKeyName, () => { 74 | resolve(); 75 | }); 76 | }); 77 | } 78 | 79 | let errorMessage; 80 | try { 81 | // Attempt to retrieve a wallet that doesn't exist 82 | await LightWalletManager.loadWalletAsync(password, storageKeyName); 83 | } catch (err) { 84 | errorMessage = err.message; 85 | } 86 | 87 | expect(errorMessage).to.equal(WalletError.NoWalletFound); 88 | }); 89 | }); 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wallet-manager 2 | 3 | A library that simplifies Ethereum wallet creation. 4 | 5 | [![npm version](https://badge.fury.io/js/%40radarrelay%2Fwallet-manager.svg)](https://badge.fury.io/js/%40radarrelay%2Fwallet-manager) 6 | [![CircleCI](https://circleci.com/gh/RadarRelay/wallet-manager.svg?style=svg&circle-token=e3f03fa489fe09a00eadb9ec96c617c4f999e58d)](https://circleci.com/gh/RadarRelay/wallet-manager) 7 | 8 | ## Installation 9 | 10 | ### npm 11 | 12 | ``` 13 | npm install @radarrelay/wallet-manager 14 | ``` 15 | 16 | ### Yarn 17 | 18 | ``` 19 | yarn add @radarrelay/wallet-manager 20 | ``` 21 | 22 | ## LightWallet Usage 23 | 24 | ### Import 25 | 26 | ```javascript 27 | import { LightWalletManager } from '@radarrelay/wallet-manager'; 28 | ``` 29 | 30 | ### LightWalletManager Methods 31 | 32 | **Create a new wallet** 33 | 34 | Create a new lightwallet and save it into local storage or as a file. 35 | 36 | Options: 37 | 38 | * **password** (mandatory) A string used to encrypt the vault when serialized. 39 | * **seedPhrase** (optional) A twelve-word mnemonic used to generate all accounts. Randomly generated if not supplied. 40 | * **salt** (optional) The salt used to encrypt & decrypt the vault. Randomly generated if not supplied. 41 | * **hdPathString** (optional) A BIP39 compliant HD Path String. Defaults to `m/44'/60'/0'/0`. 42 | * **storageKeyName** (optional) The local storage key or file name. 43 | 44 | ```javascript 45 | const lightWallet = await LightWalletManager.createWalletAsync(options: LightWalletOptions): Promise 46 | ``` 47 | 48 | **Save an existing wallet** 49 | 50 | Save the encrypted lightwallet into local storage or as a file. 51 | 52 | ```javascript 53 | LightWalletManager.saveWallet(wallet: LightWallet): void 54 | ``` 55 | 56 | **Load an existing wallet** 57 | 58 | Load the lightwallet from local storage or the file system. 59 | 60 | ```javascript 61 | const lightWallet = await LightWalletManager.loadWalletAsync(password: string): Promise 62 | ``` 63 | 64 | 65 | ### LightWallet Methods 66 | 67 | **Add new accounts** 68 | 69 | Adds 1 or more accounts to the lightwallet instance and saves the updated wallet. 70 | 71 | ```javascript 72 | lightWallet.addNewAccounts(numberOfAccounts: number = 1): void 73 | ``` 74 | 75 | **Export private key** 76 | 77 | Exports the private key for a single account. 78 | 79 | ```javascript 80 | const privateKey = lightWallet.exportAccountPrivateKeyAsync(account: string, password: string): Promise 81 | ``` 82 | 83 | **Export seed phrase** 84 | 85 | Exports the wallet's seed phrase. 86 | 87 | ```javascript 88 | const seedPhrase = await lightWallet.exportSeedPhraseAsync(password: string): Promise 89 | ``` 90 | 91 | **Get accounts** 92 | 93 | Gets all the accounts from the wallet. 94 | 95 | ```javascript 96 | const accounts = lightWallet.getAccounts(): string[] 97 | ``` 98 | 99 | **Serialize** 100 | 101 | Serialize the encrypted lightwallet. 102 | 103 | ```javascript 104 | const serializedWallet = lightWallet.serialize(): string 105 | ``` 106 | 107 | ### Signer Methods 108 | 109 | **Sign a message** 110 | 111 | ```javascript 112 | const signedMsg = await lightWallet.signer.signPersonalMessageAsync(account: string, message: string): Promise 113 | ``` 114 | 115 | **Sign a message hash** 116 | 117 | ```javascript 118 | const signedMsgHash = await lightWallet.signer.signPersonalMessageHashAsync(account: string, messageHash: string): Promise 119 | ``` 120 | 121 | **Sign a transaction** 122 | 123 | ```javascript 124 | const signedTx = await lightWallet.signer.signTransactionAsync(txParams: PartialTxParams): Promise 125 | ``` 126 | 127 | ## Contributing 128 | 129 | Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. 130 | 131 | ## License 132 | 133 | This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details. 134 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWalletUtils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [0, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | Object.defineProperty(exports, "__esModule", { value: true }); 38 | var types_1 = require("../../types"); 39 | var LightWalletUtils = /** @class */ (function () { 40 | function LightWalletUtils() { 41 | } 42 | /** 43 | * Derives a symmetric key from the plaintext password and salt 44 | * 45 | * @param {keystore} keystore The wallet's keystore instance 46 | * @param {string} password The plaintext password 47 | */ 48 | LightWalletUtils.deriveKeyFromPasswordAsync = function (keystore, password) { 49 | return __awaiter(this, void 0, void 0, function () { 50 | return __generator(this, function (_a) { 51 | return [2 /*return*/, new Promise(function (resolve) { 52 | keystore.keyFromPassword(password, function (err, pwDerivedKey) { 53 | resolve(pwDerivedKey); 54 | }); 55 | })]; 56 | }); 57 | }); 58 | }; 59 | /** 60 | * Validate the pwDerivedKey or throw an InvalidPassword exception 61 | * 62 | * @param {Uint8Array} pwDerivedKey The password derived symmetric key 63 | * @param {keystore} keystore The lightwallet keystore 64 | */ 65 | LightWalletUtils.validatePwDerivedKeyOrThrow = function (pwDerivedKey, keystore) { 66 | var valid = keystore.isDerivedKeyCorrect(pwDerivedKey); 67 | if (!valid) { 68 | throw new Error(types_1.WalletError.InvalidPassword); 69 | } 70 | }; 71 | return LightWalletUtils; 72 | }()); 73 | exports.LightWalletUtils = LightWalletUtils; 74 | -------------------------------------------------------------------------------- /src/wallets/lightwallet/LightWalletManager.ts: -------------------------------------------------------------------------------- 1 | import * as lightwallet from 'eth-lightwallet'; 2 | import * as _ from 'lodash'; 3 | import { Store } from '../../Store'; 4 | import { LightWalletOptions, WalletError } from '../../types'; 5 | import { DEFAULT_DERIVATION_PATH } from '../../constants'; 6 | import { LightWallet } from './LightWallet'; 7 | import { LightWalletUtils } from './LightWalletUtils'; 8 | 9 | export class LightWalletManager { 10 | 11 | /** 12 | * Creates a new lightwallet and saves it in local storage 13 | * 14 | * @param options LightWallet initialization options 15 | */ 16 | public static async createWalletAsync(options: LightWalletOptions): Promise { 17 | const filledOptions = this.populateMissingOptions(options); 18 | 19 | this.throwOnError(WalletError.StorageDisabled); 20 | this.validateSeedPhraseOrThrow(options.seedPhrase); 21 | 22 | const keystore: lightwallet.keystore = await this.initializeKeystoreAsync(filledOptions); 23 | const pwDerivedKey: Uint8Array = await LightWalletUtils.deriveKeyFromPasswordAsync(keystore, options.password); 24 | 25 | keystore.generateNewAddress(pwDerivedKey, 1); 26 | 27 | const lightWallet = new LightWallet(keystore, lightwallet.signing, pwDerivedKey); 28 | Store.saveWallet(lightWallet, options.storageKeyName); 29 | return lightWallet; 30 | } 31 | 32 | /** 33 | * Save the wallet 34 | * 35 | * @param {LightWallet} wallet The wallet instance 36 | */ 37 | public static saveWallet(wallet: LightWallet, keyName?: string): void { 38 | if (wallet) Store.saveWallet(wallet, keyName); 39 | } 40 | 41 | /** 42 | * Loads a wallet from local storage 43 | * 44 | * @param {string} password The plaintext password 45 | */ 46 | public static async loadWalletAsync(password: string, keyName?: string): Promise { 47 | const serializedKeystore = Store.loadWallet(keyName); 48 | const keystore = lightwallet.keystore.deserialize(serializedKeystore); 49 | const pwDerivedKey: Uint8Array = await LightWalletUtils.deriveKeyFromPasswordAsync(keystore, password); 50 | LightWalletUtils.validatePwDerivedKeyOrThrow(pwDerivedKey, keystore); 51 | 52 | return new LightWallet(keystore, lightwallet.signing, pwDerivedKey); 53 | } 54 | 55 | /** 56 | * Initializes a new eth-lightwallet keystore 57 | * 58 | * @param {LightWalletOptions} options LightWallet initialization options 59 | */ 60 | private static async initializeKeystoreAsync(options: LightWalletOptions): Promise { 61 | return new Promise(resolve => { 62 | // Create LightWallet 63 | lightwallet.keystore.createVault(options, (err, keystore) => { 64 | resolve(keystore); 65 | }); 66 | }); 67 | } 68 | 69 | /** 70 | * Populate the missing wallet options 71 | * 72 | * @param {LightWalletOptions} options LightWallet initialization options 73 | */ 74 | private static populateMissingOptions(options: LightWalletOptions): LightWalletOptions { 75 | if (_.isUndefined(options.hdPathString)) { 76 | options.hdPathString = DEFAULT_DERIVATION_PATH; 77 | } 78 | if (_.isUndefined(options.seedPhrase)) { 79 | options.seedPhrase = lightwallet.keystore.generateRandomSeed(); 80 | } 81 | return options; 82 | } 83 | 84 | /** 85 | * Throw the appropriate exception on error 86 | * 87 | * @param {WalletError[]} errors An array of possible WalletErrors 88 | */ 89 | private static throwOnError(...errors: WalletError[]) { 90 | for (const error of errors) { 91 | switch (error) { 92 | case WalletError.StorageDisabled: 93 | if (!Store.isStorageSupported()) throw new Error(WalletError.StorageDisabled); 94 | break; 95 | } 96 | } 97 | } 98 | 99 | /** 100 | * Validate the seed or throw an InvalidSeed exception 101 | * 102 | * @param {string} seed The seed to validate 103 | */ 104 | private static validateSeedPhraseOrThrow(seed: string): void { 105 | const valid = lightwallet.keystore.isSeedValid(seed); 106 | 107 | if (!valid) { 108 | throw new Error(WalletError.InvalidSeed); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWallet.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [0, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | Object.defineProperty(exports, "__esModule", { value: true }); 38 | var LightWalletSigner_1 = require("./LightWalletSigner"); 39 | var types_1 = require("../../types"); 40 | var Store_1 = require("../../Store"); 41 | var LightWalletUtils_1 = require("./LightWalletUtils"); 42 | var LightWallet = /** @class */ (function () { 43 | function LightWallet(keystore, signing, pwDerivedKey) { 44 | this.keystore = keystore; 45 | this.signing = signing; 46 | this.pwDerivedKey = pwDerivedKey; 47 | this.type = types_1.WalletType.LightWallet; 48 | this.signer = new LightWalletSigner_1.LightWalletSigner(keystore, signing, pwDerivedKey); 49 | } 50 | /** 51 | * Adds one or more accounts to the wallet 52 | * 53 | * @param {number} [numberOfAccounts=1] The number of accounts to add 54 | */ 55 | LightWallet.prototype.addNewAccounts = function (numberOfAccounts) { 56 | if (numberOfAccounts === void 0) { numberOfAccounts = 1; } 57 | this.keystore.generateNewAddress(this.pwDerivedKey, numberOfAccounts); 58 | Store_1.Store.saveWallet(this); 59 | }; 60 | /** 61 | * Gets all the accounts from the wallet 62 | * 63 | */ 64 | LightWallet.prototype.getAccounts = function () { 65 | var accounts = this.keystore.getAddresses(); 66 | return accounts; 67 | }; 68 | /** 69 | * Serialize the wallet keystore 70 | * 71 | */ 72 | LightWallet.prototype.serialize = function () { 73 | return this.keystore.serialize(); 74 | }; 75 | /** 76 | * Exports the wallet's seed phrase 77 | * 78 | * @param {string} password The plaintext password 79 | */ 80 | LightWallet.prototype.exportSeedPhraseAsync = function (password) { 81 | return __awaiter(this, void 0, void 0, function () { 82 | var pwDerivedKey; 83 | return __generator(this, function (_a) { 84 | switch (_a.label) { 85 | case 0: return [4 /*yield*/, LightWalletUtils_1.LightWalletUtils.deriveKeyFromPasswordAsync(this.keystore, password)]; 86 | case 1: 87 | pwDerivedKey = _a.sent(); 88 | LightWalletUtils_1.LightWalletUtils.validatePwDerivedKeyOrThrow(pwDerivedKey, this.keystore); 89 | return [2 /*return*/, this.keystore.getSeed(pwDerivedKey)]; 90 | } 91 | }); 92 | }); 93 | }; 94 | /** 95 | * Exports the private key for a single account 96 | * 97 | * @param {string} account The account used for the export 98 | * @param {string} password The plaintext password 99 | */ 100 | LightWallet.prototype.exportAccountPrivateKeyAsync = function (account, password) { 101 | return __awaiter(this, void 0, void 0, function () { 102 | var pwDerivedKey; 103 | return __generator(this, function (_a) { 104 | switch (_a.label) { 105 | case 0: return [4 /*yield*/, LightWalletUtils_1.LightWalletUtils.deriveKeyFromPasswordAsync(this.keystore, password)]; 106 | case 1: 107 | pwDerivedKey = _a.sent(); 108 | LightWalletUtils_1.LightWalletUtils.validatePwDerivedKeyOrThrow(pwDerivedKey, this.keystore); 109 | return [2 /*return*/, this.keystore.exportPrivateKey(account, pwDerivedKey)]; 110 | } 111 | }); 112 | }); 113 | }; 114 | return LightWallet; 115 | }()); 116 | exports.LightWallet = LightWallet; 117 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWalletSigner.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [0, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | Object.defineProperty(exports, "__esModule", { value: true }); 38 | var EthereumTx = require("ethereumjs-tx"); 39 | var LightWalletSigner = /** @class */ (function () { 40 | function LightWalletSigner(keystore, signing, pwDerivedKey) { 41 | this._keystore = keystore; 42 | this._signing = signing; 43 | this._pwDerivedKey = pwDerivedKey; 44 | } 45 | /** 46 | * Sign a personal message hash 47 | * 48 | * @param {string} account The account to sign with 49 | * @param {string} hash The hash to sign 50 | */ 51 | LightWalletSigner.prototype.signPersonalMessageHashAsync = function (account, hash) { 52 | return __awaiter(this, void 0, void 0, function () { 53 | var result, signature, err_1; 54 | return __generator(this, function (_a) { 55 | switch (_a.label) { 56 | case 0: 57 | _a.trys.push([0, 2, , 3]); 58 | return [4 /*yield*/, this._signing.signMsgHash(this._keystore, this._pwDerivedKey, hash, account, this._keystore.hdPathString)]; 59 | case 1: 60 | result = _a.sent(); 61 | signature = this._signing.concatSig(result); 62 | return [2 /*return*/, signature]; 63 | case 2: 64 | err_1 = _a.sent(); 65 | throw err_1; 66 | case 3: return [2 /*return*/]; 67 | } 68 | }); 69 | }); 70 | }; 71 | /** 72 | * Sign a personal message 73 | * 74 | * @param {string} account The account to sign with 75 | * @param {string} message The message to sign 76 | */ 77 | LightWalletSigner.prototype.signPersonalMessageAsync = function (account, message) { 78 | return __awaiter(this, void 0, void 0, function () { 79 | var result, signature, err_2; 80 | return __generator(this, function (_a) { 81 | switch (_a.label) { 82 | case 0: 83 | _a.trys.push([0, 2, , 3]); 84 | return [4 /*yield*/, this._signing.signMsg(this._keystore, this._pwDerivedKey, message, account, this._keystore.hdPathString)]; 85 | case 1: 86 | result = _a.sent(); 87 | signature = this._signing.concatSig(result); 88 | return [2 /*return*/, signature]; 89 | case 2: 90 | err_2 = _a.sent(); 91 | throw err_2; 92 | case 3: return [2 /*return*/]; 93 | } 94 | }); 95 | }); 96 | }; 97 | /** 98 | * Sign a transaction 99 | * 100 | * @param {PartialTxParams} txParams The transaction parameters 101 | */ 102 | LightWalletSigner.prototype.signTransactionAsync = function (txParams) { 103 | return __awaiter(this, void 0, void 0, function () { 104 | var tx, txHex, signedTxHex; 105 | return __generator(this, function (_a) { 106 | try { 107 | tx = new EthereumTx(txParams); 108 | txHex = tx.serialize().toString('hex'); 109 | signedTxHex = this._signing.signTx(this._keystore, this._pwDerivedKey, txHex, txParams.from, this._keystore.hdPathString); 110 | signedTxHex = "0x" + signedTxHex; 111 | return [2 /*return*/, signedTxHex]; 112 | } 113 | catch (err) { 114 | throw err; 115 | } 116 | return [2 /*return*/]; 117 | }); 118 | }); 119 | }; 120 | return LightWalletSigner; 121 | }()); 122 | exports.LightWalletSigner = LightWalletSigner; 123 | -------------------------------------------------------------------------------- /dist/wallets/lightwallet/LightWalletManager.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __generator = (this && this.__generator) || function (thisArg, body) { 11 | var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; 12 | return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; 13 | function verb(n) { return function (v) { return step([n, v]); }; } 14 | function step(op) { 15 | if (f) throw new TypeError("Generator is already executing."); 16 | while (_) try { 17 | if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; 18 | if (y = 0, t) op = [0, t.value]; 19 | switch (op[0]) { 20 | case 0: case 1: t = op; break; 21 | case 4: _.label++; return { value: op[1], done: false }; 22 | case 5: _.label++; y = op[1]; op = [0]; continue; 23 | case 7: op = _.ops.pop(); _.trys.pop(); continue; 24 | default: 25 | if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } 26 | if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } 27 | if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } 28 | if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } 29 | if (t[2]) _.ops.pop(); 30 | _.trys.pop(); continue; 31 | } 32 | op = body.call(thisArg, _); 33 | } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } 34 | if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; 35 | } 36 | }; 37 | Object.defineProperty(exports, "__esModule", { value: true }); 38 | var lightwallet = require("eth-lightwallet"); 39 | var _ = require("lodash"); 40 | var Store_1 = require("../../Store"); 41 | var types_1 = require("../../types"); 42 | var constants_1 = require("../../constants"); 43 | var LightWallet_1 = require("./LightWallet"); 44 | var LightWalletUtils_1 = require("./LightWalletUtils"); 45 | var LightWalletManager = /** @class */ (function () { 46 | function LightWalletManager() { 47 | } 48 | /** 49 | * Creates a new lightwallet and saves it in local storage 50 | * 51 | * @param options LightWallet initialization options 52 | */ 53 | LightWalletManager.createWalletAsync = function (options) { 54 | return __awaiter(this, void 0, void 0, function () { 55 | var filledOptions, keystore, pwDerivedKey, lightWallet; 56 | return __generator(this, function (_a) { 57 | switch (_a.label) { 58 | case 0: 59 | filledOptions = this.populateMissingOptions(options); 60 | this.throwOnError(types_1.WalletError.StorageDisabled); 61 | this.validateSeedPhraseOrThrow(options.seedPhrase); 62 | return [4 /*yield*/, this.initializeKeystoreAsync(filledOptions)]; 63 | case 1: 64 | keystore = _a.sent(); 65 | return [4 /*yield*/, LightWalletUtils_1.LightWalletUtils.deriveKeyFromPasswordAsync(keystore, options.password)]; 66 | case 2: 67 | pwDerivedKey = _a.sent(); 68 | keystore.generateNewAddress(pwDerivedKey, 1); 69 | lightWallet = new LightWallet_1.LightWallet(keystore, lightwallet.signing, pwDerivedKey); 70 | Store_1.Store.saveWallet(lightWallet, options.storageKeyName); 71 | return [2 /*return*/, lightWallet]; 72 | } 73 | }); 74 | }); 75 | }; 76 | /** 77 | * Save the wallet 78 | * 79 | * @param {LightWallet} wallet The wallet instance 80 | */ 81 | LightWalletManager.saveWallet = function (wallet, keyName) { 82 | if (wallet) 83 | Store_1.Store.saveWallet(wallet, keyName); 84 | }; 85 | /** 86 | * Loads a wallet from local storage 87 | * 88 | * @param {string} password The plaintext password 89 | */ 90 | LightWalletManager.loadWalletAsync = function (password, keyName) { 91 | return __awaiter(this, void 0, void 0, function () { 92 | var serializedKeystore, keystore, pwDerivedKey; 93 | return __generator(this, function (_a) { 94 | switch (_a.label) { 95 | case 0: 96 | serializedKeystore = Store_1.Store.loadWallet(keyName); 97 | keystore = lightwallet.keystore.deserialize(serializedKeystore); 98 | return [4 /*yield*/, LightWalletUtils_1.LightWalletUtils.deriveKeyFromPasswordAsync(keystore, password)]; 99 | case 1: 100 | pwDerivedKey = _a.sent(); 101 | LightWalletUtils_1.LightWalletUtils.validatePwDerivedKeyOrThrow(pwDerivedKey, keystore); 102 | return [2 /*return*/, new LightWallet_1.LightWallet(keystore, lightwallet.signing, pwDerivedKey)]; 103 | } 104 | }); 105 | }); 106 | }; 107 | /** 108 | * Initializes a new eth-lightwallet keystore 109 | * 110 | * @param {LightWalletOptions} options LightWallet initialization options 111 | */ 112 | LightWalletManager.initializeKeystoreAsync = function (options) { 113 | return __awaiter(this, void 0, void 0, function () { 114 | return __generator(this, function (_a) { 115 | return [2 /*return*/, new Promise(function (resolve) { 116 | // Create LightWallet 117 | lightwallet.keystore.createVault(options, function (err, keystore) { 118 | resolve(keystore); 119 | }); 120 | })]; 121 | }); 122 | }); 123 | }; 124 | /** 125 | * Populate the missing wallet options 126 | * 127 | * @param {LightWalletOptions} options LightWallet initialization options 128 | */ 129 | LightWalletManager.populateMissingOptions = function (options) { 130 | if (_.isUndefined(options.hdPathString)) { 131 | options.hdPathString = constants_1.DEFAULT_DERIVATION_PATH; 132 | } 133 | if (_.isUndefined(options.seedPhrase)) { 134 | options.seedPhrase = lightwallet.keystore.generateRandomSeed(); 135 | } 136 | return options; 137 | }; 138 | /** 139 | * Throw the appropriate exception on error 140 | * 141 | * @param {WalletError[]} errors An array of possible WalletErrors 142 | */ 143 | LightWalletManager.throwOnError = function () { 144 | var errors = []; 145 | for (var _i = 0; _i < arguments.length; _i++) { 146 | errors[_i] = arguments[_i]; 147 | } 148 | for (var _a = 0, errors_1 = errors; _a < errors_1.length; _a++) { 149 | var error = errors_1[_a]; 150 | switch (error) { 151 | case types_1.WalletError.StorageDisabled: 152 | if (!Store_1.Store.isStorageSupported()) 153 | throw new Error(types_1.WalletError.StorageDisabled); 154 | break; 155 | } 156 | } 157 | }; 158 | /** 159 | * Validate the seed or throw an InvalidSeed exception 160 | * 161 | * @param {string} seed The seed to validate 162 | */ 163 | LightWalletManager.validateSeedPhraseOrThrow = function (seed) { 164 | var valid = lightwallet.keystore.isSeedValid(seed); 165 | if (!valid) { 166 | throw new Error(types_1.WalletError.InvalidSeed); 167 | } 168 | }; 169 | return LightWalletManager; 170 | }()); 171 | exports.LightWalletManager = LightWalletManager; 172 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@types/chai@^4.0.4": 6 | version "4.1.3" 7 | resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.3.tgz#b8a74352977a23b604c01aa784f5b793443fb7dc" 8 | 9 | "@types/lodash@^4.14.109": 10 | version "4.14.109" 11 | resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.109.tgz#b1c4442239730bf35cabaf493c772b18c045886d" 12 | 13 | "@types/mocha@^2.2.43": 14 | version "2.2.48" 15 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.48.tgz#3523b126a0b049482e1c3c11877460f76622ffab" 16 | 17 | "@types/node@^8.0.46": 18 | version "8.10.18" 19 | resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.18.tgz#eb9ad8b0723d13fa9bc8b42543e3661ed805f2bb" 20 | 21 | ansi-regex@^2.0.0: 22 | version "2.1.1" 23 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 24 | 25 | ansi-styles@^2.2.1: 26 | version "2.2.1" 27 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 28 | 29 | ansi-styles@^3.2.1: 30 | version "3.2.1" 31 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 32 | dependencies: 33 | color-convert "^1.9.0" 34 | 35 | argparse@^1.0.7: 36 | version "1.0.10" 37 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 38 | dependencies: 39 | sprintf-js "~1.0.2" 40 | 41 | assertion-error@^1.0.1: 42 | version "1.1.0" 43 | resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" 44 | 45 | babel-code-frame@^6.22.0: 46 | version "6.26.0" 47 | resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" 48 | dependencies: 49 | chalk "^1.1.3" 50 | esutils "^2.0.2" 51 | js-tokens "^3.0.2" 52 | 53 | balanced-match@^1.0.0: 54 | version "1.0.0" 55 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 56 | 57 | base-x@^3.0.2: 58 | version "3.0.4" 59 | resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" 60 | dependencies: 61 | safe-buffer "^5.0.1" 62 | 63 | base64-js@^1.0.2: 64 | version "1.3.0" 65 | resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" 66 | 67 | "bignumber.js@git+https://github.com/frozeman/bignumber.js-nolookahead.git": 68 | version "2.0.7" 69 | resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" 70 | 71 | bindings@^1.2.1: 72 | version "1.3.0" 73 | resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" 74 | 75 | bip66@^1.1.3: 76 | version "1.1.5" 77 | resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" 78 | dependencies: 79 | safe-buffer "^5.0.1" 80 | 81 | bitcore-lib@^0.15.0: 82 | version "0.15.0" 83 | resolved "https://registry.yarnpkg.com/bitcore-lib/-/bitcore-lib-0.15.0.tgz#f924be13869f2aab7e04aeec5642ad3359b6cec2" 84 | dependencies: 85 | bn.js "=4.11.8" 86 | bs58 "=4.0.1" 87 | buffer-compare "=1.1.1" 88 | elliptic "=6.4.0" 89 | inherits "=2.0.1" 90 | lodash "=4.17.4" 91 | 92 | bitcore-mnemonic@^1.5.0: 93 | version "1.5.0" 94 | resolved "https://registry.yarnpkg.com/bitcore-mnemonic/-/bitcore-mnemonic-1.5.0.tgz#c7e785beb6bf0616ed4992785dc3658670425a39" 95 | dependencies: 96 | bitcore-lib "^0.15.0" 97 | unorm "^1.3.3" 98 | 99 | bn.js@=4.11.8, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.4.0: 100 | version "4.11.8" 101 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" 102 | 103 | bn.js@^2.0.3: 104 | version "2.2.0" 105 | resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-2.2.0.tgz#12162bc2ae71fc40a5626c33438f3a875cd37625" 106 | 107 | brace-expansion@^1.1.7: 108 | version "1.1.11" 109 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 110 | dependencies: 111 | balanced-match "^1.0.0" 112 | concat-map "0.0.1" 113 | 114 | brorand@^1.0.1: 115 | version "1.1.0" 116 | resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" 117 | 118 | browser-stdout@1.3.0: 119 | version "1.3.0" 120 | resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" 121 | 122 | browserify-aes@^1.0.6: 123 | version "1.2.0" 124 | resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" 125 | dependencies: 126 | buffer-xor "^1.0.3" 127 | cipher-base "^1.0.0" 128 | create-hash "^1.1.0" 129 | evp_bytestokey "^1.0.3" 130 | inherits "^2.0.1" 131 | safe-buffer "^5.0.1" 132 | 133 | bs58@=4.0.1: 134 | version "4.0.1" 135 | resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" 136 | dependencies: 137 | base-x "^3.0.2" 138 | 139 | buffer-compare@=1.1.1: 140 | version "1.1.1" 141 | resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.1.1.tgz#5be7be853af89198d1f4ddc090d1d66a48aef596" 142 | 143 | buffer-xor@^1.0.3: 144 | version "1.0.3" 145 | resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" 146 | 147 | buffer@^4.9.0: 148 | version "4.9.1" 149 | resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" 150 | dependencies: 151 | base64-js "^1.0.2" 152 | ieee754 "^1.1.4" 153 | isarray "^1.0.0" 154 | 155 | builtin-modules@^1.1.1: 156 | version "1.1.1" 157 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 158 | 159 | chai@^3.5.0: 160 | version "3.5.0" 161 | resolved "https://registry.yarnpkg.com/chai/-/chai-3.5.0.tgz#4d02637b067fe958bdbfdd3a40ec56fef7373247" 162 | dependencies: 163 | assertion-error "^1.0.1" 164 | deep-eql "^0.1.3" 165 | type-detect "^1.0.0" 166 | 167 | chalk@^1.1.3: 168 | version "1.1.3" 169 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 170 | dependencies: 171 | ansi-styles "^2.2.1" 172 | escape-string-regexp "^1.0.2" 173 | has-ansi "^2.0.0" 174 | strip-ansi "^3.0.0" 175 | supports-color "^2.0.0" 176 | 177 | chalk@^2.3.0: 178 | version "2.4.1" 179 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" 180 | dependencies: 181 | ansi-styles "^3.2.1" 182 | escape-string-regexp "^1.0.5" 183 | supports-color "^5.3.0" 184 | 185 | cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: 186 | version "1.0.4" 187 | resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" 188 | dependencies: 189 | inherits "^2.0.1" 190 | safe-buffer "^5.0.1" 191 | 192 | color-convert@^1.9.0: 193 | version "1.9.1" 194 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" 195 | dependencies: 196 | color-name "^1.1.1" 197 | 198 | color-name@^1.1.1: 199 | version "1.1.3" 200 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 201 | 202 | commander@2.9.0: 203 | version "2.9.0" 204 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" 205 | dependencies: 206 | graceful-readlink ">= 1.0.0" 207 | 208 | commander@^2.12.1: 209 | version "2.15.1" 210 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" 211 | 212 | concat-map@0.0.1: 213 | version "0.0.1" 214 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 215 | 216 | core-js@^0.8.3: 217 | version "0.8.4" 218 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-0.8.4.tgz#c22665f1e0d1b9c3c5e1b08dabd1f108695e4fcf" 219 | 220 | create-hash@^1.1.0, create-hash@^1.1.2: 221 | version "1.2.0" 222 | resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" 223 | dependencies: 224 | cipher-base "^1.0.1" 225 | inherits "^2.0.1" 226 | md5.js "^1.3.4" 227 | ripemd160 "^2.0.1" 228 | sha.js "^2.4.0" 229 | 230 | create-hmac@^1.1.4: 231 | version "1.1.7" 232 | resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" 233 | dependencies: 234 | cipher-base "^1.0.3" 235 | create-hash "^1.1.0" 236 | inherits "^2.0.1" 237 | ripemd160 "^2.0.0" 238 | safe-buffer "^5.0.1" 239 | sha.js "^2.4.8" 240 | 241 | crypto-js@^3.1.4, crypto-js@^3.1.5: 242 | version "3.1.8" 243 | resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" 244 | 245 | debug@2.6.8: 246 | version "2.6.8" 247 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" 248 | dependencies: 249 | ms "2.0.0" 250 | 251 | deep-eql@^0.1.3: 252 | version "0.1.3" 253 | resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" 254 | dependencies: 255 | type-detect "0.1.1" 256 | 257 | diff@3.2.0: 258 | version "3.2.0" 259 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" 260 | 261 | diff@^3.2.0: 262 | version "3.5.0" 263 | resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" 264 | 265 | dom-walk@^0.1.0: 266 | version "0.1.1" 267 | resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" 268 | 269 | drbg.js@^1.0.1: 270 | version "1.0.1" 271 | resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" 272 | dependencies: 273 | browserify-aes "^1.0.6" 274 | create-hash "^1.1.2" 275 | create-hmac "^1.1.4" 276 | 277 | elliptic@=6.4.0, elliptic@^6.2.3: 278 | version "6.4.0" 279 | resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" 280 | dependencies: 281 | bn.js "^4.4.0" 282 | brorand "^1.0.1" 283 | hash.js "^1.0.0" 284 | hmac-drbg "^1.0.0" 285 | inherits "^2.0.1" 286 | minimalistic-assert "^1.0.0" 287 | minimalistic-crypto-utils "^1.0.0" 288 | 289 | elliptic@^3.1.0: 290 | version "3.1.0" 291 | resolved "http://registry.npmjs.org/elliptic/-/elliptic-3.1.0.tgz#c21682ef762769b56a74201609105da11d5f60cc" 292 | dependencies: 293 | bn.js "^2.0.3" 294 | brorand "^1.0.1" 295 | hash.js "^1.0.0" 296 | inherits "^2.0.1" 297 | 298 | escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 299 | version "1.0.5" 300 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 301 | 302 | esprima@^4.0.0: 303 | version "4.0.0" 304 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" 305 | 306 | esutils@^2.0.2: 307 | version "2.0.2" 308 | resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" 309 | 310 | eth-lightwallet@^3.0.1: 311 | version "3.0.1" 312 | resolved "https://registry.yarnpkg.com/eth-lightwallet/-/eth-lightwallet-3.0.1.tgz#297022932aa568f4e4eb0873bff257f5e5b78709" 313 | dependencies: 314 | bitcore-lib "^0.15.0" 315 | bitcore-mnemonic "^1.5.0" 316 | buffer "^4.9.0" 317 | crypto-js "^3.1.5" 318 | elliptic "^3.1.0" 319 | ethereumjs-tx "^1.3.3" 320 | ethereumjs-util "^5.1.1" 321 | rlp "^2.0.0" 322 | scrypt-async "^1.2.0" 323 | tweetnacl "0.13.2" 324 | web3 "0.20.2" 325 | 326 | ethereum-common@^0.0.18: 327 | version "0.0.18" 328 | resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" 329 | 330 | ethereumjs-tx@^1.3.3: 331 | version "1.3.4" 332 | resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.4.tgz#c2304912f6c07af03237ad8675ac036e290dad48" 333 | dependencies: 334 | ethereum-common "^0.0.18" 335 | ethereumjs-util "^5.0.0" 336 | 337 | ethereumjs-util@^5.0.0, ethereumjs-util@^5.1.1: 338 | version "5.2.0" 339 | resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" 340 | dependencies: 341 | bn.js "^4.11.0" 342 | create-hash "^1.1.2" 343 | ethjs-util "^0.1.3" 344 | keccak "^1.0.2" 345 | rlp "^2.0.0" 346 | safe-buffer "^5.1.1" 347 | secp256k1 "^3.0.1" 348 | 349 | ethjs-util@^0.1.3: 350 | version "0.1.4" 351 | resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.4.tgz#1c8b6879257444ef4d3f3fbbac2ded12cd997d93" 352 | dependencies: 353 | is-hex-prefixed "1.0.0" 354 | strip-hex-prefix "1.0.0" 355 | 356 | evp_bytestokey@^1.0.3: 357 | version "1.0.3" 358 | resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" 359 | dependencies: 360 | md5.js "^1.3.4" 361 | safe-buffer "^5.1.1" 362 | 363 | fs.realpath@^1.0.0: 364 | version "1.0.0" 365 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 366 | 367 | glob@7.1.1: 368 | version "7.1.1" 369 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" 370 | dependencies: 371 | fs.realpath "^1.0.0" 372 | inflight "^1.0.4" 373 | inherits "2" 374 | minimatch "^3.0.2" 375 | once "^1.3.0" 376 | path-is-absolute "^1.0.0" 377 | 378 | glob@^7.1.1: 379 | version "7.1.2" 380 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 381 | dependencies: 382 | fs.realpath "^1.0.0" 383 | inflight "^1.0.4" 384 | inherits "2" 385 | minimatch "^3.0.4" 386 | once "^1.3.0" 387 | path-is-absolute "^1.0.0" 388 | 389 | global@^4.3.2: 390 | version "4.3.2" 391 | resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" 392 | dependencies: 393 | min-document "^2.19.0" 394 | process "~0.5.1" 395 | 396 | "graceful-readlink@>= 1.0.0": 397 | version "1.0.1" 398 | resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" 399 | 400 | growl@1.9.2: 401 | version "1.9.2" 402 | resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" 403 | 404 | has-ansi@^2.0.0: 405 | version "2.0.0" 406 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 407 | dependencies: 408 | ansi-regex "^2.0.0" 409 | 410 | has-flag@^1.0.0: 411 | version "1.0.0" 412 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 413 | 414 | has-flag@^3.0.0: 415 | version "3.0.0" 416 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 417 | 418 | hash-base@^3.0.0: 419 | version "3.0.4" 420 | resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" 421 | dependencies: 422 | inherits "^2.0.1" 423 | safe-buffer "^5.0.1" 424 | 425 | hash.js@^1.0.0, hash.js@^1.0.3: 426 | version "1.1.3" 427 | resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" 428 | dependencies: 429 | inherits "^2.0.3" 430 | minimalistic-assert "^1.0.0" 431 | 432 | he@1.1.1: 433 | version "1.1.1" 434 | resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" 435 | 436 | hmac-drbg@^1.0.0: 437 | version "1.0.1" 438 | resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" 439 | dependencies: 440 | hash.js "^1.0.3" 441 | minimalistic-assert "^1.0.0" 442 | minimalistic-crypto-utils "^1.0.1" 443 | 444 | ieee754@^1.1.4: 445 | version "1.1.11" 446 | resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.11.tgz#c16384ffe00f5b7835824e67b6f2bd44a5229455" 447 | 448 | inflight@^1.0.4: 449 | version "1.0.6" 450 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 451 | dependencies: 452 | once "^1.3.0" 453 | wrappy "1" 454 | 455 | inherits@2, inherits@^2.0.1, inherits@^2.0.3: 456 | version "2.0.3" 457 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 458 | 459 | inherits@=2.0.1: 460 | version "2.0.1" 461 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" 462 | 463 | is-hex-prefixed@1.0.0: 464 | version "1.0.0" 465 | resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" 466 | 467 | isarray@^1.0.0: 468 | version "1.0.0" 469 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 470 | 471 | js-tokens@^3.0.2: 472 | version "3.0.2" 473 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" 474 | 475 | js-yaml@^3.7.0: 476 | version "3.11.0" 477 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.11.0.tgz#597c1a8bd57152f26d622ce4117851a51f5ebaef" 478 | dependencies: 479 | argparse "^1.0.7" 480 | esprima "^4.0.0" 481 | 482 | json3@3.3.2: 483 | version "3.3.2" 484 | resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" 485 | 486 | keccak@^1.0.2: 487 | version "1.4.0" 488 | resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" 489 | dependencies: 490 | bindings "^1.2.1" 491 | inherits "^2.0.3" 492 | nan "^2.2.1" 493 | safe-buffer "^5.1.0" 494 | 495 | lodash._baseassign@^3.0.0: 496 | version "3.2.0" 497 | resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" 498 | dependencies: 499 | lodash._basecopy "^3.0.0" 500 | lodash.keys "^3.0.0" 501 | 502 | lodash._basecopy@^3.0.0: 503 | version "3.0.1" 504 | resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" 505 | 506 | lodash._basecreate@^3.0.0: 507 | version "3.0.3" 508 | resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" 509 | 510 | lodash._getnative@^3.0.0: 511 | version "3.9.1" 512 | resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" 513 | 514 | lodash._isiterateecall@^3.0.0: 515 | version "3.0.9" 516 | resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" 517 | 518 | lodash.create@3.1.1: 519 | version "3.1.1" 520 | resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" 521 | dependencies: 522 | lodash._baseassign "^3.0.0" 523 | lodash._basecreate "^3.0.0" 524 | lodash._isiterateecall "^3.0.0" 525 | 526 | lodash.isarguments@^3.0.0: 527 | version "3.1.0" 528 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 529 | 530 | lodash.isarray@^3.0.0: 531 | version "3.0.4" 532 | resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" 533 | 534 | lodash.keys@^3.0.0: 535 | version "3.1.2" 536 | resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" 537 | dependencies: 538 | lodash._getnative "^3.0.0" 539 | lodash.isarguments "^3.0.0" 540 | lodash.isarray "^3.0.0" 541 | 542 | lodash@=4.17.4: 543 | version "4.17.4" 544 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 545 | 546 | lodash@^4.17.10: 547 | version "4.17.10" 548 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" 549 | 550 | md5.js@^1.3.4: 551 | version "1.3.4" 552 | resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" 553 | dependencies: 554 | hash-base "^3.0.0" 555 | inherits "^2.0.1" 556 | 557 | min-document@^2.19.0: 558 | version "2.19.0" 559 | resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" 560 | dependencies: 561 | dom-walk "^0.1.0" 562 | 563 | minimalistic-assert@^1.0.0: 564 | version "1.0.1" 565 | resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" 566 | 567 | minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: 568 | version "1.0.1" 569 | resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" 570 | 571 | minimatch@^3.0.2, minimatch@^3.0.4: 572 | version "3.0.4" 573 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 574 | dependencies: 575 | brace-expansion "^1.1.7" 576 | 577 | minimist@0.0.8: 578 | version "0.0.8" 579 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 580 | 581 | mkdirp@0.5.1: 582 | version "0.5.1" 583 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 584 | dependencies: 585 | minimist "0.0.8" 586 | 587 | mocha@^3.1.2: 588 | version "3.5.3" 589 | resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" 590 | dependencies: 591 | browser-stdout "1.3.0" 592 | commander "2.9.0" 593 | debug "2.6.8" 594 | diff "3.2.0" 595 | escape-string-regexp "1.0.5" 596 | glob "7.1.1" 597 | growl "1.9.2" 598 | he "1.1.1" 599 | json3 "3.3.2" 600 | lodash.create "3.1.1" 601 | mkdirp "0.5.1" 602 | supports-color "3.1.2" 603 | 604 | mock-local-storage@^1.0.5: 605 | version "1.0.5" 606 | resolved "https://registry.yarnpkg.com/mock-local-storage/-/mock-local-storage-1.0.5.tgz#899ff300027cefed47816e6dc539bb059fcce489" 607 | dependencies: 608 | core-js "^0.8.3" 609 | global "^4.3.2" 610 | 611 | ms@2.0.0: 612 | version "2.0.0" 613 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 614 | 615 | nan@^2.2.1: 616 | version "2.10.0" 617 | resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" 618 | 619 | once@^1.3.0: 620 | version "1.4.0" 621 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 622 | dependencies: 623 | wrappy "1" 624 | 625 | path-is-absolute@^1.0.0: 626 | version "1.0.1" 627 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 628 | 629 | path-parse@^1.0.5: 630 | version "1.0.5" 631 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" 632 | 633 | process@~0.5.1: 634 | version "0.5.2" 635 | resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" 636 | 637 | resolve@^1.3.2: 638 | version "1.7.1" 639 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" 640 | dependencies: 641 | path-parse "^1.0.5" 642 | 643 | ripemd160@^2.0.0, ripemd160@^2.0.1: 644 | version "2.0.2" 645 | resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" 646 | dependencies: 647 | hash-base "^3.0.0" 648 | inherits "^2.0.1" 649 | 650 | rlp@^2.0.0: 651 | version "2.0.0" 652 | resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.0.0.tgz#9db384ff4b89a8f61563d92395d8625b18f3afb0" 653 | 654 | safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1: 655 | version "5.1.2" 656 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 657 | 658 | scrypt-async@^1.2.0: 659 | version "1.3.1" 660 | resolved "https://registry.yarnpkg.com/scrypt-async/-/scrypt-async-1.3.1.tgz#a11fd6fac981b4b823ee01dee0221169500ddae9" 661 | 662 | secp256k1@^3.0.1: 663 | version "3.5.0" 664 | resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.0.tgz#677d3b8a8e04e1a5fa381a1ae437c54207b738d0" 665 | dependencies: 666 | bindings "^1.2.1" 667 | bip66 "^1.1.3" 668 | bn.js "^4.11.3" 669 | create-hash "^1.1.2" 670 | drbg.js "^1.0.1" 671 | elliptic "^6.2.3" 672 | nan "^2.2.1" 673 | safe-buffer "^5.1.0" 674 | 675 | semver@^5.3.0: 676 | version "5.5.0" 677 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" 678 | 679 | sha.js@^2.4.0, sha.js@^2.4.8: 680 | version "2.4.11" 681 | resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" 682 | dependencies: 683 | inherits "^2.0.1" 684 | safe-buffer "^5.0.1" 685 | 686 | sprintf-js@~1.0.2: 687 | version "1.0.3" 688 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 689 | 690 | strip-ansi@^3.0.0: 691 | version "3.0.1" 692 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 693 | dependencies: 694 | ansi-regex "^2.0.0" 695 | 696 | strip-hex-prefix@1.0.0: 697 | version "1.0.0" 698 | resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" 699 | dependencies: 700 | is-hex-prefixed "1.0.0" 701 | 702 | supports-color@3.1.2: 703 | version "3.1.2" 704 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" 705 | dependencies: 706 | has-flag "^1.0.0" 707 | 708 | supports-color@^2.0.0: 709 | version "2.0.0" 710 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 711 | 712 | supports-color@^5.3.0: 713 | version "5.4.0" 714 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" 715 | dependencies: 716 | has-flag "^3.0.0" 717 | 718 | tslib@^1.8.0, tslib@^1.8.1: 719 | version "1.9.2" 720 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.2.tgz#8be0cc9a1f6dc7727c38deb16c2ebd1a2892988e" 721 | 722 | tslint-config-0xproject@0.0.2: 723 | version "0.0.2" 724 | resolved "https://registry.yarnpkg.com/tslint-config-0xproject/-/tslint-config-0xproject-0.0.2.tgz#39901e0c0b3e9388f00092a28b90c015395d5bba" 725 | dependencies: 726 | tslint-react "^3.0.0" 727 | 728 | tslint-react@^3.0.0: 729 | version "3.6.0" 730 | resolved "https://registry.yarnpkg.com/tslint-react/-/tslint-react-3.6.0.tgz#7f462c95c4a0afaae82507f06517ff02942196a1" 731 | dependencies: 732 | tsutils "^2.13.1" 733 | 734 | tslint@^5.8.0: 735 | version "5.10.0" 736 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.10.0.tgz#11e26bccb88afa02dd0d9956cae3d4540b5f54c3" 737 | dependencies: 738 | babel-code-frame "^6.22.0" 739 | builtin-modules "^1.1.1" 740 | chalk "^2.3.0" 741 | commander "^2.12.1" 742 | diff "^3.2.0" 743 | glob "^7.1.1" 744 | js-yaml "^3.7.0" 745 | minimatch "^3.0.4" 746 | resolve "^1.3.2" 747 | semver "^5.3.0" 748 | tslib "^1.8.0" 749 | tsutils "^2.12.1" 750 | 751 | tsutils@^2.12.1, tsutils@^2.13.1: 752 | version "2.27.1" 753 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.27.1.tgz#ab0276ac23664f36ce8fd4414daec4aebf4373ee" 754 | dependencies: 755 | tslib "^1.8.1" 756 | 757 | tweetnacl@0.13.2: 758 | version "0.13.2" 759 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.13.2.tgz#453161770469d45cd266c36404e2bc99a8fa9944" 760 | 761 | type-detect@0.1.1: 762 | version "0.1.1" 763 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" 764 | 765 | type-detect@^1.0.0: 766 | version "1.0.0" 767 | resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-1.0.0.tgz#762217cc06db258ec48908a1298e8b95121e8ea2" 768 | 769 | typescript@^2.5.3: 770 | version "2.9.1" 771 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-2.9.1.tgz#fdb19d2c67a15d11995fd15640e373e09ab09961" 772 | 773 | unorm@^1.3.3: 774 | version "1.4.1" 775 | resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" 776 | 777 | utf8@^2.1.1: 778 | version "2.1.2" 779 | resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" 780 | 781 | web3@0.20.2: 782 | version "0.20.2" 783 | resolved "https://registry.yarnpkg.com/web3/-/web3-0.20.2.tgz#c54dac5fc0e377399c04c1a6ecbb12e4513278d6" 784 | dependencies: 785 | bignumber.js "git+https://github.com/frozeman/bignumber.js-nolookahead.git" 786 | crypto-js "^3.1.4" 787 | utf8 "^2.1.1" 788 | xhr2 "*" 789 | xmlhttprequest "*" 790 | 791 | wrappy@1: 792 | version "1.0.2" 793 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 794 | 795 | xhr2@*: 796 | version "0.1.4" 797 | resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" 798 | 799 | xmlhttprequest@*: 800 | version "1.8.0" 801 | resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" 802 | --------------------------------------------------------------------------------