diff --git a/app/package.json b/app/package.json index 99495df..1701978 100644 --- a/app/package.json +++ b/app/package.json @@ -28,6 +28,7 @@ "@ionic-native/splash-screen": "3.10.2", "@ionic-native/status-bar": "3.10.2", "@ionic/storage": "2.0.1", + "angular2-qrcode": "^2.0.1", "ionic-angular": "3.4.2", "ionicons": "3.0.0", "rxjs": "5.4.0", @@ -37,12 +38,12 @@ "devDependencies": { "@angular/cli": "1.1.2", "@ionic/app-scripts": "1.3.7", - "@ionic/cli-plugin-cordova": "1.5.0", - "@ionic/cli-plugin-ionic-angular": "1.4.0", + "@ionic/cli-plugin-cordova": "1.6.2", + "@ionic/cli-plugin-ionic-angular": "1.4.1", "@types/jasmine": "2.5.41", "@types/node": "7.0.4", "codecov": "2.2.0", - "ionic": "3.6.0", + "ionic": "3.7.0", "jasmine-core": "2.5.2", "jasmine-spec-reporter": "3.2.0", "karma": "1.4.1", diff --git a/app/src/app/app.module.ts b/app/src/app/app.module.ts index 8e5cca9..ca547f3 100644 --- a/app/src/app/app.module.ts +++ b/app/src/app/app.module.ts @@ -7,6 +7,7 @@ import { SplashScreen } from '@ionic-native/splash-screen'; import { InsightApp } from './app.component'; import { PagesModule, BlocksPage, BroadcastTxPage, NodeStatusPage, VerifyMessagePage } from '../pages'; import { BlocksService, StorageService } from '../services'; +import { ApiProvider } from '../providers/api/api'; @NgModule({ declarations: [ @@ -31,7 +32,8 @@ import { BlocksService, StorageService } from '../services'; SplashScreen, StorageService, BlocksService, - {provide: ErrorHandler, useClass: IonicErrorHandler} + {provide: ErrorHandler, useClass: IonicErrorHandler}, + ApiProvider ] }) diff --git a/app/src/app/app.scss b/app/src/app/app.scss index a967d6f..553250e 100644 --- a/app/src/app/app.scss +++ b/app/src/app/app.scss @@ -7,7 +7,14 @@ // styles are for the entire app and not just one component. // Additionally, this file can be also used as an entry point // to import other Sass files to be included in the output CSS. -// + +.ellipsis { + display: block; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + // Shared Sass variables, which can be used to adjust Ionic's // default Sass variables, belong in "theme/variables.scss". // diff --git a/app/src/components/head-nav/head-nav.html b/app/src/components/head-nav/head-nav.html new file mode 100644 index 0000000..b441164 --- /dev/null +++ b/app/src/components/head-nav/head-nav.html @@ -0,0 +1,12 @@ + + + {{title}} + + + + + diff --git a/app/src/components/head-nav/head-nav.module.ts b/app/src/components/head-nav/head-nav.module.ts new file mode 100644 index 0000000..7fb2c00 --- /dev/null +++ b/app/src/components/head-nav/head-nav.module.ts @@ -0,0 +1,16 @@ +import { NgModule } from '@angular/core'; +import { IonicModule } from 'ionic-angular'; +import { HeadNavComponent } from './head-nav'; + +@NgModule({ + declarations: [ + HeadNavComponent, + ], + imports: [ + IonicModule, + ], + exports: [ + HeadNavComponent + ] +}) +export class HeadNavComponentModule {} diff --git a/app/src/components/head-nav/head-nav.scss b/app/src/components/head-nav/head-nav.scss new file mode 100644 index 0000000..b78439c --- /dev/null +++ b/app/src/components/head-nav/head-nav.scss @@ -0,0 +1,3 @@ +head-nav { + +} diff --git a/app/src/components/head-nav/head-nav.ts b/app/src/components/head-nav/head-nav.ts new file mode 100644 index 0000000..54fee4c --- /dev/null +++ b/app/src/components/head-nav/head-nav.ts @@ -0,0 +1,101 @@ +import { Component } from '@angular/core'; +import { Input } from '@angular/core'; +import { NavController } from 'ionic-angular'; +import { Http } from '@angular/http'; +import { ApiProvider } from '../../providers/api/api'; + +/** + * Generated class for the HeadNavComponent component. + * + * See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html + * for more info on Angular Components. + */ +@Component({ + selector: 'head-nav', + templateUrl: 'head-nav.html' +}) +export class HeadNavComponent { + + public loading: boolean; + @Input() public title: string; + public q: string; + public badQuery: boolean = false; + + constructor(private navCtrl: NavController, private http: Http, private api: ApiProvider) { + } + + private resetSearch(): void { + this.q = ''; + this.loading = false; + } + + public search(): void { + let apiPrefix: string = this.api.apiPrefix; + + this.http.get(apiPrefix + 'block/' + this.q).subscribe( + function (data: any) { + this.resetSearch(); + console.log('block', data); + let parsedData: any = JSON.parse(data._body); + this.navCtrl.push('block-detail', { + 'blockHash': parsedData.hash + }); + }.bind(this), + () => { + this.http.get(apiPrefix + 'tx/' + this.q).subscribe( + function (data: any) { + this.resetSearch(); + console.log('tx', data); + let parsedData: any = JSON.parse(data._body); + this.navCtrl.push('transaction', { + 'txId': parsedData.txid + }); + }.bind(this), + () => { + this.http.get(apiPrefix + 'addr/' + this.q).subscribe( + function (data: any) { + this.resetSearch(); + console.log('addr', data); + let parsedData: any = JSON.parse(data._body); + this.navCtrl.push('address', { + 'addrStr': parsedData.addrStr + }); + }.bind(this), + () => { + this.http.get(apiPrefix + 'block-index/' + this.q).subscribe( + function (data: any): void { + this.resetSearch(); + let parsedData: any = JSON.parse(data._body); + this.navCtrl.push('block-detail', { + 'blockHash': parsedData.blockHash + }); + }.bind(this), + function (): void { + this.loading = false; + this.reportBadQuery(); + }.bind(this) + ); + } + ); + } + ); + } + ); + } + + /* tslint:disable:no-unused-variable */ + private reportBadQuery(): void { + this.badQuery = true; + console.log('badQuery', this.badQuery); + + setTimeout( + function (): void { + this.badQuery = false; + console.log('badQuery', this.badQuery); + }.bind(this), + 2000 + ); + }; + /* tslint:enable:no-unused-variable */ + +} diff --git a/app/src/components/transaction-list/transaction-list.html b/app/src/components/transaction-list/transaction-list.html new file mode 100644 index 0000000..6620fc2 --- /dev/null +++ b/app/src/components/transaction-list/transaction-list.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/app/src/components/transaction-list/transaction-list.module.ts b/app/src/components/transaction-list/transaction-list.module.ts new file mode 100644 index 0000000..19dac1d --- /dev/null +++ b/app/src/components/transaction-list/transaction-list.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { IonicModule } from 'ionic-angular'; +import { TransactionListComponent } from './transaction-list'; +import { TransactionComponentModule } from '../transaction/transaction.module'; + +@NgModule({ + declarations: [ + TransactionListComponent + ], + imports: [ + IonicModule, + TransactionComponentModule + ], + exports: [ + TransactionListComponent + ] +}) +export class TransactionListComponentModule {} diff --git a/app/src/components/transaction-list/transaction-list.scss b/app/src/components/transaction-list/transaction-list.scss new file mode 100644 index 0000000..6e9f0ff --- /dev/null +++ b/app/src/components/transaction-list/transaction-list.scss @@ -0,0 +1,3 @@ +transaction-list { + +} diff --git a/app/src/components/transaction-list/transaction-list.ts b/app/src/components/transaction-list/transaction-list.ts new file mode 100644 index 0000000..a5d1e64 --- /dev/null +++ b/app/src/components/transaction-list/transaction-list.ts @@ -0,0 +1,40 @@ +import { Component } from '@angular/core'; +import { Input } from '@angular/core'; +import { Http } from '@angular/http'; +import { ApiProvider } from '../../providers/api/api'; + +/** + * Generated class for the TransactionListComponent component. + * + * See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html + * for more info on Angular Components. + */ +@Component({ + selector: 'transaction-list', + templateUrl: 'transaction-list.html' +}) +export class TransactionListComponent { + + public loading: boolean = true; + @Input() public queryType: string; + @Input() public queryValue: string; + public transactions: any = []; + + constructor(private http: Http, private api: ApiProvider) { + } + + private ngOnInit(): void { + let url: string = this.api.apiPrefix + 'txs?' + this.queryType + '=' + this.queryValue; + + this.http.get(url).subscribe( + (data) => { + this.transactions = JSON.parse(data['_body']); + this.loading = false; + }, + (err) => { + console.log('err is', err); + this.loading = false; + } + ); + } +} diff --git a/app/src/components/transaction/transaction.html b/app/src/components/transaction/transaction.html new file mode 100644 index 0000000..ca9b1e8 --- /dev/null +++ b/app/src/components/transaction/transaction.html @@ -0,0 +1,83 @@ + + + + + + +
+ first seen at + +
+
+ mined + +
+
+
+ + + + + + + No Inputs (Newly Generated Coins) + + + + + +
+

{{ vin.addr }} {{ vin.value + ' BTC' }}

+
+

Confirmations {{vin.confirmations}}

+

scriptSig

+
+
+

{{item}}

+
+
+
+
+
+
+ +
+ + + + + + +
+

{{ getAddress(vout) }}

+
+

Type {{vout.scriptPubKey.type}}

+

scriptPubKey

+
+ {{vout.scriptPubKey.asm}} +
+
+
+ +
+ {{ vout.value + ' BTC' }} + (S) + (U) +
+
+
+
+
+ + + + Fee {{ tx.fees + ' BTC' }} + + + {{ tx.confirmations }} Confirmations + {{ tx.valueOut + ' BTC' }} + + +
diff --git a/app/src/components/transaction/transaction.module.ts b/app/src/components/transaction/transaction.module.ts new file mode 100644 index 0000000..6b5a1a4 --- /dev/null +++ b/app/src/components/transaction/transaction.module.ts @@ -0,0 +1,18 @@ +import { NgModule } from '@angular/core'; +import { IonicModule } from 'ionic-angular'; +import { TransactionComponent } from './transaction'; +import { SplitPipe } from '../../pipes/split/split'; + +@NgModule({ + declarations: [ + TransactionComponent, + SplitPipe + ], + imports: [ + IonicModule + ], + exports: [ + TransactionComponent + ] +}) +export class TransactionComponentModule {} diff --git a/app/src/components/transaction/transaction.scss b/app/src/components/transaction/transaction.scss new file mode 100644 index 0000000..59fc005 --- /dev/null +++ b/app/src/components/transaction/transaction.scss @@ -0,0 +1,11 @@ +transaction { + ion-grid { + background-color: #F4F4F4; + border: 1px solid #eee; + border-radius: 2px; + + ion-row { + border: 1px solid #eee; + } + } +} diff --git a/app/src/components/transaction/transaction.ts b/app/src/components/transaction/transaction.ts new file mode 100644 index 0000000..074ee97 --- /dev/null +++ b/app/src/components/transaction/transaction.ts @@ -0,0 +1,46 @@ +import { Component } from '@angular/core'; +import { Input } from '@angular/core'; +import { NavController } from 'ionic-angular'; + +/** + * Generated class for the TransactionComponent component. + * + * See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html + * for more info on Angular Components. + */ +@Component({ + selector: 'transaction', + templateUrl: 'transaction.html' +}) +export class TransactionComponent { + + public expanded: boolean = false; + @Input() public tx: any = {}; + + constructor(private navCtrl: NavController) { + } + + public getAddress(vout: any): string { + if (vout.scriptPubKey && vout.scriptPubKey.addresses) { + return vout.scriptPubKey.addresses[0]; + } else { + return 'Unparsed address'; + } + } + + public goToTx(txId: string): void { + this.navCtrl.push('transaction', { + 'txId': txId + }); + } + + public goToAddress(addrStr: string): void { + this.navCtrl.push('address', { + 'addrStr': addrStr + }); + } + + public toggleExpanded(): void { + this.expanded = !this.expanded; + } +} diff --git a/app/src/components/transactions/transactions.html b/app/src/components/transactions/transactions.html deleted file mode 100644 index 4263992..0000000 --- a/app/src/components/transactions/transactions.html +++ /dev/null @@ -1,48 +0,0 @@ -
-
-

{{ tx.txid }}

-
- first seen at - -
-
- mined - -
- -
-
-
- No Inputs (Newly Generated Coins) -
-
- -
- > -
- -
-
-

{{ getAddress(vout) }} {{ vout.value + ' BTC' }} (S)(U)

-
-
-
- -
-
-
{{ vin.addr }}
-

{{ vin.value + ' BTC' }}

-
- -
- > -
- -
-
-

{{ getAddress(vout) }} {{ vout.value + ' BTC' }} (S)(U)

-
-
-
-
-
diff --git a/app/src/components/transactions/transactions.module.ts b/app/src/components/transactions/transactions.module.ts deleted file mode 100644 index d60c200..0000000 --- a/app/src/components/transactions/transactions.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { NgModule } from '@angular/core'; -import { IonicModule } from 'ionic-angular'; -import { TransactionsComponent } from './transactions'; - -@NgModule({ - declarations: [ - TransactionsComponent - ], - imports: [ - IonicModule - ], - exports: [ - TransactionsComponent - ] -}) -export class TransactionsComponentModule {} diff --git a/app/src/components/transactions/transactions.scss b/app/src/components/transactions/transactions.scss deleted file mode 100644 index 0912214..0000000 --- a/app/src/components/transactions/transactions.scss +++ /dev/null @@ -1,3 +0,0 @@ -transactions { - -} diff --git a/app/src/components/transactions/transactions.ts b/app/src/components/transactions/transactions.ts deleted file mode 100644 index 4c594c2..0000000 --- a/app/src/components/transactions/transactions.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Component } from '@angular/core'; -import { Input } from '@angular/core'; -import { Http } from '@angular/http'; - -/** - * Generated class for the TransactionsComponent component. - * - * See https://angular.io/docs/ts/latest/api/core/index/ComponentMetadata-class.html - * for more info on Angular Components. - */ -@Component({ - selector: 'transactions', - templateUrl: 'transactions.html' -}) -export class TransactionsComponent { - - public loading: boolean = true; - @Input() public blockHash: string; - public transactions: any = []; - - constructor(private http: Http) { - } - - private ngOnInit(): void { - let apiPrefix: string = 'http://localhost:3001/insight-api/'; - - this.http.get(apiPrefix + 'txs?block=' + this.blockHash).subscribe( - (data) => { - this.transactions = JSON.parse(data['_body']); - this.loading = false; - - this.transactions.txs.forEach((tx) => { - console.log('tx is', tx); - }); - }, - (err) => { - console.log('err is', err); - this.loading = false; - } - ); - } - - public getAddress(vout: any): string { - if (vout.scriptPubKey && vout.scriptPubKey.addresses) { - return vout.scriptPubKey.addresses[0]; - } else { - return 'Unparsed address'; - } - } -} diff --git a/app/src/pages/address/address.html b/app/src/pages/address/address.html new file mode 100644 index 0000000..9e441f5 --- /dev/null +++ b/app/src/pages/address/address.html @@ -0,0 +1,47 @@ + + + + + +

Address

+

Address {{ address.addrStr }}

+

{{ address.balance }} BTC

+ +

Summary

+ + + + Total Received + + {{ address.totalReceived }} BTC + + + + Total Sent + + {{ address.totalSent }} BTC + + + + Final Balance + + {{ address.balance }} BTC + + + + No. Transactions + + {{ address.txApperances }} + + + + +

+ +

+ +

Transactions

+ + + +
diff --git a/app/src/pages/address/address.module.ts b/app/src/pages/address/address.module.ts new file mode 100644 index 0000000..c354f4e --- /dev/null +++ b/app/src/pages/address/address.module.ts @@ -0,0 +1,22 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { AddressPage } from './address'; +import { TransactionListComponentModule } from '../../components/transaction-list/transaction-list.module'; +import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module'; +import { QRCodeModule } from 'angular2-qrcode'; + +@NgModule({ + declarations: [ + AddressPage + ], + imports: [ + IonicPageModule.forChild(AddressPage), + TransactionListComponentModule, + HeadNavComponentModule, + QRCodeModule + ], + exports: [ + AddressPage + ] +}) +export class AddressPageModule {} diff --git a/app/src/pages/address/address.scss b/app/src/pages/address/address.scss new file mode 100644 index 0000000..b081ff6 --- /dev/null +++ b/app/src/pages/address/address.scss @@ -0,0 +1,3 @@ +page-address { + +} diff --git a/app/src/pages/address/address.ts b/app/src/pages/address/address.ts new file mode 100644 index 0000000..e392a33 --- /dev/null +++ b/app/src/pages/address/address.ts @@ -0,0 +1,43 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams } from 'ionic-angular'; +import { Http } from '@angular/http'; +import { ApiProvider } from '../../providers/api/api'; + +/** + * Generated class for the AddressPage page. + * + * See http://ionicframework.com/docs/components/#navigation for more info + * on Ionic pages and navigation. + */ +@IonicPage({ + name: 'address', + segment: 'address/:addrStr' +}) +@Component({ + selector: 'page-address', + templateUrl: 'address.html' +}) +export class AddressPage { + + public loading: boolean = true; + private addrStr: string; + public address: any = {}; + + constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, private api: ApiProvider) { + this.addrStr = navParams.get('addrStr'); + } + + public ionViewDidLoad(): void { + this.http.get(this.api.apiPrefix + 'addr/' + this.addrStr + '/?noTxList=1').subscribe( + (data) => { + this.address = JSON.parse(data['_body']); + this.loading = false; + }, + (err) => { + console.log('err is', err); + this.loading = false; + } + ); + } + +} diff --git a/app/src/pages/block-detail/block-detail.html b/app/src/pages/block-detail/block-detail.html index 428a119..354ef77 100644 --- a/app/src/pages/block-detail/block-detail.html +++ b/app/src/pages/block-detail/block-detail.html @@ -1,41 +1,98 @@ - - - - Block Detail - - + - -

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 }}

+

Block #{{ block.height }}

+

BlockHash {{ block.hash }}

-

Transactions

- -
-
-

Loading...

+

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

+ +
+ diff --git a/app/src/pages/block-detail/block-detail.module.ts b/app/src/pages/block-detail/block-detail.module.ts index 1a14b2f..1c835b5 100644 --- a/app/src/pages/block-detail/block-detail.module.ts +++ b/app/src/pages/block-detail/block-detail.module.ts @@ -1,15 +1,17 @@ import { NgModule } from '@angular/core'; import { IonicPageModule } from 'ionic-angular'; import { BlockDetailPage } from './block-detail'; -import { TransactionsComponent } from '../../components/transactions/transactions'; +import { TransactionListComponentModule } from '../../components/transaction-list/transaction-list.module'; +import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module'; @NgModule({ declarations: [ - BlockDetailPage, - TransactionsComponent + BlockDetailPage ], imports: [ - IonicPageModule.forChild(BlockDetailPage) + IonicPageModule.forChild(BlockDetailPage), + TransactionListComponentModule, + HeadNavComponentModule ], exports: [ BlockDetailPage diff --git a/app/src/pages/block-detail/block-detail.ts b/app/src/pages/block-detail/block-detail.ts index bcd5983..66053d5 100644 --- a/app/src/pages/block-detail/block-detail.ts +++ b/app/src/pages/block-detail/block-detail.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; import { IonicPage, NavController, NavParams } from 'ionic-angular'; import { Http } from '@angular/http'; +import { ApiProvider } from '../../providers/api/api'; /** * Generated class for the BlockDetailPage page. @@ -24,12 +25,10 @@ export class BlockDetailPage { tx: [] }; - constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams) { + constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams, private api: ApiProvider) { this.blockHash = navParams.get('blockHash'); - let apiPrefix: string = 'http://localhost:3001/insight-api/'; - - this.http.get(apiPrefix + 'block/' + this.blockHash).subscribe( + this.http.get(this.api.apiPrefix + 'block/' + this.blockHash).subscribe( (data) => { this.block = JSON.parse(data['_body']); this.loading = false; diff --git a/app/src/pages/blocksPage/blocksPage.html b/app/src/pages/blocksPage/blocksPage.html index 718c3bb..6e7d491 100644 --- a/app/src/pages/blocksPage/blocksPage.html +++ b/app/src/pages/blocksPage/blocksPage.html @@ -1,41 +1,32 @@ - - - {{title}} - - - - + - + - + Height + Timestamp + Transactions + Mined By + Size - - - Height - Transactions - Mined By - - - - - - #{{block.height}} - - - {{block.transactionCount}} transactions - - - {{block.poolName}} - - - - + + + {{block.height}} + + + {{ block.timestamp * 1000 | date:'medium' }} + + + {{block.transactionCount}} + + + {{block.poolName}} + + + {{ block.size }} + + + diff --git a/app/src/pages/blocksPage/blocksPage.spec.ts b/app/src/pages/blocksPage/blocksPage.spec.ts index 27921e3..4e8ace9 100644 --- a/app/src/pages/blocksPage/blocksPage.spec.ts +++ b/app/src/pages/blocksPage/blocksPage.spec.ts @@ -21,9 +21,11 @@ describe('Blocks', () => { expect(instance).toBeTruthy(); }); + /* it('has a search method', () => { spyOn(instance, 'search'); instance.search(); expect(instance.search).toHaveBeenCalled(); }); + */ }); diff --git a/app/src/pages/blocksPage/blocksPage.ts b/app/src/pages/blocksPage/blocksPage.ts index cd06daf..5f2eeaf 100644 --- a/app/src/pages/blocksPage/blocksPage.ts +++ b/app/src/pages/blocksPage/blocksPage.ts @@ -3,7 +3,6 @@ import { NavController } from 'ionic-angular'; import { Observable } from 'rxjs'; import { Block } from '../../models'; import { BlocksService } from '../../services'; -import { Http } from '@angular/http'; @Component({ templateUrl: './blocksPage.html' @@ -11,81 +10,22 @@ import { Http } from '@angular/http'; export class BlocksPage { - public loading: boolean; public title: string; public blocks: Observable; - public q: string; - public badQuery: boolean = false; - constructor(private navCtrl: NavController, private http: Http, private blocksService: BlocksService) { + constructor(private navCtrl: NavController, private blocksService: BlocksService) { this.title = 'Blocks'; this.blocks = blocksService.latestBlocks; - // this.blocks.subscribe((blocks) => { - // console.log(blocks); - // }); + this.blocks.subscribe((blocks) => { + console.log('blocks', blocks); + }); blocksService.getLatestBlocks(); } - public search(): void { - console.log('q is', this.q); - let apiPrefix: string = 'http://localhost:3001/insight-api/'; - this.http.get(apiPrefix + 'block/' + this.q).subscribe( - (data) => { - this.resetSearch(); - console.log('block', data); - }, - () => { - this.http.get(apiPrefix + 'tx/' + this.q).subscribe( - (data: any) => { - this.resetSearch(); - console.log('tx', data); - }, - () => { - this.http.get(apiPrefix + 'addr/' + this.q).subscribe( - (data: any) => { - this.resetSearch(); - console.log('addr', data); - }, - () => { - this.http.get(apiPrefix + 'block-index/' + this.q).subscribe( - function (data: any): void { - this.resetSearch(); - let parsedData: any = JSON.parse(data._body); - this.navCtrl.push('block-detail', { - 'blockHash': parsedData.blockHash - }); - }.bind(this), - function (): void { - this.loading = false; - this.reportBadQuery(); - }.bind(this) - ); - } - ); - } - ); - } - ); + public goToBlock(blockHash: string): void { + this.navCtrl.push('block-detail', { + 'blockHash': blockHash + }); } - private resetSearch(): void { - this.q = ''; - this.loading = false; - } - - /* tslint:disable:no-unused-variable */ - private reportBadQuery(): void { - this.badQuery = true; - console.log('badQuery', this.badQuery); - - setTimeout( - function (): void { - this.badQuery = false; - console.log('badQuery', this.badQuery); - }.bind(this), - 2000 - ); - }; - /* tslint:enable:no-unused-variable */ - } diff --git a/app/src/pages/pages.module.ts b/app/src/pages/pages.module.ts index fe59ce6..2da0e6a 100644 --- a/app/src/pages/pages.module.ts +++ b/app/src/pages/pages.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { IonicModule } from 'ionic-angular'; import { ComponentsModule } from '../components'; +import { HeadNavComponentModule } from '../components/head-nav/head-nav.module'; import { BlocksPage, BroadcastTxPage, @@ -15,7 +16,7 @@ import { NodeStatusPage, VerifyMessagePage ], - imports: [ IonicModule, ComponentsModule ], + imports: [ IonicModule, ComponentsModule, HeadNavComponentModule ], exports: [ // CustomComponent, ], diff --git a/app/src/pages/transaction/transaction.html b/app/src/pages/transaction/transaction.html new file mode 100644 index 0000000..26a1663 --- /dev/null +++ b/app/src/pages/transaction/transaction.html @@ -0,0 +1,42 @@ + + + + + +

Transaction

+

Transaction {{ tx.txid }}

+ +

Summary

+ + + + 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/pages/transaction/transaction.module.ts b/app/src/pages/transaction/transaction.module.ts new file mode 100644 index 0000000..b24dc21 --- /dev/null +++ b/app/src/pages/transaction/transaction.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { IonicPageModule } from 'ionic-angular'; +import { TransactionPage } from './transaction'; +import { TransactionComponentModule } from '../../components/transaction/transaction.module'; +import { HeadNavComponentModule } from '../../components/head-nav/head-nav.module'; + +@NgModule({ + declarations: [ + TransactionPage + ], + imports: [ + IonicPageModule.forChild(TransactionPage), + TransactionComponentModule, + HeadNavComponentModule + ], + exports: [ + TransactionPage + ] +}) +export class TransactionPageModule {} diff --git a/app/src/pages/transaction/transaction.scss b/app/src/pages/transaction/transaction.scss new file mode 100644 index 0000000..b7253af --- /dev/null +++ b/app/src/pages/transaction/transaction.scss @@ -0,0 +1,3 @@ +page-transaction { + +} diff --git a/app/src/pages/transaction/transaction.ts b/app/src/pages/transaction/transaction.ts new file mode 100644 index 0000000..0d3eabb --- /dev/null +++ b/app/src/pages/transaction/transaction.ts @@ -0,0 +1,48 @@ +import { Component } from '@angular/core'; +import { IonicPage, NavController, NavParams } from 'ionic-angular'; +import { Http } from '@angular/http'; +import { ApiProvider } from '../../providers/api/api'; + +/** + * Generated class for the TransactionPage page. + * + * See http://ionicframework.com/docs/components/#navigation for more info + * on Ionic pages and navigation. + */ +@IonicPage({ + name: 'transaction', + segment: 'tx/:txId' +}) +@Component({ + selector: 'page-transaction', + templateUrl: 'transaction.html' +}) +export class TransactionPage { + + public loading: boolean = true; + private txId: string; + public tx: any = {}; + + constructor(public navCtrl: NavController, public navParams: NavParams, private http: Http, private api: ApiProvider) { + this.txId = navParams.get('txId'); + } + + public ionViewDidLoad(): void { + this.http.get(this.api.apiPrefix + 'tx/' + this.txId).subscribe( + (data) => { + this.tx = JSON.parse(data['_body']); + this.loading = false; + }, + (err) => { + console.log('err is', err); + this.loading = false; + } + ); + } + + public goToBlock(blockHash: string): void { + this.navCtrl.push('block-detail', { + 'blockHash': blockHash + }); + } +} diff --git a/app/src/pipes/split/split.ts b/app/src/pipes/split/split.ts new file mode 100644 index 0000000..ab08efd --- /dev/null +++ b/app/src/pipes/split/split.ts @@ -0,0 +1,21 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +/** + * Generated class for the SplitPipe pipe. + * + * See https://angular.io/docs/ts/latest/guide/pipes.html for more info on + * Angular Pipes. + */ +@Pipe({ + name: 'split' +}) +export class SplitPipe implements PipeTransform { + /** + * Takes a value and makes it lowercase. + */ + public transform(value: string, delimiter: string): Array { + 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 new file mode 100644 index 0000000..31c1966 --- /dev/null +++ b/app/src/providers/api/api.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import { Http } from '@angular/http'; +import 'rxjs/add/operator/map'; + +/* + Generated class for the ApiProvider provider. + + See https://angular.io/docs/ts/latest/guide/dependency-injection.html + for more info on providers and Angular DI. +*/ +@Injectable() +export class ApiProvider { + + public apiPrefix: string = 'http://localhost:3001/insight-api/'; + + constructor(public http: Http) { + } + +} diff --git a/app/src/providers/currency/currency.spec.ts b/app/src/providers/currency/currency.spec.ts new file mode 100644 index 0000000..d1ef863 --- /dev/null +++ b/app/src/providers/currency/currency.spec.ts @@ -0,0 +1,78 @@ +/* tslint:disable:no-unused-variable */ +import { TestBed, ComponentFixture, inject } from '@angular/core/testing'; +import { HttpModule } from '@angular/http'; +import { CurrencyProvider } from './currency'; + +describe('CurrencyProvider', () => { + let currency; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + HttpModule + ], + providers: [ + CurrencyProvider + ] + }); + }); + + beforeEach(inject([CurrencyProvider], _cp => { + currency = _cp; + })); + + it('initialises', () => { + expect(currency).not.toBeNull(); + expect(currency.defaultCurrency).toBe('BTC'); + expect(currency.currencySymbol).toBe('BTC'); + expect(currency.factor).toBe(1); + }); + + it('sets currency by updating the symbol and changing the multiplication factor', () => { + currency.setCurrency('USD'); + expect(currency.currencySymbol).toBe('USD'); + expect(currency.factor).toEqual(1); + + currency.setCurrency('BTC'); + expect(currency.currencySymbol).toBe('BTC'); + expect(currency.factor).toEqual(1); + + currency.setCurrency('mBTC'); + expect(currency.currencySymbol).toBe('mBTC'); + expect(currency.factor).toEqual(1000); + + currency.setCurrency('bits'); + expect(currency.currencySymbol).toBe('bits'); + expect(currency.factor).toEqual(1000000); + }); + + it('rounds float using specified number of decimal places', () => { + let aFloat = 4.32943; + + expect(currency.roundFloat(aFloat, 2)).toBe(4.33); + expect(currency.roundFloat(aFloat, 3)).toBe(4.329); + expect(currency.roundFloat(aFloat, 4)).toBe(4.3294); + expect(currency.roundFloat(aFloat, 5)).toBe(4.32943); + + aFloat = 1234567890.09876543; + + expect(currency.roundFloat(aFloat, 2)).toBe(1234567890.10); + expect(currency.roundFloat(aFloat, 3)).toBe(1234567890.099); + expect(currency.roundFloat(aFloat, 4)).toBe(1234567890.0988); + expect(currency.roundFloat(aFloat, 5)).toBe(1234567890.09877); + expect(currency.roundFloat(aFloat, 6)).toBe(1234567890.098765); + expect(currency.roundFloat(aFloat, 7)).toBe(1234567890.0987654); + expect(currency.roundFloat(aFloat, 8)).toBe(1234567890.09876543); + }); + + it('gets proper conversion after changing currency', () => { + let aFloat = 12345.09876543; + expect(currency.getConversion(aFloat)).toBe('12345.09876543 BTC'); + + currency.setCurrency('mBTC'); + expect(currency.getConversion(aFloat)).toBe('12345098.76543 mBTC'); + + currency.setCurrency('bits'); + expect(currency.getConversion(aFloat)).toBe('12345098765.43 bits'); + }); +}); diff --git a/app/src/providers/currency/currency.ts b/app/src/providers/currency/currency.ts new file mode 100644 index 0000000..fe6f412 --- /dev/null +++ b/app/src/providers/currency/currency.ts @@ -0,0 +1,68 @@ +import { Injectable } from '@angular/core'; +import { Http } from '@angular/http'; +import 'rxjs/add/operator/map'; + +/* + Generated class for the CurrencyProvider provider. + + See https://angular.io/docs/ts/latest/guide/dependency-injection.html + for more info on providers and Angular DI. +*/ +@Injectable() +export class CurrencyProvider { + + private defaultCurrency: string; + private currencySymbol: string; + private factor: number = 1; + + constructor(public http: Http) { + this.defaultCurrency = 'BTC'; + this.currencySymbol = this.defaultCurrency; + } + + private roundFloat(aFloat: number, decimalPlaces: number): number { + return Math.round(aFloat * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces); + } + + public getConversion(value: number): string { + if (value === 0.00000000) return '0 ' + this.currencySymbol; // fix value to show + + let response: number; + + if (this.currencySymbol === 'USD') { + response = this.roundFloat((value * this.factor), 2); + } else if (this.currencySymbol === 'mBTC') { + this.factor = 1000; + response = this.roundFloat((value * this.factor), 5); + } else if (this.currencySymbol === 'bits') { + this.factor = 1000000; + response = this.roundFloat((value * this.factor), 2); + } else { // assumes currencySymbol is BTC + this.factor = 1; + response = this.roundFloat((value * this.factor), 8); + } + + return response + ' ' + this.currencySymbol; + } + + public setCurrency(currency: string): void { + this.currencySymbol = currency; + localStorage.setItem('insight-currency', currency); + + if (currency === 'USD') { + // TODO Replace this with call + /* + Currency.get({}, function(res) { + $rootScope.currency.factor = $rootScope.currency.bitstamp = res.data.bitstamp; + }); + */ + } else if (currency === 'mBTC') { + this.factor = 1000; + } else if (currency === 'bits') { + this.factor = 1000000; + } else { + this.factor = 1; + } + } + +} diff --git a/app/src/test.ts b/app/src/test.ts index 8ba1c44..5a0cc78 100644 --- a/app/src/test.ts +++ b/app/src/test.ts @@ -16,6 +16,8 @@ import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController import { ConfigMock, PlatformMock } from './mocks'; import { BlocksServiceMock } from './services/mocks'; import { BlocksService } from './services'; +import { ApiProvider } from './providers/api/api'; +import { HeadNavComponentModule } from './components/head-nav/head-nav.module'; // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. declare var __karma__: any; @@ -60,13 +62,15 @@ export class TestUtils { App, Form, Keyboard, DomController, MenuController, NavController, GestureController, {provide: Platform, useClass: PlatformMock}, {provide: Config, useClass: ConfigMock}, - {provide: BlocksService, useClass: BlocksServiceMock} + {provide: BlocksService, useClass: BlocksServiceMock}, + ApiProvider ], imports: [ FormsModule, IonicModule, ReactiveFormsModule, - HttpModule + HttpModule, + HeadNavComponentModule ] }); } diff --git a/app/yarn.lock b/app/yarn.lock index f03015a..53191d9 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -159,42 +159,46 @@ ws "1.1.1" xml2js "^0.4.17" -"@ionic/cli-plugin-cordova@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-cordova/-/cli-plugin-cordova-1.4.0.tgz#2d3dd7bbd7321e0f1994b6f1a217176f55145296" +"@ionic/cli-plugin-cordova@1.6.2": + version "1.6.2" + resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-cordova/-/cli-plugin-cordova-1.6.2.tgz#f71d10641df8b522f54f8274e0d5bc4dbb8b5208" dependencies: - "@ionic/cli-utils" "1.4.0" - chalk "^1.1.3" - xml2js "^0.4.17" + "@ionic/cli-utils" "1.7.0" + chalk "^2.0.0" + elementtree "^0.1.7" + tslib "^1.7.1" -"@ionic/cli-plugin-ionic-angular@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-ionic-angular/-/cli-plugin-ionic-angular-1.3.1.tgz#8985f5a520db97ed6206615464e173d086ecd1ea" +"@ionic/cli-plugin-ionic-angular@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@ionic/cli-plugin-ionic-angular/-/cli-plugin-ionic-angular-1.4.1.tgz#bb94b7ad61c2f79757b2dff041c0b7e2151777ec" dependencies: - "@ionic/cli-utils" "1.4.0" - chalk "^1.1.3" + "@ionic/cli-utils" "1.7.0" + chalk "^2.0.0" + tslib "^1.7.1" -"@ionic/cli-utils@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@ionic/cli-utils/-/cli-utils-1.4.0.tgz#78c70b69c3b98a463aa01ea507d7d01da3dfa675" +"@ionic/cli-utils@1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@ionic/cli-utils/-/cli-utils-1.7.0.tgz#05bdbf3e7533eeeee27d58f3adbfe26bf2bf0d1d" dependencies: - archiver "^1.3.0" - chalk "^1.1.3" - cross-spawn "^4.0.2" + archiver "^2.0.0" + chalk "^2.0.0" + ci-info "^1.0.0" + cross-spawn "^5.1.0" dargs "^5.1.0" - inquirer "^3.0.6" + dev-null "^0.1.1" + inquirer "^3.2.1" leek "0.0.24" lodash "^4.17.4" minimist "^1.2.0" ncp "^2.0.0" - os-name "^2.0.1" - rimraf "^2.5.4" - semver "^5.3.0" - slice-ansi "0.0.4" - string-width "^2.0.0" + semver "^5.4.1" + slice-ansi "^1.0.0" + string-width "^2.1.1" + strip-ansi "^4.0.0" superagent "^3.5.2" + tslib "^1.7.1" uuid "^3.0.1" - wrap-ansi "^2.1.0" + wrap-ansi "^3.0.1" "@ionic/storage@2.0.1": version "2.0.1" @@ -331,6 +335,12 @@ amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" +angular2-qrcode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/angular2-qrcode/-/angular2-qrcode-2.0.1.tgz#1b4e65c302694b5078ca06f71138f7e4367754dc" + dependencies: + qrious "^2.2.0" + ansi-escapes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" @@ -385,9 +395,9 @@ archiver-utils@^1.3.0: normalize-path "^2.0.0" readable-stream "^2.0.0" -archiver@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/archiver/-/archiver-1.3.0.tgz#4f2194d6d8f99df3f531e6881f14f15d55faaf22" +archiver@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-2.0.0.tgz#ffb73ecccd8dd65b0019e1180f78092a053d43c4" dependencies: archiver-utils "^1.3.0" async "^2.0.0" @@ -397,7 +407,7 @@ archiver@^1.3.0: readable-stream "^2.0.0" tar-stream "^1.5.0" walkdir "^0.0.11" - zip-stream "^1.1.0" + zip-stream "^1.2.0" are-we-there-yet@~1.1.2: version "1.1.4" @@ -1182,6 +1192,14 @@ caniuse-db@^1.0.30000529, caniuse-db@^1.0.30000618, caniuse-db@^1.0.30000634, ca version "1.0.30000697" resolved "https://registry.yarnpkg.com/caniuse-db/-/caniuse-db-1.0.30000697.tgz#20ce6a9ceeef4ef4a15dc8e80f2e8fb9049e8d77" +canvas@^1.6.5: + version "1.6.6" + resolved "https://registry.yarnpkg.com/canvas/-/canvas-1.6.6.tgz#1c7af9e07d003dd082698b4a4e027773281029ca" + dependencies: + nan "^2.4.0" + parse-css-font "^2.0.2" + units-css "^0.4.0" + caseless@~0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.11.0.tgz#715b96ea9841593cc33067923f5ec60ebda4f7d7" @@ -1207,6 +1225,14 @@ chalk@1.1.3, chalk@^1.0.0, chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" +chalk@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + chalk@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" @@ -1245,6 +1271,10 @@ chokidar@^1.4.1, chokidar@^1.4.3, chokidar@^1.6.0, chokidar@^1.6.1: optionalDependencies: fsevents "^1.0.0" +ci-info@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.0.0.tgz#dc5285f2b4e251821683681c381c3388f46ec534" + cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.3.tgz#eeabf194419ce900da3018c207d212f2a6df0a07" @@ -1591,11 +1621,12 @@ cross-spawn@^3.0.0: lru-cache "^4.0.1" which "^1.2.9" -cross-spawn@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" dependencies: lru-cache "^4.0.1" + shebang-command "^1.2.0" which "^1.2.9" cryptiles@2.x.x: @@ -1623,6 +1654,32 @@ css-color-names@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" +css-font-size-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-font-size-keywords/-/css-font-size-keywords-1.0.0.tgz#854875ace9aca6a8d2ee0d345a44aae9bb6db6cb" + +css-font-stretch-keywords@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/css-font-stretch-keywords/-/css-font-stretch-keywords-1.0.1.tgz#50cee9b9ba031fb5c952d4723139f1e107b54b10" + +css-font-style-keywords@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/css-font-style-keywords/-/css-font-style-keywords-1.0.1.tgz#5c3532813f63b4a1de954d13cea86ab4333409e4" + +css-font-weight-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-font-weight-keywords/-/css-font-weight-keywords-1.0.0.tgz#9bc04671ac85bc724b574ef5d3ac96b0d604fd97" + +css-global-keywords@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/css-global-keywords/-/css-global-keywords-1.0.1.tgz#72a9aea72796d019b1d2a3252de4e5aaa37e4a69" + +css-list-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/css-list-helpers/-/css-list-helpers-1.0.1.tgz#fff57192202db83240c41686f919e449a7024f7d" + dependencies: + tcomb "^2.5.0" + css-loader@^0.28.1: version "0.28.4" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-0.28.4.tgz#6cf3579192ce355e8b38d5f42dd7a1f2ec898d0f" @@ -1663,6 +1720,10 @@ css-selector-tokenizer@^0.7.0: fastparse "^1.1.1" regexpu-core "^1.0.0" +css-system-font-keywords@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz#85c6f086aba4eb32c571a3086affc434b84823ed" + css-what@2.1: version "2.1.0" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.0.tgz#9467d032c38cfaefb9f2d79501253062f87fa1bd" @@ -1840,6 +1901,10 @@ detect-node@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" +dev-null@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dev-null/-/dev-null-0.1.1.tgz#5a205ce3c2b2ef77b6238d6ba179eb74c6a0e818" + di@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/di/-/di-0.0.1.tgz#806649326ceaa7caa3306d75d985ea2748ba913c" @@ -1959,6 +2024,12 @@ electron-to-chromium@^1.2.7: version "1.3.15" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.15.tgz#08397934891cbcfaebbd18b82a95b5a481138369" +elementtree@^0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/elementtree/-/elementtree-0.1.7.tgz#9ac91be6e52fb6e6244c4e54a4ac3ed8ae8e29c0" + dependencies: + sax "1.1.4" + elliptic@^6.0.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -2966,7 +3037,7 @@ inline-process-browser@^1.0.0: falafel "^1.0.1" through2 "^0.6.5" -inquirer@^3.0.0, inquirer@^3.0.6: +inquirer@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.1.1.tgz#87621c4fba4072f48a8dd71c9f9df6f100b2d534" dependencies: @@ -2985,6 +3056,25 @@ inquirer@^3.0.0, inquirer@^3.0.6: strip-ansi "^3.0.0" through "^2.3.6" +inquirer@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.1.tgz#06ceb0f540f45ca548c17d6840959878265fa175" + dependencies: + ansi-escapes "^2.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + interpret@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.0.3.tgz#cbc35c62eeee73f19ab7b10a801511401afc0f90" @@ -3003,6 +3093,22 @@ ionic-angular@3.4.2: version "3.4.2" resolved "https://registry.yarnpkg.com/ionic-angular/-/ionic-angular-3.4.2.tgz#762631f1af78a5ae1c0aa0f4d23b31435142abe1" +ionic@3.7.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/ionic/-/ionic-3.7.0.tgz#a3c32174c6d5455c3bc74b6b9152e0f97dce23c8" + dependencies: + "@ionic/cli-utils" "1.7.0" + chalk "^2.0.0" + diff "^3.2.0" + minimist "^1.2.0" + opn "^5.1.0" + os-name "^2.0.1" + rimraf "^2.6.1" + semver "^5.3.0" + ssh-config "^1.0.1" + tar "^2.2.1" + tslib "^1.7.1" + ionicons@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ionicons/-/ionicons-3.0.0.tgz#40b8daf4fd7a31150bd002160f66496e22a98c3c" @@ -3182,6 +3288,10 @@ is-utf8@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + is@~0.2.6: version "0.2.7" resolved "https://registry.yarnpkg.com/is/-/is-0.2.7.tgz#3b34a2c48f359972f35042849193ae7264b63562" @@ -3206,6 +3316,10 @@ isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" +isnumeric@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/isnumeric/-/isnumeric-0.2.0.tgz#a2347ba360de19e33d0ffd590fddf7755cbf2e64" + isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" @@ -4019,7 +4133,7 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -nan@^2.3.0, nan@^2.3.2: +nan@^2.3.0, nan@^2.3.2, nan@^2.4.0: version "2.6.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.6.2.tgz#e4ff34e6c95fdfb5aecc08de6596f43605a7db45" @@ -4307,6 +4421,12 @@ opn@4.0.2, opn@^4.0.0: object-assign "^4.0.1" pinkie-promise "^2.0.0" +opn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.1.0.tgz#72ce2306a17dbea58ff1041853352b4a8fc77519" + dependencies: + is-wsl "^1.1.0" + optimist@^0.6.1, optimist@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -4390,6 +4510,20 @@ parse-asn1@^5.0.0: evp_bytestokey "^1.0.0" pbkdf2 "^3.0.3" +parse-css-font@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/parse-css-font/-/parse-css-font-2.0.2.tgz#7b60b060705a25a9b90b7f0ed493e5823248a652" + dependencies: + css-font-size-keywords "^1.0.0" + css-font-stretch-keywords "^1.0.1" + css-font-style-keywords "^1.0.1" + css-font-weight-keywords "^1.0.0" + css-global-keywords "^1.0.1" + css-list-helpers "^1.0.1" + css-system-font-keywords "^1.0.0" + tcomb "^2.5.0" + unquote "^1.1.0" + parse-glob@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" @@ -4912,6 +5046,12 @@ qjobs@^1.1.4: version "1.1.5" resolved "https://registry.yarnpkg.com/qjobs/-/qjobs-1.1.5.tgz#659de9f2cf8dcc27a1481276f205377272382e73" +qrious@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/qrious/-/qrious-2.3.0.tgz#ca7ce68a82099a67a90e4979f4b1cdf51ef32475" + optionalDependencies: + canvas "^1.6.5" + qs@6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.2.0.tgz#3b7848c03c2dece69a9522b0fae8c4126d745f3b" @@ -5399,6 +5539,10 @@ sax@0.6.x: version "0.6.1" resolved "https://registry.yarnpkg.com/sax/-/sax-0.6.1.tgz#563b19c7c1de892e09bfc4f2fc30e3c27f0952b9" +sax@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.1.4.tgz#74b6d33c9ae1e001510f179a91168588f1aedaa9" + sax@>=0.6.0, sax@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" @@ -5449,6 +5593,10 @@ selenium-webdriver@^2.53.2: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" +semver@^5.4.1: + version "5.4.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" + semver@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-2.3.2.tgz#b9848f25d6cf36333073ec9ef8856d42f1233e52" @@ -5590,9 +5738,11 @@ slash@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" +slice-ansi@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + dependencies: + is-fullwidth-code-point "^2.0.0" sntp@1.x.x: version "1.0.9" @@ -5761,6 +5911,10 @@ sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" +ssh-config@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ssh-config/-/ssh-config-1.0.1.tgz#38742116dced7d45f5362ca86af77130ccbebc8b" + sshpk@^1.7.0: version "1.13.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.13.1.tgz#512df6da6287144316dc4c18fe1cf1d940739be3" @@ -5829,6 +5983,13 @@ string-width@^2.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string_decoder@0.10, string_decoder@^0.10.25, string_decoder@~0.10.x: version "0.10.31" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" @@ -5988,6 +6149,10 @@ tar@^2.0.0, tar@^2.2.1: fstream "^1.0.2" inherits "2" +tcomb@^2.5.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tcomb/-/tcomb-2.7.0.tgz#10d62958041669a5d53567b9a4ee8cde22b1c2b0" + temp-write@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-2.1.0.tgz#59890918e0ef09d548aaa342f4bd3409d8404e96" @@ -6283,10 +6448,21 @@ uniqs@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" +units-css@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/units-css/-/units-css-0.4.0.tgz#d6228653a51983d7c16ff28f8b9dc3b1ffed3a07" + dependencies: + isnumeric "^0.2.0" + viewport-dimensions "^0.2.0" + unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" +unquote@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.0.tgz#98e1fc608b6b854c75afb1b95afc099ba69d942f" + unreachable-branch-transform@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz#d99cc4c6e746d264928845b611db54b0f3474caa" @@ -6399,6 +6575,10 @@ verror@1.3.6: dependencies: extsprintf "1.0.2" +viewport-dimensions@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/viewport-dimensions/-/viewport-dimensions-0.2.0.tgz#de740747db5387fd1725f5175e91bac76afdf36c" + vlq@^0.2.1: version "0.2.2" resolved "https://registry.yarnpkg.com/vlq/-/vlq-0.2.2.tgz#e316d5257b40b86bb43cb8d5fea5d7f54d6b0ca1" @@ -6622,13 +6802,20 @@ wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" -wrap-ansi@^2.0.0, wrap-ansi@^2.1.0: +wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" dependencies: string-width "^1.0.1" strip-ansi "^3.0.1" +wrap-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-3.0.1.tgz#288a04d87eda5c286e060dfe8f135ce8d007f8ba" + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -6787,7 +6974,7 @@ yn@^1.2.0: dependencies: object-assign "^4.1.1" -zip-stream@^1.1.0: +zip-stream@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-1.2.0.tgz#a8bc45f4c1b49699c6b90198baacaacdbcd4ba04" dependencies: