all three tasks have been completed (#253)
* all three tasks have been completed * created copy seed phrase
|
|
@ -120,13 +120,16 @@
|
|||
"BUTTON_CREATE": "Create wallet",
|
||||
"NOT_CORRECT_FILE_OR_PASSWORD": "Invalid wallet file or password does not match",
|
||||
"CHOOSE_PATH": "Please choose a path",
|
||||
"SEED_PASSWORD": "Seed password",
|
||||
"OK": "OK",
|
||||
"FORM_ERRORS": {
|
||||
"NAME_REQUIRED": "Name is required",
|
||||
"NAME_DUPLICATE": "Name is duplicate",
|
||||
"MAX_LENGTH": "Maximum name length reached",
|
||||
"CONFIRM_NOT_MATCH": "Confirm password not match",
|
||||
"KEY_REQUIRED": "Key is required",
|
||||
"KEY_NOT_VALID": "Key not valid"
|
||||
"KEY_NOT_VALID": "Key not valid",
|
||||
"INCORRECT_PASSWORD": "Incorrect password"
|
||||
}
|
||||
},
|
||||
"SEED_PHRASE": {
|
||||
|
|
@ -214,10 +217,21 @@
|
|||
"SEED_PHRASE_HINT": "Click to reveal the seed phrase",
|
||||
"BUTTON_SAVE": "Save",
|
||||
"BUTTON_REMOVE": "Close wallet",
|
||||
"CREATE_PASSWORD_SECURE": "Create a password to secure your seed",
|
||||
"INFO": "info",
|
||||
"SEED_IS_UNSECURED": "Seed is unsecured",
|
||||
"SEED_IS_SECURED": "Seed is secured",
|
||||
"REMEMBER_YOU_WILL_REQUIRE": "Remember, you will require the password to restore it.",
|
||||
"FORM": {
|
||||
"CONFIRM_PASSWORD": "Confirm password",
|
||||
"GENERATE_SECURE_SEED": "Generate Secure Seed",
|
||||
"SECURED_SEED_WILL_REQUIRE": "Secured seed will require this password to restore."
|
||||
},
|
||||
"FORM_ERRORS": {
|
||||
"NAME_REQUIRED": "Name is required",
|
||||
"NAME_DUPLICATE": "Name is duplicate",
|
||||
"MAX_LENGTH": "Maximum name length reached"
|
||||
"MAX_LENGTH": "Maximum name length reached",
|
||||
"PASSWORDS_DONT_MATCH": "Passwords don't match"
|
||||
}
|
||||
},
|
||||
"ASSIGN_ALIAS": {
|
||||
|
|
|
|||
1
src/gui/qt-daemon/html/assets/icons/info.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{fill:#fff;}</style></defs><title>info</title><path class="cls-1" d="M192,42.05476A149.94522,149.94522,0,0,1,298.02728,298.02728,149.94522,149.94522,0,1,1,85.97271,85.97271,148.96374,148.96374,0,0,1,192,42.05476M192,0C85.96132,0,0,85.96132,0,192S85.96132,384,192,384s192-85.96132,192-192S298.03868,0,192,0Z"/><rect class="cls-1" x="171" y="247.94524" width="42" height="42"/><rect class="cls-1" x="171" y="94.05476" width="42" height="120"/></svg>
|
||||
|
After Width: | Height: | Size: 561 B |
21
src/gui/qt-daemon/html/assets/icons/safety.svg
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 320 384" style="enable-background:new 0 0 320 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{clip-path:url(#SVGID_2_);}
|
||||
.st1{clip-path:url(#SVGID_2_);fill:none;stroke:#000000;stroke-width:42;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_1_" width="320" height="384"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
||||
</clipPath>
|
||||
<path class="st0" d="M159.9,44.5L278,85.8V232c0,0.9-0.4,9.2-14.7,26c-11,13-26.9,27.1-47.3,42c-20.6,15.1-41.6,27.8-56.1,36.1
|
||||
c-14.5-8.3-35.4-21-56-36.1c-20.3-14.9-36.2-29-47.2-42C42.4,241.2,42,232.9,42,232V85.8L159.9,44.5 M159.9,0L0,56v176
|
||||
c0,70.7,159.9,152,159.9,152S320,302.7,320,232V56L159.9,0z"/>
|
||||
<polyline class="st1" points="100.1,182.2 142.3,218.5 220.3,145.1 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
10
src/gui/qt-daemon/html/assets/icons/secured.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M26,15v-5c0-5.5-4.5-10-10-10h-0.1c-5.5,0-10,4.5-10,10v5H3v17h12.9H16h13V15H26z M9.9,10c0-3.3,2.7-6,6-6H16
|
||||
c3.3,0,6,2.7,6,6v5H9.9V10z M14,27v-7h4v7H14z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 582 B |
10
src/gui/qt-daemon/html/assets/icons/unsecured.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M22,15h-3.4H9.9v-5c0-3.3,2.7-6,6-6H16c3,0,5.4,2.2,5.9,5h4c-0.5-5-4.8-9-9.9-9h-0.1c-5.5,0-10,4.5-10,10v5H3
|
||||
v17h12.9H16h13V15h-3H22z M18,27h-4v-7h4V27z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 581 B |
|
|
@ -205,6 +205,16 @@ button {
|
|||
color: themed(redTextColor);
|
||||
}
|
||||
}
|
||||
.success-block {
|
||||
font-size: 1rem;
|
||||
line-height: 1.4rem;
|
||||
align-self: flex-end;
|
||||
text-align: right;
|
||||
|
||||
@include themify($themes) {
|
||||
color: themed(greenTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-text {
|
||||
|
|
|
|||
1
src/gui/qt-daemon/html/info.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{fill:#fff;}</style></defs><title>info</title><path class="cls-1" d="M192,42.05476A149.94522,149.94522,0,0,1,298.02728,298.02728,149.94522,149.94522,0,1,1,85.97271,85.97271,148.96374,148.96374,0,0,1,192,42.05476M192,0C85.96132,0,0,85.96132,0,192S85.96132,384,192,384s192-85.96132,192-192S298.03868,0,192,0Z"/><rect class="cls-1" x="171" y="247.94524" width="42" height="42"/><rect class="cls-1" x="171" y="94.05476" width="42" height="120"/></svg>
|
||||
|
After Width: | Height: | Size: 561 B |
|
|
@ -649,7 +649,7 @@ module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
|
|||
/*! no static exports found */
|
||||
/***/ (function(module, exports) {
|
||||
|
||||
var core = module.exports = { version: '2.6.11' };
|
||||
var core = module.exports = { version: '2.6.12' };
|
||||
if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef
|
||||
|
||||
|
||||
|
|
@ -1823,7 +1823,7 @@ var store = global[SHARED] || (global[SHARED] = {});
|
|||
})('versions', []).push({
|
||||
version: core.version,
|
||||
mode: __webpack_require__(/*! ./_library */ "./node_modules/core-js/modules/_library.js") ? 'pure' : 'global',
|
||||
copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
|
||||
copyright: '© 2020 Denis Pushkarev (zloirock.ru)'
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -5800,8 +5800,8 @@ __webpack_require__.r(__webpack_exports__);
|
|||
/*! no static exports found */
|
||||
/***/ (function(module, exports, __webpack_require__) {
|
||||
|
||||
__webpack_require__(/*! /Users/mekasan/Projects/Projects/zano_v1/src/gui/qt-daemon/html_source/src/polyfills.ts */"./src/polyfills.ts");
|
||||
module.exports = __webpack_require__(/*! /Users/mekasan/Projects/Projects/zano_v1/src/gui/qt-daemon/html_source/node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
|
||||
__webpack_require__(/*! D:\Project\WORK_NEW\zano\src\gui\qt-daemon\html_source\src\polyfills.ts */"./src/polyfills.ts");
|
||||
module.exports = __webpack_require__(/*! D:\Project\WORK_NEW\zano\src\gui\qt-daemon\html_source\node_modules\@angular-devkit\build-angular\src\angular-cli-files\models\jit-polyfills.js */"./node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/jit-polyfills.js");
|
||||
|
||||
|
||||
/***/ })
|
||||
|
|
|
|||
21
src/gui/qt-daemon/html/safety.svg
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 320 384" style="enable-background:new 0 0 320 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{clip-path:url(#SVGID_2_);}
|
||||
.st1{clip-path:url(#SVGID_2_);fill:none;stroke:#000000;stroke-width:42;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_1_" width="320" height="384"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
||||
</clipPath>
|
||||
<path class="st0" d="M159.9,44.5L278,85.8V232c0,0.9-0.4,9.2-14.7,26c-11,13-26.9,27.1-47.3,42c-20.6,15.1-41.6,27.8-56.1,36.1
|
||||
c-14.5-8.3-35.4-21-56-36.1c-20.3-14.9-36.2-29-47.2-42C42.4,241.2,42,232.9,42,232V85.8L159.9,44.5 M159.9,0L0,56v176
|
||||
c0,70.7,159.9,152,159.9,152S320,302.7,320,232V56L159.9,0z"/>
|
||||
<polyline class="st1" points="100.1,182.2 142.3,218.5 220.3,145.1 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
10
src/gui/qt-daemon/html/secured.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M26,15v-5c0-5.5-4.5-10-10-10h-0.1c-5.5,0-10,4.5-10,10v5H3v17h12.9H16h13V15H26z M9.9,10c0-3.3,2.7-6,6-6H16
|
||||
c3.3,0,6,2.7,6,6v5H9.9V10z M14,27v-7h4v7H14z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 582 B |
10
src/gui/qt-daemon/html/unsecured.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M22,15h-3.4H9.9v-5c0-3.3,2.7-6,6-6H16c3,0,5.4,2.2,5.9,5h4c-0.5-5-4.8-9-9.9-9h-0.1c-5.5,0-10,4.5-10,10v5H3
|
||||
v17h12.9H16h13V15h-3H22z M18,27h-4v-7h4V27z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 581 B |
|
|
@ -36,6 +36,7 @@
|
|||
"ngx-contextmenu": "^5.1.1",
|
||||
"ngx-papaparse": "^3.0.3",
|
||||
"qrcode": "^1.3.0",
|
||||
"node-sass": "^4.0.0",
|
||||
"rxjs": "~6.3.3",
|
||||
"zone.js": "~0.8.26"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -412,23 +412,28 @@ export class BackendService {
|
|||
this.runCommand('close_wallet', {wallet_id: +wallet_id}, callback);
|
||||
}
|
||||
|
||||
getSmartWalletInfo(wallet_id, callback) {
|
||||
this.runCommand('get_smart_wallet_info', {wallet_id: +wallet_id}, callback);
|
||||
getSmartWalletInfo({wallet_id, seed_password}, callback) {
|
||||
this.runCommand('get_smart_wallet_info', {wallet_id: +wallet_id, seed_password}, callback);
|
||||
}
|
||||
|
||||
getSeedPhraseInfo(param, callback) {
|
||||
this.runCommand('get_seed_phrase_info', param, callback);
|
||||
}
|
||||
|
||||
runWallet(wallet_id, callback?) {
|
||||
this.runCommand('run_wallet', {wallet_id: +wallet_id}, callback);
|
||||
}
|
||||
|
||||
isValidRestoreWalletText(text, callback) {
|
||||
this.runCommand('is_valid_restore_wallet_text', text, callback);
|
||||
isValidRestoreWalletText(param, callback) {
|
||||
this.runCommand('is_valid_restore_wallet_text', param, callback);
|
||||
}
|
||||
|
||||
restoreWallet(path, pass, restore_key, callback) {
|
||||
restoreWallet(path, pass, seed_phrase, seed_pass, callback) {
|
||||
const params = {
|
||||
restore_key: restore_key,
|
||||
seed_phrase: seed_phrase,
|
||||
path: path,
|
||||
pass: pass
|
||||
pass: pass,
|
||||
seed_pass
|
||||
};
|
||||
this.runCommand('restore_wallet', params, callback);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-block half-block">
|
||||
<label for="seed-password">{{ 'RESTORE_WALLET.SEED_PASSWORD' | translate }}</label>
|
||||
<input type="password" id="seed-password" formControlName="seedPassword" [attr.readonly]="this.seedPhraseInfo?.syntax_correct && this.seedPhraseInfo?.require_password ? null : true">
|
||||
<div class="error-block" *ngIf="(restoreForm.controls['seedPassword'].dirty || restoreForm.controls['seedPassword'].touched) && !this.seedPhraseInfo?.hash_sum_matched">
|
||||
<span>{{ 'RESTORE_WALLET.FORM_ERRORS.INCORRECT_PASSWORD' | translate }}</span>
|
||||
</div>
|
||||
<div class="success-block" *ngIf="this.seedPhraseInfo?.hash_sum_matched">
|
||||
<span>{{ 'RESTORE_WALLET.OK' | translate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wrap-buttons">
|
||||
<button type="button" class="transparent-button" *ngIf="walletSaved" disabled><i class="icon"></i>{{walletSavedName}}</button>
|
||||
<button type="button" class="blue-button select-button" (click)="saveWallet()" [disabled]="!restoreForm.valid" *ngIf="!walletSaved">{{ 'RESTORE_WALLET.BUTTON_SELECT' | translate }}</button>
|
||||
|
|
|
|||
|
|
@ -1,42 +1,57 @@
|
|||
import {Component, NgZone, OnInit} from '@angular/core';
|
||||
import {FormGroup, FormControl, Validators} from '@angular/forms';
|
||||
import {Router} from '@angular/router';
|
||||
import {BackendService} from '../_helpers/services/backend.service';
|
||||
import {VariablesService} from '../_helpers/services/variables.service';
|
||||
import {ModalService} from '../_helpers/services/modal.service';
|
||||
import {Wallet} from '../_helpers/models/wallet.model';
|
||||
import {TranslateService} from '@ngx-translate/core';
|
||||
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { BackendService } from '../_helpers/services/backend.service';
|
||||
import { VariablesService } from '../_helpers/services/variables.service';
|
||||
import { ModalService } from '../_helpers/services/modal.service';
|
||||
import { Wallet } from '../_helpers/models/wallet.model';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Subject } from 'rxjs/internal/Subject';
|
||||
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'app-restore-wallet',
|
||||
templateUrl: './restore-wallet.component.html',
|
||||
styleUrls: ['./restore-wallet.component.scss']
|
||||
styleUrls: ['./restore-wallet.component.scss'],
|
||||
})
|
||||
export class RestoreWalletComponent implements OnInit {
|
||||
|
||||
restoreForm = new FormGroup({
|
||||
name: new FormControl('', [Validators.required, (g: FormControl) => {
|
||||
for (let i = 0; i < this.variablesService.wallets.length; i++) {
|
||||
if (g.value === this.variablesService.wallets[i].name) {
|
||||
return {'duplicate': true};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}]),
|
||||
key: new FormControl('', Validators.required),
|
||||
password: new FormControl('', Validators.pattern(this.variablesService.pattern)),
|
||||
confirm: new FormControl('')
|
||||
}, function (g: FormGroup) {
|
||||
return g.get('password').value === g.get('confirm').value ? null : {'confirm_mismatch': true};
|
||||
});
|
||||
export class RestoreWalletComponent implements OnInit, OnDestroy {
|
||||
restoreForm = new FormGroup(
|
||||
{
|
||||
name: new FormControl('', [
|
||||
Validators.required,
|
||||
(g: FormControl) => {
|
||||
for (let i = 0; i < this.variablesService.wallets.length; i++) {
|
||||
if (g.value === this.variablesService.wallets[i].name) {
|
||||
return { duplicate: true };
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
]),
|
||||
key: new FormControl('', Validators.required),
|
||||
password: new FormControl(
|
||||
'',
|
||||
Validators.pattern(this.variablesService.pattern)
|
||||
),
|
||||
confirm: new FormControl(''),
|
||||
seedPassword: new FormControl('', Validators.pattern(this.variablesService.pattern)),
|
||||
},
|
||||
function (g: FormGroup) {
|
||||
return g.get('password').value === g.get('confirm').value
|
||||
? null
|
||||
: { confirm_mismatch: true };
|
||||
}
|
||||
);
|
||||
|
||||
wallet = {
|
||||
id: ''
|
||||
id: '',
|
||||
};
|
||||
|
||||
walletSaved = false;
|
||||
walletSavedName = '';
|
||||
progressWidth = '9rem';
|
||||
seedPhraseInfo = null;
|
||||
unsubscribeAll = new Subject<boolean>();
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
|
|
@ -47,7 +62,36 @@ export class RestoreWalletComponent implements OnInit {
|
|||
private translate: TranslateService
|
||||
) {}
|
||||
|
||||
ngOnInit() {}
|
||||
ngOnInit() {
|
||||
this.checkValidSeedPhrasePassword();
|
||||
this.changeDetectionSeedPhrasePassword();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsubscribeAll.next(true);
|
||||
this.unsubscribeAll.complete();
|
||||
}
|
||||
|
||||
changeDetectionSeedPhrasePassword() {
|
||||
this.restoreForm.controls.seedPassword.valueChanges
|
||||
.pipe(debounceTime(0), distinctUntilChanged(), takeUntil(this.unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
this.checkValidSeedPhrasePassword();
|
||||
});
|
||||
this.restoreForm.controls.key.valueChanges
|
||||
.pipe(debounceTime(0), distinctUntilChanged(), takeUntil(this.unsubscribeAll))
|
||||
.subscribe(() => {
|
||||
this.checkValidSeedPhrasePassword();
|
||||
});
|
||||
}
|
||||
|
||||
checkValidSeedPhrasePassword() {
|
||||
const seed_password = this.restoreForm.controls.seedPassword.value;
|
||||
const seed_phrase = this.restoreForm.controls.key.value;
|
||||
this.backend.getSeedPhraseInfo({seed_phrase, seed_password}, (status, data) => {
|
||||
this.seedPhraseInfo = data;
|
||||
});
|
||||
}
|
||||
|
||||
createWallet() {
|
||||
this.ngZone.run(() => {
|
||||
|
|
@ -57,66 +101,133 @@ export class RestoreWalletComponent implements OnInit {
|
|||
}
|
||||
|
||||
saveWallet() {
|
||||
if (this.restoreForm.valid && this.restoreForm.get('name').value.length <= this.variablesService.maxWalletNameLength) {
|
||||
this.backend.isValidRestoreWalletText(this.restoreForm.get('key').value, (valid_status, valid_data) => {
|
||||
if (valid_data !== 'TRUE') {
|
||||
this.ngZone.run(() => {
|
||||
this.restoreForm.get('key').setErrors({key_not_valid: true});
|
||||
});
|
||||
} else {
|
||||
this.backend.saveFileDialog(this.translate.instant('RESTORE_WALLET.CHOOSE_PATH'), '*', this.variablesService.settings.default_path, (save_status, save_data) => {
|
||||
if (save_status) {
|
||||
this.variablesService.settings.default_path = save_data.path.substr(0, save_data.path.lastIndexOf('/'));
|
||||
this.walletSavedName = save_data.path.substr(save_data.path.lastIndexOf('/') + 1, save_data.path.length - 1);
|
||||
this.backend.restoreWallet(save_data.path, this.restoreForm.get('password').value, this.restoreForm.get('key').value, (restore_status, restore_data) => {
|
||||
if (restore_status) {
|
||||
this.wallet.id = restore_data.wallet_id;
|
||||
this.variablesService.opening_wallet = new Wallet(
|
||||
restore_data.wallet_id,
|
||||
this.restoreForm.get('name').value,
|
||||
this.restoreForm.get('password').value,
|
||||
restore_data['wi'].path,
|
||||
restore_data['wi'].address,
|
||||
restore_data['wi'].balance,
|
||||
restore_data['wi'].unlocked_balance,
|
||||
restore_data['wi'].mined_total,
|
||||
restore_data['wi'].tracking_hey
|
||||
if (
|
||||
this.restoreForm.valid &&
|
||||
this.restoreForm.get('name').value.length <=
|
||||
this.variablesService.maxWalletNameLength
|
||||
) {
|
||||
this.backend.isValidRestoreWalletText(
|
||||
{
|
||||
seed_phrase: this.restoreForm.get('key').value,
|
||||
seed_password: this.restoreForm.get('seedPassword').value,
|
||||
},
|
||||
(valid_status, valid_data) => {
|
||||
if (valid_data !== 'TRUE') {
|
||||
this.ngZone.run(() => {
|
||||
this.restoreForm.get('key').setErrors({ key_not_valid: true });
|
||||
});
|
||||
} else {
|
||||
this.backend.saveFileDialog(
|
||||
this.translate.instant('RESTORE_WALLET.CHOOSE_PATH'),
|
||||
'*',
|
||||
this.variablesService.settings.default_path,
|
||||
(save_status, save_data) => {
|
||||
if (save_status) {
|
||||
this.variablesService.settings.default_path = save_data.path.substr(
|
||||
0,
|
||||
save_data.path.lastIndexOf('/')
|
||||
);
|
||||
this.variablesService.opening_wallet.is_auditable = restore_data['wi'].is_auditable;
|
||||
this.variablesService.opening_wallet.is_watch_only = restore_data['wi'].is_watch_only;
|
||||
this.variablesService.opening_wallet.currentPage = 1;
|
||||
this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(this.variablesService.opening_wallet.address);
|
||||
this.variablesService.opening_wallet.pages = new Array(1).fill(1);
|
||||
this.variablesService.opening_wallet.totalPages = 1;
|
||||
this.variablesService.opening_wallet.currentPage = 1;
|
||||
this.variablesService.opening_wallet.total_history_item = 0;
|
||||
this.variablesService.opening_wallet.restore = true;
|
||||
if (restore_data.recent_history && restore_data.recent_history.history) {
|
||||
this.variablesService.opening_wallet.totalPages = Math.ceil( restore_data.recent_history.total_history_items / this.variablesService.count);
|
||||
this.variablesService.opening_wallet.totalPages > this.variablesService.maxPages
|
||||
? this.variablesService.opening_wallet.pages = new Array(5).fill(1).map((value, index) => value + index)
|
||||
: this.variablesService.opening_wallet.pages = new Array(this.variablesService.opening_wallet.totalPages).fill(1).map((value, index) => value + index);
|
||||
this.variablesService.opening_wallet.prepareHistory(restore_data.recent_history.history);
|
||||
}
|
||||
this.backend.getContracts(this.variablesService.opening_wallet.wallet_id, (contracts_status, contracts_data) => {
|
||||
if (contracts_status && contracts_data.hasOwnProperty('contracts')) {
|
||||
this.ngZone.run(() => {
|
||||
this.variablesService.opening_wallet.prepareContractsAfterOpen(contracts_data.contracts, this.variablesService.exp_med_ts, this.variablesService.height_app, this.variablesService.settings.viewedContracts, this.variablesService.settings.notViewedContracts);
|
||||
});
|
||||
this.walletSavedName = save_data.path.substr(
|
||||
save_data.path.lastIndexOf('/') + 1,
|
||||
save_data.path.length - 1
|
||||
);
|
||||
this.backend.restoreWallet(
|
||||
save_data.path,
|
||||
this.restoreForm.get('password').value,
|
||||
this.restoreForm.get('key').value,
|
||||
this.restoreForm.get('seedPassword').value,
|
||||
(restore_status, restore_data) => {
|
||||
if (restore_status) {
|
||||
this.wallet.id = restore_data.wallet_id;
|
||||
this.variablesService.opening_wallet = new Wallet(
|
||||
restore_data.wallet_id,
|
||||
this.restoreForm.get('name').value,
|
||||
this.restoreForm.get('password').value,
|
||||
restore_data['wi'].path,
|
||||
restore_data['wi'].address,
|
||||
restore_data['wi'].balance,
|
||||
restore_data['wi'].unlocked_balance,
|
||||
restore_data['wi'].mined_total,
|
||||
restore_data['wi'].tracking_hey
|
||||
);
|
||||
this.variablesService.opening_wallet.is_auditable =
|
||||
restore_data['wi'].is_auditable;
|
||||
this.variablesService.opening_wallet.is_watch_only =
|
||||
restore_data['wi'].is_watch_only;
|
||||
this.variablesService.opening_wallet.currentPage = 1;
|
||||
this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(
|
||||
this.variablesService.opening_wallet.address
|
||||
);
|
||||
this.variablesService.opening_wallet.pages = new Array(
|
||||
1
|
||||
).fill(1);
|
||||
this.variablesService.opening_wallet.totalPages = 1;
|
||||
this.variablesService.opening_wallet.currentPage = 1;
|
||||
this.variablesService.opening_wallet.total_history_item = 0;
|
||||
this.variablesService.opening_wallet.restore = true;
|
||||
if (
|
||||
restore_data.recent_history &&
|
||||
restore_data.recent_history.history
|
||||
) {
|
||||
this.variablesService.opening_wallet.totalPages = Math.ceil(
|
||||
restore_data.recent_history.total_history_items /
|
||||
this.variablesService.count
|
||||
);
|
||||
this.variablesService.opening_wallet.totalPages >
|
||||
this.variablesService.maxPages
|
||||
? (this.variablesService.opening_wallet.pages = new Array(
|
||||
5
|
||||
)
|
||||
.fill(1)
|
||||
.map((value, index) => value + index))
|
||||
: (this.variablesService.opening_wallet.pages = new Array(
|
||||
this.variablesService.opening_wallet.totalPages
|
||||
)
|
||||
.fill(1)
|
||||
.map((value, index) => value + index));
|
||||
this.variablesService.opening_wallet.prepareHistory(
|
||||
restore_data.recent_history.history
|
||||
);
|
||||
}
|
||||
this.backend.getContracts(
|
||||
this.variablesService.opening_wallet.wallet_id,
|
||||
(contracts_status, contracts_data) => {
|
||||
if (
|
||||
contracts_status &&
|
||||
contracts_data.hasOwnProperty('contracts')
|
||||
) {
|
||||
this.ngZone.run(() => {
|
||||
this.variablesService.opening_wallet.prepareContractsAfterOpen(
|
||||
contracts_data.contracts,
|
||||
this.variablesService.exp_med_ts,
|
||||
this.variablesService.height_app,
|
||||
this.variablesService.settings
|
||||
.viewedContracts,
|
||||
this.variablesService.settings
|
||||
.notViewedContracts
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
this.ngZone.run(() => {
|
||||
this.walletSaved = true;
|
||||
this.progressWidth = '50%';
|
||||
});
|
||||
} else {
|
||||
this.modalService.prepareModal(
|
||||
'error',
|
||||
'RESTORE_WALLET.NOT_CORRECT_FILE_OR_PASSWORD'
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
this.ngZone.run(() => {
|
||||
this.walletSaved = true;
|
||||
this.progressWidth = '50%';
|
||||
});
|
||||
} else {
|
||||
this.modalService.prepareModal('error', 'RESTORE_WALLET.NOT_CORRECT_FILE_OR_PASSWORD');
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,7 +243,9 @@ export class RestoreWalletComponent implements OnInit {
|
|||
if (!exists) {
|
||||
this.backend.runWallet(this.wallet.id, (run_status, run_data) => {
|
||||
if (run_status) {
|
||||
this.variablesService.wallets.push(this.variablesService.opening_wallet);
|
||||
this.variablesService.wallets.push(
|
||||
this.variablesService.opening_wallet
|
||||
);
|
||||
if (this.variablesService.appPass) {
|
||||
this.backend.storeSecureAppData();
|
||||
}
|
||||
|
|
@ -145,7 +258,10 @@ export class RestoreWalletComponent implements OnInit {
|
|||
});
|
||||
} else {
|
||||
this.variablesService.opening_wallet = null;
|
||||
this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');
|
||||
this.modalService.prepareModal(
|
||||
'error',
|
||||
'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN'
|
||||
);
|
||||
this.backend.closeWallet(this.wallet.id, () => {
|
||||
this.ngZone.run(() => {
|
||||
this.router.navigate(['/']);
|
||||
|
|
|
|||
|
|
@ -32,9 +32,9 @@ export class SeedPhraseComponent implements OnInit, OnDestroy {
|
|||
if (params.wallet_id) {
|
||||
this.wallet_id = params.wallet_id;
|
||||
this.backend.getSmartWalletInfo(params.wallet_id, (status, data) => {
|
||||
if (data.hasOwnProperty('restore_key')) {
|
||||
if (data.hasOwnProperty('seed_phrase')) {
|
||||
this.ngZone.run(() => {
|
||||
this.seedPhrase = data['restore_key'].trim();
|
||||
this.seedPhrase = data['seed_phrase'].trim();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@
|
|||
|
||||
<div class="input-block">
|
||||
<label for="wallet-name">{{ 'WALLET_DETAILS.LABEL_NAME' | translate }}</label>
|
||||
<input type="text" id="wallet-name" formControlName="name" [maxLength]="variablesService.maxWalletNameLength" (contextmenu)="variablesService.onContextMenu($event)">
|
||||
<div class="error-block" *ngIf="detailsForm.controls['name'].invalid && (detailsForm.controls['name'].dirty || detailsForm.controls['name'].touched)">
|
||||
<input type="text" id="wallet-name" formControlName="name" [maxLength]="variablesService.maxWalletNameLength"
|
||||
(contextmenu)="variablesService.onContextMenu($event)">
|
||||
<div class="error-block"
|
||||
*ngIf="detailsForm.controls['name'].invalid && (detailsForm.controls['name'].dirty || detailsForm.controls['name'].touched)">
|
||||
<div *ngIf="detailsForm.controls['name'].errors['required']">
|
||||
{{ 'WALLET_DETAILS.FORM_ERRORS.NAME_REQUIRED' | translate }}
|
||||
</div>
|
||||
|
|
@ -33,24 +35,57 @@
|
|||
<label for="wallet-location">{{ 'WALLET_DETAILS.LABEL_FILE_LOCATION' | translate }}</label>
|
||||
<input type="text" id="wallet-location" formControlName="path" readonly>
|
||||
</div>
|
||||
|
||||
<div class="input-block textarea">
|
||||
<label for="seed-phrase">{{ 'WALLET_DETAILS.LABEL_SEED_PHRASE' | translate }}</label>
|
||||
<div class="seed-phrase" id="seed-phrase">
|
||||
<div class="seed-phrase-hint" (click)="showSeedPhrase()" *ngIf="!showSeed">{{ 'WALLET_DETAILS.SEED_PHRASE_HINT' | translate }}</div>
|
||||
<div class="seed-phrase-content" *ngIf="showSeed" (contextmenu)="variablesService.onContextMenuOnlyCopy($event, seedPhrase)">
|
||||
<ng-container *ngFor="let word of seedPhrase.split(' '); let index = index">
|
||||
<div class="word">{{(index + 1) + '. ' + word}}</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="wallet-buttons">
|
||||
<button type="submit" class="blue-button" [disabled]="!detailsForm.valid">{{ 'WALLET_DETAILS.BUTTON_SAVE' | translate }}</button>
|
||||
<button type="button" class="blue-button" (click)="closeWallet()">{{ 'WALLET_DETAILS.BUTTON_REMOVE' | translate }}</button>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<ng-container *ngIf="!showSeed else seedPhraseContent">
|
||||
<form class="form-seed mt-2" [formGroup]="seedPhraseForm" (ngSubmit)="onSubmitSeed()">
|
||||
<label>{{ 'WALLET_DETAILS.LABEL_SEED_PHRASE' | translate }}</label>
|
||||
<div class="form-content">
|
||||
<div class="seed-phrase-form">
|
||||
<div class="input-block">
|
||||
<label for="create-password">{{ 'WALLET_DETAILS.CREATE_PASSWORD_SECURE' | translate }} (<a class="text-coral">{{ 'WALLET_DETAILS.INFO' | translate }}</a>)</label>
|
||||
<input type="password" id="create-password" formControlName="password">
|
||||
</div>
|
||||
<div class="input-block">
|
||||
<label for="confirm-password">{{ 'WALLET_DETAILS.FORM.CONFIRM_PASSWORD' | translate }}</label>
|
||||
<input type="password" id="confirm-password" formControlName="confirmPassword">
|
||||
</div>
|
||||
<span class="error-message" *ngIf="!seedPhraseForm.valid">
|
||||
{{ 'WALLET_DETAILS.FORM_ERRORS.PASSWORDS_DONT_MATCH' | translate }}
|
||||
</span>
|
||||
|
||||
<button type="submit" class="blue-button" [disabled]="!seedPhraseForm.valid"><i class="icon safety"></i>
|
||||
{{ 'WALLET_DETAILS.FORM.GENERATE_SECURE_SEED' | translate }}</button>
|
||||
|
||||
<a class="secured-seed"><i class="icon info"></i>{{ 'WALLET_DETAILS.FORM.SECURED_SEED_WILL_REQUIRE' | translate }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ng-container>
|
||||
|
||||
<ng-template #seedPhraseContent>
|
||||
<div class="seed-phrase mt-2">
|
||||
<div class="seed-phrase-title">
|
||||
<span>{{ 'WALLET_DETAILS.LABEL_SEED_PHRASE' | translate }}</span>
|
||||
<p class="right-part">
|
||||
<i class="icon" [class.copy]="!copyAnimation" [class.copied]="copyAnimation" (click)="copySeedPhrase()"></i>
|
||||
<span
|
||||
*ngIf="seedPhraseForm.controls.password.value.length == 0">{{ 'WALLET_DETAILS.SEED_IS_UNSECURED' | translate }} <i class="icon unsecured"></i></span>
|
||||
<span
|
||||
*ngIf="seedPhraseForm.controls.password.value.length > 0">{{ 'WALLET_DETAILS.SEED_IS_SECURED' | translate }} <i class="icon secured"></i></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="seed-phrase-content">
|
||||
<ng-container *ngFor="let word of seedPhrase.split(' '); let index = index">
|
||||
<div class="item"
|
||||
[class.dark]="(index + 1) >= 1 && (index + 1) <= 7 || (index + 1) >= 15 && (index + 1) <= 21">
|
||||
{{(index + 1) + '. ' + word}}</div>
|
||||
</ng-container>
|
||||
</div>
|
||||
<div class="seed-phrase-footer"
|
||||
*ngIf="seedPhraseForm.controls.password.value.length > 0">
|
||||
<span class="title">{{ 'WALLET_DETAILS.REMEMBER_YOU_WILL_REQUIRE' | translate }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
|
@ -8,32 +8,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.seed-phrase {
|
||||
display: flex;
|
||||
font-size: 1.4rem;
|
||||
line-height: 1.5rem;
|
||||
padding: 1.4rem;
|
||||
width: 100%;
|
||||
height: 8.8rem;
|
||||
|
||||
.seed-phrase-hint {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.seed-phrase-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.wallet-buttons {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -45,5 +19,190 @@
|
|||
max-width: 15rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.form-seed {
|
||||
|
||||
label {
|
||||
color: #556576;
|
||||
font-size: 1.3rem;
|
||||
line-height: 2.4rem;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
border: 2px solid #2b3644;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 3rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.text-coral {
|
||||
color: #4db1ff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.seed-phrase-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
max-width: 38rem;
|
||||
width: 100%;
|
||||
|
||||
.input-block,
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.error-message {
|
||||
margin-top: 1rem;
|
||||
color: #ff6f00;
|
||||
}
|
||||
|
||||
.secured-seed {
|
||||
color: #e0e0e0;
|
||||
font-size: 1.2rem;
|
||||
line-height: 2.4rem;
|
||||
text-decoration: none;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.icon {
|
||||
margin-right: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 2rem;
|
||||
|
||||
.icon {
|
||||
margin-right: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.seed-phrase {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
background-color: transparent !important;
|
||||
|
||||
&-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
.right-part {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
.icon {
|
||||
cursor: pointer;
|
||||
width: 1.7rem;
|
||||
height: 1.7rem;
|
||||
|
||||
&.copy {
|
||||
background-color: #4caefb;
|
||||
margin-right: 1.2rem;
|
||||
mask: url(~src/assets/icons/copy.svg) no-repeat center;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
|
||||
&.copied {
|
||||
margin-right: 1.2rem;
|
||||
background-color: #4caefb;
|
||||
mask: url(~src/assets/icons/complete-testwallet.svg) no-repeat center;
|
||||
}
|
||||
&.secured, &.unsecured {
|
||||
margin-left: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
color: #556576;
|
||||
font-size: 1.3rem;
|
||||
line-height: 2.4rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
.icon {
|
||||
margin-left: 1.2rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-content {
|
||||
border-top: 2px solid #2b3644;
|
||||
border-bottom: 2px solid #2b3644;
|
||||
padding: 1rem 0 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin-bottom: 1rem;
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 2rem;
|
||||
width: calc(100% / 7);
|
||||
min-height: 35px;
|
||||
font-size: 1.3rem;
|
||||
color: #e0e0e0;
|
||||
|
||||
&.dark {
|
||||
background-color: #18202a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-footer {
|
||||
text-align: center;
|
||||
.title {
|
||||
color: #556576;
|
||||
font-size: 1.3rem;
|
||||
line-height: 2.4rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: inline-flex;
|
||||
width: 1.6rem;
|
||||
height: 1.6rem;
|
||||
|
||||
&.secured {
|
||||
background-color: #5cda9d;
|
||||
mask: url(~src/assets/icons/secured.svg) no-repeat center;
|
||||
}
|
||||
|
||||
&.info {
|
||||
background-color: #4caefb;
|
||||
mask: url(~src/assets/icons/info.svg) no-repeat center;
|
||||
}
|
||||
|
||||
&.unsecured {
|
||||
background-color: #ff6f00;
|
||||
mask: url(~src/assets/icons/unsecured.svg) no-repeat center;
|
||||
}
|
||||
|
||||
&.safety {
|
||||
background-color: #111921;
|
||||
mask: url(~src/assets/icons/safety.svg) no-repeat center;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,35 +1,64 @@
|
|||
import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';
|
||||
import {FormGroup, FormControl, Validators} from '@angular/forms';
|
||||
import {BackendService} from '../_helpers/services/backend.service';
|
||||
import {VariablesService} from '../_helpers/services/variables.service';
|
||||
import {Router} from '@angular/router';
|
||||
import {Location} from '@angular/common';
|
||||
import { Component, NgZone, OnDestroy, OnInit } from '@angular/core';
|
||||
import { FormGroup, FormControl, Validators } from '@angular/forms';
|
||||
import { BackendService } from '../_helpers/services/backend.service';
|
||||
import { VariablesService } from '../_helpers/services/variables.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { Location } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-wallet-details',
|
||||
templateUrl: './wallet-details.component.html',
|
||||
styleUrls: ['./wallet-details.component.scss']
|
||||
styleUrls: ['./wallet-details.component.scss'],
|
||||
})
|
||||
export class WalletDetailsComponent implements OnInit, OnDestroy {
|
||||
seedPhrase = '';
|
||||
showSeed = false;
|
||||
copyAnimation = false;
|
||||
copyAnimationTimeout;
|
||||
|
||||
detailsForm = new FormGroup({
|
||||
name: new FormControl('', [Validators.required, (g: FormControl) => {
|
||||
for (let i = 0; i < this.variablesService.wallets.length; i++) {
|
||||
if (g.value === this.variablesService.wallets[i].name) {
|
||||
if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {
|
||||
return {'same': true};
|
||||
} else {
|
||||
return {'duplicate': true};
|
||||
name: new FormControl('', [
|
||||
Validators.required,
|
||||
(g: FormControl) => {
|
||||
for (let i = 0; i < this.variablesService.wallets.length; i++) {
|
||||
if (g.value === this.variablesService.wallets[i].name) {
|
||||
if (
|
||||
this.variablesService.wallets[i].wallet_id ===
|
||||
this.variablesService.currentWallet.wallet_id
|
||||
) {
|
||||
return { same: true };
|
||||
} else {
|
||||
return { duplicate: true };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}]),
|
||||
path: new FormControl('')
|
||||
return null;
|
||||
},
|
||||
]),
|
||||
path: new FormControl(''),
|
||||
});
|
||||
|
||||
seedPhraseForm = new FormGroup(
|
||||
{
|
||||
password: new FormControl(
|
||||
'',
|
||||
Validators.pattern(this.variablesService.pattern)
|
||||
),
|
||||
confirmPassword: new FormControl(
|
||||
'',
|
||||
Validators.pattern(this.variablesService.pattern)
|
||||
),
|
||||
},
|
||||
{ validators: this.checkPasswords }
|
||||
);
|
||||
|
||||
checkPasswords(group: FormGroup) {
|
||||
const pass = group.controls.password.value;
|
||||
const confirmPass = group.controls.confirmPassword.value;
|
||||
|
||||
return pass === confirmPass ? null : { notSame: true };
|
||||
}
|
||||
|
||||
constructor(
|
||||
private router: Router,
|
||||
private backend: BackendService,
|
||||
|
|
@ -40,55 +69,91 @@ export class WalletDetailsComponent implements OnInit, OnDestroy {
|
|||
|
||||
ngOnInit() {
|
||||
this.showSeed = false;
|
||||
this.detailsForm.get('name').setValue(this.variablesService.currentWallet.name);
|
||||
this.detailsForm.get('path').setValue(this.variablesService.currentWallet.path);
|
||||
this.backend.getSmartWalletInfo(this.variablesService.currentWallet.wallet_id, (status, data) => {
|
||||
if (data.hasOwnProperty('restore_key')) {
|
||||
this.ngZone.run(() => {
|
||||
this.seedPhrase = data['restore_key'].trim();
|
||||
});
|
||||
}
|
||||
});
|
||||
this.detailsForm
|
||||
.get('name')
|
||||
.setValue(this.variablesService.currentWallet.name);
|
||||
this.detailsForm
|
||||
.get('path')
|
||||
.setValue(this.variablesService.currentWallet.path);
|
||||
}
|
||||
|
||||
showSeedPhrase() {
|
||||
this.showSeed = true;
|
||||
}
|
||||
|
||||
onSubmitSeed() {
|
||||
if (this.seedPhraseForm.valid) {
|
||||
this.showSeedPhrase();
|
||||
const wallet_id = this.variablesService.currentWallet.wallet_id;
|
||||
const seed_password = this.seedPhraseForm.controls.password.value;
|
||||
this.backend.getSmartWalletInfo(
|
||||
{ wallet_id, seed_password },
|
||||
(status, data) => {
|
||||
if (data.hasOwnProperty('seed_phrase')) {
|
||||
this.ngZone.run(() => {
|
||||
this.seedPhrase = data['seed_phrase'].trim();
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
onSubmitEdit() {
|
||||
if (this.detailsForm.value) {
|
||||
this.variablesService.currentWallet.name = this.detailsForm.get('name').value;
|
||||
this.variablesService.currentWallet.name = this.detailsForm.get(
|
||||
'name'
|
||||
).value;
|
||||
this.ngZone.run(() => {
|
||||
this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);
|
||||
this.router.navigate([
|
||||
'/wallet/' + this.variablesService.currentWallet.wallet_id,
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
closeWallet() {
|
||||
this.backend.closeWallet(this.variablesService.currentWallet.wallet_id, () => {
|
||||
for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {
|
||||
if (this.variablesService.wallets[i].wallet_id === this.variablesService.currentWallet.wallet_id) {
|
||||
this.variablesService.wallets.splice(i, 1);
|
||||
this.backend.closeWallet(
|
||||
this.variablesService.currentWallet.wallet_id,
|
||||
() => {
|
||||
for (let i = this.variablesService.wallets.length - 1; i >= 0; i--) {
|
||||
if (
|
||||
this.variablesService.wallets[i].wallet_id ===
|
||||
this.variablesService.currentWallet.wallet_id
|
||||
) {
|
||||
this.variablesService.wallets.splice(i, 1);
|
||||
}
|
||||
}
|
||||
this.ngZone.run(() => {
|
||||
if (this.variablesService.wallets.length) {
|
||||
this.variablesService.currentWallet = this.variablesService.wallets[0];
|
||||
this.router.navigate([
|
||||
'/wallet/' + this.variablesService.currentWallet.wallet_id,
|
||||
]);
|
||||
} else {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
});
|
||||
if (this.variablesService.appPass) {
|
||||
this.backend.storeSecureAppData();
|
||||
}
|
||||
}
|
||||
this.ngZone.run(() => {
|
||||
if (this.variablesService.wallets.length) {
|
||||
this.variablesService.currentWallet = this.variablesService.wallets[0];
|
||||
this.router.navigate(['/wallet/' + this.variablesService.currentWallet.wallet_id]);
|
||||
} else {
|
||||
this.router.navigate(['/']);
|
||||
}
|
||||
});
|
||||
if (this.variablesService.appPass) {
|
||||
this.backend.storeSecureAppData();
|
||||
}
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
back() {
|
||||
this.location.back();
|
||||
}
|
||||
|
||||
ngOnDestroy() {}
|
||||
copySeedPhrase() {
|
||||
this.backend.setClipboard(this.seedPhrase);
|
||||
this.copyAnimation = true;
|
||||
this.copyAnimationTimeout = window.setTimeout(() => {
|
||||
this.copyAnimation = false;
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
clearTimeout(this.copyAnimationTimeout);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,13 +120,16 @@
|
|||
"BUTTON_CREATE": "Create wallet",
|
||||
"NOT_CORRECT_FILE_OR_PASSWORD": "Invalid wallet file or password does not match",
|
||||
"CHOOSE_PATH": "Please choose a path",
|
||||
"SEED_PASSWORD": "Seed password",
|
||||
"OK": "OK",
|
||||
"FORM_ERRORS": {
|
||||
"NAME_REQUIRED": "Name is required",
|
||||
"NAME_DUPLICATE": "Name is duplicate",
|
||||
"MAX_LENGTH": "Maximum name length reached",
|
||||
"CONFIRM_NOT_MATCH": "Confirm password not match",
|
||||
"KEY_REQUIRED": "Key is required",
|
||||
"KEY_NOT_VALID": "Key not valid"
|
||||
"KEY_NOT_VALID": "Key not valid",
|
||||
"INCORRECT_PASSWORD": "Incorrect password"
|
||||
}
|
||||
},
|
||||
"SEED_PHRASE": {
|
||||
|
|
@ -214,10 +217,21 @@
|
|||
"SEED_PHRASE_HINT": "Click to reveal the seed phrase",
|
||||
"BUTTON_SAVE": "Save",
|
||||
"BUTTON_REMOVE": "Close wallet",
|
||||
"CREATE_PASSWORD_SECURE": "Create a password to secure your seed",
|
||||
"INFO": "info",
|
||||
"SEED_IS_UNSECURED": "Seed is unsecured",
|
||||
"SEED_IS_SECURED": "Seed is secured",
|
||||
"REMEMBER_YOU_WILL_REQUIRE": "Remember, you will require the password to restore it.",
|
||||
"FORM": {
|
||||
"CONFIRM_PASSWORD": "Confirm password",
|
||||
"GENERATE_SECURE_SEED": "Generate Secure Seed",
|
||||
"SECURED_SEED_WILL_REQUIRE": "Secured seed will require this password to restore."
|
||||
},
|
||||
"FORM_ERRORS": {
|
||||
"NAME_REQUIRED": "Name is required",
|
||||
"NAME_DUPLICATE": "Name is duplicate",
|
||||
"MAX_LENGTH": "Maximum name length reached"
|
||||
"MAX_LENGTH": "Maximum name length reached",
|
||||
"PASSWORDS_DONT_MATCH": "Passwords don't match"
|
||||
}
|
||||
},
|
||||
"ASSIGN_ALIAS": {
|
||||
|
|
|
|||
1
src/gui/qt-daemon/html_source/src/assets/icons/info.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 384"><defs><style>.cls-1{fill:#fff;}</style></defs><title>info</title><path class="cls-1" d="M192,42.05476A149.94522,149.94522,0,0,1,298.02728,298.02728,149.94522,149.94522,0,1,1,85.97271,85.97271,148.96374,148.96374,0,0,1,192,42.05476M192,0C85.96132,0,0,85.96132,0,192S85.96132,384,192,384s192-85.96132,192-192S298.03868,0,192,0Z"/><rect class="cls-1" x="171" y="247.94524" width="42" height="42"/><rect class="cls-1" x="171" y="94.05476" width="42" height="120"/></svg>
|
||||
|
After Width: | Height: | Size: 561 B |
21
src/gui/qt-daemon/html_source/src/assets/icons/safety.svg
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 22.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Слой_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 320 384" style="enable-background:new 0 0 320 384;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{clip-path:url(#SVGID_2_);}
|
||||
.st1{clip-path:url(#SVGID_2_);fill:none;stroke:#000000;stroke-width:42;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<g>
|
||||
<defs>
|
||||
<rect id="SVGID_1_" width="320" height="384"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use xlink:href="#SVGID_1_" style="overflow:visible;"/>
|
||||
</clipPath>
|
||||
<path class="st0" d="M159.9,44.5L278,85.8V232c0,0.9-0.4,9.2-14.7,26c-11,13-26.9,27.1-47.3,42c-20.6,15.1-41.6,27.8-56.1,36.1
|
||||
c-14.5-8.3-35.4-21-56-36.1c-20.3-14.9-36.2-29-47.2-42C42.4,241.2,42,232.9,42,232V85.8L159.9,44.5 M159.9,0L0,56v176
|
||||
c0,70.7,159.9,152,159.9,152S320,302.7,320,232V56L159.9,0z"/>
|
||||
<polyline class="st1" points="100.1,182.2 142.3,218.5 220.3,145.1 "/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1 KiB |
10
src/gui/qt-daemon/html_source/src/assets/icons/secured.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M26,15v-5c0-5.5-4.5-10-10-10h-0.1c-5.5,0-10,4.5-10,10v5H3v17h12.9H16h13V15H26z M9.9,10c0-3.3,2.7-6,6-6H16
|
||||
c3.3,0,6,2.7,6,6v5H9.9V10z M14,27v-7h4v7H14z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 582 B |
10
src/gui/qt-daemon/html_source/src/assets/icons/unsecured.svg
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 32 32" style="enable-background:new 0 0 32 32;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<path class="st0" d="M22,15h-3.4H9.9v-5c0-3.3,2.7-6,6-6H16c3,0,5.4,2.2,5.9,5h4c-0.5-5-4.8-9-9.9-9h-0.1c-5.5,0-10,4.5-10,10v5H3
|
||||
v17h12.9H16h13V15h-3H22z M18,27h-4v-7h4V27z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 581 B |
|
|
@ -205,6 +205,16 @@ button {
|
|||
color: themed(redTextColor);
|
||||
}
|
||||
}
|
||||
.success-block {
|
||||
font-size: 1rem;
|
||||
line-height: 1.4rem;
|
||||
align-self: flex-end;
|
||||
text-align: right;
|
||||
|
||||
@include themify($themes) {
|
||||
color: themed(greenTextColor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error-text {
|
||||
|
|
|
|||