diff --git a/web-ui/src/app/app-routing.module.ts b/web-ui/src/app/app-routing.module.ts
index f6b3628f..79352934 100644
--- a/web-ui/src/app/app-routing.module.ts
+++ b/web-ui/src/app/app-routing.module.ts
@@ -1,20 +1,17 @@
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
-import { HomeComponent } from './components/home/home.component';
-import { TransactionComponent } from './components/transaction/transaction.component';
-import { AddressDetailsComponent } from './components/address-details/address-details.component';
-import { BlockComponent } from './components/block/block.component';
-import { MasternodeDetailsComponent } from './components/masternode-details/masternode-details.component';
import { TrezorConnectComponent } from './components/trezor-connect/trezor-connect.component';
+import { CalculatorComponent } from './components/calculator/calculator.component';
const routes: Routes = [
- { path: '', component: HomeComponent },
- { path: 'addresses/:address', component: AddressDetailsComponent },
- { path: 'blocks/:query', component: BlockComponent },
- { path: 'transactions/:txid', component: TransactionComponent },
- { path: 'masternodes/:ip', component: MasternodeDetailsComponent },
+ { path: '', loadChildren: './components/home/home.module#HomeModule' },
+ { path: 'blocks', loadChildren: './components/blocks/blocks.module#BlocksModule' },
+ { path: 'transactions', loadChildren: './components/transactions/transactions.module#TransactionsModule' },
+ { path: 'nodes', loadChildren: './components/nodes/nodes.module#NodesModule' },
+ { path: 'addresses', loadChildren: './components/addresses/addresses.module#AddressesModule' },
{ path: 'trezor', component: TrezorConnectComponent },
+ { path: 'calculator', component: CalculatorComponent },
{ path: '**', redirectTo: '' }
];
diff --git a/web-ui/src/app/app.component.html b/web-ui/src/app/app.component.html
index 754cb953..359bb35c 100644
--- a/web-ui/src/app/app.component.html
+++ b/web-ui/src/app/app.component.html
@@ -1,6 +1,8 @@
-
-
+
-
+
\ No newline at end of file
diff --git a/web-ui/src/app/app.component.ts b/web-ui/src/app/app.component.ts
index 603025e1..e099f2d7 100644
--- a/web-ui/src/app/app.component.ts
+++ b/web-ui/src/app/app.component.ts
@@ -73,7 +73,7 @@ export class AppComponent implements OnInit {
'TPoS': 'Trustless Proof of Stake',
// messages
- 'message.unavailable': 'Unavailable',
+ 'message.unavailable': '-',
'message.serverUnavailable': 'The server unavailable, please try again in a minute',
'message.unknownErrors': 'Unknown error, please try again in a minute',
'message.transactionNotFound': 'Transaction not found',
@@ -81,6 +81,7 @@ export class AppComponent implements OnInit {
'message.blockNotFound': 'Block not found',
'message.masternodeNotFound': 'Masternode not found',
'message.loadingLatestBlocks': 'Loading latest blocks...',
+ 'message.loadingTransactions': 'Loading transactions...',
'message.loadingRichestAddresses': 'Loading richest addresses...',
'message.transactionsNotAvailable': 'The transactions are not available, please try again in some minutes',
'message.totalSupply': 'The total number of coins generated (excluding the burned coins)',
@@ -98,11 +99,11 @@ export class AppComponent implements OnInit {
'action.verifyAddress': 'Show full address',
// labels
- 'label.searchField': 'Transaction id, Blockhash, Block number, Address, IP address',
+ 'label.searchField': 'Search by transaction ID, address, blockhash, block height, IP address',
'label.transactionId': 'Transaction Id',
'label.confirmations': 'Confirmations',
'label.blockhash': 'Block Hash',
- 'label.blocktime': 'Block Time',
+ 'label.blocktime': 'Time',
'label.medianTime': 'Median Time',
'label.noInput': 'No input',
'label.coinbase': 'Coinbase',
@@ -120,13 +121,24 @@ export class AppComponent implements OnInit {
'label.normalFee': 'Normal',
'label.lowFee': 'Low',
'label.satoshis': 'Satoshis',
+ 'label.showMore': 'Show More',
+ 'label.currentInflation': 'Current Inflation',
+ 'label.masternodeROI': 'Masternode ROI',
+ 'label.stakingROI': 'Staking ROI',
+ 'label.coinsInMasternodes': 'Coins in Masternodes',
+ 'label.tposNodes': 'TPoS Nodes',
+ 'label.coinsStaking': 'Coins Staking',
+ 'label.coinsTrustlesslyStaking': 'Coins Trustlessly Staking',
'label.address': 'Address',
+ 'label.addresses': 'Addresses',
+ 'label.ip': 'IP',
'label.balance': 'Balance',
'label.available': 'Available',
'label.received': 'Received',
'label.spent': 'Spent',
'label.transactionCount': 'Transactions',
+ 'label.transactinoLabel': 'Transactions',
'label.blockType': 'Block type',
'label.next': 'Next',
@@ -138,13 +150,18 @@ export class AppComponent implements OnInit {
'label.bits': 'Bits',
'label.chainwork': 'Chainwork',
'label.difficulty': 'Difficulty',
- 'label.transactions': 'Transactions',
+ 'label.transactions': 'TXS',
'label.rewards': 'Rewards',
'label.coinstake': 'Coinstake',
'label.masternode': 'Masternode',
'label.amount': 'Amount',
'label.blockReward': 'Block reward',
+ 'label.txHash': 'TX Hash',
+ 'label.type': 'Type',
+ 'label.result': 'Result',
+ 'label.time': 'Time',
+
'label.tposContract': 'Contract',
'label.owner': 'Owner',
'label.merchant': 'Merchant',
@@ -152,7 +169,9 @@ export class AppComponent implements OnInit {
'label.summary': 'Summary',
'label.block': 'Block',
'label.transaction': 'Transaction',
- 'label.height': 'Block height',
+ 'label.height': 'Height',
+ 'label.inflation': 'Inflation',
+ 'label.price': 'Price',
'label.extractedBy': 'Extracted by',
'label.latestBlocks': 'Latest 10 blocks',
'label.totalSupply': 'Total supply',
@@ -165,12 +184,41 @@ export class AppComponent implements OnInit {
'label.protocol': 'Protocol',
'label.status': 'Status',
'label.lastSeen': 'Last seen',
- 'label.payee': 'Payee',
- 'label.active': 'Active',
+ 'label.payee': 'Payee Address',
+ 'label.active': 'Active Since',
'label.details': 'Details',
'label.raw': 'Raw',
'label.date': 'Date',
- 'label.more': 'More'
+ 'label.more': 'More',
+ 'label.enabled': 'Enabled',
+ 'label.distributedAcross': 'Distributed Across',
+ 'label.protocols': 'Protocols',
+
+ 'label.isStakingCoinsTrustlessly': 'Is this address staking coins trustlessly?',
+ 'label.contractState': 'Contract state',
+ 'label.merchantAddress': 'Merchant address',
+ 'label.merchantCommission': 'Merchant commission',
+ 'label.contractTxid': 'Contract txid',
+
+ 'label.yes': 'Yes',
+ 'label.no': 'No',
+ 'label.tposDetails': 'TPoS Details',
+
+ 'label.calculator': 'Calculator',
+ 'label.xsnAmountHold': 'Amount of XSN you hold',
+ 'label.optimalSetup': 'Optimal setup',
+ 'label.masternodeAnd': 'Masternode(s) and',
+ 'label.xsnStaking': 'XSN staking',
+ 'label.masternodeStakingRemaining': 'Masternode(s) + staking remaining',
+ 'label.moreProfitable': 'is 33% more profitable',
+ 'label.stakingAllCoins': 'Staking all coins',
+ 'label.daily': 'Daily',
+ 'label.monthly': 'Monthly',
+ 'label.yearly': 'Yearly',
+ 'label.days': 'days',
+ 'label.waitingTimePerReward': 'Waiting time per reward (est.)',
+ 'label.requiredForMasternode': 'Required for Masternode',
+ 'label.rewardPerBlock': 'Reward per block'
};
}
}
diff --git a/web-ui/src/app/app.module.ts b/web-ui/src/app/app.module.ts
index 4577c524..40d9931d 100644
--- a/web-ui/src/app/app.module.ts
+++ b/web-ui/src/app/app.module.ts
@@ -1,22 +1,15 @@
-import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
-import { FormsModule, ReactiveFormsModule } from '@angular/forms';
-import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
-import { CommonModule } from '@angular/common';
+import { HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { AppRoutingModule } from './app-routing.module';
-import { AlertModule, BsDropdownModule, CollapseModule, TooltipModule, ModalModule } from 'ngx-bootstrap';
+import { AlertModule } from 'ngx-bootstrap';
import { TabsModule } from 'ngx-bootstrap/tabs';
import { TranslateModule } from '@ngx-translate/core';
import { ToastrModule } from 'ngx-toastr';
+import { FormsModule } from '@angular/forms';
import { NgHttpLoaderModule } from 'ng-http-loader';
-import { NgxPaginationModule } from 'ngx-pagination';
-
-import { MomentModule } from 'ngx-moment';
-
-import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { AddressesService } from './services/addresses.service';
import { BalancesService } from './services/balances.service';
@@ -31,71 +24,30 @@ import { TransactionsService } from './services/transactions.service';
import { TrezorRepositoryService } from './services/trezor-repository.service';
import { AppComponent } from './app.component';
-import { HomeComponent } from './components/home/home.component';
-import { FooterComponent } from './components/footer/footer.component';
-import { NavbarComponent } from './components/navbar/navbar.component';
-import { TransactionDetailsComponent } from './components/transaction-details/transaction-details.component';
-import { FinderComponent } from './components/finder/finder.component';
-import { AddressDetailsComponent } from './components/address-details/address-details.component';
-import { BlockDetailsComponent } from './components/block-details/block-details.component';
-import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.component';
-import { TickerComponent } from './components/ticker/ticker.component';
-import { RichestAddressesComponent } from './components/richest-addresses/richest-addresses.component';
-import { MasternodesComponent } from './components/masternodes/masternodes.component';
-import { MasternodeDetailsComponent } from './components/masternode-details/masternode-details.component';
-import { TransactionRawComponent } from './components/transaction-raw/transaction-raw.component';
-import { TransactionComponent } from './components/transaction/transaction.component';
-import { BlockComponent } from './components/block/block.component';
-import { BlockRawComponent } from './components/block-raw/block-raw.component';
-import { ExplorerDatetimePipe } from './pipes/explorer-datetime.pipe';
-import { ExplorerCurrencyPipe } from './pipes/explorer-currency.pipe';
-import { ExplorerAmountPipe } from './pipes/explorer-amount.pipe';
import { TrezorConnectComponent } from './components/trezor-connect/trezor-connect.component';
+import { SharedModule } from './components/shared/shared.module';
+import { PipesModule } from './pipes/pipes.module';
+import { TposnodesService } from './services/tposnodes.service';
+import { CalculatorComponent } from './components/calculator/calculator.component';
@NgModule({
declarations: [
AppComponent,
- HomeComponent,
- FooterComponent,
- NavbarComponent,
- TransactionDetailsComponent,
- FinderComponent,
- AddressDetailsComponent,
- BlockDetailsComponent,
- LatestBlocksComponent,
- TickerComponent,
- RichestAddressesComponent,
- MasternodesComponent,
- MasternodeDetailsComponent,
- TransactionRawComponent,
- TransactionComponent,
- BlockComponent,
- BlockRawComponent,
- ExplorerDatetimePipe,
- ExplorerCurrencyPipe,
- ExplorerAmountPipe,
- TrezorConnectComponent
+ TrezorConnectComponent,
+ CalculatorComponent
],
imports: [
AppRoutingModule,
- AlertModule.forRoot(),
- BsDropdownModule.forRoot(),
- CollapseModule.forRoot(),
- TooltipModule.forRoot(),
- ModalModule.forRoot(),
- CommonModule,
+ FormsModule,
+ SharedModule,
+ PipesModule,
BrowserAnimationsModule,
ToastrModule.forRoot(),
- BrowserModule,
- FormsModule,
- ReactiveFormsModule,
HttpClientModule,
NgHttpLoaderModule,
TranslateModule.forRoot(),
- NgxPaginationModule,
TabsModule.forRoot(),
- MomentModule,
- InfiniteScrollModule
+ AlertModule.forRoot()
],
providers: [
AddressesService,
@@ -104,6 +56,7 @@ import { TrezorConnectComponent } from './components/trezor-connect/trezor-conne
ErrorService,
LanguageService,
MasternodesService,
+ TposnodesService,
NavigatorService,
NotificationService,
TickerService,
diff --git a/web-ui/src/app/components/address-details/address-details.component.html b/web-ui/src/app/components/address-details/address-details.component.html
deleted file mode 100644
index 043c8464..00000000
--- a/web-ui/src/app/components/address-details/address-details.component.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
-
-
-
-
{{'message.addressNotFound' | translate}}
-
-
-
-
{{'label.address' | translate}}
- {{ addressLabel[addressString]}}
-
-
-
-
-
-
-
-
- | {{'label.summary' | translate}} |
- |
-
-
-
-
-
- | {{'label.address' | translate}} |
- {{addressString}} |
-
-
- | {{'label.balance' | translate}} |
- {{address.available | explorerCurrency}} |
-
-
- | {{'label.received' | translate}} |
- {{address.received | explorerCurrency}} |
-
-
- | {{'label.spent' | translate}} |
- {{address.spent | explorerCurrency}} |
-
-
-
-
-
-
-
-
-
-
-
{{'label.transactions' | translate}}
-
-
-
-
-
- | # |
- {{'label.transaction' | translate}} |
- {{'label.blockhash' | translate}} |
- {{'label.date' | translate}} |
- {{'label.value' | translate}} |
- {{'label.size' | translate}} |
-
-
-
-
-
- | {{index + 1}} |
-
- {{item.id | slice:0:15}}...
- |
-
- {{item.blockhash | slice:0:15}}...
- |
- {{item.time * 1000 | explorerDatetime}} |
- {{renderValue(item) | explorerCurrency}} |
- {{item.size}} bytes |
-
-
-
-
-
-
-
-
diff --git a/web-ui/src/app/components/addresses/address-details/address-details.component.css b/web-ui/src/app/components/addresses/address-details/address-details.component.css
new file mode 100644
index 00000000..75b2ac61
--- /dev/null
+++ b/web-ui/src/app/components/addresses/address-details/address-details.component.css
@@ -0,0 +1,5 @@
+.transaction-table-wrapper {
+ width: 100%;
+ padding: 0;
+ margin-top: 15px;
+}
\ No newline at end of file
diff --git a/web-ui/src/app/components/addresses/address-details/address-details.component.html b/web-ui/src/app/components/addresses/address-details/address-details.component.html
new file mode 100644
index 00000000..bdaf45d4
--- /dev/null
+++ b/web-ui/src/app/components/addresses/address-details/address-details.component.html
@@ -0,0 +1,108 @@
+
+
+
+
+
+ {{addressLabel[addressString] ? addressLabel[addressString] : 'label.address' | translate}}
+
+
+
+
+
+
{{'message.addressNotFound' | translate}}
+
+
+
+
+
+
+
+
+
+
+
+ {{'label.summary' | translate}}
+
+ |
+ |
+
+
+
+
+
+ | {{'label.address' | translate}} |
+ {{addressString}} |
+
+
+ | {{'label.balance' | translate}} |
+ {{address.available | explorerCurrency}} |
+
+
+ | {{'label.received' | translate}} |
+ {{address.received | explorerCurrency}} |
+
+
+ | {{'label.spent' | translate}} |
+ {{address.spent | explorerCurrency}} |
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{'label.tposDetails' | translate}} ({{'label.enabled' | translate | uppercase}})
+
+ |
+ |
+
+
+
+
+
+ | {{'label.isStakingCoinsTrustlessly' | translate}} |
+ {{'label.yes' | translate}} |
+
+
+ | {{'label.contractState' | translate}} |
+ {{tposContract ? tposContract.state : ''}} |
+
+
+ | {{'label.merchantAddress' | translate}} |
+
+ {{tposContract.merchant}}
+ |
+
+
+ | {{'label.merchantCommission' | translate}} |
+ {{tposContract ? tposContract.merchantCommission : ''}} |
+
+
+ | {{'label.contractTxid' | translate}} |
+
+ {{tposContract.txid}}
+ |
+
+
+
+
+
+
+
+
+
+
{{'label.transactinoLabel' | translate}}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web-ui/src/app/components/address-details/address-details.component.spec.ts b/web-ui/src/app/components/addresses/address-details/address-details.component.spec.ts
similarity index 71%
rename from web-ui/src/app/components/address-details/address-details.component.spec.ts
rename to web-ui/src/app/components/addresses/address-details/address-details.component.spec.ts
index 80af318f..cb24884a 100644
--- a/web-ui/src/app/components/address-details/address-details.component.spec.ts
+++ b/web-ui/src/app/components/addresses/address-details/address-details.component.spec.ts
@@ -1,14 +1,14 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AddressDetailsComponent } from './address-details.component';
-import { ExplorerCurrencyPipe } from '../../pipes/explorer-currency.pipe';
-import { ExplorerDatetimePipe } from '../../pipes/explorer-datetime.pipe';
+import { ExplorerCurrencyPipe } from '../../../pipes/explorer-currency.pipe';
+import { ExplorerDatetimePipe } from '../../../pipes/explorer-datetime.pipe';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
-import { AddressesService } from '../../services/addresses.service';
-import { ErrorService } from '../../services/error.service';
+import { AddressesService } from '../../../services/addresses.service';
+import { ErrorService } from '../../../services/error.service';
import { Observable } from 'rxjs';
import { NO_ERRORS_SCHEMA, } from '@angular/core';
@@ -17,11 +17,13 @@ describe('AddressDetailsComponent', () => {
let component: AddressDetailsComponent;
let fixture: ComponentFixture
;
- const addressesServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('AddressesService', ['get', 'getAddressesV2']);
+ const addressesServiceSpy: jasmine.SpyObj =
+ jasmine.createSpyObj('AddressesService', ['get', 'getAddressesV2', 'getTposContracts']);
const errorServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('ErrorService', ['renderServerErrors']);
beforeEach(async(() => {
addressesServiceSpy.get.and.returnValue(Observable.create());
+ addressesServiceSpy.getTposContracts.and.returnValue(Observable.create());
TestBed.configureTestingModule({
declarations: [
@@ -39,7 +41,7 @@ describe('AddressDetailsComponent', () => {
],
schemas: [NO_ERRORS_SCHEMA]
})
- .compileComponents();
+ .compileComponents();
}));
beforeEach(() => {
diff --git a/web-ui/src/app/components/address-details/address-details.component.ts b/web-ui/src/app/components/addresses/address-details/address-details.component.ts
similarity index 50%
rename from web-ui/src/app/components/address-details/address-details.component.ts
rename to web-ui/src/app/components/addresses/address-details/address-details.component.ts
index 67e0a01f..6813972e 100644
--- a/web-ui/src/app/components/address-details/address-details.component.ts
+++ b/web-ui/src/app/components/addresses/address-details/address-details.component.ts
@@ -1,15 +1,17 @@
-import {tap} from 'rxjs/operators';
+import { tap } from 'rxjs/operators';
import { Component, OnInit, HostListener } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
-import { Balance } from '../../models/balance';
-import { AddressesService } from '../../services/addresses.service';
-import { ErrorService } from '../../services/error.service';
-import { LightWalletTransaction } from '../..//models/light-wallet-transaction';
+import { Balance } from '../../../models/balance';
+import { AddressesService } from '../../../services/addresses.service';
+import { ErrorService } from '../../../services/error.service';
+import { LightWalletTransaction } from '../../../models/light-wallet-transaction';
-import { getNumberOfRowsForScreen } from '../../utils';
-import { addressLabels } from '../../config';
+import { getNumberOfRowsForScreen } from '../../../utils';
+import { addressLabels } from '../../../config';
+import { TposContract } from '../../../models/tposcontract';
+import { WrappedResult } from '../../../models/wrapped-result';
@Component({
selector: 'app-address-details',
@@ -21,6 +23,7 @@ export class AddressDetailsComponent implements OnInit {
address: Balance;
addressString: string;
addressLabel = addressLabels;
+ tposContract: TposContract = null;
// pagination
limit = 30;
@@ -34,29 +37,23 @@ export class AddressDetailsComponent implements OnInit {
ngOnInit() {
const height = this.getScreenSize();
this.limit = getNumberOfRowsForScreen(height);
- this.addressString = this.route.snapshot.paramMap.get('address');
+ this.addressString = this.route.snapshot.paramMap.get('id');
this.addressesService.get(this.addressString).subscribe(
response => this.onAddressRetrieved(response),
response => this.onError(response)
);
+ this.addressesService.getTposContracts(this.addressString).subscribe(
+ response => this.onTposContractsReceived(response),
+ response => this.onError(response)
+ );
}
private onAddressRetrieved(response: Balance) {
this.address = response;
- this.load();
}
- load() {
- const order = 'desc';
- let lastSeenTxid = '';
- if (this.items.length > 0) {
- lastSeenTxid = this.items[this.items.length - 1].id;
- }
-
- this.addressesService
- .getTransactionsV2(this.addressString, this.limit, lastSeenTxid, order).pipe(
- tap(response => this.items.push(...response.data)))
- .subscribe();
+ private onTposContractsReceived(response: WrappedResult) {
+ this.tposContract = response.data[0];
}
@HostListener('window:resize', ['$event'])
@@ -67,23 +64,4 @@ export class AddressDetailsComponent implements OnInit {
private onError(response: any) {
this.errorService.renderServerErrors(null, response);
}
-
- renderValue(tx: LightWalletTransaction): string {
- const spent = tx
- .inputs
- .map(input => input.value)
- .reduce((a, b) => a + b, 0);
-
- const received = tx
- .outputs
- .map(output => output.value)
- .reduce((a, b) => a + b, 0);
-
- const diff = Math.abs(received - spent);
- if (received >= spent) {
- return '+' + diff;
- } else {
- return '-' + diff;
- }
- }
}
diff --git a/web-ui/src/app/components/addresses/address-list/address-list.component.css b/web-ui/src/app/components/addresses/address-list/address-list.component.css
new file mode 100644
index 00000000..0ea14c57
--- /dev/null
+++ b/web-ui/src/app/components/addresses/address-list/address-list.component.css
@@ -0,0 +1,15 @@
+.new-address {
+ animation: blinker 1s linear;
+}
+
+@keyframes blinker {
+ 50% {
+ background-color: #FFFFFF08;
+ }
+}
+
+.address-table-wrapper {
+ width: 100%;
+ padding: 0;
+ margin-top: 15px;
+}
\ No newline at end of file
diff --git a/web-ui/src/app/components/addresses/address-list/address-list.component.html b/web-ui/src/app/components/addresses/address-list/address-list.component.html
new file mode 100644
index 00000000..94a5293f
--- /dev/null
+++ b/web-ui/src/app/components/addresses/address-list/address-list.component.html
@@ -0,0 +1,43 @@
+
+
+ {{'label.addresses' | translate}}
+
+
+
+
+
{{'label.richestAddresses' | translate}}
+
+
+
+
+
+
+ | # |
+ {{'label.address' | translate | uppercase}} |
+ {{'label.amount' | translate | uppercase}} |
+ {{'label.percentOfCoins' | translate | uppercase}} |
+ {{'label.addressLabel' | translate | uppercase}} |
+
+
+
+
+
+ | {{index + 1}} |
+
+ {{item.address}}
+ |
+ {{item.available | explorerCurrency}} |
+ {{'message.unavailable' | translate}} |
+
+ {{getPercent(item) | number:'1.2-2'}} %
+ |
+
+ {{addressLabel[item.address]}}
+ |
+
+
+
+
+
+
diff --git a/web-ui/src/app/components/richest-addresses/richest-addresses.component.spec.ts b/web-ui/src/app/components/addresses/address-list/address-list.component.spec.ts
similarity index 70%
rename from web-ui/src/app/components/richest-addresses/richest-addresses.component.spec.ts
rename to web-ui/src/app/components/addresses/address-list/address-list.component.spec.ts
index 54f2809e..bada6c47 100644
--- a/web-ui/src/app/components/richest-addresses/richest-addresses.component.spec.ts
+++ b/web-ui/src/app/components/addresses/address-list/address-list.component.spec.ts
@@ -1,21 +1,21 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-import { RichestAddressesComponent } from './richest-addresses.component';
-import { ExplorerCurrencyPipe } from '../../pipes/explorer-currency.pipe';
+import { AddressListComponent } from './address-list.component';
+import { ExplorerCurrencyPipe } from '../../../pipes/explorer-currency.pipe';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
import { TranslateModule } from '@ngx-translate/core';
-import { BalancesService } from '../../services/balances.service';
-import { TickerService } from '../../services/ticker.service';
-import { NotificationService } from '../../services/notification.service';
+import { BalancesService } from '../../../services/balances.service';
+import { TickerService } from '../../../services/ticker.service';
+import { NotificationService } from '../../../services/notification.service';
import { Observable } from 'rxjs';
import { NO_ERRORS_SCHEMA, } from '@angular/core';
-describe('RichestAddressesComponent', () => {
- let component: RichestAddressesComponent;
- let fixture: ComponentFixture;
+describe('AddressListComponent', () => {
+ let component: AddressListComponent;
+ let fixture: ComponentFixture;
const balancesServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('BalancesService', ['getHighest']);
const tickerServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('TickerService', ['get']);
@@ -27,7 +27,7 @@ describe('RichestAddressesComponent', () => {
TestBed.configureTestingModule({
declarations: [
- RichestAddressesComponent,
+ AddressListComponent,
ExplorerCurrencyPipe
],
imports: [
@@ -45,7 +45,7 @@ describe('RichestAddressesComponent', () => {
}));
beforeEach(() => {
- fixture = TestBed.createComponent(RichestAddressesComponent);
+ fixture = TestBed.createComponent(AddressListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
diff --git a/web-ui/src/app/components/richest-addresses/richest-addresses.component.ts b/web-ui/src/app/components/addresses/address-list/address-list.component.ts
similarity index 56%
rename from web-ui/src/app/components/richest-addresses/richest-addresses.component.ts
rename to web-ui/src/app/components/addresses/address-list/address-list.component.ts
index 2b61edec..42d612b5 100644
--- a/web-ui/src/app/components/richest-addresses/richest-addresses.component.ts
+++ b/web-ui/src/app/components/addresses/address-list/address-list.component.ts
@@ -2,22 +2,21 @@
import { tap } from 'rxjs/operators';
import { Component, OnInit, OnDestroy, HostListener } from '@angular/core';
-import { Balance } from '../../models/balance';
+import { Balance } from '../../../models/balance';
-import { BalancesService } from '../../services/balances.service';
-import { TickerService } from '../../services/ticker.service';
-import { NotificationService } from '../../services/notification.service';
-import { ServerStats } from '../../models/ticker';
+import { BalancesService } from '../../../services/balances.service';
+import { TickerService } from '../../../services/ticker.service';
+import { ServerStats } from '../../../models/ticker';
-import { getNumberOfRowsForScreen } from '../../utils';
-import { addressLabels } from '../../config';
+import { getNumberOfRowsForScreen } from '../../../utils';
+import { addressLabels } from '../../../config';
@Component({
- selector: 'app-richest-addresses',
- templateUrl: './richest-addresses.component.html',
- styleUrls: ['./richest-addresses.component.css']
+ selector: 'app-address-list',
+ templateUrl: './address-list.component.html',
+ styleUrls: ['./address-list.component.css']
})
-export class RichestAddressesComponent implements OnInit {
+export class AddressListComponent implements OnInit {
// ticker
ticker: ServerStats;
@@ -30,15 +29,13 @@ export class RichestAddressesComponent implements OnInit {
constructor(
private balancesService: BalancesService,
- private tickerService: TickerService,
- private notificationService: NotificationService) { }
+ private tickerService: TickerService) { }
ngOnInit() {
const height = this.getScreenSize();
- // this.limit = getNumberOfRowsForScreen(height);
+ this.limit = getNumberOfRowsForScreen(height);
this.load();
this.tickerService.get().subscribe(response => this.ticker = response);
- this.notificationService.warning("Mount our explorer (https://github.com/X9Developers/block-explorer/) on your computer and query the DB directly to view the full address database");
}
load() {
@@ -47,9 +44,9 @@ export class RichestAddressesComponent implements OnInit {
// here leads to inaccurate results.
//
// for now, let's limit this to 100 results only.
- if (this.items.length >= 100) {
- return;
- }
+ // if (this.items.length >= 100) {
+ // return;
+ // }
let lastSeenAddress = '';
if (this.items.length > 0) {
diff --git a/web-ui/src/app/components/addresses/addresses-routing.module.ts b/web-ui/src/app/components/addresses/addresses-routing.module.ts
new file mode 100644
index 00000000..daa35a26
--- /dev/null
+++ b/web-ui/src/app/components/addresses/addresses-routing.module.ts
@@ -0,0 +1,28 @@
+import { NgModule } from '@angular/core';
+import { RouterModule, Routes } from '@angular/router';
+import { AddressesComponent } from './addresses.component';
+import { AddressDetailsComponent } from './address-details/address-details.component';
+import { AddressListComponent } from './address-list/address-list.component';
+
+const routes: Routes = [
+ {
+ path: '',
+ component: AddressesComponent,
+ children: [
+ {
+ path: ':id',
+ component: AddressDetailsComponent
+ },
+ {
+ path: '',
+ component: AddressListComponent
+ }
+ ]
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(routes)],
+ exports: [RouterModule]
+})
+export class AddressesRoutingModule { }
diff --git a/web-ui/src/app/components/addresses/addresses.component.html b/web-ui/src/app/components/addresses/addresses.component.html
new file mode 100644
index 00000000..c5a194e2
--- /dev/null
+++ b/web-ui/src/app/components/addresses/addresses.component.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/web-ui/src/app/components/addresses/addresses.component.ts b/web-ui/src/app/components/addresses/addresses.component.ts
new file mode 100644
index 00000000..cbfab52f
--- /dev/null
+++ b/web-ui/src/app/components/addresses/addresses.component.ts
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-addresses',
+ templateUrl: './addresses.component.html'
+})
+export class AddressesComponent { }
diff --git a/web-ui/src/app/components/addresses/addresses.module.ts b/web-ui/src/app/components/addresses/addresses.module.ts
new file mode 100644
index 00000000..640693d2
--- /dev/null
+++ b/web-ui/src/app/components/addresses/addresses.module.ts
@@ -0,0 +1,37 @@
+import { NgModule } from '@angular/core';
+import { CommonModule } from '@angular/common';
+
+import { FormsModule, ReactiveFormsModule } from '@angular/forms';
+import { SharedModule } from '../shared/shared.module';
+import { TranslateModule } from '@ngx-translate/core';
+import { MomentModule } from 'ngx-moment';
+import { TabsModule, AlertModule } from 'ngx-bootstrap';
+import { PipesModule } from '../../pipes/pipes.module';
+import { InfiniteScrollModule } from 'ngx-infinite-scroll';
+import { AddressesRoutingModule } from './addresses-routing.module';
+import { AddressesComponent } from './addresses.component';
+import { AddressDetailsComponent } from './address-details/address-details.component';
+import { AddressListComponent } from './address-list/address-list.component';
+
+@NgModule({
+ imports: [
+ CommonModule,
+ FormsModule,
+ ReactiveFormsModule,
+ AddressesRoutingModule,
+ SharedModule,
+ PipesModule,
+ TranslateModule,
+ MomentModule,
+ TabsModule,
+ AlertModule,
+ InfiniteScrollModule
+ ],
+ declarations: [
+ AddressesComponent,
+ AddressDetailsComponent,
+ AddressListComponent
+ ]
+})
+
+export class AddressesModule { }
diff --git a/web-ui/src/app/components/block-details/block-details.component.html b/web-ui/src/app/components/block-details/block-details.component.html
deleted file mode 100644
index 56df6105..00000000
--- a/web-ui/src/app/components/block-details/block-details.component.html
+++ /dev/null
@@ -1,339 +0,0 @@
-
-
-
-
{{'message.blockNotFound' | translate}}
-
-
-
-
-
-
{{'label.block' | translate}} #{{blockDetails.block.height}}
-
-
-
-
-
-
- | {{'label.summary' | translate}} |
- |
-
-
-
-
-
-
- | {{'label.blockType' | translate}} |
- {{getBlockType(blockDetails)}} |
-
-
- | {{'label.tposContract' | translate}} |
-
- {{blockDetails.block.tposContract}}
- |
-
-
- | {{'label.blockhash' | translate}} |
- {{blockDetails.block.hash}} |
-
-
- | {{'label.merkleRoot' | translate}} |
- {{blockDetails.block.merkleRoot}} |
-
-
- | {{'label.confirmations' | translate}} |
- {{blockDetails.block.confirmations}} |
-
-
- | {{'label.size' | translate}} |
- {{blockDetails.block.size}} bytes |
-
-
- | {{'label.version' | translate}} |
- {{blockDetails.block.version}} |
-
-
- | {{'label.nonce' | translate}} |
- {{blockDetails.block.nonce}} |
-
-
- | {{'label.bits' | translate}} |
- {{blockDetails.block.bits}} |
-
-
- | {{'label.chainwork' | translate}} |
- {{blockDetails.block.chainwork}} |
-
-
- | {{'label.difficulty' | translate}} |
- {{blockDetails.block.difficulty}} |
-
-
- | {{'label.blocktime' | translate}} |
- {{blockDetails.block.time * 1000 | explorerDatetime}} |
-
-
- | {{'label.medianTime' | translate}} |
- {{blockDetails.block.medianTime * 1000 | explorerDatetime}} |
-
-
-
-
-
- |
-
- {{'label.previous' | translate}} ({{blockDetails.block.height - 1}})
-
- |
-
-
- {{'label.next' | translate}} ({{blockDetails.block.height + 1}})
-
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | {{'label.blockReward' | translate}} |
- {{blockDetails.rewards.reward.value | explorerCurrency}} |
-
-
-
-
-
- | {{'label.address' | translate}} |
-
- {{blockDetails.rewards.reward.address}}
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
- | {{'label.rewards' | translate}} |
- {{getPoSTotalReward(blockDetails) | explorerCurrency}} |
-
-
-
-
-
- |
- |
-
-
- |
- {{'label.coinstake' | translate}}
- |
- |
-
-
- | {{'label.amount' | translate}} |
- {{blockDetails.rewards.coinstake.value | explorerCurrency}} |
-
-
- | {{'label.address' | translate}} |
-
- {{blockDetails.rewards.coinstake.address}}
- |
-
-
- |
- |
-
-
- |
- {{'label.masternode' | translate}}
- |
- |
-
-
- | {{'label.amount' | translate}} |
- {{blockDetails.rewards.masternode.value | explorerCurrency}} |
-
-
- | {{'label.address' | translate}} |
-
- {{blockDetails.rewards.masternode.address}}
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
- | {{'label.rewards' | translate}} |
- {{getTPoSTotalReward(blockDetails) | explorerCurrency}} |
-
-
-
-
-
- |
- |
-
-
- |
- {{'label.owner' | translate}}
- |
- |
-
-
- | {{'label.amount' | translate}} |
- {{blockDetails.rewards.owner.value | explorerCurrency}} |
-
-
- | {{'label.address' | translate}} |
-
- {{blockDetails.rewards.owner.address}}
- |
-
-
-
- |
- |
-
-
- |
- {{'label.merchant' | translate}}
- |
- |
-
-
- | {{'label.amount' | translate}} |
- {{blockDetails.rewards.merchant.value | explorerCurrency}} |
-
-
- | {{'label.address' | translate}} |
-
- {{blockDetails.rewards.merchant.address}}
- |
-
-
-
- |
- |
-
-
- |
- {{'label.masternode' | translate}}
- |
- |
-
-
- | {{'label.amount' | translate}} |
- {{blockDetails.rewards.masternode.value | explorerCurrency}} |
-
-
- | {{'label.address' | translate}} |
-
- {{blockDetails.rewards.masternode.address}}
- |
-
-
-
-
-
-
-
-
-
-
-
-
{{'message.transactionsNotAvailable' | translate}}
-
-
-
-
-
-
-
-
-
-
-
- | # |
- {{'label.transaction' | translate}} |
- {{'label.date' | translate}} |
- {{'label.value' | translate}} |
- {{'label.size' | translate}} |
-
-
-
-
-
- | {{index + 1}} |
-
- {{item.id | slice:0:35}}...
- |
- {{item.time * 1000 | explorerDatetime}} |
- {{item.sent | explorerCurrency}} |
- {{item.size}} bytes |
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/web-ui/src/app/components/block-raw/block-raw.component.css b/web-ui/src/app/components/block-raw/block-raw.component.css
deleted file mode 100644
index e69de29b..00000000
diff --git a/web-ui/src/app/components/block/block.component.css b/web-ui/src/app/components/block/block.component.css
deleted file mode 100644
index e69de29b..00000000
diff --git a/web-ui/src/app/components/block/block.component.html b/web-ui/src/app/components/block/block.component.html
deleted file mode 100644
index 283915f8..00000000
--- a/web-ui/src/app/components/block/block.component.html
+++ /dev/null
@@ -1,14 +0,0 @@
-
diff --git a/web-ui/src/app/components/block/block.component.spec.ts b/web-ui/src/app/components/block/block.component.spec.ts
deleted file mode 100644
index 5bac74d8..00000000
--- a/web-ui/src/app/components/block/block.component.spec.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { async, ComponentFixture, TestBed } from '@angular/core/testing';
-
-import { BlockComponent } from './block.component';
-
-import { TranslateModule } from '@ngx-translate/core';
-
-import { NO_ERRORS_SCHEMA, } from '@angular/core';
-
-describe('BlockComponent', () => {
- let component: BlockComponent;
- let fixture: ComponentFixture
;
-
- beforeEach(async(() => {
- TestBed.configureTestingModule({
- declarations: [
- BlockComponent
- ],
- imports: [
- TranslateModule.forRoot()
- ],
- schemas: [NO_ERRORS_SCHEMA]
- })
- .compileComponents();
- }));
-
- beforeEach(() => {
- fixture = TestBed.createComponent(BlockComponent);
- component = fixture.componentInstance;
- fixture.detectChanges();
- });
-
- it('should create', () => {
- expect(component).toBeTruthy();
- });
-});
diff --git a/web-ui/src/app/components/block/block.component.ts b/web-ui/src/app/components/block/block.component.ts
deleted file mode 100644
index 95347d80..00000000
--- a/web-ui/src/app/components/block/block.component.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-
-@Component({
- selector: 'app-block',
- templateUrl: './block.component.html',
- styleUrls: ['./block.component.css']
-})
-export class BlockComponent implements OnInit {
-
- currentView = 'details';
-
- constructor() { }
-
- ngOnInit() {
- }
-
- selectView(view: string) {
- this.currentView = view;
- }
-
- isSelected(view: string): boolean {
- return this.currentView === view;
- }
-}
diff --git a/web-ui/src/app/components/blocks/block-details/block-details.component.css b/web-ui/src/app/components/blocks/block-details/block-details.component.css
new file mode 100644
index 00000000..5d8ed592
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-details/block-details.component.css
@@ -0,0 +1,37 @@
+.block-details-content {
+ font-size: 12px;
+}
+
+.block-details-left-side {
+ border-right: 1px solid #282D3C;
+ margin-right: -1px;
+}
+
+.block-details-right-side {
+ border-left: 1px solid #282D3C;
+}
+
+@media screen and (max-width: 1199px) {
+
+ .block-details-left-side,
+ .block-details-right-side {
+ border: none;
+ margin-right: 0;
+ }
+
+ .block-details-right-side>div:first-child {
+ border-top: 1px solid #282D3C;
+ }
+}
+
+.block-details-label-row {
+ font-size: 14px;
+}
+
+.block-details-transactions-container {
+ padding-top: 10px;
+}
+
+.block-details-transactions-container>div:first-child {
+ border-top: 1px solid #282D3C;
+}
\ No newline at end of file
diff --git a/web-ui/src/app/components/blocks/block-details/block-details.component.html b/web-ui/src/app/components/blocks/block-details/block-details.component.html
new file mode 100644
index 00000000..607deb48
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-details/block-details.component.html
@@ -0,0 +1,306 @@
+
+
+
+
{{'message.blockNotFound' | translate}}
+
+
+
+
+
+
+
+
+
+ |
+ {{'label.summary' | translate | uppercase}}
+ |
+
+
+
+
+ | {{'label.blockType' | translate}} |
+ {{getBlockType(blockDetails)}} |
+
+
+ | {{'label.tposContract' | translate}} |
+
+ {{blockDetails.block.tposContract}}
+ |
+
+
+ | {{'label.blockhash' | translate}} |
+ {{blockDetails.block.hash}} |
+
+
+ | {{'label.merkleRoot' | translate}} |
+ {{blockDetails.block.merkleRoot}} |
+
+
+ | {{'label.confirmations' | translate}} |
+ {{blockDetails.block.confirmations}} |
+
+
+ | {{'label.size' | translate}} |
+ {{blockDetails.block.size}} bytes |
+
+
+ | {{'label.version' | translate}} |
+ {{blockDetails.block.version}} |
+
+
+ | {{'label.nonce' | translate}} |
+ {{blockDetails.block.nonce}} |
+
+
+ | {{'label.bits' | translate}} |
+ {{blockDetails.block.bits}} |
+
+
+ | {{'label.chainwork' | translate}} |
+ {{blockDetails.block.chainwork}} |
+
+
+ | {{'label.difficulty' | translate}} |
+ {{blockDetails.block.difficulty}} |
+
+
+ | {{'label.blocktime' | translate}} |
+ {{blockDetails.block.time * 1000 | explorerDatetime}} |
+
+
+ | {{'label.medianTime' | translate}} |
+ {{blockDetails.block.medianTime * 1000 | explorerDatetime}} |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{'label.blockReward' | translate | uppercase}}
+ {{blockDetails.rewards.reward.value | explorerCurrency}}
+ |
+
+
+
+ | {{'label.address' | translate}} |
+
+ {{blockDetails.rewards.reward.address}}
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{'label.rewards' | translate | uppercase}}
+ {{getPoSTotalReward(blockDetails) | explorerCurrency}}
+ |
+
+
+ |
+ |
+
+
+ |
+ {{'label.coinstake' | translate | uppercase}}
+ |
+
+
+ | {{'label.amount' | translate}} |
+ {{blockDetails.rewards.coinstake.value | explorerCurrency}} |
+
+
+ | {{'label.address' | translate}} |
+
+ {{blockDetails.rewards.coinstake.address}}
+ |
+
+
+ |
+ |
+
+
+ |
+ {{'label.masternode' | translate | uppercase}}
+ |
+
+
+ | {{'label.amount' | translate}} |
+ {{blockDetails.rewards.masternode.value | explorerCurrency}} |
+
+
+ | {{'label.address' | translate}} |
+
+ {{blockDetails.rewards.masternode.address}}
+ |
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{'label.rewards' | translate | uppercase}}
+ {{getTPoSTotalReward(blockDetails) | explorerCurrency}}
+ |
+
+
+ |
+ |
+
+
+ |
+ {{'label.owner' | translate | uppercase}}
+ |
+
+
+ | {{'label.amount' | translate}} |
+ {{blockDetails.rewards.owner.value | explorerCurrency}} |
+
+
+ | {{'label.address' | translate}} |
+
+ {{blockDetails.rewards.owner.address}}
+ |
+
+
+
+ |
+ |
+
+
+ |
+ {{'label.merchant' | translate | uppercase}}
+ |
+
+
+ | {{'label.amount' | translate}} |
+ {{blockDetails.rewards.merchant.value | explorerCurrency}} |
+
+
+ | {{'label.address' | translate}} |
+
+ {{blockDetails.rewards.merchant.address}}
+ |
+
+
+
+ |
+ |
+
+
+ |
+ {{'label.masternode' | translate | uppercase}}
+ |
+
+
+ | {{'label.amount' | translate}} |
+ {{blockDetails.rewards.masternode.value | explorerCurrency}} |
+
+
+ | {{'label.address' | translate}} |
+
+ {{blockDetails.rewards.masternode.address}}
+ |
+
+
+
+
+
+
+
+
+
+
+
+
{{'message.transactionsNotAvailable' | translate}}
+
+
+
+
+
+
+
+
+
+ | # |
+ {{'label.transaction' | translate}} |
+ {{'label.date' | translate}} |
+ {{'label.value' | translate}} |
+ {{'label.size' | translate}} |
+
+
+
+
+
+ | {{index + 1}} |
+
+ {{item.id | slice:0:35}}...
+ |
+ {{item.time * 1000 | explorerDatetime}} |
+ {{item.sent | explorerCurrency}} |
+ {{item.size}} bytes |
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/web-ui/src/app/components/blocks/block-details/block-details.component.spec.ts b/web-ui/src/app/components/blocks/block-details/block-details.component.spec.ts
new file mode 100644
index 00000000..a084b3a8
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-details/block-details.component.spec.ts
@@ -0,0 +1,97 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { BlockDetailsComponent } from './block-details.component';
+import { ExplorerCurrencyPipe } from '../../../pipes/explorer-currency.pipe';
+import { ExplorerDatetimePipe } from '../../../pipes/explorer-datetime.pipe';
+
+import { RouterTestingModule } from '@angular/router/testing';
+import { TranslateModule } from '@ngx-translate/core';
+
+import { BlocksService } from '../../../services/blocks.service';
+import { ErrorService } from '../../../services/error.service';
+import { Observable } from 'rxjs';
+
+import { NO_ERRORS_SCHEMA, } from '@angular/core';
+
+const sampleBlockDetails = {
+ 'block': {
+ 'hash': '225f7e1388f4d4199033ff077d0ece9aaa04d82fda8cc3c5789fa18f2a84b597',
+ 'previousBlockhash': '83b8ebe36a88e6a2df01abcd97aae6c908be9088e94379f9cc4f533a171db43f',
+ 'nextBlockhash': 'dc4cfb8f386e5cedbbe002da267a19daeb2598ce500bd1bb04c1fa59cffbbf99',
+ 'merkleRoot': '29d826f65e46a9cdb09740a576cb066ba10e4acdb27977340a6a9b571042bf76',
+ 'transactions': [
+ 'b2b3029d694ce3ad1cbbc3f49f5d1c94b63a313ab4bc26a13a5094826b305ef8',
+ 'fc9d478982c89b1e309bb42bd1ce64c5a99f7a818d5e9e4920a6a70a31bd168e'
+ ],
+ 'confirmations': 3,
+ 'size': 490,
+ 'height': 1277693,
+ 'version': 536870912,
+ 'time': 1597940753,
+ 'medianTime': 1597940526,
+ 'nonce': 0,
+ 'bits': '1c0143a1',
+ 'chainwork': '0000000000000000000000000000000000000000000000000c4daa33831c9b22',
+ 'difficulty': 202.5004526306896,
+ 'tposContract': '6170c1916b53f7c18353dc6271efa53bf17f43635de571976a9a7719fad76be0'
+ },
+ 'rewards': {
+ 'owner': {
+ 'address': 'XvfB23af9aFfqZ2NFGqqwsUcitUkKH5RwM',
+ 'value': 8.73
+ },
+ 'merchant': {
+ 'address': 'XczvAzAPnqAa2hQL3ip1rJHmiBoZ6E5RGM',
+ 'value': 0.27
+ },
+ 'masternode': {
+ 'address': 'XwyktBrhrGct4BuJCt3GAPvV6jNyo4Stfw',
+ 'value': 9
+ },
+ 'coinstake': null,
+ 'reward': null,
+ 'stakedAmount': 2008.82863013,
+ 'stakedDuration': 358545
+ }
+};
+
+describe('BlockDetailsComponent', () => {
+ let component: BlockDetailsComponent;
+ let fixture: ComponentFixture;
+
+ const blocksServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('BlocksService', ['getTransactionsV2', 'pipe', 'tape']);
+ const errorServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('ErrorService', ['renderServerErrors']);
+
+ beforeEach(async(() => {
+ blocksServiceSpy.getTransactionsV2.and.returnValue(Observable.create());
+
+ TestBed.configureTestingModule({
+ declarations: [
+ BlockDetailsComponent,
+ ExplorerCurrencyPipe,
+ ExplorerDatetimePipe
+ ],
+ imports: [
+ RouterTestingModule,
+ TranslateModule.forRoot()
+ ],
+ providers: [
+ { provide: BlocksService, useValue: blocksServiceSpy },
+ { provide: ErrorService, useValue: errorServiceSpy }
+ ],
+ schemas: [NO_ERRORS_SCHEMA]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BlockDetailsComponent);
+ component = fixture.componentInstance;
+ component.blockDetails = sampleBlockDetails;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/web-ui/src/app/components/block-details/block-details.component.ts b/web-ui/src/app/components/blocks/block-details/block-details.component.ts
similarity index 58%
rename from web-ui/src/app/components/block-details/block-details.component.ts
rename to web-ui/src/app/components/blocks/block-details/block-details.component.ts
index 16bcb31a..c9f64ad2 100644
--- a/web-ui/src/app/components/block-details/block-details.component.ts
+++ b/web-ui/src/app/components/blocks/block-details/block-details.component.ts
@@ -1,16 +1,10 @@
+import { Component, OnInit, Input, HostListener } from '@angular/core';
+import { tap } from 'rxjs/operators';
-import {tap} from 'rxjs/operators';
-import { Component, OnInit, HostListener } from '@angular/core';
-import { ActivatedRoute } from '@angular/router';
-
-import { BlockDetails } from '../../models/block';
-import { Transaction } from '../../models/transaction';
-
-import { BlocksService } from '../../services/blocks.service';
-import { ErrorService } from '../../services/error.service';
-import { PaginatedResult } from '../../models/paginated-result';
-
-import { getNumberOfRowsForScreen } from '../../utils';
+import { BlockDetails } from '../../../models/block';
+import { Transaction } from '../../../models/transaction';
+import { BlocksService } from '../../../services/blocks.service';
+import { getNumberOfRowsForScreen } from '../../../utils';
@Component({
selector: 'app-block-details',
@@ -19,42 +13,25 @@ import { getNumberOfRowsForScreen } from '../../utils';
})
export class BlockDetailsComponent implements OnInit {
- blockhash: string;
+ @Input()
blockDetails: BlockDetails;
// pagination
limit = 30;
transactions: Transaction[] = [];
- constructor(
- private route: ActivatedRoute,
- private blocksService: BlocksService,
- private errorService: ErrorService) { }
+ constructor(private blocksService: BlocksService) { }
ngOnInit() {
const height = this.getScreenSize();
this.limit = getNumberOfRowsForScreen(height);
- this.route.params.forEach(params => this.onQuery(params['query']));
- }
- private onQuery(query: string) {
- this.clearCurrentValues();
- this.blocksService.get(query).subscribe(
- response => this.onBlockRetrieved(response),
- response => this.onError(response)
- );
- }
-
- private clearCurrentValues() {
- this.blockhash = null;
- this.blockDetails = null;
- this.transactions = [];
+ this.load();
}
- private onBlockRetrieved(response: BlockDetails) {
- this.blockDetails = response;
- this.blockhash = response.block.hash;
- this.load();
+ @HostListener('window:resize', ['$event'])
+ private getScreenSize(_?): number {
+ return window.innerHeight;
}
load() {
@@ -64,20 +41,11 @@ export class BlockDetailsComponent implements OnInit {
}
this.blocksService
- .getTransactionsV2(this.blockhash, this.limit, lastSeenTxid).pipe(
- tap(response => this.transactions.push(...response.data)))
+ .getTransactionsV2(this.blockDetails.block.hash, this.limit, lastSeenTxid).pipe(
+ tap(response => this.transactions.push(...response.data)))
.subscribe();
}
- @HostListener('window:resize', ['$event'])
- private getScreenSize(_?): number {
- return window.innerHeight;
- }
-
- private onError(response: any) {
- this.errorService.renderServerErrors(null, response);
- }
-
getBlockType(details: BlockDetails): string {
if (details.block.tposContract != null) {
return 'Trustless Proof of Stake';
diff --git a/web-ui/src/app/components/blocks/block-list/block-list.component.css b/web-ui/src/app/components/blocks/block-list/block-list.component.css
new file mode 100644
index 00000000..f519295b
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-list/block-list.component.css
@@ -0,0 +1,20 @@
+.block-table-wrapper {
+ width: 100%;
+ padding: 0;
+ margin-top: 15px;
+}
+
+.blocks-info {
+ float: right;
+ background-color: #1C202E;
+ border-radius: 20px;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ padding: 2px 6px;
+ font-size: 12px;
+}
+
+.blocks-info>div {
+ margin: 10px;
+}
\ No newline at end of file
diff --git a/web-ui/src/app/components/blocks/block-list/block-list.component.html b/web-ui/src/app/components/blocks/block-list/block-list.component.html
new file mode 100644
index 00000000..a9881094
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-list/block-list.component.html
@@ -0,0 +1,21 @@
+
+
+ {{'label.blocks' | translate}}
+
+
+
+
+ {{'label.height' | translate | uppercase}}: {{stats.blocks}}
+
+
+ {{'label.inflation' | translate | uppercase}}: 7.58%
+
+
+ {{'label.price' | translate | uppercase}}: ${{prices.usd}}
+
+
+
+
+
\ No newline at end of file
diff --git a/web-ui/src/app/components/blocks/block-list/block-list.component.spec.ts b/web-ui/src/app/components/blocks/block-list/block-list.component.spec.ts
new file mode 100644
index 00000000..fc0c920a
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-list/block-list.component.spec.ts
@@ -0,0 +1,44 @@
+import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { TranslateModule } from '@ngx-translate/core';
+
+import { BlockListComponent } from './block-list.component';
+
+import { NO_ERRORS_SCHEMA, } from '@angular/core';
+import { TickerService } from '../../../services/ticker.service';
+import { Observable } from 'rxjs';
+
+describe('BlockListComponent', () => {
+ let component: BlockListComponent;
+ let fixture: ComponentFixture;
+
+ const tickerServiceSpy: jasmine.SpyObj = jasmine.createSpyObj('TickerService', ['get', 'getPrices']);
+
+ beforeEach(async(() => {
+ tickerServiceSpy.get.and.returnValue(Observable.create());
+ tickerServiceSpy.getPrices.and.returnValue(Observable.create());
+
+ TestBed.configureTestingModule({
+ declarations: [
+ BlockListComponent
+ ],
+ imports: [
+ TranslateModule.forRoot()
+ ],
+ schemas: [NO_ERRORS_SCHEMA],
+ providers: [
+ { provide: TickerService, useValue: tickerServiceSpy }
+ ]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(BlockListComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/web-ui/src/app/components/blocks/block-list/block-list.component.ts b/web-ui/src/app/components/blocks/block-list/block-list.component.ts
new file mode 100644
index 00000000..31a9d861
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-list/block-list.component.ts
@@ -0,0 +1,32 @@
+import { Component, OnInit } from '@angular/core';
+import { Prices, ServerStats } from '../../../models/ticker';
+import { TickerService } from '../../../services/ticker.service';
+
+@Component({
+ selector: 'app-block-list',
+ templateUrl: './block-list.component.html',
+ styleUrls: ['./block-list.component.css']
+})
+export class BlockListComponent implements OnInit {
+
+ prices: Prices = new Prices();
+ stats: ServerStats = new ServerStats();
+
+ constructor(private tickerService: TickerService) { }
+
+ ngOnInit() {
+ this.tickerService
+ .getPrices()
+ .subscribe(
+ response => this.prices = response,
+ response => console.log(response)
+ );
+
+ this.tickerService
+ .get()
+ .subscribe(
+ response => this.stats = response,
+ response => console.log(response)
+ );
+ }
+}
diff --git a/web-ui/src/app/components/blocks/block-raw/block-raw.component.css b/web-ui/src/app/components/blocks/block-raw/block-raw.component.css
new file mode 100644
index 00000000..c5a0d11b
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block-raw/block-raw.component.css
@@ -0,0 +1,5 @@
+pre {
+ background-color: transparent;
+ border: none;
+ padding: 10px 20px;
+}
\ No newline at end of file
diff --git a/web-ui/src/app/components/block-raw/block-raw.component.html b/web-ui/src/app/components/blocks/block-raw/block-raw.component.html
similarity index 70%
rename from web-ui/src/app/components/block-raw/block-raw.component.html
rename to web-ui/src/app/components/blocks/block-raw/block-raw.component.html
index a484b7e7..c7b78029 100644
--- a/web-ui/src/app/components/block-raw/block-raw.component.html
+++ b/web-ui/src/app/components/blocks/block-raw/block-raw.component.html
@@ -3,6 +3,6 @@
{{'message.blockNotFound' | translate}}
-
{{block | json}}
+
{{block | json}}
-
+
\ No newline at end of file
diff --git a/web-ui/src/app/components/block-raw/block-raw.component.spec.ts b/web-ui/src/app/components/blocks/block-raw/block-raw.component.spec.ts
similarity index 85%
rename from web-ui/src/app/components/block-raw/block-raw.component.spec.ts
rename to web-ui/src/app/components/blocks/block-raw/block-raw.component.spec.ts
index 5c8f7011..92043d53 100644
--- a/web-ui/src/app/components/block-raw/block-raw.component.spec.ts
+++ b/web-ui/src/app/components/blocks/block-raw/block-raw.component.spec.ts
@@ -5,9 +5,9 @@ import { BlockRawComponent } from './block-raw.component';
import { RouterTestingModule } from '@angular/router/testing';
import { TranslateModule } from '@ngx-translate/core';
-import { NavigatorService } from './../../services/navigator.service';
-import { BlocksService } from '../../services/blocks.service';
-import { ErrorService } from '../../services/error.service';
+import { NavigatorService } from '../../../services/navigator.service';
+import { BlocksService } from '../../../services/blocks.service';
+import { ErrorService } from '../../../services/error.service';
import { TranslateService } from '@ngx-translate/core';
import { NO_ERRORS_SCHEMA, } from '@angular/core';
@@ -26,7 +26,7 @@ describe('BlockRawComponent', () => {
blocksServiceSpy.getRaw.and.returnValue(Observable.create());
TestBed.configureTestingModule({
- declarations: [ BlockRawComponent ],
+ declarations: [BlockRawComponent],
imports: [
RouterTestingModule,
TranslateModule.forRoot()
@@ -39,7 +39,7 @@ describe('BlockRawComponent', () => {
],
schemas: [NO_ERRORS_SCHEMA]
})
- .compileComponents();
+ .compileComponents();
}));
beforeEach(() => {
diff --git a/web-ui/src/app/components/block-raw/block-raw.component.ts b/web-ui/src/app/components/blocks/block-raw/block-raw.component.ts
similarity index 79%
rename from web-ui/src/app/components/block-raw/block-raw.component.ts
rename to web-ui/src/app/components/blocks/block-raw/block-raw.component.ts
index 7f97862e..9e6cb264 100644
--- a/web-ui/src/app/components/block-raw/block-raw.component.ts
+++ b/web-ui/src/app/components/blocks/block-raw/block-raw.component.ts
@@ -3,11 +3,11 @@ import { ActivatedRoute, Router } from '@angular/router';
import { TranslateService } from '@ngx-translate/core';
-import { Transaction } from '../../models/transaction';
+import { Transaction } from '../../../models/transaction';
-import { ErrorService } from '../../services/error.service';
-import { NavigatorService } from '../../services/navigator.service';
-import { BlocksService } from '../../services/blocks.service';
+import { ErrorService } from '../../../services/error.service';
+import { NavigatorService } from '../../../services/navigator.service';
+import { BlocksService } from '../../../services/blocks.service';
@Component({
selector: 'app-block-raw',
@@ -26,7 +26,7 @@ export class BlockRawComponent implements OnInit {
private errorService: ErrorService) { }
ngOnInit() {
- this.route.params.forEach(params => this.onBlockQuery(params['query']));
+ this.route.params.forEach(params => this.onBlockQuery(params['id']));
}
private onBlockQuery(query: string) {
diff --git a/web-ui/src/app/components/blocks/block/block.component.css b/web-ui/src/app/components/blocks/block/block.component.css
new file mode 100644
index 00000000..3f1620ae
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block/block.component.css
@@ -0,0 +1,43 @@
+.block-tab-bar {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: flex-end;
+}
+
+.block-tab-bar>li>a {
+ color: #01D9DE;
+ background-color: transparent;
+ font-size: 14px;
+ padding: 0;
+}
+
+.block-tab-bar>li {
+ margin: 0 5px;
+ padding: 13px 13px 9px;
+ cursor: pointer;
+}
+
+.block-tab-bar>li.active>a {
+ color: #FFFFFF;
+}
+
+.block-tab-bar>li.active,
+.block-tab-bar>li:hover {
+ background-color: #222534;
+ border-radius: 20px;
+}
+
+.block-tab-content {
+ padding: 10px 0;
+ border-top: 1px solid #282D3C;
+}
+
+.block-tab-footer {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+ padding: 20px;
+ border-top: 1px solid #282D3C;
+}
\ No newline at end of file
diff --git a/web-ui/src/app/components/blocks/block/block.component.html b/web-ui/src/app/components/blocks/block/block.component.html
new file mode 100644
index 00000000..d36fe840
--- /dev/null
+++ b/web-ui/src/app/components/blocks/block/block.component.html
@@ -0,0 +1,37 @@
+