Commit 6e3e2d7f authored by Jeremy Bokobza's avatar Jeremy Bokobza

Merge remote-tracking branch 'upstream/master' into feature/list-files

parents 94932a80 ede7dece
...@@ -2,12 +2,7 @@ ...@@ -2,12 +2,7 @@
## Request/Response ## Request/Response
RESPONSE: responsecode (`200` if success, `400`/`500` if error, see later) RESPONSE: response code (`200` for all successful requests, `4xx`/`5xx` if error, see later)
```
{
"success": "true"
}
```
HEADERS HEADERS
`Content-Type:application/json` `Content-Type:application/json`
...@@ -16,15 +11,19 @@ HEADERS ...@@ -16,15 +11,19 @@ HEADERS
### General errors ### General errors
`400` series status codes for client issues & `500` series status codes for server issues.
API should standardize that all `400` series errors come with consumable JSON error representation.
BODY BODY
The error response is an array of error objects.
Depending on the circumstance the API will either return an error at the first encounter or will continue until multiple errors are gathered.
``` ```
{ {
"success": "false", "errors": [
"message": "something bad happened", // ex.Message maybe? {
"description": ex.ToString() "status": 400,
"message": "No wallet file found at Wallets\\myFirstWallet.json",
"description": "System.ArgumentException: No wallet file found at..."
}
]
} }
``` ```
...@@ -36,11 +35,7 @@ This error message comes at all request if the wallet is not created yet, except ...@@ -36,11 +35,7 @@ This error message comes at all request if the wallet is not created yet, except
- `POST /wallet/send-transaction` - `POST /wallet/send-transaction`
``` ```
{ 404 (Not Found) - "wallet is not created"
"success": "false",
"message": "wallet is not created",
"description": ""
}
``` ```
### wallet is not decrypted ### wallet is not decrypted
...@@ -53,11 +48,7 @@ This error message comes at all request if the wallet is not loaded yet, except ...@@ -53,11 +48,7 @@ This error message comes at all request if the wallet is not loaded yet, except
- `DELETE /wallet` - `DELETE /wallet`
``` ```
{ 400 (Bad Request) - "wallet is not decrypted"
"success": "false",
"message": "wallet is not decrypted",
"description": ""
}
``` ```
## Key Management ## Key Management
...@@ -99,7 +90,6 @@ POST /wallet/send-transaction - Attempts to send a transaction ...@@ -99,7 +90,6 @@ POST /wallet/send-transaction - Attempts to send a transaction
### Responses ### Responses
``` ```
{ {
"success": "true",
"walletFilePath": "path to the wallet file", "walletFilePath": "path to the wallet file",
"encryptedSeed": "6PYKWP34en1wELfcJDgXaFRPugjgkDdEk2p2Pzytm1158dxgNyLAUXwpKL", "encryptedSeed": "6PYKWP34en1wELfcJDgXaFRPugjgkDdEk2p2Pzytm1158dxgNyLAUXwpKL",
"chainCode": "q/Fn7+RSIVM0p0Nj6rIuNkybF+0WKeSZPMQS2QCbDzY=", "chainCode": "q/Fn7+RSIVM0p0Nj6rIuNkybF+0WKeSZPMQS2QCbDzY=",
...@@ -119,7 +109,6 @@ POST /wallet/send-transaction - Attempts to send a transaction ...@@ -119,7 +109,6 @@ POST /wallet/send-transaction - Attempts to send a transaction
### Responses ### Responses
``` ```
{ {
"success": "true",
"extkey": "sadwqdpqoijedqcdoijsadoijsadisa", "extkey": "sadwqdpqoijedqcdoijsadoijsadisa",
"extpubkey": "dalkdsaklkjdlkjdsaljlkjdsalkjdsalk", "extpubkey": "dalkdsaklkjdlkjdsaljlkjdsalkjdsalk",
} }
...@@ -128,7 +117,6 @@ POST /wallet/send-transaction - Attempts to send a transaction ...@@ -128,7 +117,6 @@ POST /wallet/send-transaction - Attempts to send a transaction
### Responses ### Responses
``` ```
{ {
"success": "true",
"connectedNodeCount": "7", "connectedNodeCount": "7",
"maxConnextedNodeCount": "8", "maxConnextedNodeCount": "8",
"headerChainHeight": "1048", "headerChainHeight": "1048",
...@@ -151,7 +139,6 @@ POST /wallet/send-transaction - Attempts to send a transaction ...@@ -151,7 +139,6 @@ POST /wallet/send-transaction - Attempts to send a transaction
### Responses ### Responses
``` ```
{ {
"success": "true",
"mnemonic": "foo bar buz", "mnemonic": "foo bar buz",
} }
``` ```
...@@ -185,7 +172,6 @@ Works as expected. ...@@ -185,7 +172,6 @@ Works as expected.
### Responses ### Responses
``` ```
{ {
"success": "true",
"addresses": // 7 unused receive address (7 is the best number: https://www.psychologytoday.com/blog/fulfillment-any-age/201109/7-reasons-we-7-reasons) "addresses": // 7 unused receive address (7 is the best number: https://www.psychologytoday.com/blog/fulfillment-any-age/201109/7-reasons-we-7-reasons)
[ [
"mzz63n3n89KVeHQXRqJEVsQX8MZj5zeqCw", "mzz63n3n89KVeHQXRqJEVsQX8MZj5zeqCw",
...@@ -203,7 +189,6 @@ Works as expected. ...@@ -203,7 +189,6 @@ Works as expected.
### Responses ### Responses
``` ```
{ {
"success": "true",
"history": "history":
[ [
{ {
...@@ -226,7 +211,6 @@ Works as expected. ...@@ -226,7 +211,6 @@ Works as expected.
### Responses ### Responses
``` ```
{ {
"success": "true",
"synced": "true", "synced": "true",
"confirmed": "0.144", "confirmed": "0.144",
"unconfirmed": "-6.23" "unconfirmed": "-6.23"
...@@ -252,7 +236,6 @@ Unconfirmed balance is the difference of unconfirmed incoming and outgoing trans ...@@ -252,7 +236,6 @@ Unconfirmed balance is the difference of unconfirmed incoming and outgoing trans
#### Successful #### Successful
``` ```
{ {
"success": "true",
"spendsUnconfirmed": "false", // If spends unconfirmed you can ask the user if it's sure about spending unconfirmed transaction (if inputs are malleated or inputs never confirm then this transaction will never confirm either" "spendsUnconfirmed": "false", // If spends unconfirmed you can ask the user if it's sure about spending unconfirmed transaction (if inputs are malleated or inputs never confirm then this transaction will never confirm either"
"fee": "0.0001", "fee": "0.0001",
"feePercentOfSent": "0.1" // Percentage of the total spent amount, there must be a safety limit implemented here "feePercentOfSent": "0.1" // Percentage of the total spent amount, there must be a safety limit implemented here
...@@ -303,11 +286,7 @@ Unconfirmed balance is the difference of unconfirmed incoming and outgoing trans ...@@ -303,11 +286,7 @@ Unconfirmed balance is the difference of unconfirmed incoming and outgoing trans
#### Errors #### Errors
``` ```
{ 400 - "wallet is not synced"
"success": "false",
"message": "wallet is not synced",
"description": ""
}
``` ```
## POST /wallet/send-transaction - Attempts to send a transaction ## POST /wallet/send-transaction - Attempts to send a transaction
......
{ {
"create": "files": {
{ "walletsPath": "/home/dev0tion/Desktop/Wallets",
"mnemonic": "foo bar buz" "walletsFiles": [
}, "myFirstWallet.json",
"load": "mySecondWallet.json"
{ ]
"success": "true"
}, },
"status": "status":
{ {
......
...@@ -8,7 +8,7 @@ const routes: Routes = [ ...@@ -8,7 +8,7 @@ const routes: Routes = [
]; ];
@NgModule({ @NgModule({
imports: [ RouterModule.forRoot(routes) ], imports: [ RouterModule.forRoot(routes, {useHash: true}) ],
exports: [ RouterModule ] exports: [ RouterModule ]
}) })
......
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { remote } from 'electron';
import { ApiService } from './shared/api/api.service'; import { ApiService } from './shared/api/api.service';
@Component({ @Component({
...@@ -13,33 +11,30 @@ import { ApiService } from './shared/api/api.service'; ...@@ -13,33 +11,30 @@ import { ApiService } from './shared/api/api.service';
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
constructor(private router: Router, private apiService: ApiService) {} constructor(private router: Router, private apiService: ApiService) {}
private errorMessage: string; private errorMessage: any;
private response: any; private responseMessage: any;
private isConfigured: boolean = true;
ngOnInit() { ngOnInit() {
this.checkWalletStatus(); this.router.navigate(['/login']);
} //this.checkWalletStatus();
private checkWalletStatus(){
this.apiService.getWalletStatus()
.subscribe(
response => this.response = response,
error => this.errorMessage = <any>error,
() => this.navigate()
);
} }
private navigate() { // private checkWalletStatus(){
if (this.response.success === "true") { // this.apiService.getWalletStatus()
// remote.dialog.showMessageBox({message: remote.app.getPath('userData')}) // .subscribe(
this.router.navigate(['/login']) // response => {
} else { // if (response.status >= 200 && response.status < 400) {
this.router.navigate(['/setup']) // this.responseMessage = response;
} // this.router.navigate(['/login']);
} // }
// },
private hasWallet() { // error => {
return true; // this.errorMessage = <any>error;
} // if (error.status === 400 || error.status === 404) {
// this.router.navigate(['/setup']);
// console.log(this.errorMessage);
// }
// }
// );
// }
} }
\ No newline at end of file
<h1>Welcome back</h1> <h1>Welcome to Breeze</h1>
<p>Please enter your password to decrypt your wallet</p> <div *ngIf="hasWallet">
<form (ngSubmit)="onSubmit()" #passwordForm="ngForm"> <p>Choose the wallet you want to open:</p>
<div class="form-group">
<label for="walletLabel">Wallet to open:</label>
<select name="wallet" #walletName (change)="walletChanged(walletName.value)">
<option *ngFor="let wallet of wallets" [value]="wallet">{{wallet}}</option>
</select>
</div>
<p>Please enter your password to decrypt your wallet</p>
<form (ngSubmit)="onSubmit()" #passwordForm="ngForm">
<div class="form-group"> <div class="form-group">
<label for="password">Your password: </label> <label for="password">Your password: </label>
<input type="password" class="form-control" id="password" required name="password"> <input type="password" class="form-control" id="password" [(ngModel)]="password" required name="password">
</div> </div>
<button type="submit" class="btn btn-success">Decrypt</button> <button type="submit" class="btn btn-success">Decrypt</button>
</form> </form>
\ No newline at end of file <p></p>
</div>
<div *ngIf="hasWallet;else no_wallet">
<p> If you like to create or restore a wallet please click the button below.</p>
</div>
<ng-template #no_wallet>
<p> Looks like you're new here. Please create or restore a wallet.</p>
</ng-template>
<button type="button" (click)="clickedCreate()" class="btn btn-success">Create or restore wallet</button>
\ No newline at end of file
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { ApiService } from '../shared/api/api.service'; import { ApiService } from '../shared/api/api.service';
import { WalletLoad } from '../shared/wallet-load';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
...@@ -10,27 +11,79 @@ import { ApiService } from '../shared/api/api.service'; ...@@ -10,27 +11,79 @@ import { ApiService } from '../shared/api/api.service';
export class LoginComponent implements OnInit { export class LoginComponent implements OnInit {
constructor(private apiService: ApiService, private router: Router) { } constructor(private apiService: ApiService, private router: Router) { }
private response: any; private walletLoad: WalletLoad;
private errorMessage: string; private hasWallet: boolean = false;
private currentWalletName: string;
private wallets: [any];
private walletPath: string;
private password: string;
private responseMessage: any;
private errorMessage: any;
ngOnInit() { ngOnInit() {
this.apiService.getWalletFiles()
.subscribe(
response => {
if (response.status >= 200 && response.status < 400) {
this.responseMessage=response;
this.wallets = response.json().walletsFiles;
this.walletPath = response.json().walletsPath;
if (this.wallets.length > 0) {
this.hasWallet = true;
this.currentWalletName = this.wallets[0].slice(0, -5);
} else {
this.hasWallet = false;
}
}
},
error => {
this.errorMessage = <any>error;
if (error.status >= 400) {
alert(this.errorMessage);
console.log(this.errorMessage);
}
}
);
} }
private onSubmit() { private onSubmit() {
this.apiService.loadWallet("123")
this.walletLoad = new WalletLoad();
this.walletLoad.password = this.password;
this.walletLoad.name = this.currentWalletName;
this.walletLoad.folderPath = this.walletPath;
console.log(this.walletLoad);
this.apiService.loadWallet(this.walletLoad)
.subscribe( .subscribe(
response => this.response = response, response => {
error => this.errorMessage = error, console.log(response);
() => this.loadWallet() if (response.status >= 200 && response.status < 400) {
this.responseMessage = response;
this.router.navigate(['/wallet']);
}
},
error => {
this.errorMessage = <any>error;
if (error.status === 403 && error.json().errors[0].message === "Wrong password, please try again.") {
alert("Wrong password, try again.");
} else if (error.status >= 400) {
alert(this.errorMessage);
console.log(this.errorMessage);
}
}
); );
} }
private loadWallet() { private walletChanged(walletName: string) {
if (this.response.success === "true") { let walletNameNoJson: string = walletName.slice(0, -5);
this.router.navigate(['/wallet/send']); this.currentWalletName = walletNameNoJson;
} else {
alert("Something went wrong.")
} }
private clickedCreate() {
this.router.navigate(['/setup']);
} }
} }
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CreateComponent } from './create.component';
describe('CreateComponent', () => {
let component: CreateComponent;
let fixture: ComponentFixture<CreateComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CreateComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CreateComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
...@@ -15,7 +15,9 @@ export class CreateComponent { ...@@ -15,7 +15,9 @@ export class CreateComponent {
constructor(private apiService: ApiService) {} constructor(private apiService: ApiService) {}
private newWallet: WalletCreation; private newWallet: WalletCreation;
private responseMessage: string; private responseMessage: string;
private errorMessage: string;
private createWallet(password: string, network: string, folderPath: string, name: string, ) { private createWallet(password: string, network: string, folderPath: string, name: string, ) {
this.newWallet = new WalletCreation(); this.newWallet = new WalletCreation();
...@@ -26,6 +28,18 @@ export class CreateComponent { ...@@ -26,6 +28,18 @@ export class CreateComponent {
this.apiService this.apiService
.createWallet(this.newWallet) .createWallet(this.newWallet)
.subscribe((response: string) => this.responseMessage = response); .subscribe(
response => {
if (response.status >= 200 && response.status < 400){
this.responseMessage = response.json();
}
},
error => {
if (error.status >= 400) {
this.errorMessage = error;
console.log(this.errorMessage);
}
}
);
} }
} }
...@@ -10,8 +10,11 @@ import { WalletRecovery } from '../../shared/wallet-recovery' ...@@ -10,8 +10,11 @@ import { WalletRecovery } from '../../shared/wallet-recovery'
export class RecoverComponent implements OnInit { export class RecoverComponent implements OnInit {
constructor(private apiService: ApiService) { } constructor(private apiService: ApiService) { }
private walletRecovery: WalletRecovery; private walletRecovery: WalletRecovery;
private responseBody: string;
private responseMessage: string;
private errorMessage: string;
ngOnInit() { ngOnInit() {
} }
...@@ -26,7 +29,18 @@ export class RecoverComponent implements OnInit { ...@@ -26,7 +29,18 @@ export class RecoverComponent implements OnInit {
this.apiService this.apiService
.recoverWallet(this.walletRecovery) .recoverWallet(this.walletRecovery)
.subscribe((response: string) => this.responseBody = response, .subscribe(
() => console.log("recoverWallet() completed")); response => {
if (response.status >= 200 && response.status < 400) {
this.responseMessage = response;
}
},
error => {
if (error.status >= 400) {
this.errorMessage = error;
console.log(this.errorMessage);
}
}
);
} }
} }
\ No newline at end of file
<h1>Welcome to Breeze. Looks like you're new here.</h1> <h1>Welcome to Breeze.</h1>
<p> <p>
If you haven't used Breeze before, please create a new wallet. If you haven't used Breeze before, please create a new wallet.
</p> </p>
......
...@@ -6,6 +6,7 @@ import 'rxjs/add/operator/catch'; ...@@ -6,6 +6,7 @@ import 'rxjs/add/operator/catch';
import { WalletCreation } from '../wallet-creation'; import { WalletCreation } from '../wallet-creation';
import { WalletRecovery } from '../wallet-recovery'; import { WalletRecovery } from '../wallet-recovery';
import { WalletLoad } from '../wallet-load';
import { Mnemonic } from '../mnemonic'; import { Mnemonic } from '../mnemonic';
/** /**
...@@ -20,13 +21,22 @@ export class ApiService { ...@@ -20,13 +21,22 @@ export class ApiService {
private webApiUrl = 'http://localhost:5000/api/v1'; private webApiUrl = 'http://localhost:5000/api/v1';
private headers = new Headers({'Content-Type': 'application/json'}); private headers = new Headers({'Content-Type': 'application/json'});
/**
* Gets available wallets at the default path
*/
getWalletFiles(): Observable<any> {
return this.http
.get(this.mockApiUrl + '/wallet/files')
.map((response: Response) => response);
}
/** /**
* Create a new wallet. * Create a new wallet.
*/ */
createWallet(data: WalletCreation): Observable<any> { createWallet(data: WalletCreation): Observable<any> {
return this.http return this.http
.post(this.webApiUrl + '/wallet/create/', JSON.stringify(data), {headers: this.headers}) .post(this.webApiUrl + '/wallet/create/', JSON.stringify(data), {headers: this.headers})
.map(response => response.json()); .map((response: Response) => response);
} }
/** /**
...@@ -35,17 +45,16 @@ export class ApiService { ...@@ -35,17 +45,16 @@ export class ApiService {
recoverWallet(data: WalletRecovery): Observable<any> { recoverWallet(data: WalletRecovery): Observable<any> {
return this.http return this.http
.post(this.webApiUrl + '/wallet/recover/', JSON.stringify(data), {headers: this.headers}) .post(this.webApiUrl + '/wallet/recover/', JSON.stringify(data), {headers: this.headers})
.map(response => response.json()); .map((response: Response) => response);
} }
/** /**
* Load a wallet * Load a wallet
*/ */
loadWallet(password: string): Observable<any> { loadWallet(data: WalletLoad): Observable<any> {
return this.http return this.http
.get(this.webApiUrl + '/wallet/load/', {headers: this.headers, body: JSON.stringify(password)}) .post(this.webApiUrl + '/wallet/load/', JSON.stringify(data), {headers: this.headers})
.map(response => response.json()) .map((response: Response) => response);
.catch(this.handleError);
} }
/** /**
...@@ -54,8 +63,7 @@ export class ApiService { ...@@ -54,8 +63,7 @@ export class ApiService {
getWalletStatus(): Observable<any> { getWalletStatus(): Observable<any> {
return this.http return this.http
.get(this.mockApiUrl + '/wallet/status') .get(this.mockApiUrl + '/wallet/status')
.map((response:Response) => response.json()) .map((response: Response) => response);
.catch(this.handleError);
} }
/** /**
...@@ -63,9 +71,8 @@ export class ApiService { ...@@ -63,9 +71,8 @@ export class ApiService {
*/ */
getWalletBalance(): Observable<any> { getWalletBalance(): Observable<any> {
return this.http return this.http
.get(this.webApiUrl + '/wallet/balance') .get(this.mockApiUrl + '/wallet/balance')
.map((response:Response) => response.json()) .map((response: Response) => response);
.catch(this.handleError);
} }
/** /**
...@@ -73,9 +80,8 @@ export class ApiService { ...@@ -73,9 +80,8 @@ export class ApiService {
*/ */
getWalletHistory(): Observable<any> { getWalletHistory(): Observable<any> {
return this.http return this.http
.get(this.webApiUrl + '/wallet/history') .get(this.mockApiUrl + '/wallet/history')
.map((response:Response) => response.json()) .map((response: Response) => response);
.catch(this.handleError);
} }
/** /**
...@@ -83,25 +89,7 @@ export class ApiService { ...@@ -83,25 +89,7 @@ export class ApiService {
*/ */
getUnusedReceiveAddresses(): Observable<any> { getUnusedReceiveAddresses(): Observable<any> {
return this.http return this.http
.get(this.webApiUrl + '/wallet/receive') .get(this.mockApiUrl + '/wallet/receive')
.map((response:Response) => response.json()) .map((response: Response) => response);
.catch(this.handleError);
}
/**
* Handle errors from the API.
* @param error
*/
private handleError (error: Response | any) {
let errMsg: string;
if (error instanceof Response) {
const body = error.json() || '';
const err = body.error || JSON.stringify(body);
errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
} else {
errMsg = error.message ? error.message : error.toString();
}
console.error(errMsg);
return Observable.throw(errMsg);
} }
} }
export class WalletLoad {
password: string;
folderPath: string;
name: string;
}
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HistoryComponent } from './history.component';
describe('HistoryComponent', () => {
let component: HistoryComponent;
let fixture: ComponentFixture<HistoryComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HistoryComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HistoryComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
...@@ -21,8 +21,17 @@ export class HistoryComponent { ...@@ -21,8 +21,17 @@ export class HistoryComponent {
private getWalletHistory() { private getWalletHistory() {
this.apiService.getWalletHistory() this.apiService.getWalletHistory()
.subscribe( .subscribe(
response => this.transactions = response.history, response => {
error => this.errorMessage = <any>error if (response.status >= 200 && response.status < 400) {
this.transactions = response.json().history;
}
},
error => {
if (error.status >= 400) {
this.errorMessage = <any>error;
console.log(this.errorMessage);
}
}
); );
} }
} }
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { DashboardComponent } from './dashboard.component';
describe('DashboardComponent', () => {
let component: DashboardComponent;
let fixture: ComponentFixture<DashboardComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ DashboardComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(DashboardComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
...@@ -21,14 +21,19 @@ export class DashboardComponent { ...@@ -21,14 +21,19 @@ export class DashboardComponent {
private getWalletBalance() { private getWalletBalance() {
this.apiService.getWalletBalance() this.apiService.getWalletBalance()
.subscribe( .subscribe(
response => this.balanceResponse = response, response => {
error => this.errorMessage = <any>error, if (response.status >= 200 && response.status < 400) {
() => this.setBalance() this.balanceResponse = response.json();
);
}
private setBalance() {
this.confirmedBalance = this.balanceResponse.confirmed; this.confirmedBalance = this.balanceResponse.confirmed;
this.unconfirmedBalance = this.balanceResponse.unconfirmed; this.unconfirmedBalance = this.balanceResponse.unconfirmed;
} }
},
error => {
if (error.status >= 400) {
this.errorMessage = <any>error;
console.log(this.errorMessage);
}
}
);
}
} }
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
<li class="nav-item"><a class="nav-link" routerLink="send">Send</a></li> <li class="nav-item"><a class="nav-link" routerLink="send">Send</a></li>
<li class="nav-item"><a class="nav-link" routerLink="receive">Receive</a></li> <li class="nav-item"><a class="nav-link" routerLink="receive">Receive</a></li>
<li class="nav-item"><a class="nav-link" routerLink="history">History</a></li> <li class="nav-item"><a class="nav-link" routerLink="history">History</a></li>
<li class="nav-item"><a class="nav-link" (click)="logOut()">Logout</a></li>
</ul> </ul>
</div> </div>
</nav> </nav>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { MenuComponent } from './menu.component';
describe('MenuComponent', () => {
let component: MenuComponent;
let fixture: ComponentFixture<MenuComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ MenuComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MenuComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({ @Component({
selector: 'app-menu', selector: 'app-menu',
...@@ -6,5 +7,9 @@ import { Component } from '@angular/core'; ...@@ -6,5 +7,9 @@ import { Component } from '@angular/core';
styleUrls: ['./menu.component.css'], styleUrls: ['./menu.component.css'],
}) })
export class MenuComponent { export class MenuComponent {
constructor(private router: Router) {}
private logOut() {
this.router.navigate(['/login']);
}
} }
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ReceiveComponent } from './receive.component';
describe('ReceiveComponent', () => {
let component: ReceiveComponent;
let fixture: ComponentFixture<ReceiveComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ReceiveComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ReceiveComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
...@@ -21,8 +21,17 @@ export class ReceiveComponent { ...@@ -21,8 +21,17 @@ export class ReceiveComponent {
private getUnusedReceiveAddresses() { private getUnusedReceiveAddresses() {
this.apiService.getUnusedReceiveAddresses() this.apiService.getUnusedReceiveAddresses()
.subscribe( .subscribe(
response => this.addresses = response.addresses, response => {
error => this.errorMessage = <any>error if (response.status >= 200 && response.status < 400) {
this.addresses = response.json().addresses;
}
},
error => {
if (error.status >= 400) {
this.errorMessage = <any>error;
console.log(this.errorMessage);
}
}
); );
} }
} }
\ No newline at end of file
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { SendComponent } from './send.component';
describe('SendComponent', () => {
let component: SendComponent;
let fixture: ComponentFixture<SendComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ SendComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SendComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { WalletComponent } from './wallet.component';
describe('WalletComponent', () => {
let component: WalletComponent;
let fixture: ComponentFixture<WalletComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ WalletComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(WalletComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
...@@ -15,7 +15,7 @@ let mainWindow = null; ...@@ -15,7 +15,7 @@ let mainWindow = null;
function createWindow () { function createWindow () {
setTimeout(() => { setTimeout(() => {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({width: 1000, height: 600, frame: true, minWidth: 1000, minHeight: 600, icon: "./assets/images/stratis-tray.png"}) mainWindow = new BrowserWindow({width: 1000, height: 600, frame: true, minWidth: 1000, minHeight: 600, icon: "./src/assets/images/stratis-tray.png"})
mainWindow.loadURL(url.format({ mainWindow.loadURL(url.format({
pathname: 'localhost:4200', pathname: 'localhost:4200',
......
...@@ -28,6 +28,28 @@ namespace Breeze.Api ...@@ -28,6 +28,28 @@ namespace Breeze.Api
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
// Add service and create Policy to allow Cross-Origin Requests
services.AddCors
(
options =>
{
options.AddPolicy
(
"CorsPolicy",
builder =>
{
var allowedDomains = new[]{"http://localhost","http://localhost:4200"};
builder
.WithOrigins(allowedDomains)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
}
);
});
// Add framework services. // Add framework services.
services.AddMvc() services.AddMvc()
// add serializers for NBitcoin objects // add serializers for NBitcoin objects
...@@ -73,6 +95,8 @@ namespace Breeze.Api ...@@ -73,6 +95,8 @@ namespace Breeze.Api
loggerFactory.AddConsole(this.Configuration.GetSection("Logging")); loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug(); loggerFactory.AddDebug();
app.UseCors("CorsPolicy");
app.UseMvc(); app.UseMvc();
// Enable middleware to serve generated Swagger as a JSON endpoint. // Enable middleware to serve generated Swagger as a JSON endpoint.
......
...@@ -59,6 +59,7 @@ ...@@ -59,6 +59,7 @@
}, },
"runtimes": { "runtimes": {
"win10-x64": {}, "win10-x64": {},
"win7-x64": {} "win7-x64": {},
"ubuntu.16.04-x64": {}
} }
} }
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