Merge pull request #787 from SonicWizard/ionic
Add Address and Transaction pages; Refactor TransactionsComponent to TransactionListComponent
This commit is contained in:
commit
f35d7dd960
@ -28,6 +28,7 @@
|
||||
"@ionic-native/splash-screen": "3.10.2",
|
||||
"@ionic-native/status-bar": "3.10.2",
|
||||
"@ionic/storage": "2.0.1",
|
||||
"angular2-qrcode": "^2.0.1",
|
||||
"ionic-angular": "3.4.2",
|
||||
"ionicons": "3.0.0",
|
||||
"rxjs": "5.4.0",
|
||||
@ -37,12 +38,12 @@
|
||||
"devDependencies": {
|
||||
"@angular/cli": "1.1.2",
|
||||
"@ionic/app-scripts": "1.3.7",
|
||||
"@ionic/cli-plugin-cordova": "1.5.0",
|
||||
"@ionic/cli-plugin-ionic-angular": "1.4.0",
|
||||
"@ionic/cli-plugin-cordova": "1.6.2",
|
||||
"@ionic/cli-plugin-ionic-angular": "1.4.1",
|
||||
"@types/jasmine": "2.5.41",
|
||||
"@types/node": "7.0.4",
|
||||
"codecov": "2.2.0",
|
||||
"ionic": "3.6.0",
|
||||
"ionic": "3.7.0",
|
||||
"jasmine-core": "2.5.2",
|
||||
"jasmine-spec-reporter": "3.2.0",
|
||||
"karma": "1.4.1",
|
||||
|
||||
@ -7,6 +7,7 @@ import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
import { InsightApp } from './app.component';
|
||||
import { PagesModule, BlocksPage, BroadcastTxPage, NodeStatusPage, VerifyMessagePage } from '../pages';
|
||||
import { BlocksService, StorageService } from '../services';
|
||||
import { ApiProvider } from '../providers/api/api';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -31,7 +32,8 @@ import { BlocksService, StorageService } from '../services';
|
||||
SplashScreen,
|
||||
StorageService,
|
||||
BlocksService,
|
||||
{provide: ErrorHandler, useClass: IonicErrorHandler}
|
||||
{provide: ErrorHandler, useClass: IonicErrorHandler},
|
||||
ApiProvider
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@ -7,7 +7,14 @@
|
||||
// styles are for the entire app and not just one component.
|
||||
// Additionally, this file can be also used as an entry point
|
||||
// to import other Sass files to be included in the output CSS.
|
||||
//
|
||||
|
||||
.ellipsis {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
// Shared Sass variables, which can be used to adjust Ionic's
|
||||
// default Sass variables, belong in "theme/variables.scss".
|
||||
//
|
||||
|
||||
12
app/src/components/head-nav/head-nav.html
Normal file
12
app/src/components/head-nav/head-nav.html
Normal file
@ -0,0 +1,12 @@
|
||||
<ion-navbar color="primary">
|
||||
<button ion-button menuToggle>
|
||||
<ion-icon name="menu"></ion-icon>
|
||||
</button>
|
||||
<ion-title>{{title}}</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only>
|
||||
<ion-icon name="search"></ion-icon>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
<ion-searchbar (ionInput)="search($event)" placeholder="{{ 'Search for block, transaction or address' }}" [(ngModel)]="q" [debounce]="1000"></ion-searchbar>
|
||||
16
app/src/components/head-nav/head-nav.module.ts
Normal file
16
app/src/components/head-nav/head-nav.module.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { HeadNavComponent } from './head-nav';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
HeadNavComponent,
|
||||
],
|
||||
imports: [
|
||||
IonicModule,
|
||||
],
|
||||
exports: [
|
||||
HeadNavComponent
|
||||
]
|
||||
})
|
||||
export class HeadNavComponentModule {}
|
||||
3
app/src/components/head-nav/head-nav.scss
Normal file
3
app/src/components/head-nav/head-nav.scss
Normal file
@ -0,0 +1,3 @@
|
||||
head-nav {
|
||||
|
||||
}
|
||||
101
app/src/components/head-nav/head-nav.ts
Normal file
101
app/src/components/head-nav/head-nav.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Input } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/**
|
||||
* Generated class for the HeadNavComponent component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'head-nav',
|
||||
templateUrl: 'head-nav.html'
|
||||
})
|
||||
export class HeadNavComponent {
|
||||
|
||||
public loading: boolean;
|
||||
@Input() public title: string;
|
||||
public q: string;
|
||||
public badQuery: boolean = false;
|
||||
|
||||
constructor(private navCtrl: NavController, private http: Http, private api: ApiProvider) {
|
||||
}
|
||||
|
||||
private resetSearch(): void {
|
||||
this.q = '';
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
public search(): void {
|
||||
let apiPrefix: string = this.api.apiPrefix;
|
||||
|
||||
this.http.get(apiPrefix + 'block/' + this.q).subscribe(
|
||||
function (data: any) {
|
||||
this.resetSearch();
|
||||
console.log('block', data);
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': parsedData.hash
|
||||
});
|
||||
}.bind(this),
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'tx/' + this.q).subscribe(
|
||||
function (data: any) {
|
||||
this.resetSearch();
|
||||
console.log('tx', data);
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
this.navCtrl.push('transaction', {
|
||||
'txId': parsedData.txid
|
||||
});
|
||||
}.bind(this),
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'addr/' + this.q).subscribe(
|
||||
function (data: any) {
|
||||
this.resetSearch();
|
||||
console.log('addr', data);
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
this.navCtrl.push('address', {
|
||||
'addrStr': parsedData.addrStr
|
||||
});
|
||||
}.bind(this),
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'block-index/' + this.q).subscribe(
|
||||
function (data: any): void {
|
||||
this.resetSearch();
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': parsedData.blockHash
|
||||
});
|
||||
}.bind(this),
|
||||
function (): void {
|
||||
this.loading = false;
|
||||
this.reportBadQuery();
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* tslint:disable:no-unused-variable */
|
||||
private reportBadQuery(): void {
|
||||
this.badQuery = true;
|
||||
console.log('badQuery', this.badQuery);
|
||||
|
||||
setTimeout(
|
||||
function (): void {
|
||||
this.badQuery = false;
|
||||
console.log('badQuery', this.badQuery);
|
||||
}.bind(this),
|
||||
2000
|
||||
);
|
||||
};
|
||||
/* tslint:enable:no-unused-variable */
|
||||
|
||||
}
|
||||
@ -0,0 +1,7 @@
|
||||
<ion-grid>
|
||||
<ion-row *ngFor="let tx of transactions.txs">
|
||||
<ion-col col-12>
|
||||
<transaction [tx]="tx"></transaction>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { TransactionListComponent } from './transaction-list';
|
||||
import { TransactionComponentModule } from '../transaction/transaction.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
TransactionListComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule,
|
||||
TransactionComponentModule
|
||||
],
|
||||
exports: [
|
||||
TransactionListComponent
|
||||
]
|
||||
})
|
||||
export class TransactionListComponentModule {}
|
||||
@ -0,0 +1,3 @@
|
||||
transaction-list {
|
||||
|
||||
}
|
||||
40
app/src/components/transaction-list/transaction-list.ts
Normal file
40
app/src/components/transaction-list/transaction-list.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Input } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/**
|
||||
* Generated class for the TransactionListComponent component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'transaction-list',
|
||||
templateUrl: 'transaction-list.html'
|
||||
})
|
||||
export class TransactionListComponent {
|
||||
|
||||
public loading: boolean = true;
|
||||
@Input() public queryType: string;
|
||||
@Input() public queryValue: string;
|
||||
public transactions: any = [];
|
||||
|
||||
constructor(private http: Http, private api: ApiProvider) {
|
||||
}
|
||||
|
||||
private ngOnInit(): void {
|
||||
let url: string = this.api.apiPrefix + 'txs?' + this.queryType + '=' + this.queryValue;
|
||||
|
||||
this.http.get(url).subscribe(
|
||||
(data) => {
|
||||
this.transactions = JSON.parse(data['_body']);
|
||||
this.loading = false;
|
||||
},
|
||||
(err) => {
|
||||
console.log('err is', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
83
app/src/components/transaction/transaction.html
Normal file
83
app/src/components/transaction/transaction.html
Normal file
@ -0,0 +1,83 @@
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-col col-8>
|
||||
<div class="ellipsis">
|
||||
<ion-icon name="add-circle" [hidden]="expanded" (click)="toggleExpanded()"></ion-icon><ion-icon name="remove-circle" [hidden]="!expanded" (click)="toggleExpanded()"></ion-icon> <span><a (click)="goToTx(tx.txid)">{{ tx.txid }}</a></span>
|
||||
</div>
|
||||
</ion-col>
|
||||
<ion-col col-4 text-right>
|
||||
<div [hidden]="!tx.firstSeenTs">
|
||||
<span translate>first seen at</span>
|
||||
<time>{{tx.firstSeenTs * 1000 | date:'medium'}}</time>
|
||||
</div>
|
||||
<div [hidden]="!tx.blocktime && tx.firstSeenTs">
|
||||
<span translate>mined</span>
|
||||
<time>{{tx.time * 1000 | date:'medium'}}</time>
|
||||
</div>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<ion-row>
|
||||
<ion-col col-5>
|
||||
|
||||
<ion-list [hidden]="!tx.isCoinBase">
|
||||
<ion-item>
|
||||
No Inputs (Newly Generated Coins)
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<ion-list [hidden]="tx.isCoinBase">
|
||||
<ion-item *ngFor="let vin of tx.vin">
|
||||
<div>
|
||||
<p><a (click)="goToAddress(vin.addr)">{{ vin.addr }}</a> <span item-end>{{ vin.value + ' BTC' }}</span></p>
|
||||
<div [hidden]="!expanded">
|
||||
<p><b>Confirmations</b> {{vin.confirmations}}</p>
|
||||
<p><b>scriptSig</b></p>
|
||||
<div *ngIf="vin.scriptSig">
|
||||
<div *ngFor="let item of vin.scriptSig.asm | split:' '" class="ellipsis">
|
||||
<p>{{item}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
</ion-col>
|
||||
<ion-col col-2 text-center>
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</ion-col>
|
||||
<ion-col col-5>
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let vout of tx.vout">
|
||||
<div>
|
||||
<p><a (click)="goToAddress(getAddress(vout))">{{ getAddress(vout) }}</a></p>
|
||||
<div [hidden]="!expanded">
|
||||
<p><b>Type</b> {{vout.scriptPubKey.type}}</p>
|
||||
<p><b>scriptPubKey</b></p>
|
||||
<div class="ellipsis">
|
||||
<span>{{vout.scriptPubKey.asm}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div item-end>
|
||||
{{ vout.value + ' BTC' }}
|
||||
<span [hidden]="!vout.spentTxId">(S)</span>
|
||||
<span [hidden]="vout.spentTxId">(U)</span>
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<ion-row>
|
||||
<ion-col col-6>
|
||||
<span [hidden]="tx.isCoinBase">Fee {{ tx.fees + ' BTC' }}</span>
|
||||
</ion-col>
|
||||
<ion-col col-6 text-right>
|
||||
{{ tx.confirmations }} Confirmations
|
||||
<span class="">{{ tx.valueOut + ' BTC' }}</span>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
18
app/src/components/transaction/transaction.module.ts
Normal file
18
app/src/components/transaction/transaction.module.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { TransactionComponent } from './transaction';
|
||||
import { SplitPipe } from '../../pipes/split/split';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
TransactionComponent,
|
||||
SplitPipe
|
||||
],
|
||||
imports: [
|
||||
IonicModule
|
||||
],
|
||||
exports: [
|
||||
TransactionComponent
|
||||
]
|
||||
})
|
||||
export class TransactionComponentModule {}
|
||||
11
app/src/components/transaction/transaction.scss
Normal file
11
app/src/components/transaction/transaction.scss
Normal file
@ -0,0 +1,11 @@
|
||||
transaction {
|
||||
ion-grid {
|
||||
background-color: #F4F4F4;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 2px;
|
||||
|
||||
ion-row {
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
app/src/components/transaction/transaction.ts
Normal file
46
app/src/components/transaction/transaction.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Input } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
* Generated class for the TransactionComponent component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'transaction',
|
||||
templateUrl: 'transaction.html'
|
||||
})
|
||||
export class TransactionComponent {
|
||||
|
||||
public expanded: boolean = false;
|
||||
@Input() public tx: any = {};
|
||||
|
||||
constructor(private navCtrl: NavController) {
|
||||
}
|
||||
|
||||
public getAddress(vout: any): string {
|
||||
if (vout.scriptPubKey && vout.scriptPubKey.addresses) {
|
||||
return vout.scriptPubKey.addresses[0];
|
||||
} else {
|
||||
return 'Unparsed address';
|
||||
}
|
||||
}
|
||||
|
||||
public goToTx(txId: string): void {
|
||||
this.navCtrl.push('transaction', {
|
||||
'txId': txId
|
||||
});
|
||||
}
|
||||
|
||||
public goToAddress(addrStr: string): void {
|
||||
this.navCtrl.push('address', {
|
||||
'addrStr': addrStr
|
||||
});
|
||||
}
|
||||
|
||||
public toggleExpanded(): void {
|
||||
this.expanded = !this.expanded;
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
<div>
|
||||
<div *ngFor="let tx of transactions.txs" style="border: 1px solid purple">
|
||||
<p>{{ tx.txid }}</p>
|
||||
<div [hidden]="!tx.firstSeenTs">
|
||||
<span translate>first seen at</span>
|
||||
<time>{{tx.firstSeenTs * 1000 | date:'medium'}}</time>
|
||||
</div>
|
||||
<div [hidden]="!tx.blocktime && tx.firstSeenTs">
|
||||
<span translate>mined</span>
|
||||
<time>{{tx.time * 1000 | date:'medium'}}</time>
|
||||
</div>
|
||||
|
||||
<div [hidden]="!tx.isCoinBase">
|
||||
<div *ngFor="let vin of tx.vin">
|
||||
<div>
|
||||
<span translate>No Inputs (Newly Generated Coins)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let vout of tx.vout">
|
||||
<div>
|
||||
<p>{{ getAddress(vout) }} {{ vout.value + ' BTC' }} <span [hidden]="!vout.spentTxId">(S)</span><span [hidden]="vout.spentTxId">(U)</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [hidden]="tx.isCoinBase">
|
||||
<div *ngFor="let vin of tx.vin">
|
||||
<div>{{ vin.addr }}</div>
|
||||
<p>{{ vin.value + ' BTC' }}</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let vout of tx.vout">
|
||||
<div>
|
||||
<p>{{ getAddress(vout) }} {{ vout.value + ' BTC' }} <span [hidden]="!vout.spentTxId">(S)</span><span [hidden]="vout.spentTxId">(U)</span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,16 +0,0 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { TransactionsComponent } from './transactions';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
TransactionsComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule
|
||||
],
|
||||
exports: [
|
||||
TransactionsComponent
|
||||
]
|
||||
})
|
||||
export class TransactionsComponentModule {}
|
||||
@ -1,3 +0,0 @@
|
||||
transactions {
|
||||
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Input } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
|
||||
/**
|
||||
* Generated class for the TransactionsComponent component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'transactions',
|
||||
templateUrl: 'transactions.html'
|
||||
})
|
||||
export class TransactionsComponent {
|
||||
|
||||
public loading: boolean = true;
|
||||
@Input() public blockHash: string;
|
||||
public transactions: any = [];
|
||||
|
||||
constructor(private http: Http) {
|
||||
}
|
||||
|
||||
private ngOnInit(): void {
|
||||
let apiPrefix: string = 'http://localhost:3001/insight-api/';
|
||||
|
||||
this.http.get(apiPrefix + 'txs?block=' + this.blockHash).subscribe(
|
||||
(data) => {
|
||||
this.transactions = JSON.parse(data['_body']);
|
||||
this.loading = false;
|
||||
|
||||
this.transactions.txs.forEach((tx) => {
|
||||
console.log('tx is', tx);
|
||||
});
|
||||
},
|
||||
(err) => {
|
||||
console.log('err is', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public getAddress(vout: any): string {
|
||||
if (vout.scriptPubKey && vout.scriptPubKey.addresses) {
|
||||
return vout.scriptPubKey.addresses[0];
|
||||
} else {
|
||||
return 'Unparsed address';
|
||||
}
|
||||
}
|
||||
}
|
||||
47
app/src/pages/address/address.html
Normal file
47
app/src/pages/address/address.html
Normal file
@ -0,0 +1,47 @@
|
||||
<ion-header>
|
||||
<head-nav [title]="'Address'"></head-nav>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Address</h1>
|
||||
<p class="ellipsis"><b>Address</b> {{ address.addrStr }}</p>
|
||||
<p>{{ address.balance }} BTC</p>
|
||||
|
||||
<h2>Summary</h2>
|
||||
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
Total Received
|
||||
<span item-end>
|
||||
{{ address.totalReceived }} BTC
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Total Sent
|
||||
<span item-end>
|
||||
{{ address.totalSent }} BTC
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Final Balance
|
||||
<span item-end>
|
||||
{{ address.balance }} BTC
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
No. Transactions
|
||||
<span item-end>
|
||||
{{ address.txApperances }}
|
||||
</span>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<p text-center>
|
||||
<qr-code [value]="address.addrStr" [size]="160"></qr-code>
|
||||
<p>
|
||||
|
||||
<h2>Transactions</h2>
|
||||
|
||||
<transaction-list [queryType]="'address'" [queryValue]="addrStr"></transaction-list>
|
||||
|
||||
</ion-content>
|
||||
22
app/src/pages/address/address.module.ts
Normal file
22
app/src/pages/address/address.module.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { AddressPage } from './address';
|
||||
import { TransactionListComponentModule } from '../../components/transaction-list/transaction-list.module';
|
||||
import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module';
|
||||
import { QRCodeModule } from 'angular2-qrcode';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AddressPage
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild(AddressPage),
|
||||
TransactionListComponentModule,
|
||||
HeadNavComponentModule,
|
||||
QRCodeModule
|
||||
],
|
||||
exports: [
|
||||
AddressPage
|
||||
]
|
||||
})
|
||||
export class AddressPageModule {}
|
||||
3
app/src/pages/address/address.scss
Normal file
3
app/src/pages/address/address.scss
Normal file
@ -0,0 +1,3 @@
|
||||
page-address {
|
||||
|
||||
}
|
||||
43
app/src/pages/address/address.ts
Normal file
43
app/src/pages/address/address.ts
Normal file
@ -0,0 +1,43 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/**
|
||||
* Generated class for the AddressPage page.
|
||||
*
|
||||
* See http://ionicframework.com/docs/components/#navigation for more info
|
||||
* on Ionic pages and navigation.
|
||||
*/
|
||||
@IonicPage({
|
||||
name: 'address',
|
||||
segment: 'address/:addrStr'
|
||||
})
|
||||
@Component({
|
||||
selector: 'page-address',
|
||||
templateUrl: 'address.html'
|
||||
})
|
||||
export class AddressPage {
|
||||
|
||||
public loading: boolean = true;
|
||||
private addrStr: string;
|
||||
public address: any = {};
|
||||
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, private api: ApiProvider) {
|
||||
this.addrStr = navParams.get('addrStr');
|
||||
}
|
||||
|
||||
public ionViewDidLoad(): void {
|
||||
this.http.get(this.api.apiPrefix + 'addr/' + this.addrStr + '/?noTxList=1').subscribe(
|
||||
(data) => {
|
||||
this.address = JSON.parse(data['_body']);
|
||||
this.loading = false;
|
||||
},
|
||||
(err) => {
|
||||
console.log('err is', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,41 +1,98 @@
|
||||
<!--
|
||||
Generated template for the BlockDetailPage page.
|
||||
|
||||
See http://ionicframework.com/docs/components/#navigation for more info on
|
||||
Ionic pages and navigation.
|
||||
-->
|
||||
<ion-header>
|
||||
|
||||
<ion-navbar>
|
||||
<ion-title>Block Detail</ion-title>
|
||||
</ion-navbar>
|
||||
|
||||
<head-nav [title]="'Block'"></head-nav>
|
||||
</ion-header>
|
||||
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Block # {{ block.height }}</h1>
|
||||
<p>BlockHash {{ block.hash }}</p>
|
||||
<h2>Summary</h2>
|
||||
<div *ngIf="!loading">
|
||||
<p>Number of Transactions {{ block.tx.length }}</p>
|
||||
<p>Height {{ block.height }} <span [hidden]="!block.isMainChain">(Mainchain)</span></p>
|
||||
<p>Block Reward {{ block.reward + ' BTC' }}</p>
|
||||
<p>Timestamp {{ block.time * 1000 | date:'medium' }}</p>
|
||||
<p>Mined by <a href="{{ block.poolInfo.url }}">{{ block.poolInfo.poolName }}</a></p>
|
||||
<p>Merkle Root {{ block.merkleroot }}</p>
|
||||
<p>Previous Block <a (click)="goToPreviousBlock()">{{ block.height - 1 }}</a></p>
|
||||
<p>Difficulty {{ block.difficulty }}</p>
|
||||
<p>Bits {{ block.bits }}</p>
|
||||
<p>Size (bytes) {{ block.size }}</p>
|
||||
<p>Version {{ block.version }}</p>
|
||||
<p>Nonce {{ block.nonce }}</p>
|
||||
<p>Next Block <a (click)="goToNextBlock()">{{ block.height + 1 }}</a></p>
|
||||
<h1>Block #{{ block.height }}</h1>
|
||||
<p class="ellipsis"><b>BlockHash</b> {{ block.hash }}</p>
|
||||
|
||||
<h3>Transactions</h3>
|
||||
<transactions [blockHash]="block.hash"></transactions>
|
||||
</div>
|
||||
<div *ngIf="loading">
|
||||
<p>Loading...</p>
|
||||
<h2>Summary</h2>
|
||||
|
||||
<ion-list *ngIf="!loading">
|
||||
<ion-item>
|
||||
Number of Transactions
|
||||
<span item-end>
|
||||
{{ block.tx.length }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Height
|
||||
<span item-end>
|
||||
{{ block.height }} <span [hidden]="!block.isMainChain">(Mainchain)</span>
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Block Reward
|
||||
<span item-end>
|
||||
{{ block.reward + ' BTC' }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Timestamp
|
||||
<span item-end>
|
||||
{{ block.time * 1000 | date:'medium' }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Mined by
|
||||
<span item-end>
|
||||
<a href="{{ block.poolInfo.url }}">{{ block.poolInfo.poolName }}</a>
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Merkle Root
|
||||
<span item-end class="ellipsis">
|
||||
{{ block.merkleroot }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Previous Block
|
||||
<span item-end>
|
||||
<a (click)="goToPreviousBlock()">{{ block.height - 1 }}</a>
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Difficulty
|
||||
<span item-end>
|
||||
{{ block.difficulty }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Bits
|
||||
<span item-end>
|
||||
{{ block.bits }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Size (bytes)
|
||||
<span item-end>
|
||||
{{ block.size }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Version
|
||||
<span item-end>
|
||||
{{ block.version }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Nonce
|
||||
<span item-end>
|
||||
{{ block.nonce }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Next Block
|
||||
<span item-end>
|
||||
<a (click)="goToNextBlock()">{{ block.height + 1 }}</a>
|
||||
</span>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<h2>Transactions</h2>
|
||||
|
||||
<transaction-list [queryType]="'block'" [queryValue]="block.hash"></transaction-list>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@ -1,15 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { BlockDetailPage } from './block-detail';
|
||||
import { TransactionsComponent } from '../../components/transactions/transactions';
|
||||
import { TransactionListComponentModule } from '../../components/transaction-list/transaction-list.module';
|
||||
import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
BlockDetailPage,
|
||||
TransactionsComponent
|
||||
BlockDetailPage
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild(BlockDetailPage)
|
||||
IonicPageModule.forChild(BlockDetailPage),
|
||||
TransactionListComponentModule,
|
||||
HeadNavComponentModule
|
||||
],
|
||||
exports: [
|
||||
BlockDetailPage
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/**
|
||||
* Generated class for the BlockDetailPage page.
|
||||
@ -24,12 +25,10 @@ export class BlockDetailPage {
|
||||
tx: []
|
||||
};
|
||||
|
||||
constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams) {
|
||||
constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams, private api: ApiProvider) {
|
||||
this.blockHash = navParams.get('blockHash');
|
||||
|
||||
let apiPrefix: string = 'http://localhost:3001/insight-api/';
|
||||
|
||||
this.http.get(apiPrefix + 'block/' + this.blockHash).subscribe(
|
||||
this.http.get(this.api.apiPrefix + 'block/' + this.blockHash).subscribe(
|
||||
(data) => {
|
||||
this.block = JSON.parse(data['_body']);
|
||||
this.loading = false;
|
||||
|
||||
@ -1,41 +1,32 @@
|
||||
<ion-header>
|
||||
<ion-navbar color="primary">
|
||||
<button ion-button menuToggle>
|
||||
<ion-icon name="menu"></ion-icon>
|
||||
</button>
|
||||
<ion-title>{{title}}</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only>
|
||||
<ion-icon name="search"></ion-icon>
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-navbar>
|
||||
<head-nav [title]="'Blocks'"></head-nav>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<ion-list>
|
||||
<ion-grid>
|
||||
<ion-row>
|
||||
<ion-searchbar (ionInput)="search($event)" placeholder="{{ 'Search for block, transaction or address' }}" [(ngModel)]="q"></ion-searchbar>
|
||||
<ion-col><b>Height</b></ion-col>
|
||||
<ion-col><b>Timestamp</b></ion-col>
|
||||
<ion-col text-right><b>Transactions</b></ion-col>
|
||||
<ion-col><b>Mined By</b></ion-col>
|
||||
<ion-col text-right><b>Size</b></ion-col>
|
||||
</ion-row>
|
||||
<ion-item>
|
||||
<ion-row>
|
||||
<ion-col>Height</ion-col>
|
||||
<ion-col>Transactions</ion-col>
|
||||
<ion-col>Mined By</ion-col>
|
||||
</ion-row>
|
||||
</ion-item>
|
||||
<ion-item *ngFor="let block of blocks | async">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
#{{block.height}}
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
{{block.transactionCount}} transactions
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<a *ngIf="block.poolName" href="{{block.url}}">{{block.poolName}}</a>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<ion-row *ngFor="let block of blocks | async">
|
||||
<ion-col>
|
||||
<a (click)="goToBlock(block.hash)">{{block.height}}</a>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
{{ block.timestamp * 1000 | date:'medium' }}
|
||||
</ion-col>
|
||||
<ion-col text-right>
|
||||
{{block.transactionCount}}
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<a *ngIf="block.poolName" href="{{block.url}}">{{block.poolName}}</a>
|
||||
</ion-col>
|
||||
<ion-col text-right>
|
||||
{{ block.size }}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</ion-content>
|
||||
|
||||
@ -21,9 +21,11 @@ describe('Blocks', () => {
|
||||
expect(instance).toBeTruthy();
|
||||
});
|
||||
|
||||
/*
|
||||
it('has a search method', () => {
|
||||
spyOn(instance, 'search');
|
||||
instance.search();
|
||||
expect(instance.search).toHaveBeenCalled();
|
||||
});
|
||||
*/
|
||||
});
|
||||
|
||||
@ -3,7 +3,6 @@ import { NavController } from 'ionic-angular';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Block } from '../../models';
|
||||
import { BlocksService } from '../../services';
|
||||
import { Http } from '@angular/http';
|
||||
|
||||
@Component({
|
||||
templateUrl: './blocksPage.html'
|
||||
@ -11,81 +10,22 @@ import { Http } from '@angular/http';
|
||||
|
||||
export class BlocksPage {
|
||||
|
||||
public loading: boolean;
|
||||
public title: string;
|
||||
public blocks: Observable<Block[]>;
|
||||
public q: string;
|
||||
public badQuery: boolean = false;
|
||||
|
||||
constructor(private navCtrl: NavController, private http: Http, private blocksService: BlocksService) {
|
||||
constructor(private navCtrl: NavController, private blocksService: BlocksService) {
|
||||
this.title = 'Blocks';
|
||||
this.blocks = blocksService.latestBlocks;
|
||||
// this.blocks.subscribe((blocks) => {
|
||||
// console.log(blocks);
|
||||
// });
|
||||
this.blocks.subscribe((blocks) => {
|
||||
console.log('blocks', blocks);
|
||||
});
|
||||
blocksService.getLatestBlocks();
|
||||
}
|
||||
|
||||
public search(): void {
|
||||
console.log('q is', this.q);
|
||||
let apiPrefix: string = 'http://localhost:3001/insight-api/';
|
||||
this.http.get(apiPrefix + 'block/' + this.q).subscribe(
|
||||
(data) => {
|
||||
this.resetSearch();
|
||||
console.log('block', data);
|
||||
},
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'tx/' + this.q).subscribe(
|
||||
(data: any) => {
|
||||
this.resetSearch();
|
||||
console.log('tx', data);
|
||||
},
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'addr/' + this.q).subscribe(
|
||||
(data: any) => {
|
||||
this.resetSearch();
|
||||
console.log('addr', data);
|
||||
},
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'block-index/' + this.q).subscribe(
|
||||
function (data: any): void {
|
||||
this.resetSearch();
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': parsedData.blockHash
|
||||
});
|
||||
}.bind(this),
|
||||
function (): void {
|
||||
this.loading = false;
|
||||
this.reportBadQuery();
|
||||
}.bind(this)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
public goToBlock(blockHash: string): void {
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': blockHash
|
||||
});
|
||||
}
|
||||
|
||||
private resetSearch(): void {
|
||||
this.q = '';
|
||||
this.loading = false;
|
||||
}
|
||||
|
||||
/* tslint:disable:no-unused-variable */
|
||||
private reportBadQuery(): void {
|
||||
this.badQuery = true;
|
||||
console.log('badQuery', this.badQuery);
|
||||
|
||||
setTimeout(
|
||||
function (): void {
|
||||
this.badQuery = false;
|
||||
console.log('badQuery', this.badQuery);
|
||||
}.bind(this),
|
||||
2000
|
||||
);
|
||||
};
|
||||
/* tslint:enable:no-unused-variable */
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { ComponentsModule } from '../components';
|
||||
import { HeadNavComponentModule } from '../components/head-nav/head-nav.module';
|
||||
import {
|
||||
BlocksPage,
|
||||
BroadcastTxPage,
|
||||
@ -15,7 +16,7 @@ import {
|
||||
NodeStatusPage,
|
||||
VerifyMessagePage
|
||||
],
|
||||
imports: [ IonicModule, ComponentsModule ],
|
||||
imports: [ IonicModule, ComponentsModule, HeadNavComponentModule ],
|
||||
exports: [
|
||||
// CustomComponent,
|
||||
],
|
||||
|
||||
42
app/src/pages/transaction/transaction.html
Normal file
42
app/src/pages/transaction/transaction.html
Normal file
@ -0,0 +1,42 @@
|
||||
<ion-header>
|
||||
<head-nav [title]="'Transaction'"></head-nav>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Transaction</h1>
|
||||
<p class="ellipsis"><b>Transaction</b> {{ tx.txid }}</p>
|
||||
|
||||
<h2>Summary</h2>
|
||||
|
||||
<ion-list>
|
||||
<ion-item>
|
||||
Size
|
||||
<span item-end>
|
||||
{{ tx.size }} (bytes)
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Received Time
|
||||
<span item-end>
|
||||
{{ tx.time * 1000 | date:'medium' }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Mined Time
|
||||
<span item-end>
|
||||
{{ tx.blocktime * 1000 | date:'medium' }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Included in Block
|
||||
<span item-end>
|
||||
<a (click)="goToBlock(tx.blockhash)">{{ tx.blockhash }}</a>
|
||||
</span>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<h2>Details</h2>
|
||||
|
||||
<transaction [tx]="tx"></transaction>
|
||||
|
||||
</ion-content>
|
||||
20
app/src/pages/transaction/transaction.module.ts
Normal file
20
app/src/pages/transaction/transaction.module.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { TransactionPage } from './transaction';
|
||||
import { TransactionComponentModule } from '../../components/transaction/transaction.module';
|
||||
import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
TransactionPage
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild(TransactionPage),
|
||||
TransactionComponentModule,
|
||||
HeadNavComponentModule
|
||||
],
|
||||
exports: [
|
||||
TransactionPage
|
||||
]
|
||||
})
|
||||
export class TransactionPageModule {}
|
||||
3
app/src/pages/transaction/transaction.scss
Normal file
3
app/src/pages/transaction/transaction.scss
Normal file
@ -0,0 +1,3 @@
|
||||
page-transaction {
|
||||
|
||||
}
|
||||
48
app/src/pages/transaction/transaction.ts
Normal file
48
app/src/pages/transaction/transaction.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/**
|
||||
* Generated class for the TransactionPage page.
|
||||
*
|
||||
* See http://ionicframework.com/docs/components/#navigation for more info
|
||||
* on Ionic pages and navigation.
|
||||
*/
|
||||
@IonicPage({
|
||||
name: 'transaction',
|
||||
segment: 'tx/:txId'
|
||||
})
|
||||
@Component({
|
||||
selector: 'page-transaction',
|
||||
templateUrl: 'transaction.html'
|
||||
})
|
||||
export class TransactionPage {
|
||||
|
||||
public loading: boolean = true;
|
||||
private txId: string;
|
||||
public tx: any = {};
|
||||
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, private api: ApiProvider) {
|
||||
this.txId = navParams.get('txId');
|
||||
}
|
||||
|
||||
public ionViewDidLoad(): void {
|
||||
this.http.get(this.api.apiPrefix + 'tx/' + this.txId).subscribe(
|
||||
(data) => {
|
||||
this.tx = JSON.parse(data['_body']);
|
||||
this.loading = false;
|
||||
},
|
||||
(err) => {
|
||||
console.log('err is', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public goToBlock(blockHash: string): void {
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': blockHash
|
||||
});
|
||||
}
|
||||
}
|
||||
21
app/src/pipes/split/split.ts
Normal file
21
app/src/pipes/split/split.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { Pipe, PipeTransform } from '@angular/core';
|
||||
|
||||
/**
|
||||
* Generated class for the SplitPipe pipe.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/guide/pipes.html for more info on
|
||||
* Angular Pipes.
|
||||
*/
|
||||
@Pipe({
|
||||
name: 'split'
|
||||
})
|
||||
export class SplitPipe implements PipeTransform {
|
||||
/**
|
||||
* Takes a value and makes it lowercase.
|
||||
*/
|
||||
public transform(value: string, delimiter: string): Array<string> {
|
||||
let array: Array<string> = value.split(delimiter);
|
||||
console.log('split is', array);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
19
app/src/providers/api/api.ts
Normal file
19
app/src/providers/api/api.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
/*
|
||||
Generated class for the ApiProvider provider.
|
||||
|
||||
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
|
||||
for more info on providers and Angular DI.
|
||||
*/
|
||||
@Injectable()
|
||||
export class ApiProvider {
|
||||
|
||||
public apiPrefix: string = 'http://localhost:3001/insight-api/';
|
||||
|
||||
constructor(public http: Http) {
|
||||
}
|
||||
|
||||
}
|
||||
78
app/src/providers/currency/currency.spec.ts
Normal file
78
app/src/providers/currency/currency.spec.ts
Normal file
@ -0,0 +1,78 @@
|
||||
/* tslint:disable:no-unused-variable */
|
||||
import { TestBed, ComponentFixture, inject } from '@angular/core/testing';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { CurrencyProvider } from './currency';
|
||||
|
||||
describe('CurrencyProvider', () => {
|
||||
let currency;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
HttpModule
|
||||
],
|
||||
providers: [
|
||||
CurrencyProvider
|
||||
]
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(inject([CurrencyProvider], _cp => {
|
||||
currency = _cp;
|
||||
}));
|
||||
|
||||
it('initialises', () => {
|
||||
expect(currency).not.toBeNull();
|
||||
expect(currency.defaultCurrency).toBe('BTC');
|
||||
expect(currency.currencySymbol).toBe('BTC');
|
||||
expect(currency.factor).toBe(1);
|
||||
});
|
||||
|
||||
it('sets currency by updating the symbol and changing the multiplication factor', () => {
|
||||
currency.setCurrency('USD');
|
||||
expect(currency.currencySymbol).toBe('USD');
|
||||
expect(currency.factor).toEqual(1);
|
||||
|
||||
currency.setCurrency('BTC');
|
||||
expect(currency.currencySymbol).toBe('BTC');
|
||||
expect(currency.factor).toEqual(1);
|
||||
|
||||
currency.setCurrency('mBTC');
|
||||
expect(currency.currencySymbol).toBe('mBTC');
|
||||
expect(currency.factor).toEqual(1000);
|
||||
|
||||
currency.setCurrency('bits');
|
||||
expect(currency.currencySymbol).toBe('bits');
|
||||
expect(currency.factor).toEqual(1000000);
|
||||
});
|
||||
|
||||
it('rounds float using specified number of decimal places', () => {
|
||||
let aFloat = 4.32943;
|
||||
|
||||
expect(currency.roundFloat(aFloat, 2)).toBe(4.33);
|
||||
expect(currency.roundFloat(aFloat, 3)).toBe(4.329);
|
||||
expect(currency.roundFloat(aFloat, 4)).toBe(4.3294);
|
||||
expect(currency.roundFloat(aFloat, 5)).toBe(4.32943);
|
||||
|
||||
aFloat = 1234567890.09876543;
|
||||
|
||||
expect(currency.roundFloat(aFloat, 2)).toBe(1234567890.10);
|
||||
expect(currency.roundFloat(aFloat, 3)).toBe(1234567890.099);
|
||||
expect(currency.roundFloat(aFloat, 4)).toBe(1234567890.0988);
|
||||
expect(currency.roundFloat(aFloat, 5)).toBe(1234567890.09877);
|
||||
expect(currency.roundFloat(aFloat, 6)).toBe(1234567890.098765);
|
||||
expect(currency.roundFloat(aFloat, 7)).toBe(1234567890.0987654);
|
||||
expect(currency.roundFloat(aFloat, 8)).toBe(1234567890.09876543);
|
||||
});
|
||||
|
||||
it('gets proper conversion after changing currency', () => {
|
||||
let aFloat = 12345.09876543;
|
||||
expect(currency.getConversion(aFloat)).toBe('12345.09876543 BTC');
|
||||
|
||||
currency.setCurrency('mBTC');
|
||||
expect(currency.getConversion(aFloat)).toBe('12345098.76543 mBTC');
|
||||
|
||||
currency.setCurrency('bits');
|
||||
expect(currency.getConversion(aFloat)).toBe('12345098765.43 bits');
|
||||
});
|
||||
});
|
||||
68
app/src/providers/currency/currency.ts
Normal file
68
app/src/providers/currency/currency.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
/*
|
||||
Generated class for the CurrencyProvider provider.
|
||||
|
||||
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
|
||||
for more info on providers and Angular DI.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CurrencyProvider {
|
||||
|
||||
private defaultCurrency: string;
|
||||
private currencySymbol: string;
|
||||
private factor: number = 1;
|
||||
|
||||
constructor(public http: Http) {
|
||||
this.defaultCurrency = 'BTC';
|
||||
this.currencySymbol = this.defaultCurrency;
|
||||
}
|
||||
|
||||
private roundFloat(aFloat: number, decimalPlaces: number): number {
|
||||
return Math.round(aFloat * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
|
||||
}
|
||||
|
||||
public getConversion(value: number): string {
|
||||
if (value === 0.00000000) return '0 ' + this.currencySymbol; // fix value to show
|
||||
|
||||
let response: number;
|
||||
|
||||
if (this.currencySymbol === 'USD') {
|
||||
response = this.roundFloat((value * this.factor), 2);
|
||||
} else if (this.currencySymbol === 'mBTC') {
|
||||
this.factor = 1000;
|
||||
response = this.roundFloat((value * this.factor), 5);
|
||||
} else if (this.currencySymbol === 'bits') {
|
||||
this.factor = 1000000;
|
||||
response = this.roundFloat((value * this.factor), 2);
|
||||
} else { // assumes currencySymbol is BTC
|
||||
this.factor = 1;
|
||||
response = this.roundFloat((value * this.factor), 8);
|
||||
}
|
||||
|
||||
return response + ' ' + this.currencySymbol;
|
||||
}
|
||||
|
||||
public setCurrency(currency: string): void {
|
||||
this.currencySymbol = currency;
|
||||
localStorage.setItem('insight-currency', currency);
|
||||
|
||||
if (currency === 'USD') {
|
||||
// TODO Replace this with call
|
||||
/*
|
||||
Currency.get({}, function(res) {
|
||||
$rootScope.currency.factor = $rootScope.currency.bitstamp = res.data.bitstamp;
|
||||
});
|
||||
*/
|
||||
} else if (currency === 'mBTC') {
|
||||
this.factor = 1000;
|
||||
} else if (currency === 'bits') {
|
||||
this.factor = 1000000;
|
||||
} else {
|
||||
this.factor = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -16,6 +16,8 @@ import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController
|
||||
import { ConfigMock, PlatformMock } from './mocks';
|
||||
import { BlocksServiceMock } from './services/mocks';
|
||||
import { BlocksService } from './services';
|
||||
import { ApiProvider } from './providers/api/api';
|
||||
import { HeadNavComponentModule } from './components/head-nav/head-nav.module';
|
||||
|
||||
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
|
||||
declare var __karma__: any;
|
||||
@ -60,13 +62,15 @@ export class TestUtils {
|
||||
App, Form, Keyboard, DomController, MenuController, NavController, GestureController,
|
||||
{provide: Platform, useClass: PlatformMock},
|
||||
{provide: Config, useClass: ConfigMock},
|
||||
{provide: BlocksService, useClass: BlocksServiceMock}
|
||||
{provide: BlocksService, useClass: BlocksServiceMock},
|
||||
ApiProvider
|
||||
],
|
||||
imports: [
|
||||
FormsModule,
|
||||
IonicModule,
|
||||
ReactiveFormsModule,
|
||||
HttpModule
|
||||
HttpModule,
|
||||
HeadNavComponentModule
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
263
app/yarn.lock
263
app/yarn.lock
@ -159,42 +159,46 @@
|
||||
ws "1.1.1"
|
||||
xml2js "^0.4.17"
|
||||
|
||||
"@ionic/cli-plugin-cordova@1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-cordova/-/cli-plugin-cordova-1.4.0.tgz#2d3dd7bbd7321e0f1994b6f1a217176f55145296"
|
||||
"@ionic/cli-plugin-cordova@1.6.2":
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-cordova/-/cli-plugin-cordova-1.6.2.tgz#f71d10641df8b522f54f8274e0d5bc4dbb8b5208"
|
||||
dependencies:
|
||||
"@ionic/cli-utils" "1.4.0"
|
||||
chalk "^1.1.3"
|
||||
xml2js "^0.4.17"
|
||||
"@ionic/cli-utils" "1.7.0"
|
||||
chalk "^2.0.0"
|
||||
elementtree "^0.1.7"
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@ionic/cli-plugin-ionic-angular@1.3.1":
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-ionic-angular/-/cli-plugin-ionic-angular-1.3.1.tgz#8985f5a520db97ed6206615464e173d086ecd1ea"
|
||||
"@ionic/cli-plugin-ionic-angular@1.4.1":
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-ionic-angular/-/cli-plugin-ionic-angular-1.4.1.tgz#bb94b7ad61c2f79757b2dff041c0b7e2151777ec"
|
||||
dependencies:
|
||||
"@ionic/cli-utils" "1.4.0"
|
||||
chalk "^1.1.3"
|
||||
"@ionic/cli-utils" "1.7.0"
|
||||
chalk "^2.0.0"
|
||||
tslib "^1.7.1"
|
||||
|
||||
"@ionic/cli-utils@1.4.0":
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-utils/-/cli-utils-1.4.0.tgz#78c70b69c3b98a463aa01ea507d7d01da3dfa675"
|
||||
"@ionic/cli-utils@1.7.0":
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-utils/-/cli-utils-1.7.0.tgz#05bdbf3e7533eeeee27d58f3adbfe26bf2bf0d1d"
|
||||
dependencies:
|
||||
archiver "^1.3.0"
|
||||
chalk "^1.1.3"
|
||||
cross-spawn "^4.0.2"
|
||||
archiver "^2.0.0"
|
||||
chalk "^2.0.0"
|
||||
ci-info "^1.0.0"
|
||||
cross-spawn "^5.1.0"
|
||||
dargs "^5.1.0"
|
||||
inquirer "^3.0.6"
|
||||
dev-null "^0.1.1"
|
||||
inquirer "^3.2.1"
|
||||
leek "0.0.24"
|
||||
lodash "^4.17.4"
|
||||
minimist "^1.2.0"
|
||||
ncp "^2.0.0"
|
||||
os-name "^2.0.1"
|
||||
rimraf "^2.5.4"
|
||||
semver "^5.3.0"
|
||||
slice-ansi "0.0.4"
|
||||
string-width "^2.0.0"
|
||||
semver "^5.4.1"
|
||||
slice-ansi "^1.0.0"
|
||||
string-width "^2.1.1"
|
||||
strip-ansi "^4.0.0"
|
||||
superagent "^3.5.2"
|
||||
tslib "^1.7.1"
|
||||
uuid "^3.0.1"
|
||||
wrap-ansi "^2.1.0"
|
||||
wrap-ansi "^3.0.1"
|
||||
|
||||
"@ionic/storage@2.0.1":
|
||||
version "2.0.1"
|
||||
@ -331,6 +335,12 @@ amdefine@>=0.0.4:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||
|
||||
angular2-qrcode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/angular2-qrcode/-/angular2-qrcode-2.0.1.tgz#1b4e65c302694b5078ca06f71138f7e4367754dc"
|
||||
dependencies:
|
||||
qrious "^2.2.0"
|
||||
|
||||
ansi-escapes@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b"
|
||||
@ -385,9 +395,9 @@ archiver-utils@^1.3.0:
|
||||
normalize-path "^2.0.0"
|
||||
readable-stream "^2.0.0"
|
||||
|
||||
archiver@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22"
|
||||
archiver@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.0.0.tgz#ffb73ecccd8dd65b0019e1180f78092a053d43c4"
|
||||
dependencies:
|
||||
archiver-utils "^1.3.0"
|
||||
async "^2.0.0"
|
||||
@ -397,7 +407,7 @@ archiver@^1.3.0:
|
||||
readable-stream "^2.0.0"
|
||||
tar-stream "^1.5.0"
|
||||
walkdir "^0.0.11"
|
||||
zip-stream "^1.1.0"
|
||||
zip-stream "^1.2.0"
|
||||
|
||||
are-we-there-yet@~1.1.2:
|
||||
version "1.1.4"
|
||||
@ -1182,6 +1192,14 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000618, caniuse-db@^1.0.30000634, ca
|
||||
version "1.0.30000697"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000697.tgz#20ce6a9ceeef4ef4a15dc8e80f2e8fb9049e8d77"
|
||||
|
||||
canvas@^1.6.5:
|
||||
version "1.6.6"
|
||||
resolved "https://registry.yarnpkg.com/canvas/-/canvas-1.6.6.tgz#1c7af9e07d003dd082698b4a4e027773281029ca"
|
||||
dependencies:
|
||||
nan "^2.4.0"
|
||||
parse-css-font "^2.0.2"
|
||||
units-css "^0.4.0"
|
||||
|
||||
caseless@~0.11.0:
|
||||
version "0.11.0"
|
||||
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7"
|
||||
@ -1207,6 +1225,14 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3:
|
||||
strip-ansi "^3.0.0"
|
||||
supports-color "^2.0.0"
|
||||
|
||||
chalk@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e"
|
||||
dependencies:
|
||||
ansi-styles "^3.1.0"
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^4.0.0"
|
||||
|
||||
chalk@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d"
|
||||
@ -1245,6 +1271,10 @@ chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.6.1:
|
||||
optionalDependencies:
|
||||
fsevents "^1.0.0"
|
||||
|
||||
ci-info@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534"
|
||||
|
||||
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07"
|
||||
@ -1591,11 +1621,12 @@ cross-spawn@^3.0.0:
|
||||
lru-cache "^4.0.1"
|
||||
which "^1.2.9"
|
||||
|
||||
cross-spawn@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41"
|
||||
cross-spawn@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449"
|
||||
dependencies:
|
||||
lru-cache "^4.0.1"
|
||||
shebang-command "^1.2.0"
|
||||
which "^1.2.9"
|
||||
|
||||
cryptiles@2.x.x:
|
||||
@ -1623,6 +1654,32 @@ css-color-names@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||
|
||||
css-font-size-keywords@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-font-size-keywords/-/css-font-size-keywords-1.0.0.tgz#854875ace9aca6a8d2ee0d345a44aae9bb6db6cb"
|
||||
|
||||
css-font-stretch-keywords@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/css-font-stretch-keywords/-/css-font-stretch-keywords-1.0.1.tgz#50cee9b9ba031fb5c952d4723139f1e107b54b10"
|
||||
|
||||
css-font-style-keywords@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/css-font-style-keywords/-/css-font-style-keywords-1.0.1.tgz#5c3532813f63b4a1de954d13cea86ab4333409e4"
|
||||
|
||||
css-font-weight-keywords@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-font-weight-keywords/-/css-font-weight-keywords-1.0.0.tgz#9bc04671ac85bc724b574ef5d3ac96b0d604fd97"
|
||||
|
||||
css-global-keywords@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/css-global-keywords/-/css-global-keywords-1.0.1.tgz#72a9aea72796d019b1d2a3252de4e5aaa37e4a69"
|
||||
|
||||
css-list-helpers@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/css-list-helpers/-/css-list-helpers-1.0.1.tgz#fff57192202db83240c41686f919e449a7024f7d"
|
||||
dependencies:
|
||||
tcomb "^2.5.0"
|
||||
|
||||
css-loader@^0.28.1:
|
||||
version "0.28.4"
|
||||
resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.4.tgz#6cf3579192ce355e8b38d5f42dd7a1f2ec898d0f"
|
||||
@ -1663,6 +1720,10 @@ css-selector-tokenizer@^0.7.0:
|
||||
fastparse "^1.1.1"
|
||||
regexpu-core "^1.0.0"
|
||||
|
||||
css-system-font-keywords@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz#85c6f086aba4eb32c571a3086affc434b84823ed"
|
||||
|
||||
css-what@2.1:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd"
|
||||
@ -1840,6 +1901,10 @@ detect-node@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127"
|
||||
|
||||
dev-null@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/dev-null/-/dev-null-0.1.1.tgz#5a205ce3c2b2ef77b6238d6ba179eb74c6a0e818"
|
||||
|
||||
di@^0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c"
|
||||
@ -1959,6 +2024,12 @@ electron-to-chromium@^1.2.7:
|
||||
version "1.3.15"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz#08397934891cbcfaebbd18b82a95b5a481138369"
|
||||
|
||||
elementtree@^0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/elementtree/-/elementtree-0.1.7.tgz#9ac91be6e52fb6e6244c4e54a4ac3ed8ae8e29c0"
|
||||
dependencies:
|
||||
sax "1.1.4"
|
||||
|
||||
elliptic@^6.0.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df"
|
||||
@ -2966,7 +3037,7 @@ inline-process-browser@^1.0.0:
|
||||
falafel "^1.0.1"
|
||||
through2 "^0.6.5"
|
||||
|
||||
inquirer@^3.0.0, inquirer@^3.0.6:
|
||||
inquirer@^3.0.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.1.tgz#87621c4fba4072f48a8dd71c9f9df6f100b2d534"
|
||||
dependencies:
|
||||
@ -2985,6 +3056,25 @@ inquirer@^3.0.0, inquirer@^3.0.6:
|
||||
strip-ansi "^3.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
inquirer@^3.2.1:
|
||||
version "3.2.1"
|
||||
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.1.tgz#06ceb0f540f45ca548c17d6840959878265fa175"
|
||||
dependencies:
|
||||
ansi-escapes "^2.0.0"
|
||||
chalk "^2.0.0"
|
||||
cli-cursor "^2.1.0"
|
||||
cli-width "^2.0.0"
|
||||
external-editor "^2.0.4"
|
||||
figures "^2.0.0"
|
||||
lodash "^4.3.0"
|
||||
mute-stream "0.0.7"
|
||||
run-async "^2.2.0"
|
||||
rx-lite "^4.0.8"
|
||||
rx-lite-aggregates "^4.0.8"
|
||||
string-width "^2.1.0"
|
||||
strip-ansi "^4.0.0"
|
||||
through "^2.3.6"
|
||||
|
||||
interpret@^1.0.0:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90"
|
||||
@ -3003,6 +3093,22 @@ ionic-angular@3.4.2:
|
||||
version "3.4.2"
|
||||
resolved "https://registry.yarnpkg.com/ionic-angular/-/ionic-angular-3.4.2.tgz#762631f1af78a5ae1c0aa0f4d23b31435142abe1"
|
||||
|
||||
ionic@3.7.0:
|
||||
version "3.7.0"
|
||||
resolved "https://registry.yarnpkg.com/ionic/-/ionic-3.7.0.tgz#a3c32174c6d5455c3bc74b6b9152e0f97dce23c8"
|
||||
dependencies:
|
||||
"@ionic/cli-utils" "1.7.0"
|
||||
chalk "^2.0.0"
|
||||
diff "^3.2.0"
|
||||
minimist "^1.2.0"
|
||||
opn "^5.1.0"
|
||||
os-name "^2.0.1"
|
||||
rimraf "^2.6.1"
|
||||
semver "^5.3.0"
|
||||
ssh-config "^1.0.1"
|
||||
tar "^2.2.1"
|
||||
tslib "^1.7.1"
|
||||
|
||||
ionicons@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-3.0.0.tgz#40b8daf4fd7a31150bd002160f66496e22a98c3c"
|
||||
@ -3182,6 +3288,10 @@ is-utf8@^0.2.0:
|
||||
version "0.2.1"
|
||||
resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72"
|
||||
|
||||
is-wsl@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d"
|
||||
|
||||
is@~0.2.6:
|
||||
version "0.2.7"
|
||||
resolved "https://registry.yarnpkg.com/is/-/is-0.2.7.tgz#3b34a2c48f359972f35042849193ae7264b63562"
|
||||
@ -3206,6 +3316,10 @@ isexe@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
|
||||
|
||||
isnumeric@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/isnumeric/-/isnumeric-0.2.0.tgz#a2347ba360de19e33d0ffd590fddf7755cbf2e64"
|
||||
|
||||
isobject@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89"
|
||||
@ -4019,7 +4133,7 @@ mute-stream@0.0.7:
|
||||
version "0.0.7"
|
||||
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
|
||||
|
||||
nan@^2.3.0, nan@^2.3.2:
|
||||
nan@^2.3.0, nan@^2.3.2, nan@^2.4.0:
|
||||
version "2.6.2"
|
||||
resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45"
|
||||
|
||||
@ -4307,6 +4421,12 @@ opn@4.0.2, opn@^4.0.0:
|
||||
object-assign "^4.0.1"
|
||||
pinkie-promise "^2.0.0"
|
||||
|
||||
opn@^5.1.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519"
|
||||
dependencies:
|
||||
is-wsl "^1.1.0"
|
||||
|
||||
optimist@^0.6.1, optimist@~0.6.0:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
|
||||
@ -4390,6 +4510,20 @@ parse-asn1@^5.0.0:
|
||||
evp_bytestokey "^1.0.0"
|
||||
pbkdf2 "^3.0.3"
|
||||
|
||||
parse-css-font@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/parse-css-font/-/parse-css-font-2.0.2.tgz#7b60b060705a25a9b90b7f0ed493e5823248a652"
|
||||
dependencies:
|
||||
css-font-size-keywords "^1.0.0"
|
||||
css-font-stretch-keywords "^1.0.1"
|
||||
css-font-style-keywords "^1.0.1"
|
||||
css-font-weight-keywords "^1.0.0"
|
||||
css-global-keywords "^1.0.1"
|
||||
css-list-helpers "^1.0.1"
|
||||
css-system-font-keywords "^1.0.0"
|
||||
tcomb "^2.5.0"
|
||||
unquote "^1.1.0"
|
||||
|
||||
parse-glob@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c"
|
||||
@ -4912,6 +5046,12 @@ qjobs@^1.1.4:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73"
|
||||
|
||||
qrious@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/qrious/-/qrious-2.3.0.tgz#ca7ce68a82099a67a90e4979f4b1cdf51ef32475"
|
||||
optionalDependencies:
|
||||
canvas "^1.6.5"
|
||||
|
||||
qs@6.2.0:
|
||||
version "6.2.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b"
|
||||
@ -5399,6 +5539,10 @@ sax@0.6.x:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9"
|
||||
|
||||
sax@1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.4.tgz#74b6d33c9ae1e001510f179a91168588f1aedaa9"
|
||||
|
||||
sax@>=0.6.0, sax@~1.2.1:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
|
||||
@ -5449,6 +5593,10 @@ selenium-webdriver@^2.53.2:
|
||||
version "5.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f"
|
||||
|
||||
semver@^5.4.1:
|
||||
version "5.4.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e"
|
||||
|
||||
semver@~2.3.1:
|
||||
version "2.3.2"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52"
|
||||
@ -5590,9 +5738,11 @@ slash@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||
|
||||
slice-ansi@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35"
|
||||
slice-ansi@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d"
|
||||
dependencies:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
|
||||
sntp@1.x.x:
|
||||
version "1.0.9"
|
||||
@ -5761,6 +5911,10 @@ sprintf-js@~1.0.2:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c"
|
||||
|
||||
ssh-config@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ssh-config/-/ssh-config-1.0.1.tgz#38742116dced7d45f5362ca86af77130ccbebc8b"
|
||||
|
||||
sshpk@^1.7.0:
|
||||
version "1.13.1"
|
||||
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3"
|
||||
@ -5829,6 +5983,13 @@ string-width@^2.0.0:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string-width@^2.1.0, string-width@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||
dependencies:
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
string_decoder@0.10, string_decoder@^0.10.25, string_decoder@~0.10.x:
|
||||
version "0.10.31"
|
||||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
@ -5988,6 +6149,10 @@ tar@^2.0.0, tar@^2.2.1:
|
||||
fstream "^1.0.2"
|
||||
inherits "2"
|
||||
|
||||
tcomb@^2.5.0:
|
||||
version "2.7.0"
|
||||
resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-2.7.0.tgz#10d62958041669a5d53567b9a4ee8cde22b1c2b0"
|
||||
|
||||
temp-write@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-2.1.0.tgz#59890918e0ef09d548aaa342f4bd3409d8404e96"
|
||||
@ -6283,10 +6448,21 @@ uniqs@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02"
|
||||
|
||||
units-css@^0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/units-css/-/units-css-0.4.0.tgz#d6228653a51983d7c16ff28f8b9dc3b1ffed3a07"
|
||||
dependencies:
|
||||
isnumeric "^0.2.0"
|
||||
viewport-dimensions "^0.2.0"
|
||||
|
||||
unpipe@1.0.0, unpipe@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
|
||||
|
||||
unquote@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.0.tgz#98e1fc608b6b854c75afb1b95afc099ba69d942f"
|
||||
|
||||
unreachable-branch-transform@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz#d99cc4c6e746d264928845b611db54b0f3474caa"
|
||||
@ -6399,6 +6575,10 @@ verror@1.3.6:
|
||||
dependencies:
|
||||
extsprintf "1.0.2"
|
||||
|
||||
viewport-dimensions@^0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz#de740747db5387fd1725f5175e91bac76afdf36c"
|
||||
|
||||
vlq@^0.2.1:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1"
|
||||
@ -6622,13 +6802,20 @@ wordwrap@~0.0.2:
|
||||
version "0.0.3"
|
||||
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107"
|
||||
|
||||
wrap-ansi@^2.0.0, wrap-ansi@^2.1.0:
|
||||
wrap-ansi@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
|
||||
dependencies:
|
||||
string-width "^1.0.1"
|
||||
strip-ansi "^3.0.1"
|
||||
|
||||
wrap-ansi@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba"
|
||||
dependencies:
|
||||
string-width "^2.1.1"
|
||||
strip-ansi "^4.0.0"
|
||||
|
||||
wrappy@1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
|
||||
@ -6787,7 +6974,7 @@ yn@^1.2.0:
|
||||
dependencies:
|
||||
object-assign "^4.1.1"
|
||||
|
||||
zip-stream@^1.1.0:
|
||||
zip-stream@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04"
|
||||
dependencies:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user