diff --git a/locale/de/translation.js b/locale/de/translation.js
index 877be43c0..45bc1674a 100644
--- a/locale/de/translation.js
+++ b/locale/de/translation.js
@@ -66,9 +66,16 @@ export const de_translation = {
'Jeder mit einer Kopie der Phrase hat Zugriff auf deine Brieftasche.', //Anyone with a copy of it can access all of your funds.
doNotShare: 'Teile Sie unter keinen Umständen mit dritten.', //Do NOT share it with anybody.
digitalStoreNotAdvised: 'Es wird empfohlen diese nicht digital zu sichern', //It is NOT advised to store this digitally.
- optionalPassphrase: 'Optionale Pass Phrase', //Optional Passphrase
+ optionalPassphrase: 'Optionale Pass Phrase (BIP39)', //Optional Passphrase (BIP39)
writtenDown: 'Ich bestätige, dass ich die Seed Phrase notiert habe', //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: '', //Seed Phrase is valid!
+ importSeedError: '', //Seed Phrase is invalid!
+ importSeedErrorSize: '', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo: '', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip: '', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: 'Erste Schritte', //Getting Started
secureYourWallet: 'Verschlüssel deine Geldbörse', //Secure your wallet
@@ -181,6 +188,8 @@ export const de_translation = {
settingsAnalytics: 'Wähle die verwendeten Analysedaten dieser Sitzung', //Choose your analytics contribution level:
settingsToggleDebug: 'Debug Modus', //Debug Mode
settingsToggleTestnet: 'Testnet Modus', //Testnet Mode
+ settingsToggleAdvancedMode: '', //Advanced Mode
+ settingsToggleAdvancedModeSubtext: '', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Transparency Report
transparencyReport: 'Transparenz-Bericht', //Transparency Report
diff --git a/locale/en/translation.js b/locale/en/translation.js
index 9484381dc..e5bd621ab 100644
--- a/locale/en/translation.js
+++ b/locale/en/translation.js
@@ -63,9 +63,18 @@ export const en_translation = {
'Anyone with a copy of it can access all of your funds.', //
doNotShare: 'Do NOT share it with anyone.', //
digitalStoreNotAdvised: 'It is NOT advised to store this digitally.', //
- optionalPassphrase: 'Optional Passphrase', //
+ optionalPassphrase: 'Optional Passphrase (BIP39)', //
writtenDown: 'I have written down my seed phrase', //
+ // Seed Phrase Import
+ importSeedValid: 'Seed Phrase is valid!', //
+ importSeedError: 'Seed Phrase is invalid!', //
+ importSeedErrorSize: 'A Seed Phrase should be 12 or 24 words long!', //
+ importSeedErrorTypo:
+ 'Seed Phrase contains typing errors! Check your input carefully', //
+ importSeedErrorSkip:
+ 'Seed Phrase appears invalid, but the warning was skipped by the user', //
+
// Wallet Dashboard
gettingStarted: 'Getting Started', //
secureYourWallet: 'Secure your wallet', //
@@ -182,6 +191,9 @@ export const en_translation = {
settingsAnalytics: 'Choose your analytics contribution level:', //
settingsToggleDebug: 'Debug Mode', //
settingsToggleTestnet: 'Testnet Mode', //
+ settingsToggleAdvancedMode: 'Advanced Mode', //
+ settingsToggleAdvancedModeSubtext:
+ 'This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!', //
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: "Your {network} wallet isn't saved!", //
diff --git a/locale/fr/translation.js b/locale/fr/translation.js
index a1b16b34f..e4df4d7f9 100644
--- a/locale/fr/translation.js
+++ b/locale/fr/translation.js
@@ -66,9 +66,16 @@ export const fr_translation = {
doNotShare: 'Ne le partagez avec personne.', //Do NOT share it with anybody.
digitalStoreNotAdvised:
'NON il est conseillé de les stocker sous forme numérique.', //It is NOT advised to store this digitally.
- optionalPassphrase: 'Phrase mot de passe Facultatif', //Optional Passphrase
+ optionalPassphrase: 'Phrase mot de passe Facultatif (BIP39)', //Optional Passphrase
writtenDown: "J'ai écrit ma phrase d'introduction", //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: '', //Seed Phrase is valid!
+ importSeedError: '', //Seed Phrase is invalid!
+ importSeedErrorSize: '', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo: '', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip: '', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: 'Démarrer', //Getting Started
secureYourWallet: 'Protégez votre portefeuille', //Secure your wallet
@@ -181,6 +188,8 @@ export const fr_translation = {
settingsAnalytics: "Choisissez votre niveau d'analyse :", //Choose your analytics contribution level:
settingsToggleDebug: 'Mode de débogage', //Debug Mode
settingsToggleTestnet: 'Mode testnet', //Testnet Mode
+ settingsToggleAdvancedMode: '', //Advanced Mode
+ settingsToggleAdvancedModeSubtext: '', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: '', //Your {network} wallet isn\'t saved!
diff --git a/locale/ph/translation.js b/locale/ph/translation.js
index 5d856a17e..672b2f35b 100644
--- a/locale/ph/translation.js
+++ b/locale/ph/translation.js
@@ -67,9 +67,16 @@ export const ph_translation = {
doNotShare: 'WAG mo itong ibibigay kahit kanino', //Do NOT share it with anybody.
digitalStoreNotAdvised:
'Ito ay HINDI payo upang itago ito digitally', //It is NOT advised to store this digitally.
- optionalPassphrase: 'Optional Passphrase', //Optional Passphrase
+ optionalPassphrase: 'Optional Passphrase (BIP39)', //Optional Passphrase
writtenDown: 'Isinulat ko na ang aking seed phrase', //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: '', //Seed Phrase is valid!
+ importSeedError: '', //Seed Phrase is invalid!
+ importSeedErrorSize: '', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo: '', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip: '', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: 'Magsimula', //Getting Started
secureYourWallet: 'I-secure ang iyong wallet', //Secure your wallet
@@ -182,6 +189,8 @@ export const ph_translation = {
settingsAnalytics: 'Pumili ng iyong analytics contribution level:', //Choose your analytics contribution level:
settingsToggleDebug: 'Debug Mode', //Debug Mode
settingsToggleTestnet: 'Testnet Mode', //Testnet Mode
+ settingsToggleAdvancedMode: '', //Advanced Mode
+ settingsToggleAdvancedModeSubtext: '', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: '', //Your {network} wallet isn\'t saved!
diff --git a/locale/pt-br/translation.js b/locale/pt-br/translation.js
index 1a3262d27..1e7bb99d9 100644
--- a/locale/pt-br/translation.js
+++ b/locale/pt-br/translation.js
@@ -66,9 +66,16 @@ export const pt_br_translation = {
doNotShare: 'NÃO a compartilhe com ninguém.', //Do NOT share it with anybody.
digitalStoreNotAdvised:
'NÃO é aconselhável armazená-la digitalmente.', //It is NOT advised to store this digitally.
- optionalPassphrase: 'Frasse-Passe Opcional', //Optional Passphrase
+ optionalPassphrase: 'Frasse-Passe Opcional (BIP39)', //Optional Passphrase
writtenDown: 'Eu escrevi a minha Seed Phrase', //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: '', //Seed Phrase is valid!
+ importSeedError: '', //Seed Phrase is invalid!
+ importSeedErrorSize: '', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo: '', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip: '', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: 'Começar', //Getting Started
secureYourWallet: 'Proteja a sua carteira', //Secure your wallet
@@ -182,6 +189,8 @@ export const pt_br_translation = {
settingsAnalytics: 'Escolha o seu nível de contribuição analítica:', //Choose your analytics contribution level:
settingsToggleDebug: 'Modo de depuração', //Debug Mode
settingsToggleTestnet: 'Modo Testnet', //Testnet Mode
+ settingsToggleAdvancedMode: '', //Advanced Mode
+ settingsToggleAdvancedModeSubtext: '', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: '', //Your {network} wallet isn\'t saved!
diff --git a/locale/pt-pt/translation.js b/locale/pt-pt/translation.js
index 1ffefc698..59ad33f10 100644
--- a/locale/pt-pt/translation.js
+++ b/locale/pt-pt/translation.js
@@ -65,9 +65,16 @@ export const pt_pt_translation = {
doNotShare: 'NÃO a compartilhe com ninguém.', //Do NOT share it with anybody.
digitalStoreNotAdvised:
'NÃO é aconselhável armazená-lo digitalmente.', //It is NOT advised to store this digitally.
- optionalPassphrase: 'Frase Senha Opcional', //Optional Passphrase
+ optionalPassphrase: 'Frase Senha Opcional (BIP39)', //Optional Passphrase
writtenDown: 'Eu escrevi a minha frase-inicial', //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: '', //Seed Phrase is valid!
+ importSeedError: '', //Seed Phrase is invalid!
+ importSeedErrorSize: '', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo: '', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip: '', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: 'A Começar', //Getting Started
secureYourWallet: 'Proteja a sua carteira', //Secure your wallet
@@ -181,6 +188,8 @@ export const pt_pt_translation = {
settingsAnalytics: 'Escolha o seu nível de contribuição analítica:', //Choose your analytics contribution level:
settingsToggleDebug: 'Modo de depuração', //Debug Mode
settingsToggleTestnet: 'Modo Testnet', //Testnet Mode
+ settingsToggleAdvancedMode: '', //Advanced Mode
+ settingsToggleAdvancedModeSubtext: '', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: '', //Your {network} wallet isn\'t saved!
diff --git a/locale/template/translation.js b/locale/template/translation.js
index a99d67995..63a85d736 100644
--- a/locale/template/translation.js
+++ b/locale/template/translation.js
@@ -78,9 +78,16 @@ var translation = {
doNotShareWarning: '', //Anyone with a copy of it can access all of your funds.
doNotShare: '', //Do NOT share it with anybody.
digitalStoreNotAdvised: '', //It is NOT advised to store this digitally.
- optionalPassphrase: '', //Optional Passphrase
+ optionalPassphrase: '', //Optional Passphrase (BIP39)
writtenDown: '', //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: '', //Seed Phrase is valid!
+ importSeedError: '', //Seed Phrase is invalid!
+ importSeedErrorSize: '', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo: '', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip: '', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: '', //Getting Started
secureYourWallet: '', //Secure your wallet
@@ -188,6 +195,8 @@ var translation = {
settingsAnalytics: '', //Choose your analytics contribution level:
settingsToggleDebug: '', //Debug Mode
settingsToggleTestnet: '', //Testnet Mode
+ settingsToggleAdvancedMode: '', //Advanced Mode
+ settingsToggleAdvancedModeSubtext: '', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: '', //Your {network} wallet isn\'t saved!
diff --git a/locale/uwu/translation.js b/locale/uwu/translation.js
index 744d39214..ec83afd0d 100644
--- a/locale/uwu/translation.js
+++ b/locale/uwu/translation.js
@@ -65,9 +65,18 @@ export const uwu_translation = {
doNotShare: 'Do NOT share it with anyuwu.', //Do NOT share it with anybody.
digitalStoreNotAdvised:
'It is NAWT advised to store this digitally.', //It is NOT advised to store this digitally.
- optionalPassphrase: 'Optional Passphwase', //Optional Passphrase
+ optionalPassphrase: 'Optional Passphwase (BIP39)', //Optional Passphrase
writtenDown: 'I haz written down my seed phrase', //I have written down my seed phrase
+ // Seed Phrase Import
+ importSeedValid: 'Seed Phwase iz valid!', //Seed Phrase is valid!
+ importSeedError: 'Seed Phwase iz invalid!', //Seed Phrase is invalid!
+ importSeedErrorSize: 'A Seed Phwase shwould be 12 or 24 words long!', //A Seed Phrase should be 12 or 24 words long!
+ importSeedErrorTypo:
+ 'Seed Phwase contains typing ewrrors! Check ur input carefully', //Seed Phrase contains typing errors! Check your input carefully
+ importSeedErrorSkip:
+ 'Seed Phwase appears invalid, but da warning was skipped by da user', //Seed Phrase appears invalid, but the warning was skipped by the user
+
// Wallet Dashboard
gettingStarted: 'Getting Stwarted', //Getting Started
secureYourWallet: 'Secure ur wawwet', //Secure your wallet
@@ -185,6 +194,9 @@ export const uwu_translation = {
settingsAutoSelectNet: 'Auto-select Expwowers and Nowodes', // Auto-select Explorers and Nodes
settingsToggleDebug: 'Debug Mowode', //Debug Mode
settingsToggleTestnet: 'Testnet Mowode', //Testnet Mode
+ settingsToggleAdvancedMode: 'Advwanced Mowode', //Advanced Mode
+ settingsToggleAdvancedModeSubtext:
+ 'Dis unlocks deeper fwunctionality and cuwustomisatwion, but may be oveuhwhelming and potentially dangerwus for unexperienced bakas!', //This unlocks deeper functionality and customisation, but may be overwhelming and potentially dangerous for unexperienced users!
// Network switching (mainnet <---> testnet)
netSwitchUnsavedWarningTitle: "Ur {network} wawwet isn't saved!", //Your {network} wallet isn\'t saved!
diff --git a/scripts/global.js b/scripts/global.js
index d3a6f345c..777445bea 100644
--- a/scripts/global.js
+++ b/scripts/global.js
@@ -22,6 +22,7 @@ import {
setColdStakingAddress,
strColdStakingAddress,
nDisplayDecimals,
+ fAdvancedMode,
} from './settings.js';
import { createAndSendTransaction, signTransaction } from './transactions.js';
import {
@@ -319,6 +320,7 @@ export async function start() {
domVersion: document.getElementById('version'),
domFlipdown: document.getElementById('flipdown'),
domTestnetToggler: document.getElementById('testnetToggler'),
+ domAdvancedModeToggler: document.getElementById('advancedModeToggler'),
};
await i18nStart();
await loadImages();
@@ -1529,19 +1531,28 @@ export async function accessOrImportWallet() {
*
* Useful for adjusting the input types or displaying password prompts depending on the import scheme
*/
-export async function onPrivateKeyChanged() {
+export async function guiUpdateImportInput() {
if (await hasEncryptedWallet()) return;
// Check whether the string is Base64 (would likely be an MPW-encrypted import)
// and it doesn't have any spaces (would be a mnemonic seed)
- const fContainsSpaces = doms.domPrivKey.value.includes(' ');
+ const fContainsSpaces = doms.domPrivKey.value.trim().includes(' ');
+
+ // If this could require a Seed Passphrase (BIP39 Passphrase) and Advanced Mode is enabled
+ // ...or if this is an Encrypted Import (Encrypted Base64 MPW key)
+ const fBIP39Passphrase = fContainsSpaces && fAdvancedMode;
doms.domPrivKeyPassword.hidden =
(doms.domPrivKey.value.length < 128 ||
!isBase64(doms.domPrivKey.value)) &&
- !fContainsSpaces;
+ !fBIP39Passphrase;
doms.domPrivKeyPassword.placeholder = fContainsSpaces
? translation.optionalPassphrase
: translation.password;
+
+ // If the "Import Password/Passphrase" is hidden, we'll also wipe it's input, in the
+ // ... edge-case that a passphrase was entered, then the import key had changed.
+ if (doms.domPrivKeyPassword.hidden) doms.domPrivKeyPassword.value = '';
+
// Uncloak the private input IF spaces are detected, to make Seed Phrases easier to input and verify
doms.domPrivKey.setAttribute('type', fContainsSpaces ? 'text' : 'password');
}
diff --git a/scripts/index.js b/scripts/index.js
index 9187e943d..6610efcee 100644
--- a/scripts/index.js
+++ b/scripts/index.js
@@ -19,7 +19,7 @@ export {
accessOrImportWallet,
guiImportWallet,
guiSetColdStakingAddress,
- onPrivateKeyChanged,
+ guiUpdateImportInput,
toClipboard,
toggleExportUI,
wipePrivateData,
@@ -46,7 +46,12 @@ export {
govVote,
} from './global.js';
export { generateWallet, getNewAddress, importWallet } from './wallet.js';
-export { toggleTestnet, toggleDebug, toggleAutoSwitch } from './settings.js';
+export {
+ toggleTestnet,
+ toggleDebug,
+ toggleAutoSwitch,
+ toggleAdvancedMode,
+} from './settings.js';
export {
createTxGUI,
undelegateGUI,
diff --git a/scripts/settings.js b/scripts/settings.js
index 23b8ed361..9beaf8bc7 100644
--- a/scripts/settings.js
+++ b/scripts/settings.js
@@ -2,6 +2,7 @@ import {
doms,
getBalance,
getStakingBalance,
+ guiUpdateImportInput,
mempool,
refreshChainData,
renderActivityGUI,
@@ -52,6 +53,8 @@ export let fAutoSwitch = true;
export let strColdStakingAddress = 'SdgQDpS8jDRJDX8yK8m9KnTMarsE84zdsy';
/** The decimals to display for the wallet balance */
export let nDisplayDecimals = 2;
+/** A mode which configures MPW towards Advanced users, with low-level feature access and less restrictions (Potentially dangerous) */
+export let fAdvancedMode = false;
let transparencyReport;
@@ -88,6 +91,10 @@ export class Settings {
* @type {number} The decimals to display for the wallet balance
*/
displayDecimals;
+ /**
+ * @type {boolean} Whether Advanced Mode is enabled or disabled
+ */
+ advancedMode;
constructor({
analytics,
explorer,
@@ -97,6 +104,7 @@ export class Settings {
translation = '',
displayCurrency = 'usd',
displayDecimals = nDisplayDecimals,
+ advancedMode = false,
} = {}) {
this.analytics = analytics;
this.explorer = explorer;
@@ -106,6 +114,7 @@ export class Settings {
this.translation = translation;
this.displayCurrency = displayCurrency;
this.displayDecimals = displayDecimals;
+ this.advancedMode = advancedMode;
}
}
@@ -196,15 +205,22 @@ export async function start() {
coldAddress,
displayCurrency,
displayDecimals,
+ advancedMode,
} = await database.getSettings();
// Set the Cold Staking address
strColdStakingAddress = coldAddress;
// Set any Toggles to their default or DB state
+ // Network Auto-Switch
fAutoSwitch = autoswitch;
doms.domAutoSwitchToggle.checked = fAutoSwitch;
+ // Advanced Mode
+ fAdvancedMode = advancedMode;
+ doms.domAdvancedModeToggler.checked = fAdvancedMode;
+ await configureAdvancedMode();
+
// Set the display currency
strCurrency = doms.domCurrencySelect.value = displayCurrency;
@@ -620,3 +636,29 @@ async function fillNodeSelect() {
// And update the UI to reflect them
doms.domNodeSelect.value = cNode.url;
}
+
+/**
+ * Toggle Advanced Mode at runtime and in DB
+ */
+export async function toggleAdvancedMode() {
+ fAdvancedMode = !fAdvancedMode;
+
+ // Configure the app accordingly
+ await configureAdvancedMode();
+
+ // Update the setting in the DB
+ const database = await Database.getInstance();
+ await database.setSettings({ advancedMode: fAdvancedMode });
+}
+
+/**
+ * Configure the app functionality and UI for the current mode
+ */
+async function configureAdvancedMode() {
+ // Re-render the Import Input UI
+ await guiUpdateImportInput();
+
+ // Hide or Show the "Mnemonic Passphrase" in the Seed Creation modal, and reset it's input
+ doms.domMnemonicModalPassphrase.value = '';
+ doms.domMnemonicModalPassphrase.hidden = !fAdvancedMode;
+}
diff --git a/scripts/wallet.js b/scripts/wallet.js
index 0c1d52727..fc91fbe76 100644
--- a/scripts/wallet.js
+++ b/scripts/wallet.js
@@ -38,6 +38,7 @@ import * as jdenticon from 'jdenticon';
import { Database } from './database.js';
import { guiRenderCurrentReceiveModal } from './contacts-book.js';
import { Account } from './accounts.js';
+import { debug, fAdvancedMode } from './settings.js';
export let fWalletLoaded = false;
@@ -657,39 +658,57 @@ export async function importWallet({
doms.domPrivKey.value = '';
doms.domPrivKeyPassword.value = '';
- if (await verifyMnemonic(privateImportValue)) {
- // Generate our masterkey via Mnemonic Phrase
+ // Clean and verify the Seed Phrase (if one exists)
+ const cPhraseValidator = await cleanAndVerifySeedPhrase(
+ privateImportValue,
+ true
+ );
+
+ // If Debugging is enabled, show what the validator returned
+ if (debug) {
+ const fnLog = cPhraseValidator.ok ? console.log : console.warn;
+ fnLog('Seed Import Validator: ' + cPhraseValidator.msg);
+ }
+
+ // If the Seed is OK, proceed
+ if (cPhraseValidator.ok) {
+ // Generate our HD MasterKey with the cleaned (Mnemonic) Seed Phrase
const seed = await mnemonicToSeed(
- privateImportValue,
+ cPhraseValidator.phrase,
passphrase
);
await setMasterKey(new HdMasterKey({ seed }));
+ } else if (cPhraseValidator.phrase.includes(' ')) {
+ // The Phrase Validator failed, but the input contains at least one space; possibly a Seed Typo?
+ return createAlert('warning', cPhraseValidator.msg, 5000);
} else {
- // Public Key Derivation
+ // The input definitely isn't a seed, so we'll try every other import method
try {
+ // XPub import (HD view only)
if (isXPub(privateImportValue)) {
await setMasterKey(
new HdMasterKey({
xpub: privateImportValue,
})
);
+ // XPrv import (HD full access)
} else if (privateImportValue.startsWith('xprv')) {
await setMasterKey(
new HdMasterKey({
xpriv: privateImportValue,
})
);
+ // Pubkey import (non-HD view only)
} else if (isStandardAddress(privateImportValue)) {
await setMasterKey(
new LegacyMasterKey({
address: privateImportValue,
})
);
+ // WIF import (non-HD full access)
} else {
- // Lastly, attempt to parse as a WIF private key
+ // Attempt to import a raw WIF private key
const pkBytes = parseWIF(privateImportValue);
-
- // Import the raw private key
await setMasterKey(new LegacyMasterKey({ pkBytes }));
}
} catch (e) {
@@ -813,37 +832,86 @@ export async function generateWallet(noUI = false) {
return masterKey;
}
-export async function verifyMnemonic(strMnemonic = '', fPopupConfirm = true) {
- const nWordCount = strMnemonic.trim().split(/\s+/g).length;
+/**
+ * Clean a Seed Phrase string and verify it's integrity
+ *
+ * This returns an object of the validation status and the cleaned Seed Phrase for safe low-level usage.
+ * @param {String} strPhraseInput - The Seed Phrase string
+ * @param {Boolean} fPopupConfirm - Allow a warning bypass popup if the Seed Phrase is unusual
+ */
+export async function cleanAndVerifySeedPhrase(
+ strPhraseInput = '',
+ fPopupConfirm = true
+) {
+ // Clean the phrase (removing unnecessary spaces) and force to lowercase
+ const strPhrase = strPhraseInput.trim().replace(/\s+/g, ' ').toLowerCase();
- // Sanity check: Convert to lowercase
- strMnemonic = strMnemonic.toLowerCase();
+ // Count the Words
+ const nWordCount = strPhrase.trim().split(' ').length;
// Ensure it's a word count that makes sense
- if (nWordCount >= 12 && nWordCount <= 24) {
- if (!validateMnemonic(strMnemonic)) {
+ if (nWordCount === 12 || nWordCount === 24) {
+ if (!validateMnemonic(strPhrase)) {
+ // If a popup is allowed and Advanced Mode is enabled, warn the user that the
+ // ... seed phrase is potentially bad, and ask for confirmation to proceed
+ if (!fPopupConfirm || !fAdvancedMode)
+ return {
+ ok: false,
+ msg: translation.importSeedErrorTypo,
+ phrase: strPhrase,
+ };
+
// The reason we want to ask the user for confirmation is that the mnemonic
- // Could have been generated with another app that has a different dictionary
- return (
- fPopupConfirm &&
- (await confirmPopup({
- title: translation.popupSeedPhraseBad,
- html: translation.popupSeedPhraseBadNote,
- }))
- );
+ // could have been generated with another app that has a different dictionary
+ const fSkipWarning = await confirmPopup({
+ title: translation.popupSeedPhraseBad,
+ html: translation.popupSeedPhraseBadNote,
+ });
+
+ if (fSkipWarning) {
+ // User is probably an Arch Linux user and used `-f`
+ return {
+ ok: true,
+ msg: translation.importSeedErrorSkip,
+ phrase: strPhrase,
+ };
+ } else {
+ // User heeded the warning and rejected the phrase
+ return {
+ ok: false,
+ msg: translation.importSeedError,
+ phrase: strPhrase,
+ };
+ }
} else {
// Valid count and mnemonic
- return true;
+ return {
+ ok: true,
+ msg: translation.importSeedValid,
+ phrase: strPhrase,
+ };
}
} else {
// Invalid count
- return false;
+ return {
+ ok: false,
+ msg: translation.importSeedErrorSize,
+ phrase: strPhrase,
+ };
}
}
+/**
+ * Display a Seed Phrase popup to the user and optionally wait for a Seed Passphrase
+ * @param {string} mnemonic - The Seed Phrase to display to the user
+ * @returns {Promise} - The Mnemonic Passphrase (empty string if omitted by user)
+ */
function informUserOfMnemonic(mnemonic) {
return new Promise((res, _) => {
+ // Configure the modal
$('#mnemonicModal').modal({ keyboard: false });
+
+ // Render the Seed Phrase and configure the button
doms.domMnemonicModalContent.innerText = mnemonic;
doms.domMnemonicModalButton.onclick = () => {
res(doms.domMnemonicModalPassphrase.value);
@@ -853,6 +921,8 @@ function informUserOfMnemonic(mnemonic) {
doms.domMnemonicModalContent.innerText = '';
doms.domMnemonicModalPassphrase.value = '';
};
+
+ // Display the modal
$('#mnemonicModal').modal('show');
});
}