mirror of
https://github.com/mempool/mempool.git
synced 2026-08-13 12:33:11 +02:00
Merge branch 'master' into natsoni/accelerate-address-page
This commit is contained in:
commit
eff91d9f88
10 changed files with 69 additions and 40 deletions
34
backend/package-lock.json
generated
34
backend/package-lock.json
generated
|
|
@ -17,7 +17,7 @@
|
|||
"crypto-js": "~4.2.0",
|
||||
"express": "~4.22.1",
|
||||
"maxmind": "~4.3.11",
|
||||
"mysql2": "~3.14.1",
|
||||
"mysql2": "~3.16.0",
|
||||
"redis": "^4.7.0",
|
||||
"rust-gbt": "file:./rust-gbt",
|
||||
"socks-proxy-agent": "~7.0.0",
|
||||
|
|
@ -5496,14 +5496,14 @@
|
|||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/mysql2": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz",
|
||||
"integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==",
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.16.0.tgz",
|
||||
"integrity": "sha512-AEGW7QLLSuSnjCS4pk3EIqOmogegmze9h8EyrndavUQnIUcfkVal/sK7QznE+a3bc6rzPbAiui9Jcb+96tPwYA==",
|
||||
"dependencies": {
|
||||
"aws-ssl-profiles": "^1.1.1",
|
||||
"denque": "^2.1.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"iconv-lite": "^0.7.0",
|
||||
"long": "^5.2.1",
|
||||
"lru.min": "^1.0.0",
|
||||
"named-placeholders": "^1.1.3",
|
||||
|
|
@ -5515,14 +5515,18 @@
|
|||
}
|
||||
},
|
||||
"node_modules/mysql2/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
|
||||
"integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/express"
|
||||
}
|
||||
},
|
||||
"node_modules/named-placeholders": {
|
||||
|
|
@ -11060,14 +11064,14 @@
|
|||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"mysql2": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz",
|
||||
"integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==",
|
||||
"version": "3.16.0",
|
||||
"resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.16.0.tgz",
|
||||
"integrity": "sha512-AEGW7QLLSuSnjCS4pk3EIqOmogegmze9h8EyrndavUQnIUcfkVal/sK7QznE+a3bc6rzPbAiui9Jcb+96tPwYA==",
|
||||
"requires": {
|
||||
"aws-ssl-profiles": "^1.1.1",
|
||||
"denque": "^2.1.0",
|
||||
"generate-function": "^2.3.1",
|
||||
"iconv-lite": "^0.6.3",
|
||||
"iconv-lite": "^0.7.0",
|
||||
"long": "^5.2.1",
|
||||
"lru.min": "^1.0.0",
|
||||
"named-placeholders": "^1.1.3",
|
||||
|
|
@ -11076,9 +11080,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
|
||||
"integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@
|
|||
"crypto-js": "~4.2.0",
|
||||
"express": "~4.22.1",
|
||||
"maxmind": "~4.3.11",
|
||||
"mysql2": "~3.14.1",
|
||||
"mysql2": "~3.16.0",
|
||||
"rust-gbt": "file:./rust-gbt",
|
||||
"redis": "^4.7.0",
|
||||
"socks-proxy-agent": "~7.0.0",
|
||||
|
|
|
|||
|
|
@ -1,14 +1,11 @@
|
|||
import { Application, Request, Response } from 'express';
|
||||
import config from '../../config';
|
||||
import pricesUpdater from '../../tasks/price-updater';
|
||||
import logger from '../../logger';
|
||||
import PricesRepository from '../../repositories/PricesRepository';
|
||||
|
||||
class PricesRoutes {
|
||||
public initRoutes(app: Application): void {
|
||||
app
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'prices', this.$getCurrentPrices.bind(this))
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'internal/usd-price-history', this.$getAllPrices.bind(this))
|
||||
;
|
||||
}
|
||||
|
||||
|
|
@ -19,23 +16,6 @@ class PricesRoutes {
|
|||
|
||||
res.json(pricesUpdater.getLatestPrices());
|
||||
}
|
||||
|
||||
private async $getAllPrices(req: Request, res: Response): Promise<void> {
|
||||
res.header('Pragma', 'public');
|
||||
res.header('Cache-control', 'public');
|
||||
res.setHeader('Expires', new Date(Date.now() + 360_0000 / config.MEMPOOL.PRICE_UPDATES_PER_HOUR).toUTCString());
|
||||
|
||||
try {
|
||||
const usdPriceHistory = await PricesRepository.$getPricesTimesAndId();
|
||||
const responseData = usdPriceHistory.map(p => {
|
||||
return { time: p.time, USD: p.USD };
|
||||
});
|
||||
res.status(200).json(responseData);
|
||||
} catch (e: any) {
|
||||
logger.err(`Exception ${e} in PricesRoutes::$getAllPrices. Code: ${e.code}. Message: ${e.message}`);
|
||||
res.status(403).send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new PricesRoutes();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,13 @@ __MEMPOOL_BACKEND_MAINNET_HTTP_HOST__=${BACKEND_MAINNET_HTTP_HOST:=127.0.0.1}
|
|||
__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__=${BACKEND_MAINNET_HTTP_PORT:=8999}
|
||||
__MEMPOOL_FRONTEND_HTTP_PORT__=${FRONTEND_HTTP_PORT:=8080}
|
||||
|
||||
__PROXIED_SERVICES__=${PROXIED_SERVICES:=false}
|
||||
__PROXIED_SERVICES_HOST__=${PROXIED_SERVICES_HOST:=https://mempool.space}
|
||||
|
||||
if [ "${__PROXIED_SERVICES__}" = "true" ]; then
|
||||
sed -i "s|proxy_pass https://mempool.space;|proxy_pass ${__PROXIED_SERVICES_HOST__};|g" /etc/nginx/conf.d/nginx-mempool.conf
|
||||
fi
|
||||
|
||||
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__/${__MEMPOOL_BACKEND_MAINNET_HTTP_HOST__}/g" /etc/nginx/conf.d/nginx-mempool.conf
|
||||
sed -i "s/__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__/${__MEMPOOL_BACKEND_MAINNET_HTTP_PORT__}/g" /etc/nginx/conf.d/nginx-mempool.conf
|
||||
|
||||
|
|
|
|||
2
frontend/package-lock.json
generated
2
frontend/package-lock.json
generated
|
|
@ -31,10 +31,8 @@
|
|||
"@types/qrcode": "~1.5.0",
|
||||
"bootstrap": "~4.6.2",
|
||||
"clipboard": "^2.0.11",
|
||||
"cypress": "15.8.1",
|
||||
"domino": "^2.1.6",
|
||||
"echarts": "~5.4.0",
|
||||
"esbuild": "^0.25.8",
|
||||
"ngx-echarts": "~20.0.2",
|
||||
"ngx-infinite-scroll": "^20.0.0",
|
||||
"qrcode": "1.5.1",
|
||||
|
|
|
|||
|
|
@ -85,7 +85,6 @@
|
|||
"ngx-infinite-scroll": "^20.0.0",
|
||||
"qrcode": "1.5.1",
|
||||
"rxjs": "~7.8.1",
|
||||
"esbuild": "^0.25.8",
|
||||
"tslib": "~2.8.0",
|
||||
"zone.js": "~0.15.1"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
|||
} else {
|
||||
this.showPreviousBlocklink = true;
|
||||
}
|
||||
if (this.latestBlock.height && this.latestBlock.height === this.blockHeight) {
|
||||
if (this.latestBlock.height != null && this.latestBlock.height === this.blockHeight) {
|
||||
this.showNextBlocklink = false;
|
||||
} else {
|
||||
this.showNextBlocklink = true;
|
||||
|
|
|
|||
|
|
@ -31,6 +31,21 @@
|
|||
</div>
|
||||
<div class="clearfix"></div>
|
||||
|
||||
@if (duplicateTxBlocks) {
|
||||
<div class="box duplicate-tx-alert">
|
||||
<div class="icon-container">
|
||||
<fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon>
|
||||
</div>
|
||||
<span>
|
||||
<ng-container i18n="transaction.duplicate.notice|Duplicate transaction notice">
|
||||
This transaction ID appears twice in the blockchain as the coinbase of blocks <a [routerLink]="['/block/' | relativeUrl, duplicateTxBlocks[0]]">{{ duplicateTxBlocks[0] }}</a> and <a [routerLink]="['/block/' | relativeUrl, duplicateTxBlocks[1]]">{{ duplicateTxBlocks[1] }}</a>, due to a bug later mitigated by <a href="https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki" target="_blank" rel="noopener">BIP-30</a>.
|
||||
</ng-container>
|
||||
<span class="mr-3"></span>
|
||||
<a href="https://blog.bitmex.com/bitcoins-duplicate-transactions/" target="_blank" rel="noopener" i18n="transaction.duplicate.read-more|Duplicate transaction read more" style="white-space: nowrap;">Read more</a>
|
||||
</span>
|
||||
</div>
|
||||
}
|
||||
|
||||
@if (!error) {
|
||||
<app-transaction-details
|
||||
[network]="network"
|
||||
|
|
|
|||
|
|
@ -317,3 +317,19 @@
|
|||
scroll-margin-top: 65px;
|
||||
}
|
||||
}
|
||||
|
||||
.duplicate-tx-alert {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
border-left: 3px solid var(--info);
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
.icon-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
color: var(--info);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,12 @@ export interface TxAuditStatus {
|
|||
firstSeen?: number;
|
||||
}
|
||||
|
||||
// Known duplicate transaction IDs from early Bitcoin history (pre-BIP-30)
|
||||
const DUPLICATE_TX_BLOCKS: Record<string, [number, number]> = {
|
||||
'e3bf3d07d4b0375638d5f1db5255fe07ba2c4cb067cd81b84ee974b6585fb468': [91722, 91880],
|
||||
'd5d27987d2a3dfc724e359870c6644b40e497bdc0589a033220fe15429d88599': [91812, 91842],
|
||||
};
|
||||
|
||||
@Component({
|
||||
selector: 'app-transaction',
|
||||
templateUrl: './transaction.component.html',
|
||||
|
|
@ -142,6 +148,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
waitingForAccelerationInfo: boolean = false;
|
||||
isLoadingFirstSeen = false;
|
||||
notAcceleratedOnLoad: boolean = null;
|
||||
duplicateTxBlocks: [number, number] | undefined;
|
||||
|
||||
featuresEnabled: boolean;
|
||||
segwitEnabled: boolean;
|
||||
|
|
@ -584,6 +591,9 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||
});
|
||||
}
|
||||
}
|
||||
if (this.network === '' && this.txId) {
|
||||
this.duplicateTxBlocks = DUPLICATE_TX_BLOCKS[this.txId?.toLowerCase()];
|
||||
}
|
||||
if (window.innerWidth <= 767.98) {
|
||||
this.router.navigate([this.relativeUrlPipe.transform('/tx'), this.txId], {
|
||||
queryParamsHandling: 'merge',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue