Merge remote-tracking branch 'upstream/next' into next-merge
This commit is contained in:
commit
e3d6ef0039
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,3 +1,4 @@
|
||||
node_modules
|
||||
package-lock.json
|
||||
*.log
|
||||
*.log
|
||||
.DS_Store
|
||||
|
||||
@ -7,17 +7,13 @@ describe('InsightApp', () => {
|
||||
});
|
||||
|
||||
it('should have a title', () => {
|
||||
expect(browser.getTitle()).toEqual('Blocks');
|
||||
expect(browser.getTitle()).toEqual('Home');
|
||||
});
|
||||
|
||||
it('should have {nav}', () => {
|
||||
expect(element(by.css('ion-navbar')).isPresent()).toEqual(true);
|
||||
});
|
||||
|
||||
it('should have correct nav text for Home', () => {
|
||||
expect(element(by.css('ion-navbar:first-child')).getText()).toContain('Blocks');
|
||||
});
|
||||
|
||||
it('has a menu button that displays the left menu', () => {
|
||||
element(by.css('.bar-button-menutoggle')).click()
|
||||
.then(() => {
|
||||
@ -26,11 +22,11 @@ describe('InsightApp', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('the left menu has a link with title Blocks', () => {
|
||||
it('the left menu has a link with title Home', () => {
|
||||
element(by.css('.bar-button-menutoggle')).click()
|
||||
.then(() => {
|
||||
browser.driver.sleep(2000); // wait for the animation
|
||||
expect(element.all(by.css('ion-label')).first().getText()).toEqual('Blocks');
|
||||
expect(element.all(by.css('ion-label')).first().getText()).toEqual('Home');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -10,7 +10,7 @@ describe('BroadcastTxPage', () => {
|
||||
element(by.css('.bar-button-menutoggle')).click().then(() => {
|
||||
browser.driver.sleep(2000); // wait for the animation
|
||||
element.all(by.className('input-wrapper')).then((items) => {
|
||||
items[1].click();
|
||||
items[2].click();
|
||||
browser.driver.sleep(2000); // wait for the animation
|
||||
let theElem = element.all(by.css('ion-label')).first;
|
||||
console.log(theElem);
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
{
|
||||
"name": "insight-ui",
|
||||
"app_id": "",
|
||||
"type": "ionic-angular"
|
||||
"type": "ionic-angular",
|
||||
"integrations": {
|
||||
"cordova": {}
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"@ionic-native/splash-screen": "3.10.2",
|
||||
"@ionic-native/status-bar": "3.10.2",
|
||||
"@ionic/storage": "2.0.1",
|
||||
"angular2-moment": "^1.6.0",
|
||||
"angular2-qrcode": "^2.0.1",
|
||||
"ionic-angular": "3.4.2",
|
||||
"ionicons": "3.0.0",
|
||||
@ -42,7 +43,7 @@
|
||||
"@types/jasmine": "2.5.41",
|
||||
"@types/node": "7.0.4",
|
||||
"codecov": "2.2.0",
|
||||
"ionic": "3.7.0",
|
||||
"ionic": "3.9.1",
|
||||
"jasmine-core": "2.5.2",
|
||||
"jasmine-spec-reporter": "3.2.0",
|
||||
"karma": "1.4.1",
|
||||
|
||||
@ -3,6 +3,7 @@ import { Platform, MenuController, Nav } from 'ionic-angular';
|
||||
import { StatusBar } from '@ionic-native/status-bar';
|
||||
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
import {
|
||||
HomePage,
|
||||
BlocksPage,
|
||||
BroadcastTxPage,
|
||||
NodeStatusPage,
|
||||
@ -31,11 +32,12 @@ export class InsightApp {
|
||||
this.splash = splash;
|
||||
this.status = status;
|
||||
|
||||
this.rootPage = BlocksPage;
|
||||
this.rootPage = HomePage;
|
||||
this.initializeApp();
|
||||
|
||||
// set our app's pages
|
||||
this.pages = [
|
||||
{ title: 'Home', component: HomePage },
|
||||
{ title: 'Blocks', component: BlocksPage },
|
||||
{ title: 'Broadcast Transaction', component: BroadcastTxPage },
|
||||
{ title: 'Verify Signed Message', component: VerifyMessagePage },
|
||||
|
||||
@ -5,9 +5,11 @@ import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
|
||||
import { StatusBar } from '@ionic-native/status-bar';
|
||||
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
import { InsightApp } from './app.component';
|
||||
import { PagesModule, BlocksPage, BroadcastTxPage, NodeStatusPage, VerifyMessagePage } from '../pages';
|
||||
import { PagesModule, HomePage, BlocksPage, BroadcastTxPage, NodeStatusPage, VerifyMessagePage } from '../pages';
|
||||
import { BlocksService, StorageService } from '../services';
|
||||
import { ApiProvider } from '../providers/api/api';
|
||||
import { CurrencyProvider } from '../providers/currency/currency';
|
||||
import { BlocksProvider } from '../providers/blocks/blocks';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@ -22,6 +24,7 @@ import { ApiProvider } from '../providers/api/api';
|
||||
bootstrap: [IonicApp],
|
||||
entryComponents: [
|
||||
InsightApp,
|
||||
HomePage,
|
||||
BlocksPage,
|
||||
BroadcastTxPage,
|
||||
NodeStatusPage,
|
||||
@ -33,7 +36,9 @@ import { ApiProvider } from '../providers/api/api';
|
||||
StorageService,
|
||||
BlocksService,
|
||||
{provide: ErrorHandler, useClass: IonicErrorHandler},
|
||||
ApiProvider
|
||||
ApiProvider,
|
||||
CurrencyProvider,
|
||||
BlocksProvider
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
@ -15,6 +15,20 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.summary ion-label {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.summary ion-item {
|
||||
color: #999;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
body {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
// Shared Sass variables, which can be used to adjust Ionic's
|
||||
// default Sass variables, belong in "theme/variables.scss".
|
||||
//
|
||||
|
||||
BIN
app/src/assets/img/angularjs.png
Normal file
BIN
app/src/assets/img/angularjs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
29
app/src/assets/img/bitcore.svg
Normal file
29
app/src/assets/img/bitcore.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 15 KiB |
BIN
app/src/assets/img/leveldb.png
Normal file
BIN
app/src/assets/img/leveldb.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
app/src/assets/img/nodejs.png
Normal file
BIN
app/src/assets/img/nodejs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.2 KiB |
@ -4,9 +4,12 @@
|
||||
</button>
|
||||
<ion-title>{{title}}</ion-title>
|
||||
<ion-buttons end>
|
||||
<button ion-button icon-only>
|
||||
<button ion-button (click)="changeCurrency()">
|
||||
<ion-icon name="logo-bitcoin" *ngIf="currency.currencySymbol !== 'USD'"></ion-icon><ion-icon name="logo-usd" *ngIf="currency.currencySymbol === 'USD'"></ion-icon> {{ currency.currencySymbol }}
|
||||
</button>
|
||||
<button ion-button icon-only (click)="toggleSearch()">
|
||||
<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>
|
||||
<ion-searchbar [hidden]="!showSearch" (ionInput)="search($event)" placeholder="{{ 'Search for block, transaction or address' }}" [(ngModel)]="q" [debounce]="1500"></ion-searchbar>
|
||||
|
||||
@ -4,10 +4,10 @@ import { HeadNavComponent } from './head-nav';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
HeadNavComponent,
|
||||
HeadNavComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule,
|
||||
IonicModule
|
||||
],
|
||||
exports: [
|
||||
HeadNavComponent
|
||||
|
||||
@ -3,6 +3,8 @@ import { Input } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
import { CurrencyProvider } from '../../providers/currency/currency';
|
||||
import { ActionSheetController } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
* Generated class for the HeadNavComponent component.
|
||||
@ -16,24 +18,21 @@ import { ApiProvider } from '../../providers/api/api';
|
||||
})
|
||||
export class HeadNavComponent {
|
||||
|
||||
public showSearch: boolean = false;
|
||||
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;
|
||||
constructor(private navCtrl: NavController, private http: Http, private api: ApiProvider, public currency: CurrencyProvider, public actionSheetCtrl: ActionSheetController) {
|
||||
}
|
||||
|
||||
public search(): void {
|
||||
this.showSearch = false;
|
||||
let apiPrefix: string = this.api.apiPrefix;
|
||||
|
||||
this.http.get(apiPrefix + 'block/' + this.q).subscribe(
|
||||
function (data: any) {
|
||||
function (data: any): void {
|
||||
this.resetSearch();
|
||||
console.log('block', data);
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
@ -43,7 +42,7 @@ export class HeadNavComponent {
|
||||
}.bind(this),
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'tx/' + this.q).subscribe(
|
||||
function (data: any) {
|
||||
function (data: any): void {
|
||||
this.resetSearch();
|
||||
console.log('tx', data);
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
@ -53,7 +52,7 @@ export class HeadNavComponent {
|
||||
}.bind(this),
|
||||
() => {
|
||||
this.http.get(apiPrefix + 'addr/' + this.q).subscribe(
|
||||
function (data: any) {
|
||||
function (data: any): void {
|
||||
this.resetSearch();
|
||||
console.log('addr', data);
|
||||
let parsedData: any = JSON.parse(data._body);
|
||||
@ -96,6 +95,51 @@ export class HeadNavComponent {
|
||||
2000
|
||||
);
|
||||
};
|
||||
|
||||
private resetSearch(): void {
|
||||
this.q = '';
|
||||
this.loading = false;
|
||||
}
|
||||
/* tslint:enable:no-unused-variable */
|
||||
|
||||
public changeCurrency(): void {
|
||||
let actionSheet: any = this.actionSheetCtrl.create({
|
||||
title: 'Change Denomination',
|
||||
buttons: [
|
||||
{
|
||||
text: 'USD',
|
||||
handler: () => {
|
||||
this.currency.setCurrency('USD');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'BTC',
|
||||
handler: () => {
|
||||
this.currency.setCurrency('BTC');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'mBTC',
|
||||
handler: () => {
|
||||
this.currency.setCurrency('mBTC');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'bits',
|
||||
handler: () => {
|
||||
this.currency.setCurrency('bits');
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Cancel',
|
||||
role: 'cancel'
|
||||
}
|
||||
]
|
||||
});
|
||||
actionSheet.present();
|
||||
}
|
||||
|
||||
public toggleSearch(): void {
|
||||
this.showSearch = !this.showSearch;
|
||||
}
|
||||
}
|
||||
|
||||
45
app/src/components/latest-blocks/latest-blocks.html
Normal file
45
app/src/components/latest-blocks/latest-blocks.html
Normal file
@ -0,0 +1,45 @@
|
||||
<!-- Generated template for the LatestBlocksComponent component -->
|
||||
<div>
|
||||
<div *ngIf="loading">
|
||||
<ion-spinner name="crescent"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<ion-grid>
|
||||
|
||||
<ion-row>
|
||||
<ion-col><b>Height</b></ion-col>
|
||||
<ion-col *ngIf="showTimeAs === 'age'"><b>Age</b></ion-col>
|
||||
<ion-col *ngIf="showTimeAs === 'timestamp'"><b>Timestamp</b></ion-col>
|
||||
<ion-col text-right><b>Transactions</b></ion-col>
|
||||
<ion-col hideWhen="portrait"><b>Mined By</b></ion-col>
|
||||
<ion-col text-right><b>Size</b></ion-col>
|
||||
</ion-row>
|
||||
<ion-row *ngFor="let block of getBlocks()">
|
||||
<ion-col>
|
||||
<a (click)="goToBlock(block.hash)">{{block.height}}</a>
|
||||
</ion-col>
|
||||
<ion-col *ngIf="showTimeAs === 'age'">
|
||||
{{ block.time | amFromUnix | amTimeAgo }}
|
||||
</ion-col>
|
||||
<ion-col *ngIf="showTimeAs === 'timestamp'">
|
||||
{{ block.time * 1000 | date:'medium' }}
|
||||
</ion-col>
|
||||
<ion-col text-right>
|
||||
{{block.txlength}}
|
||||
</ion-col>
|
||||
<ion-col hideWhen="portrait">
|
||||
<a *ngIf="block.poolInfo.poolName" href="{{block.poolInfo.url}}">{{block.poolInfo.poolName}}</a>
|
||||
</ion-col>
|
||||
<ion-col text-right>
|
||||
{{ block.size }}
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row *ngIf="showAllBlocksButton">
|
||||
<ion-col text-center>
|
||||
<button ion-button (click)="goToBlocks()">See all blocks</button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</div>
|
||||
</div>
|
||||
18
app/src/components/latest-blocks/latest-blocks.module.ts
Normal file
18
app/src/components/latest-blocks/latest-blocks.module.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { LatestBlocksComponent } from './latest-blocks';
|
||||
import { MomentModule } from 'angular2-moment';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LatestBlocksComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule,
|
||||
MomentModule
|
||||
],
|
||||
exports: [
|
||||
LatestBlocksComponent
|
||||
]
|
||||
})
|
||||
export class LatestBlocksComponentModule {}
|
||||
23
app/src/components/latest-blocks/latest-blocks.scss
Normal file
23
app/src/components/latest-blocks/latest-blocks.scss
Normal file
@ -0,0 +1,23 @@
|
||||
latest-blocks {
|
||||
ion-grid {
|
||||
// border: 2px solid green;
|
||||
margin: 10px 0 20px;
|
||||
|
||||
ion-row {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
ion-row:nth-child(even) {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
ion-row:first-child {
|
||||
background-color: white;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
ion-row:last-child {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
65
app/src/components/latest-blocks/latest-blocks.ts
Normal file
65
app/src/components/latest-blocks/latest-blocks.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { Component, NgZone, Input } from '@angular/core';
|
||||
import { BlocksProvider } from '../../providers/blocks/blocks';
|
||||
import { NavController } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
* Generated class for the LatestBlocksComponent component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'latest-blocks',
|
||||
templateUrl: 'latest-blocks.html'
|
||||
})
|
||||
export class LatestBlocksComponent {
|
||||
|
||||
public loading: boolean = true;
|
||||
public blocks: Array<any> = [];
|
||||
@Input() public numBlocks: number;
|
||||
@Input() public showAllBlocksButton: boolean;
|
||||
@Input() public showTimeAs: string;
|
||||
|
||||
constructor(private blocksProvider: BlocksProvider, private navCtrl: NavController, ngZone: NgZone) {
|
||||
this.loadBlocks();
|
||||
ngZone.runOutsideAngular(() => {
|
||||
setInterval(
|
||||
function (): void {
|
||||
ngZone.run(function (): void {
|
||||
this.loadBlocks.call(this);
|
||||
}.bind(this));
|
||||
}.bind(this),
|
||||
1000 * 30
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private loadBlocks(): void {
|
||||
this.blocksProvider.getBlocks().subscribe(
|
||||
(data) => {
|
||||
this.blocks = JSON.parse(data['_body']).blocks;
|
||||
this.loading = false;
|
||||
},
|
||||
(err) => {
|
||||
console.log('err', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public goToBlock(blockHash: string): void {
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': blockHash
|
||||
});
|
||||
}
|
||||
|
||||
public getBlocks(): Array<any> {
|
||||
/* tslint:disable:no-unused-variable */
|
||||
return this.blocks.filter((block, index) => index < this.numBlocks);
|
||||
/* tslint:enable:no-unused-variable */
|
||||
}
|
||||
|
||||
public goToBlocks(): void {
|
||||
this.navCtrl.push('blocks');
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
<!-- Generated template for the LatestTransactionsComponent component -->
|
||||
<div>
|
||||
{{text}}
|
||||
</div>
|
||||
@ -0,0 +1,16 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { LatestTransactionsComponent } from './latest-transactions';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LatestTransactionsComponent
|
||||
],
|
||||
imports: [
|
||||
IonicModule
|
||||
],
|
||||
exports: [
|
||||
LatestTransactionsComponent
|
||||
]
|
||||
})
|
||||
export class LatestTransactionsComponentModule {}
|
||||
@ -0,0 +1,3 @@
|
||||
latest-transactions {
|
||||
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
import { Component } from '@angular/core';
|
||||
// import { Http } from '@angular/http';
|
||||
// import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/**
|
||||
* Generated class for the LatestTransactionsComponent component.
|
||||
*
|
||||
* See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html
|
||||
* for more info on Angular Components.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'latest-transactions',
|
||||
templateUrl: 'latest-transactions.html'
|
||||
})
|
||||
export class LatestTransactionsComponent {
|
||||
|
||||
private text: string;
|
||||
|
||||
constructor(/*private http: Http, private api: ApiProvider*/) {
|
||||
console.log('Hello LatestTransactionsComponent Component');
|
||||
this.text = 'Hello Latest Transactions';
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
);
|
||||
*/
|
||||
|
||||
/*
|
||||
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;
|
||||
}
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,7 +1,14 @@
|
||||
<ion-grid>
|
||||
<ion-row *ngFor="let tx of transactions.txs">
|
||||
<ion-col col-12>
|
||||
<transaction [tx]="tx"></transaction>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
<div *ngIf="loading">
|
||||
<ion-spinner name="crescent"></ion-spinner>
|
||||
</div>
|
||||
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<ion-grid>
|
||||
<ion-row *ngFor="let tx of transactions.txs">
|
||||
<ion-col col-12>
|
||||
<transaction [tx]="tx"></transaction>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
</div>
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
</ion-row>
|
||||
|
||||
<ion-row>
|
||||
<ion-col col-5>
|
||||
<ion-col col-12 col-md-5>
|
||||
|
||||
<ion-list [hidden]="!tx.isCoinBase">
|
||||
<ion-item>
|
||||
@ -27,42 +27,56 @@
|
||||
</ion-list>
|
||||
|
||||
<ion-list [hidden]="tx.isCoinBase">
|
||||
<ion-item *ngFor="let vin of tx.vin">
|
||||
<ion-item *ngFor="let vin of aggregateItems(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 class="ellipsis">
|
||||
<p><a (click)="goToAddress(vin.addr)">{{ vin.addr }}</a></p>
|
||||
</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>
|
||||
<p *ngIf="vin.confirmations"><b>Confirmations</b> {{vin.confirmations}}</p>
|
||||
<p><b>scriptSig</b></p>
|
||||
<div *ngFor="let item of vin.items">
|
||||
<div *ngIf="item.scriptSig">
|
||||
<div *ngFor="let scriptSig of item.scriptSig.asm | split:' '">
|
||||
<div class="ellipsis">
|
||||
<p>{{ scriptSig }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div item-end>
|
||||
{{ vout.value + ' BTC' }}
|
||||
{{ currency.getConversion(vin.value) }}
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
</ion-col>
|
||||
|
||||
<ion-col col-12 col-md-1 text-center>
|
||||
<ion-icon name="arrow-forward"></ion-icon>
|
||||
</ion-col>
|
||||
|
||||
<ion-col col-12 col-md-6>
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let vout of tx.vout">
|
||||
<div>
|
||||
<div class="ellipsis">
|
||||
<p><a (click)="goToAddress(getAddress(vout))">{{ getAddress(vout) }}</a></p>
|
||||
</div>
|
||||
<div [hidden]="!expanded">
|
||||
<p><b>Type</b> {{vout.scriptPubKey.type}}</p>
|
||||
<p><b>scriptPubKey</b></p>
|
||||
<div class="ellipsis">
|
||||
<p>{{vout.scriptPubKey.asm}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div item-end>
|
||||
{{ currency.getConversion(vout.value) }}
|
||||
<span [hidden]="!vout.spentTxId">(S)</span>
|
||||
<span [hidden]="vout.spentTxId">(U)</span>
|
||||
</div>
|
||||
@ -72,12 +86,14 @@
|
||||
</ion-row>
|
||||
|
||||
<ion-row>
|
||||
<ion-col col-6>
|
||||
<span [hidden]="tx.isCoinBase">Fee {{ tx.fees + ' BTC' }}</span>
|
||||
<ion-col col-3>
|
||||
<span [hidden]="tx.isCoinBase">Fee {{ currency.getConversion(tx.fees) }}</span>
|
||||
</ion-col>
|
||||
<ion-col col-6 text-right>
|
||||
<ion-col col-6 text-center>
|
||||
{{ tx.confirmations }} Confirmations
|
||||
<span class="">{{ tx.valueOut + ' BTC' }}</span>
|
||||
</ion-col>
|
||||
<ion-col col-3 text-right>
|
||||
<span class="">{{ currency.getConversion(tx.valueOut) }}</span>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
transaction {
|
||||
// TODO Customize the grid to have 13 columns so that we have 6-col inputs, 6-col outputs, 1 col arrow
|
||||
// See http://ionicframework.com/docs/api/components/grid/Grid/#customizing-the-grid
|
||||
|
||||
ion-grid {
|
||||
background-color: #F4F4F4;
|
||||
border: 1px solid #eee;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { Input } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CurrencyProvider } from '../../providers/currency/currency';
|
||||
|
||||
/**
|
||||
* Generated class for the TransactionComponent component.
|
||||
@ -14,10 +15,12 @@ import { NavController } from 'ionic-angular';
|
||||
})
|
||||
export class TransactionComponent {
|
||||
|
||||
private COIN: number = 100000000;
|
||||
|
||||
public expanded: boolean = false;
|
||||
@Input() public tx: any = {};
|
||||
|
||||
constructor(private navCtrl: NavController) {
|
||||
constructor(private navCtrl: NavController, public currency: CurrencyProvider) {
|
||||
}
|
||||
|
||||
public getAddress(vout: any): string {
|
||||
@ -43,4 +46,70 @@ export class TransactionComponent {
|
||||
public toggleExpanded(): void {
|
||||
this.expanded = !this.expanded;
|
||||
}
|
||||
|
||||
public aggregateItems(items: Array<any>): Array<any> {
|
||||
if (!items) return [];
|
||||
|
||||
let l: number = items.length;
|
||||
|
||||
let ret: Array<any> = [];
|
||||
let tmp: any = {};
|
||||
let u: number = 0;
|
||||
|
||||
for (let i: number = 0; i < l; i++) {
|
||||
|
||||
let notAddr: boolean = false;
|
||||
// non standard input
|
||||
if (items[i].scriptSig && !items[i].addr) {
|
||||
items[i].addr = 'Unparsed address [' + u++ + ']';
|
||||
items[i].notAddr = true;
|
||||
notAddr = true;
|
||||
}
|
||||
|
||||
// non standard output
|
||||
if (items[i].scriptPubKey && !items[i].scriptPubKey.addresses) {
|
||||
items[i].scriptPubKey.addresses = ['Unparsed address [' + u++ + ']'];
|
||||
items[i].notAddr = true;
|
||||
notAddr = true;
|
||||
}
|
||||
|
||||
// multiple addr at output
|
||||
if (items[i].scriptPubKey && items[i].scriptPubKey.addresses.length > 1) {
|
||||
items[i].addr = items[i].scriptPubKey.addresses.join(',');
|
||||
ret.push(items[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
let addr: string = items[i].addr || (items[i].scriptPubKey && items[i].scriptPubKey.addresses[0]);
|
||||
|
||||
if (!tmp[addr]) {
|
||||
tmp[addr] = {};
|
||||
tmp[addr].valueSat = 0;
|
||||
tmp[addr].count = 0;
|
||||
tmp[addr].addr = addr;
|
||||
tmp[addr].items = [];
|
||||
}
|
||||
tmp[addr].isSpent = items[i].spentTxId;
|
||||
|
||||
tmp[addr].doubleSpentTxID = tmp[addr].doubleSpentTxID || items[i].doubleSpentTxID;
|
||||
tmp[addr].doubleSpentIndex = tmp[addr].doubleSpentIndex || items[i].doubleSpentIndex;
|
||||
tmp[addr].dbError = tmp[addr].dbError || items[i].dbError;
|
||||
tmp[addr].valueSat += Math.round(items[i].value * this.COIN);
|
||||
tmp[addr].items.push(items[i]);
|
||||
tmp[addr].notAddr = notAddr;
|
||||
|
||||
if (items[i].unconfirmedInput)
|
||||
tmp[addr].unconfirmedInput = true;
|
||||
|
||||
tmp[addr].count++;
|
||||
}
|
||||
|
||||
for (let v in tmp) {
|
||||
let obj: any = tmp[v];
|
||||
obj.value = obj.value || parseInt(obj.valueSat) / this.COIN;
|
||||
ret.push(obj);
|
||||
}
|
||||
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
@ -3,45 +3,51 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Address</h1>
|
||||
<p class="ellipsis"><b>Address</b> {{ address.addrStr }}</p>
|
||||
<p>{{ address.balance }} BTC</p>
|
||||
<div *ngIf="loading">
|
||||
<ion-spinner name="crescent"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<h2>Summary</h2>
|
||||
<div *ngIf="!loading">
|
||||
<h1>Address</h1>
|
||||
<p class="ellipsis"><b>Address</b> {{ address.addrStr }}</p>
|
||||
<p>{{ currency.getConversion(address.balance) }}</p>
|
||||
|
||||
<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>
|
||||
<h2>Summary</h2>
|
||||
|
||||
<p text-center>
|
||||
<qr-code [value]="address.addrStr" [size]="160"></qr-code>
|
||||
<p>
|
||||
<ion-list class="summary">
|
||||
<ion-item>
|
||||
Total Received
|
||||
<span item-end>
|
||||
{{ currency.getConversion(address.totalReceived) }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Total Sent
|
||||
<span item-end>
|
||||
{{ currency.getConversion(address.totalSent) }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Final Balance
|
||||
<span item-end>
|
||||
{{ currency.getConversion(address.balance) }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
No. Transactions
|
||||
<span item-end>
|
||||
{{ address.txApperances }}
|
||||
</span>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
||||
<h2>Transactions</h2>
|
||||
<p text-center>
|
||||
<qr-code [value]="address.addrStr" [size]="160"></qr-code>
|
||||
<p>
|
||||
|
||||
<transaction-list [queryType]="'address'" [queryValue]="addrStr"></transaction-list>
|
||||
<h2>Transactions</h2>
|
||||
|
||||
<transaction-list [queryType]="'address'" [queryValue]="addrStr"></transaction-list>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@ -2,6 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
import { CurrencyProvider } from '../../providers/currency/currency';
|
||||
|
||||
/**
|
||||
* Generated class for the AddressPage page.
|
||||
@ -23,7 +24,7 @@ export class AddressPage {
|
||||
private addrStr: string;
|
||||
public address: any = {};
|
||||
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, private api: ApiProvider) {
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, private api: ApiProvider, public currency: CurrencyProvider) {
|
||||
this.addrStr = navParams.get('addrStr');
|
||||
}
|
||||
|
||||
|
||||
@ -3,96 +3,102 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Block #{{ block.height }}</h1>
|
||||
<p class="ellipsis"><b>BlockHash</b> {{ block.hash }}</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">
|
||||
<ion-spinner name="crescent"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<h2>Transactions</h2>
|
||||
<h1>Block #{{ block.height }}</h1>
|
||||
<p class="ellipsis"><b>BlockHash</b> {{ block.hash }}</p>
|
||||
|
||||
<transaction-list [queryType]="'block'" [queryValue]="block.hash"></transaction-list>
|
||||
<h2>Summary</h2>
|
||||
|
||||
<ion-list *ngIf="!loading" class="summary">
|
||||
<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>
|
||||
{{ currency.getConversion(block.reward) }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Timestamp
|
||||
<span item-end>
|
||||
{{ block.time * 1000 | date:'medium' }}
|
||||
</span>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
Mined by
|
||||
<span item-end *ngIf="block.poolInfo">
|
||||
<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>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@ -2,6 +2,7 @@ import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
import { CurrencyProvider } from '../../providers/currency/currency';
|
||||
|
||||
/**
|
||||
* Generated class for the BlockDetailPage page.
|
||||
@ -25,9 +26,11 @@ export class BlockDetailPage {
|
||||
tx: []
|
||||
};
|
||||
|
||||
constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams, private api: ApiProvider) {
|
||||
constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams, private api: ApiProvider, public currency: CurrencyProvider) {
|
||||
this.blockHash = navParams.get('blockHash');
|
||||
}
|
||||
|
||||
public ionViewDidLoad(): void {
|
||||
this.http.get(this.api.apiPrefix + 'block/' + this.blockHash).subscribe(
|
||||
(data) => {
|
||||
this.block = JSON.parse(data['_body']);
|
||||
@ -40,10 +43,6 @@ export class BlockDetailPage {
|
||||
);
|
||||
}
|
||||
|
||||
public ionViewWillLeave(): void {
|
||||
this.loading = true;
|
||||
}
|
||||
|
||||
public goToPreviousBlock(): void {
|
||||
this.navCtrl.push('block-detail', {
|
||||
'blockHash': this.block.previousblockhash
|
||||
|
||||
14
app/src/pages/blocks/blocks.html
Normal file
14
app/src/pages/blocks/blocks.html
Normal file
@ -0,0 +1,14 @@
|
||||
<ion-header>
|
||||
<head-nav [title]="'Blocks'"></head-nav>
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<div *ngIf="loading">
|
||||
<ion-spinner name="crescent"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!loading">
|
||||
<h1>Blocks</h1>
|
||||
<latest-blocks [numBlocks]="100" [showTimeAs]="'timestamp'" [showAllBlocksButton]="false"></latest-blocks>
|
||||
</div>
|
||||
</ion-content>
|
||||
20
app/src/pages/blocks/blocks.module.ts
Normal file
20
app/src/pages/blocks/blocks.module.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { BlocksPage } from './blocks';
|
||||
import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module';
|
||||
import { LatestBlocksComponentModule } from '../../components/latest-blocks/latest-blocks.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
BlocksPage
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild(BlocksPage),
|
||||
HeadNavComponentModule,
|
||||
LatestBlocksComponentModule
|
||||
],
|
||||
exports: [
|
||||
BlocksPage
|
||||
]
|
||||
})
|
||||
export class BlocksPageModule {}
|
||||
23
app/src/pages/blocks/blocks.scss
Normal file
23
app/src/pages/blocks/blocks.scss
Normal file
@ -0,0 +1,23 @@
|
||||
page-blocks {
|
||||
ion-grid {
|
||||
// border: 2px solid green;
|
||||
margin: 10px 0 20px;
|
||||
|
||||
ion-row {
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
|
||||
ion-row:nth-child(even) {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
ion-row:first-child {
|
||||
background-color: white;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
ion-row:last-child {
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
37
app/src/pages/blocks/blocks.ts
Normal file
37
app/src/pages/blocks/blocks.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { BlocksProvider } from '../../providers/blocks/blocks';
|
||||
|
||||
/**
|
||||
* Generated class for the BlocksPage page.
|
||||
*
|
||||
* See http://ionicframework.com/docs/components/#navigation for more info
|
||||
* on Ionic pages and navigation.
|
||||
*/
|
||||
@IonicPage({
|
||||
name: 'blocks',
|
||||
segment: 'blocks/'
|
||||
})
|
||||
@Component({
|
||||
selector: 'page-blocks',
|
||||
templateUrl: 'blocks.html'
|
||||
})
|
||||
export class BlocksPage {
|
||||
|
||||
public loading: boolean = true;
|
||||
public blocks: Array<any> = [];
|
||||
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams, private blocksProvider: BlocksProvider) {
|
||||
this.blocksProvider.getBlocks().subscribe(
|
||||
(data) => {
|
||||
this.blocks = JSON.parse(data['_body']).blocks;
|
||||
console.log('this.blocks', this.blocks);
|
||||
this.loading = false;
|
||||
},
|
||||
(err) => {
|
||||
console.log('err', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -4,16 +4,20 @@ import { Observable } from 'rxjs';
|
||||
import { Block } from '../../models';
|
||||
import { BlocksService } from '../../services';
|
||||
|
||||
/**
|
||||
* @deprecated Use BlocksPage from ../blocks/blocks
|
||||
*/
|
||||
@Component({
|
||||
templateUrl: './blocksPage.html'
|
||||
})
|
||||
|
||||
export class BlocksPage {
|
||||
|
||||
public title: string;
|
||||
public blocks: Observable<Block[]>;
|
||||
|
||||
constructor(private navCtrl: NavController, private blocksService: BlocksService) {
|
||||
// TODO Put loading spinner on page
|
||||
|
||||
this.title = 'Blocks';
|
||||
this.blocks = blocksService.latestBlocks;
|
||||
this.blocks.subscribe((blocks) => {
|
||||
|
||||
39
app/src/pages/home/home.html
Normal file
39
app/src/pages/home/home.html
Normal file
@ -0,0 +1,39 @@
|
||||
<!--
|
||||
Generated template for the HomePage page.
|
||||
|
||||
See http://ionicframework.com/docs/components/#navigation for more info on
|
||||
Ionic pages and navigation.
|
||||
-->
|
||||
<ion-header>
|
||||
<head-nav [title]="'Home'"></head-nav>
|
||||
</ion-header>
|
||||
|
||||
|
||||
<ion-content padding>
|
||||
|
||||
<div>
|
||||
<h1>Latest Blocks</h1>
|
||||
<latest-blocks [numBlocks]="6" [showTimeAs]="'age'" [showAllBlocksButton]="true"></latest-blocks>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h1>Latest Transactions</h1>
|
||||
<latest-transactions></latest-transactions>
|
||||
</div>
|
||||
|
||||
<div class="about">
|
||||
<h2>About</h2>
|
||||
<p><strong>insight</strong> is an <a href="https://insight.is/"
|
||||
target="_blank">open-source Bitcoin blockchain explorer</a> with complete REST and websocket APIs that can be used for writing web wallets and other apps that need more advanced blockchain queries than provided by bitcoind RPC. Check out the <a href="https://github.com/bitpay/insight-ui" target="_blank">source code</a>.</p>
|
||||
<p><strong>insight</strong> is still in development, so be sure to report any bugs and provide feedback for improvement at our <a href="https://github.com/bitpay/insight-ui/issues" target="_blank">github issue tracker</a>.</p>
|
||||
<div id="powered" class="row">
|
||||
<div class="powered-text">
|
||||
<small class="text-muted">Powered by</small>
|
||||
</div>
|
||||
<a href="http://bitcore.io" target="_blank" class="bitcore" title="Bitcore"></a>
|
||||
<a href="http://angularjs.org" target="_blank" class="angularjs" title="AngularJS"></a>
|
||||
<a href="https://code.google.com/p/leveldb/" target="_blank" class="leveldb" title="LevelDB"></a>
|
||||
<a href="http://nodejs.org" target="_blank" class="nodejs" title="NodeJs"></a>
|
||||
</div>
|
||||
</div>
|
||||
</ion-content>
|
||||
20
app/src/pages/home/home.module.ts
Normal file
20
app/src/pages/home/home.module.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicPageModule } from 'ionic-angular';
|
||||
import { HomePage } from './home';
|
||||
import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module';
|
||||
import { LatestTransactionsComponentModule } from '../../components/latest-transactions/latest-transactions.module';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
HomePage
|
||||
],
|
||||
imports: [
|
||||
IonicPageModule.forChild(HomePage),
|
||||
HeadNavComponentModule,
|
||||
LatestTransactionsComponentModule
|
||||
],
|
||||
exports: [
|
||||
HomePage
|
||||
]
|
||||
})
|
||||
export class HomePageModule {}
|
||||
50
app/src/pages/home/home.scss
Normal file
50
app/src/pages/home/home.scss
Normal file
@ -0,0 +1,50 @@
|
||||
page-home {
|
||||
.about {
|
||||
background-color: #F4F4F4;
|
||||
border: 1px solid #eee;
|
||||
border-radius: 5px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
#powered .powered-text {
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 30px auto 0;
|
||||
text-align: center;
|
||||
width: 90%;
|
||||
}
|
||||
#powered .powered-text small {
|
||||
background-color: #f4f4f4;
|
||||
padding: 4px;
|
||||
position: relative;
|
||||
top: -12px;
|
||||
}
|
||||
|
||||
#powered a {
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
height: 45px;
|
||||
}
|
||||
#powered a.bitcore {
|
||||
background-image: url('../../assets/img/bitcore.svg');
|
||||
background-size: 80px;
|
||||
width: 30%;
|
||||
}
|
||||
#powered a.nodejs {
|
||||
background-image: url('../../assets/img/nodejs.png');
|
||||
background-size: 80px;
|
||||
width: 30%;
|
||||
}
|
||||
#powered a.angularjs {
|
||||
background-image: url('../../assets/img/angularjs.png');
|
||||
background-size: 50px;
|
||||
width: 20%;
|
||||
}
|
||||
#powered a.leveldb {
|
||||
background-image: url('../../assets/img/leveldb.png');
|
||||
background-size: 50px;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
}
|
||||
27
app/src/pages/home/home.ts
Normal file
27
app/src/pages/home/home.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
|
||||
/**
|
||||
* Generated class for the HomePage page.
|
||||
*
|
||||
* See http://ionicframework.com/docs/components/#navigation for more info
|
||||
* on Ionic pages and navigation.
|
||||
*/
|
||||
@IonicPage({
|
||||
name: 'home',
|
||||
segment: 'home'
|
||||
})
|
||||
@Component({
|
||||
selector: 'page-home',
|
||||
templateUrl: 'home.html'
|
||||
})
|
||||
export class HomePage {
|
||||
|
||||
constructor(public navCtrl: NavController, public navParams: NavParams) {
|
||||
}
|
||||
|
||||
public ionViewDidLoad(): void {
|
||||
console.log('ionViewDidLoad HomePage');
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
export * from './blocksPage/blocksPage';
|
||||
export * from './broadcastTxPage/broadcastTxPage';
|
||||
export * from './nodeStatusPage/nodeStatusPage';
|
||||
export * from './verifyMessagePage/verifyMessagePage';
|
||||
export * from './home/home';
|
||||
export * from './blocks/blocks';
|
||||
export * from './pages.module';
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { ComponentsModule } from '../components';
|
||||
import { BlocksPageModule } from '../pages/blocks/blocks.module';
|
||||
import { HeadNavComponentModule } from '../components/head-nav/head-nav.module';
|
||||
import { LatestTransactionsComponentModule } from '../components/latest-transactions/latest-transactions.module';
|
||||
import { LatestBlocksComponentModule } from '../components/latest-blocks/latest-blocks.module';
|
||||
import {
|
||||
BlocksPage,
|
||||
HomePage,
|
||||
BroadcastTxPage,
|
||||
NodeStatusPage,
|
||||
VerifyMessagePage
|
||||
@ -11,12 +14,19 @@ import {
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
BlocksPage,
|
||||
HomePage,
|
||||
BroadcastTxPage,
|
||||
NodeStatusPage,
|
||||
VerifyMessagePage
|
||||
],
|
||||
imports: [ IonicModule, ComponentsModule, HeadNavComponentModule ],
|
||||
imports: [
|
||||
IonicModule,
|
||||
ComponentsModule,
|
||||
BlocksPageModule,
|
||||
HeadNavComponentModule,
|
||||
LatestTransactionsComponentModule,
|
||||
LatestBlocksComponentModule
|
||||
],
|
||||
exports: [
|
||||
// CustomComponent,
|
||||
],
|
||||
|
||||
@ -3,40 +3,46 @@
|
||||
</ion-header>
|
||||
|
||||
<ion-content padding>
|
||||
<h1>Transaction</h1>
|
||||
<p class="ellipsis"><b>Transaction</b> {{ tx.txid }}</p>
|
||||
<div *ngIf="loading">
|
||||
<ion-spinner name="crescent"></ion-spinner>
|
||||
</div>
|
||||
|
||||
<h2>Summary</h2>
|
||||
<div *ngIf="!loading">
|
||||
<h1>Transaction</h1>
|
||||
<p class="ellipsis"><b>Transaction</b> {{ tx.txid }}</p>
|
||||
|
||||
<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>Summary</h2>
|
||||
|
||||
<h2>Details</h2>
|
||||
<ion-list class="summary">
|
||||
<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>
|
||||
|
||||
<transaction [tx]="tx"></transaction>
|
||||
<h2>Details</h2>
|
||||
|
||||
<transaction [tx]="tx"></transaction>
|
||||
</div>
|
||||
|
||||
</ion-content>
|
||||
|
||||
@ -15,7 +15,6 @@ export class SplitPipe implements PipeTransform {
|
||||
*/
|
||||
public transform(value: string, delimiter: string): Array<string> {
|
||||
let array: Array<string> = value.split(delimiter);
|
||||
console.log('split is', array);
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@ import 'rxjs/add/operator/map';
|
||||
@Injectable()
|
||||
export class ApiProvider {
|
||||
|
||||
public apiPrefix: string = 'http://localhost:3001/insight-api/';
|
||||
public apiPrefix: string = 'https://insight.bitpay.com/api/';
|
||||
|
||||
constructor(public http: Http) {
|
||||
}
|
||||
|
||||
23
app/src/providers/blocks/blocks.ts
Normal file
23
app/src/providers/blocks/blocks.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import 'rxjs/add/operator/map';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
|
||||
/*
|
||||
Generated class for the BlocksProvider provider.
|
||||
|
||||
See https://angular.io/docs/ts/latest/guide/dependency-injection.html
|
||||
for more info on providers and Angular DI.
|
||||
*/
|
||||
@Injectable()
|
||||
export class BlocksProvider {
|
||||
|
||||
constructor(public http: Http, private api: ApiProvider) {
|
||||
console.log('Hello BlocksProvider Provider');
|
||||
}
|
||||
|
||||
public getBlocks(): any {
|
||||
return this.http.get(this.api.apiPrefix + 'blocks');
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,9 +2,10 @@
|
||||
import { TestBed, ComponentFixture, inject } from '@angular/core/testing';
|
||||
import { HttpModule } from '@angular/http';
|
||||
import { CurrencyProvider } from './currency';
|
||||
import { ApiProvider } from '../api/api';
|
||||
|
||||
describe('CurrencyProvider', () => {
|
||||
let currency;
|
||||
let currency: CurrencyProvider;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
@ -12,6 +13,7 @@ describe('CurrencyProvider', () => {
|
||||
HttpModule
|
||||
],
|
||||
providers: [
|
||||
ApiProvider,
|
||||
CurrencyProvider
|
||||
]
|
||||
});
|
||||
@ -47,7 +49,7 @@ describe('CurrencyProvider', () => {
|
||||
});
|
||||
|
||||
it('rounds float using specified number of decimal places', () => {
|
||||
let aFloat = 4.32943;
|
||||
let aFloat: number = 4.32943;
|
||||
|
||||
expect(currency.roundFloat(aFloat, 2)).toBe(4.33);
|
||||
expect(currency.roundFloat(aFloat, 3)).toBe(4.329);
|
||||
@ -66,7 +68,7 @@ describe('CurrencyProvider', () => {
|
||||
});
|
||||
|
||||
it('gets proper conversion after changing currency', () => {
|
||||
let aFloat = 12345.09876543;
|
||||
let aFloat: number = 12345.09876543;
|
||||
expect(currency.getConversion(aFloat)).toBe('12345.09876543 BTC');
|
||||
|
||||
currency.setCurrency('mBTC');
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Http } from '@angular/http';
|
||||
import { ApiProvider } from '../../providers/api/api';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
/*
|
||||
@ -11,16 +12,18 @@ import 'rxjs/add/operator/map';
|
||||
@Injectable()
|
||||
export class CurrencyProvider {
|
||||
|
||||
private defaultCurrency: string;
|
||||
private currencySymbol: string;
|
||||
private factor: number = 1;
|
||||
public defaultCurrency: string;
|
||||
public currencySymbol: string;
|
||||
public factor: number = 1;
|
||||
private bitstamp: number;
|
||||
private loading: boolean;
|
||||
|
||||
constructor(public http: Http) {
|
||||
constructor(public http: Http, private api: ApiProvider) {
|
||||
this.defaultCurrency = 'BTC';
|
||||
this.currencySymbol = this.defaultCurrency;
|
||||
}
|
||||
|
||||
private roundFloat(aFloat: number, decimalPlaces: number): number {
|
||||
public roundFloat(aFloat: number, decimalPlaces: number): number {
|
||||
return Math.round(aFloat * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
|
||||
}
|
||||
|
||||
@ -50,12 +53,17 @@ export class CurrencyProvider {
|
||||
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;
|
||||
});
|
||||
*/
|
||||
this.http.get(this.api.apiPrefix + 'currency').subscribe(
|
||||
(data) => {
|
||||
let currencyParsed: any = JSON.parse(data['_body']);
|
||||
this.factor = this.bitstamp = currencyParsed.data.bitstamp;
|
||||
this.loading = false;
|
||||
},
|
||||
(err) => {
|
||||
console.log('err is', err);
|
||||
this.loading = false;
|
||||
}
|
||||
);
|
||||
} else if (currency === 'mBTC') {
|
||||
this.factor = 1000;
|
||||
} else if (currency === 'bits') {
|
||||
|
||||
@ -17,7 +17,9 @@ import { ConfigMock, PlatformMock } from './mocks';
|
||||
import { BlocksServiceMock } from './services/mocks';
|
||||
import { BlocksService } from './services';
|
||||
import { ApiProvider } from './providers/api/api';
|
||||
import { CurrencyProvider } from './providers/currency/currency';
|
||||
import { HeadNavComponentModule } from './components/head-nav/head-nav.module';
|
||||
import { ActionSheetController } from 'ionic-angular';
|
||||
|
||||
// Unfortunately there's no typing for the `__karma__` variable. Just declare it as any.
|
||||
declare var __karma__: any;
|
||||
@ -63,7 +65,9 @@ export class TestUtils {
|
||||
{provide: Platform, useClass: PlatformMock},
|
||||
{provide: Config, useClass: ConfigMock},
|
||||
{provide: BlocksService, useClass: BlocksServiceMock},
|
||||
ApiProvider
|
||||
ApiProvider,
|
||||
CurrencyProvider,
|
||||
ActionSheetController
|
||||
],
|
||||
imports: [
|
||||
FormsModule,
|
||||
|
||||
203
app/yarn.lock
203
app/yarn.lock
@ -200,6 +200,39 @@
|
||||
uuid "^3.0.1"
|
||||
wrap-ansi "^3.0.1"
|
||||
|
||||
"@ionic/cli-utils@1.9.1":
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/cli-utils/-/cli-utils-1.9.1.tgz#a0118819cb8de1f3bc4bc5b401e5b61d7f41d5b5"
|
||||
dependencies:
|
||||
"@types/gulp" "^3.8.33"
|
||||
archiver "^2.0.0"
|
||||
chalk "^2.0.0"
|
||||
chokidar "^1.7.0"
|
||||
ci-info "^1.0.0"
|
||||
cross-spawn "^5.1.0"
|
||||
dargs "^5.1.0"
|
||||
diff "^3.3.0"
|
||||
elementtree "^0.1.7"
|
||||
express "^4.15.4"
|
||||
inquirer "^3.2.1"
|
||||
leek "0.0.24"
|
||||
lodash "^4.17.4"
|
||||
minimist "^1.2.0"
|
||||
ncp "^2.0.0"
|
||||
opn "^5.1.0"
|
||||
proxy-middleware "^0.15.0"
|
||||
semver "^5.4.1"
|
||||
slice-ansi "^1.0.0"
|
||||
ssh-config "^1.0.1"
|
||||
string-width "^2.1.1"
|
||||
strip-ansi "^4.0.0"
|
||||
superagent "^3.5.2"
|
||||
tar "^2.2.1"
|
||||
tiny-lr "^1.0.5"
|
||||
tslib "^1.7.1"
|
||||
uuid "^3.0.1"
|
||||
wrap-ansi "^3.0.1"
|
||||
|
||||
"@ionic/storage@2.0.1":
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@ionic/storage/-/storage-2.0.1.tgz#bb1a8c276007d008d7acdda426b56065b0fd3c0b"
|
||||
@ -221,6 +254,14 @@
|
||||
magic-string "^0.19.0"
|
||||
source-map "^0.5.6"
|
||||
|
||||
"@types/gulp@^3.8.33":
|
||||
version "3.8.33"
|
||||
resolved "https://registry.yarnpkg.com/@types/gulp/-/gulp-3.8.33.tgz#b1b076820738c9c4eb7808cd926bff1683e1c2ab"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/orchestrator" "*"
|
||||
"@types/vinyl" "*"
|
||||
|
||||
"@types/jasmine@2.5.41":
|
||||
version "2.5.41"
|
||||
resolved "https://registry.yarnpkg.com/@types/jasmine/-/jasmine-2.5.41.tgz#d5e86161a0af80d52062b310a33ed65b051a0713"
|
||||
@ -229,6 +270,10 @@
|
||||
version "0.0.30"
|
||||
resolved "https://registry.yarnpkg.com/@types/localforage/-/localforage-0.0.30.tgz#3d60a6bf6dda38e3f8a469611598379f1f649509"
|
||||
|
||||
"@types/node@*":
|
||||
version "8.0.24"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.24.tgz#06c580084d9add1fb40c1510ef0b448961246fb1"
|
||||
|
||||
"@types/node@7.0.4":
|
||||
version "7.0.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-7.0.4.tgz#9aabc135979ded383325749f508894c662948c8b"
|
||||
@ -237,6 +282,17 @@
|
||||
version "6.0.79"
|
||||
resolved "https://registry.yarnpkg.com/@types/node/-/node-6.0.79.tgz#5efe7d4a6d8c453c7e9eaf55d931f4a22fac5169"
|
||||
|
||||
"@types/orchestrator@*":
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/orchestrator/-/orchestrator-0.3.0.tgz#bf84a1699c9330d4fe89cd81263e8fc09fb32978"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
"@types/q" "^0"
|
||||
|
||||
"@types/q@^0":
|
||||
version "0.0.36"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.36.tgz#97d786389641bcbd0e22bfc729a534175976371d"
|
||||
|
||||
"@types/q@^0.0.32":
|
||||
version "0.0.32"
|
||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-0.0.32.tgz#bd284e57c84f1325da702babfc82a5328190c0c5"
|
||||
@ -245,6 +301,12 @@
|
||||
version "2.53.42"
|
||||
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-2.53.42.tgz#74cb77fb6052edaff2a8984ddafd88d419f25cac"
|
||||
|
||||
"@types/vinyl@*":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/vinyl/-/vinyl-2.0.0.tgz#fd213bf7f4136dde21fe1895500b12c186f8c268"
|
||||
dependencies:
|
||||
"@types/node" "*"
|
||||
|
||||
abbrev@1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.0.tgz#d0554c2256636e2f56e7c2e5ad183f859428d81f"
|
||||
@ -335,6 +397,12 @@ amdefine@>=0.0.4:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5"
|
||||
|
||||
angular2-moment@^1.6.0:
|
||||
version "1.6.0"
|
||||
resolved "https://registry.yarnpkg.com/angular2-moment/-/angular2-moment-1.6.0.tgz#2be11b63d9cbdff8fee06f575c1beee2d863d62b"
|
||||
dependencies:
|
||||
moment "^2.16.0"
|
||||
|
||||
angular2-qrcode@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/angular2-qrcode/-/angular2-qrcode-2.0.1.tgz#1b4e65c302694b5078ca06f71138f7e4367754dc"
|
||||
@ -1256,7 +1324,7 @@ chokidar@1.6.1:
|
||||
optionalDependencies:
|
||||
fsevents "^1.0.0"
|
||||
|
||||
chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.6.1:
|
||||
chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.6.1, chokidar@^1.7.0:
|
||||
version "1.7.0"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-1.7.0.tgz#798e689778151c8076b4b360e5edd28cda2bb468"
|
||||
dependencies:
|
||||
@ -1800,7 +1868,7 @@ date-now@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"
|
||||
|
||||
debug@*, debug@2, debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8:
|
||||
debug@*, debug@2, debug@2.6.8, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0, debug@^2.6.3, debug@^2.6.8, debug@~2.6.7:
|
||||
version "2.6.8"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc"
|
||||
dependencies:
|
||||
@ -1880,6 +1948,10 @@ depd@1.1.0, depd@~1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.0.tgz#e1bd82c6aab6ced965b97b88b17ed3e528ca18c3"
|
||||
|
||||
depd@1.1.1, depd@~1.1.1:
|
||||
version "1.1.1"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.1.tgz#5783b4e1c459f06fa5ca27f991f3d06e7a310359"
|
||||
|
||||
des.js@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc"
|
||||
@ -1917,6 +1989,10 @@ diff@^3.1.0, diff@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9"
|
||||
|
||||
diff@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.0.tgz#056695150d7aa93237ca7e378ac3b1682b7963b9"
|
||||
|
||||
diffie-hellman@^5.0.0:
|
||||
version "5.0.2"
|
||||
resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e"
|
||||
@ -2327,6 +2403,39 @@ express@^4.13.3:
|
||||
utils-merge "1.0.0"
|
||||
vary "~1.1.1"
|
||||
|
||||
express@^4.15.4:
|
||||
version "4.15.4"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.15.4.tgz#032e2253489cf8fce02666beca3d11ed7a2daed1"
|
||||
dependencies:
|
||||
accepts "~1.3.3"
|
||||
array-flatten "1.1.1"
|
||||
content-disposition "0.5.2"
|
||||
content-type "~1.0.2"
|
||||
cookie "0.3.1"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.8"
|
||||
depd "~1.1.1"
|
||||
encodeurl "~1.0.1"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.0"
|
||||
finalhandler "~1.0.4"
|
||||
fresh "0.5.0"
|
||||
merge-descriptors "1.0.1"
|
||||
methods "~1.1.2"
|
||||
on-finished "~2.3.0"
|
||||
parseurl "~1.3.1"
|
||||
path-to-regexp "0.1.7"
|
||||
proxy-addr "~1.1.5"
|
||||
qs "6.5.0"
|
||||
range-parser "~1.2.0"
|
||||
send "0.15.4"
|
||||
serve-static "1.12.4"
|
||||
setprototypeof "1.0.3"
|
||||
statuses "~1.3.1"
|
||||
type-is "~1.6.15"
|
||||
utils-merge "1.0.0"
|
||||
vary "~1.1.1"
|
||||
|
||||
extend@3, extend@^3.0.0, extend@~3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444"
|
||||
@ -2446,6 +2555,18 @@ finalhandler@1.0.3, finalhandler@~1.0.3:
|
||||
statuses "~1.3.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
finalhandler@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.0.4.tgz#18574f2e7c4b98b8ae3b230c21f201f31bdb3fb7"
|
||||
dependencies:
|
||||
debug "2.6.8"
|
||||
encodeurl "~1.0.1"
|
||||
escape-html "~1.0.3"
|
||||
on-finished "~2.3.0"
|
||||
parseurl "~1.3.1"
|
||||
statuses "~1.3.1"
|
||||
unpipe "~1.0.0"
|
||||
|
||||
find-up@^1.0.0:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f"
|
||||
@ -2913,6 +3034,15 @@ http-errors@~1.6.1:
|
||||
setprototypeof "1.0.3"
|
||||
statuses ">= 1.3.1 < 2"
|
||||
|
||||
http-errors@~1.6.2:
|
||||
version "1.6.2"
|
||||
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.2.tgz#0a002cc85707192a7e7946ceedc11155f60ec736"
|
||||
dependencies:
|
||||
depd "1.1.1"
|
||||
inherits "2.0.3"
|
||||
setprototypeof "1.0.3"
|
||||
statuses ">= 1.3.1 < 2"
|
||||
|
||||
http-proxy-middleware@~0.17.4:
|
||||
version "0.17.4"
|
||||
resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.17.4.tgz#642e8848851d66f09d4f124912846dbaeb41b833"
|
||||
@ -3093,20 +3223,16 @@ 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"
|
||||
ionic@3.9.1:
|
||||
version "3.9.1"
|
||||
resolved "https://registry.yarnpkg.com/ionic/-/ionic-3.9.1.tgz#be50eea2f55bad40574772ecaeaf5a460fd16330"
|
||||
dependencies:
|
||||
"@ionic/cli-utils" "1.7.0"
|
||||
"@ionic/cli-utils" "1.9.1"
|
||||
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:
|
||||
@ -3121,6 +3247,10 @@ ipaddr.js@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.3.0.tgz#1e03a52fdad83a8bbb2b25cbf4998b4cffcd3dec"
|
||||
|
||||
ipaddr.js@1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.4.0.tgz#296aca878a821816e5b85d0a285a99bcff4582f0"
|
||||
|
||||
is-absolute-url@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6"
|
||||
@ -4106,6 +4236,10 @@ mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkd
|
||||
dependencies:
|
||||
minimist "0.0.8"
|
||||
|
||||
moment@^2.16.0:
|
||||
version "2.18.1"
|
||||
resolved "https://registry.yarnpkg.com/moment/-/moment-2.18.1.tgz#c36193dd3ce1c2eed2adb7c802dbbc77a81b1c0f"
|
||||
|
||||
ms@0.7.1:
|
||||
version "0.7.1"
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-0.7.1.tgz#9cd13c03adbff25b65effde7ce864ee952017098"
|
||||
@ -5004,7 +5138,14 @@ proxy-addr@~1.1.3, proxy-addr@~1.1.4:
|
||||
forwarded "~0.1.0"
|
||||
ipaddr.js "1.3.0"
|
||||
|
||||
proxy-middleware@0.15.0:
|
||||
proxy-addr@~1.1.5:
|
||||
version "1.1.5"
|
||||
resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-1.1.5.tgz#71c0ee3b102de3f202f3b64f608d173fcba1a918"
|
||||
dependencies:
|
||||
forwarded "~0.1.0"
|
||||
ipaddr.js "1.4.0"
|
||||
|
||||
proxy-middleware@0.15.0, proxy-middleware@^0.15.0:
|
||||
version "0.15.0"
|
||||
resolved "https://registry.yarnpkg.com/proxy-middleware/-/proxy-middleware-0.15.0.tgz#a3fdf1befb730f951965872ac2f6074c61477a56"
|
||||
|
||||
@ -5060,7 +5201,7 @@ qs@6.4.0, qs@~6.4.0:
|
||||
version "6.4.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233"
|
||||
|
||||
qs@^6.1.0, qs@^6.2.0:
|
||||
qs@6.5.0, qs@^6.1.0, qs@^6.2.0, qs@^6.4.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.0.tgz#8d04954d364def3efc55b5a0793e1e2c8b1e6e49"
|
||||
|
||||
@ -5645,6 +5786,24 @@ send@0.15.3:
|
||||
range-parser "~1.2.0"
|
||||
statuses "~1.3.1"
|
||||
|
||||
send@0.15.4:
|
||||
version "0.15.4"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.15.4.tgz#985faa3e284b0273c793364a35c6737bd93905b9"
|
||||
dependencies:
|
||||
debug "2.6.8"
|
||||
depd "~1.1.1"
|
||||
destroy "~1.0.4"
|
||||
encodeurl "~1.0.1"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.0"
|
||||
fresh "0.5.0"
|
||||
http-errors "~1.6.2"
|
||||
mime "1.3.4"
|
||||
ms "2.0.0"
|
||||
on-finished "~2.3.0"
|
||||
range-parser "~1.2.0"
|
||||
statuses "~1.3.1"
|
||||
|
||||
serve-index@^1.7.2:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.0.tgz#d2b280fc560d616ee81b48bf0fa82abed2485ce7"
|
||||
@ -5666,6 +5825,15 @@ serve-static@1.12.3:
|
||||
parseurl "~1.3.1"
|
||||
send "0.15.3"
|
||||
|
||||
serve-static@1.12.4:
|
||||
version "1.12.4"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.12.4.tgz#9b6aa98eeb7253c4eedc4c1f6fdbca609901a961"
|
||||
dependencies:
|
||||
encodeurl "~1.0.1"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.1"
|
||||
send "0.15.4"
|
||||
|
||||
serve-static@~1.11.2:
|
||||
version "1.11.2"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.11.2.tgz#2cf9889bd4435a320cc36895c9aa57bd662e6ac7"
|
||||
@ -6203,6 +6371,17 @@ tiny-lr@1.0.3:
|
||||
object-assign "^4.1.0"
|
||||
qs "^6.2.0"
|
||||
|
||||
tiny-lr@^1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tiny-lr/-/tiny-lr-1.0.5.tgz#21f40bf84ebd1f853056680375eef1670c334112"
|
||||
dependencies:
|
||||
body "^5.1.0"
|
||||
debug "~2.6.7"
|
||||
faye-websocket "~0.10.0"
|
||||
livereload-js "^2.2.2"
|
||||
object-assign "^4.1.0"
|
||||
qs "^6.4.0"
|
||||
|
||||
tmp@0.0.24:
|
||||
version "0.0.24"
|
||||
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.24.tgz#d6a5e198d14a9835cc6f2d7c3d9e302428c8cf12"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user