diff --git a/.gitignore b/.gitignore
index 93846b4..f471896 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,7 @@ results
build
node_modules
+package-lock.json
# extras
*.swp
@@ -47,3 +48,5 @@ public/css/main.css
README.html
po/*
!po/*.po
+
+mynode/
diff --git a/app/package.json b/app/package.json
index d59fbd2..99495df 100644
--- a/app/package.json
+++ b/app/package.json
@@ -37,11 +37,12 @@
"devDependencies": {
"@angular/cli": "1.1.2",
"@ionic/app-scripts": "1.3.7",
- "@ionic/cli-plugin-cordova": "1.4.0",
- "@ionic/cli-plugin-ionic-angular": "1.3.1",
+ "@ionic/cli-plugin-cordova": "1.5.0",
+ "@ionic/cli-plugin-ionic-angular": "1.4.0",
"@types/jasmine": "2.5.41",
"@types/node": "7.0.4",
"codecov": "2.2.0",
+ "ionic": "3.6.0",
"jasmine-core": "2.5.2",
"jasmine-spec-reporter": "3.2.0",
"karma": "1.4.1",
diff --git a/app/src/components/transactions/transactions.html b/app/src/components/transactions/transactions.html
new file mode 100644
index 0000000..4263992
--- /dev/null
+++ b/app/src/components/transactions/transactions.html
@@ -0,0 +1,48 @@
+
+
+
{{ 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
new file mode 100644
index 0000000..d60c200
--- /dev/null
+++ b/app/src/components/transactions/transactions.module.ts
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 0000000..0912214
--- /dev/null
+++ b/app/src/components/transactions/transactions.scss
@@ -0,0 +1,3 @@
+transactions {
+
+}
diff --git a/app/src/components/transactions/transactions.ts b/app/src/components/transactions/transactions.ts
new file mode 100644
index 0000000..4c594c2
--- /dev/null
+++ b/app/src/components/transactions/transactions.ts
@@ -0,0 +1,50 @@
+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/block-detail/block-detail.html b/app/src/pages/block-detail/block-detail.html
new file mode 100644
index 0000000..428a119
--- /dev/null
+++ b/app/src/pages/block-detail/block-detail.html
@@ -0,0 +1,41 @@
+
+
+
+
+ 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 }}
+
+
Transactions
+
+
+
+
diff --git a/app/src/pages/block-detail/block-detail.module.ts b/app/src/pages/block-detail/block-detail.module.ts
new file mode 100644
index 0000000..1a14b2f
--- /dev/null
+++ b/app/src/pages/block-detail/block-detail.module.ts
@@ -0,0 +1,18 @@
+import { NgModule } from '@angular/core';
+import { IonicPageModule } from 'ionic-angular';
+import { BlockDetailPage } from './block-detail';
+import { TransactionsComponent } from '../../components/transactions/transactions';
+
+@NgModule({
+ declarations: [
+ BlockDetailPage,
+ TransactionsComponent
+ ],
+ imports: [
+ IonicPageModule.forChild(BlockDetailPage)
+ ],
+ exports: [
+ BlockDetailPage
+ ]
+})
+export class BlockDetailPageModule {}
diff --git a/app/src/pages/block-detail/block-detail.scss b/app/src/pages/block-detail/block-detail.scss
new file mode 100644
index 0000000..95a60c5
--- /dev/null
+++ b/app/src/pages/block-detail/block-detail.scss
@@ -0,0 +1,3 @@
+page-block-detail {
+
+}
diff --git a/app/src/pages/block-detail/block-detail.ts b/app/src/pages/block-detail/block-detail.ts
new file mode 100644
index 0000000..bcd5983
--- /dev/null
+++ b/app/src/pages/block-detail/block-detail.ts
@@ -0,0 +1,60 @@
+import { Component } from '@angular/core';
+import { IonicPage, NavController, NavParams } from 'ionic-angular';
+import { Http } from '@angular/http';
+
+/**
+ * Generated class for the BlockDetailPage page.
+ *
+ * See http://ionicframework.com/docs/components/#navigation for more info
+ * on Ionic pages and navigation.
+ */
+@IonicPage({
+ name: 'block-detail',
+ segment: 'block/:blockHash'
+})
+@Component({
+ selector: 'page-block-detail',
+ templateUrl: 'block-detail.html'
+})
+export class BlockDetailPage {
+
+ public loading: boolean = true;
+ private blockHash: string;
+ public block: any = {
+ tx: []
+ };
+
+ constructor(public navCtrl: NavController, private http: Http, public navParams: NavParams) {
+ this.blockHash = navParams.get('blockHash');
+
+ let apiPrefix: string = 'http://localhost:3001/insight-api/';
+
+ this.http.get(apiPrefix + 'block/' + this.blockHash).subscribe(
+ (data) => {
+ this.block = JSON.parse(data['_body']);
+ this.loading = false;
+ },
+ (err) => {
+ console.log('err is', err);
+ this.loading = false;
+ }
+ );
+ }
+
+ public ionViewWillLeave(): void {
+ this.loading = true;
+ }
+
+ public goToPreviousBlock(): void {
+ this.navCtrl.push('block-detail', {
+ 'blockHash': this.block.previousblockhash
+ });
+ }
+
+ public goToNextBlock(): void {
+ this.navCtrl.push('block-detail', {
+ 'blockHash': this.block.nextblockhash
+ });
+ }
+
+}
diff --git a/app/src/pages/blocksPage/blocksPage.html b/app/src/pages/blocksPage/blocksPage.html
index 1449175..718c3bb 100644
--- a/app/src/pages/blocksPage/blocksPage.html
+++ b/app/src/pages/blocksPage/blocksPage.html
@@ -14,6 +14,9 @@
+
+
+
Height
diff --git a/app/src/pages/blocksPage/blocksPage.spec.ts b/app/src/pages/blocksPage/blocksPage.spec.ts
index 8cc55b0..27921e3 100644
--- a/app/src/pages/blocksPage/blocksPage.spec.ts
+++ b/app/src/pages/blocksPage/blocksPage.spec.ts
@@ -20,4 +20,10 @@ describe('Blocks', () => {
it('initializes', () => {
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 c7e83c6..cd06daf 100644
--- a/app/src/pages/blocksPage/blocksPage.ts
+++ b/app/src/pages/blocksPage/blocksPage.ts
@@ -3,6 +3,7 @@ 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'
@@ -10,11 +11,13 @@ import { BlocksService } from '../../services';
export class BlocksPage {
+ public loading: boolean;
public title: string;
public blocks: Observable;
+ public q: string;
+ public badQuery: boolean = false;
- constructor(private nav: NavController, private blocksService: BlocksService) {
- this.nav = nav;
+ constructor(private navCtrl: NavController, private http: Http, private blocksService: BlocksService) {
this.title = 'Blocks';
this.blocks = blocksService.latestBlocks;
// this.blocks.subscribe((blocks) => {
@@ -22,4 +25,67 @@ export class BlocksPage {
// });
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)
+ );
+ }
+ );
+ }
+ );
+ }
+ );
+ }
+
+ 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/broadcastTxPage/broadcastTxPage.html b/app/src/pages/broadcastTxPage/broadcastTxPage.html
index 600cbbe..0a3f19d 100644
--- a/app/src/pages/broadcastTxPage/broadcastTxPage.html
+++ b/app/src/pages/broadcastTxPage/broadcastTxPage.html
@@ -8,18 +8,24 @@
-
-
- This form can be used to broadcast a raw transaction in hex format over the Bitcoin network.
-
+
+
diff --git a/app/src/pages/broadcastTxPage/broadcastTxPage.spec.ts b/app/src/pages/broadcastTxPage/broadcastTxPage.spec.ts
index 7c771a3..cd15055 100644
--- a/app/src/pages/broadcastTxPage/broadcastTxPage.spec.ts
+++ b/app/src/pages/broadcastTxPage/broadcastTxPage.spec.ts
@@ -20,4 +20,10 @@ describe('BroadcastTxPage', () => {
it('initializes', () => {
expect(instance).toBeTruthy();
});
+
+ it('has a send method', () => {
+ spyOn(instance, 'send');
+ instance.send();
+ expect(instance.send).toHaveBeenCalled();
+ });
});
diff --git a/app/src/pages/broadcastTxPage/broadcastTxPage.ts b/app/src/pages/broadcastTxPage/broadcastTxPage.ts
index 63e28cd..40563ef 100644
--- a/app/src/pages/broadcastTxPage/broadcastTxPage.ts
+++ b/app/src/pages/broadcastTxPage/broadcastTxPage.ts
@@ -1,5 +1,6 @@
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
+import { FormBuilder, FormGroup, Validators } from '@angular/forms';
@Component({
templateUrl: './broadcastTxPage.html'
@@ -9,9 +10,22 @@ export class BroadcastTxPage {
public title: string;
private nav: NavController;
+ public transaction: string;
+ public txForm: FormGroup;
- constructor(nav: NavController) {
+ constructor(nav: NavController, public formBuilder: FormBuilder) {
this.nav = nav;
this.title = 'Broadcast Transaction';
+ this.txForm = formBuilder.group({
+ rawData: ['', Validators.pattern(/^[0-9A-Fa-f]+$/)]
+ });
+ }
+
+ public send(): void {
+ let postData: any = {
+ rawtx: this.transaction
+ };
+
+ console.log('the postData is', postData);
}
}
diff --git a/app/src/services/blocksService.spec.ts b/app/src/services/blocksService.spec.ts
index cf99bfb..f104a48 100644
--- a/app/src/services/blocksService.spec.ts
+++ b/app/src/services/blocksService.spec.ts
@@ -1,8 +1,8 @@
-import { BlocksService } from './blocksService';
-import { Block } from '../models';
-import { TestUtils } from '../test';
+// import { BlocksService } from './blocksService';
+// import { Block } from '../models';
+// import { TestUtils } from '../test';
-let blocks: BlocksService = null;
+// let blocks: BlocksService = null;
// describe('BlocksService', () => {
diff --git a/app/src/services/blocksService.ts b/app/src/services/blocksService.ts
index 747f49d..724b593 100644
--- a/app/src/services/blocksService.ts
+++ b/app/src/services/blocksService.ts
@@ -1,6 +1,6 @@
import { Http, Response } from '@angular/http';
import { Injectable } from '@angular/core';
-import { Observable, Subject } from 'rxjs';
+import { Subject } from 'rxjs';
import { Block, InsightBlockObject } from '../models';
@Injectable()
diff --git a/app/src/test.ts b/app/src/test.ts
index ee17df7..8ba1c44 100644
--- a/app/src/test.ts
+++ b/app/src/test.ts
@@ -11,7 +11,7 @@ import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { getTestBed, TestBed } from '@angular/core/testing';
import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
import { HttpModule } from '@angular/http';
-import { MockBackend } from '@angular/http/testing';
+// import { MockBackend } from '@angular/http/testing';
import { App, Config, Form, IonicModule, Keyboard, DomController, MenuController, NavController, Platform, GestureController } from 'ionic-angular';
import { ConfigMock, PlatformMock } from './mocks';
import { BlocksServiceMock } from './services/mocks';