11import * as bip39 from 'bip39' ;
22import crypto from 'crypto' ;
33import * as HDKey from 'ethereumjs-wallet/hdkey' ;
4- import Swal from 'sweetalert2' ;
54import Web3ProviderEngine from 'web3-provider-engine' ;
65import FixtureSubprovider from 'web3-provider-engine/subproviders/fixture.js' ;
76import RpcSubprovider from 'web3-provider-engine/subproviders/rpc.js' ;
87import HookedWalletSubprovider from 'web3-provider-engine/subproviders/hooked-wallet-ethtx.js' ;
98import networkConfig from './networkConfig' ;
10- import { encryptMnemonic , encryptSecret , decryptMnemonic , decryptSecret } from './utils/encryption' ;
9+ import { encryptMnemonic , decryptMnemonic } from './utils/encryption' ;
1110
1211const STORAGE_SESSION_KEY = 'wallet-session' ;
1312const MNEMONIC_PATH = "m/44'/60'/0'/0/0" ;
1413
15- /**
16- * Fetch encrypted mnemonic from browser's local storage
17- * @method getEncryptedMnemonic
18- * @returns {String } encryptedMnemonic
19- */
20- function getEncryptedMnemonic ( ) {
21- const data = localStorage . getItem ( STORAGE_SESSION_KEY ) ;
22- if ( ! data ) {
23- return Error ( 'User not logged in' ) ;
24- }
25-
26- const { encryptedMnemonic} = JSON . parse ( data ) ;
27- return encryptedMnemonic ;
28- }
29-
30- /**
31- * Prompt for wallet password
32- * @method promptPassword
33- * @returns {Promise<String> } password
34- */
35- async function promptPassword ( ) {
36- const { value : password } = await Swal . fire ( {
37- title : 'Enter your password' ,
38- input : 'password' ,
39- inputPlaceholder : 'Enter your password' ,
40- inputAttributes : {
41- maxlength : 50 ,
42- autocapitalize : 'off' ,
43- autocorrect : 'off'
44- }
45- } ) ;
46-
47- if ( ! password ) {
48- throw new Error ( 'Password not entered' ) ;
49- }
50-
51- return password ;
52- }
53-
54- /**
55- * Get wallet password from encrypted password
56- * @method getPassword
57- * @param address - wallet address
58- * @returns {Promise<String> } password
59- */
60- async function getPassword ( ) {
61- const data = localStorage . getItem ( STORAGE_SESSION_KEY ) ;
62- const address = JSON . parse ( data ) . address ;
63- const encryptedPassword = sessionStorage . getItem ( STORAGE_SESSION_KEY ) ;
64-
65- if ( ! encryptedPassword ) {
66- return promptPassword ( ) ;
67- }
68-
69- return decryptSecret ( address , encryptedPassword ) ;
70- }
71-
7214/**
7315 * `SpringWallet` class
7416 */
@@ -82,7 +24,25 @@ export default class SpringWallet {
8224 throw new Error ( "'network' not defined" ) ;
8325 }
8426 this . network = networkConfig ( network ) ;
85- this . provider = this . initProvider ( network ) ;
27+ this . walletAddress = this . initWalletAddress ( ) ;
28+ this . privateKey = this . initPrivateKey ( ) ;
29+ this . provider = this . initProvider ( this . network ) ;
30+ }
31+
32+ initWalletAddress ( ) {
33+ let walletSession = SpringWallet . getWalletSession ( ) ;
34+ if ( ! walletSession ) {
35+ return null ;
36+ }
37+ return walletSession . address ;
38+ }
39+
40+ initPrivateKey ( ) {
41+ let privateKey = sessionStorage . getItem ( STORAGE_SESSION_KEY ) ;
42+ if ( ! privateKey ) {
43+ return null ;
44+ }
45+ return privateKey ;
8646 }
8747
8848 initProvider ( opts ) {
@@ -97,21 +57,30 @@ export default class SpringWallet {
9757 } )
9858 ) ;
9959
100- opts . getPrivateKey = async ( address , cb ) => {
60+ opts . getPrivateKey = ( address , cb ) => {
10161 if ( address . toLowerCase ( ) === this . walletAddress . toLowerCase ( ) ) {
102- const privKey = this . wallet . getPrivateKey ( ) . toString ( 'hex' ) ;
103- cb ( null , Buffer . from ( privKey , 'hex' ) ) ;
62+ if ( this . privateKey ) {
63+ cb ( null , this . privateKey ) ;
64+ } else if ( this . wallet ) {
65+ const privKey = this . wallet . getPrivateKey ( ) . toString ( 'hex' ) ;
66+ cb ( null , Buffer . from ( privKey , 'hex' ) ) ;
67+ } else {
68+ cb ( 'unlock wallet' ) ;
69+ }
10470 } else {
10571 cb ( 'unknown account' ) ;
10672 }
10773 } ;
10874
109- opts . getAccounts = async ( cb ) => {
110- if ( ! this . wallet ) {
111- await this . unlockWallet ( ) ;
75+ opts . getAccounts = ( cb ) => {
76+ let address ;
77+ if ( this . walletAddress ) {
78+ address = this . walletAddress ;
79+ } else if ( this . wallet ) {
80+ address = this . wallet . getChecksumAddressString ( ) ;
81+ this . walletAddress = address ;
11282 }
113- const address = this . wallet . getChecksumAddressString ( ) ;
114- this . walletAddress = address ;
83+
11584 cb ( false , [ address ] ) ;
11685 } ;
11786
@@ -143,26 +112,6 @@ export default class SpringWallet {
143112 return bip39 . validateMnemonic ( phrase ) ;
144113 }
145114
146- /**
147- * Returns wallet address
148- * @method createWallet
149- * @param {String } 12-words Plain mnemonic phrase
150- * @returns {String } wallet address
151- */
152- static async createWallet ( phrase , password ) {
153- if ( ! bip39 . validateMnemonic ( phrase ) ) {
154- throw new Error ( 'Not a valid bip39 mnemonic' ) ;
155- }
156- const encryptedMnemonic = await encryptMnemonic ( phrase , password ) ;
157- const hdKey = HDKey . fromMasterSeed ( bip39 . mnemonicToSeedSync ( phrase ) ) ;
158- const wallet = hdKey
159- . derivePath ( MNEMONIC_PATH )
160- . deriveChild ( 0 )
161- . getWallet ( ) ;
162- const address = wallet . getChecksumAddressString ( ) ;
163- return { address, encryptedMnemonic} ;
164- }
165-
166115 /**
167116 * Encrypt Plain text mnemonic phrase
168117 * @method encryptMnemonic
@@ -174,14 +123,40 @@ export default class SpringWallet {
174123 return encryptMnemonic ( phrase , password ) ;
175124 }
176125
126+ /**
127+ * Decrypt an encrypted mnemonic with a password
128+ * @method decryptMnemonic
129+ * @param {String } encryptedMnemonic - Hex-encoded string of the encrypted mnemonic
130+ * @param {String } password - Password
131+ * @return {Promise<String> } mnemonic - plain text mnemonic phrase
132+ */
133+ static decryptMnemonic ( encryptedMnemonic , password ) {
134+ return decryptMnemonic ( encryptedMnemonic , password ) ;
135+ }
136+
177137 /**
178138 * Set wallet session in browser's localStorage
179139 * @method setWalletSession
180140 * @param {String } address - derived wallet address
181141 * @param {String } encryptedMnemonic
182142 */
183143 static setWalletSession ( address , encryptedMnemonic ) {
184- localStorage . setItem ( STORAGE_SESSION_KEY , JSON . stringify ( { address, encryptedMnemonic} ) ) ;
144+ localStorage . setItem ( STORAGE_SESSION_KEY , JSON . stringify ( { address, encryptedMnemonic } ) ) ;
145+ }
146+
147+ /**
148+ * Fetch encrypted mnemonic from browser's local storage
149+ * @method getEncryptedMnemonic
150+ * @returns {String } encryptedMnemonic
151+ */
152+ static getWalletSession ( ) {
153+ const data = localStorage . getItem ( STORAGE_SESSION_KEY ) ;
154+ if ( ! data ) {
155+ return null ;
156+ }
157+
158+ const { address, encryptedMnemonic } = JSON . parse ( data ) ;
159+ return { address, encryptedMnemonic } ;
185160 }
186161
187162 /**
@@ -190,7 +165,7 @@ export default class SpringWallet {
190165 * @param path Mnemonic Path
191166 * @returns wallet instance
192167 */
193- async initializeWalletFromMnemonic ( mnemonic ) {
168+ static async initializeWalletFromMnemonic ( mnemonic ) {
194169 const hdKey = await HDKey . fromMasterSeed ( bip39 . mnemonicToSeedSync ( mnemonic ) ) ;
195170 const wallet = await hdKey
196171 . derivePath ( MNEMONIC_PATH )
@@ -199,45 +174,13 @@ export default class SpringWallet {
199174 return wallet ;
200175 }
201176
202- /**
203- * Unlocks a wallet
204- * @method unlockWallet
205- * @param {String } encryptedMnemonic
206- * @returns {Promise<Boolean> }
207- */
208- async unlockWallet ( ) {
209- const password = await getPassword ( ) ;
210- const encryptedMnemonic = getEncryptedMnemonic ( ) ;
211- try {
212- const mnemonic = await decryptMnemonic ( encryptedMnemonic , password ) ;
213- this . wallet = await this . initializeWalletFromMnemonic ( mnemonic ) ;
214- const address = await this . wallet . getChecksumAddressString ( ) ;
215- await encryptSecret ( address , password ) ;
216- return true ;
217- } catch ( error ) {
218- throw new Error ( 'Invalid Password' ) ;
219- }
220- }
221-
222- /**
223- * Reinitialize a wallet with new encrypted mnemonic
224- * checks if the derived wallet address is same
225- * @method reinitializeWallet
226- * @param {String } address - wallet address
227- * @param {String } encryptedMnemonic - new encrypted mnemonic
228- * @returns {Promise<Boolean> }
229- */
230- static async reinitializeWallet ( address , encryptedMnemonic ) {
231- const password = await getPassword ( ) ;
232- const mnemonic = await decryptMnemonic ( encryptedMnemonic , password ) ;
233- const Wallet = await this . initializeWalletFromMnemonic ( mnemonic , MNEMONIC_PATH ) ;
234- const derivedWalletAddress = await Wallet . getChecksumAddressString ( ) ;
235- if ( derivedWalletAddress !== address ) {
236- throw new Error ( 'Different wallet mnemonics' ) ;
237- }
238- SpringWallet . setWalletSession ( address , encryptMnemonic ) ;
239- return true ;
177+ async unlockWallet ( mnemonic ) {
178+ const wallet = await SpringWallet . initializeWalletFromMnemonic ( mnemonic ) ;
179+ this . wallet = wallet ;
180+ this . walletAddress = wallet . getChecksumAddressString ( ) ;
181+ const privKey = wallet . getPrivateKey ( ) . toString ( 'hex' ) ;
182+ this . privateKey = Buffer . from ( privKey , 'hex' ) ;
183+ sessionStorage . setItem ( STORAGE_SESSION_KEY , privKey ) ;
184+ return this . walletAddress ;
240185 }
241186}
242-
243- export { decryptMnemonic } ;
0 commit comments