1
0
Fork 0
forked from lthn/blockchain

Merge branch 'master' into offsig

This commit is contained in:
sowle 2019-04-23 02:07:41 +03:00
commit 6702b53662
30 changed files with 823 additions and 298 deletions

View file

@ -316,6 +316,7 @@ DISABLE_VS_WARNINGS(4355)
send_guard.unlock();//manual unlock
LOG_ERROR("send to [" << print_connection_context_short(context) << ", (" << (void*)this << ")] que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection");
close();
shutdown();
return false;
}
@ -351,6 +352,8 @@ DISABLE_VS_WARNINGS(4355)
template<class t_protocol_handler>
bool connection<t_protocol_handler>::shutdown()
{
if (m_was_shutdown)
return true;
// Initiate graceful connection closure.
boost::system::error_code ignored_ec;
socket_.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ignored_ec);

View file

@ -4,6 +4,7 @@
"SETUP_CONFIRM_PASS": "Confirm the password",
"MASTER_PASS": "Master password",
"BUTTON_NEXT": "Next",
"BUTTON_SKIP": "Skip",
"INCORRECT_PASSWORD": "Invalid password",
"FORM_ERRORS": {
"PASS_REQUIRED": "Password is required.",
@ -83,6 +84,13 @@
"NAME_REQUIRED": "Name is required.",
"NAME_DUPLICATE": "Name is duplicate.",
"MAX_LENGTH": "Maximum name length reached."
},
"MODAL": {
"TITLE": "Type wallet password",
"LABEL": "Password to this wallet",
"OPEN": "Open wallet",
"SKIP": "Skip",
"NOT_FOUND": "Not found"
}
},
"RESTORE_WALLET": {

View file

@ -780,3 +780,14 @@ app-progress-container {
}
}
}
app-open-wallet-modal {
.modal {
@include themify($themes) {
background: themed(modalBackground);
color: themed(mainTextColor);
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -13,9 +13,27 @@ export class BackendService {
backendObject: any;
backendLoaded = false;
constructor(private translate: TranslateService, private variablesService: VariablesService, private modalService: ModalService, private moneyToIntPipe: MoneyToIntPipe) {}
constructor(
private translate: TranslateService,
private variablesService: VariablesService,
private modalService: ModalService,
private moneyToIntPipe: MoneyToIntPipe
) {
}
private Debug(type, message) {
static bigNumberParser(key, val) {
if (val.constructor.name === 'BigNumber' && ['balance', 'unlocked_balance', 'amount', 'fee', 'b_fee', 'to_pay', 'a_pledge', 'b_pledge', 'coast', 'a'].indexOf(key) === -1) {
return val.toNumber();
}
if (key === 'rcv' || key === 'spn') {
for (let i = 0; i < val.length; i++) {
val[i] = new BigNumber(val[i]);
}
}
return val;
}
static Debug(type, message) {
switch (type) {
case 0:
console.error(message);
@ -112,13 +130,14 @@ export class BackendService {
}
}
break;
case 'NOT_FOUND': if (command !== 'open_wallet' && command !== 'get_alias_info_by_name' && command !== 'get_alias_info_by_address') {
error_translate = this.translate.instant('ERRORS.FILE_NOT_FOUND');
params = JSON.parse(params);
if (params.path) {
error_translate += ': ' + params.path;
case 'NOT_FOUND':
if (command !== 'open_wallet' && command !== 'get_alias_info_by_name' && command !== 'get_alias_info_by_address') {
error_translate = this.translate.instant('ERRORS.FILE_NOT_FOUND');
params = JSON.parse(params);
if (params.path) {
error_translate += ': ' + params.path;
}
}
}
break;
case 'CANCELED':
case '':
@ -142,36 +161,21 @@ export class BackendService {
}
}
private bigNumberParser(key, val) {
if (val.constructor.name === 'BigNumber' && ['balance', 'unlocked_balance', 'amount', 'fee', 'b_fee', 'to_pay', 'a_pledge', 'b_pledge', 'coast', 'a'].indexOf(key) === -1) {
return val.toNumber();
}
if (key === 'rcv' || key === 'spn') {
for (let i = 0; i < val.length; i++) {
val[i] = new BigNumber(val[i]);
}
}
return val;
}
private commandDebug(command, params, result) {
this.Debug(2, '----------------- ' + command + ' -----------------');
BackendService.Debug(2, '----------------- ' + command + ' -----------------');
const debug = {
_send_params: params,
_result: result
};
this.Debug(2, debug);
BackendService.Debug(2, debug);
try {
this.Debug(2, JSONBigNumber.parse(result, this.bigNumberParser));
BackendService.Debug(2, JSONBigNumber.parse(result, BackendService.bigNumberParser));
} catch (e) {
this.Debug(2, {response_data: result, error_code: 'OK'});
BackendService.Debug(2, {response_data: result, error_code: 'OK'});
}
}
private asVal(data) {
return {v: data};
}
private backendCallback(resultStr, params, callback, command) {
let Result = resultStr;
if (command !== 'get_clipboard') {
@ -179,7 +183,7 @@ export class BackendService {
Result = {};
} else {
try {
Result = JSONBigNumber.parse(resultStr, this.bigNumberParser);
Result = JSONBigNumber.parse(resultStr, BackendService.bigNumberParser);
} catch (e) {
Result = {response_data: resultStr, error_code: 'OK'};
}
@ -194,7 +198,7 @@ export class BackendService {
const Status = (Result.error_code === 'OK' || Result.error_code === 'TRUE');
if (!Status && Status !== undefined && Result.error_code !== undefined) {
this.Debug(1, 'API error for command: "' + command + '". Error code: ' + Result.error_code);
BackendService.Debug(1, 'API error for command: "' + command + '". Error code: ' + Result.error_code);
}
const data = ((typeof Result === 'object') && 'response_data' in Result) ? Result.response_data : Result;
@ -220,7 +224,7 @@ export class BackendService {
if (this.backendObject) {
const Action = this.backendObject[command];
if (!Action) {
this.Debug(0, 'Run Command Error! Command "' + command + '" don\'t found in backendObject');
BackendService.Debug(0, 'Run Command Error! Command "' + command + '" don\'t found in backendObject');
} else {
const that = this;
params = (typeof params === 'string') ? params : JSONBigNumber.stringify(params);
@ -245,7 +249,7 @@ export class BackendService {
this.backendObject[command].connect(callback);
} else {
this.backendObject[command].connect((str) => {
callback(JSONBigNumber.parse(str, this.bigNumberParser));
callback(JSONBigNumber.parse(str, BackendService.bigNumberParser));
});
}
}
@ -285,6 +289,12 @@ export class BackendService {
}
storeAppData(callback?) {
if (this.variablesService.wallets.length) {
this.variablesService.settings.wallets = [];
this.variablesService.wallets.forEach((wallet) => {
this.variablesService.settings.wallets.push({name: wallet.name, path: wallet.path});
});
}
this.runCommand('store_app_data', this.variablesService.settings, callback);
}
@ -292,10 +302,7 @@ export class BackendService {
this.runCommand('get_secure_app_data', pass, callback);
}
storeSecureAppData(callback) {
if (this.variablesService.appPass === '') {
return callback(false);
}
storeSecureAppData(callback?) {
const wallets = [];
this.variablesService.wallets.forEach((wallet) => {
wallets.push({name: wallet.name, pass: wallet.pass, path: wallet.path});
@ -305,6 +312,12 @@ export class BackendService {
});
}
dropSecureAppData(callback?) {
this.backendObject['drop_secure_app_data']((dataStore) => {
this.backendCallback(dataStore, {}, callback, 'drop_secure_app_data');
});
}
haveSecureAppData(callback) {
this.runCommand('have_secure_app_data', {}, callback);
}
@ -346,7 +359,7 @@ export class BackendService {
this.runCommand('open_wallet', params, callback);
}
closeWallet(wallet_id, callback) {
closeWallet(wallet_id, callback?) {
this.runCommand('close_wallet', {wallet_id: +wallet_id}, callback);
}
@ -354,7 +367,7 @@ export class BackendService {
this.runCommand('get_smart_wallet_info', {wallet_id: +wallet_id}, callback);
}
runWallet(wallet_id, callback) {
runWallet(wallet_id, callback?) {
this.runCommand('run_wallet', {wallet_id: +wallet_id}, callback);
}
@ -418,7 +431,7 @@ export class BackendService {
fee: this.variablesService.default_fee_big,
b_fee: this.variablesService.default_fee_big
};
this.Debug(1, params);
BackendService.Debug(1, params);
this.runCommand('create_proposal', params, callback);
}
@ -426,7 +439,7 @@ export class BackendService {
const params = {
wallet_id: parseInt(wallet_id, 10)
};
this.Debug(1, params);
BackendService.Debug(1, params);
this.runCommand('get_contracts', params, callback);
}
@ -435,7 +448,7 @@ export class BackendService {
wallet_id: parseInt(wallet_id, 10),
contract_id: contract_id
};
this.Debug(1, params);
BackendService.Debug(1, params);
this.runCommand('accept_proposal', params, callback);
}
@ -445,7 +458,7 @@ export class BackendService {
contract_id: contract_id,
release_type: release_type // "normal" or "burn"
};
this.Debug(1, params);
BackendService.Debug(1, params);
this.runCommand('release_contract', params, callback);
}
@ -456,7 +469,7 @@ export class BackendService {
fee: this.variablesService.default_fee_big,
expiration_period: parseInt(time, 10) * 60 * 60
};
this.Debug(1, params);
BackendService.Debug(1, params);
this.runCommand('request_cancel_contract', params, callback);
}
@ -465,7 +478,7 @@ export class BackendService {
wallet_id: parseInt(wallet_id, 10),
contract_id: contract_id
};
this.Debug(1, params);
BackendService.Debug(1, params);
this.runCommand('accept_cancel_contract', params, callback);
}
@ -506,7 +519,7 @@ export class BackendService {
this.runCommand('set_localization_strings', params, callback);
}
registerAlias (wallet_id, alias, address, fee, comment, reward, callback) {
registerAlias(wallet_id, alias, address, fee, comment, reward, callback) {
const params = {
wallet_id: wallet_id,
alias: {
@ -521,7 +534,7 @@ export class BackendService {
this.runCommand('request_alias_registration', params, callback);
}
updateAlias (wallet_id, alias, fee, callback) {
updateAlias(wallet_id, alias, fee, callback) {
const params = {
wallet_id: wallet_id,
alias: {
@ -535,24 +548,24 @@ export class BackendService {
this.runCommand('request_alias_update', params, callback);
}
getAllAliases (callback) {
getAllAliases(callback) {
this.runCommand('get_all_aliases', {}, callback);
}
getAliasByName (value, callback) {
getAliasByName(value, callback) {
return this.runCommand('get_alias_info_by_name', value, callback);
}
getAliasByAddress (value, callback) {
getAliasByAddress(value, callback) {
return this.runCommand('get_alias_info_by_address', value, callback);
}
getAliasCoast (alias, callback) {
getAliasCoast(alias, callback) {
this.runCommand('get_alias_coast', {v: alias}, callback);
}
getWalletAlias(address) {
if (address != null && this.variablesService.daemon_state === 2) {
if (address !== null && this.variablesService.daemon_state === 2) {
if (this.variablesService.aliasesChecked[address] == null) {
this.variablesService.aliasesChecked[address] = {};
if (this.variablesService.aliases.length) {

View file

@ -13,6 +13,7 @@ export class VariablesService {
public digits = 12;
public appPass = '';
public appLogin = false;
public moneyEquivalent = 0;
public defaultTheme = 'dark';
public defaultCurrency = 'ZAN';
@ -35,7 +36,8 @@ export class VariablesService {
language: 'en',
default_path: '/',
viewedContracts: [],
notViewedContracts: []
notViewedContracts: [],
wallets: []
};
public wallets: Array<Wallet> = [];
@ -56,6 +58,7 @@ export class VariablesService {
this.ngZone.run(() => {
this.idle.stop();
this.appPass = '';
this.appLogin = false;
this.router.navigate(['/login'], {queryParams: {type: 'auth'}});
});
});

View file

@ -1,4 +1,4 @@
<app-sidebar *ngIf="variablesService.appPass"></app-sidebar>
<app-sidebar *ngIf="variablesService.appLogin"></app-sidebar>
<div class="app-content scrolled-content">
<router-outlet *ngIf="[0, 1, 2].indexOf(variablesService.daemon_state) !== -1"></router-outlet>
@ -24,3 +24,6 @@
<ng-template contextMenuItem (execute)="contextMenuPaste($event.item)">{{ 'CONTEXT_MENU.PASTE' | translate }}</ng-template>
<ng-template contextMenuItem (execute)="contextMenuSelect($event.item)">{{ 'CONTEXT_MENU.SELECT' | translate }}</ng-template>
</context-menu>
<app-open-wallet-modal *ngIf="needOpenWallets.length" [wallets]="needOpenWallets"></app-open-wallet-modal>

View file

@ -20,6 +20,8 @@ export class AppComponent implements OnInit, OnDestroy {
onQuitRequest = false;
firstOnlineState = false;
needOpenWallets = [];
@ViewChild('allContextMenu') public allContextMenu: ContextMenuComponent;
@ViewChild('onlyCopyContextMenu') public onlyCopyContextMenu: ContextMenuComponent;
@ -75,8 +77,9 @@ export class AppComponent implements OnInit, OnDestroy {
this.ngZone.run(() => {
this.router.navigate(['/']);
});
this.needOpenWallets = [];
this.variablesService.daemon_state = 5;
this.backend.storeSecureAppData(() => {
const saveFunction = () => {
this.backend.storeAppData(() => {
const recursionCloseWallets = () => {
if (this.variablesService.wallets.length) {
@ -91,7 +94,14 @@ export class AppComponent implements OnInit, OnDestroy {
};
recursionCloseWallets();
});
});
};
if (this.variablesService.appPass) {
this.backend.storeSecureAppData(() => {
saveFunction();
});
} else {
saveFunction();
}
}
this.onQuitRequest = true;
});
@ -386,7 +396,8 @@ export class AppComponent implements OnInit, OnDestroy {
for (let i = 0, length = data.events.length; i < length; i++) {
switch (data.events[i].method) {
case 'CORE_EVENT_BLOCK_ADDED': break;
case 'CORE_EVENT_BLOCK_ADDED':
break;
case 'CORE_EVENT_ADD_ALIAS':
if (this.variablesService.aliasesChecked[data.events[i].details.address] != null) {
this.variablesService.aliasesChecked[data.events[i].details.address]['name'] = '@' + data.events[i].details.alias;
@ -439,7 +450,8 @@ export class AppComponent implements OnInit, OnDestroy {
}
this.variablesService.changeAliases();
break;
default: break;
default:
break;
}
}
}
@ -490,9 +502,17 @@ export class AppComponent implements OnInit, OnDestroy {
this.router.navigate(['/login'], {queryParams: {type: 'auth'}});
});
} else {
this.ngZone.run(() => {
this.router.navigate(['/login'], {queryParams: {type: 'reg'}});
});
if (Object.keys(data).length !== 0) {
this.needOpenWallets = JSON.parse(JSON.stringify(this.variablesService.settings.wallets));
this.ngZone.run(() => {
this.variablesService.appLogin = true;
this.router.navigate(['/']);
});
} else {
this.ngZone.run(() => {
this.router.navigate(['/login'], {queryParams: {type: 'reg'}});
});
}
}
});
}
@ -531,6 +551,9 @@ export class AppComponent implements OnInit, OnDestroy {
} else if (error === 'OVERFLOW') {
this.variablesService.aliases = [];
this.variablesService.enableAliasSearch = false;
this.variablesService.wallets.forEach(wallet => {
wallet.alias = this.backend.getWalletAlias(wallet.address);
});
} else {
this.variablesService.enableAliasSearch = true;
if (data.aliases && data.aliases.length) {
@ -547,10 +570,18 @@ export class AppComponent implements OnInit, OnDestroy {
wallet.alias = this.backend.getWalletAlias(wallet.address);
});
this.variablesService.aliases = this.variablesService.aliases.sort((a, b) => {
if (a.name.length > b.name.length) return 1;
if (a.name.length < b.name.length) return -1;
if (a.name > b.name) return 1;
if (a.name < b.name) return -1;
if (a.name.length > b.name.length) {
return 1;
}
if (a.name.length < b.name.length) {
return -1;
}
if (a.name > b.name) {
return 1;
}
if (a.name < b.name) {
return -1;
}
return 0;
});
this.variablesService.changeAliases();

View file

@ -10,6 +10,7 @@ import { SidebarComponent } from './sidebar/sidebar.component';
import { MainComponent } from './main/main.component';
import { CreateWalletComponent } from './create-wallet/create-wallet.component';
import { OpenWalletComponent } from './open-wallet/open-wallet.component';
import { OpenWalletModalComponent } from './open-wallet-modal/open-wallet-modal.component';
import { RestoreWalletComponent } from './restore-wallet/restore-wallet.component';
import { SeedPhraseComponent } from './seed-phrase/seed-phrase.component';
import { WalletDetailsComponent } from './wallet-details/wallet-details.component';
@ -73,6 +74,7 @@ Highcharts.setOptions({
MainComponent,
CreateWalletComponent,
OpenWalletComponent,
OpenWalletModalComponent,
RestoreWalletComponent,
SeedPhraseComponent,
WalletDetailsComponent,

View file

@ -77,6 +77,7 @@ export class CreateWalletComponent implements OnInit {
generate_data['wi'].mined_total,
generate_data['wi'].tracking_hey
);
this.variablesService.opening_wallet.alias = this.backend.getWalletAlias(generate_data['wi'].address);
this.ngZone.run(() => {
this.walletSaved = true;
this.progressWidth = '50%';

View file

@ -9,21 +9,11 @@
<div class="input-block">
<label for="master-pass">{{ 'LOGIN.SETUP_MASTER_PASS' | translate }}</label>
<input type="password" id="master-pass" formControlName="password" (contextmenu)="variablesService.onContextMenuPasteSelect($event)">
<div class="error-block" *ngIf="regForm.controls['password'].invalid && (regForm.controls['password'].dirty || regForm.controls['password'].touched)">
<div *ngIf="regForm.controls['password'].errors['required']">
{{ 'LOGIN.FORM_ERRORS.PASS_REQUIRED' | translate }}
</div>
</div>
</div>
<div class="input-block">
<label for="confirm-pass">{{ 'LOGIN.SETUP_CONFIRM_PASS' | translate }}</label>
<input type="password" id="confirm-pass" formControlName="confirmation" (contextmenu)="variablesService.onContextMenuPasteSelect($event)">
<div class="error-block" *ngIf="regForm.controls['confirmation'].invalid && (regForm.controls['confirmation'].dirty || regForm.controls['confirmation'].touched)">
<div *ngIf="regForm.controls['confirmation'].errors['required']">
{{ 'LOGIN.FORM_ERRORS.CONFIRM_REQUIRED' | translate }}
</div>
</div>
<div class="error-block" *ngIf="regForm.controls['password'].dirty && regForm.controls['confirmation'].dirty && regForm.errors">
<div *ngIf="regForm.errors['mismatch']">
{{ 'LOGIN.FORM_ERRORS.MISMATCH' | translate }}
@ -31,7 +21,10 @@
</div>
</div>
<button type="submit" class="blue-button">{{ 'LOGIN.BUTTON_NEXT' | translate }}</button>
<div class="wrap-button">
<button type="submit" class="blue-button" [disabled]="!regForm.controls['password'].value.length || !regForm.controls['confirmation'].value.length || (regForm.errors && regForm.errors['mismatch'])">{{ 'LOGIN.BUTTON_NEXT' | translate }}</button>
<button type="button" class="blue-button" (click)="onSkipCreatePass()" [disabled]="regForm.controls['password'].value.length || regForm.controls['confirmation'].value.length">{{ 'LOGIN.BUTTON_SKIP' | translate }}</button>
</div>
</form>
@ -40,11 +33,6 @@
<div class="input-block">
<label for="master-pass-login">{{ 'LOGIN.MASTER_PASS' | translate }}</label>
<input type="password" id="master-pass-login" formControlName="password" autofocus (contextmenu)="variablesService.onContextMenuPasteSelect($event)">
<div class="error-block" *ngIf="authForm.controls['password'].invalid && (authForm.controls['password'].dirty || authForm.controls['password'].touched)">
<div *ngIf="authForm.controls['password'].errors['required']">
{{ 'LOGIN.FORM_ERRORS.PASS_REQUIRED' | translate }}
</div>
</div>
</div>
<button type="submit" class="blue-button">{{ 'LOGIN.BUTTON_NEXT' | translate }}</button>

View file

@ -16,13 +16,23 @@
.logo {
background: url(../../assets/icons/logo.svg) no-repeat center;
width: 100%;
height: 20rem;
height: 15rem;
}
.form-login {
display: flex;
flex-direction: column;
.wrap-button {
display: flex;
align-items: center;
justify-content: space-between;
button {
margin: 2.5rem 0;
}
}
button {
margin: 2.5rem auto;
width: 100%;

View file

@ -16,14 +16,14 @@ export class LoginComponent implements OnInit, OnDestroy {
queryRouting;
regForm = new FormGroup({
password: new FormControl('', Validators.required),
confirmation: new FormControl('', Validators.required)
password: new FormControl(''),
confirmation: new FormControl('')
}, function (g: FormGroup) {
return g.get('password').value === g.get('confirmation').value ? null : {'mismatch': true};
});
authForm = new FormGroup({
password: new FormControl('', Validators.required)
password: new FormControl('')
});
type = 'reg';
@ -32,7 +32,7 @@ export class LoginComponent implements OnInit, OnDestroy {
private route: ActivatedRoute,
private router: Router,
private backend: BackendService,
private variablesService: VariablesService,
public variablesService: VariablesService,
private modalService: ModalService,
private ngZone: NgZone
) {
@ -51,6 +51,8 @@ export class LoginComponent implements OnInit, OnDestroy {
this.variablesService.appPass = this.regForm.get('password').value;
this.backend.storeSecureAppData((status, data) => {
if (status) {
this.variablesService.appLogin = true;
this.variablesService.startCountdown();
this.ngZone.run(() => {
this.router.navigate(['/']);
});
@ -61,11 +63,20 @@ export class LoginComponent implements OnInit, OnDestroy {
}
}
onSkipCreatePass(): void {
this.variablesService.appPass = '';
this.ngZone.run(() => {
this.variablesService.appLogin = true;
this.router.navigate(['/']);
});
}
onSubmitAuthPass(): void {
if (this.authForm.valid) {
const appPass = this.authForm.get('password').value;
this.backend.getSecureAppData({pass: appPass}, (status, data) => {
if (!data.error_code) {
this.variablesService.appLogin = true;
this.variablesService.startCountdown();
this.variablesService.appPass = appPass;
if (this.variablesService.wallets.length) {

View file

@ -0,0 +1,18 @@
<div class="modal">
<h3 class="title">{{ 'OPEN_WALLET.MODAL.TITLE' | translate }}</h3>
<form class="open-form" (ngSubmit)="openWallet()">
<div class="wallet-path">{{ wallet.name }}</div>
<div class="wallet-path">{{ wallet.path }}</div>
<div class="input-block" *ngIf="!wallet.notFound && !wallet.emptyPass">
<label for="password">{{ 'OPEN_WALLET.MODAL.LABEL' | translate }}</label>
<input type="password" id="password" name="password" [(ngModel)]="wallet.pass" (contextmenu)="variablesService.onContextMenuPasteSelect($event)"/>
</div>
<div class="error-block" *ngIf="wallet.notFound">
{{ 'OPEN_WALLET.MODAL.NOT_FOUND' | translate }}
</div>
<div class="wrap-button">
<button type="submit" class="blue-button" [disabled]="wallet.notFound">{{ 'OPEN_WALLET.MODAL.OPEN' | translate }}</button>
<button type="button" class="blue-button" (click)="skipWallet()">{{ 'OPEN_WALLET.MODAL.SKIP' | translate }}</button>
</div>
</form>
</div>

View file

@ -0,0 +1,45 @@
:host {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.25);
}
.modal {
display: flex;
flex-direction: column;
background-position: center;
background-size: 200%;
padding: 2rem;
width: 34rem;
.title {
font-size: 1.8rem;
text-align: center;
}
.open-form {
.wallet-path {
font-size: 1.3rem;
margin: 5rem 0 2rem;
}
.wrap-button {
display: flex;
align-items: center;
justify-content: space-between;
margin: 2rem -2rem 0;
button {
flex: 1 0 0;
margin: 0 2rem ;
}
}
}
}

View file

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { OpenWalletModalComponent } from './open-wallet-modal.component';
describe('OpenWalletModalComponent', () => {
let component: OpenWalletModalComponent;
let fixture: ComponentFixture<OpenWalletModalComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ OpenWalletModalComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(OpenWalletModalComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View file

@ -0,0 +1,121 @@
import {Component, OnInit, Input, NgZone} from '@angular/core';
import {VariablesService} from '../_helpers/services/variables.service';
import {Wallet} from '../_helpers/models/wallet.model';
import {BackendService} from '../_helpers/services/backend.service';
import {TranslateService} from '@ngx-translate/core';
import {ModalService} from '../_helpers/services/modal.service';
@Component({
selector: 'app-open-wallet-modal',
templateUrl: './open-wallet-modal.component.html',
styleUrls: ['./open-wallet-modal.component.scss']
})
export class OpenWalletModalComponent implements OnInit {
@Input() wallets;
wallet = {
name: '',
path: '',
pass: '',
notFound: false,
emptyPass: false
};
constructor(
public variablesService: VariablesService,
private backend: BackendService,
private translate: TranslateService,
private modalService: ModalService,
private ngZone: NgZone,
) {
}
ngOnInit() {
if (this.wallets.length) {
this.wallet = this.wallets[0];
this.wallet.pass = '';
this.backend.openWallet(this.wallet.path, '', true, (status, data, error) => {
if (error === 'FILE_NOT_FOUND') {
this.wallet.notFound = true;
}
if (status) {
this.wallet.pass = '';
this.wallet.emptyPass = true;
this.backend.closeWallet(data.wallet_id);
this.openWallet();
}
});
}
}
openWallet() {
if (this.wallets.length === 0) {
return;
}
this.backend.openWallet(this.wallet.path, this.wallet.pass, false, (open_status, open_data, open_error) => {
if (open_error && open_error === 'FILE_NOT_FOUND') {
let error_translate = this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND1');
error_translate += ':<br>' + this.wallet.path;
error_translate += this.translate.instant('OPEN_WALLET.FILE_NOT_FOUND2');
this.modalService.prepareModal('error', error_translate);
} else {
if (open_status || open_error === 'FILE_RESTORED') {
let exists = false;
this.variablesService.wallets.forEach((wallet) => {
if (wallet.address === open_data['wi'].address) {
exists = true;
}
});
if (exists) {
this.modalService.prepareModal('error', 'OPEN_WALLET.WITH_ADDRESS_ALREADY_OPEN');
this.backend.closeWallet(open_data.wallet_id);
} else {
const new_wallet = new Wallet(
open_data.wallet_id,
this.wallet.name,
this.wallet.pass,
open_data['wi'].path,
open_data['wi'].address,
open_data['wi'].balance,
open_data['wi'].unlocked_balance,
open_data['wi'].mined_total,
open_data['wi'].tracking_hey
);
new_wallet.alias = this.backend.getWalletAlias(new_wallet.address);
if (open_data.recent_history && open_data.recent_history.history) {
new_wallet.prepareHistory(open_data.recent_history.history);
}
this.backend.getContracts(open_data.wallet_id, (contracts_status, contracts_data) => {
if (contracts_status && contracts_data.hasOwnProperty('contracts')) {
this.ngZone.run(() => {
new_wallet.prepareContractsAfterOpen(
contracts_data.contracts,
this.variablesService.exp_med_ts,
this.variablesService.height_app,
this.variablesService.settings.viewedContracts,
this.variablesService.settings.notViewedContracts
);
});
}
});
this.variablesService.wallets.push(new_wallet);
this.backend.runWallet(open_data.wallet_id);
this.skipWallet();
}
}
}
});
}
skipWallet() {
if (this.wallets.length) {
this.wallets.splice(0, 1);
this.ngOnInit();
}
}
}

View file

@ -110,9 +110,9 @@ export class OpenWalletComponent implements OnInit, OnDestroy {
this.variablesService.wallets.push(new_wallet);
this.backend.runWallet(open_data.wallet_id, (run_status, run_data) => {
if (run_status) {
this.backend.storeSecureAppData((status, data) => {
console.log('Store App Data', status, data);
});
if (this.variablesService.appPass) {
this.backend.storeSecureAppData();
}
this.ngZone.run(() => {
this.router.navigate(['/wallet/' + open_data.wallet_id]);
});

View file

@ -1,5 +1,5 @@
import {Component, NgZone, OnDestroy, OnInit} from '@angular/core';
import {Location} from "@angular/common";
import {Location} from '@angular/common';
import {BackendService} from '../_helpers/services/backend.service';
import {ActivatedRoute, Router} from '@angular/router';
import {VariablesService} from '../_helpers/services/variables.service';
@ -52,9 +52,9 @@ export class SeedPhraseComponent implements OnInit, OnDestroy {
this.backend.runWallet(this.wallet_id, (run_status, run_data) => {
if (run_status) {
this.variablesService.wallets.push(this.variablesService.opening_wallet);
this.backend.storeSecureAppData((status, data) => {
console.log('Store App Data', status, data);
});
if (this.variablesService.appPass) {
this.backend.storeSecureAppData();
}
this.ngZone.run(() => {
this.router.navigate(['/wallet/' + this.wallet_id]);
});

View file

@ -54,14 +54,9 @@
<span class="master-password-title">{{ 'SETTINGS.MASTER_PASSWORD.TITLE' | translate }}</span>
<div class="input-block">
<div class="input-block" *ngIf="variablesService.appPass">
<label for="old-password">{{ 'SETTINGS.MASTER_PASSWORD.OLD' | translate }}</label>
<input type="password" id="old-password" formControlName="password" (contextmenu)="variablesService.onContextMenuPasteSelect($event)"/>
<div class="error-block" *ngIf="changeForm.controls['password'].invalid && (changeForm.controls['password'].dirty || changeForm.controls['password'].touched)">
<div *ngIf="changeForm.controls['password'].errors['required']">
{{ 'SETTINGS.FORM_ERRORS.PASS_REQUIRED' | translate }}
</div>
</div>
<div class="error-block" *ngIf="changeForm.invalid && changeForm.controls['password'].valid && (changeForm.controls['password'].dirty || changeForm.controls['password'].touched) && changeForm.errors && changeForm.errors.pass_mismatch">
{{ 'SETTINGS.FORM_ERRORS.PASS_NOT_MATCH' | translate }}
</div>
@ -70,21 +65,11 @@
<div class="input-block">
<label for="new-password">{{ 'SETTINGS.MASTER_PASSWORD.NEW' | translate }}</label>
<input type="password" id="new-password" formControlName="new_password" (contextmenu)="variablesService.onContextMenuPasteSelect($event)"/>
<div class="error-block" *ngIf="changeForm.controls['new_password'].invalid && (changeForm.controls['new_password'].dirty || changeForm.controls['new_password'].touched)">
<div *ngIf="changeForm.controls['new_password'].errors['required']">
{{ 'SETTINGS.FORM_ERRORS.PASS_REQUIRED' | translate }}
</div>
</div>
</div>
<div class="input-block">
<label for="confirm-password">{{ 'SETTINGS.MASTER_PASSWORD.CONFIRM' | translate }}</label>
<input type="password" id="confirm-password" formControlName="new_confirmation" (contextmenu)="variablesService.onContextMenuPasteSelect($event)"/>
<div class="error-block" *ngIf="changeForm.controls['new_confirmation'].invalid && (changeForm.controls['new_confirmation'].dirty || changeForm.controls['new_confirmation'].touched)">
<div *ngIf="changeForm.controls['new_confirmation'].errors['required']">
{{ 'SETTINGS.FORM_ERRORS.PASS_REQUIRED' | translate }}
</div>
</div>
<div class="error-block" *ngIf="changeForm.invalid && (changeForm.controls['new_confirmation'].dirty || changeForm.controls['new_confirmation'].touched) && changeForm.errors && changeForm.errors.confirm_mismatch">
{{ 'SETTINGS.FORM_ERRORS.CONFIRM_NOT_MATCH' | translate }}
</div>

View file

@ -1,7 +1,7 @@
import {Component, NgZone, OnInit, Renderer2} from '@angular/core';
import {VariablesService} from '../_helpers/services/variables.service';
import {BackendService} from '../_helpers/services/backend.service';
import {FormControl, FormGroup, Validators} from '@angular/forms';
import {FormControl, FormGroup} from '@angular/forms';
import {Location} from '@angular/common';
@Component({
@ -63,13 +63,16 @@ export class SettingsComponent implements OnInit {
this.theme = this.variablesService.settings.theme;
this.scale = this.variablesService.settings.scale;
this.changeForm = new FormGroup({
password: new FormControl('', Validators.required),
new_password: new FormControl('', Validators.required),
new_confirmation: new FormControl('', Validators.required)
password: new FormControl(''),
new_password: new FormControl(''),
new_confirmation: new FormControl('')
}, [(g: FormGroup) => {
return g.get('new_password').value === g.get('new_confirmation').value ? null : {'confirm_mismatch': true};
}, (g: FormGroup) => {
return g.get('password').value === this.variablesService.appPass ? null : {'pass_mismatch': true};
if (this.variablesService.appPass) {
return g.get('password').value === this.variablesService.appPass ? null : {'pass_mismatch': true};
}
return null;
}]);
}
@ -99,18 +102,19 @@ export class SettingsComponent implements OnInit {
onSubmitChangePass() {
if (this.changeForm.valid) {
this.variablesService.appPass = this.changeForm.get('new_password').value;
this.backend.storeSecureAppData((status, data) => {
if (status) {
this.changeForm.reset();
} else {
console.log(data);
}
});
if (this.variablesService.appPass) {
this.backend.storeSecureAppData();
} else {
this.backend.dropSecureAppData();
}
this.changeForm.reset();
}
}
onLockChange() {
this.variablesService.restartCountdown();
if (this.variablesService.appLogin) {
this.variablesService.restartCountdown();
}
this.backend.storeAppData();
}

View file

@ -49,6 +49,7 @@ export class SidebarComponent implements OnInit, OnDestroy {
logOut() {
this.variablesService.stopCountdown();
this.variablesService.appLogin = false;
this.variablesService.appPass = '';
this.ngZone.run(() => {
this.router.navigate(['/login'], {queryParams: {type: 'auth'}});

View file

@ -72,16 +72,17 @@ export class WalletDetailsComponent implements OnInit, OnDestroy {
this.variablesService.wallets.splice(i, 1);
}
}
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(['/']);
}
});
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();
}
});
}

View file

@ -4,6 +4,7 @@
"SETUP_CONFIRM_PASS": "Confirm the password",
"MASTER_PASS": "Master password",
"BUTTON_NEXT": "Next",
"BUTTON_SKIP": "Skip",
"INCORRECT_PASSWORD": "Invalid password",
"FORM_ERRORS": {
"PASS_REQUIRED": "Password is required.",
@ -83,6 +84,13 @@
"NAME_REQUIRED": "Name is required.",
"NAME_DUPLICATE": "Name is duplicate.",
"MAX_LENGTH": "Maximum name length reached."
},
"MODAL": {
"TITLE": "Type wallet password",
"LABEL": "Password to this wallet",
"OPEN": "Open wallet",
"SKIP": "Skip",
"NOT_FOUND": "Not found"
}
},
"RESTORE_WALLET": {

View file

@ -780,3 +780,14 @@ app-progress-container {
}
}
}
app-open-wallet-modal {
.modal {
@include themify($themes) {
background: themed(modalBackground);
color: themed(mainTextColor);
}
}
}

View file

@ -12,4 +12,4 @@ EOM
esac
printf "tx_daily_count.value "
connectivity_tool --ip=127.0.0.1 --rpc-port=$ZANO_RPC_PORT --timeout=1000 --rpc-get-daemon-info --getinfo-flags-hex="0x0000000000000080" | grep transactions_cnt_per_day | cut -d ' ' -f2
connectivity_tool --ip=127.0.0.1 --rpc-port=$ZANO_RPC_PORT --timeout=10000 --rpc-get-daemon-info --getinfo-flags-hex="0x0000000000000080" | grep transactions_cnt_per_day | cut -d ' ' -f2

View file

@ -12,4 +12,4 @@ EOM
esac
printf "tx_daily_volume.value "
connectivity_tool --ip=127.0.0.1 --rpc-port=$ZANO_RPC_PORT --timeout=1000 --rpc-get-daemon-info --getinfo-flags-hex="0x0000000000000080" | grep transactions_volume_per_day | cut -d ' ' -f2
connectivity_tool --ip=127.0.0.1 --rpc-port=$ZANO_RPC_PORT --timeout=10000 --rpc-get-daemon-info --getinfo-flags-hex="0x0000000000000080" | grep transactions_volume_per_day | cut -d ' ' -f2