mirror of https://github.com/BTCPrivate/copay.git
Merge pull request #7859 from gabrielbazan7/fix/backupflow
[V4] FIX: Backup flow for wallets with password on their mnemonics
This commit is contained in:
commit
1a537d2b47
|
@ -9,36 +9,41 @@
|
|||
|
||||
<ion-content>
|
||||
<div *ngIf="deleted">
|
||||
<h1 translate>Wallet recovery phrase not available.</h1>
|
||||
<p translate>You can still export it from Advanced > Export.</p>
|
||||
<h1 class="deleted-title">{{'Wallet recovery phrase not available' |translate}}</h1>
|
||||
<ion-item-divider text-wrap>
|
||||
{{'You can still export it from Advanced > Export.' |translate}}
|
||||
<span *ngIf="wallet.coin == 'bch'" translate>
|
||||
Note: if this BCH wallet was duplicated from a BTC wallet, they share the same recovery phrase.
|
||||
</span>
|
||||
</ion-item-divider>
|
||||
</div>
|
||||
|
||||
<ion-slides pager="true" *ngIf="!deleted">
|
||||
<ion-slide>
|
||||
<div *ngIf="mnemonicWords && mnemonicWords[0] || !credentialsEncrypted">
|
||||
<h4 translate>Please carefully write down this phrase.</h4>
|
||||
<h4 class="slide-title" translate>Please carefully write down this phrase.</h4>
|
||||
<div copy-to-clipboard="{{ copyRecoveryPhrase() }}" class="phrase">
|
||||
<span *ngFor="let word of mnemonicWords">
|
||||
<span>{{word}}</span>
|
||||
<span *ngIf="useIdeograms"> </span>
|
||||
<span *ngIf="useIdeograms"> </span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="bottom-absolute">
|
||||
<div class="tldr" translate>We'll confirm on the next screen.</div>
|
||||
<ion-item-divider>{{"We'll confirm on the next screen." | translate}}</ion-item-divider>
|
||||
<button ion-button block [disabled]="credentialsEncrypted || error" (click)="slideNext()" translate>I've written it down</button>
|
||||
</div>
|
||||
</div>
|
||||
</ion-slide>
|
||||
|
||||
<ion-slide>
|
||||
<h1 translate>Let's verify your backup phrase.</h1>
|
||||
<h4 class="slide-title" translate>Let's verify your backup phrase.</h4>
|
||||
<div class="phrase">
|
||||
<button ion-button outline *ngFor="let customWord of customWords; let i = index" (click)="removeButton(i, customWord)">{{customWord.word}}</button>
|
||||
</div>
|
||||
<div class="bottom-absolute">
|
||||
<div *ngIf="!selectComplete">
|
||||
<div class="tldr" translate>Please tap each word in the correct order.</div>
|
||||
<ion-item-divider>{{'Please tap each word in the correct order.' | translate}}</ion-item-divider>
|
||||
<div>
|
||||
<button ion-button *ngFor="let shuffledWord of shuffledMnemonicWords; let i = index" (click)="addButton(i, shuffledWord)"
|
||||
[disabled]="shuffledWord.selected">{{shuffledWord.word}}
|
||||
|
@ -47,7 +52,7 @@
|
|||
</div>
|
||||
|
||||
<div *ngIf="selectComplete">
|
||||
<div class="tldr" translate>Is this correct?</div>
|
||||
<ion-item-divider>{{'Is this correct?' | translate}}</ion-item-divider>
|
||||
<div>
|
||||
<button ion-button block (click)="slideNext();" translate>Confirm</button>
|
||||
<button ion-button block outline (click)="setFlow();" translate>Clear</button>
|
||||
|
@ -57,18 +62,19 @@
|
|||
</ion-slide>
|
||||
|
||||
<ion-slide *ngIf="wallet.mnemonicHasPassphrase">
|
||||
<h1 translate>Enter your password</h1>
|
||||
<p translate>In order to verify your wallet backup, please type your password.</p>
|
||||
<div class="input">
|
||||
<input type="password" id="passphrase" [(ngModel)]="passphrase" autocapitalize="off" spellcheck="false" />
|
||||
</div>
|
||||
|
||||
<div class="password-required" translate>
|
||||
This recovery phrase was created with a password. To recover this wallet both the recovery phrase and password are needed.
|
||||
</div>
|
||||
<h4 translate>Enter your password</h4>
|
||||
<ion-item-divider text-wrap>{{'In order to verify your wallet backup, please type your password.' | translate}}</ion-item-divider>
|
||||
<ion-item>
|
||||
<ion-label stacked translate>Password</ion-label>
|
||||
<ion-input type="password" id="password" [(ngModel)]="password" autocapitalize="off" spellcheck="false"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item-divider text-wrap class="assertive">
|
||||
{{'This recovery phrase was created with a password. To recover this wallet both the recovery phrase and password are needed.'
|
||||
| translate}}
|
||||
</ion-item-divider>
|
||||
|
||||
<div class="bottom-absolute">
|
||||
<button ion-button block [disabled]="!passphrase" (click)="finalStep();" translate>Confirm</button>
|
||||
<button ion-button block [disabled]="!password" (click)="finalStep()" translate>Confirm</button>
|
||||
</div>
|
||||
</ion-slide>
|
||||
</ion-slides>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
page-backup-game {
|
||||
p {
|
||||
line-height: 1.6;
|
||||
font-size: 18px;
|
||||
margin-right: 10px;
|
||||
margin-left: 10px;
|
||||
.deleted-title {
|
||||
text-align: center;
|
||||
}
|
||||
.slide-title {
|
||||
padding: 20px;
|
||||
}
|
||||
.swiper-pagination {
|
||||
display: none;
|
||||
|
@ -11,11 +11,6 @@ page-backup-game {
|
|||
.slide-zoom {
|
||||
height: 100%;
|
||||
}
|
||||
.password-required {
|
||||
padding: 2rem;
|
||||
font-size: 14px;
|
||||
color: color($colors, danger);
|
||||
}
|
||||
.password {
|
||||
background-color: color($colors, light);
|
||||
padding: 2rem;
|
||||
|
@ -23,19 +18,10 @@ page-backup-game {
|
|||
.phrase {
|
||||
display: -webkit-box;
|
||||
background: color($colors, light);
|
||||
border: 2px dashed #d9d9d9;
|
||||
border-radius: 3px;
|
||||
color: color($colors, secondary);
|
||||
text-align: center;
|
||||
max-width: 500px;
|
||||
min-height: 12rem;
|
||||
align-items: center;
|
||||
margin: 20px auto;
|
||||
padding: 15px 0;
|
||||
line-height: 170%;
|
||||
word-spacing: 10px;
|
||||
}
|
||||
.tldr {
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import { Component, ViewChild } from '@angular/core';
|
||||
import { NavController, Slides, Navbar, AlertController, NavParams } from 'ionic-angular';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
|
||||
//pahes
|
||||
import { DisclaimerPage } from '../../onboarding/disclaimer/disclaimer';
|
||||
|
||||
//providers
|
||||
import { ProfileProvider } from '../../../providers/profile/profile';
|
||||
import { WalletProvider } from '../../../providers/wallet/wallet';
|
||||
import { BwcProvider } from '../../../providers/bwc/bwc';
|
||||
import { Logger } from '@nsalaun/ng-logger';
|
||||
import * as _ from 'lodash';
|
||||
import { OnGoingProcessProvider } from '../../../providers/on-going-process/on-going-process';
|
||||
|
||||
@Component({
|
||||
selector: 'page-backup-game',
|
||||
|
@ -21,14 +26,13 @@ export class BackupGamePage {
|
|||
public deleted: boolean;
|
||||
public mnemonicWords: Array<String>;
|
||||
public shuffledMnemonicWords: Array<any>;
|
||||
public passphrase: String;
|
||||
public password: String;
|
||||
public customWords: Array<any>;
|
||||
public selectComplete: boolean;
|
||||
public error: boolean;
|
||||
public credentialsEncrypted: boolean;
|
||||
|
||||
private mnemonicHasPassphrase: any;
|
||||
private data: any;
|
||||
private walletId: string;
|
||||
private wallet: any;
|
||||
private keys: any;
|
||||
|
@ -41,7 +45,8 @@ export class BackupGamePage {
|
|||
private logger: Logger,
|
||||
private profileProvider: ProfileProvider,
|
||||
private walletProvider: WalletProvider,
|
||||
private bwcProvider: BwcProvider
|
||||
private bwcProvider: BwcProvider,
|
||||
private onGoingProcessProvider: OnGoingProcessProvider
|
||||
) {
|
||||
this.walletId = this.navParams.get('walletId');
|
||||
this.fromOnboarding = this.navParams.get('fromOnboarding');
|
||||
|
@ -70,12 +75,13 @@ export class BackupGamePage {
|
|||
ngOnInit() {
|
||||
this.currentIndex = 0;
|
||||
this.navBar.backButtonClick = (e: UIEvent) => {
|
||||
this.slidePrev();
|
||||
if (this.slides) this.slidePrev();
|
||||
else this.navCtrl.pop();
|
||||
}
|
||||
}
|
||||
|
||||
ionViewDidLoad() {
|
||||
this.slides.lockSwipes(true);
|
||||
if (this.slides) this.slides.lockSwipes(true);
|
||||
}
|
||||
|
||||
private shuffledWords(words: Array<String>) {
|
||||
|
@ -197,13 +203,12 @@ export class BackupGamePage {
|
|||
if (!this.keys) return;
|
||||
|
||||
let words = this.keys.mnemonic;
|
||||
this.data = {};
|
||||
|
||||
this.mnemonicWords = words.split(/[\u3000\s]+/);
|
||||
this.shuffledMnemonicWords = this.shuffledWords(this.mnemonicWords);
|
||||
this.mnemonicHasPassphrase = this.wallet.mnemonicHasPassphrase();
|
||||
this.useIdeograms = words.indexOf("\u3000") >= 0;
|
||||
this.data['passphrase'] = null;
|
||||
this.password = '';
|
||||
this.customWords = [];
|
||||
this.selectComplete = false;
|
||||
this.error = false;
|
||||
|
@ -234,12 +239,12 @@ export class BackupGamePage {
|
|||
let walletClient = this.bwcProvider.getClient();
|
||||
let separator = this.useIdeograms ? '\u3000' : ' ';
|
||||
let customSentence = customWordList.join(separator);
|
||||
let passphrase = this.data.passphrase || '';
|
||||
let password = this.password || '';
|
||||
|
||||
try {
|
||||
walletClient.seedFromMnemonic(customSentence, {
|
||||
network: this.wallet.credentials.network,
|
||||
passphrase: passphrase,
|
||||
password: password,
|
||||
account: this.wallet.credentials.account
|
||||
});
|
||||
} catch (err) {
|
||||
|
@ -259,9 +264,9 @@ export class BackupGamePage {
|
|||
};
|
||||
|
||||
private finalStep(): void {
|
||||
//ongoingProcess.set('validatingWords', true);
|
||||
this.onGoingProcessProvider.set('validatingWords', true);
|
||||
this.confirm().then(() => {
|
||||
//ongoingProcess.set('validatingWords', false);
|
||||
this.onGoingProcessProvider.set('validatingWords', false);
|
||||
this.showBackupResult();
|
||||
}).catch((err) => {
|
||||
this.backupError(err);
|
||||
|
|
Loading…
Reference in New Issue