增加助记词恢复钱包和根据助记词生成帐号的功能
This commit is contained in:
parent
6064f447e6
commit
2b4235449e
@ -14,19 +14,22 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@metamask/eth-sig-util": "^4.0.1",
|
"@metamask/eth-sig-util": "^4.0.1",
|
||||||
"bip39": "^3.0.4",
|
"bip39": "^3.0.4",
|
||||||
|
"crypto-js": "^4.1.1",
|
||||||
"ethereumjs-wallet": "^1.0.2",
|
"ethereumjs-wallet": "^1.0.2",
|
||||||
"web3": "^1.7.4",
|
"web3": "^1.7.4",
|
||||||
"whatwg-fetch": "^3.6.2"
|
"whatwg-fetch": "^3.6.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"assert": "^2.0.0",
|
|
||||||
"buffer": "^6.0.3",
|
|
||||||
"@babel/cli": "^7.12.1",
|
"@babel/cli": "^7.12.1",
|
||||||
"@babel/core": "^7.12.3",
|
"@babel/core": "^7.12.3",
|
||||||
"babel-loader": "^8.1.0",
|
|
||||||
"@babel/preset-env": "^7.12.1",
|
"@babel/preset-env": "^7.12.1",
|
||||||
"@babel/preset-typescript": "^7.12.1",
|
"@babel/preset-typescript": "^7.12.1",
|
||||||
"@babel/runtime": "^7.12.1",
|
"@babel/runtime": "^7.12.1",
|
||||||
|
"@types/aes-js": "^3.1.1",
|
||||||
|
"@types/crypto-js": "^4.1.1",
|
||||||
|
"assert": "^2.0.0",
|
||||||
|
"babel-loader": "^8.1.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"crypto-browserify": "^3.12.0",
|
"crypto-browserify": "^3.12.0",
|
||||||
"https-browserify": "^1.0.0",
|
"https-browserify": "^1.0.0",
|
||||||
"os-browserify": "^0.3.0",
|
"os-browserify": "^0.3.0",
|
||||||
|
37
src/index.ts
37
src/index.ts
@ -11,6 +11,7 @@ import { IAccount, initAccount } from "./data/DataModel";
|
|||||||
import { DataManage } from "./manage/DataManage";
|
import { DataManage } from "./manage/DataManage";
|
||||||
import { WALLET_STORAGE_KEY_NAME } from "./config/constants";
|
import { WALLET_STORAGE_KEY_NAME } from "./config/constants";
|
||||||
import { DEFALUT_TOKENS } from "./config/chain_config";
|
import { DEFALUT_TOKENS } from "./config/chain_config";
|
||||||
|
import { newMnemonic, restoreWalletByMnemonic } from "./manage/WalletManage";
|
||||||
|
|
||||||
|
|
||||||
var global =
|
var global =
|
||||||
@ -88,19 +89,28 @@ export default class JCWallet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.wallet || this.wallet.length === 0) {
|
if (!this.wallet || this.wallet.length === 0) {
|
||||||
// let key = '0xa6c4354fb93a55fb67117969a12465209395ec31089fea9e6e061f873b87a473'
|
// this.createAccount();
|
||||||
// this.wallet.add(key);
|
this.newWallet('111111');
|
||||||
// this.web3.eth.accounts.wallet.save(this.password, WALLET_STORAGE_KEY_NAME);
|
|
||||||
this.createAccount();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public newWallet(password: string) {
|
||||||
|
this.password = password
|
||||||
|
newMnemonic(this.password)
|
||||||
|
this.createAccount()
|
||||||
|
}
|
||||||
|
|
||||||
|
public restoreFromMnemonic(mnemonic: string, password: string) {
|
||||||
|
this.password = password
|
||||||
|
this.wallet.clear()
|
||||||
|
restoreWalletByMnemonic(mnemonic, this.password);
|
||||||
|
this.createAccount()
|
||||||
|
}
|
||||||
|
|
||||||
get currentChain() {
|
get currentChain() {
|
||||||
return this._currentChain
|
return this._currentChain
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
updateCurrentChain(chainId: number) {
|
updateCurrentChain(chainId: number) {
|
||||||
const chainData = this.chainMap.get(chainId)
|
const chainData = this.chainMap.get(chainId)
|
||||||
this._currentChain = chainData
|
this._currentChain = chainData
|
||||||
@ -164,13 +174,14 @@ export default class JCWallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public createAccount() {
|
public createAccount() {
|
||||||
let account = this.web3.eth.accounts.create()
|
// let account = this.web3.eth.accounts.create()
|
||||||
this.wallet.add(account)
|
const index = this.getMaxIdexOfType(0);
|
||||||
|
const accountNew = this.dataManage.newAccount(this.password, index)
|
||||||
|
const account = this.wallet.add(accountNew)
|
||||||
this.wallet.save(this.password, WALLET_STORAGE_KEY_NAME)
|
this.wallet.save(this.password, WALLET_STORAGE_KEY_NAME)
|
||||||
const chain = this.currentChain.id
|
const chain = this.currentChain.id
|
||||||
let data = this.data.find(o => o.address === account.address)
|
let data = this.data.find(o => o.address === account.address)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
const index = this.getMaxIdexOfType(0);
|
|
||||||
const nickname = `Account ${ index + 1 }`
|
const nickname = `Account ${ index + 1 }`
|
||||||
data = initAccount({
|
data = initAccount({
|
||||||
address: account.address,
|
address: account.address,
|
||||||
@ -188,11 +199,7 @@ export default class JCWallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public importAccount(privateKey: string) {
|
public importAccount(privateKey: string) {
|
||||||
let account = this.web3.eth.accounts.privateKeyToAccount(privateKey)
|
const account = this.wallet.add(privateKey);
|
||||||
if (this.wallet[account.address]) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
this.wallet.add(account);
|
|
||||||
const chain = this.currentChain.id
|
const chain = this.currentChain.id
|
||||||
let data = this.data.find(o => o.address === account.address)
|
let data = this.data.find(o => o.address === account.address)
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@ -286,4 +293,4 @@ export * from './config/chain_config'
|
|||||||
export * from './util/number.util'
|
export * from './util/number.util'
|
||||||
export * from './util/wallet.util'
|
export * from './util/wallet.util'
|
||||||
export * from "./data/DataModel";
|
export * from "./data/DataModel";
|
||||||
export * from './config/chain_config';
|
export * from './config/chain_config';
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import { IAccount } from "../data/DataModel";
|
import { IAccount } from "../data/DataModel";
|
||||||
import { singleton } from "../decorator/singleton.decorator";
|
import { singleton } from "../decorator/singleton.decorator";
|
||||||
|
import { aesDecrypt, aesEncrypt } from "../util/crypto.util";
|
||||||
|
|
||||||
const LOCAL_ACCOUNT_DATAS = 'local_account_datas'
|
const LOCAL_ACCOUNT_DATAS = 'local_account_datas'
|
||||||
|
const LOCAL_WALLET_MNEMONIC = 'local_wallet_mnemonic'
|
||||||
@singleton
|
@singleton
|
||||||
export class DataManage{
|
export class DataManage{
|
||||||
public loadData(){
|
public loadData(){
|
||||||
@ -21,4 +23,21 @@ export class DataManage{
|
|||||||
const dataStr = JSON.stringify(datas)
|
const dataStr = JSON.stringify(datas)
|
||||||
localStorage.setItem(LOCAL_ACCOUNT_DATAS, dataStr)
|
localStorage.setItem(LOCAL_ACCOUNT_DATAS, dataStr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public loadMnemonic(password: string) {
|
||||||
|
let dataStr: string = localStorage.getItem(LOCAL_WALLET_MNEMONIC)
|
||||||
|
if (dataStr) {
|
||||||
|
dataStr = aesDecrypt(dataStr, password)
|
||||||
|
}
|
||||||
|
return dataStr
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public saveMnemonic(mnemonic: string, password: string) {
|
||||||
|
const dataStr = aesEncrypt(mnemonic, password);
|
||||||
|
localStorage.setItem(LOCAL_WALLET_MNEMONIC, dataStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
22
src/manage/WalletManage.ts
Normal file
22
src/manage/WalletManage.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { hdkey } from 'ethereumjs-wallet'
|
||||||
|
import { generateMnemonic, mnemonicToSeedSync } from "bip39";
|
||||||
|
|
||||||
|
|
||||||
|
export function newAccount(password: string, index: number) {
|
||||||
|
const mnemonic = this.loadMnemonic(password)
|
||||||
|
const seed = mnemonicToSeedSync(mnemonic)
|
||||||
|
const hdWallet = hdkey.fromMasterSeed(seed)
|
||||||
|
const keyPair1 = hdWallet.derivePath(`m/44'/60'/0'/0/${index}`)
|
||||||
|
const w1 = keyPair1.getWallet()
|
||||||
|
return {address: w1.getAddressString(), privateKey: w1.getPrivateKeyString()}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function newMnemonic(password: string) {
|
||||||
|
let mnemonic = generateMnemonic()
|
||||||
|
this.saveMnemonic(mnemonic, password)
|
||||||
|
return mnemonic
|
||||||
|
}
|
||||||
|
|
||||||
|
export function restoreWalletByMnemonic(mnemonic: string, password: string) {
|
||||||
|
this.saveMnemonic(mnemonic, password)
|
||||||
|
}
|
32
src/util/crypto.util.ts
Normal file
32
src/util/crypto.util.ts
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import { AES, enc, mode, pad } from 'crypto-js';
|
||||||
|
import sha256 from 'crypto-js/sha256'
|
||||||
|
|
||||||
|
function generateIV(password: string) {
|
||||||
|
const key = sha256(password).toString();
|
||||||
|
const keyHex = enc.Base64.parse(key);
|
||||||
|
const ivHex = keyHex.clone();
|
||||||
|
ivHex.sigBytes = 16;
|
||||||
|
ivHex.words.splice(4);
|
||||||
|
return {keyHex,ivHex}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aesEncrypt(text: string, password: string) {
|
||||||
|
const {keyHex, ivHex} = generateIV(password);
|
||||||
|
const messageHex = enc.Utf8.parse(text);
|
||||||
|
const encrypted = AES.encrypt(messageHex, keyHex, {
|
||||||
|
"iv": ivHex,
|
||||||
|
"mode": mode.CBC,
|
||||||
|
"padding": pad.Pkcs7
|
||||||
|
});
|
||||||
|
return encrypted.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function aesDecrypt(encryptedText: string, password: string) {
|
||||||
|
const {keyHex, ivHex} = generateIV(password);
|
||||||
|
const decrypt = AES.decrypt(encryptedText, keyHex, {
|
||||||
|
"iv": ivHex,
|
||||||
|
"mode": mode.CBC,
|
||||||
|
"padding": pad.Pkcs7
|
||||||
|
});
|
||||||
|
return enc.Utf8.stringify(decrypt);
|
||||||
|
}
|
15
yarn.lock
15
yarn.lock
@ -1204,6 +1204,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
defer-to-connect "^1.0.1"
|
defer-to-connect "^1.0.1"
|
||||||
|
|
||||||
|
"@types/aes-js@^3.1.1":
|
||||||
|
version "3.1.1"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/aes-js/-/aes-js-3.1.1.tgz#34b3978122310c135de4b377270d1d65676fae28"
|
||||||
|
integrity sha512-SDSGgXT3LRCH6qMWk8OHT1vLSVNuHNvCpKCx2/TYtQMbMGGgxJC9fspwSkQjqzRagrWnCrxuLL3jMNXLXHHvSw==
|
||||||
|
|
||||||
"@types/bn.js@^4.11.3":
|
"@types/bn.js@^4.11.3":
|
||||||
version "4.11.6"
|
version "4.11.6"
|
||||||
resolved "https://registry.npmmirror.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
|
resolved "https://registry.npmmirror.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c"
|
||||||
@ -1218,6 +1223,11 @@
|
|||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/crypto-js@^4.1.1":
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.npmmirror.com/@types/crypto-js/-/crypto-js-4.1.1.tgz#602859584cecc91894eb23a4892f38cfa927890d"
|
||||||
|
integrity sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==
|
||||||
|
|
||||||
"@types/json-schema@^7.0.5":
|
"@types/json-schema@^7.0.5":
|
||||||
version "7.0.11"
|
version "7.0.11"
|
||||||
resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
resolved "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||||
@ -2381,6 +2391,11 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0, crypto-browserify@^3.12.0:
|
|||||||
randombytes "^2.0.0"
|
randombytes "^2.0.0"
|
||||||
randomfill "^1.0.3"
|
randomfill "^1.0.3"
|
||||||
|
|
||||||
|
crypto-js@^4.1.1:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.npmmirror.com/crypto-js/-/crypto-js-4.1.1.tgz#9e485bcf03521041bd85844786b83fb7619736cf"
|
||||||
|
integrity sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==
|
||||||
|
|
||||||
cyclist@^1.0.1:
|
cyclist@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.npmmirror.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
resolved "https://registry.npmmirror.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user