Commit 750b2f19 authored by Pieterjan Vanhoof's avatar Pieterjan Vanhoof Committed by GitHub

Merge pull request #233 from stratisproject/ui

Add Stratis
parents dfc76ea9 5d2e3ac1
......@@ -61,22 +61,10 @@ function createWindow() {
// Emitted when the window is going to close.
mainWindow.on('close', function () {
if (process.platform !== 'darwin' && !serve) {
var http = require('http');
const options = {
hostname: 'localhost',
port: 5000,
path: '/api/node/shutdown',
method: 'POST'
};
const req = http.request(options, (res) => {});
req.write('');
req.end();
}
}
);
}
closeBitcoinApi(),
closeStratisApi();
})
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
......@@ -86,7 +74,8 @@ app.on('ready', function () {
console.log("Breeze UI was started in development mode. This requires the user to be running the Breeze Daemon himself.")
}
else {
startApi();
startBitcoinApi();
startStratisApi();
}
createTray();
createWindow();
......@@ -113,17 +102,73 @@ app.on('activate', function () {
}
});
function startApi() {
var apiProcess;
const exec = require('child_process').exec;
function closeBitcoinApi() {
if (process.platform !== 'darwin' && !serve) {
var http1 = require('http');
const options1 = {
hostname: 'localhost',
port: 5000,
path: '/api/node/shutdown',
method: 'POST'
};
const req = http1.request(options1, (res) => {});
req.write('');
req.end();
}
};
function closeStratisApi() {
if (process.platform !== 'darwin' && !serve) {
var http2 = require('http');
const options2 = {
hostname: 'localhost',
port: 5105,
path: '/api/node/shutdown',
method: 'POST'
};
const req = http2.request(options2, (res) => {});
req.write('');
req.end();
}
};
function startBitcoinApi() {
var bitcoinProcess;
const execBitcoin = require('child_process').exec;
//Start Breeze Bitcoin Daemon
let apiPath = path.join(__dirname, '".//assets//daemon//Breeze.Daemon"');
if (os.platform() === 'win32') {
apiPath = path.join(__dirname, '".\\assets\\daemon\\Breeze.Daemon.exe"');
}
bitcoinProcess = execBitcoin('"' + apiPath + '" light -testnet', {
detached: true
}, (error, stdout, stderr) => {
if (error) {
writeLogError(`exec error: ${error}`);
return;
}
if (serve) {
writeLog(`stdout: ${stdout}`);
writeLog(`stderr: ${stderr}`);
}
});
}
function startStratisApi() {
var stratisProcess;
const execStratis = require('child_process').exec;
//Start Breeze Daemon
//Start Breeze Stratis Daemon
let apiPath = path.join(__dirname, '".//assets//daemon//Breeze.Daemon"');
if (os.platform() === 'win32') {
apiPath = path.join(__dirname, '".\\assets\\daemon\\Breeze.Daemon.exe"');
}
apiProcess = exec('"' + apiPath + '" light -testnet', {
stratisProcess = execStratis('"' + apiPath + '" stratis light -testnet', {
detached: true
}, (error, stdout, stderr) => {
if (error) {
......
......@@ -20,6 +20,7 @@ export class LoginComponent implements OnInit {
private openWalletForm: FormGroup;
private hasWallet: boolean = false;
private wallets: [string];
private isDecrypting = false;
ngOnInit() {
this.getWalletFiles();
......@@ -62,34 +63,6 @@ export class LoginComponent implements OnInit {
}
};
private updateWalletFileDisplay(walletName: string) {
this.openWalletForm.patchValue({selectWallet: walletName})
}
private onDecryptClicked() {
this.setGlobalWalletName(this.openWalletForm.get("selectWallet").value);
let walletLoad = new WalletLoad(
this.openWalletForm.get("password").value,
this.globalService.getWalletPath(),
this.openWalletForm.get("selectWallet").value
);
this.loadWallet(walletLoad);
}
private onCreateClicked() {
this.router.navigate(['/setup']);
}
private onEnter() {
if (this.openWalletForm.valid) {
this.onDecryptClicked();
}
}
private setGlobalWalletName(walletName: string) {
this.globalService.setWalletName(walletName);
}
private getWalletFiles() {
this.apiService.getWalletFiles()
.subscribe(
......@@ -125,17 +98,71 @@ export class LoginComponent implements OnInit {
;
}
private loadWallet(walletLoad: WalletLoad) {
this.apiService.loadWallet(walletLoad)
private updateWalletFileDisplay(walletName: string) {
this.openWalletForm.patchValue({selectWallet: walletName})
}
private onCreateClicked() {
this.router.navigate(['/setup']);
}
private onEnter() {
if (this.openWalletForm.valid) {
this.onDecryptClicked();
}
}
private onDecryptClicked() {
this.isDecrypting = true;
this.globalService.setWalletName(this.openWalletForm.get("selectWallet").value);
let walletLoad = new WalletLoad(
this.openWalletForm.get("selectWallet").value,
this.openWalletForm.get("password").value
);
this.loadWallets(walletLoad);
}
private loadWallets(walletLoad: WalletLoad) {
this.apiService.loadBitcoinWallet(walletLoad)
.subscribe(
response => {
if (response.status >= 200 && response.status < 400) {
this.globalService.setWalletName(walletLoad.name)
// Set Bitcoin as the default wallet
this.globalService.setCoinName("TestBitcoin");
this.globalService.setCoinUnit("TBTC");
this.globalService.setWalletName(walletLoad.name);
this.globalService.setCoinType(1);
}
},
error => {
this.isDecrypting = false;
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
if (!error.json().errors[0]) {
console.log(error);
}
else {
alert(error.json().errors[0].message);
}
}
},
() => this.loadStratisWallet(walletLoad)
)
;
}
private loadStratisWallet(walletLoad: WalletLoad) {
this.apiService.loadStratisWallet(walletLoad)
.subscribe(
response => {
if (response.status >= 200 && response.status < 400) {
// Navigate to the wallet section
this.router.navigate(['/wallet']);
}
},
error => {
this.isDecrypting = false;
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
......
......@@ -34,7 +34,7 @@
</div>
<!-- /row-->
<div class="row d-flex justify-content-center">
<button type="button" class="btn btn-darkgray btn-lg" [disabled]="!createWalletForm.valid" (click)="onCreateClicked()">Create</button>
<button type="button" class="btn btn-darkgray btn-lg" [disabled]="!createWalletForm.valid || isCreating" (click)="onCreateClicked()">Create</button>
</div>
<!-- /row-->
</div>
......
import { Component, Injectable } from '@angular/core';
import { Component, Injectable, OnInit } from '@angular/core';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
import { Router } from '@angular/router';
......@@ -16,7 +16,7 @@ import { Mnemonic } from '../../shared/classes/mnemonic';
styleUrls: ['./create.component.css'],
})
export class CreateComponent {
export class CreateComponent implements OnInit {
constructor(private globalService: GlobalService, private apiService: ApiService, private router: Router, private fb: FormBuilder) {
this.buildCreateForm();
}
......@@ -24,13 +24,18 @@ export class CreateComponent {
private createWalletForm: FormGroup;
private newWallet: WalletCreation;
private mnemonic: string;
private isCreating: Boolean = false;
ngOnInit() {
this.getNewMnemonic();
}
private buildCreateForm(): void {
this.createWalletForm = this.fb.group({
"walletName": ["",
Validators.compose([
Validators.required,
Validators.minLength(3),
Validators.minLength(1),
Validators.maxLength(24),
Validators.pattern(/^[a-zA-Z0-9]*$/)
])
......@@ -75,10 +80,10 @@ export class CreateComponent {
validationMessages = {
'walletName': {
'required': 'Name is required.',
'minlength': 'Name must be at least 3 characters long.',
'maxlength': 'Name cannot be more than 24 characters long.',
'pattern': 'Enter a valid wallet name. [a-Z] and [0-9] are the only characters allowed.'
'required': 'A wallet name is required.',
'minlength': 'A wallet name must be at least one character long.',
'maxlength': 'A wallet name cannot be more than 24 characters long.',
'pattern': 'Please enter a valid wallet name. [a-Z] and [0-9] are the only characters allowed.'
},
'walletPassword': {
'required': 'A password is required.',
......@@ -95,27 +100,84 @@ export class CreateComponent {
}
private onCreateClicked() {
this.isCreating = true;
if (this.mnemonic) {
this.newWallet = new WalletCreation(
this.createWalletForm.get("walletName").value,
this.mnemonic,
this.createWalletForm.get("walletPassword").value,
this.createWalletForm.get("selectNetwork").value,
this.globalService.getWalletPath(),
this.createWalletForm.get("walletName").value
this.createWalletForm.get("selectNetwork").value
);
this.createWallet(this.newWallet);
this.createWallets(this.newWallet);
}
}
private createWallet(wallet: WalletCreation) {
private getNewMnemonic() {
this.apiService
.createWallet(wallet)
.getNewMnemonic()
.subscribe(
response => {
if (response.status >= 200 && response.status < 400){
this.mnemonic = response.json();
}
},
error => {
console.log(error);
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
if (!error.json().errors[0]) {
console.log(error);
}
else {
alert(error.json().errors[0].message);
}
}
}
)
;
}
private createWallets(wallet: WalletCreation) {
this.apiService
.createBitcoinWallet(wallet)
.subscribe(
response => {
if (response.status >= 200 && response.status < 400){
// Bitcoin wallet created
}
},
error => {
console.log(error);
this.isCreating = false;
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
if (!error.json().errors[0]) {
console.log(error);
}
else {
alert(error.json().errors[0].message);
}
}
},
() => this.createStratisWallet(wallet)
)
;
}
private createStratisWallet(wallet: WalletCreation) {
this.apiService
.createStratisWallet(wallet)
.subscribe(
response => {
if (response.status >= 200 && response.status < 400){
alert("Your wallet has been created.\n\nPlease write down your 12 word passphrase: \n" + this.mnemonic + "\n\nYou can recover your wallet on any computer with:\n- your passphrase AND\n- your password AND\n- the wallet creation time\n\nUnlike most other wallets if an attacker acquires your passphrase, it will not be able to hack your wallet without knowing your password. On the contrary, unlike other wallets, you will not be able to recover your wallet only with your passphrase if you lose your password.");
this.router.navigate(['']);
}
},
error => {
this.isCreating = false;
console.log(error);
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
......
......@@ -37,7 +37,7 @@
</div>
<!-- /row-->
<div class="row d-flex justify-content-center">
<button type="button" class="btn btn-darkgray btn-lg" [disabled]="!recoverWalletForm.valid" (click)="onRecoverClicked()">Recover</button>
<button type="button" class="btn btn-darkgray btn-lg" [disabled]="!recoverWalletForm.valid || isRecovering" (click)="onRecoverClicked()">Recover</button>
</div>
<!-- /row-->
</div>
......
......@@ -22,6 +22,7 @@ export class RecoverComponent implements OnInit {
private recoverWalletForm: FormGroup;
private creationDate: Date;
private walletRecovery: WalletRecovery;
private isRecovering: Boolean = false;
private responseMessage: string;
private errorMessage: string;
......@@ -35,8 +36,9 @@ export class RecoverComponent implements OnInit {
"walletPassword": ["", Validators.required],
"walletName": ["", [
Validators.required,
Validators.minLength(3),
Validators.maxLength(24)
Validators.minLength(1),
Validators.maxLength(24),
Validators.pattern(/^[a-zA-Z0-9]*$/)
]
],
"selectNetwork": ["test", Validators.required]
......@@ -77,10 +79,11 @@ export class RecoverComponent implements OnInit {
'required': 'A password is required.'
},
'walletName': {
'required': 'Name is required.',
'minlength': 'Name must be at least 3 characters long.',
'maxlength': 'Name cannot be more than 24 characters long.'
}
'required': 'A wallet name is required.',
'minlength': 'A wallet name must be at least one character long.',
'maxlength': 'A wallet name cannot be more than 24 characters long.',
'pattern': 'Please enter a valid wallet name. [a-Z] and [0-9] are the only characters allowed.'
},
};
private onBackClicked() {
......@@ -88,21 +91,48 @@ export class RecoverComponent implements OnInit {
}
private onRecoverClicked(){
this.isRecovering = true;
this.walletRecovery = new WalletRecovery(
this.recoverWalletForm.get("walletName").value,
this.recoverWalletForm.get("walletMnemonic").value,
this.recoverWalletForm.get("walletPassword").value,
this.recoverWalletForm.get("selectNetwork").value,
this.globalService.getWalletPath(),
this.recoverWalletForm.get("walletName").value,
this.creationDate
);
this.recoverWallet(this.walletRecovery);
this.recoverWallets(this.walletRecovery);
}
private recoverWallet(recoverWallet: WalletRecovery) {
private recoverWallets(recoverWallet: WalletRecovery) {
this.apiService
.recoverBitcoinWallet(recoverWallet)
.subscribe(
response => {
if (response.status >= 200 && response.status < 400) {
//Bitcoin Wallet Recovered
}
},
error => {
this.isRecovering = false;
console.log(error);
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
if (!error.json().errors[0]) {
console.log(error);
}
else {
alert(error.json().errors[0].message);
}
}
},
() => this.recoverStratisWallet(recoverWallet)
)
;
}
private recoverStratisWallet(recoverWallet: WalletRecovery){
this.apiService
.recoverWallet(recoverWallet)
.recoverStratisWallet(recoverWallet)
.subscribe(
response => {
if (response.status >= 200 && response.status < 400) {
......@@ -112,6 +142,7 @@ export class RecoverComponent implements OnInit {
}
},
error => {
this.isRecovering = false;
console.log(error);
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
......@@ -124,6 +155,7 @@ export class RecoverComponent implements OnInit {
}
}
}
);
)
;
}
}
export class WalletCreation {
constructor(password: string, network:string, folderPath: string, name: string) {
constructor(name: string, mnemonic: string, password: string, network:string, folderPath: string = null ) {
this.name = name;
this.mnemonic = mnemonic;
this.password = password;
this.network = network;
this.folderPath = folderPath;
this.name = name;
}
name: string;
mnemonic: string;
password: string;
network: string;
folderPath: string;
name: string;
folderPath?: string;
}
export class WalletLoad {
constructor(password: string, folderPath: string, name: string) {
constructor(name: string, password: string, folderPath: string = null ) {
this.name = name;
this.password = password;
this.folderPath = folderPath;
this.name = name;
}
public password: string;
public folderPath: string;
public name: string;
public password: string;
public folderPath?: string;
}
export class WalletRecovery {
constructor(mnemonic: string, password: string, network:string, folderPath: string, walletName: string, creationDate: Date) {
constructor(walletName: string, mnemonic: string, password: string, network:string, creationDate: Date, folderPath: string = null) {
this.name = walletName;
this.mnemonic = mnemonic;
this.password = password;
this.network = network;
this.folderPath = folderPath;
this.name = walletName;
this.creationDate = creationDate;
this.folderPath = folderPath;
}
mnemonic: string;
password: string;
folderPath: string;
name: string;
network: string;
creationDate: Date;
folderPath?: string;
}
import { Pipe, PipeTransform } from '@angular/core';
import { GlobalService } from '../services/global.service';
@Pipe({
name: 'coinNotation'
})
export class CoinNotationPipe implements PipeTransform {
constructor (private globalService: GlobalService) {
this.setCoinUnit();
}
private coinUnit = "BTC";
private coinUnit: string;
private coinNotation: number;
private decimalLimit = 8;
......@@ -15,13 +19,40 @@ export class CoinNotationPipe implements PipeTransform {
switch (this.getCoinUnit()) {
case "BTC":
temp = value / 100000000;
return temp.toFixed(this.decimalLimit) + " TBTC";
return temp.toFixed(this.decimalLimit) + " BTC";
case "mBTC":
temp = value / 100000;
return temp.toFixed(this.decimalLimit) + " TmBTC";
return temp.toFixed(this.decimalLimit) + " mBTC";
case "uBTC":
temp = value / 100;
return temp.toFixed(this.decimalLimit) + " uBTC";
case "TBTC":
temp = value / 100000000;
return temp.toFixed(this.decimalLimit) + " TBTC";
case "TmBTC":
temp = value / 100000;
return temp.toFixed(this.decimalLimit) + " TmBTC";
case "TuBTC":
temp = value / 100;
return temp.toFixed(this.decimalLimit) + " TuBTC";
case "STRAT":
temp = value / 100000000;
return temp.toFixed(this.decimalLimit) + " STRAT";
case "mSTRAT":
temp = value / 100000;
return temp.toFixed(this.decimalLimit) + " mSTRAT";
case "uSTRAT":
temp = value / 100;
return temp.toFixed(this.decimalLimit) + " uSTRAT";
case "TSTRAT":
temp = value / 100000000;
return temp.toFixed(this.decimalLimit) + " TSTRAT";
case "TmSTRAT":
temp = value / 100000;
return temp.toFixed(this.decimalLimit) + " TmSTRAT";
case "TuSTRAT":
temp = value / 100;
return temp.toFixed(this.decimalLimit) + " TuSTRAT";
}
}
}
......@@ -29,6 +60,10 @@ export class CoinNotationPipe implements PipeTransform {
getCoinUnit() {
return this.coinUnit;
}
setCoinUnit() {
this.coinUnit = this.globalService.getCoinUnit();
};
}
......@@ -7,6 +7,8 @@ import 'rxjs/add/operator/catch';
import "rxjs/add/observable/interval";
import 'rxjs/add/operator/startWith';
import { GlobalService } from './global.service';
import { WalletCreation } from '../classes/wallet-creation';
import { WalletRecovery } from '../classes/wallet-recovery';
import { WalletLoad } from '../classes/wallet-load';
......@@ -20,46 +22,96 @@ import { TransactionSending } from '../classes/transaction-sending';
*/
@Injectable()
export class ApiService {
constructor(private http: Http) {};
constructor(private http: Http, private globalService: GlobalService) {};
private mockApiUrl = 'http://localhost:3000/api';
private webApiUrl = 'http://localhost:5000/api';
private headers = new Headers({'Content-Type': 'application/json'});
private pollingInterval = 3000;
private bitcoinApiUrl = 'http://localhost:5000/api';
private stratisApiUrl = 'http://localhost:5105/api';
private currentApiUrl = 'http://localhost:5000/api';
private getCurrentCoin() {
let currentCoin = this.globalService.getCoinName();
if (currentCoin === "Bitcoin" || currentCoin === "TestBitcoin") {
this.currentApiUrl = this.bitcoinApiUrl;
} else if (currentCoin === "Stratis" || currentCoin === "TestStratis") {
this.currentApiUrl = this.stratisApiUrl;
}
}
/**
* Gets available wallets at the default path
*/
getWalletFiles(): Observable<any> {
return this.http
.get(this.webApiUrl + '/wallet/files')
.get(this.bitcoinApiUrl + '/wallet/files')
.map((response: Response) => response);
}
/**
* Get a new mnemonic
*/
getNewMnemonic(): Observable<any> {
let params: URLSearchParams = new URLSearchParams();
params.set('language', 'English');
params.set('wordCount', '12');
return this.http
.get(this.bitcoinApiUrl + '/wallet/mnemonic', new RequestOptions({headers: this.headers, search: params}))
.map((response: Response) => response);
}
/**
* Create a new Bitcoin wallet.
*/
createBitcoinWallet(data: WalletCreation): Observable<any> {
return this.http
.post(this.bitcoinApiUrl + '/wallet/create/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Create a new Stratis wallet.
*/
createStratisWallet(data: WalletCreation): Observable<any> {
return this.http
.post(this.stratisApiUrl + '/wallet/create/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Create a new wallet.
* Recover a Bitcoin wallet.
*/
createWallet(data: WalletCreation): Observable<any> {
recoverBitcoinWallet(data: WalletRecovery): Observable<any> {
return this.http
.post(this.webApiUrl + '/wallet/create/', JSON.stringify(data), {headers: this.headers})
.post(this.bitcoinApiUrl + '/wallet/recover/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Recover a wallet.
* Recover a Stratis wallet.
*/
recoverWallet(data: WalletRecovery): Observable<any> {
recoverStratisWallet(data: WalletRecovery): Observable<any> {
return this.http
.post(this.webApiUrl + '/wallet/recover/', JSON.stringify(data), {headers: this.headers})
.post(this.stratisApiUrl + '/wallet/recover/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Load a wallet
* Load a Bitcoin wallet
*/
loadWallet(data: WalletLoad): Observable<any> {
loadBitcoinWallet(data: WalletLoad): Observable<any> {
return this.http
.post(this.webApiUrl + '/wallet/load/', JSON.stringify(data), {headers: this.headers})
.post(this.bitcoinApiUrl + '/wallet/load/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Load a Stratis wallet
*/
loadStratisWallet(data: WalletLoad): Observable<any> {
return this.http
.post(this.stratisApiUrl + '/wallet/load/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
......@@ -67,8 +119,10 @@ export class ApiService {
* Get wallet status info from the API.
*/
getWalletStatus(): Observable<any> {
this.getCurrentCoin();
return this.http
.get(this.webApiUrl + '/wallet/status')
.get(this.currentApiUrl + '/wallet/status')
.map((response: Response) => response);
}
......@@ -76,13 +130,15 @@ export class ApiService {
* Get general wallet info from the API.
*/
getGeneralInfo(data: WalletInfo): Observable<any> {
this.getCurrentCoin();
let params: URLSearchParams = new URLSearchParams();
params.set('Name', data.walletName);
return Observable
.interval(this.pollingInterval)
.startWith(0)
.switchMap(() => this.http.get(this.webApiUrl + '/wallet/general-info', new RequestOptions({headers: this.headers, search: params})))
.switchMap(() => this.http.get(this.currentApiUrl + '/wallet/general-info', new RequestOptions({headers: this.headers, search: params})))
.map((response: Response) => response);
}
......@@ -90,66 +146,79 @@ export class ApiService {
* Get wallet balance info from the API.
*/
getWalletBalance(data: WalletInfo): Observable<any> {
this.getCurrentCoin();
let params: URLSearchParams = new URLSearchParams();
params.set('walletName', data.walletName);
return Observable
.interval(this.pollingInterval)
.startWith(0)
.switchMap(() => this.http.get(this.webApiUrl + '/wallet/balance', new RequestOptions({headers: this.headers, search: params})))
.switchMap(() => this.http.get(this.currentApiUrl + '/wallet/balance', new RequestOptions({headers: this.headers, search: params})))
.map((response: Response) => response);
// return this.http
// .get(this.webApiUrl + '/wallet/balance', new RequestOptions({headers: this.headers, search: params}))
// .map((response: Response) => response);
}
/**
* Get a wallets transaction history info from the API.
*/
getWalletHistory(data: WalletInfo): Observable<any> {
this.getCurrentCoin();
let params: URLSearchParams = new URLSearchParams();
params.set('walletName', data.walletName);
return Observable
.interval(this.pollingInterval)
.startWith(0)
.switchMap(() => this.http.get(this.webApiUrl + '/wallet/history', new RequestOptions({headers: this.headers, search: params})))
.switchMap(() => this.http.get(this.currentApiUrl + '/wallet/history', new RequestOptions({headers: this.headers, search: params})))
.map((response: Response) => response);
// return this.http
// .get(this.webApiUrl + '/wallet/history', new RequestOptions({headers: this.headers, search: params}))
// .map((response: Response) => response);
}
/**
* Get unused receive addresses for a certain wallet from the API.
*/
getUnusedReceiveAddress(data: WalletInfo): Observable<any> {
this.getCurrentCoin();
let params: URLSearchParams = new URLSearchParams();
params.set('walletName', data.walletName);
params.set('accountName', "account 0"); //temporary
return this.http
.get(this.webApiUrl + '/wallet/address', new RequestOptions({headers: this.headers, search: params}))
.get(this.currentApiUrl + '/wallet/address', new RequestOptions({headers: this.headers, search: params}))
.map((response: Response) => response);
}
/**
* Build a transaction
*/
buildTransaction(data: TransactionBuilding): Observable<any> {
this.getCurrentCoin();
return this.http
.post(this.webApiUrl + '/wallet/build-transaction/', JSON.stringify(data), {headers: this.headers})
.post(this.currentApiUrl + '/wallet/build-transaction/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Send transaction
*/
sendTransaction(data: TransactionSending): Observable<any> {
this.getCurrentCoin();
return this.http
.post(this.webApiUrl + '/wallet/send-transaction/', JSON.stringify(data), {headers: this.headers})
.post(this.currentApiUrl + '/wallet/send-transaction/', JSON.stringify(data), {headers: this.headers})
.map((response: Response) => response);
}
/**
* Send shutdown signal to the daemon
*/
shutdownNode(): Observable<any> {
this.getCurrentCoin();
return this.http
.post(this.webApiUrl + '/node/shutdown', '')
.post(this.currentApiUrl + '/node/shutdown', '')
.map((response: Response) => response);
}
}
......@@ -6,18 +6,25 @@ export class GlobalService {
private walletPath: string;
private currentWalletName: string;
private coinType: number;
private coinType: number = 0;
private coinName: string = "TestBitcoin";
private coinUnit: string = "TBTC";
private network: string = "TestNet";
getWalletPath() {
return this.walletPath;
}
setWalletPath(walletPath: string) {
this.walletPath = walletPath;
}
getNetwork() {
return "TestNet";
return this.network;
}
setWalletPath(walletPath: string) {
this.walletPath = walletPath;
setNetwork(network: string) {
this.network = network;
}
getWalletName() {
......@@ -28,11 +35,27 @@ export class GlobalService {
this.currentWalletName = currentWalletName;
}
getCoinType () {
getCoinType() {
return this.coinType;
}
setCoinType (coinType: number) {
this.coinType = coinType;
}
getCoinName() {
return this.coinName;
}
setCoinName(coinName: string) {
this.coinName = coinName;
}
getCoinUnit() {
return this.coinUnit;
}
setCoinUnit(coinUnit: string) {
this.coinUnit = coinUnit;
}
}
......@@ -19,8 +19,8 @@
<!-- /JUMBOTRON-->
<!-- TRANSACTIONS -->
<section id="transaction" class="container mt-4">
<h5 class="pt-4">Transactions</h5>
<section id="transaction" class="container">
<h5>Transactions</h5>
<div *ngIf="transactions; else noTransactions">
<div *ngFor="let transaction of transactions">
<div class="card" (click)="openTransactionDetailDialog(transaction)">
......
......@@ -12,7 +12,7 @@
<span class="float-right"><a ngxClipboard [cbContent]="address" (click)="onCopiedClick()">copy</a></span>
</div>
<div class="myAddress"><code>{{ address }}</code></div>
<div class="text-center row" *ngIf="copied">
<div class="text-center" *ngIf="copied">
<span class="badge badge-success col">Your address has been copied to your clipboard.</span>
</div>
</form>
......
......@@ -18,7 +18,7 @@
</ul>
<ul class="list-inline row">
<li class="list-inline-item col blockLabel">Amount</li>
<li class="list-inline-item col-9 blockText"><strong class="text-danger">-{{ transaction.amount }}</strong> <small class="text-uppercase ml-2">BTC</small></li>
<li class="list-inline-item col-9 blockText text-danger">-{{ transaction.amount | number:'1.8-8' }} {{ coinUnit }}</li>
</ul>
<ul class="list-inline row">
<li class="list-inline-item col blockLabel">Destination</li>
......
......@@ -2,6 +2,8 @@ import { Component, OnInit, Input } from '@angular/core';
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { GlobalService } from '../../../shared/services/global.service';
@Component({
selector: 'app-send-confirmation',
templateUrl: './send-confirmation.component.html',
......@@ -10,12 +12,13 @@ import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
export class SendConfirmationComponent implements OnInit {
@Input() transaction: any;
constructor(public activeModal: NgbActiveModal) { }
constructor(private globalService: GlobalService, public activeModal: NgbActiveModal) { }
private showDetails: boolean = false;
private coinUnit: string;
ngOnInit() {
console.log(this.transaction);
this.coinUnit = this.globalService.getCoinUnit();
}
toggleDetails() {
......
......@@ -11,7 +11,7 @@
<div class="form-group clearfix">
<label class="float-left" for="yourAddress">Amount</label>
<!--<span class="float-right"><a href="#">max</a></span>-->
<input type="text" class="form-control form-control-danger" formControlName="amount" id="Amount" placeholder="0.00 BTC">
<input type="text" class="form-control form-control-danger" formControlName="amount" id="Amount" placeholder="0.00 {{ coinUnit }}">
<div *ngIf="formErrors.amount" class="form-control-feedback">{{ formErrors.amount }}</div>
</div>
<!--<div class="form-group has-success">-->
......@@ -54,7 +54,7 @@
<a><button type="button" class="btn btn-link col-12" (click)="activeModal.close('Close click')">Cancel</button></a>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-lg btn-primary" [disabled]="!sendForm.valid" (click)="send()">Send</button>
<button type="submit" class="btn btn-lg btn-primary" [disabled]="!sendForm.valid || isSending" (click)="send()">Send</button>
</div>
</div>
</div>
......
import { Component } from '@angular/core';
import { Component, OnInit } from '@angular/core';
import { ApiService } from '../../shared/services/api.service';
import { GlobalService } from '../../shared/services/global.service';
import { FormGroup, FormControl, Validators, FormBuilder } from '@angular/forms';
......@@ -16,7 +16,7 @@ import { SendConfirmationComponent } from './send-confirmation/send-confirmation
styleUrls: ['./send.component.css'],
})
export class SendComponent {
export class SendComponent implements OnInit {
constructor(private apiService: ApiService, private globalService: GlobalService, private modalService: NgbModal, public activeModal: NgbActiveModal, private fb: FormBuilder) {
this.buildSendForm();
}
......@@ -24,7 +24,13 @@ export class SendComponent {
private sendForm: FormGroup;
private responseMessage: any;
private errorMessage: string;
private coinUnit: string;
private transaction: TransactionBuilding;
private isSending: Boolean = false;
ngOnInit() {
this.coinUnit = this.globalService.getCoinUnit();
}
private buildSendForm(): void {
this.sendForm = this.fb.group({
......@@ -79,6 +85,8 @@ export class SendComponent {
};
private send() {
this.isSending = true;
this.transaction = new TransactionBuilding(
this.globalService.getWalletName(),
this.globalService.getCoinType(),
......@@ -96,11 +104,11 @@ export class SendComponent {
response => {
if (response.status >= 200 && response.status < 400){
this.responseMessage = response.json();
console.log(this.responseMessage);
}
},
error => {
console.log(error);
this.isSending = false;
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
......@@ -142,6 +150,7 @@ export class SendComponent {
},
error => {
console.log(error);
this.isSending = false;
if (error.status === 0) {
alert("Something went wrong while connecting to the API. Please restart the application.");
} else if (error.status >= 400) {
......
<!-- SIDEBAR -->
<!-- sidebar -->
<aside id="sidebar">
<!-- menu-->
<ul class="list-unstyled menu">
<li class="active">
<!--<a href="#">--><img src="../../../assets/images/ico_bitcoin.svg" alt="Bitcoin"><!--</a>-->
<li (click)="loadBitcoinWallet()" [class.active]="bitcoinActive">
<img src="../../../assets/images/ico_bitcoin.svg" alt="Bitcoin">
<span class="bar"></span>
</li>
<!--<li>
<a href="#"><img src="../../../assets/images/ico_stratis.svg" alt="Stratis"></a>
<li (click)="loadStratisWallet()" [class.active]="!bitcoinActive">
<img src="../../../assets/images/ico_stratis.svg" alt="Stratis">
<span class="bar"></span>
</li>-->
</li>
</ul>
<!-- /menu-->
<ul class="list-unstyled second">
......
import { Component, OnInit } from '@angular/core';
import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { LogoutConfirmationComponent } from '../logout-confirmation/logout-confirmation.component';
import { Router } from '@angular/router';
import { GlobalService } from '../../shared/services/global.service';
@Component({
selector: 'sidebar',
......@@ -9,13 +12,36 @@ import { LogoutConfirmationComponent } from '../logout-confirmation/logout-confi
})
export class SidebarComponent implements OnInit {
constructor(private modalService: NgbModal) { }
constructor(private globalService: GlobalService, private router: Router, private modalService: NgbModal) { }
private bitcoinActive: Boolean;
ngOnInit() {
if (this.globalService.getCoinName() === "Bitcoin" || this.globalService.getCoinName() === "TestBitcoin") {
this.bitcoinActive = true;
} else if (this.globalService.getCoinName() === "Stratis" || this.globalService.getCoinName() === "TestStratis") {
this.bitcoinActive = false;
}
}
private loadBitcoinWallet() {
this.toggleClass();
this.globalService.setCoinName("TestBitcoin");
this.globalService.setCoinUnit("TBTC");
this.router.navigate(['/wallet']);
}
private loadStratisWallet() {
this.toggleClass();
this.globalService.setCoinName("TestStratis");
this.globalService.setCoinUnit("TSTRAT");
this.router.navigate(['/wallet/stratis-wallet']);
}
private toggleClass(){
this.bitcoinActive = !this.bitcoinActive;
}
private logOut() {
const modalRef = this.modalService.open(LogoutConfirmationComponent);
}
}
......@@ -8,14 +8,20 @@ import { HistoryComponent } from './history/history.component';
import { DashboardComponent } from './dashboard/dashboard.component';
const routes: Routes = [
{ path: '', redirectTo: 'wallet', pathMatch: 'full' },
{ path: 'wallet', component: WalletComponent,
{ path: '', component: WalletComponent,
children: [
{ path: '', redirectTo:'dashboard', pathMatch:'full' },
{ path: 'dashboard', component: DashboardComponent},
{ path: 'history', component: HistoryComponent}
]
},
{ path: 'stratis-wallet', component: WalletComponent,
children: [
{ path: '', redirectTo:'dashboard', pathMatch:'full' },
{ path: 'dashboard', component: DashboardComponent},
{ path: 'history', component: HistoryComponent}
]
}
];
@NgModule({
......
......@@ -139,10 +139,12 @@ em {
font-size: .85em;
color: $gray-dark;
}
p {margin-bottom: 0 !important;}
.lead {
color: $black;
font-size: 1.85em;
font-weight: 500;
margin-bottom: 0;
.h2 {
font-size: 2em;
font-weight: 600;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment