From 44fb85ddb924e131180a2457f07abd59097e0b6d Mon Sep 17 00:00:00 2001 From: gz-c Date: Wed, 1 Aug 2018 10:48:14 +0800 Subject: [PATCH 01/25] Remove go1.8 from travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c09453f7..5249bfc0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: go go: - - "1.8" - "1.9" - "1.10" From a696c127e5763e26ccbd7e72faa07bf27c6dee35 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Tue, 7 Aug 2018 11:17:06 -0400 Subject: [PATCH 02/25] Remove CoinsFormatterComponent --- src/app/app.module.ts | 2 -- .../coins-formatter.component.html | 1 - .../coins-formatter.component.scss | 9 ------ .../coins-formatter.component.spec.ts | 24 --------------- .../coins-formatter.component.ts | 30 ------------------- .../address-detail.component.html | 14 ++++----- .../block-details.component.html | 6 ++-- .../pages/richlist/richlist.component.html | 2 +- .../transaction-detail.component.html | 4 +-- .../unconfirmed-transactions.component.html | 4 +-- .../unspent-outputs.component.html | 4 +-- .../unspent-outputs.component.ts | 2 +- 12 files changed, 18 insertions(+), 84 deletions(-) delete mode 100644 src/app/components/layout/coins-formatter/coins-formatter.component.html delete mode 100644 src/app/components/layout/coins-formatter/coins-formatter.component.scss delete mode 100644 src/app/components/layout/coins-formatter/coins-formatter.component.spec.ts delete mode 100644 src/app/components/layout/coins-formatter/coins-formatter.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index d2fa5d03..eb30b682 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -29,7 +29,6 @@ import { GenericHeaderComponent } from 'app/components/layout/generic-header/gen import { GenericFooterComponent } from 'app/components/layout/generic-footer/generic-footer.component'; import { ExplorerDatePipe } from 'app/pipes/explorer-date.pipe'; import { DatePipe } from '@angular/common'; -import { CoinsFormatterComponent } from 'app/components/layout/coins-formatter/coins-formatter.component'; import { DateFormatterComponent } from 'app/components/layout/date-formatter/date-formatter.component'; import { SearchService } from './services/search/search.service'; import { SearchComponent } from './components/pages/search/search.component'; @@ -109,7 +108,6 @@ const ROUTES = [ UnspentOutputsComponent, CopyButtonComponent, ExplorerDatePipe, - CoinsFormatterComponent, DateFormatterComponent, SearchComponent, ], diff --git a/src/app/components/layout/coins-formatter/coins-formatter.component.html b/src/app/components/layout/coins-formatter/coins-formatter.component.html deleted file mode 100644 index 0d201803..00000000 --- a/src/app/components/layout/coins-formatter/coins-formatter.component.html +++ /dev/null @@ -1 +0,0 @@ -{{integerPart | number:'1.0-0'}}.{{decimalPart}} \ No newline at end of file diff --git a/src/app/components/layout/coins-formatter/coins-formatter.component.scss b/src/app/components/layout/coins-formatter/coins-formatter.component.scss deleted file mode 100644 index 1b01652d..00000000 --- a/src/app/components/layout/coins-formatter/coins-formatter.component.scss +++ /dev/null @@ -1,9 +0,0 @@ -@import '../../../../assets/scss/_variables.scss'; - -.decimal-part { - font-size: 12px; -} - -.-white { - color: #f7f7f7; -} \ No newline at end of file diff --git a/src/app/components/layout/coins-formatter/coins-formatter.component.spec.ts b/src/app/components/layout/coins-formatter/coins-formatter.component.spec.ts deleted file mode 100644 index a8aa0767..00000000 --- a/src/app/components/layout/coins-formatter/coins-formatter.component.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { async, ComponentFixture, TestBed } from '@angular/core/testing'; -import { CoinsFormatterComponent } from 'app/components/layout/coins-formatter/coins-formatter.component'; - -describe('GenericHeaderComponent', () => { - let component: CoinsFormatterComponent; - let fixture: ComponentFixture; - - beforeEach(async(() => { - TestBed.configureTestingModule({ - declarations: [ CoinsFormatterComponent ] - }) - .compileComponents(); - })); - - beforeEach(() => { - fixture = TestBed.createComponent(CoinsFormatterComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should be created', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/src/app/components/layout/coins-formatter/coins-formatter.component.ts b/src/app/components/layout/coins-formatter/coins-formatter.component.ts deleted file mode 100644 index fb425280..00000000 --- a/src/app/components/layout/coins-formatter/coins-formatter.component.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { Component, Input } from '@angular/core'; - -@Component({ - selector: 'coins-formatter', - templateUrl: './coins-formatter.component.html', - styleUrls: ['./coins-formatter.component.scss'] -}) -export class CoinsFormatterComponent { - - integerPart: number = undefined; - decimalPart: string; - - @Input() - set amount(value: number | string) { - - if (value == undefined || value == null) return; - - const number = typeof value == "number" ? value : Number((value as string).replace(new RegExp(',', 'g'), '')); - - this.integerPart = Math.trunc(number); - - const decimal = Math.abs(number - this.integerPart); - if (decimal > 0) this.decimalPart = (Number(decimal.toFixed(6)) + '').split('.')[1]; - } - - @Input() - whiteText = false; - - constructor() { } -} diff --git a/src/app/components/pages/address-detail/address-detail.component.html b/src/app/components/pages/address-detail/address-detail.component.html index 0bf1af82..234ad081 100644 --- a/src/app/components/pages/address-detail/address-detail.component.html +++ b/src/app/components/pages/address-detail/address-detail.component.html @@ -7,8 +7,8 @@

{{ 'addressDetail.title' | translate }}

{{ 'general.address' | translate }}
{{ address ? address : loadingMsg }}
{{ 'addressDetail.txsNumber' | translate }}
{{ transactions ? transactions.length : loadingMsg }}
-
{{ 'addressDetail.totalReceived' | translate }}
{{'general.coinIdentifier' | translate}} {{loadingMsg}}
-
{{ 'addressDetail.currentBalance' | translate }}
{{'general.coinIdentifier' | translate}} {{loadingMsg}}
+
{{ 'addressDetail.totalReceived' | translate }}
{{ transactions ? ((totalReceived | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
+
{{ 'addressDetail.currentBalance' | translate }}
{{ transactions ? ((balance | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
{{ 'addressDetail.tools' | translate }}
{{ 'addressDetail.unspentOutputs' | translate }} {{ loadingMsg }}
@@ -34,7 +34,7 @@

{{ 'addressDetail.title' | translate }}


- {{ (transaction.balance<0?"":"+") }} {{ 'general.coinIdentifier' | translate }} ({{ 'txBoxes.pending' | translate }}) + {{ (transaction.balance<0?"":"+")+(transaction.balance | number:'1.0-6') }} {{ 'general.coinIdentifier' | translate }} ({{ 'txBoxes.pending' | translate }})
@@ -54,14 +54,14 @@

{{ 'addressDetail.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
{{ input.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
{{ 'txBoxes.outputs' | translate }}
{{ output.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
@@ -72,13 +72,13 @@

{{ 'addressDetail.title' | translate }}

{{ 'txBoxes.initialBalance' | translate }}: 
{{ 'txBoxes.initialBalanceShort' | translate }}: 
-
+
{{ transaction.initialBalance | number:'1.0-6' }}
{{ 'txBoxes.finalBalance' | translate }}: 
{{ 'txBoxes.finalBalanceShort' | translate }}: 
-
+
{{ transaction.finalBalance | number:'1.0-6' }}
diff --git a/src/app/components/pages/block-details/block-details.component.html b/src/app/components/pages/block-details/block-details.component.html index 11f560e3..aab00712 100644 --- a/src/app/components/pages/block-details/block-details.component.html +++ b/src/app/components/pages/block-details/block-details.component.html @@ -19,7 +19,7 @@

{{ 'blockDetails.title' | translate }}

{{ 'blockDetails.size' | translate }}
{{ block ? (block.size | number) + ' bytes' : loadingMsg }}
{{ 'blockDetails.hash' | translate }}
{{ block.hash }} {{ loadingMsg }}
{{ 'blockDetails.parentHash' | translate }}
{{ block.parent_hash }} {{ 'blockDetails.withoutParent' | translate }} {{ loadingMsg }}
-
{{ 'blockDetails.totalAmount' | translate }}
{{'general.coinIdentifier' | translate}} {{loadingMsg}}
+
{{ 'blockDetails.totalAmount' | translate }}
{{ block ? ((block.transactions | transactionsValue) | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate) : loadingMsg }}
@@ -57,14 +57,14 @@

{{ 'blockDetails.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
{{ input.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
{{ 'txBoxes.outputs' | translate }}
{{ output.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
diff --git a/src/app/components/pages/richlist/richlist.component.html b/src/app/components/pages/richlist/richlist.component.html index 0d7dbaaa..31322ec1 100644 --- a/src/app/components/pages/richlist/richlist.component.html +++ b/src/app/components/pages/richlist/richlist.component.html @@ -20,7 +20,7 @@

{{ 'richlist.title' | translate }}

{{ i+1 }}
{{ entry.address }}
-
+
{{ entry.coins | number:'1.0-6' }}
diff --git a/src/app/components/pages/transaction-detail/transaction-detail.component.html b/src/app/components/pages/transaction-detail/transaction-detail.component.html index 2b9c56b3..4553463c 100644 --- a/src/app/components/pages/transaction-detail/transaction-detail.component.html +++ b/src/app/components/pages/transaction-detail/transaction-detail.component.html @@ -43,14 +43,14 @@

{{ 'transactionDetail.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
{{ input.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
{{ 'txBoxes.outputs' | translate }}
{{ output.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
diff --git a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html index 4cab289f..5c93b169 100644 --- a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html +++ b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html @@ -43,14 +43,14 @@

{{ 'unconfirmedTx.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
{{ input.address }} -
{{ 'general.coins' | translate }}:
+
{{ 'general.coins' | translate }}: {{ input.coins | number:'1.0-6' }}
{{ 'txBoxes.outputs' | translate }}
{{ output.address }} -
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
diff --git a/src/app/components/pages/unspent-outputs/unspent-outputs.component.html b/src/app/components/pages/unspent-outputs/unspent-outputs.component.html index c3879542..8c927de7 100644 --- a/src/app/components/pages/unspent-outputs/unspent-outputs.component.html +++ b/src/app/components/pages/unspent-outputs/unspent-outputs.component.html @@ -3,7 +3,7 @@

{{ 'unspentOutputs.title' | translate }}

{{ 'unspentOutputs.address' | translate }}
{{ address }} {{ loadingMsg }}
{{ 'unspentOutputs.outputsNumber' | translate }}
{{ outputs ? outputs.head_outputs.length : loadingMsg }}
-
{{ 'unspentOutputs.total' | translate }}
{{'general.coinIdentifier' | translate}} {{loadingMsg}}
+
{{ 'unspentOutputs.total' | translate }}
{{ coins != null ? (coins | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate) : loadingMsg }}
@@ -35,7 +35,7 @@

{{ 'unspentOutputs.title' | translate }}

{{ output.hash }}
-
{{ 'general.coins' | translate }}: 
+
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
diff --git a/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts b/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts index 43cff7cd..5c719bb0 100644 --- a/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts +++ b/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts @@ -14,7 +14,7 @@ import { TranslateService } from '@ngx-translate/core'; export class UnspentOutputsComponent implements OnInit { address: string; outputs: GetCurrentBalanceResponse; - coins: number; + coins: number = null; loadingMsg = ""; longErrorMsg: string; From 31ba8d801788f9fc44a562391a76897405cd9ce1 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Tue, 7 Aug 2018 11:47:45 -0400 Subject: [PATCH 03/25] Fix style problems --- src/app/components/pages/richlist/richlist.component.scss | 5 +++++ src/styles.scss | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/app/components/pages/richlist/richlist.component.scss b/src/app/components/pages/richlist/richlist.component.scss index e69de29b..fd320fb1 100644 --- a/src/app/components/pages/richlist/richlist.component.scss +++ b/src/app/components/pages/richlist/richlist.component.scss @@ -0,0 +1,5 @@ +.table { + a { + text-decoration: none; + } +} \ No newline at end of file diff --git a/src/styles.scss b/src/styles.scss index 6ae9e0f0..6e0fedb7 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -44,7 +44,7 @@ h2 { padding-top: 0; } - > span:first-child { + > span:first-of-type { display: block; float: left; color: $gray; From 47e7db1cedce29143a3ffbfae7200256ee96e21c Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Tue, 14 Aug 2018 18:41:11 -0400 Subject: [PATCH 04/25] Add the /api/health endpoint --- explorer.go | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/explorer.go b/explorer.go index e1cedb29..a18a71c4 100644 --- a/explorer.go +++ b/explorer.go @@ -726,6 +726,35 @@ var apiEndpoints = []APIEndpoint{ } }`, }, + { + ExplorerPath: "/api/health", + SkycoinPath: "/health", + Description: "Returns information about the current state of the node.", + ExampleRequest: "/api/health", + ExampleResponse: `{ + "blockchain": { + "head": { + "seq": 21175, + "block_hash": "8a3e0aac619551ae009cfb28c2b36bb1300925f74da770d1512072314f6a4c80", + "previous_block_hash": "001eb7911b6a6ab7c75feb88726dd2bc8b87133aebc82201c4404537eb74f7ac", + "timestamp": 1523168686, + "fee": 2, + "version": 0, + "tx_body_hash": "36be8d70d1e9f70b340ea7ecf0b247c27086bad10568044c1196fe150f6cea1b" + }, + "unspents": 14750, + "unconfirmed": 0, + "time_since_last_block": "12m6s" + }, + "version": { + "version": "0.23.0", + "commit": "f61b4319c2f146a5ad86f7cbda26a1ba6a09998d", + "branch": "develop" + }, + "open_connections": 30, + "uptime": "13.686460853s" +}`, + }, } var docEndpoint APIEndpoint = APIEndpoint{ From c731b46c3a6e93df6a1310a43b3db0a44d4a5cb0 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Sun, 9 Sep 2018 14:13:17 -0400 Subject: [PATCH 05/25] Show coin hours --- e2e/address-detail/address-detail.e2e-spec.ts | 6 +- e2e/block-details/block-details.e2e-spec.ts | 2 +- .../transaction-detail.e2e-spec.ts | 2 +- explorer.go | 667 ++++++++++++++---- src/app/app.datatypes.ts | 293 +++----- .../address-detail.component.html | 6 +- .../address-detail.component.ts | 7 +- .../block-details.component.html | 5 +- .../transaction-detail.component.html | 5 +- .../unconfirmed-transactions.component.html | 5 +- src/app/services/api/api.service.ts | 20 +- src/app/services/explorer/explorer.service.ts | 60 +- src/assets/i18n/en.json | 6 +- 13 files changed, 692 insertions(+), 392 deletions(-) diff --git a/e2e/address-detail/address-detail.e2e-spec.ts b/e2e/address-detail/address-detail.e2e-spec.ts index 484b728e..a661d872 100644 --- a/e2e/address-detail/address-detail.e2e-spec.ts +++ b/e2e/address-detail/address-detail.e2e-spec.ts @@ -20,7 +20,7 @@ describe('skycoin-explorer Address Page', () => { }); it('should have 5 address details rows', () => { - expect(generalFunctions.getDetailsRowCount()).toEqual(5); + expect(generalFunctions.getDetailsRowCount()).toEqual(6); }); it('should have the correct address for small screens', () => { @@ -77,9 +77,9 @@ describe('skycoin-explorer Address Page', () => { it('should have the correct coins amount', () => { if (browser.params.chain == '180') { - expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(1318628); + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(1655151); } else { - expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(6.002); + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(158.002); } }); diff --git a/e2e/block-details/block-details.e2e-spec.ts b/e2e/block-details/block-details.e2e-spec.ts index c32819df..f523f269 100644 --- a/e2e/block-details/block-details.e2e-spec.ts +++ b/e2e/block-details/block-details.e2e-spec.ts @@ -53,7 +53,7 @@ describe('skycoin-explorer Block Details Page', () => { }); it('should have the correct coins amount', () => { - expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(1999980); + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(2013866); }); it('should display the "Previous block" button', () => { diff --git a/e2e/transaction-detail/transaction-detail.e2e-spec.ts b/e2e/transaction-detail/transaction-detail.e2e-spec.ts index f9d3ea8b..4e73789c 100644 --- a/e2e/transaction-detail/transaction-detail.e2e-spec.ts +++ b/e2e/transaction-detail/transaction-detail.e2e-spec.ts @@ -45,7 +45,7 @@ describe('skycoin-explorer Transaction Page', () => { }); it('should have the correct coins amount', () => { - expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(1999980); + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(2013866); }); it('should show the error message', () => { diff --git a/explorer.go b/explorer.go index a18a71c4..87ef9bf8 100644 --- a/explorer.go +++ b/explorer.go @@ -130,8 +130,9 @@ type APIEndpoint struct { QueryArgs []string `json:"query_args,omitempty"` Description string `json:"description"` ExampleRequest string `json:"example_request"` - // This string will be parsed into a map[string]interface{} in order to render newlines - ExampleResponse string `json:"-"` + // This strings will be parsed into a map[string]interface{} in order to render newlines + ExampleResponse string `json:"-"` + ExampleVerboseResponse string `json:"-"` } func (s APIEndpoint) ServeHTTP(w http.ResponseWriter, r *http.Request) { @@ -290,8 +291,8 @@ var apiEndpoints = []APIEndpoint{ { ExplorerPath: "/api/block", SkycoinPath: "/block", - QueryArgs: []string{"hash", "seq"}, - Description: "Returns information about a block, given a hash or sequence number.", + QueryArgs: []string{"hash", "seq", "verbose"}, + Description: "Returns information about a block, given a hash or sequence number. Assign 1 to the \"verbose\" argument to get more data in the response.", ExampleRequest: "/api/block?hash=e20d5832b3f9bea4da58e149e4805b4e4a962ea7c5ce3cd9f31c6d7fc72e3300", ExampleResponse: `{ "header": { @@ -338,14 +339,79 @@ var apiEndpoints = []APIEndpoint{ ] }, "size": 414 +}`, + ExampleVerboseResponse: `{ + "header": { + "seq": 1893, + "block_hash": "e20d5832b3f9bea4da58e149e4805b4e4a962ea7c5ce3cd9f31c6d7fc72e3300", + "previous_block_hash": "e99fe31adf3a15aab77eb81d7aaa5477a96d2ce7f74ccb3d4cdce4da2eb01cb2", + "timestamp": 1499405825, + "fee": 5033788, + "version": 0, + "tx_body_hash": "c297eb14a9e68ec5501aa886e5bb720a58fe6466be633a8264f61eee9580a2c3" + }, + "body": { + "txns": [ + { + "length": 414, + "type": 0, + "txid": "c297eb14a9e68ec5501aa886e5bb720a58fe6466be633a8264f61eee9580a2c3", + "inner_hash": "5fcc1649794894f2c79411a832f799ba12e0528ff530d7068abaa03c10e451cf", + "fee": 5033788, + "sigs": [ + "b951fd0c1528df88c87eb90cb1ecbc3ba2b6332ace16c2f1cc731976c0cebfb10ecb1c20335374f8cf0b832364a523c3e16f32c3240ed4eccfac1803caf8815100", + "6a06e57d130f6e780eecbe0c2626eed7724a2443438258598af287bf8fc1b87f041d04a7082550bd2055a08f0849419200fdac27c018d5cebf84e8bba1c4f61201", + "8cc9ae6ae5be81456fc8e2d54b6868c45b415556c689c8c4329cd30b671a18254885a1aef8a3ac9ab76a8dc83e08607516fdef291a003935ae4507775ae53c7800" + ], + "inputs": [ + { + "uxid": "0922a7b41d1b76b6b56bfad0d5d0f6845517bbd895c660eab0ebe3899b5f63c4", + "owner": "2Q2VViWhgBzz6c8GkXQyDVFdQUWcBcDon4L", + "coins": "7.000000", + "hours": 851106, + "calculated_hours": 851311 + }, + { + "uxid": "d73cf1f1d04a1d493fe3480a00e48187f9201bb64828fe0c638f17c0c88bb3d9", + "owner": "YPhukwVyLsPGX1FAPQa2ktr5XnSLqyGbr5", + "coins": "5.000000", + "hours": 6402335, + "calculated_hours": 6402335 + }, + { + "uxid": "16dd81af869743599fe60108c22d7ee1fcbf1a7f460fffd3a015fbb3f721c36d", + "owner": "YPhukwVyLsPGX1FAPQa2ktr5XnSLqyGbr5", + "coins": "2400.000000", + "hours": 800291, + "calculated_hours": 800291 + } + ], + "outputs": [ + { + "uxid": "8a941208d3f2d2c4a32438e05645fb64dba3b4b7d83c48d52f51bc1eb9a4117a", + "dst": "2GgFvqoyk9RjwVzj8tqfcXVXB4orBwoc9qv", + "coins": "2361.000000", + "hours": 1006716 + }, + { + "uxid": "a70d1f0f488066a327acd0d5ea77b87d62b3b061d3db8361c90194a6520ab29f", + "dst": "SeDoYN6SNaTiAZFHwArnFwQmcyz7ZvJm17", + "coins": "51.000000", + "hours": 2013433 + } + ] + } + ] + }, + "size": 414 }`, }, { ExplorerPath: "/api/blocks", SkycoinPath: "/blocks", - QueryArgs: []string{"start", "end"}, - Description: "Returns information about a range of blocks, given a start and end block sequence number. The range of blocks will include both the start and end sequence numbers.", + QueryArgs: []string{"start", "end", "verbose"}, + Description: "Returns information about a range of blocks, given a start and end block sequence number. The range of blocks will include both the start and end sequence numbers. Assign 1 to the \"verbose\" argument to get more data in the response.", ExampleRequest: "https://explorer.skycoin.net/api/blocks?start=1891&end=1892", ExampleResponse: `{ "blocks": [ @@ -400,8 +466,8 @@ var apiEndpoints = []APIEndpoint{ ] } ] - }, - "size": 802 + }, + "size": 802 }, { "header": { @@ -442,8 +508,158 @@ var apiEndpoints = []APIEndpoint{ ] } ] - }, - "size": 220 + }, + "size": 220 + } + ] +}`, + ExampleVerboseResponse: `{ + "blocks": [ + { + "header": { + "seq": 1891, + "block_hash": "015265e82b4a28eee364327bf0d3b51fed54c2067318029974c262478a09bf17", + "previous_block_hash": "71bf5abc05a4344597cf7df25249203df12e73b0a2e37dab386eb292a6cc5faa", + "timestamp": 1499402935, + "fee": 38414015, + "version": 0, + "tx_body_hash": "ac9759e9ffc3450d9af92e205f909375131df64e8f158a26e5e1e15334f45c8d" + }, + "body": { + "txns": [ + { + "length": 802, + "type": 0, + "txid": "ac9759e9ffc3450d9af92e205f909375131df64e8f158a26e5e1e15334f45c8d", + "inner_hash": "cd36c8a00ff1fa81d94747b2d64107657fa40fa43bb0e5afc70d16661eca4286", + "fee": 38414015, + "sigs": [ + "d34f0a9f0b82028e44702c7fc694e35aeb2777630efaaae32b9854b6c59c9ad747bdb91111864a050f024efd325a744cbbb7c1dde55a776c8f0d4856ac07fa5801", + "aa2f3ec98866bafda37f6e0b52be6fd1201131ce6b7edf1988b762edf14c35880b26a3a3fe9369a0f9eedecbe958abae83e54d572440903f5ff5b11cb9eb5e9200", + "746e171c22c99939d2d7e4b615f98de74f1c6ae152cb3d1e17e4d5e25d6f52b444242080a5a3d8f36de3befb8ec915321a7cb282eafc661c0857de753a6b40e100", + "e4f3db5afa209cbceac814d0f5c6fff8b57a3cc5c15063cd0b390067705de0a87313488d5eabd369855a87879a8d163fce08faeacd9d6538528d29c7cdbdaedf00", + "038263cdaf43a544b4ef66b2c910b9dd807ecd55e2fbf513c776b7accb1ff1fb5f591fbba22af58cf399d743955ab6cc7e3e641ecc675253306b2d0b6570672f00", + "215d1527af817f9c0613cacc3c2d07873ff563ab113023fc83ea836e3ac827f240df8a3d390d8e867cdda149d0db8f86bf435fa354dc4f3ac8c3a9b39297d7ba00", + "a2d7a50176ac1ca9417ca35f9848621bc3e0aeacb0cce713e9f93d82db4988ac5bca5bf02610c64f1580b198aadf49b04a14542466f7dca49d73b6c70f2577a201" + ], + "inputs": [ + { + "uxid": "e72d8ba4ce2d3b37aeb71df2e3bed80ee07204b3fa633f56cbce7bca836bd39c", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "3.000000", + "hours": 0, + "calculated_hours": 58814 + }, + { + "uxid": "6a349ba12c5d2827de6c24773d3dd8f6572e86adba4c8954a6d6e68df9e165e2", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "2400.000000", + "hours": 348891, + "calculated_hours": 44390964 + }, + { + "uxid": "bb9a579003de101bee76d83d4f8796b97b34ba55555c9729a14919648c3dd7bc", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "2.000000", + "hours": 2442307, + "calculated_hours": 2442329 + }, + { + "uxid": "6232b9b399cd86c7c0b42f9780728dea59f47565cd451010eda90e002079cdfe", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "100.000000", + "hours": 2437264, + "calculated_hours": 2438357 + }, + { + "uxid": "d30ded9d1e3b0067d667a2a04fdacff895099ca7371d20d36d6e6565a4180e10", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "500.000000", + "hours": 1252147, + "calculated_hours": 1257601 + }, + { + "uxid": "f248f84f019e573ba913827b9e55ef57cdd21d622b7000ff4d89d303ca2e7c20", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "900.000000", + "hours": 304661, + "calculated_hours": 314456 + }, + { + "uxid": "0e64b71334792a5e6170fd526bab7f0abb3b5a1ef0912d8b273f59c6e3ff0d75", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "1000.000000", + "hours": 305303, + "calculated_hours": 316164 + } + ], + "outputs": [ + { + "uxid": "ce1075dd609622b0c28d4106f58943d7f0cae6baffbe9f048bb5bc5f23706b93", + "dst": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "4900.000000", + "hours": 6402335 + }, + { + "uxid": "d73cf1f1d04a1d493fe3480a00e48187f9201bb64828fe0c638f17c0c88bb3d9", + "dst": "YPhukwVyLsPGX1FAPQa2ktr5XnSLqyGbr5", + "coins": "5.000000", + "hours": 6402335 + } + ] + } + ] + }, + "size": 802 + }, + { + "header": { + "seq": 1892, + "block_hash": "e99fe31adf3a15aab77eb81d7aaa5477a96d2ce7f74ccb3d4cdce4da2eb01cb2", + "previous_block_hash": "015265e82b4a28eee364327bf0d3b51fed54c2067318029974c262478a09bf17", + "timestamp": 1499403255, + "fee": 4801753, + "version": 0, + "tx_body_hash": "b3c6f0f87c5282ff7ff5e6d637c2581e6a56826a76ec3dd221d02786881e3d14" + }, + "body": { + "txns": [ + { + "length": 220, + "type": 0, + "txid": "b3c6f0f87c5282ff7ff5e6d637c2581e6a56826a76ec3dd221d02786881e3d14", + "inner_hash": "3dde2cd3b6562e229e99e1a0c3d87be89ab42bb773343d1471a9627cd004fc67", + "fee": 4801753, + "sigs": [ + "22557281582f7daaf07fc79cd1c33438c06788c8561cf2fee96d81d46ffe827f44d57e0cadeb80662ea5b720c4062d5b72827dc72ea9db7afefbfe644aefea2d00" + ], + "inputs": [ + { + "uxid": "ce1075dd609622b0c28d4106f58943d7f0cae6baffbe9f048bb5bc5f23706b93", + "owner": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "4900.000000", + "hours": 6402335, + "calculated_hours": 6402335 + } + ], + "outputs": [ + { + "uxid": "c8b8eac053a5640bae40144cbc3dda02746071e3c7d00a4b5dfd06d28f928ec4", + "dst": "PRXLNyB64cqaiG4pCoFZZ8Tuv7LWYPpa7m", + "coins": "2500.000000", + "hours": 800291 + }, + { + "uxid": "16dd81af869743599fe60108c22d7ee1fcbf1a7f460fffd3a015fbb3f721c36d", + "dst": "YPhukwVyLsPGX1FAPQa2ktr5XnSLqyGbr5", + "coins": "2400.000000", + "hours": 800291 + } + ] + } + ] + }, + "size": 220 } ] }`, @@ -487,8 +703,8 @@ var apiEndpoints = []APIEndpoint{ { ExplorerPath: "/api/transaction", SkycoinPath: "/transaction", - QueryArgs: []string{"txid"}, - Description: "Returns transaction metadata.", + QueryArgs: []string{"txid", "verbose"}, + Description: "Returns transaction metadata. Assign 1 to the \"verbose\" argument to get more data in the response.", ExampleRequest: "/api/transaction?txid=edd2de176948cbd27cdd8cba7ca4b5afb8dbf8174dd6de95f73ce359affe4f05", ExampleResponse: `{ "status": { @@ -526,6 +742,49 @@ var apiEndpoints = []APIEndpoint{ } ] } +}`, + ExampleVerboseResponse: `{ + "status": { + "confirmed": true, + "unconfirmed": false, + "height": 55518, + "block_seq": 1747 + }, + "time": 1498734315, + "txn": { + "timestamp": 1498734315, + "length": 220, + "type": 0, + "txid": "edd2de176948cbd27cdd8cba7ca4b5afb8dbf8174dd6de95f73ce359affe4f05", + "inner_hash": "1a0b3794925960bc4a61fc1deebbdb48879f2272cdf7247e62d97b3f9df6ba72", + "fee": 16308, + "sigs": [ + "642a1443755bc949114b2c1a02cdf70d996a96c4971428fca39515b4143bb04b5a1922faeb45f7201fe10e40f162eeed61802fc55345ae7b9fcd12cc1a36f7b101" + ], + "inputs": [ + { + "uxid": "8aab2420737e710430e95823e4853b5b9f36ab8afb679a6963564be34bfa87a4", + "owner": "2b3974pDXkdHR6VGQvVZc1iZBzrJtNfAHPY", + "coins": "1537.000000", + "hours": 12150, + "calculated_hours": 20863 + } + ], + "outputs": [ + { + "uxid": "a72bebed7cf5fab28a4f57e525de5c22a34b3bd2a3bca0074e6658d618969ab0", + "dst": "2GgFvqoyk9RjwVzj8tqfcXVXB4orBwoc9qv", + "coins": "1513.000000", + "hours": 1518 + }, + { + "uxid": "51a9abaf13e3b404902698e6841738e7e054b59127733c60a5edd3a67c596f6d", + "dst": "2dbpXFWsbTRRACGMcvinhKcWyXybMbv5yx8", + "coins": "24.000000", + "hours": 3037 + } + ] + } }`, }, @@ -551,44 +810,86 @@ var apiEndpoints = []APIEndpoint{ { ExplorerPath: "/api/pendingTxs", SkycoinPath: "/pendingTxs", - Description: "Returns the unconfirmed transactions in the pool.", + QueryArgs: []string{"verbose"}, + Description: "Returns the unconfirmed transactions in the pool. Assign 1 to the \"verbose\" argument to get more data in the response.", ExampleRequest: "/api/pendingTxs", ExampleResponse: `[ - { - "transaction": { - "length": 317, - "type": 0, - "txid": "89578005d8730fe1789288ee7dea036160a9bd43234fb673baa6abd91289a48b", - "inner_hash": "cac977eee019832245724aa643ceff451b9d8b24612b2f6a58177c79e8a4c26f", - "sigs": [ - "3f084a0c750731dd985d3137200f9b5fc3de06069e62edea0cdd3a91d88e56b95aff5104a3e797ab4d6d417861af0c343efb0fff2e5ba9e7cf88ab714e10f38101", - "e9a8aa8860d189daf0b1dbfd2a4cc309fc0c7250fa81113aa7258f9603d19727793c1b7533131605db64752aeb9c1f4465198bb1d8dd597213d6406a0a81ed3701" - ], - "inputs": [ - "bb89d4ed40d0e6e3a82c12e70b01a4bc240d2cd4f252cfac88235abe61bd3ad0", - "170d6fd7be1d722a1969cb3f7d45cdf4d978129c3433915dbaf098d4f075bbfc" - ], - "outputs": [ - { - "uxid": "ec9cf2f6052bab24ec57847c72cfb377c06958a9e04a077d07b6dd5bf23ec106", - "dst": "nu7eSpT6hr5P21uzw7bnbxm83B6ywSjHdq", - "coins": "60.000000", - "hours": 2458 - }, - { - "uxid": "be40210601829ba8653bac1d6ecc4049955d97fb490a48c310fd912280422bd9", - "dst": "2iVtHS5ye99Km5PonsB42No3pQRGEURmxyc", - "coins": "1.000000", - "hours": 2458 - } - ] + { + "transaction": { + "length": 317, + "type": 0, + "txid": "89578005d8730fe1789288ee7dea036160a9bd43234fb673baa6abd91289a48b", + "inner_hash": "cac977eee019832245724aa643ceff451b9d8b24612b2f6a58177c79e8a4c26f", + "sigs": [ + "3f084a0c750731dd985d3137200f9b5fc3de06069e62edea0cdd3a91d88e56b95aff5104a3e797ab4d6d417861af0c343efb0fff2e5ba9e7cf88ab714e10f38101", + "e9a8aa8860d189daf0b1dbfd2a4cc309fc0c7250fa81113aa7258f9603d19727793c1b7533131605db64752aeb9c1f4465198bb1d8dd597213d6406a0a81ed3701" + ], + "inputs": [ + "bb89d4ed40d0e6e3a82c12e70b01a4bc240d2cd4f252cfac88235abe61bd3ad0", + "170d6fd7be1d722a1969cb3f7d45cdf4d978129c3433915dbaf098d4f075bbfc" + ], + "outputs": [ + { + "uxid": "ec9cf2f6052bab24ec57847c72cfb377c06958a9e04a077d07b6dd5bf23ec106", + "dst": "nu7eSpT6hr5P21uzw7bnbxm83B6ywSjHdq", + "coins": "60.000000", + "hours": 2458 }, - "received": "2017-05-09T10:11:57.14303834+02:00", - "checked": "2017-05-09T10:19:58.801315452+02:00", - "announced": "0001-01-01T00:00:00Z", - "is_valid": true - } - ]`, + { + "uxid": "be40210601829ba8653bac1d6ecc4049955d97fb490a48c310fd912280422bd9", + "dst": "2iVtHS5ye99Km5PonsB42No3pQRGEURmxyc", + "coins": "1.000000", + "hours": 2458 + } + ] + }, + "received": "2017-05-09T10:11:57.14303834+02:00", + "checked": "2017-05-09T10:19:58.801315452+02:00", + "announced": "0001-01-01T00:00:00Z", + "is_valid": true + } +]`, + ExampleVerboseResponse: `[ + { + "transaction": { + "length": 220, + "type": 0, + "txid": "d455564dcf1fb666c3846cf579ff33e21c203e2923938c6563fe7fcb8573ba44", + "inner_hash": "4e73155db8ed04a3bd2b953218efcc9122ebfbf4c55f08f50d1563e48eacf71d", + "fee": 12855964, + "sigs": [ + "17330c256a50e2117ddccf51f1980fc14380f0f9476432196ade3043668759847b97e1b209961458745684d9239541f79d9ca9255582864d30a540017ab84f2b01" + ], + "inputs": [ + { + "uxid": "27e7bc48ceca4d47e806a87100a8a98592b7618702e1cd479bf4c190462a6d09", + "owner": "23MjQipM9YsPKkYiuaBmf6m7fD54wrzHxpd", + "coins": "7815.000000", + "hours": 279089, + "calculated_hours": 13101146 + } + ], + "outputs": [ + { + "uxid": "4b4ebf62acbaece798d0dfc92fcea85768a2874dad8a9b8eb5454288deae468c", + "dst": "23MjQipM9YsPKkYiuaBmf6m7fD54wrzHxpd", + "coins": "586.000000", + "hours": 122591 + }, + { + "uxid": "781cfb134d5fdad48f3c937dfcfc66b169a305adc8abdfe92a0ec94c564913f2", + "dst": "2ehrG4VKLRuvBNWYz3U7tS75QWvzyWR89Dg", + "coins": "7229.000000", + "hours": 122591 + } + ] + }, + "received": "2018-06-20T14:14:52.415702671+08:00", + "checked": "2018-08-26T19:47:45.328131142+08:00", + "announced": "2018-08-26T19:51:47.356083569+08:00", + "is_valid": true + } +]`, }, { ExplorerPath: "/api/richlist", @@ -633,81 +934,171 @@ var apiEndpoints = []APIEndpoint{ { ExplorerPath: "/api/transactions", SkycoinPath: "/transactions", - QueryArgs: []string{"addrs", "confirmed"}, - Description: "Returns transactions for a list of comma-separated addresses. If no addresses are specified, returns all transactions.", + QueryArgs: []string{"addrs", "confirmed", "verbose"}, + Description: "Returns transactions for a list of comma-separated addresses. If no addresses are specified, returns all transactions. Assign 1 to the \"verbose\" argument to get more data in the response.", ExampleRequest: "/api/transactions?addrs=7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD,6dkVxyKFbFKg9Vdg6HPg1UANLByYRqkrdY&confirmed=1", ExampleResponse: `[ - { - "status": { - "confirmed": true, - "unconfirmed": false, - "height": 10492, - "block_seq": 1177, - "unknown": false - }, - "time": 1494275011, - "txn": { - "length": 317, - "type": 0, - "txid": "b09cd3a8baef6a449848f50a1b97943006ca92747d4e485d0647a3ea74550eca", - "inner_hash": "2cb370051c92521a04ba5357e229d8ffa90d9d1741ea223b44dd60a1483ee0e5", - "timestamp": 1494275011, - "sigs": [ - "a55155ca15f73f0762f79c15917949a936658cff668647daf82a174eed95703a02622881f9cf6c7495536676f931b2d91d389a9e7b034232b3a1519c8da6fb8800", - "cc7d7cbd6f31adabd9bde2c0deaa9277c0f3cf807a4ec97e11872817091dc3705841a6adb74acb625ee20ab6d3525350b8663566003276073d94c3bfe22fe48e01" - ], - "inputs": [ - "4f4b0078a9cd19b3395e54b3f42af6adc997f77f04e0ca54016c67c4f2384e3c", - "36f4871646b6564b2f1ab72bd768a67579a1e0242bc68bcbcf1779bc75b3dddd" - ], - "outputs": [ - { - "uxid": "5287f390628909dd8c25fad0feb37859c0c1ddcf90da0c040c837c89fefd9191", - "dst": "2K6NuLBBapWndAssUtkxKfCtyjDQDHrEhhT", - "coins": "8.000000", - "hours": 7454 - }, - { - "uxid": "a1268e9bd2033b49b44afa765d20876467254f51e5515626780467267a65c563", - "dst": "7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD", - "coins": "1.000000", - "hours": 7454 - } - ] - } - }, - { - "status": { - "confirmed": true, - "unconfirmed": false, - "height": 10491, - "block_seq": 1178, - "unknown": false - }, - "time": 1494275231, - "txn": { - "length": 183, - "type": 0, - "txid": "a6446654829a4a844add9f181949d12f8291fdd2c0fcb22200361e90e814e2d3", - "inner_hash": "075f255d42ddd2fb228fe488b8b468526810db7a144aeed1fd091e3fd404626e", - "timestamp": 1494275231, - "sigs": [ - "9b6fae9a70a42464dda089c943fafbf7bae8b8402e6bf4e4077553206eebc2ed4f7630bb1bd92505131cca5bf8bd82a44477ef53058e1995411bdbf1f5dfad1f00" - ], - "inputs": [ - "5287f390628909dd8c25fad0feb37859c0c1ddcf90da0c040c837c89fefd9191" - ], - "outputs": [ - { - "uxid": "70fa9dfb887f9ef55beb4e960f60e4703c56f98201acecf2cad729f5d7e84690", - "dst": "7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD", - "coins": "8.000000", - "hours": 931 - } - ] - } - } - ]`, + { + "status": { + "confirmed": true, + "unconfirmed": false, + "height": 10492, + "block_seq": 1177, + "unknown": false + }, + "time": 1494275011, + "txn": { + "length": 317, + "type": 0, + "txid": "b09cd3a8baef6a449848f50a1b97943006ca92747d4e485d0647a3ea74550eca", + "inner_hash": "2cb370051c92521a04ba5357e229d8ffa90d9d1741ea223b44dd60a1483ee0e5", + "timestamp": 1494275011, + "sigs": [ + "a55155ca15f73f0762f79c15917949a936658cff668647daf82a174eed95703a02622881f9cf6c7495536676f931b2d91d389a9e7b034232b3a1519c8da6fb8800", + "cc7d7cbd6f31adabd9bde2c0deaa9277c0f3cf807a4ec97e11872817091dc3705841a6adb74acb625ee20ab6d3525350b8663566003276073d94c3bfe22fe48e01" + ], + "inputs": [ + "4f4b0078a9cd19b3395e54b3f42af6adc997f77f04e0ca54016c67c4f2384e3c", + "36f4871646b6564b2f1ab72bd768a67579a1e0242bc68bcbcf1779bc75b3dddd" + ], + "outputs": [ + { + "uxid": "5287f390628909dd8c25fad0feb37859c0c1ddcf90da0c040c837c89fefd9191", + "dst": "2K6NuLBBapWndAssUtkxKfCtyjDQDHrEhhT", + "coins": "8.000000", + "hours": 7454 + }, + { + "uxid": "a1268e9bd2033b49b44afa765d20876467254f51e5515626780467267a65c563", + "dst": "7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD", + "coins": "1.000000", + "hours": 7454 + } + ] + } + }, + { + "status": { + "confirmed": true, + "unconfirmed": false, + "height": 10491, + "block_seq": 1178, + "unknown": false + }, + "time": 1494275231, + "txn": { + "length": 183, + "type": 0, + "txid": "a6446654829a4a844add9f181949d12f8291fdd2c0fcb22200361e90e814e2d3", + "inner_hash": "075f255d42ddd2fb228fe488b8b468526810db7a144aeed1fd091e3fd404626e", + "timestamp": 1494275231, + "sigs": [ + "9b6fae9a70a42464dda089c943fafbf7bae8b8402e6bf4e4077553206eebc2ed4f7630bb1bd92505131cca5bf8bd82a44477ef53058e1995411bdbf1f5dfad1f00" + ], + "inputs": [ + "5287f390628909dd8c25fad0feb37859c0c1ddcf90da0c040c837c89fefd9191" + ], + "outputs": [ + { + "uxid": "70fa9dfb887f9ef55beb4e960f60e4703c56f98201acecf2cad729f5d7e84690", + "dst": "7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD", + "coins": "8.000000", + "hours": 931 + } + ] + } + } +]`, + ExampleVerboseResponse: `[ + { + "status": { + "confirmed": true, + "unconfirmed": false, + "height": 56088, + "block_seq": 1177 + }, + "time": 1494275011, + "txn": { + "timestamp": 1494275011, + "length": 317, + "type": 0, + "txid": "b09cd3a8baef6a449848f50a1b97943006ca92747d4e485d0647a3ea74550eca", + "inner_hash": "2cb370051c92521a04ba5357e229d8ffa90d9d1741ea223b44dd60a1483ee0e5", + "fee": 44726, + "sigs": [ + "a55155ca15f73f0762f79c15917949a936658cff668647daf82a174eed95703a02622881f9cf6c7495536676f931b2d91d389a9e7b034232b3a1519c8da6fb8800", + "cc7d7cbd6f31adabd9bde2c0deaa9277c0f3cf807a4ec97e11872817091dc3705841a6adb74acb625ee20ab6d3525350b8663566003276073d94c3bfe22fe48e01" + ], + "inputs": [ + { + "uxid": "4f4b0078a9cd19b3395e54b3f42af6adc997f77f04e0ca54016c67c4f2384e3c", + "owner": "2K6NuLBBapWndAssUtkxKfCtyjDQDHrEhhT", + "coins": "1.000000", + "hours": 52836, + "calculated_hours": 52857 + }, + { + "uxid": "36f4871646b6564b2f1ab72bd768a67579a1e0242bc68bcbcf1779bc75b3dddd", + "owner": "2K6NuLBBapWndAssUtkxKfCtyjDQDHrEhhT", + "coins": "8.000000", + "hours": 6604, + "calculated_hours": 6777 + } + ], + "outputs": [ + { + "uxid": "5287f390628909dd8c25fad0feb37859c0c1ddcf90da0c040c837c89fefd9191", + "dst": "2K6NuLBBapWndAssUtkxKfCtyjDQDHrEhhT", + "coins": "8.000000", + "hours": 7454 + }, + { + "uxid": "a1268e9bd2033b49b44afa765d20876467254f51e5515626780467267a65c563", + "dst": "7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD", + "coins": "1.000000", + "hours": 7454 + } + ] + } + }, + { + "status": { + "confirmed": true, + "unconfirmed": false, + "height": 56087, + "block_seq": 1178 + }, + "time": 1494275231, + "txn": { + "timestamp": 1494275231, + "length": 183, + "type": 0, + "txid": "a6446654829a4a844add9f181949d12f8291fdd2c0fcb22200361e90e814e2d3", + "inner_hash": "075f255d42ddd2fb228fe488b8b468526810db7a144aeed1fd091e3fd404626e", + "fee": 6523, + "sigs": [ + "9b6fae9a70a42464dda089c943fafbf7bae8b8402e6bf4e4077553206eebc2ed4f7630bb1bd92505131cca5bf8bd82a44477ef53058e1995411bdbf1f5dfad1f00" + ], + "inputs": [ + { + "uxid": "5287f390628909dd8c25fad0feb37859c0c1ddcf90da0c040c837c89fefd9191", + "owner": "2K6NuLBBapWndAssUtkxKfCtyjDQDHrEhhT", + "coins": "8.000000", + "hours": 7454, + "calculated_hours": 7454 + } + ], + "outputs": [ + { + "uxid": "70fa9dfb887f9ef55beb4e960f60e4703c56f98201acecf2cad729f5d7e84690", + "dst": "7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD", + "coins": "8.000000", + "hours": 931 + } + ] + } + } +]`, }, { ExplorerPath: "/api/balance", @@ -716,15 +1107,15 @@ var apiEndpoints = []APIEndpoint{ Description: "Returns the combined balance of a list of comma-separated addresses.", ExampleRequest: "/api/balance?addrs=7cpQ7t3PZZXvjTst8G7Uvs7XH4LeM8fBPD,nu7eSpT6hr5P21uzw7bnbxm83B6ywSjHdq", ExampleResponse: `{ - "confirmed": { - "coins": 70000000, - "hours": 28052 - }, - "predicted": { - "coins": 9000000, - "hours": 8385 - } - }`, + "confirmed": { + "coins": 70000000, + "hours": 28052 + }, + "predicted": { + "coins": 9000000, + "hours": 8385 + } +}`, }, { ExplorerPath: "/api/health", @@ -767,7 +1158,8 @@ var docEndpoint APIEndpoint = APIEndpoint{ // formatting when rendered in the browser as JSON type ParsedJSONAPIEndpoint struct { APIEndpoint - ParsedExampleResponse interface{} `json:"example_response,omitempty"` + ParsedExampleResponse interface{} `json:"example_response,omitempty"` + ParsedExampleVerboseResponse interface{} `json:"example_vervose_response,omitempty"` } var parsedJSONAPIEndpoints []ParsedJSONAPIEndpoint @@ -789,6 +1181,16 @@ func init() { log.Println(apiEndpoints[i].ExampleResponse) log.Panic(err) } + if apiEndpoints[i].ExampleVerboseResponse != "" { + resp = []byte(apiEndpoints[i].ExampleVerboseResponse) + if err := json.Unmarshal(resp, &parsedJSONAPIEndpoints[i].ParsedExampleVerboseResponse); err != nil { + log.Println("Error parsing example verbose response JSON:", err) + log.Println("path:", apiEndpoints[i].ExplorerPath) + log.Println("Example verbose response:") + log.Println(apiEndpoints[i].ExampleVerboseResponse) + log.Panic(err) + } + } } } @@ -862,6 +1264,11 @@ code.inline { border-radius: 3px; padding: 0.2em; background-color: #F7FAFB; fon

{{ .ExampleResponse }}

{{ end }} +{{ if .ExampleVerboseResponse }} +

Example verbose response:

+

{{ .ExampleVerboseResponse }}

+{{ end }} + {{ if .SkycoinPath }}

Internal skycoin node path:

{{ .SkycoinPath }}

diff --git a/src/app/app.datatypes.ts b/src/app/app.datatypes.ts index 64b5ff3e..5fdedfb4 100644 --- a/src/app/app.datatypes.ts +++ b/src/app/app.datatypes.ts @@ -1,7 +1,3 @@ -/** - * Skycoin Data Types Version 0.1 - last updated december 9th - */ - /** * Elementary Types */ @@ -28,6 +24,14 @@ export class Blockchain { blocks: number; } +export class Input { + owner: string; + coins: number; + uxid: string; + hours: number; + calculatedHours: number; +} + export class Output { address: string; coins: number; @@ -38,7 +42,7 @@ export class Output { export class Transaction { block: number; id: string; - inputs: Output[]; + inputs: Input[]; outputs: Output[]; status: boolean; timestamp: number; @@ -64,143 +68,115 @@ export class RichlistEntry { } /** - * Node Response Types + * Generic Node Response Types */ -export class GetAddressResponseTransaction { - inputs: GetAddressResponseTransactionInput[]; - outputs: GetAddressResponseTransactionOutput[]; - status: any; - timestamp: number; - txid: string; - length: number; +export class GenericBlockResponse { + header: GenericBlockHeaderResponse; + body: GenericBlockBodyResponse; + size: number; } -export function parseGetAddressTransaction(raw: GetAddressResponseTransaction, address: string): Transaction { +class GenericBlockHeaderResponse { + block_hash: string; + previous_block_hash: string; + seq: number; + timestamp: number; +} - let balance = 0; - for (const input of raw.inputs) { - if (input.owner.toLowerCase() === address.toLowerCase()) { - balance -= parseFloat(input.coins); - } - } - for (let output of raw.outputs) { - if (output.dst.toLowerCase() === address.toLowerCase()) { - balance += parseFloat(output.coins); - } - } +class GenericBlockBodyResponse { + txns: GenericTransactionResponse[]; +} - return { - block: null, - id: raw.txid, - timestamp: raw.timestamp, - inputs: raw.inputs.map(input => parseGetAddressInput(input)), - outputs: raw.outputs.map(output => parseGetAddressOutput(output)), - status: raw.status.confirmed, - balance: balance, - initialBalance: null, - finalBalance: null, - length: raw.length, - } +export class GenericTransactionResponse { + inputs: GenericTransactionInputResponse[]; + outputs: GenericTransactionOutputResponse[]; + status: any; + timestamp: number; + txid: string; + length: number; + fee: number; } -class GetAddressResponseTransactionInput { +class GenericTransactionInputResponse { uxid: string; owner: string; coins: string; - hours: string; -} - -function parseGetAddressInput(raw: GetAddressResponseTransactionInput): Output { - return { - address: raw.owner, - coins: parseFloat(raw.coins), - hash: raw.uxid, - hours: parseInt(raw.hours), - } + hours: number; + calculated_hours: number; } -class GetAddressResponseTransactionOutput { - uxid: string; - dst: string; +class GenericTransactionOutputResponse { coins: string; + dst: string; hours: number; + uxid: string; } -function parseGetAddressOutput(raw: GetAddressResponseTransactionOutput): Output { +export function parseGenericBlock(block: GenericBlockResponse): Block { return { - address: raw.dst, - coins: parseFloat(raw.coins), - hash: raw.uxid, - hours: raw.hours, + id: block.header.seq, + hash: block.header.block_hash, + parent_hash: block.header.previous_block_hash, + timestamp: block.header.timestamp, + transactions: block.body.txns.map(transaction => parseGenericTransaction(transaction)), + size: block.size, } } -export class GetUnconfirmedTransaction { - transaction: GetUnconfirmedTransactionBody; - received: string; - is_valid: boolean; -} - -export class GetUnconfirmedTransactionBody { - txid: string; - length: number; - inputs: string[]; - outputs: GetAddressResponseTransactionOutput[]; -} +export function parseGenericTransaction(raw: GenericTransactionResponse, address: string = null): Transaction { + let balance = null; + if (address) { + balance = 0; + for (const input of raw.inputs) { + if (input.owner.toLowerCase() === address.toLowerCase()) { + balance -= parseFloat(input.coins); + } + } + for (let output of raw.outputs) { + if (output.dst.toLowerCase() === address.toLowerCase()) { + balance += parseFloat(output.coins); + } + } + } -export function parseGetUnconfirmedTransaction(raw: GetUnconfirmedTransaction): Transaction { - return { + const response = { block: null, - id: raw.transaction.txid, - inputs: raw.transaction.inputs.map(input => ({ address: null, coins: null, hash: input, hours: null })), - outputs: raw.transaction.outputs.map(output => parseGetAddressOutput(output)), - status: raw.is_valid, - timestamp: new Date(raw.received).getTime(), - balance: null, + id: raw.txid, + timestamp: raw.timestamp, + inputs: raw.inputs.map(input => parseGenericTransactionInput(input)), + outputs: raw.outputs.map(output => parseGenericTransactionOutput(output)), + status: null, + balance: balance, initialBalance: null, finalBalance: null, - length: raw.transaction.length, + length: raw.length, } -} - -export class GetBlocksResponse { - blocks: GetBlocksResponseBlock[]; -} -export class GetBlocksResponseBlock { - body: GetBlocksResponseBlockBody; - header: GetBlocksResponseBlockHeader; - size: number; -} + if (raw.status) { + if (raw.status.confirmed) { + response.status = raw.status.confirmed; + } -export function parseGetBlocksBlock(block: GetBlocksResponseBlock): Block { - return { - id: block.header.seq, - hash: block.header.block_hash, - parent_hash: block.header.previous_block_hash, - timestamp: block.header.timestamp, - transactions: block.body.txns.map(transaction => parseGetBlocksTransaction(transaction)), - size: block.size, + if (raw.status.height) { + response.block = raw.status.block_seq; + } } + + return response; } -function parseGetBlocksTransaction(transaction: GetBlocksResponseBlockBodyTransaction): Transaction { +function parseGenericTransactionInput(raw: GenericTransactionInputResponse): Input { return { - block: null, - id: transaction.txid, - timestamp: null, - inputs: transaction.inputs.map(input => ({ address: null, coins: null, hash: input, hours: null })), - outputs: transaction.outputs.map(output => parseGetBlocksOutput(output)), - status: null, - balance: null, - initialBalance: null, - finalBalance: null, - length: transaction.length, + owner: raw.owner, + coins: parseFloat(raw.coins), + uxid: raw.uxid, + hours: raw.hours, + calculatedHours: raw.calculated_hours, } } -function parseGetBlocksOutput(raw: GetBlocksResponseBlockBodyTransactionOutput): Output { +function parseGenericTransactionOutput(raw: GenericTransactionOutputResponse): Output { return { address: raw.dst, coins: parseFloat(raw.coins), @@ -209,29 +185,25 @@ function parseGetBlocksOutput(raw: GetBlocksResponseBlockBodyTransactionOutput): } } -class GetBlocksResponseBlockBody { - txns: GetBlocksResponseBlockBodyTransaction[]; -} +/** + * Node Response Types + */ -class GetBlocksResponseBlockBodyTransaction { - txid: string; - length: number; - inputs: string[]; - outputs: GetBlocksResponseBlockBodyTransactionOutput[]; +export class GetUnconfirmedTransactionResponse { + transaction: GenericTransactionResponse; + received: string; + is_valid: boolean; } -class GetBlocksResponseBlockBodyTransactionOutput { - coins: string; - dst: string; - hours: number; - uxid: string; +export function parseGetUnconfirmedTransaction(raw: GetUnconfirmedTransactionResponse): Transaction { + raw.transaction.timestamp = new Date(raw.received).getTime(); + raw.transaction.status = { confirmed: raw.is_valid }; + + return parseGenericTransaction(raw.transaction); } -class GetBlocksResponseBlockHeader { - block_hash: string; - previous_block_hash: string; - seq: number; - timestamp: number; +export class GetBlocksResponse { + blocks: GenericBlockResponse[]; } export class GetBlockchainMetadataResponse { @@ -279,62 +251,14 @@ export class GetOutputsRequestOutput { } export class GetTransactionResponse { - status: GetTransactionStatus; + status: any; time: number; - txn: GetTransactionTransaction; + txn: GenericTransactionResponse; } export function parseGetTransaction(raw: GetTransactionResponse): Transaction { - return { - block: raw.status.block_seq, - id: raw.txn.txid, - inputs: raw.txn.inputs.map(input => parseGetTransactionInput(input)), - outputs: raw.txn.outputs.map(output => parseGetTransactionOutput(output)), - status: raw.status.confirmed, - timestamp: raw.txn.timestamp, - balance: null, - initialBalance: null, - finalBalance: null, - length: raw.txn.length, - } -} - -function parseGetTransactionInput(raw: string): Output { - return { - address: null, - coins: null, - hash: raw, - hours: null, - } -} - -function parseGetTransactionOutput(raw: GetTransactionOutput): Output { - return { - address: raw.dst, - coins: parseFloat(raw.coins), - hash: raw.uxid, - hours: raw.hours, - } -} - -class GetTransactionOutput { - uxid: string; - dst: string; - coins: string; - hours: number; -} - -class GetTransactionStatus { - confirmed: boolean; - block_seq: number; -} - -class GetTransactionTransaction { - inputs: string[]; - outputs: GetTransactionOutput[]; - timestamp: number; - txid: string; - length: number; + raw.txn.status = raw.status; + return parseGenericTransaction(raw.txn); } export class GetUxoutResponse { @@ -352,18 +276,3 @@ export function parseGetUxout(raw: GetUxoutResponse): Output { hash: raw.uxid, } } - -/** - * Web Cipher Types - */ - -export class TransactionInput { - hash: string; - secret: string; -} - -export class TransactionOutput { - address: string; - coins: number; - hours: number; -} diff --git a/src/app/components/pages/address-detail/address-detail.component.html b/src/app/components/pages/address-detail/address-detail.component.html index 234ad081..cf2d53cf 100644 --- a/src/app/components/pages/address-detail/address-detail.component.html +++ b/src/app/components/pages/address-detail/address-detail.component.html @@ -9,6 +9,7 @@

{{ 'addressDetail.title' | translate }}

{{ 'addressDetail.txsNumber' | translate }}
{{ transactions ? transactions.length : loadingMsg }}
{{ 'addressDetail.totalReceived' | translate }}
{{ transactions ? ((totalReceived | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
{{ 'addressDetail.currentBalance' | translate }}
{{ transactions ? ((balance | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
+
{{ 'addressDetail.hoursBalance' | translate }}
{{ transactions ? ((hoursBalance | number:'1.0-6')) : loadingMsg }}
{{ 'addressDetail.tools' | translate }}
{{ 'addressDetail.unspentOutputs' | translate }} {{ loadingMsg }}
@@ -53,8 +54,10 @@

{{ 'addressDetail.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
- {{ input.address }} + {{ input.owner }}
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
+
{{ 'general.iniialHours' | translate }}: 
{{ input.hours | number:'1.0-6' }}
+
{{ 'general.calculatedHours' | translate }}: 
{{ input.calculatedHours | number:'1.0-6' }}
@@ -62,6 +65,7 @@

{{ 'addressDetail.title' | translate }}

{{ output.address }}
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
+
{{ 'general.hours' | translate }}: 
{{ output.hours | number:'1.0-6' }}
diff --git a/src/app/components/pages/address-detail/address-detail.component.ts b/src/app/components/pages/address-detail/address-detail.component.ts index 194e568e..59b907d2 100644 --- a/src/app/components/pages/address-detail/address-detail.component.ts +++ b/src/app/components/pages/address-detail/address-detail.component.ts @@ -16,6 +16,7 @@ export class AddressDetailComponent implements OnInit { address: string; totalReceived: number; balance: number; + hoursBalance: number; transactions: any[]; pageTransactions: any[]; pageIndex = 0; @@ -45,6 +46,7 @@ export class AddressDetailComponent implements OnInit { if (this.address != params['address']) { this.transactions = undefined; this.balance = undefined; + this.hoursBalance = undefined; } this.address = params['address']; @@ -81,7 +83,10 @@ export class AddressDetailComponent implements OnInit { ); this.route.params.switchMap((params: Params) => this.api.getBalance(params['address'])) - .subscribe(response => this.balance = response.confirmed.coins / 1000000); + .subscribe(response => { + this.balance = response.confirmed.coins / 1000000; + this.hoursBalance = response.confirmed.hours; + }); } updateTransactions() { diff --git a/src/app/components/pages/block-details/block-details.component.html b/src/app/components/pages/block-details/block-details.component.html index aab00712..7df77467 100644 --- a/src/app/components/pages/block-details/block-details.component.html +++ b/src/app/components/pages/block-details/block-details.component.html @@ -56,8 +56,10 @@

{{ 'blockDetails.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
- {{ input.address }} + {{ input.owner }}
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
+
{{ 'general.iniialHours' | translate }}: 
{{ input.hours | number:'1.0-6' }}
+
{{ 'general.calculatedHours' | translate }}: 
{{ input.calculatedHours | number:'1.0-6' }}
@@ -65,6 +67,7 @@

{{ 'blockDetails.title' | translate }}

{{ output.address }}
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
+
{{ 'general.hours' | translate }}: 
{{ output.hours | number:'1.0-6' }}
diff --git a/src/app/components/pages/transaction-detail/transaction-detail.component.html b/src/app/components/pages/transaction-detail/transaction-detail.component.html index 4553463c..955275c4 100644 --- a/src/app/components/pages/transaction-detail/transaction-detail.component.html +++ b/src/app/components/pages/transaction-detail/transaction-detail.component.html @@ -42,8 +42,10 @@

{{ 'transactionDetail.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
- {{ input.address }} + {{ input.owner }}
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
+
{{ 'general.iniialHours' | translate }}: 
{{ input.hours | number:'1.0-6' }}
+
{{ 'general.calculatedHours' | translate }}: 
{{ input.calculatedHours | number:'1.0-6' }}
@@ -51,6 +53,7 @@

{{ 'transactionDetail.title' | translate }}

{{ output.address }}
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
+
{{ 'general.hours' | translate }}: 
{{ output.hours | number:'1.0-6' }}
diff --git a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html index 5c93b169..ac59dd5b 100644 --- a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html +++ b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html @@ -42,8 +42,10 @@

{{ 'unconfirmedTx.title' | translate }}

{{ 'txBoxes.inputs' | translate }}
- {{ input.address }} + {{ input.owner }}
{{ 'general.coins' | translate }}: {{ input.coins | number:'1.0-6' }}
+
{{ 'general.iniialHours' | translate }}: 
{{ input.hours | number:'1.0-6' }}
+
{{ 'general.calculatedHours' | translate }}: 
{{ input.calculatedHours | number:'1.0-6' }}
@@ -51,6 +53,7 @@

{{ 'unconfirmedTx.title' | translate }}

{{ output.address }}
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
+
{{ 'general.hours' | translate }}: 
{{ output.hours | number:'1.0-6' }}
diff --git a/src/app/services/api/api.service.ts b/src/app/services/api/api.service.ts index 4e35e3c3..8cbc2975 100644 --- a/src/app/services/api/api.service.ts +++ b/src/app/services/api/api.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@angular/core'; import { Http } from '@angular/http'; import { Observable } from 'rxjs/Observable'; import { CoinSupply } from '../../components/pages/blocks/block'; -import { Blockchain, GetBlocksResponse, GetBlockchainMetadataResponse, GetUnconfirmedTransaction, GetUxoutResponse, GetAddressResponseTransaction, - GetCurrentBalanceResponse, GetBlocksResponseBlock, RichlistEntry, GetBalanceResponse, GetTransactionResponse } from '../../app.datatypes'; +import { Blockchain, GetBlocksResponse, GetBlockchainMetadataResponse, GetUnconfirmedTransactionResponse, GetUxoutResponse, GenericTransactionResponse, + GetCurrentBalanceResponse, GenericBlockResponse, RichlistEntry, GetBalanceResponse, GetTransactionResponse } from '../../app.datatypes'; import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; @@ -17,16 +17,20 @@ export class ApiService { private http: Http ) { } - getAddress(address: string): Observable { + getAddress(address: string): Observable { return this.get('address', { address: address }); } - getUnconfirmedTransactions(): Observable { - return this.get('pendingTxs'); + getUnconfirmedTransactions(): Observable { + return this.get('pendingTxs', { verbose: 1 }); } - getBlock(hash: string): Observable { - return this.get('block', { hash: hash }); + getBlockById(id: number): Observable { + return this.get('block', { seq: id, verbose: 1 }); + } + + getBlockByHash(hash: string): Observable { + return this.get('block', { hash: hash, verbose: 1 }); } getBlocks(startNumber: number, endNumber: number): Observable { @@ -53,7 +57,7 @@ export class ApiService { } getTransaction(transactionId:string): Observable { - return this.get('transaction', { txid: transactionId }); + return this.get('transaction', { txid: transactionId, verbose: 1 }); } getUxout(uxid: string): Observable { diff --git a/src/app/services/explorer/explorer.service.ts b/src/app/services/explorer/explorer.service.ts index 00233df9..d41d0683 100644 --- a/src/app/services/explorer/explorer.service.ts +++ b/src/app/services/explorer/explorer.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ApiService } from '../api/api.service'; import { Observable } from 'rxjs/Observable'; -import { Block, Output, parseGetAddressTransaction, parseGetBlocksBlock, parseGetTransaction, parseGetUnconfirmedTransaction, parseGetUxout, Transaction } from '../../app.datatypes'; +import { Block, Output, parseGenericTransaction, parseGenericBlock, parseGetUnconfirmedTransaction, parseGetUxout, Transaction, parseGetTransaction } from '../../app.datatypes'; import 'rxjs/add/observable/forkJoin'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/mergeMap'; @@ -15,39 +15,26 @@ export class ExplorerService { ) { } getBlock(id: number): Observable { - return this.api.getBlocks(id, id).flatMap(response => { - if (response.blocks.length > 0) { - const block = parseGetBlocksBlock(response.blocks[0]); - return Observable.forkJoin(block.transactions.map(transaction => { - return this.retrieveInputsForTransaction(transaction); - })).map(transactions => { - block.transactions = transactions; - return block; - }); - } else { - let emptyArray: Block[] = [null]; - return emptyArray; - } - }); + return this.api.getBlockById(id).map(response => parseGenericBlock(response)); } getBlocks(start: number, end: number): Observable { return this.api.getBlocks(start, end) - .map(response => response.blocks.map(block => parseGetBlocksBlock(block)).sort((a, b) => b.id - a.id)); + .map(response => response.blocks.map(block => parseGenericBlock(block)).sort((a, b) => b.id - a.id)); } getBlockByHash(hash: string): Observable { - return this.api.getBlock(hash).map(response => parseGetBlocksBlock(response)); + return this.api.getBlockByHash(hash).map(response => parseGenericBlock(response)); } getTransactions(address: string): Observable { return this.api.getAddress(address) .map(response => { - response = response.sort((a, b) => b.timestamp - a.timestamp) + response = response.sort((a, b) => a.timestamp - b.timestamp) let currentBalance = 0; - return response.reverse().map(rawTx => { - let parsedTx = parseGetAddressTransaction(rawTx, address); + return response.map(rawTx => { + let parsedTx = parseGenericTransaction(rawTx, address); parsedTx.initialBalance = currentBalance; currentBalance += parsedTx.balance; parsedTx.finalBalance = currentBalance; @@ -58,40 +45,11 @@ export class ExplorerService { getUnconfirmedTransactions(): Observable { return this.api.getUnconfirmedTransactions() - .flatMap(response => { - - let parsedResponse = response.map(rawTx => parseGetUnconfirmedTransaction(rawTx)); - - if (parsedResponse.length > 0) { - return Observable.forkJoin(parsedResponse.map(transaction => { - return this.retrieveInputsForTransaction(transaction); - })); - } else { - return Observable.of(parsedResponse); - } - }) + .map(response => response.map(rawTx => parseGetUnconfirmedTransaction(rawTx))); } getTransaction(transactionId: string): Observable { return this.api.getTransaction(transactionId) - .map(response => parseGetTransaction(response)) - .flatMap(transaction => this.retrieveInputsForTransaction(transaction)); - } - - private retrieveInputsForTransaction(transaction: Transaction): Observable { - if (transaction.inputs.length != 0) { - return Observable.forkJoin(transaction.inputs.map(input => { - return this.retrieveOutputById(input.hash); - })).map(inputs => { - transaction.inputs = inputs; - return transaction; - }); - } else { - return Observable.of(transaction); - } - } - - private retrieveOutputById(id): Observable { - return this.api.getUxout(id).map(response => parseGetUxout(response)) + .map(response => parseGetTransaction(response)); } } diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index e26db1b4..2f183a54 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -3,6 +3,9 @@ "coinIdentifier": "SKY", "address": "Address", "coins": "Coins", + "iniialHours": "Initial Hours", + "calculatedHours": "Final Hours", + "hours": "Hours", "loadingMsg": "Loading...", "shortLoadingErrorMsg": "Loading error", "longLoadingErrorMsg": "Error loading data, try again later...", @@ -55,7 +58,8 @@ "title": "Address", "txsNumber": "# of Transactions", "totalReceived": "Total Received", - "currentBalance": "Current Balance", + "currentBalance": "Current Coins", + "hoursBalance": "Current Hours", "tools": "Tools", "unspentOutputs": "Unspent outputs", "withoutTransactions": "Without transactions" From cbc645f7fa45bd1f20bdd3a12b0580b524d2fbbe Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Mon, 10 Sep 2018 15:39:52 -0400 Subject: [PATCH 06/25] Updated e2e tests --- README.md | 16 +++++++ e2e/general.po.ts | 2 +- e2e/test-fixtures/blockchain-180.db | Bin 1048576 -> 1048576 bytes .../unconfirmed-transactions.e2e-spec.ts | 39 ++++++++++++++++++ .../unconfirmed-transactions.po.ts | 20 ++++++++- 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4fe04fe0..74eb9b6c 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,22 @@ Run linters: make lint ``` +### e2e Tests + +If you are running a Skycoin node normally, you can run the e2e tests with: + +```sh +npm run e2e +``` + +If you are running a Skycoin node using the test database (`blockchain-180.db`), you can run the e2e tests with: + +```sh +npm run e2e-blockchain-180 +``` + +The second method is the one used in Travis. + ### Customization [CUSTOMIZATION.md](CUSTOMIZATION.md) diff --git a/e2e/general.po.ts b/e2e/general.po.ts index 1ae7db59..8f1fa5d8 100644 --- a/e2e/general.po.ts +++ b/e2e/general.po.ts @@ -61,7 +61,7 @@ export class GeneralPageFunctions { return element .all(by.css('.-balance > div:nth-of-type(2)')) .map((element, i) => element.getText()) - .then(texts => texts.map(text => Number((text as string).replace(',', ''))).reduce((total, val) => total+val, 0)) + .then(texts => texts.map(text => Number((text as string).replace(new RegExp(',', 'g'), ''))).reduce((total, val) => total+val, 0)) .then(result => Math.round(result * 1000000) / 1000000); } diff --git a/e2e/test-fixtures/blockchain-180.db b/e2e/test-fixtures/blockchain-180.db index f0908f2d660d25a917a2e8fbcfe6c4068d6e01c4..817ab5d6a34c399526c3305386fe5fbc9d0b6666 100644 GIT binary patch delta 1575 zcmZo@aA;_7n4rMOGyS7IleqXy1_-EPfzWSi6ZfdzsoySmjpIG%#)LzxlLQnPr%(R) zAEC4os?;G|$I?#TYh&Pg{>}g7xePXQ9QeV%DS<0tI#&bxB(GFP1_mHvU}R=s5CPJ1 zP`)xyI}ecG0FndZ`B1(9l)oCt7YDLo{6j3;pEa--Fizjr#Lidm0F?O(#O4NuDMrR= zDW-{ zV@nhBJ3uoSerVe6zkBCs*7P*D&~xun*+nl$@!m38`QaR&-pnhV6IDRYvutFODJoqz z=cL(7rln@)^>^Ffm(Sk2Sx!#ivg*Yup;^04zCE3O?$x*I4T0s}jz^oy82q!6PdDC6 zypm~sd}(mL5!jQ{|K4U*m|WN*#nsut)(bRN-7?Zh)@zL-Ep~;q z&7Z$|;pCPTZ)~qf7_a~6{_3cuJA?J3=~qk`h3ygkfM_Jqoaz0}jAC2}&rk1eV%N3@ zy9jKa0+190Vh%8mfk6{UvjedL5GSUj6vb!erKDEGXQXDPXOsZNKw!)CGfnJKjMKJ% zP~yzx+H`@-fRSq|H>2<7h=3LRZ32wj1eiDsCUXP`OjTgC*ghkGBZGfpf=62bQ(FLY zTL4R20Bc(S+qM99jtAR09GHIaZ*$<_5ZKNkzzk$2aBw(m=lH+^WNzT#D%j3t!1|4U zngJ)rc8&zrAN2JC!^tPp20R03&9AZ~{8o1pwwD8C!Z?}GBD zK>3rP{JBv6WGH_bls{#9p(?A)_NfN!+5FQAIJrRiZj)vMP!^PMV}OAP%4e{AlmX-; z=d1edPaD`TGEy{G)g%gn=bH090?+ AiU0rr delta 2217 zcmeH|OH30%7{_M|ZFdW}OD$q0#I27IB$34%#)RcyB0je!#&|H@QjnmeZMv8cU)^AA ze1ITpyYXaiUQ8$u+bi5X^yI-47d^wp5Io>a_g}39E^^R=lg$3+H#7Tn=bPECX{x5F z&dS_`z242Y9(+TblB##uadP-=^QoZ+3*mXu+7d(DgtdO<*E9pulBs+)__6K+o3^xd zSWs+UbxFOC5$y^19Gn9!@HLnN?GIsYUR>0D`jSukCN7qJ3g^!@aF_NJF(GCot|+;9 zrNk@zhM3V@8Lcj()n_z!M)MRkFTXk<5ntsY+;|iT{Iew#Ri2m964_sg(u`OgU>A4} z41%Vz)A2a_!67}x24xlcFOOFSk!r5wfTZe;v_pLd-^zc>4xliCl(95FPUzt zMC0hSOe@O@%LVh#v^LiGSK6)}U)$!J)J0lVTG{=*^x~nc#_OZb;+@5~$^2r?gels= zCd-)co_e6h%j^c~*D-$7_4@;Mm%f}r6gnZ*GUC${3-yjh`olXedX}iG`u66Eq zT6fA`Ld>ZG-(TI?)=DHof?y|j0z3_#0joPckPUII{WsAY1-I{e9R1b(e*~Wbrx(Hz zv8V|?DeWvtrumTRAj=6W3jDmIM1_0d8vGDkhqu9#aJI>;m~g>SG7Ar+(UC{T2)qD) z2499x!^`k2d==gfUxRCKLN{2ZZFZ_yk>H`*juROjlW+y@x7P#Sj*=erta2qi=3&P{ z$t4Bf-#+exY!$T9g_1oVce>c>`xPA;N(~!EWHcVPzAv|NQ&!JPi`y6-F=l8h$Q_~A zfE8I8;0uFeiP#-u&MK@#_7%oc(YO(fjgKbcM$T@Z^cJnsC%Nfv+(-_`$0Nx^V(f*j z8A1yeT?lVB=1iKx1C?acAFmW1bpA&O3Biwn$3X?`0ee9eybN9iS*BPSb3pEa_p5;( YqGPxB`R7-MeXSPs{QvsT=U~J01GTM#aR2}S diff --git a/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts b/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts index 1b7b378f..a2bd7040 100644 --- a/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts +++ b/e2e/unconfirmed-transactions/unconfirmed-transactions.e2e-spec.ts @@ -1,5 +1,6 @@ import { UnconfirmedTransactionsPage } from './unconfirmed-transactions.po'; import { GeneralPageFunctions } from "../general.po"; +import { browser } from 'protractor'; describe('skycoin-explorer Unconfirmed Transactions Page', () => { const page = new UnconfirmedTransactionsPage(); @@ -15,4 +16,42 @@ describe('skycoin-explorer Unconfirmed Transactions Page', () => { it('should display 4 Unconfirmed Transactions details', () => { expect(generalFunctions.getDetailsRowCount()).toEqual(4); }); + + if (browser.params.chain == '180') { + it('should show the correct number of transactions', () => { + expect(page.getNumberOfTransactions()).toBe(1); + }); + + it('should show the correct total size', () => { + expect(page.getSize()).toBe(220); + }); + + it('should show a valid newest date', () => { + expect(page.getTimestampValidity(3)).toBeTruthy(); + }); + + it('should show a valid oldest date', () => { + expect(page.getTimestampValidity(4)).toBeTruthy(); + }); + + it('should show the correct transaction ID', () => { + expect(generalFunctions.getTransactionId(0)).toEqual('701d23fd513bad325938ba56869f9faba19384a8ec3dd41833aff147eac53947'); + }); + + it('should show a valid transaction date', () => { + expect(generalFunctions.getTransactionDateValidity(0)).toBeTruthy(); + }); + + it('should show the correct transaction inputs', () => { + expect(generalFunctions.getTransactionInputs(0)).toBe('R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ'); + }); + + it('should show the correct transaction outputs', () => { + expect(generalFunctions.getTransactionOutputs(0)).toBe('R6aHqKWSQfvpdo2fGSrq4F1RYXkBWR9HHJ,212mwY3Dmey6vwnWpiph99zzCmopXTqeVEN'); + }); + + it('should have the correct coins amount', () => { + expect(generalFunctions.getTransactionInputsAndOutputsTotalCoins()).toBe(63299981); + }); + } }); \ No newline at end of file diff --git a/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts b/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts index 78e07508..1b1fdf76 100644 --- a/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts +++ b/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts @@ -1,5 +1,23 @@ import { browser, by, element } from 'protractor'; export class UnconfirmedTransactionsPage { - + + getNumberOfTransactions() { + return element(by.css('.element-details > div:nth-of-type(1) > div')) + .getText() + .then(text => Number(text)); + } + + getSize() { + return element(by.css('.element-details > div:nth-of-type(2) > div')) + .getText() + .then(text => Number(text.split(' ')[0])); + } + + getTimestampValidity(index: number) { + return element(by.css('.element-details > div:nth-of-type(' + index + ') > div')) + .getText() + .then(text => !isNaN((new Date(text)).getTime())); + } + } \ No newline at end of file From 18ab19ac7ee7e9f9c89d038f44df0dc104750e79 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Mon, 10 Sep 2018 17:21:57 -0400 Subject: [PATCH 07/25] Show total sent --- e2e/address-detail/address-detail.e2e-spec.ts | 12 ++++++++++-- e2e/address-detail/address-detail.po.ts | 8 +++++++- .../address-detail/address-detail.component.html | 1 + .../pages/address-detail/address-detail.component.ts | 2 ++ src/assets/i18n/en.json | 1 + 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/e2e/address-detail/address-detail.e2e-spec.ts b/e2e/address-detail/address-detail.e2e-spec.ts index a661d872..09b0bac1 100644 --- a/e2e/address-detail/address-detail.e2e-spec.ts +++ b/e2e/address-detail/address-detail.e2e-spec.ts @@ -19,8 +19,8 @@ describe('skycoin-explorer Address Page', () => { expect(page.getPageTitleForSmallScreens()).toBe("Address"); }); - it('should have 5 address details rows', () => { - expect(generalFunctions.getDetailsRowCount()).toEqual(6); + it('should have 6 address details rows', () => { + expect(generalFunctions.getDetailsRowCount()).toEqual(7); }); it('should have the correct address for small screens', () => { @@ -39,6 +39,14 @@ describe('skycoin-explorer Address Page', () => { } }); + it('should show the correct sent amount', () => { + if (browser.params.chain == '180') { + expect(page.getTotalSent()).toBe(0); + } else { + expect(page.getTotalSent()).toBe(0); + } + }); + it('should show the correct current balance', () => { if (browser.params.chain == '180') { expect(page.getCurrentBalance()).toBe(100); diff --git a/e2e/address-detail/address-detail.po.ts b/e2e/address-detail/address-detail.po.ts index 3d2b24e0..232de0cc 100644 --- a/e2e/address-detail/address-detail.po.ts +++ b/e2e/address-detail/address-detail.po.ts @@ -23,8 +23,14 @@ export class AddressDetailPage { .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); } + getTotalSent() { + return element(by.css('.element-details > div:nth-of-type(4) > div')) + .getText() + .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); + } + getCurrentBalance() { - return element(by.css('.element-details > div:nth-of-type(3) > div')) + return element(by.css('.element-details > div:nth-of-type(5) > div')) .getText() .then(text => Number(text.split(' ')[0].replace(new RegExp(',', 'g'), ''))); } diff --git a/src/app/components/pages/address-detail/address-detail.component.html b/src/app/components/pages/address-detail/address-detail.component.html index cf2d53cf..83c30928 100644 --- a/src/app/components/pages/address-detail/address-detail.component.html +++ b/src/app/components/pages/address-detail/address-detail.component.html @@ -8,6 +8,7 @@

{{ 'addressDetail.title' | translate }}

{{ 'addressDetail.txsNumber' | translate }}
{{ transactions ? transactions.length : loadingMsg }}
{{ 'addressDetail.totalReceived' | translate }}
{{ transactions ? ((totalReceived | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
+
{{ 'addressDetail.totalSent' | translate }}
{{ transactions ? ((totalSent | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
{{ 'addressDetail.currentBalance' | translate }}
{{ transactions ? ((balance | number:'1.0-6') + ' ' + ('general.coinIdentifier' | translate)) : loadingMsg }}
{{ 'addressDetail.hoursBalance' | translate }}
{{ transactions ? ((hoursBalance | number:'1.0-6')) : loadingMsg }}
{{ 'addressDetail.tools' | translate }}
diff --git a/src/app/components/pages/address-detail/address-detail.component.ts b/src/app/components/pages/address-detail/address-detail.component.ts index 59b907d2..f49d7789 100644 --- a/src/app/components/pages/address-detail/address-detail.component.ts +++ b/src/app/components/pages/address-detail/address-detail.component.ts @@ -15,6 +15,7 @@ import { TranslateService } from '@ngx-translate/core'; export class AddressDetailComponent implements OnInit { address: string; totalReceived: number; + totalSent: number; balance: number; hoursBalance: number; transactions: any[]; @@ -65,6 +66,7 @@ export class AddressDetailComponent implements OnInit { transactions => { this.transactions = transactions; this.totalReceived = transactions.reduce((a, b) => b.balance > 0 ? (a + b.balance) : a, 0); + this.totalSent = transactions.reduce((a, b) => b.balance < 0 ? (a + b.balance) : a, 0) * -1; this.updateTransactions(); }, error => { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 2f183a54..dfefdae3 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -58,6 +58,7 @@ "title": "Address", "txsNumber": "# of Transactions", "totalReceived": "Total Received", + "totalSent": "Total Sent", "currentBalance": "Current Coins", "hoursBalance": "Current Hours", "tools": "Tools", From 3da155697caa038bac74b39e79f6d8b5cf412da9 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Thu, 4 Oct 2018 15:48:32 -0400 Subject: [PATCH 08/25] Show timezone --- .../date-formatter.component.html | 9 ++++-- .../date-formatter.component.scss | 4 +++ .../date-formatter.component.ts | 2 ++ .../pages/blocks/blocks.component.html | 13 ++++---- .../pages/blocks/blocks.component.scss | 8 +++++ .../pages/blocks/blocks.component.ts | 2 ++ src/styles.scss | 30 +++++++++++++++++++ 7 files changed, 61 insertions(+), 7 deletions(-) diff --git a/src/app/components/layout/date-formatter/date-formatter.component.html b/src/app/components/layout/date-formatter/date-formatter.component.html index 50a1f623..31d476b8 100644 --- a/src/app/components/layout/date-formatter/date-formatter.component.html +++ b/src/app/components/layout/date-formatter/date-formatter.component.html @@ -1,2 +1,7 @@ -{{date * dateMultiplier | date:'yyyy-MM-dd'}} -{{date * dateMultiplier | date:'hh:mm:ss'}} \ No newline at end of file +
+ {{date * dateMultiplier | date:'yyyy-MM-dd'}} + {{date * dateMultiplier | date:'hh:mm:ss'}} +
+
{{date * dateMultiplier | date:'OOOO'}}
+
+
\ No newline at end of file diff --git a/src/app/components/layout/date-formatter/date-formatter.component.scss b/src/app/components/layout/date-formatter/date-formatter.component.scss index d29e2cfb..e7962f99 100644 --- a/src/app/components/layout/date-formatter/date-formatter.component.scss +++ b/src/app/components/layout/date-formatter/date-formatter.component.scss @@ -1,5 +1,9 @@ @import '../../../../assets/scss/_variables.scss'; +.root { + display: inline; +} + .time { display: inline-block; } \ No newline at end of file diff --git a/src/app/components/layout/date-formatter/date-formatter.component.ts b/src/app/components/layout/date-formatter/date-formatter.component.ts index 149e46f5..93c9b47b 100644 --- a/src/app/components/layout/date-formatter/date-formatter.component.ts +++ b/src/app/components/layout/date-formatter/date-formatter.component.ts @@ -9,6 +9,8 @@ export class DateFormatterComponent { @Input()date; @Input()dateMultiplier = 1000; + + mouseOver = false; constructor() { } } diff --git a/src/app/components/pages/blocks/blocks.component.html b/src/app/components/pages/blocks/blocks.component.html index d683a0eb..a043bacd 100644 --- a/src/app/components/pages/blocks/blocks.component.html +++ b/src/app/components/pages/blocks/blocks.component.html @@ -35,15 +35,18 @@

{{ 'blocks.blocksTitle' | translate }}

-
+
-
- {{ block.timestamp * 1000 | date:'yyyy' }}
- {{ (block.timestamp * 1000 | date:'MMM dd').toUpperCase() }}
- {{ block.timestamp * 1000 | date:'HH:mm' }} +
+ {{ block.timestamp * 1000 | date:'yyyy' }}
+ {{ (block.timestamp * 1000 | date:'MMM dd').toUpperCase() }}
+ {{ block.timestamp * 1000 | date:'HH:mm' }} +
+
{{ block.timestamp * 1000 | date:'OOOO' }}
+
{{ block.id }}
diff --git a/src/app/components/pages/blocks/blocks.component.scss b/src/app/components/pages/blocks/blocks.component.scss index f145b3f5..e4b5b45b 100644 --- a/src/app/components/pages/blocks/blocks.component.scss +++ b/src/app/components/pages/blocks/blocks.component.scss @@ -50,4 +50,12 @@ .-link { text-decoration: none; +} + +.-small-date { + display: inline; +} + +.-small-padding { + padding-right: 5px; } \ No newline at end of file diff --git a/src/app/components/pages/blocks/blocks.component.ts b/src/app/components/pages/blocks/blocks.component.ts index 70419295..89d8e733 100644 --- a/src/app/components/pages/blocks/blocks.component.ts +++ b/src/app/components/pages/blocks/blocks.component.ts @@ -25,6 +25,8 @@ export class BlocksComponent implements OnInit { loadingMetadataMsg = ""; longErrorMsg: string; + mouseOver = -1; + get pageCount() { return Math.ceil(this.blockCount / this.pageSize); } diff --git a/src/styles.scss b/src/styles.scss index 6e0fedb7..3124850a 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -51,6 +51,10 @@ h2 { width: 130px; } + > div:last-of-type { + display: flex; + } + .-link { color: $primary; } @@ -341,3 +345,29 @@ copy-button { } } } + +.timezone-container { + height: 0px; + position: relative; + top: 1px; + font-size: 9px; +} + +.timezone-label { + background-color: rgba(0, 0, 0, 0.05); + padding: 2px 4px; + display: inline; +} + +.timezone-icon { + margin-right: 4px; + font-family: 'Font Awesome 5 Free'; + font-size: 12px; + user-select: none; + font-weight: 600; + opacity: 0.25; +} + +.timezone-icon-opaque { + opacity: 0.5 !important; +} From 73d86924a0480a5df155d4adee3599c3fd963f33 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Sun, 7 Oct 2018 11:45:40 -0400 Subject: [PATCH 09/25] Show tx fee --- src/app/app.datatypes.ts | 2 ++ .../address-detail/address-detail.component.html | 10 ++++++---- .../pages/block-details/block-details.component.html | 11 +++++++++++ .../transaction-detail.component.html | 11 +++++++++++ .../unconfirmed-transactions.component.html | 11 +++++++++++ src/assets/i18n/en.json | 9 ++++----- src/styles.scss | 8 ++++++++ 7 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/app/app.datatypes.ts b/src/app/app.datatypes.ts index 5fdedfb4..f7dfdf7e 100644 --- a/src/app/app.datatypes.ts +++ b/src/app/app.datatypes.ts @@ -50,6 +50,7 @@ export class Transaction { initialBalance: number; finalBalance: number; length: number; + fee: number; } export class Wallet { @@ -151,6 +152,7 @@ export function parseGenericTransaction(raw: GenericTransactionResponse, address initialBalance: null, finalBalance: null, length: raw.length, + fee: raw.fee, } if (raw.status) { diff --git a/src/app/components/pages/address-detail/address-detail.component.html b/src/app/components/pages/address-detail/address-detail.component.html index 83c30928..412e61d7 100644 --- a/src/app/components/pages/address-detail/address-detail.component.html +++ b/src/app/components/pages/address-detail/address-detail.component.html @@ -74,15 +74,17 @@

{{ 'addressDetail.title' | translate }}

{{ 'txBoxes.balance' | translate }}
+
+
{{ 'txBoxes.fee' | translate }}: 
+
{{ transaction.fee | number:'1.0-0' }}
+
-
{{ 'txBoxes.initialBalance' | translate }}: 
-
{{ 'txBoxes.initialBalanceShort' | translate }}: 
+
{{ 'txBoxes.initialBalance' | translate }}: 
{{ transaction.initialBalance | number:'1.0-6' }}
-
{{ 'txBoxes.finalBalance' | translate }}: 
-
{{ 'txBoxes.finalBalanceShort' | translate }}: 
+
{{ 'txBoxes.finalBalance' | translate }}: 
{{ transaction.finalBalance | number:'1.0-6' }}
diff --git a/src/app/components/pages/block-details/block-details.component.html b/src/app/components/pages/block-details/block-details.component.html index 7df77467..bd473bb8 100644 --- a/src/app/components/pages/block-details/block-details.component.html +++ b/src/app/components/pages/block-details/block-details.component.html @@ -71,6 +71,17 @@

{{ 'blockDetails.title' | translate }}

+
+
+
{{ 'txBoxes.balance' | translate }}
+
+
+
{{ 'txBoxes.fee' | translate }}: 
+
{{ transaction.fee | number:'1.0-0' }}
+
+
+
+
\ No newline at end of file diff --git a/src/app/components/pages/transaction-detail/transaction-detail.component.html b/src/app/components/pages/transaction-detail/transaction-detail.component.html index 955275c4..3ae76109 100644 --- a/src/app/components/pages/transaction-detail/transaction-detail.component.html +++ b/src/app/components/pages/transaction-detail/transaction-detail.component.html @@ -57,5 +57,16 @@

{{ 'transactionDetail.title' | translate }}

+
+
+
{{ 'txBoxes.balance' | translate }}
+
+
+
{{ 'txBoxes.fee' | translate }}: 
+
{{ transaction.fee | number:'1.0-0' }}
+
+
+
+
diff --git a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html index ac59dd5b..56e8addb 100644 --- a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html +++ b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html @@ -57,5 +57,16 @@

{{ 'unconfirmedTx.title' | translate }}

+
+
+
{{ 'txBoxes.balance' | translate }}
+
+
+
{{ 'txBoxes.fee' | translate }}: 
+
{{ transaction.fee | number:'1.0-0' }}
+
+
+
+
diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index dfefdae3..0539e634 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -18,11 +18,10 @@ "outputs": "Outputs", "pending": "pending", "date": "Date", - "balance": "Balance", - "initialBalance": "Initial address balance", - "finalBalance": "Final address balance", - "initialBalanceShort": "Initial", - "finalBalanceShort": "Final", + "balance": "More info", + "fee": "Transaction fee (in hours)", + "initialBalance": "Initial coins balance", + "finalBalance": "Final coins balance", "firstSeen": "First seen at" }, "blocks": { diff --git a/src/styles.scss b/src/styles.scss index 6e0fedb7..651818c0 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -191,10 +191,17 @@ h2 { .-balance-variation { border-top: 1px solid $col-normal-separator; text-align: right; + display: flex; + align-items: center; + + .fee-box { + flex-grow: 1; + } > div { display: inline-block; padding: $siz-small-margin 0px; + text-align: left; @media (max-width: $max-xs-width) { width: 100%; @@ -226,6 +233,7 @@ h2 { & { border-top: none; text-align: left; + display: unset; } } } From 937e1fd14a08c4811116ca3fe631f8b6938c3a26 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Sun, 7 Oct 2018 12:36:55 -0400 Subject: [PATCH 10/25] Fix e2e tests --- e2e/address-detail/address-detail.po.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/address-detail/address-detail.po.ts b/e2e/address-detail/address-detail.po.ts index 232de0cc..2cffbe69 100644 --- a/e2e/address-detail/address-detail.po.ts +++ b/e2e/address-detail/address-detail.po.ts @@ -39,7 +39,7 @@ export class AddressDetailPage { return element .all(by.css('.transaction')) .get(transsactionIndex) - .element(by.css('.-balance-variation > div:nth-of-type(1) > div:nth-of-type(3)')) + .element(by.css('.-balance-variation > div:nth-of-type(2) > div:nth-of-type(2)')) .getText() .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } @@ -48,7 +48,7 @@ export class AddressDetailPage { return element .all(by.css('.transaction')) .get(transsactionIndex) - .element(by.css('.-balance-variation > div:nth-of-type(2) > div:nth-of-type(3)')) + .element(by.css('.-balance-variation > div:nth-of-type(3) > div:nth-of-type(2)')) .getText() .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } From 12d3a71c6287118c1a768e6a9b607bb572343007 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Sun, 7 Oct 2018 13:39:23 -0400 Subject: [PATCH 11/25] Fix e2e test --- e2e/block-details/block-details.po.ts | 3 ++- e2e/blocks/blocks.po.ts | 9 +++++---- e2e/general.po.ts | 10 +++++++++- e2e/transaction-detail/transaction-detail.po.ts | 3 ++- .../unconfirmed-transactions.po.ts | 3 ++- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/e2e/block-details/block-details.po.ts b/e2e/block-details/block-details.po.ts index 02ed5d8c..db9f42fb 100644 --- a/e2e/block-details/block-details.po.ts +++ b/e2e/block-details/block-details.po.ts @@ -1,4 +1,5 @@ import { browser, by, element } from 'protractor'; +import { GeneralPageFunctions } from "../general.po"; export class BlockDetailsPage { @@ -11,7 +12,7 @@ export class BlockDetailsPage { getTimestampValidity() { return element(by.css('.element-details > div:nth-of-type(2) > div')) .getText() - .then(text => !isNaN((new Date(text)).getTime())); + .then(text => GeneralPageFunctions.processAndCheckDate(text)); } getSize() { diff --git a/e2e/blocks/blocks.po.ts b/e2e/blocks/blocks.po.ts index 119ab0aa..48d35820 100644 --- a/e2e/blocks/blocks.po.ts +++ b/e2e/blocks/blocks.po.ts @@ -1,4 +1,5 @@ import { browser, by, element, protractor } from 'protractor'; +import { GeneralPageFunctions } from "../general.po"; export class BlocksPage { getPageTitle(titleNumber: number) { @@ -51,21 +52,21 @@ export class BlocksPage { getTimeValidity(row: number) { return this.getTableCellValue(row, 1) - .then(text => !isNaN((new Date(text)).getTime())); + .then(text => GeneralPageFunctions.processAndCheckDate(text)); } getBlockNumber(row: number) { - return this.getTableCellValue(row, 4) + return this.getTableCellValue(row, 5) .then(text => Number(text)); } getTransactionCount(row: number) { - return this.getTableCellValue(row, 5) + return this.getTableCellValue(row, 6) .then(text => Number(text)); } getBlockHashLength(row: number) { - return this.getTableCellValue(row, 6) + return this.getTableCellValue(row, 7) .then(text => text.length); } diff --git a/e2e/general.po.ts b/e2e/general.po.ts index 8f1fa5d8..1bc0a85a 100644 --- a/e2e/general.po.ts +++ b/e2e/general.po.ts @@ -36,7 +36,7 @@ export class GeneralPageFunctions { .get(transsactionIndex) .element(by.css('.-date')) .getText() - .then(text => !isNaN((new Date(text)).getTime())); + .then(text => GeneralPageFunctions.processAndCheckDate(text)); } getTransactionInputs(transsactionIndex: number) { @@ -69,4 +69,12 @@ export class GeneralPageFunctions { return element(by.css('div.row.-msg-container > div')) .getText(); } + + static processAndCheckDate(text: string): boolean { + let numberText = text; + if (isNaN(Number(numberText.substr(0,1)))) { + numberText = numberText.substr(1, numberText.length-1); + } + return !isNaN((new Date(numberText)).getTime()) + } } \ No newline at end of file diff --git a/e2e/transaction-detail/transaction-detail.po.ts b/e2e/transaction-detail/transaction-detail.po.ts index 1ff6e6aa..64a7089c 100644 --- a/e2e/transaction-detail/transaction-detail.po.ts +++ b/e2e/transaction-detail/transaction-detail.po.ts @@ -1,10 +1,11 @@ import { browser, by, element } from 'protractor'; +import { GeneralPageFunctions } from "../general.po"; export class TransactionDetailPage { getTimestampValidity() { return element(by.css('.element-details > div:nth-of-type(2) > div')) .getText() - .then(text => !isNaN((new Date(text)).getTime())); + .then(text => GeneralPageFunctions.processAndCheckDate(text)); } getSize() { diff --git a/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts b/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts index 1b1fdf76..48a4bd56 100644 --- a/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts +++ b/e2e/unconfirmed-transactions/unconfirmed-transactions.po.ts @@ -1,4 +1,5 @@ import { browser, by, element } from 'protractor'; +import { GeneralPageFunctions } from "../general.po"; export class UnconfirmedTransactionsPage { @@ -17,7 +18,7 @@ export class UnconfirmedTransactionsPage { getTimestampValidity(index: number) { return element(by.css('.element-details > div:nth-of-type(' + index + ') > div')) .getText() - .then(text => !isNaN((new Date(text)).getTime())); + .then(text => GeneralPageFunctions.processAndCheckDate(text)); } } \ No newline at end of file From 1144be0d7974c06504c7126a0a4dcd98f6d1b121 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Mon, 8 Oct 2018 13:22:24 -0400 Subject: [PATCH 12/25] 24 hours format --- .../layout/date-formatter/date-formatter.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/layout/date-formatter/date-formatter.component.html b/src/app/components/layout/date-formatter/date-formatter.component.html index 31d476b8..28c27849 100644 --- a/src/app/components/layout/date-formatter/date-formatter.component.html +++ b/src/app/components/layout/date-formatter/date-formatter.component.html @@ -1,6 +1,6 @@
{{date * dateMultiplier | date:'yyyy-MM-dd'}} - {{date * dateMultiplier | date:'hh:mm:ss'}} + {{date * dateMultiplier | date:'HH:mm:ss'}}
{{date * dateMultiplier | date:'OOOO'}}
From d0cf9176be3f023b3ecc8616fa9f32fe1b890d97 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Mon, 8 Oct 2018 13:47:00 -0400 Subject: [PATCH 13/25] Delete repeated date --- e2e/transaction-detail/transaction-detail.e2e-spec.ts | 8 ++------ e2e/transaction-detail/transaction-detail.po.ts | 10 ++-------- .../transaction-detail.component.html | 1 - 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/e2e/transaction-detail/transaction-detail.e2e-spec.ts b/e2e/transaction-detail/transaction-detail.e2e-spec.ts index 4e73789c..0d804b02 100644 --- a/e2e/transaction-detail/transaction-detail.e2e-spec.ts +++ b/e2e/transaction-detail/transaction-detail.e2e-spec.ts @@ -12,12 +12,8 @@ describe('skycoin-explorer Transaction Page', () => { expect(generalFunctions.getPageTitle()).toBe("Transaction"); }); - it('should display 4 transaction details rows', () => { - expect(generalFunctions.getDetailsRowCount()).toEqual(4); - }); - - it('should show a valid timestamp', () => { - expect(page.getTimestampValidity()).toBeTruthy(); + it('should display 3 transaction details rows', () => { + expect(generalFunctions.getDetailsRowCount()).toEqual(3); }); it('should show the correct size', () => { diff --git a/e2e/transaction-detail/transaction-detail.po.ts b/e2e/transaction-detail/transaction-detail.po.ts index 64a7089c..d5935c71 100644 --- a/e2e/transaction-detail/transaction-detail.po.ts +++ b/e2e/transaction-detail/transaction-detail.po.ts @@ -2,20 +2,14 @@ import { browser, by, element } from 'protractor'; import { GeneralPageFunctions } from "../general.po"; export class TransactionDetailPage { - getTimestampValidity() { - return element(by.css('.element-details > div:nth-of-type(2) > div')) - .getText() - .then(text => GeneralPageFunctions.processAndCheckDate(text)); - } - getSize() { - return element(by.css('.element-details > div:nth-of-type(3) > div')) + return element(by.css('.element-details > div:nth-of-type(2) > div')) .getText() .then(text => Number(text.split(' ')[0])); } getBlockNumber() { - return element(by.css('.element-details > div:nth-of-type(4) > div > a')) + return element(by.css('.element-details > div:nth-of-type(3) > div > a')) .getText() .then(text => Number(text.replace(new RegExp(',', 'g'), ''))); } diff --git a/src/app/components/pages/transaction-detail/transaction-detail.component.html b/src/app/components/pages/transaction-detail/transaction-detail.component.html index 955275c4..dd313c02 100644 --- a/src/app/components/pages/transaction-detail/transaction-detail.component.html +++ b/src/app/components/pages/transaction-detail/transaction-detail.component.html @@ -2,7 +2,6 @@

{{ 'transactionDetail.title' | translate }}

From ab1c3f26ea3b2a470e17228280df35474989ee9f Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Tue, 9 Oct 2018 16:42:37 -0400 Subject: [PATCH 14/25] Code cleaning --- src/app/app.component.html | 8 +- src/app/app.component.ts | 23 ----- src/app/app.datatypes.ts | 42 ++-------- src/app/app.module.ts | 6 +- .../copy-button/copy-button.component.ts | 2 +- .../layout/loading/loading.component.css | 9 -- .../layout/loading/loading.component.html | 22 ++--- .../layout/loading/loading.component.scss | 5 ++ .../layout/loading/loading.component.ts | 13 ++- .../pages/address-detail/UnspentOutput.ts | 37 --------- .../address-detail.component.html | 9 +- .../address-detail.component.ts | 4 +- .../block-details.component.html | 9 +- .../block-details/block-details.component.ts | 5 +- src/app/components/pages/blocks/block.ts | 83 ------------------- .../pages/blocks/blocks.component.html | 11 +-- .../pages/blocks/blocks.component.ts | 3 +- .../pages/richlist/richlist.component.html | 11 +-- .../pages/search/search.component.html | 10 +-- .../pages/search/search.component.ts | 2 - .../transaction-detail.component.html | 9 +- .../transaction-detail.component.ts | 5 +- .../unconfirmed-transactions.component.html | 9 +- .../unconfirmed-transactions.component.ts | 4 +- .../unspent-outputs.component.html | 9 +- .../unspent-outputs.component.ts | 5 +- src/app/pipes/explorer-date.pipe.spec.ts | 8 -- src/app/pipes/explorer-date.pipe.ts | 17 ---- src/app/services/api/api.service.spec.ts | 8 +- src/app/services/api/api.service.ts | 26 ++---- src/app/services/explorer/explorer.service.ts | 2 +- src/styles.scss | 4 - 32 files changed, 67 insertions(+), 353 deletions(-) delete mode 100644 src/app/components/layout/loading/loading.component.css create mode 100644 src/app/components/layout/loading/loading.component.scss delete mode 100644 src/app/components/pages/address-detail/UnspentOutput.ts delete mode 100644 src/app/components/pages/blocks/block.ts delete mode 100644 src/app/pipes/explorer-date.pipe.spec.ts delete mode 100644 src/app/pipes/explorer-date.pipe.ts diff --git a/src/app/app.component.html b/src/app/app.component.html index 4cdb423d..e48924c3 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,10 +1,10 @@
-
- - -
+
+ + +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index cd9ebf9a..eed11092 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -9,8 +9,6 @@ import { HeaderConfig, FooterConfig } from 'app/app.config'; styleUrls: ['./app.component.css'] }) export class AppComponent { - loading: boolean; - headerConfig = HeaderConfig; footerConfig = FooterConfig; @@ -22,29 +20,8 @@ export class AppComponent { translate.use('en'); router.events.subscribe((event: RouterEvent) => { - this.navigationInterceptor(event); if (event instanceof NavigationEnd) window.scrollTo(0, 0); }); } - - // Shows and hides the loading spinner during RouterEvent changes - navigationInterceptor(event: RouterEvent): void { - if (event instanceof NavigationStart) { - this.loading = true; - } - - if (event instanceof NavigationEnd) { - this.loading = false; - } - - // Set loading state to false in both of the below events to hide the spinner in case a request fails - if (event instanceof NavigationCancel) { - this.loading = false; - } - - if (event instanceof NavigationError) { - this.loading = false; - } - } } diff --git a/src/app/app.datatypes.ts b/src/app/app.datatypes.ts index f7dfdf7e..f1980c3b 100644 --- a/src/app/app.datatypes.ts +++ b/src/app/app.datatypes.ts @@ -2,15 +2,6 @@ * Elementary Types */ -export class Address { - address: string; - next_seed?: string; - secret_key?: string; - public_key?: string; - balance?: number; - hours?: number; -} - export class Block { id: number; hash: string; @@ -53,15 +44,6 @@ export class Transaction { fee: number; } -export class Wallet { - label: string; - addresses: Address[]; - seed?: string; - balance?: number; - hours?: number; - hidden?: boolean; -} - export class RichlistEntry { address: string; coins: string; @@ -212,7 +194,7 @@ export class GetBlockchainMetadataResponse { head: GetBlockchainMetadataResponseHead; } -export class GetBlockchainMetadataResponseHead { +class GetBlockchainMetadataResponseHead { seq: number; } @@ -238,20 +220,6 @@ class GetCurrentBalanceResponseOutput { hours: number; } -export class GetOutputsRequest { - head_outputs: GetOutputsRequestOutput[]; - outgoing_outputs: any[]; - incoming_outputs: any[]; -} - -export class GetOutputsRequestOutput { - hash: string; - src_tx: string; - address: string; - coins: string; - hours: number; -} - export class GetTransactionResponse { status: any; time: number; @@ -278,3 +246,11 @@ export function parseGetUxout(raw: GetUxoutResponse): Output { hash: raw.uxid, } } + +export interface GetCoinSupplyResponse { + current_supply: number, + total_supply: number, + max_supply: number, + current_coinhour_supply: number, + total_coinhour_supply: number, +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts index eb30b682..709beed3 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -10,7 +10,7 @@ import { LoadingComponent } from './components/layout/loading/loading.component' import { BlocksComponent } from './components/pages/blocks/blocks.component'; import { UnconfirmedTransactionsComponent } from './components/pages/unconfirmed-transactions/unconfirmed-transactions.component'; import { ApiService } from './services/api/api.service'; -import { HttpModule } from '@angular/http'; +import { HttpClientModule } from '@angular/common/http'; import { BlockDetailsComponent } from './components/pages/block-details/block-details.component'; import { TransactionDetailComponent } from './components/pages/transaction-detail/transaction-detail.component'; import { AddressDetailComponent } from './components/pages/address-detail/address-detail.component'; @@ -27,7 +27,6 @@ import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { AppTranslateLoader } from 'app/app.translate-loader'; import { GenericHeaderComponent } from 'app/components/layout/generic-header/generic-header.component'; import { GenericFooterComponent } from 'app/components/layout/generic-footer/generic-footer.component'; -import { ExplorerDatePipe } from 'app/pipes/explorer-date.pipe'; import { DatePipe } from '@angular/common'; import { DateFormatterComponent } from 'app/components/layout/date-formatter/date-formatter.component'; import { SearchService } from './services/search/search.service'; @@ -107,7 +106,6 @@ const ROUTES = [ RichlistComponent, UnspentOutputsComponent, CopyButtonComponent, - ExplorerDatePipe, DateFormatterComponent, SearchComponent, ], @@ -115,7 +113,7 @@ const ROUTES = [ BrowserModule, BrowserAnimationsModule, FormsModule, - HttpModule, + HttpClientModule, RouterModule.forRoot(ROUTES), TranslateModule.forRoot({ loader: { diff --git a/src/app/components/layout/copy-button/copy-button.component.ts b/src/app/components/layout/copy-button/copy-button.component.ts index 5e874dd1..60df5965 100644 --- a/src/app/components/layout/copy-button/copy-button.component.ts +++ b/src/app/components/layout/copy-button/copy-button.component.ts @@ -1,4 +1,4 @@ -import { Component, Input, OnInit, HostBinding } from '@angular/core'; +import { Component, Input, HostBinding } from '@angular/core'; import { trigger, state, style, transition, animate } from '@angular/animations'; import { AnimationEvent } from '@angular/animations/src/animation_event'; diff --git a/src/app/components/layout/loading/loading.component.css b/src/app/components/layout/loading/loading.component.css deleted file mode 100644 index dba0ce31..00000000 --- a/src/app/components/layout/loading/loading.component.css +++ /dev/null @@ -1,9 +0,0 @@ -.modalShow{ - z-index: 1003; - display: block; - opacity: 1; - max-width: 80%; - margin: 0 auto; - transform: scaleX(1); - top: 10%; -} diff --git a/src/app/components/layout/loading/loading.component.html b/src/app/components/layout/loading/loading.component.html index f3724046..e48f014d 100644 --- a/src/app/components/layout/loading/loading.component.html +++ b/src/app/components/layout/loading/loading.component.html @@ -1,16 +1,8 @@ - -
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+
diff --git a/src/app/components/pages/address-detail/address-detail.component.ts b/src/app/components/pages/address-detail/address-detail.component.ts index f49d7789..da391c2a 100644 --- a/src/app/components/pages/address-detail/address-detail.component.ts +++ b/src/app/components/pages/address-detail/address-detail.component.ts @@ -1,8 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Params, Router } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import { ApiService } from '../../../services/api/api.service'; import { ExplorerService } from '../../../services/explorer/explorer.service'; -import { Output, Transaction } from '../../../app.datatypes'; import {Observable} from 'rxjs/Observable'; import 'rxjs/Rx'; import { TranslateService } from '@ngx-translate/core'; @@ -33,7 +32,6 @@ export class AddressDetailComponent implements OnInit { private api: ApiService, private explorer: ExplorerService, private route: ActivatedRoute, - private router: Router, private translate: TranslateService ) { translate.get('general.loadingMsg').subscribe((res: string) => { diff --git a/src/app/components/pages/block-details/block-details.component.html b/src/app/components/pages/block-details/block-details.component.html index bd473bb8..fbc18c92 100644 --- a/src/app/components/pages/block-details/block-details.component.html +++ b/src/app/components/pages/block-details/block-details.component.html @@ -23,14 +23,7 @@

{{ 'blockDetails.title' | translate }}

-
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+
diff --git a/src/app/components/pages/block-details/block-details.component.ts b/src/app/components/pages/block-details/block-details.component.ts index 1e8d28de..357f7a88 100644 --- a/src/app/components/pages/block-details/block-details.component.ts +++ b/src/app/components/pages/block-details/block-details.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Params, Router } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import { ExplorerService } from '../../../services/explorer/explorer.service'; -import { Block, Output, Transaction } from '../../../app.datatypes'; +import { Block } from '../../../app.datatypes'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/switchMap'; import { TranslateService } from '@ngx-translate/core'; @@ -21,7 +21,6 @@ export class BlockDetailsComponent implements OnInit { constructor( private explorer: ExplorerService, private route: ActivatedRoute, - private router: Router, private translate: TranslateService, private api: ApiService, ) { diff --git a/src/app/components/pages/blocks/block.ts b/src/app/components/pages/blocks/block.ts deleted file mode 100644 index e65b9eee..00000000 --- a/src/app/components/pages/blocks/block.ts +++ /dev/null @@ -1,83 +0,0 @@ -// TODO: This does not belong here, fix it! -// TODO: Many unused properties, perhaps refactor? - -export class Block { - constructor( - public header: BlockHeader, - public body: BlockBody - ) {} -} - -export class BlockHeader { - constructor( - public seq: number, - public block_hash: string, - public previous_block_hash: string, - public timestamp: string, - public fee: number, - public version: number, - public tx_body_hash: string, - ) {} -} - -export class BlockBody { - constructor( - public txns: Transaction[] - ) {} -} - -export class Output { - constructor( - public uxid: string, - public dst: string, - public coins: number, - public hrs: number, - ) {} -} - -export class BlockChainMetaDataHead { - constructor( - public seq: number, - public block_hash: string, - public previous_block_hash: string, - public timestamp: number, - public fee: number, - public version: number, - public tx_body_hash: string, - ) {} -} - -export class BlockChainMetaData { - constructor( - public head: BlockChainMetaDataHead, - public unspents: number, - public unconfirmed: number, - ) {} -} - - -export class Transaction { - constructor( - public length: number, - public type: number, - public txid: string, - public inner_hash: number, - public sigs: string[], - public inputs: string[], - public outputs: Output[], - ) {} -} - -export interface CoinSupply { - current_supply: number, - total_supply: number, - max_supply: number, - current_coinhour_supply: number, - total_coinhour_supply: number, -} - -export class BlockResponse { - constructor( - public blocks: Block[] - ) {} -} diff --git a/src/app/components/pages/blocks/blocks.component.html b/src/app/components/pages/blocks/blocks.component.html index a043bacd..405735a3 100644 --- a/src/app/components/pages/blocks/blocks.component.html +++ b/src/app/components/pages/blocks/blocks.component.html @@ -25,14 +25,9 @@

{{ 'blocks.blocksTitle' | translate }}

{{ 'blocks.blockhash' | translate }}
-
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+ + +
diff --git a/src/app/components/pages/blocks/blocks.component.ts b/src/app/components/pages/blocks/blocks.component.ts index 89d8e733..c6f35fb9 100644 --- a/src/app/components/pages/blocks/blocks.component.ts +++ b/src/app/components/pages/blocks/blocks.component.ts @@ -1,5 +1,5 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { ActivatedRoute } from '@angular/router'; import { ApiService } from '../../../services/api/api.service'; import { Block } from '../../../app.datatypes'; import { ExplorerService } from '../../../services/explorer/explorer.service'; @@ -35,7 +35,6 @@ export class BlocksComponent implements OnInit { private api: ApiService, private explorer: ExplorerService, private route: ActivatedRoute, - private router: Router, private translate: TranslateService ) { translate.get('general.loadingMsg').subscribe((res: string) => { diff --git a/src/app/components/pages/richlist/richlist.component.html b/src/app/components/pages/richlist/richlist.component.html index 31322ec1..55f3b8e8 100644 --- a/src/app/components/pages/richlist/richlist.component.html +++ b/src/app/components/pages/richlist/richlist.component.html @@ -8,14 +8,9 @@

{{ 'richlist.title' | translate }}

{{ 'general.coins' | translate }}
-
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+ + +
{{ i+1 }}
diff --git a/src/app/components/pages/search/search.component.html b/src/app/components/pages/search/search.component.html index 6306cb16..8fe6b26e 100644 --- a/src/app/components/pages/search/search.component.html +++ b/src/app/components/pages/search/search.component.html @@ -1,10 +1,2 @@

{{ 'search.title' | translate }}

- -
-
- - {{ 'general.waitingData' | translate }} - - {{ errorMsg | translate:{ term: searchTerm } }} -
-
\ No newline at end of file + \ No newline at end of file diff --git a/src/app/components/pages/search/search.component.ts b/src/app/components/pages/search/search.component.ts index a8db251b..3039418a 100644 --- a/src/app/components/pages/search/search.component.ts +++ b/src/app/components/pages/search/search.component.ts @@ -2,7 +2,6 @@ import { Component, OnInit } from '@angular/core'; import { ActivatedRoute, Params, Router } from '@angular/router'; import { SearchService, SearchError } from '../../../services/search/search.service'; -import { TranslateService } from '@ngx-translate/core'; @Component({ templateUrl: './search.component.html', @@ -16,7 +15,6 @@ export class SearchComponent implements OnInit { private searchService: SearchService, private route: ActivatedRoute, private router: Router, - private translate: TranslateService, ) {} ngOnInit() { diff --git a/src/app/components/pages/transaction-detail/transaction-detail.component.html b/src/app/components/pages/transaction-detail/transaction-detail.component.html index 63f0bfd7..5bf2e7a5 100644 --- a/src/app/components/pages/transaction-detail/transaction-detail.component.html +++ b/src/app/components/pages/transaction-detail/transaction-detail.component.html @@ -7,14 +7,7 @@

{{ 'transactionDetail.title' | translate }}

-
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+
diff --git a/src/app/components/pages/transaction-detail/transaction-detail.component.ts b/src/app/components/pages/transaction-detail/transaction-detail.component.ts index a8185ca6..4d343bc3 100644 --- a/src/app/components/pages/transaction-detail/transaction-detail.component.ts +++ b/src/app/components/pages/transaction-detail/transaction-detail.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Params, Router } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import 'rxjs/add/operator/mergeMap'; -import { Output, Transaction } from '../../../app.datatypes'; +import { Transaction } from '../../../app.datatypes'; import { ExplorerService } from '../../../services/explorer/explorer.service'; import { TranslateService } from '@ngx-translate/core'; @@ -19,7 +19,6 @@ export class TransactionDetailComponent implements OnInit { constructor( private explorer: ExplorerService, private route: ActivatedRoute, - private router: Router, private translate: TranslateService ) { translate.get('general.loadingMsg').subscribe((res: string) => { diff --git a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html index 56e8addb..ce967a39 100644 --- a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html +++ b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.html @@ -8,14 +8,7 @@

{{ 'unconfirmedTx.title' | translate }}

-
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+
diff --git a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.ts b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.ts index 7e730819..595d55cf 100644 --- a/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.ts +++ b/src/app/components/pages/unconfirmed-transactions/unconfirmed-transactions.component.ts @@ -1,7 +1,6 @@ import { Component, OnInit } from '@angular/core'; -import { Router } from '@angular/router'; import { ExplorerService } from '../../../services/explorer/explorer.service'; -import { Output, Transaction } from '../../../app.datatypes'; +import { Transaction } from '../../../app.datatypes'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/switchMap'; import { TranslateService } from '@ngx-translate/core'; @@ -22,7 +21,6 @@ export class UnconfirmedTransactionsComponent implements OnInit { constructor( private explorer: ExplorerService, - private router: Router, private translate: TranslateService ) { translate.get('general.loadingMsg').subscribe((res: string) => { diff --git a/src/app/components/pages/unspent-outputs/unspent-outputs.component.html b/src/app/components/pages/unspent-outputs/unspent-outputs.component.html index 8c927de7..7091a124 100644 --- a/src/app/components/pages/unspent-outputs/unspent-outputs.component.html +++ b/src/app/components/pages/unspent-outputs/unspent-outputs.component.html @@ -7,14 +7,7 @@

{{ 'unspentOutputs.title' | translate }}

-
-
- - {{ 'general.waitingData' | translate }} - - {{ longErrorMsg }} -
-
+
diff --git a/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts b/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts index 5c719bb0..05b12af3 100644 --- a/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts +++ b/src/app/components/pages/unspent-outputs/unspent-outputs.component.ts @@ -1,7 +1,7 @@ import { Component, OnInit } from '@angular/core'; -import { ActivatedRoute, Params, Router } from '@angular/router'; +import { ActivatedRoute, Params } from '@angular/router'; import { ApiService } from '../../../services/api/api.service'; -import { Block, Output, Transaction, GetCurrentBalanceResponse } from '../../../app.datatypes'; +import { GetCurrentBalanceResponse } from '../../../app.datatypes'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/switchMap'; import { TranslateService } from '@ngx-translate/core'; @@ -21,7 +21,6 @@ export class UnspentOutputsComponent implements OnInit { constructor( private api: ApiService, private route: ActivatedRoute, - private router: Router, private translate: TranslateService ) { translate.get('general.loadingMsg').subscribe((res: string) => { diff --git a/src/app/pipes/explorer-date.pipe.spec.ts b/src/app/pipes/explorer-date.pipe.spec.ts deleted file mode 100644 index 71efc677..00000000 --- a/src/app/pipes/explorer-date.pipe.spec.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ExplorerDatePipe } from "app/pipes/explorer-date.pipe"; - -describe('ExplorerDatePipe', () => { - it('create an instance', () => { - const pipe = new ExplorerDatePipe(null); - expect(pipe).toBeTruthy(); - }); -}); diff --git a/src/app/pipes/explorer-date.pipe.ts b/src/app/pipes/explorer-date.pipe.ts deleted file mode 100644 index a0815ee6..00000000 --- a/src/app/pipes/explorer-date.pipe.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Pipe, PipeTransform } from '@angular/core'; -import { Transaction } from '../app.datatypes'; -import { DatePipe } from '@angular/common'; - -@Pipe({ - name: 'explorerDate', -}) -export class ExplorerDatePipe implements PipeTransform { - - constructor(private datePipe: DatePipe) { - } - - transform(value: any, unixDateInSeconds = true): string { - value = unixDateInSeconds ? value * 1000 : value; - return this.datePipe.transform(value, 'yyyy-MM-dd HH:mm:ss', 'UTC'); - } -} \ No newline at end of file diff --git a/src/app/services/api/api.service.spec.ts b/src/app/services/api/api.service.spec.ts index 9b4ba30f..65b6c71c 100644 --- a/src/app/services/api/api.service.spec.ts +++ b/src/app/services/api/api.service.spec.ts @@ -1,15 +1,15 @@ import { TestBed, inject } from '@angular/core/testing'; -import { ApiServiceService } from './api.service'; +import { ApiService } from './api.service'; -describe('ApiServiceService', () => { +describe('ApiService', () => { beforeEach(() => { TestBed.configureTestingModule({ - providers: [ApiServiceService] + providers: [ApiService] }); }); - it('should be created', inject([ApiServiceService], (service: ApiServiceService) => { + it('should be created', inject([ApiService], (service: ApiService) => { expect(service).toBeTruthy(); })); }); diff --git a/src/app/services/api/api.service.ts b/src/app/services/api/api.service.ts index 8cbc2975..2e5968c9 100644 --- a/src/app/services/api/api.service.ts +++ b/src/app/services/api/api.service.ts @@ -1,9 +1,8 @@ import { Injectable } from '@angular/core'; -import { Http } from '@angular/http'; +import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs/Observable'; -import { CoinSupply } from '../../components/pages/blocks/block'; -import { Blockchain, GetBlocksResponse, GetBlockchainMetadataResponse, GetUnconfirmedTransactionResponse, GetUxoutResponse, GenericTransactionResponse, - GetCurrentBalanceResponse, GenericBlockResponse, RichlistEntry, GetBalanceResponse, GetTransactionResponse } from '../../app.datatypes'; +import { Blockchain, GetBlocksResponse, GetBlockchainMetadataResponse, GetUnconfirmedTransactionResponse, GenericTransactionResponse, + GetCurrentBalanceResponse, GenericBlockResponse, RichlistEntry, GetBalanceResponse, GetTransactionResponse, GetCoinSupplyResponse } from '../../app.datatypes'; import 'rxjs/add/observable/throw'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/catch'; @@ -14,7 +13,7 @@ export class ApiService { private url = '/api/'; constructor( - private http: Http + private http: HttpClient ) { } getAddress(address: string): Observable { @@ -44,7 +43,7 @@ export class ApiService { })) } - getCoinSupply(): Observable { + getCoinSupply(): Observable { return this.get('coinSupply'); } @@ -60,27 +59,18 @@ export class ApiService { return this.get('transaction', { txid: transactionId, verbose: 1 }); } - getUxout(uxid: string): Observable { - return this.get('uxout', { uxid: uxid }); - } - getRichlist(): Observable { return this.get('richlist').map(response => response.richlist); } // Old methods - getInputAddress(uxid:string): any{ - return this.get('uxout?uxid=' + uxid); - } - - private get(url, options = null) { + get(url: string, options: object = null): any { return this.http.get(this.getUrl(url, options)) - .map((res: any) => res.json()) .catch((error: any) => Observable.throw(error || 'Server error')); } - private getQueryString(parameters = null) { + private getQueryString(parameters: object = null): string { if (!parameters) { return ''; } @@ -91,7 +81,7 @@ export class ApiService { }, []).join('&'); } - private getUrl(url, options = null) { + private getUrl(url: string, options: object = null): string { return this.url + url + '?' + this.getQueryString(options); } } diff --git a/src/app/services/explorer/explorer.service.ts b/src/app/services/explorer/explorer.service.ts index d41d0683..473c6272 100644 --- a/src/app/services/explorer/explorer.service.ts +++ b/src/app/services/explorer/explorer.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { ApiService } from '../api/api.service'; import { Observable } from 'rxjs/Observable'; -import { Block, Output, parseGenericTransaction, parseGenericBlock, parseGetUnconfirmedTransaction, parseGetUxout, Transaction, parseGetTransaction } from '../../app.datatypes'; +import { Block, parseGenericTransaction, parseGenericBlock, parseGetUnconfirmedTransaction, Transaction, parseGetTransaction } from '../../app.datatypes'; import 'rxjs/add/observable/forkJoin'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/mergeMap'; diff --git a/src/styles.scss b/src/styles.scss index 2f6e93c3..31b7b5da 100644 --- a/src/styles.scss +++ b/src/styles.scss @@ -62,10 +62,6 @@ h2 { } } -.-msg-container { - padding: $siz-normal-margin $siz-big-margin; -} - @media (min-width: ($max-sm-width+1)) { .-xs-sm-only { display: none !important; From b136691259e491ff0c20a3d05c8245a240e252b0 Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Wed, 10 Oct 2018 17:20:42 -0400 Subject: [PATCH 15/25] Update /api/health --- explorer.go | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/explorer.go b/explorer.go index 87ef9bf8..d35e54c4 100644 --- a/explorer.go +++ b/explorer.go @@ -1125,25 +1125,32 @@ var apiEndpoints = []APIEndpoint{ ExampleResponse: `{ "blockchain": { "head": { - "seq": 21175, - "block_hash": "8a3e0aac619551ae009cfb28c2b36bb1300925f74da770d1512072314f6a4c80", - "previous_block_hash": "001eb7911b6a6ab7c75feb88726dd2bc8b87133aebc82201c4404537eb74f7ac", - "timestamp": 1523168686, - "fee": 2, + "seq": 58894, + "block_hash": "3961bea8c4ab45d658ae42effd4caf36b81709dc52a5708fdd4c8eb1b199a1f6", + "previous_block_hash": "8eca94e7597b87c8587286b66a6b409f6b4bf288a381a56d7fde3594e319c38a", + "timestamp": 1537581604, + "fee": 485194, "version": 0, - "tx_body_hash": "36be8d70d1e9f70b340ea7ecf0b247c27086bad10568044c1196fe150f6cea1b" + "tx_body_hash": "c03c0dd28841d5aa87ce4e692ec8adde923799146ec5504e17ac0c95036362dd", + "ux_hash": "f7d30ecb49f132283862ad58f691e8747894c9fc241cb3a864fc15bd3e2c83d3" }, - "unspents": 14750, - "unconfirmed": 0, - "time_since_last_block": "12m6s" + "unspents": 38171, + "unconfirmed": 1, + "time_since_last_block": "4m46s" }, "version": { - "version": "0.23.0", - "commit": "f61b4319c2f146a5ad86f7cbda26a1ba6a09998d", + "version": "0.24.1", + "commit": "8798b5ee43c7ce43b9b75d57a1a6cd2c1295cd1e", "branch": "develop" }, - "open_connections": 30, - "uptime": "13.686460853s" + "open_connections": 8, + "uptime": "6m30.629057248s", + "csrf_enabled": true, + "csp_enabled": true, + "wallet_api_enabled": true, + "gui_enabled": true, + "unversioned_api_enabled": false, + "json_rpc_enabled": false }`, }, } From 18d5db0e3a2e16063b698cd37fb619e0cd44eb3d Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Wed, 10 Oct 2018 18:13:15 -0400 Subject: [PATCH 16/25] Fix normal e2e tests --- package.json | 2 +- protractor.conf.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 846b1c9d..bd6b9028 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "build": "ng build --prod", "test": "ng test", "lint": "ng lint", - "e2e": "ng e2e", + "e2e": "ng e2e skycoin-explorer-e2e", "e2e-blockchain-180": "ng e2e skycoin-explorer-e2e-blockchain-180", "snyk-protect": "snyk protect", "prepare": "npm run snyk-protect" diff --git a/protractor.conf.js b/protractor.conf.js index d7ec311d..2dae319c 100644 --- a/protractor.conf.js +++ b/protractor.conf.js @@ -9,7 +9,10 @@ exports.config = { './e2e/**/*.e2e-spec.ts' ], capabilities: { - 'browserName': 'chrome' + 'browserName': 'chrome', + chromeOptions: { + args: ['window-size=1920,1080'] + } }, directConnect: true, baseUrl: 'http://127.0.0.1:8001/', From 44d826600017112251f2a61f4e6f23a02bbeb64a Mon Sep 17 00:00:00 2001 From: Senyoret1 <34079003+Senyoret1@users.noreply.github.com> Date: Fri, 12 Oct 2018 08:57:00 -0400 Subject: [PATCH 17/25] Create tx info component --- src/app/app.module.ts | 2 + .../transaction-info.component.html | 70 +++++++++++++++++++ .../transaction-info.component.scss | 0 .../transaction-info.component.spec.ts | 25 +++++++ .../transaction-info.component.ts | 14 ++++ .../address-detail.component.html | 66 +---------------- .../block-details.component.html | 52 +------------- .../transaction-detail.component.html | 54 +------------- .../unconfirmed-transactions.component.html | 54 +------------- src/styles.scss | 4 -- 10 files changed, 115 insertions(+), 226 deletions(-) create mode 100644 src/app/components/layout/transaction-info/transaction-info.component.html create mode 100644 src/app/components/layout/transaction-info/transaction-info.component.scss create mode 100644 src/app/components/layout/transaction-info/transaction-info.component.spec.ts create mode 100644 src/app/components/layout/transaction-info/transaction-info.component.ts diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 709beed3..e730f2ab 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -31,6 +31,7 @@ import { DatePipe } from '@angular/common'; import { DateFormatterComponent } from 'app/components/layout/date-formatter/date-formatter.component'; import { SearchService } from './services/search/search.service'; import { SearchComponent } from './components/pages/search/search.component'; +import { TransactionInfoComponent } from './components/layout/transaction-info/transaction-info.component'; const ROUTES = [ @@ -108,6 +109,7 @@ const ROUTES = [ CopyButtonComponent, DateFormatterComponent, SearchComponent, + TransactionInfoComponent, ], imports: [ BrowserModule, diff --git a/src/app/components/layout/transaction-info/transaction-info.component.html b/src/app/components/layout/transaction-info/transaction-info.component.html new file mode 100644 index 00000000..a7d5d1d1 --- /dev/null +++ b/src/app/components/layout/transaction-info/transaction-info.component.html @@ -0,0 +1,70 @@ +
+ + +
+
+
{{ 'txBoxes.inputs' | translate }}
+
{{ 'txBoxes.outputs' | translate }}
+
+
+
+
+
+
{{ 'txBoxes.inputs' | translate }}
+
+ {{ input.owner }} +
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
+
{{ 'general.iniialHours' | translate }}: 
{{ input.hours | number:'1.0-6' }}
+
{{ 'general.calculatedHours' | translate }}: 
{{ input.calculatedHours | number:'1.0-6' }}
+
+
+
+
{{ 'txBoxes.outputs' | translate }}
+
+ {{ output.address }} +
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
+
{{ 'general.hours' | translate }}: 
{{ output.hours | number:'1.0-6' }}
+
+
+
+
+
+
{{ 'txBoxes.balance' | translate }}
+
+
+
{{ 'txBoxes.fee' | translate }}: 
+
{{ transaction.fee | number:'1.0-0' }}
+
+ +
+
{{ 'txBoxes.initialBalance' | translate }}: 
+
{{ transaction.initialBalance | number:'1.0-6' }}
+
+ +
+
{{ 'txBoxes.finalBalance' | translate }}: 
+
{{ transaction.finalBalance | number:'1.0-6' }}
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/src/app/components/layout/transaction-info/transaction-info.component.scss b/src/app/components/layout/transaction-info/transaction-info.component.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/app/components/layout/transaction-info/transaction-info.component.spec.ts b/src/app/components/layout/transaction-info/transaction-info.component.spec.ts new file mode 100644 index 00000000..7208f300 --- /dev/null +++ b/src/app/components/layout/transaction-info/transaction-info.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { TransactionInfoComponent } from './transaction-info.component'; + +describe('TransactionInfoComponent', () => { + let component: TransactionInfoComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ TransactionInfoComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(TransactionInfoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should be created', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/components/layout/transaction-info/transaction-info.component.ts b/src/app/components/layout/transaction-info/transaction-info.component.ts new file mode 100644 index 00000000..ffa11635 --- /dev/null +++ b/src/app/components/layout/transaction-info/transaction-info.component.ts @@ -0,0 +1,14 @@ +import { Component, Input } from '@angular/core'; +import { HeaderConfig } from 'app/app.config'; + +@Component({ + selector: 'transaction-info', + templateUrl: './transaction-info.component.html', + styleUrls: ['./transaction-info.component.scss'] +}) +export class TransactionInfoComponent { + @Input() transaction: any; + @Input() unconfirmed = false; + + constructor() { } +} diff --git a/src/app/components/pages/address-detail/address-detail.component.html b/src/app/components/pages/address-detail/address-detail.component.html index ff8fa466..bebaaa74 100644 --- a/src/app/components/pages/address-detail/address-detail.component.html +++ b/src/app/components/pages/address-detail/address-detail.component.html @@ -20,71 +20,7 @@

{{ 'addressDetail.title' | translate }}

-
-
-
-
-
-
{{ 'txBoxes.transactionID' | translate }}:

- -
-
- {{ (transaction.balance<0?"":"+")+(transaction.balance | number:'1.0-6') }} {{ 'general.coinIdentifier' | translate }} ({{ 'txBoxes.pending' | translate }}) -
-
-
-
{{ 'txBoxes.date' | translate }}:
-
-
- -
-
-
{{ 'txBoxes.inputs' | translate }}
-
{{ 'txBoxes.outputs' | translate }}
-
-
-
-
-
-
{{ 'txBoxes.inputs' | translate }}
-
- {{ input.owner }} -
{{ 'general.coins' | translate }}: 
{{ input.coins | number:'1.0-6' }}
-
{{ 'general.iniialHours' | translate }}: 
{{ input.hours | number:'1.0-6' }}
-
{{ 'general.calculatedHours' | translate }}: 
{{ input.calculatedHours | number:'1.0-6' }}
-
-
-
-
{{ 'txBoxes.outputs' | translate }}
-
- {{ output.address }} -
{{ 'general.coins' | translate }}: 
{{ output.coins | number:'1.0-6' }}
-
{{ 'general.hours' | translate }}: 
{{ output.hours | number:'1.0-6' }}
-
-
-
-
-
-
{{ 'txBoxes.balance' | translate }}
-
-
-
{{ 'txBoxes.fee' | translate }}: 
-
{{ transaction.fee | number:'1.0-0' }}
-
-
-
{{ 'txBoxes.initialBalance' | translate }}: 
-
{{ transaction.initialBalance | number:'1.0-6' }}
-
- -
-
{{ 'txBoxes.finalBalance' | translate }}: 
-
{{ transaction.finalBalance | number:'1.0-6' }}
-
-
-
-
-
-
+