Merge branch 'master' into mononaut/fix-liquid-fees

This commit is contained in:
wiz 2023-07-21 17:38:47 +09:00 committed by GitHub
commit 7a6da07a61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 161 additions and 45 deletions

View File

@ -7,7 +7,8 @@ updates:
open-pull-requests-limit: 10 open-pull-requests-limit: 10
ignore: ignore:
- dependency-name: "*" - dependency-name: "*"
update-types: ["version-update:semver-major"] update-types:
["version-update:semver-major", "version-update:semver-patch"]
allow: allow:
- dependency-type: "production" - dependency-type: "production"
@ -18,7 +19,8 @@ updates:
open-pull-requests-limit: 10 open-pull-requests-limit: 10
ignore: ignore:
- dependency-name: "*" - dependency-name: "*"
update-types: ["version-update:semver-major"] update-types:
["version-update:semver-major", "version-update:semver-patch"]
allow: allow:
- dependency-type: "production" - dependency-type: "production"
@ -28,7 +30,8 @@ updates:
interval: weekly interval: weekly
ignore: ignore:
- dependency-name: "*" - dependency-name: "*"
update-types: ["version-update:semver-major"] update-types:
["version-update:semver-major", "version-update:semver-patch"]
- package-ecosystem: docker - package-ecosystem: docker
directory: "/docker/frontend" directory: "/docker/frontend"
@ -36,7 +39,8 @@ updates:
interval: weekly interval: weekly
ignore: ignore:
- dependency-name: "*" - dependency-name: "*"
update-types: ["version-update:semver-major"] update-types:
["version-update:semver-major", "version-update:semver-patch"]
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
@ -44,4 +48,5 @@ updates:
interval: weekly interval: weekly
ignore: ignore:
- dependency-name: "*" - dependency-name: "*"
update-types: ["version-update:semver-major"] update-types:
["version-update:semver-major", "version-update:semver-patch"]

View File

@ -9,7 +9,7 @@ jobs:
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')" if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
strategy: strategy:
matrix: matrix:
node: ["16", "17", "18"] node: ["16", "17", "18", "20"]
flavor: ["dev", "prod"] flavor: ["dev", "prod"]
fail-fast: false fail-fast: false
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"
@ -60,7 +60,7 @@ jobs:
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')" if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
strategy: strategy:
matrix: matrix:
node: ["16", "17", "18"] node: ["16", "17", "18", "20"]
flavor: ["dev", "prod"] flavor: ["dev", "prod"]
fail-fast: false fail-fast: false
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"

1
backend/.dockerignore Normal file
View File

@ -0,0 +1 @@
Dockerfile

View File

@ -2,7 +2,7 @@
These instructions are mostly intended for developers. These instructions are mostly intended for developers.
If you choose to use these instructions for a production setup, be aware that you will still probably need to do additional configuration for your specific OS, environment, use-case, etc. We do our best here to provide a good starting point, but only proceed if you know what you're doing. Mempool does not provide support for custom setups. If you choose to use these instructions for a production setup, be aware that you will still probably need to do additional configuration for your specific OS, environment, use-case, etc. We do our best here to provide a good starting point, but only proceed if you know what you're doing. Mempool only provides support for custom setups to [enterprise sponsors](https://mempool.space/enterprise).
See other ways to set up Mempool on [the main README](/../../#installation-methods). See other ways to set up Mempool on [the main README](/../../#installation-methods).

View File

@ -7,9 +7,10 @@ WORKDIR /build
COPY . . COPY . .
RUN apt-get update RUN apt-get update
RUN apt-get install -y build-essential python3 pkg-config curl RUN apt-get install -y build-essential python3 pkg-config curl ca-certificates
# Install Rust via rustup # Install Rust via rustup
RUN CPU_ARCH=$(uname -m); if [ "$CPU_ARCH" = "armv7l" ]; then c_rehash; fi
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain stable
ENV PATH="/root/.cargo/bin:$PATH" ENV PATH="/root/.cargo/bin:$PATH"

View File

@ -64,7 +64,9 @@ li.nav-item {
.navbar-collapse { .navbar-collapse {
flex-basis: auto; @media (min-width: 564px) {
flex-basis: auto;
}
justify-content: flex-end; justify-content: flex-end;
} }

View File

@ -139,6 +139,8 @@
<td class="" *ngIf="this.miningWindowPreference === '24h'"><b>{{ miningStats.lastEstimatedHashrate}} {{ <td class="" *ngIf="this.miningWindowPreference === '24h'"><b>{{ miningStats.lastEstimatedHashrate}} {{
miningStats.miningUnits.hashrateUnit }}</b></td> miningStats.miningUnits.hashrateUnit }}</b></td>
<td class=""><b>{{ miningStats.blockCount }}</b></td> <td class=""><b>{{ miningStats.blockCount }}</b></td>
<td *ngIf="auditAvailable"></td>
<td *ngIf="auditAvailable"></td>
<td class="d-none d-md-table-cell"><b>{{ miningStats.totalEmptyBlock }} ({{ miningStats.totalEmptyBlockRatio <td class="d-none d-md-table-cell"><b>{{ miningStats.totalEmptyBlock }} ({{ miningStats.totalEmptyBlockRatio
}}%)</b></td> }}%)</b></td>
</tr> </tr>

View File

@ -92,9 +92,9 @@
<table class="table table-xs table-data"> <table class="table table-xs table-data">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.reward">Reward</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.reward">Reward</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="latest-blocks.avg_health" *ngIf="auditAvailable">Avg Health</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="latest-blocks.avg_health" *ngIf="auditAvailable">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -117,9 +117,9 @@
<table class="table table-xs table-data"> <table class="table table-xs table-data">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.reward">Reward</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.reward">Reward</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="latest-blocks.avg_health" *ngIf="auditAvailable">Avg Health</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="latest-blocks.avg_health" *ngIf="auditAvailable">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -143,9 +143,9 @@
<table class="table table-xs table-data"> <table class="table table-xs table-data">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -165,9 +165,9 @@
<table class="table table-xs table-data"> <table class="table table-xs table-data">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -382,9 +382,9 @@
<table class="table table-xs table-data text-center"> <table class="table table-xs table-data text-center">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.total-reward">Reward</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.total-reward">Reward</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -407,9 +407,9 @@
<table class="table table-xs table-data text-center"> <table class="table table-xs table-data text-center">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.total-reward">Reward</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.total-reward">Reward</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th> <th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -433,9 +433,9 @@
<table class="table table-xs table-data text-center"> <table class="table table-xs table-data text-center">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -458,9 +458,9 @@
<table class="table table-xs table-data text-center"> <table class="table table-xs table-data text-center">
<thead> <thead>
<tr> <tr>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th> <th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>

View File

@ -188,11 +188,19 @@ div.scrollable {
} }
} }
.block-count-title { .data-title {
color: #4a68b9; color: #4a68b9;
font-size: 14px; font-size: 14px;
} }
.clip {
@media (max-width: 576px) {
max-width: 85px;
overflow: hidden;
text-overflow: ellipsis;
}
}
.table-data tr { .table-data tr {
background-color: transparent; background-color: transparent;
} }

View File

@ -18,9 +18,10 @@
form { form {
margin-top: 5px; margin-top: 5px;
@media (min-width: 576px) { @media (min-width: 564px) {
margin-top: 0px; margin-top: 0px;
margin-left: 8px; margin-left: 5px;
margin-right: -5px;
} }
@media (min-width: 992px) { @media (min-width: 992px) {
width: 100%; width: 100%;

View File

@ -73,7 +73,7 @@
</div> </div>
</div> </div>
<div class="col" style="max-height: 410px"> <div class="col" style="max-height: 410px">
<div class="card"> <div class="card" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'; else latestBlocks">
<div class="card-body"> <div class="card-body">
<a class="title-link" href="" [routerLink]="['/rbf' | relativeUrl]"> <a class="title-link" href="" [routerLink]="['/rbf' | relativeUrl]">
<h5 class="card-title d-inline" i18n="dashboard.latest-rbf-replacements">Latest replacements</h5> <h5 class="card-title d-inline" i18n="dashboard.latest-rbf-replacements">Latest replacements</h5>
@ -106,6 +106,46 @@
</table> </table>
</div> </div>
</div> </div>
<ng-template #latestBlocks>
<div class="card">
<div class="card-body">
<a class="title-link" href="" [routerLink]="['/blocks' | relativeUrl]">
<h5 class="card-title d-inline" i18n="dashboard.latest-blocks">Latest blocks</h5>
<span>&nbsp;</span>
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: 'text-top'; font-size: 13px; color: '#4a68b9'"></fa-icon>
</a>
<table class="table lastest-blocks-table">
<thead>
<th class="table-cell-height" i18n="dashboard.latest-blocks.height">Height</th>
<th *ngIf="!stateService.env.MINING_DASHBOARD" class="table-cell-mined" i18n="dashboard.latest-blocks.mined">Mined</th>
<th *ngIf="stateService.env.MINING_DASHBOARD" class="table-cell-mined pl-lg-4" i18n="mining.pool-name">Pool</th>
<th class="table-cell-transaction-count" i18n="dashboard.latest-blocks.transaction-count">TXs</th>
<th class="table-cell-size" i18n="dashboard.latest-blocks.size">Size</th>
</thead>
<tbody>
<tr *ngFor="let block of blocks$ | async; let i = index; trackBy: trackByBlock">
<td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
<td *ngIf="!stateService.env.MINING_DASHBOARD" class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time></td>
<td *ngIf="stateService.env.MINING_DASHBOARD" class="table-cell-mined pl-lg-4">
<a class="clear-link" [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]">
<img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
onError="this.src = '/resources/mining-pools/default.svg'">
<span class="pool-name">{{ block.extras.pool.name }}</span>
</a>
</td>
<td class="table-cell-transaction-count">{{ block.tx_count | number }}</td>
<td class="table-cell-size">
<div class="progress">
<div class="progress-bar progress-mempool {{ network$ | async }}" role="progressbar" [ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }">&nbsp;</div>
<div class="progress-text" [innerHTML]="block.size | bytes: 2"></div>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</ng-template>
</div> </div>
<div class="col" style="max-height: 410px"> <div class="col" style="max-height: 410px">
<div class="card"> <div class="card">

View File

@ -175,6 +175,43 @@
height: 18px; height: 18px;
} }
.lastest-blocks-table {
width: 100%;
text-align: left;
tr, td, th {
border: 0px;
padding-top: 0.65rem !important;
padding-bottom: 0.7rem !important;
}
.table-cell-height {
width: 15%;
}
.table-cell-mined {
width: 35%;
text-align: left;
}
.table-cell-transaction-count {
display: none;
text-align: right;
width: 20%;
display: table-cell;
}
.table-cell-size {
display: none;
text-align: center;
width: 30%;
@media (min-width: 485px) {
display: table-cell;
}
@media (min-width: 768px) {
display: none;
}
@media (min-width: 992px) {
display: table-cell;
}
}
}
.lastest-replacements-table { .lastest-replacements-table {
width: 100%; width: 100%;
text-align: left; text-align: left;

View File

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnDestroy, OnInit } from '@angular/core';
import { combineLatest, merge, Observable, of, Subscription } from 'rxjs'; import { combineLatest, merge, Observable, of, Subscription } from 'rxjs';
import { filter, map, scan, share, switchMap } from 'rxjs/operators'; import { filter, map, scan, share, switchMap, tap } from 'rxjs/operators';
import { BlockExtended, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface'; import { BlockExtended, OptimizedMempoolStats, RbfTree } from '../interfaces/node-api.interface';
import { MempoolInfo, TransactionStripped, ReplacementInfo } from '../interfaces/websocket.interface'; import { MempoolInfo, TransactionStripped, ReplacementInfo } from '../interfaces/websocket.interface';
import { ApiService } from '../services/api.service'; import { ApiService } from '../services/api.service';
@ -39,6 +39,7 @@ export class DashboardComponent implements OnInit, OnDestroy {
mempoolLoadingStatus$: Observable<number>; mempoolLoadingStatus$: Observable<number>;
vBytesPerSecondLimit = 1667; vBytesPerSecondLimit = 1667;
transactions$: Observable<TransactionStripped[]>; transactions$: Observable<TransactionStripped[]>;
blocks$: Observable<BlockExtended[]>;
replacements$: Observable<ReplacementInfo[]>; replacements$: Observable<ReplacementInfo[]>;
latestBlockHeight: number; latestBlockHeight: number;
mempoolTransactionsWeightPerSecondData: any; mempoolTransactionsWeightPerSecondData: any;
@ -144,6 +145,23 @@ export class DashboardComponent implements OnInit, OnDestroy {
}, []), }, []),
); );
this.blocks$ = this.stateService.blocks$
.pipe(
tap((blocks) => {
this.latestBlockHeight = blocks[0].height;
}),
switchMap((blocks) => {
if (this.stateService.env.MINING_DASHBOARD === true) {
for (const block of blocks) {
// @ts-ignore: Need to add an extra field for the template
block.extras.pool.logo = `/resources/mining-pools/` +
block.extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg';
}
}
return of(blocks.slice(0, 6));
})
);
this.replacements$ = this.stateService.rbfLatestSummary$; this.replacements$ = this.stateService.rbfLatestSummary$;
this.mempoolStats$ = this.stateService.connectionState$ this.mempoolStats$ = this.stateService.connectionState$

View File

@ -8936,8 +8936,8 @@ export const faqData = [
type: "endpoint", type: "endpoint",
category: "self-hosting", category: "self-hosting",
showConditions: bitcoinNetworks, showConditions: bitcoinNetworks,
fragment: "host-my-own-instance-linux-server", fragment: "host-my-own-instance-server",
title: "How can I host my own instance on a Linux server?", title: "How can I host a Mempool instance on my own server?",
}, },
{ {
type: "endpoint", type: "endpoint",

View File

@ -40,7 +40,7 @@
<div class="doc-content"> <div class="doc-content">
<p class="doc-welcome-note">Below is a reference for the {{ network.val === '' ? 'Bitcoin' : network.val.charAt(0).toUpperCase() + network.val.slice(1) }} <ng-container i18n="api-docs.title">REST API service</ng-container>.</p> <p class="doc-welcome-note">Below is a reference for the {{ network.val === '' ? 'Bitcoin' : network.val.charAt(0).toUpperCase() + network.val.slice(1) }} <ng-container i18n="api-docs.title">REST API service</ng-container>.</p>
<p class="doc-welcome-note api-note" *ngIf="officialMempoolInstance">Note that we enforce rate limits. If you exceed these limits, you will get an HTTP 429 error. If you repeatedly exceed the limits, you may be banned from accessing the service altogether. Consider an <a [routerLink]="['/enterprise']">enterprise sponsorship</a> if you need higher API limits.</p> <p class="doc-welcome-note api-note" *ngIf="officialMempoolInstance">Note that we enforce rate limits. If you exceed these limits, you will get an HTTP 429 error. If you repeatedly exceed the limits, you may be banned from accessing the service altogether. Consider an <a href="/enterprise">enterprise sponsorship</a> if you need higher API limits.</p>
<div class="doc-item-container" *ngFor="let item of restDocs"> <div class="doc-item-container" *ngFor="let item of restDocs">
<h3 *ngIf="( item.type === 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )">{{ item.title }}</h3> <h3 *ngIf="( item.type === 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )">{{ item.title }}</h3>
@ -279,8 +279,9 @@
We support one-click installation on a number of Raspberry Pi full-node distros including Umbrel, RaspiBlitz, MyNode, RoninDojo, and Start9's Embassy. We support one-click installation on a number of Raspberry Pi full-node distros including Umbrel, RaspiBlitz, MyNode, RoninDojo, and Start9's Embassy.
</ng-template> </ng-template>
<ng-template type="host-my-own-instance-linux-server"> <ng-template type="host-my-own-instance-server">
You can manually install Mempool on your own Linux server, but this requires advanced sysadmin skills since you will be manually configuring everything. We do not provide support for manual deployments. <p>You can manually install Mempool on your own server, but this requires advanced sysadmin skills since you will be manually configuring everything. You could also use our <a href="https://github.com/mempool/mempool/tree/master/docker" target="_blank">Docker images</a>.</p><p>In any case, we only provide support for manual deployments to <a href="/enterprise">enterprise sponsors</a>.</p>
<p>For casual users, we strongly suggest installing Mempool using one of the <a href="https://github.com/mempool/mempool#one-click-installation" target="_blank">1-click install methods</a>.</p>
</ng-template> </ng-template>
<ng-template type="install-mempool-with-docker"> <ng-template type="install-mempool-with-docker">

View File

@ -2,7 +2,7 @@
These instructions are for setting up a serious production Mempool website for Bitcoin (mainnet, testnet, signet), Liquid (mainnet, testnet), and Bisq. These instructions are for setting up a serious production Mempool website for Bitcoin (mainnet, testnet, signet), Liquid (mainnet, testnet), and Bisq.
Again, this setup is no joke—home users should use [one of the other installation methods](../#installation-methods). Again, this setup is no joke—home users should use [one of the other installation methods](../#installation-methods). Support is only provided to [enterprise sponsors](https://mempool.space/enterprise).
### Server Hardware ### Server Hardware