diff --git a/backend/src/interfaces.ts b/backend/src/interfaces.ts
index 0360f727b..c8b7cdd0c 100644
--- a/backend/src/interfaces.ts
+++ b/backend/src/interfaces.ts
@@ -76,7 +76,7 @@ export interface Vout {
scriptpubkey: string;
scriptpubkey_asm: string;
scriptpubkey_type: string;
- scriptpubkey_address: string;
+ scriptpubkey_address?: string;
value: number;
asset?: string;
diff --git a/frontend/.gitignore b/frontend/.gitignore
index 7063e22de..1b086fca2 100644
--- a/frontend/.gitignore
+++ b/frontend/.gitignore
@@ -47,3 +47,4 @@ Thumbs.db
src/resources/assets.json
src/resources/assets.minimal.json
+src/resources/pools.json
diff --git a/frontend/package.json b/frontend/package.json
index 71591436f..473966eb8 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -23,8 +23,8 @@
"ng": "ng",
"start": "npm run sync-assets-dev && ng serve --proxy-config proxy.conf.json",
"build": "ng build --prod && npm run sync-assets",
- "sync-assets": "node sync-asset-registry.js",
- "sync-assets-dev": "node sync-asset-registry.js dev",
+ "sync-assets": "node sync-assets.js",
+ "sync-assets-dev": "node sync-assets.js dev",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index bfbac5ec0..6052b4c68 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -49,6 +49,7 @@ import { AssetComponent } from './components/asset/asset.component';
import { ScriptpubkeyTypePipe } from './pipes/scriptpubkey-type-pipe/scriptpubkey-type.pipe';
import { AssetsComponent } from './assets/assets.component';
import { RelativeUrlPipe } from './pipes/relative-url/relative-url.pipe';
+import { MinerComponent } from './pipes/miner/miner.component';
@NgModule({
declarations: [
@@ -88,6 +89,7 @@ import { RelativeUrlPipe } from './pipes/relative-url/relative-url.pipe';
ScriptpubkeyTypePipe,
AssetsComponent,
RelativeUrlPipe,
+ MinerComponent,
],
imports: [
BrowserModule,
diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html
index 50600233b..41c8cfd74 100644
--- a/frontend/src/app/components/block/block.component.html
+++ b/frontend/src/app/components/block/block.component.html
@@ -49,12 +49,12 @@
Total fees |
- () |
+ () |
Reward + fees: |
- ()
+ ()
|
@@ -68,6 +68,10 @@
|
+
+ Miner |
+ |
+
diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts
index 3f60e6b95..e815fceed 100644
--- a/frontend/src/app/components/block/block.component.ts
+++ b/frontend/src/app/components/block/block.component.ts
@@ -37,6 +37,7 @@ export class BlockComponent implements OnInit, OnDestroy {
.pipe(
switchMap((params: ParamMap) => {
const blockHash: string = params.get('id') || '';
+ this.block = undefined;
this.error = undefined;
this.fees = undefined;
diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss
index 819b6eb77..c78f6ec37 100644
--- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss
+++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss
@@ -57,7 +57,7 @@
width: 100%;
left: -12px;
text-shadow: 0px 32px 3px #111;
- z-index: 100;
+ z-index: 1;
}
.bitcoin-block::after {
diff --git a/frontend/src/app/pipes/miner/miner.component.html b/frontend/src/app/pipes/miner/miner.component.html
new file mode 100644
index 000000000..895e36622
--- /dev/null
+++ b/frontend/src/app/pipes/miner/miner.component.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+ {{ miner }}
+
+
+ Unknown
+
+
diff --git a/frontend/src/app/pipes/miner/miner.component.scss b/frontend/src/app/pipes/miner/miner.component.scss
new file mode 100644
index 000000000..b6e8c8ca1
--- /dev/null
+++ b/frontend/src/app/pipes/miner/miner.component.scss
@@ -0,0 +1,3 @@
+.badge {
+ font-size: 14px;
+}
diff --git a/frontend/src/app/pipes/miner/miner.component.ts b/frontend/src/app/pipes/miner/miner.component.ts
new file mode 100644
index 000000000..6e33c5f9c
--- /dev/null
+++ b/frontend/src/app/pipes/miner/miner.component.ts
@@ -0,0 +1,68 @@
+import { Component, Input, OnChanges } from '@angular/core';
+import { AssetsService } from 'src/app/services/assets.service';
+import { Transaction } from 'src/app/interfaces/electrs.interface';
+
+@Component({
+ selector: 'app-miner',
+ templateUrl: './miner.component.html',
+ styleUrls: ['./miner.component.scss'],
+})
+export class MinerComponent implements OnChanges {
+ @Input() coinbaseTransaction: Transaction;
+ miner = '';
+ title = '';
+ url = '';
+ loading = true;
+
+ constructor(
+ private assetsService: AssetsService,
+ ) { }
+
+ ngOnChanges() {
+ this.loading = true;
+ this.findMinerFromCoinbase();
+ }
+
+ findMinerFromCoinbase() {
+ if (this.coinbaseTransaction == null || this.coinbaseTransaction.vin == null || this.coinbaseTransaction.vin.length === 0) {
+ return null;
+ }
+
+ this.assetsService.getMiningPools$.subscribe((pools) => {
+ for (const vout of this.coinbaseTransaction.vout) {
+ if (!vout.scriptpubkey_address) {
+ continue;
+ }
+
+ if (pools.payout_addresses[vout.scriptpubkey_address]) {
+ this.miner = pools.payout_addresses[vout.scriptpubkey_address].name;
+ this.title = 'Identified by payout address: ' + vout.scriptpubkey_address;
+ this.url = pools.payout_addresses[vout.scriptpubkey_address].link;
+ break;
+ }
+
+ for (const tag in pools.coinbase_tags) {
+ if (pools.coinbase_tags.hasOwnProperty(tag)) {
+ const coinbaseAscii = this.hex2ascii(this.coinbaseTransaction.vin[0].scriptsig);
+ if (coinbaseAscii.indexOf(tag) > -1) {
+ this.miner = pools.coinbase_tags[tag].name;
+ this.title = 'Identified by coinbase tag: ' + tag;
+ this.url = pools.coinbase_tags[tag].link;
+ break;
+ }
+ }
+ }
+ }
+
+ this.loading = false;
+ });
+ }
+
+ hex2ascii(hex: string) {
+ let str = '';
+ for (let i = 0; i < hex.length; i += 2) {
+ str += String.fromCharCode(parseInt(hex.substr(i, 2), 16));
+ }
+ return str;
+ }
+}
diff --git a/frontend/src/app/services/assets.service.ts b/frontend/src/app/services/assets.service.ts
index 4023f048d..2adf57211 100644
--- a/frontend/src/app/services/assets.service.ts
+++ b/frontend/src/app/services/assets.service.ts
@@ -9,11 +9,13 @@ import { shareReplay } from 'rxjs/operators';
export class AssetsService {
getAssetsJson$: Observable;
getAssetsMinimalJson$: Observable;
+ getMiningPools$: Observable;
constructor(
private httpClient: HttpClient,
) {
this.getAssetsJson$ = this.httpClient.get('/resources/assets.json').pipe(shareReplay());
this.getAssetsMinimalJson$ = this.httpClient.get('/resources/assets.minimal.json').pipe(shareReplay());
+ this.getMiningPools$ = this.httpClient.get('/resources/pools.json').pipe(shareReplay());
}
}
diff --git a/frontend/sync-asset-registry.js b/frontend/sync-assets.js
similarity index 80%
rename from frontend/sync-asset-registry.js
rename to frontend/sync-assets.js
index 0b56cfcbc..304eae57a 100644
--- a/frontend/sync-asset-registry.js
+++ b/frontend/sync-assets.js
@@ -17,3 +17,5 @@ console.log('Downloading assets');
download(PATH + 'assets.json', 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.json');
console.log('Downloading assets minimal');
download(PATH + 'assets.minimal.json', 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.minimal.json');
+console.log('Downloading mining pools info');
+download(PATH + 'pools.json', 'https://raw.githubusercontent.com/btccom/Blockchain-Known-Pools/master/pools.json');
\ No newline at end of file