From 8afb08936c585899da1db84a1c7a1db6177b8ab5 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Thu, 30 Jul 2020 10:51:13 +1000 Subject: [PATCH 1/6] Add support for creating hardware wallet --- .../main-process/modules/wallet-rpc.js | 40 +++++++++++++++---- src/i18n/en-us.js | 2 + src/pages/wallet-select/create.vue | 20 ++++++---- src/store/gateway/state.js | 3 +- 4 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src-electron/main-process/modules/wallet-rpc.js b/src-electron/main-process/modules/wallet-rpc.js index a97087c..76d7757 100644 --- a/src-electron/main-process/modules/wallet-rpc.js +++ b/src-electron/main-process/modules/wallet-rpc.js @@ -270,7 +270,7 @@ export class WalletRPC { break; case "create_wallet": - this.createWallet(params.name, params.password, params.language); + this.createWallet(params.name, params.password, params.language, params.hardware_wallet); break; case "restore_wallet": @@ -507,13 +507,19 @@ export class WalletRPC { }); } - createWallet(filename, password, language) { + isHardwareWallet(filename) { + let hwfile = path.join(this.wallet_dir, filename + ".hwdev.txt"); + return fs.existsSync(hwfile); + } + + createWallet(filename, password, language, hardware_wallet) { // Reset the status error this.sendGateway("reset_wallet_error"); this.sendRPC("create_wallet", { filename, password, - language + language, + hardware_wallet: !!hardware_wallet }).then(data => { if (data.hasOwnProperty("error")) { this.sendGateway("set_wallet_error", { status: data.error }); @@ -700,6 +706,10 @@ export class WalletRPC { errorOnExist: true }); } + + if (fs.existsSync(import_path + ".hwdev.txt")) { + fs.copySync(import_path + ".hwdev.txt", destination + ".hwdev.txt", fs.constants.COPYFILE_EXCL); + } } catch (e) { this.sendGateway("set_wallet_error", { status: { @@ -787,6 +797,10 @@ export class WalletRPC { } } + if (this.isHardwareWallet(filename)) { + wallet.info.hardware_wallet = true; + } + this.saveWallet().then(() => { let address_txt_path = path.join( this.wallet_dir, @@ -833,6 +847,9 @@ export class WalletRPC { }); } + const hardware_wallet_file = path.join(this.wallet_dir, filename + ".hwdev.txt"); + const hardware_wallet = fs.existsSync(hardware_wallet_file); + // store hash of the password so we can check against it later when requesting private keys, or for sending txs this.wallet_state.password_hash = crypto .pbkdf2Sync(password, this.auth[2], 1000, 64, "sha512") @@ -844,6 +861,12 @@ export class WalletRPC { this.purchasedNames = {}; + this.sendGateway("set_wallet_data", { + info: { + hardware_wallet + } + }); + // Check if we have a view only wallet by querying the spend key this.sendRPC("query_key", { key_type: "spend_key" }).then(data => { if (data.hasOwnProperty("error") || !data.hasOwnProperty("result")) { @@ -2665,16 +2688,19 @@ export class WalletRPC { return; } - // Exclude all files without a keys extension - if (path.extname(filename) !== ".keys") return; + // Exclude all files without a keys or .hwdev.txt extensions + const hardware_wallet_ext = ".hwdev.txt"; + const hardware_wallet = filename.includes(hardware_wallet_ext); + if (path.extname(filename) !== ".keys" && !hardware_wallet) return; - const wallet_name = path.parse(filename).name; + const wallet_name = path.parse(filename).name.split(".")[0]; if (!wallet_name) return; let wallet_data = { name: wallet_name, address: null, - password_protected: null + password_protected: null, + hardware_wallet }; if ( diff --git a/src/i18n/en-us.js b/src/i18n/en-us.js index 41a7816..02030cc 100644 --- a/src/i18n/en-us.js +++ b/src/i18n/en-us.js @@ -515,6 +515,8 @@ export default { "Purchase or update an ONS record. If you purchase a name, it may take a minute or two for it to show up in the list.", onsDescription: "Here you can find all the ONS names owned by this wallet. Decrypting a record you own will return the name and value of that ONS record.", + hardwareWallet: "Hardware wallet", + "Purchase or update a name for a Session ID. If you purchase a name, it may take a minute or two for it to show up in the list.", loadingSettings: "Loading settings", oxenBalance: "Balance", lokinetNameDescription: diff --git a/src/pages/wallet-select/create.vue b/src/pages/wallet-select/create.vue index dcb2ca5..cc518b6 100644 --- a/src/pages/wallet-select/create.vue +++ b/src/pages/wallet-select/create.vue @@ -50,12 +50,17 @@ /> - + + + + + + + + + + + @@ -88,7 +93,8 @@ export default { name: "", language: languageOptions[0].value, password: "", - password_confirm: "" + password_confirm: "", + hardware_wallet: false }, languageOptions }; diff --git a/src/store/gateway/state.js b/src/store/gateway/state.js index cee838c..826fb14 100644 --- a/src/store/gateway/state.js +++ b/src/store/gateway/state.js @@ -33,7 +33,8 @@ export default { height: 0, balance: 0, unlocked_balance: 0, - view_only: false + view_only: false, + hardware_wallet: false }, secret: { mnemonic: "", From 1b6960c636502c2802ab6654a9ff7a7011d9b803 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Thu, 30 Jul 2020 11:27:13 +1000 Subject: [PATCH 2/6] Display hardware wallets separetely --- .../main-process/modules/wallet-rpc.js | 14 +- src/components/wallet_list_item.vue | 91 +++++++++++++ src/i18n/en-us.js | 6 + src/pages/wallet-select/index.vue | 127 +++++------------- 4 files changed, 138 insertions(+), 100 deletions(-) create mode 100644 src/components/wallet_list_item.vue diff --git a/src-electron/main-process/modules/wallet-rpc.js b/src-electron/main-process/modules/wallet-rpc.js index 76d7757..24bbe2a 100644 --- a/src-electron/main-process/modules/wallet-rpc.js +++ b/src-electron/main-process/modules/wallet-rpc.js @@ -2688,19 +2688,17 @@ export class WalletRPC { return; } - // Exclude all files without a keys or .hwdev.txt extensions - const hardware_wallet_ext = ".hwdev.txt"; - const hardware_wallet = filename.includes(hardware_wallet_ext); - if (path.extname(filename) !== ".keys" && !hardware_wallet) return; + // Exclude all files without keys + if (path.extname(filename) !== ".keys") return; - const wallet_name = path.parse(filename).name.split(".")[0]; + const wallet_name = path.parse(filename).name; if (!wallet_name) return; let wallet_data = { name: wallet_name, address: null, password_protected: null, - hardware_wallet + hardware_wallet: false }; if ( @@ -2729,6 +2727,10 @@ export class WalletRPC { } } + if (fs.existsSync(path.join(this.wallet_dir, wallet_name + ".hwdev.txt"))) { + wallet_data.hardware_wallet = true; + } + wallets.list.push(wallet_data); } catch (e) { // Something went wrong diff --git a/src/components/wallet_list_item.vue b/src/components/wallet_list_item.vue new file mode 100644 index 0000000..f119a71 --- /dev/null +++ b/src/components/wallet_list_item.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/src/i18n/en-us.js b/src/i18n/en-us.js index 02030cc..0d4a2bc 100644 --- a/src/i18n/en-us.js +++ b/src/i18n/en-us.js @@ -516,6 +516,7 @@ export default { onsDescription: "Here you can find all the ONS names owned by this wallet. Decrypting a record you own will return the name and value of that ONS record.", hardwareWallet: "Hardware wallet", + hardwareWallets: "Hardware wallets", "Purchase or update a name for a Session ID. If you purchase a name, it may take a minute or two for it to show up in the list.", loadingSettings: "Loading settings", oxenBalance: "Balance", @@ -545,8 +546,13 @@ export default { recentIncomingTransactionsToAddress: "Recent incoming transactions to this address", recentTransactionsWithAddress: "Recent transactions with this address", +<<<<<<< HEAD rescanModalDescription: "Select full rescan or rescan of spent outputs only.", +======= + regularWallets: "Regular wallets", + rescanModalDescription: "Select full rescan or rescan of spent outputs only.", +>>>>>>> Display hardware wallets separetely saveSeedWarning: "Please copy and save these in a secure location!", saveToAddressBook: "Save to address book", seedWords: "Seed words", diff --git a/src/pages/wallet-select/index.vue b/src/pages/wallet-select/index.vue index 32d7efd..d81c375 100644 --- a/src/pages/wallet-select/index.vue +++ b/src/pages/wallet-select/index.vue @@ -1,90 +1,40 @@