diff --git a/.gitignore b/.gitignore
index 05a92b9..c188cf5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
node_modules
package-lock.json
-*.log
\ No newline at end of file
+*.log
+.DS_Store
diff --git a/app/e2e/app.e2e-spec.ts b/app/e2e/app.e2e-spec.ts
index d1e06d8..4b8a378 100644
--- a/app/e2e/app.e2e-spec.ts
+++ b/app/e2e/app.e2e-spec.ts
@@ -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');
});
});
});
diff --git a/app/e2e/broadcastTxPage.e2e-spec.ts b/app/e2e/broadcastTxPage.e2e-spec.ts
index 11943c5..70c34fe 100644
--- a/app/e2e/broadcastTxPage.e2e-spec.ts
+++ b/app/e2e/broadcastTxPage.e2e-spec.ts
@@ -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);
diff --git a/app/ionic.config.json b/app/ionic.config.json
index b8ac8d6..a7bf4dd 100644
--- a/app/ionic.config.json
+++ b/app/ionic.config.json
@@ -1,5 +1,8 @@
{
"name": "insight-ui",
"app_id": "",
- "type": "ionic-angular"
+ "type": "ionic-angular",
+ "integrations": {
+ "cordova": {}
+ }
}
diff --git a/app/package.json b/app/package.json
index 5f07727..bb7407e 100644
--- a/app/package.json
+++ b/app/package.json
@@ -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",
diff --git a/app/src/app/app.component.ts b/app/src/app/app.component.ts
index fb4dd6e..f089c75 100644
--- a/app/src/app/app.component.ts
+++ b/app/src/app/app.component.ts
@@ -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 },
diff --git a/app/src/app/app.module.ts b/app/src/app/app.module.ts
index ca547f3..7d0c351 100644
--- a/app/src/app/app.module.ts
+++ b/app/src/app/app.module.ts
@@ -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
]
})
diff --git a/app/src/app/app.scss b/app/src/app/app.scss
index 553250e..e254df4 100644
--- a/app/src/app/app.scss
+++ b/app/src/app/app.scss
@@ -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".
//
diff --git a/app/src/assets/img/angularjs.png b/app/src/assets/img/angularjs.png
new file mode 100644
index 0000000..21aefd4
Binary files /dev/null and b/app/src/assets/img/angularjs.png differ
diff --git a/app/src/assets/img/bitcore.svg b/app/src/assets/img/bitcore.svg
new file mode 100644
index 0000000..856b0a1
--- /dev/null
+++ b/app/src/assets/img/bitcore.svg
@@ -0,0 +1,29 @@
+
+
+ Group copy + bitcore copy@2x
+ Created with Sketch (http://www.bohemiancoding.com/sketch)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/assets/img/leveldb.png b/app/src/assets/img/leveldb.png
new file mode 100644
index 0000000..da13a67
Binary files /dev/null and b/app/src/assets/img/leveldb.png differ
diff --git a/app/src/assets/img/nodejs.png b/app/src/assets/img/nodejs.png
new file mode 100644
index 0000000..4cba6f8
Binary files /dev/null and b/app/src/assets/img/nodejs.png differ
diff --git a/app/src/components/head-nav/head-nav.html b/app/src/components/head-nav/head-nav.html
index b441164..1d5ff08 100644
--- a/app/src/components/head-nav/head-nav.html
+++ b/app/src/components/head-nav/head-nav.html
@@ -4,9 +4,12 @@
{{title}}
-
+
+ {{ currency.currencySymbol }}
+
+
-
+
diff --git a/app/src/components/head-nav/head-nav.module.ts b/app/src/components/head-nav/head-nav.module.ts
index 7fb2c00..96140da 100644
--- a/app/src/components/head-nav/head-nav.module.ts
+++ b/app/src/components/head-nav/head-nav.module.ts
@@ -4,10 +4,10 @@ import { HeadNavComponent } from './head-nav';
@NgModule({
declarations: [
- HeadNavComponent,
+ HeadNavComponent
],
imports: [
- IonicModule,
+ IonicModule
],
exports: [
HeadNavComponent
diff --git a/app/src/components/head-nav/head-nav.ts b/app/src/components/head-nav/head-nav.ts
index 54fee4c..664e77e 100644
--- a/app/src/components/head-nav/head-nav.ts
+++ b/app/src/components/head-nav/head-nav.ts
@@ -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;
+ }
}
diff --git a/app/src/components/latest-blocks/latest-blocks.html b/app/src/components/latest-blocks/latest-blocks.html
new file mode 100644
index 0000000..8268be4
--- /dev/null
+++ b/app/src/components/latest-blocks/latest-blocks.html
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+ Height
+ Age
+ Timestamp
+ Transactions
+ Mined By
+ Size
+
+
+
+ {{block.height}}
+
+
+ {{ block.time | amFromUnix | amTimeAgo }}
+
+
+ {{ block.time * 1000 | date:'medium' }}
+
+
+ {{block.txlength}}
+
+
+ {{block.poolInfo.poolName}}
+
+
+ {{ block.size }}
+
+
+
+
+ See all blocks
+
+
+
+
+
diff --git a/app/src/components/latest-blocks/latest-blocks.module.ts b/app/src/components/latest-blocks/latest-blocks.module.ts
new file mode 100644
index 0000000..f2086b9
--- /dev/null
+++ b/app/src/components/latest-blocks/latest-blocks.module.ts
@@ -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 {}
diff --git a/app/src/components/latest-blocks/latest-blocks.scss b/app/src/components/latest-blocks/latest-blocks.scss
new file mode 100644
index 0000000..0ae897d
--- /dev/null
+++ b/app/src/components/latest-blocks/latest-blocks.scss
@@ -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;
+ }
+ }
+}
diff --git a/app/src/components/latest-blocks/latest-blocks.ts b/app/src/components/latest-blocks/latest-blocks.ts
new file mode 100644
index 0000000..21fc1e4
--- /dev/null
+++ b/app/src/components/latest-blocks/latest-blocks.ts
@@ -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 = [];
+ @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 {
+ /* 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');
+ }
+}
diff --git a/app/src/components/latest-transactions/latest-transactions.html b/app/src/components/latest-transactions/latest-transactions.html
new file mode 100644
index 0000000..948536e
--- /dev/null
+++ b/app/src/components/latest-transactions/latest-transactions.html
@@ -0,0 +1,4 @@
+
+
+ {{text}}
+
diff --git a/app/src/components/latest-transactions/latest-transactions.module.ts b/app/src/components/latest-transactions/latest-transactions.module.ts
new file mode 100644
index 0000000..7eb0b92
--- /dev/null
+++ b/app/src/components/latest-transactions/latest-transactions.module.ts
@@ -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 {}
diff --git a/app/src/components/latest-transactions/latest-transactions.scss b/app/src/components/latest-transactions/latest-transactions.scss
new file mode 100644
index 0000000..570ea96
--- /dev/null
+++ b/app/src/components/latest-transactions/latest-transactions.scss
@@ -0,0 +1,3 @@
+latest-transactions {
+
+}
diff --git a/app/src/components/latest-transactions/latest-transactions.ts b/app/src/components/latest-transactions/latest-transactions.ts
new file mode 100644
index 0000000..4650fff
--- /dev/null
+++ b/app/src/components/latest-transactions/latest-transactions.ts
@@ -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;
+ }
+ );
+ */
+ }
+
+}
diff --git a/app/src/components/transaction-list/transaction-list.html b/app/src/components/transaction-list/transaction-list.html
index 6620fc2..9c0a459 100644
--- a/app/src/components/transaction-list/transaction-list.html
+++ b/app/src/components/transaction-list/transaction-list.html
@@ -1,7 +1,14 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/components/transaction/transaction.html b/app/src/components/transaction/transaction.html
index ca9b1e8..78b2ea6 100644
--- a/app/src/components/transaction/transaction.html
+++ b/app/src/components/transaction/transaction.html
@@ -18,7 +18,7 @@
-
+
@@ -27,42 +27,56 @@
-
+
-
{{ vin.addr }} {{ vin.value + ' BTC' }}
-
-
Confirmations {{vin.confirmations}}
-
scriptSig
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
{{ getAddress(vout) }}
-
Type {{vout.scriptPubKey.type}}
-
scriptPubKey
-
-
{{vout.scriptPubKey.asm}}
+
Confirmations {{vin.confirmations}}
+
scriptSig
+
- {{ vout.value + ' BTC' }}
+ {{ currency.getConversion(vin.value) }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Type {{vout.scriptPubKey.type}}
+
scriptPubKey
+
+
{{vout.scriptPubKey.asm}}
+
+
+
+
+
+ {{ currency.getConversion(vout.value) }}
(S)
(U)
@@ -72,12 +86,14 @@
-
- Fee {{ tx.fees + ' BTC' }}
+
+ Fee {{ currency.getConversion(tx.fees) }}
-
+
{{ tx.confirmations }} Confirmations
- {{ tx.valueOut + ' BTC' }}
+
+
+ {{ currency.getConversion(tx.valueOut) }}
diff --git a/app/src/components/transaction/transaction.scss b/app/src/components/transaction/transaction.scss
index 59fc005..40a22fb 100644
--- a/app/src/components/transaction/transaction.scss
+++ b/app/src/components/transaction/transaction.scss
@@ -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;
diff --git a/app/src/components/transaction/transaction.ts b/app/src/components/transaction/transaction.ts
index 074ee97..8d5cc19 100644
--- a/app/src/components/transaction/transaction.ts
+++ b/app/src/components/transaction/transaction.ts
@@ -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): Array {
+ if (!items) return [];
+
+ let l: number = items.length;
+
+ let ret: Array = [];
+ 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;
+ };
}
diff --git a/app/src/pages/address/address.html b/app/src/pages/address/address.html
index 9e441f5..4dfc4d7 100644
--- a/app/src/pages/address/address.html
+++ b/app/src/pages/address/address.html
@@ -3,45 +3,51 @@
- Address
- Address {{ address.addrStr }}
- {{ address.balance }} BTC
+
+
+
- Summary
+
+
Address
+
Address {{ address.addrStr }}
+
{{ currency.getConversion(address.balance) }}
-
-
- Total Received
-
- {{ address.totalReceived }} BTC
-
-
-
- Total Sent
-
- {{ address.totalSent }} BTC
-
-
-
- Final Balance
-
- {{ address.balance }} BTC
-
-
-
- No. Transactions
-
- {{ address.txApperances }}
-
-
-
+
Summary
-
-
-
+
+
+ Total Received
+
+ {{ currency.getConversion(address.totalReceived) }}
+
+
+
+ Total Sent
+
+ {{ currency.getConversion(address.totalSent) }}
+
+
+
+ Final Balance
+
+ {{ currency.getConversion(address.balance) }}
+
+
+
+ No. Transactions
+
+ {{ address.txApperances }}
+
+
+
-
Transactions
+
+
+
-
+
Transactions
+
+
+
diff --git a/app/src/pages/address/address.ts b/app/src/pages/address/address.ts
index e392a33..459f4de 100644
--- a/app/src/pages/address/address.ts
+++ b/app/src/pages/address/address.ts
@@ -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');
}
diff --git a/app/src/pages/block-detail/block-detail.html b/app/src/pages/block-detail/block-detail.html
index 354ef77..aaebe36 100644
--- a/app/src/pages/block-detail/block-detail.html
+++ b/app/src/pages/block-detail/block-detail.html
@@ -3,96 +3,102 @@
- Block #{{ block.height }}
- BlockHash {{ block.hash }}
-
- Summary
-
-
-
- Number of Transactions
-
- {{ block.tx.length }}
-
-
-
- Height
-
- {{ block.height }} (Mainchain)
-
-
-
- Block Reward
-
- {{ block.reward + ' BTC' }}
-
-
-
- Timestamp
-
- {{ block.time * 1000 | date:'medium' }}
-
-
-
- Mined by
-
- {{ block.poolInfo.poolName }}
-
-
-
- Merkle Root
-
- {{ block.merkleroot }}
-
-
-
- Previous Block
-
- {{ block.height - 1 }}
-
-
-
- Difficulty
-
- {{ block.difficulty }}
-
-
-
- Bits
-
- {{ block.bits }}
-
-
-
- Size (bytes)
-
- {{ block.size }}
-
-
-
- Version
-
- {{ block.version }}
-
-
-
- Nonce
-
- {{ block.nonce }}
-
-
-
- Next Block
-
- {{ block.height + 1 }}
-
-
-
+
+
+
-
Transactions
+
Block #{{ block.height }}
+
BlockHash {{ block.hash }}
-
+
Summary
+
+
+
+ Number of Transactions
+
+ {{ block.tx.length }}
+
+
+
+ Height
+
+ {{ block.height }} (Mainchain)
+
+
+
+ Block Reward
+
+ {{ currency.getConversion(block.reward) }}
+
+
+
+ Timestamp
+
+ {{ block.time * 1000 | date:'medium' }}
+
+
+
+ Mined by
+
+ {{ block.poolInfo.poolName }}
+
+
+
+ Merkle Root
+
+ {{ block.merkleroot }}
+
+
+
+ Previous Block
+
+ {{ block.height - 1 }}
+
+
+
+ Difficulty
+
+ {{ block.difficulty }}
+
+
+
+ Bits
+
+ {{ block.bits }}
+
+
+
+ Size (bytes)
+
+ {{ block.size }}
+
+
+
+ Version
+
+ {{ block.version }}
+
+
+
+ Nonce
+
+ {{ block.nonce }}
+
+
+
+ Next Block
+
+ {{ block.height + 1 }}
+
+
+
+
+
+
Transactions
+
+
+
diff --git a/app/src/pages/block-detail/block-detail.ts b/app/src/pages/block-detail/block-detail.ts
index 66053d5..95bdaf8 100644
--- a/app/src/pages/block-detail/block-detail.ts
+++ b/app/src/pages/block-detail/block-detail.ts
@@ -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
diff --git a/app/src/pages/blocks/blocks.html b/app/src/pages/blocks/blocks.html
new file mode 100644
index 0000000..54d52dc
--- /dev/null
+++ b/app/src/pages/blocks/blocks.html
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
Blocks
+
+
+
diff --git a/app/src/pages/blocks/blocks.module.ts b/app/src/pages/blocks/blocks.module.ts
new file mode 100644
index 0000000..521ae44
--- /dev/null
+++ b/app/src/pages/blocks/blocks.module.ts
@@ -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 {}
diff --git a/app/src/pages/blocks/blocks.scss b/app/src/pages/blocks/blocks.scss
new file mode 100644
index 0000000..563b211
--- /dev/null
+++ b/app/src/pages/blocks/blocks.scss
@@ -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;
+ }
+ }
+}
diff --git a/app/src/pages/blocks/blocks.ts b/app/src/pages/blocks/blocks.ts
new file mode 100644
index 0000000..5dcf67c
--- /dev/null
+++ b/app/src/pages/blocks/blocks.ts
@@ -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 = [];
+
+ 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;
+ }
+ );
+ }
+}
diff --git a/app/src/pages/blocksPage/blocksPage.ts b/app/src/pages/blocksPage/blocksPage.ts
index 5f2eeaf..e5273a4 100644
--- a/app/src/pages/blocksPage/blocksPage.ts
+++ b/app/src/pages/blocksPage/blocksPage.ts
@@ -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;
constructor(private navCtrl: NavController, private blocksService: BlocksService) {
+ // TODO Put loading spinner on page
+
this.title = 'Blocks';
this.blocks = blocksService.latestBlocks;
this.blocks.subscribe((blocks) => {
diff --git a/app/src/pages/home/home.html b/app/src/pages/home/home.html
new file mode 100644
index 0000000..ad57d6d
--- /dev/null
+++ b/app/src/pages/home/home.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
Latest Blocks
+
+
+
+
+
Latest Transactions
+
+
+
+
+
About
+
insight is an open-source Bitcoin blockchain explorer 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 source code .
+
insight is still in development, so be sure to report any bugs and provide feedback for improvement at our github issue tracker .
+
+
+ Powered by
+
+
+
+
+
+
+
+
diff --git a/app/src/pages/home/home.module.ts b/app/src/pages/home/home.module.ts
new file mode 100644
index 0000000..b3d3a15
--- /dev/null
+++ b/app/src/pages/home/home.module.ts
@@ -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 {}
diff --git a/app/src/pages/home/home.scss b/app/src/pages/home/home.scss
new file mode 100644
index 0000000..91b4923
--- /dev/null
+++ b/app/src/pages/home/home.scss
@@ -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%;
+ }
+
+}
diff --git a/app/src/pages/home/home.ts b/app/src/pages/home/home.ts
new file mode 100644
index 0000000..5880022
--- /dev/null
+++ b/app/src/pages/home/home.ts
@@ -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');
+ }
+
+}
diff --git a/app/src/pages/index.ts b/app/src/pages/index.ts
index a449179..67a109d 100644
--- a/app/src/pages/index.ts
+++ b/app/src/pages/index.ts
@@ -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';
diff --git a/app/src/pages/pages.module.ts b/app/src/pages/pages.module.ts
index 2da0e6a..6156b14 100644
--- a/app/src/pages/pages.module.ts
+++ b/app/src/pages/pages.module.ts
@@ -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,
],
diff --git a/app/src/pages/transaction/transaction.html b/app/src/pages/transaction/transaction.html
index 26a1663..7f904dc 100644
--- a/app/src/pages/transaction/transaction.html
+++ b/app/src/pages/transaction/transaction.html
@@ -3,40 +3,46 @@
- Transaction
- Transaction {{ tx.txid }}
+
+
+
- Summary
+
+
Transaction
+
Transaction {{ tx.txid }}
-
-
- Size
-
- {{ tx.size }} (bytes)
-
-
-
- Received Time
-
- {{ tx.time * 1000 | date:'medium' }}
-
-
-
- Mined Time
-
- {{ tx.blocktime * 1000 | date:'medium' }}
-
-
-
- Included in Block
-
- {{ tx.blockhash }}
-
-
-
+
Summary
-
Details
+
+
+ Size
+
+ {{ tx.size }} (bytes)
+
+
+
+ Received Time
+
+ {{ tx.time * 1000 | date:'medium' }}
+
+
+
+ Mined Time
+
+ {{ tx.blocktime * 1000 | date:'medium' }}
+
+
+
+ Included in Block
+
+ {{ tx.blockhash }}
+
+
+
-
+
Details
+
+
+
diff --git a/app/src/pipes/split/split.ts b/app/src/pipes/split/split.ts
index ab08efd..1f2e7ca 100644
--- a/app/src/pipes/split/split.ts
+++ b/app/src/pipes/split/split.ts
@@ -15,7 +15,6 @@ export class SplitPipe implements PipeTransform {
*/
public transform(value: string, delimiter: string): Array {
let array: Array = value.split(delimiter);
- console.log('split is', array);
return array;
}
}
diff --git a/app/src/providers/api/api.ts b/app/src/providers/api/api.ts
index 31c1966..a15b48e 100644
--- a/app/src/providers/api/api.ts
+++ b/app/src/providers/api/api.ts
@@ -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) {
}
diff --git a/app/src/providers/blocks/blocks.ts b/app/src/providers/blocks/blocks.ts
new file mode 100644
index 0000000..6ab163c
--- /dev/null
+++ b/app/src/providers/blocks/blocks.ts
@@ -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');
+ }
+
+}
diff --git a/app/src/providers/currency/currency.spec.ts b/app/src/providers/currency/currency.spec.ts
index d1ef863..02fa17a 100644
--- a/app/src/providers/currency/currency.spec.ts
+++ b/app/src/providers/currency/currency.spec.ts
@@ -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');
diff --git a/app/src/providers/currency/currency.ts b/app/src/providers/currency/currency.ts
index fe6f412..b3f571b 100644
--- a/app/src/providers/currency/currency.ts
+++ b/app/src/providers/currency/currency.ts
@@ -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') {
diff --git a/app/src/test.ts b/app/src/test.ts
index 5a0cc78..c317506 100644
--- a/app/src/test.ts
+++ b/app/src/test.ts
@@ -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,
diff --git a/app/yarn.lock b/app/yarn.lock
index 53191d9..575bfc5 100644
--- a/app/yarn.lock
+++ b/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"