Compare commits

..

52 Commits

Author SHA1 Message Date
softsimon
870e895144 Correcting docker disk cache config variable 2023-03-20 16:12:56 +09:00
softsimon
517cf613c1 Removing Sigterm. Cache write block interval configuration. 2023-03-20 15:46:05 +09:00
softsimon
d54bcc898b Fix missing temp cache in disk cache 2023-03-20 15:44:55 +09:00
wiz
704e1741ed Merge pull request #3449 from mempool/nymkappa/fix-tests 2023-03-20 14:22:01 +09:00
nymkappa
ad5ce6dba4 Fix maxmind tests 2023-03-20 14:02:31 +09:00
wiz
1718ddd4c3 Merge pull request #3444 from mempool/nymkappa/missing-docker
Update docker configs
2023-03-19 18:56:06 +09:00
wiz
32c2db2153 Fix backend docker config path for GeoIP data 2023-03-19 18:42:38 +09:00
wiz
0abb9cbb7c Fix boolean configuration option in docker backend config 2023-03-19 17:49:37 +09:00
wiz
e2e71c7a46 Add Maxmind GeoIP Lite download to Docker build 2023-03-19 17:49:08 +09:00
softsimon
5839ed428e Merge pull request #3378 from mempool/nymkappa/responsive
Fix block list component responsive
2023-03-19 16:48:47 +09:00
nymkappa
af6d115dbb Add missing MAXMIND in docker configs - Remove duplicated __MEMPOOL_INDEXING_BLOCKS_AMOUNT__ 2023-03-19 15:39:17 +09:00
nymkappa
194968d16f Fix block list component responsive 2023-03-19 15:23:00 +09:00
softsimon
30686bd322 Updating korean translation 2023-03-19 12:32:07 +09:00
softsimon
175c645777 Crediting korean translator 2023-03-19 12:05:13 +09:00
wiz
587a259843 Merge pull request #3440 from mempool/ops/bump-elements-v22.1
ops: Bump elementsd to v22.1
2023-03-18 20:06:53 +09:00
softsimon
64749ca726 Pull from transifex 2023-03-18 19:39:07 +09:00
wiz
8f2493dadb ops: Use old elements RPC port 7040 2023-03-18 18:48:37 +09:00
softsimon
7d8ea075d9 Merge pull request #3405 from mempool/nymkappa/pool-health
Show block health in pool block list
2023-03-18 18:48:10 +09:00
wiz
328327e5dc Merge pull request #3104 from mempool/mononaut/liquid-tooltip-fees
Fix missing fees in liquid block tooltips
2023-03-18 18:33:17 +09:00
wiz
fd1816d451 Merge pull request #3402 from mempool/hunicus/promo-subtitles
Add subtitles for promo video
2023-03-18 18:27:35 +09:00
hunicus
72f25b873c Add zh subtitles for promo video 2023-03-18 05:17:23 -04:00
hunicus
994656953c Fix promo video subtitles for sv 2023-03-18 05:15:48 -04:00
Mononaut
ed46232b83 Fix missing fees in liquid block tooltips 2023-03-18 18:11:10 +09:00
wiz
dca18a1c66 Merge branch 'master' into hunicus/promo-subtitles 2023-03-18 17:59:03 +09:00
wiz
c291ee1789 Merge pull request #3407 from mempool/hunicus/mempool-size-faq
Add faqs on mempool size and memory usage
2023-03-18 17:58:56 +09:00
hunicus
caf15351f7 Merge branch 'master' into hunicus/promo-subtitles 2023-03-18 17:58:29 +09:00
hunicus
6be9f23790 Add more languages for promo captions 2023-03-18 04:57:20 -04:00
nymkappa
adc51f6217 Update i18n 2023-03-18 16:40:30 +09:00
softsimon
ec8a46ede6 Pulling from transifex 2023-03-18 15:33:57 +09:00
softsimon
b78fdf5a23 Merge pull request #3353 from mempool/mononaut/mempool-block-animations
Improve mempool block animations
2023-03-18 12:46:20 +09:00
wiz
7c2493f3fa ops: Bump elementsd to v22.1 2023-03-17 22:07:48 +09:00
hunicus
b0a0ad11b4 Show mempool.space memory usage faq on official 2023-03-17 21:25:28 +09:00
hunicus
377f71eb52 Integrate feedback to memory usage faqs 2023-03-17 21:25:28 +09:00
hunicus
eefe343973 Add faqs on mempool size and memory usage 2023-03-17 21:25:28 +09:00
softsimon
41a6674fad Merge pull request #3379 from mempool/nymkappa/testnet-signet-price-zero
Don't fetch prices on signet/testnet, always show 0
2023-03-17 16:40:09 +09:00
softsimon
effba92729 Merge pull request #3381 from mempool/mononaut/network-special-blocks
Limit special blocks by network, add future halvings
2023-03-17 16:39:54 +09:00
wiz
c9f4bdda17 Merge pull request #3408 from knorrium/gha_docker_digest
Docker digest GHA
2023-03-17 14:49:19 +09:00
Mononaut
b5c2073414 Fix getSimilarity error on empty mempool 2023-03-16 22:16:40 +09:00
Mononaut
25aacb5046 Calculate similarity score with audit disabled 2023-03-16 22:16:40 +09:00
Mononaut
c24724dcdf animate mempool blocks conditional on mined block similarity 2023-03-16 22:16:40 +09:00
Mononaut
64ab14f995 mempool block entry animation 2023-03-16 22:16:40 +09:00
nymkappa
4a64c0dfa5 Fix skeleton 2023-03-16 16:35:59 +09:00
nymkappa
0ebe0a5dc9 Add new stats in mining pool page 2023-03-16 16:13:11 +09:00
hunicus
c683a52a01 Show captions for non-english locales 2023-03-16 02:29:33 -04:00
Felipe Knorr Kuhn
5fbdd0bb2a Remove push trigger 2023-03-15 22:48:28 -07:00
Felipe Knorr Kuhn
599881366b Add GHA for Docker digest 2023-03-15 22:43:41 -07:00
hunicus
4c294b010d Make subtitles default to current locale 2023-03-15 23:06:10 -04:00
hunicus
418c32e334 Make git ignore mp4 and vtt files in /resources 2023-03-15 23:06:10 -04:00
hunicus
12b605e5cc Fetch subtitles files from github
For en, sv, and ja.
2023-03-15 23:06:10 -04:00
hunicus
cdfde05452 Make new folder for promo video assets
Video, cover image, and subtitle files.
2023-03-15 02:50:17 -04:00
Mononaut
7bf8fea9f2 Limit special blocks by network, add future halvings 2023-03-14 16:58:02 +09:00
nymkappa
a5dd141934 Don't fetch prices on signet/testnet, always show 0 2023-03-14 15:39:15 +09:00
58 changed files with 874 additions and 285 deletions

26
.github/workflows/get_image_digest.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: 'Print images digest'
on:
workflow_dispatch:
inputs:
version:
description: 'Image Version'
required: false
default: 'latest'
type: string
jobs:
print-images-sha:
runs-on: 'ubuntu-latest'
name: Print digest for images
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: digest
- name: Run script
working-directory: digest
run: |
sh ./docker/scripts/get_image_digest.sh $VERSION
env:
VERSION: ${{ github.event.inputs.version }}

View File

@@ -27,7 +27,8 @@
"AUDIT": false, "AUDIT": false,
"ADVANCED_GBT_AUDIT": false, "ADVANCED_GBT_AUDIT": false,
"ADVANCED_GBT_MEMPOOL": false, "ADVANCED_GBT_MEMPOOL": false,
"CPFP_INDEXING": false "CPFP_INDEXING": false,
"DISK_CACHE_BLOCK_INTERVAL": 6
}, },
"CORE_RPC": { "CORE_RPC": {
"HOST": "127.0.0.1", "HOST": "127.0.0.1",

View File

@@ -28,7 +28,8 @@
"ADVANCED_GBT_AUDIT": "__MEMPOOL_ADVANCED_GBT_AUDIT__", "ADVANCED_GBT_AUDIT": "__MEMPOOL_ADVANCED_GBT_AUDIT__",
"ADVANCED_GBT_MEMPOOL": "__MEMPOOL_ADVANCED_GBT_MEMPOOL__", "ADVANCED_GBT_MEMPOOL": "__MEMPOOL_ADVANCED_GBT_MEMPOOL__",
"CPFP_INDEXING": "__MEMPOOL_CPFP_INDEXING__", "CPFP_INDEXING": "__MEMPOOL_CPFP_INDEXING__",
"MAX_BLOCKS_BULK_QUERY": "__MEMPOOL_MAX_BLOCKS_BULK_QUERY__" "MAX_BLOCKS_BULK_QUERY": "__MEMPOOL_MAX_BLOCKS_BULK_QUERY__",
"DISK_CACHE_BLOCK_INTERVAL": "__MEMPOOL_DISK_CACHE_BLOCK_INTERVAL__"
}, },
"CORE_RPC": { "CORE_RPC": {
"HOST": "__CORE_RPC_HOST__", "HOST": "__CORE_RPC_HOST__",

View File

@@ -42,6 +42,7 @@ describe('Mempool Backend Config', () => {
ADVANCED_GBT_MEMPOOL: false, ADVANCED_GBT_MEMPOOL: false,
CPFP_INDEXING: false, CPFP_INDEXING: false,
MAX_BLOCKS_BULK_QUERY: 0, MAX_BLOCKS_BULK_QUERY: 0,
DISK_CACHE_BLOCK_INTERVAL: 6,
}); });
expect(config.ELECTRUM).toStrictEqual({ HOST: '127.0.0.1', PORT: 3306, TLS_ENABLED: true }); expect(config.ELECTRUM).toStrictEqual({ HOST: '127.0.0.1', PORT: 3306, TLS_ENABLED: true });
@@ -106,6 +107,13 @@ describe('Mempool Backend Config', () => {
BISQ_URL: 'https://bisq.markets/api', BISQ_URL: 'https://bisq.markets/api',
BISQ_ONION: 'http://bisqmktse2cabavbr2xjq7xw3h6g5ottemo5rolfcwt6aly6tp5fdryd.onion/api' BISQ_ONION: 'http://bisqmktse2cabavbr2xjq7xw3h6g5ottemo5rolfcwt6aly6tp5fdryd.onion/api'
}); });
expect(config.MAXMIND).toStrictEqual({
ENABLED: false,
GEOLITE2_CITY: '/usr/local/share/GeoIP/GeoLite2-City.mmdb',
GEOLITE2_ASN: '/usr/local/share/GeoIP/GeoLite2-ASN.mmdb',
GEOIP2_ISP: '/usr/local/share/GeoIP/GeoIP2-ISP.mmdb'
});
}); });
}); });

View File

@@ -5,9 +5,9 @@ const PROPAGATION_MARGIN = 180; // in seconds, time since a transaction is first
class Audit { class Audit {
auditBlock(transactions: TransactionExtended[], projectedBlocks: MempoolBlockWithTransactions[], mempool: { [txId: string]: TransactionExtended }) auditBlock(transactions: TransactionExtended[], projectedBlocks: MempoolBlockWithTransactions[], mempool: { [txId: string]: TransactionExtended })
: { censored: string[], added: string[], fresh: string[], score: number } { : { censored: string[], added: string[], fresh: string[], score: number, similarity: number } {
if (!projectedBlocks?.[0]?.transactionIds || !mempool) { if (!projectedBlocks?.[0]?.transactionIds || !mempool) {
return { censored: [], added: [], fresh: [], score: 0 }; return { censored: [], added: [], fresh: [], score: 0, similarity: 1 };
} }
const matches: string[] = []; // present in both mined block and template const matches: string[] = []; // present in both mined block and template
@@ -16,6 +16,8 @@ class Audit {
const isCensored = {}; // missing, without excuse const isCensored = {}; // missing, without excuse
const isDisplaced = {}; const isDisplaced = {};
let displacedWeight = 0; let displacedWeight = 0;
let matchedWeight = 0;
let projectedWeight = 0;
const inBlock = {}; const inBlock = {};
const inTemplate = {}; const inTemplate = {};
@@ -38,11 +40,16 @@ class Audit {
isCensored[txid] = true; isCensored[txid] = true;
} }
displacedWeight += mempool[txid].weight; displacedWeight += mempool[txid].weight;
} else {
matchedWeight += mempool[txid].weight;
} }
projectedWeight += mempool[txid].weight;
inTemplate[txid] = true; inTemplate[txid] = true;
} }
displacedWeight += (4000 - transactions[0].weight); displacedWeight += (4000 - transactions[0].weight);
projectedWeight += transactions[0].weight;
matchedWeight += transactions[0].weight;
// we can expect an honest miner to include 'displaced' transactions in place of recent arrivals and censored txs // we can expect an honest miner to include 'displaced' transactions in place of recent arrivals and censored txs
// these displaced transactions should occupy the first N weight units of the next projected block // these displaced transactions should occupy the first N weight units of the next projected block
@@ -121,12 +128,14 @@ class Audit {
const numCensored = Object.keys(isCensored).length; const numCensored = Object.keys(isCensored).length;
const numMatches = matches.length - 1; // adjust for coinbase tx const numMatches = matches.length - 1; // adjust for coinbase tx
const score = numMatches > 0 ? (numMatches / (numMatches + numCensored)) : 0; const score = numMatches > 0 ? (numMatches / (numMatches + numCensored)) : 0;
const similarity = projectedWeight ? matchedWeight / projectedWeight : 1;
return { return {
censored: Object.keys(isCensored), censored: Object.keys(isCensored),
added, added,
fresh, fresh,
score score,
similarity,
}; };
} }
} }

View File

@@ -143,7 +143,10 @@ class Blocks {
* @returns BlockSummary * @returns BlockSummary
*/ */
public summarizeBlock(block: IBitcoinApi.VerboseBlock): BlockSummary { public summarizeBlock(block: IBitcoinApi.VerboseBlock): BlockSummary {
const stripped = block.tx.map((tx) => { if (Common.isLiquid()) {
block = this.convertLiquidFees(block);
}
const stripped = block.tx.map((tx: IBitcoinApi.VerboseTransaction) => {
return { return {
txid: tx.txid, txid: tx.txid,
vsize: tx.weight / 4, vsize: tx.weight / 4,
@@ -158,6 +161,13 @@ class Blocks {
}; };
} }
private convertLiquidFees(block: IBitcoinApi.VerboseBlock): IBitcoinApi.VerboseBlock {
block.tx.forEach(tx => {
tx.fee = Object.values(tx.fee || {}).reduce((total, output) => total + output, 0);
});
return block;
}
/** /**
* Return a block with additional data (reward, coinbase, fees...) * Return a block with additional data (reward, coinbase, fees...)
* @param block * @param block
@@ -641,7 +651,7 @@ class Blocks {
if (this.newBlockCallbacks.length) { if (this.newBlockCallbacks.length) {
this.newBlockCallbacks.forEach((cb) => cb(blockExtended, txIds, transactions)); this.newBlockCallbacks.forEach((cb) => cb(blockExtended, txIds, transactions));
} }
if (!memPool.hasPriority() && (block.height % 6 === 0)) { if (!memPool.hasPriority() && (block.height % config.MEMPOOL.DISK_CACHE_BLOCK_INTERVAL === 0)) {
diskCache.$saveCacheToDisk(); diskCache.$saveCacheToDisk();
} }

View File

@@ -1,4 +1,4 @@
import { CpfpInfo, TransactionExtended, TransactionStripped } from '../mempool.interfaces'; import { CpfpInfo, MempoolBlockWithTransactions, TransactionExtended, TransactionStripped } from '../mempool.interfaces';
import config from '../config'; import config from '../config';
import { NodeSocket } from '../repositories/NodesSocketsRepository'; import { NodeSocket } from '../repositories/NodesSocketsRepository';
import { isIP } from 'net'; import { isIP } from 'net';
@@ -164,6 +164,30 @@ export class Common {
return parents; return parents;
} }
// calculates the ratio of matched transactions to projected transactions by weight
static getSimilarity(projectedBlock: MempoolBlockWithTransactions, transactions: TransactionExtended[]): number {
let matchedWeight = 0;
let projectedWeight = 0;
const inBlock = {};
for (const tx of transactions) {
inBlock[tx.txid] = tx;
}
// look for transactions that were expected in the template, but missing from the mined block
for (const tx of projectedBlock.transactions) {
if (inBlock[tx.txid]) {
matchedWeight += tx.vsize * 4;
}
projectedWeight += tx.vsize * 4;
}
projectedWeight += transactions[0].weight;
matchedWeight += transactions[0].weight;
return projectedWeight ? matchedWeight / projectedWeight : 1;
}
static getSqlInterval(interval: string | null): string | null { static getSqlInterval(interval: string | null): string | null {
switch (interval) { switch (interval) {
case '24h': return '1 DAY'; case '24h': return '1 DAY';

View File

@@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository';
import { RowDataPacket } from 'mysql2'; import { RowDataPacket } from 'mysql2';
class DatabaseMigration { class DatabaseMigration {
private static currentVersion = 58; private static currentVersion = 59;
private queryTimeout = 3600_000; private queryTimeout = 3600_000;
private statisticsAddedIndexed = false; private statisticsAddedIndexed = false;
private uniqueLogs: string[] = []; private uniqueLogs: string[] = [];
@@ -510,6 +510,11 @@ class DatabaseMigration {
// We only run some migration queries for this version // We only run some migration queries for this version
await this.updateToSchemaVersion(58); await this.updateToSchemaVersion(58);
} }
if (databaseSchemaVersion < 59 && (config.MEMPOOL.NETWORK === 'signet' || config.MEMPOOL.NETWORK === 'testnet')) {
// https://github.com/mempool/mempool/issues/3360
await this.$executeQuery(`TRUNCATE prices`);
}
} }
/** /**

View File

@@ -19,20 +19,16 @@ class DiskCache {
private isWritingCache = false; private isWritingCache = false;
constructor() { constructor() {
if (!cluster.isMaster) { if (!cluster.isPrimary) {
return; return;
} }
process.on('SIGINT', (e) => { process.on('SIGINT', (e) => {
this.saveCacheToDiskSync(); this.$saveCacheToDisk(true);
process.exit(2); process.exit(0);
});
process.on('SIGTERM', (e) => {
this.saveCacheToDiskSync();
process.exit(2);
}); });
} }
async $saveCacheToDisk(): Promise<void> { async $saveCacheToDisk(sync: boolean = false): Promise<void> {
if (!cluster.isPrimary) { if (!cluster.isPrimary) {
return; return;
} }
@@ -41,7 +37,7 @@ class DiskCache {
return; return;
} }
try { try {
logger.debug('Writing mempool and blocks data to disk cache (async)...'); logger.debug(`Writing mempool and blocks data to disk cache (${ sync ? 'sync' : 'async' })...`);
this.isWritingCache = true; this.isWritingCache = true;
const mempool = memPool.getMempool(); const mempool = memPool.getMempool();
@@ -54,68 +50,46 @@ class DiskCache {
const chunkSize = Math.floor(mempoolArray.length / DiskCache.CHUNK_FILES); const chunkSize = Math.floor(mempoolArray.length / DiskCache.CHUNK_FILES);
await fsPromises.writeFile(DiskCache.FILE_NAME, JSON.stringify({ if (sync) {
network: config.MEMPOOL.NETWORK, fs.writeFileSync(DiskCache.TMP_FILE_NAME, JSON.stringify({
cacheSchemaVersion: this.cacheSchemaVersion, network: config.MEMPOOL.NETWORK,
blocks: blocks.getBlocks(), cacheSchemaVersion: this.cacheSchemaVersion,
blockSummaries: blocks.getBlockSummaries(), blocks: blocks.getBlocks(),
mempool: {}, blockSummaries: blocks.getBlockSummaries(),
mempoolArray: mempoolArray.splice(0, chunkSize),
}), { flag: 'w' });
for (let i = 1; i < DiskCache.CHUNK_FILES; i++) {
await fsPromises.writeFile(DiskCache.FILE_NAMES.replace('{number}', i.toString()), JSON.stringify({
mempool: {}, mempool: {},
mempoolArray: mempoolArray.splice(0, chunkSize), mempoolArray: mempoolArray.splice(0, chunkSize),
}), { flag: 'w' }); }), { flag: 'w' });
} for (let i = 1; i < DiskCache.CHUNK_FILES; i++) {
logger.debug('Mempool and blocks data saved to disk cache'); fs.writeFileSync(DiskCache.TMP_FILE_NAMES.replace('{number}', i.toString()), JSON.stringify({
this.isWritingCache = false; mempool: {},
} catch (e) { mempoolArray: mempoolArray.splice(0, chunkSize),
logger.warn('Error writing to cache file: ' + (e instanceof Error ? e.message : e)); }), { flag: 'w' });
this.isWritingCache = false; }
}
}
saveCacheToDiskSync(): void { fs.renameSync(DiskCache.TMP_FILE_NAME, DiskCache.FILE_NAME);
if (!cluster.isPrimary) { for (let i = 1; i < DiskCache.CHUNK_FILES; i++) {
return; fs.renameSync(DiskCache.TMP_FILE_NAMES.replace('{number}', i.toString()), DiskCache.FILE_NAMES.replace('{number}', i.toString()));
} }
if (this.isWritingCache) { } else {
logger.debug('Saving cache already in progress. Skipping.'); await fsPromises.writeFile(DiskCache.TMP_FILE_NAME, JSON.stringify({
return; network: config.MEMPOOL.NETWORK,
} cacheSchemaVersion: this.cacheSchemaVersion,
try { blocks: blocks.getBlocks(),
logger.debug('Writing mempool and blocks data to disk cache (sync)...'); blockSummaries: blocks.getBlockSummaries(),
this.isWritingCache = true;
const mempool = memPool.getMempool();
const mempoolArray: TransactionExtended[] = [];
for (const tx in mempool) {
mempoolArray.push(mempool[tx]);
}
Common.shuffleArray(mempoolArray);
const chunkSize = Math.floor(mempoolArray.length / DiskCache.CHUNK_FILES);
fs.writeFileSync(DiskCache.TMP_FILE_NAME, JSON.stringify({
network: config.MEMPOOL.NETWORK,
cacheSchemaVersion: this.cacheSchemaVersion,
blocks: blocks.getBlocks(),
blockSummaries: blocks.getBlockSummaries(),
mempool: {},
mempoolArray: mempoolArray.splice(0, chunkSize),
}), { flag: 'w' });
for (let i = 1; i < DiskCache.CHUNK_FILES; i++) {
fs.writeFileSync(DiskCache.TMP_FILE_NAMES.replace('{number}', i.toString()), JSON.stringify({
mempool: {}, mempool: {},
mempoolArray: mempoolArray.splice(0, chunkSize), mempoolArray: mempoolArray.splice(0, chunkSize),
}), { flag: 'w' }); }), { flag: 'w' });
} for (let i = 1; i < DiskCache.CHUNK_FILES; i++) {
await fsPromises.writeFile(DiskCache.TMP_FILE_NAMES.replace('{number}', i.toString()), JSON.stringify({
mempool: {},
mempoolArray: mempoolArray.splice(0, chunkSize),
}), { flag: 'w' });
}
fs.renameSync(DiskCache.TMP_FILE_NAME, DiskCache.FILE_NAME); await fsPromises.rename(DiskCache.TMP_FILE_NAME, DiskCache.FILE_NAME);
for (let i = 1; i < DiskCache.CHUNK_FILES; i++) { for (let i = 1; i < DiskCache.CHUNK_FILES; i++) {
fs.renameSync(DiskCache.TMP_FILE_NAMES.replace('{number}', i.toString()), DiskCache.FILE_NAMES.replace('{number}', i.toString())); await fsPromises.rename(DiskCache.TMP_FILE_NAMES.replace('{number}', i.toString()), DiskCache.FILE_NAMES.replace('{number}', i.toString()));
}
} }
logger.debug('Mempool and blocks data saved to disk cache'); logger.debug('Mempool and blocks data saved to disk cache');

View File

@@ -13,6 +13,7 @@ import BlocksAuditsRepository from '../../repositories/BlocksAuditsRepository';
import PricesRepository from '../../repositories/PricesRepository'; import PricesRepository from '../../repositories/PricesRepository';
import { bitcoinCoreApi } from '../bitcoin/bitcoin-api-factory'; import { bitcoinCoreApi } from '../bitcoin/bitcoin-api-factory';
import { IEsploraApi } from '../bitcoin/esplora-api.interface'; import { IEsploraApi } from '../bitcoin/esplora-api.interface';
import database from '../../database';
class Mining { class Mining {
private blocksPriceIndexingRunning = false; private blocksPriceIndexingRunning = false;
@@ -141,6 +142,9 @@ class Mining {
const blockCount1w: number = await BlocksRepository.$blockCount(pool.id, '1w'); const blockCount1w: number = await BlocksRepository.$blockCount(pool.id, '1w');
const totalBlock1w: number = await BlocksRepository.$blockCount(null, '1w'); const totalBlock1w: number = await BlocksRepository.$blockCount(null, '1w');
const avgHealth = await BlocksRepository.$getAvgBlockHealthPerPoolId(pool.id);
const totalReward = await BlocksRepository.$getTotalRewardForPoolId(pool.id);
let currentEstimatedHashrate = 0; let currentEstimatedHashrate = 0;
try { try {
currentEstimatedHashrate = await bitcoinClient.getNetworkHashPs(totalBlock24h); currentEstimatedHashrate = await bitcoinClient.getNetworkHashPs(totalBlock24h);
@@ -162,6 +166,8 @@ class Mining {
}, },
estimatedHashrate: currentEstimatedHashrate * (blockCount24h / totalBlock24h), estimatedHashrate: currentEstimatedHashrate * (blockCount24h / totalBlock24h),
reportedHashrate: null, reportedHashrate: null,
avgBlockHealth: avgHealth,
totalReward: totalReward,
}; };
} }

View File

@@ -432,7 +432,7 @@ class WebsocketHandler {
} }
if (Common.indexingEnabled() && memPool.isInSync()) { if (Common.indexingEnabled() && memPool.isInSync()) {
const { censored, added, fresh, score } = Audit.auditBlock(transactions, projectedBlocks, auditMempool); const { censored, added, fresh, score, similarity } = Audit.auditBlock(transactions, projectedBlocks, auditMempool);
const matchRate = Math.round(score * 100 * 100) / 100; const matchRate = Math.round(score * 100 * 100) / 100;
const stripped = projectedBlocks[0]?.transactions ? projectedBlocks[0].transactions.map((tx) => { const stripped = projectedBlocks[0]?.transactions ? projectedBlocks[0].transactions.map((tx) => {
@@ -464,8 +464,14 @@ class WebsocketHandler {
if (block.extras) { if (block.extras) {
block.extras.matchRate = matchRate; block.extras.matchRate = matchRate;
block.extras.similarity = similarity;
} }
} }
} else if (block.extras) {
const mBlocks = mempoolBlocks.getMempoolBlocksWithTransactions();
if (mBlocks?.length && mBlocks[0].transactions) {
block.extras.similarity = Common.getSimilarity(mBlocks[0], transactions);
}
} }
const removed: string[] = []; const removed: string[] = [];

View File

@@ -33,6 +33,7 @@ interface IConfig {
ADVANCED_GBT_MEMPOOL: boolean; ADVANCED_GBT_MEMPOOL: boolean;
CPFP_INDEXING: boolean; CPFP_INDEXING: boolean;
MAX_BLOCKS_BULK_QUERY: number; MAX_BLOCKS_BULK_QUERY: number;
DISK_CACHE_BLOCK_INTERVAL: number;
}; };
ESPLORA: { ESPLORA: {
REST_API_URL: string; REST_API_URL: string;
@@ -155,6 +156,7 @@ const defaults: IConfig = {
'ADVANCED_GBT_MEMPOOL': false, 'ADVANCED_GBT_MEMPOOL': false,
'CPFP_INDEXING': false, 'CPFP_INDEXING': false,
'MAX_BLOCKS_BULK_QUERY': 0, 'MAX_BLOCKS_BULK_QUERY': 0,
'DISK_CACHE_BLOCK_INTERVAL': 6,
}, },
'ESPLORA': { 'ESPLORA': {
'REST_API_URL': 'http://127.0.0.1:3000', 'REST_API_URL': 'http://127.0.0.1:3000',

View File

@@ -153,6 +153,7 @@ export interface BlockExtension {
feeRange: number[]; // fee rate percentiles feeRange: number[]; // fee rate percentiles
reward: number; reward: number;
matchRate: number | null; matchRate: number | null;
similarity?: number;
pool: { pool: {
id: number; // Note - This is the `unique_id`, not to mix with the auto increment `id` id: number; // Note - This is the `unique_id`, not to mix with the auto increment `id`
name: string; name: string;

View File

@@ -330,6 +330,55 @@ class BlocksRepository {
} }
} }
/**
* Get average block health for all blocks for a single pool
*/
public async $getAvgBlockHealthPerPoolId(poolId: number): Promise<number> {
const params: any[] = [];
const query = `
SELECT AVG(blocks_audits.match_rate) AS avg_match_rate
FROM blocks
JOIN blocks_audits ON blocks.height = blocks_audits.height
WHERE blocks.pool_id = ?
`;
params.push(poolId);
try {
const [rows] = await DB.query(query, params);
if (!rows[0] || !rows[0].avg_match_rate) {
return 0;
}
return Math.round(rows[0].avg_match_rate * 100) / 100;
} catch (e) {
logger.err(`Cannot get average block health for pool id ${poolId}. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}
/**
* Get average block health for all blocks for a single pool
*/
public async $getTotalRewardForPoolId(poolId: number): Promise<number> {
const params: any[] = [];
const query = `
SELECT sum(reward) as total_reward
FROM blocks
WHERE blocks.pool_id = ?
`;
params.push(poolId);
try {
const [rows] = await DB.query(query, params);
if (!rows[0] || !rows[0].total_reward) {
return 0;
}
return rows[0].total_reward;
} catch (e) {
logger.err(`Cannot get total reward for pool id ${poolId}. Reason: ` + (e instanceof Error ? e.message : e));
throw e;
}
}
/** /**
* Get the oldest indexed block * Get the oldest indexed block
*/ */

View File

@@ -73,6 +73,11 @@ class PriceUpdater {
} }
public async $run(): Promise<void> { public async $run(): Promise<void> {
if (config.MEMPOOL.NETWORK === 'signet' || config.MEMPOOL.NETWORK === 'testnet') {
// Coins have no value on testnet/signet, so we want to always show 0
return;
}
if (this.running === true) { if (this.running === true) {
return; return;
} }
@@ -88,7 +93,7 @@ class PriceUpdater {
if (this.historyInserted === false && config.DATABASE.ENABLED === true) { if (this.historyInserted === false && config.DATABASE.ENABLED === true) {
await this.$insertHistoricalPrices(); await this.$insertHistoricalPrices();
} }
} catch (e) { } catch (e: any) {
logger.err(`Cannot save BTC prices in db. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining); logger.err(`Cannot save BTC prices in db. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining);
} }

View File

@@ -112,6 +112,7 @@ Below we list all settings from `mempool-config.json` and the corresponding over
"ADVANCED_GBT_MEMPOOL": false, "ADVANCED_GBT_MEMPOOL": false,
"CPFP_INDEXING": false, "CPFP_INDEXING": false,
"MAX_BLOCKS_BULK_QUERY": 0, "MAX_BLOCKS_BULK_QUERY": 0,
"DISK_CACHE_BLOCK_INTERVAL": 6
}, },
``` ```
@@ -143,6 +144,7 @@ Corresponding `docker-compose.yml` overrides:
MEMPOOL_ADVANCED_GBT_MEMPOOL: "" MEMPOOL_ADVANCED_GBT_MEMPOOL: ""
MEMPOOL_CPFP_INDEXING: "" MEMPOOL_CPFP_INDEXING: ""
MAX_BLOCKS_BULK_QUERY: "" MAX_BLOCKS_BULK_QUERY: ""
DISK_CACHE_BLOCK_INTERVAL: ""
... ...
``` ```
@@ -432,3 +434,26 @@ Corresponding `docker-compose.yml` overrides:
CLIGHTNING_SOCKET: "" CLIGHTNING_SOCKET: ""
... ...
``` ```
<br/>
`mempool-config.json`:
```json
"MAXMIND": {
"ENABLED": true,
"GEOLITE2_CITY": "/usr/local/share/GeoIP/GeoLite2-City.mmdb",
"GEOLITE2_ASN": "/usr/local/share/GeoIP/GeoLite2-ASN.mmdb",
"GEOIP2_ISP": "/usr/local/share/GeoIP/GeoIP2-ISP.mmdb"
}
```
Corresponding `docker-compose.yml` overrides:
```yaml
api:
environment:
MAXMIND_ENABLED: true,
MAXMIND_GEOLITE2_CITY: "/backend/GeoIP/GeoLite2-City.mmdb",
MAXMIND_GEOLITE2_ASN": "/backend/GeoIP/GeoLite2-ASN.mmdb",
MAXMIND_GEOIP2_ISP": "/backend/GeoIP/GeoIP2-ISP.mmdb"
...
```

View File

@@ -17,6 +17,7 @@ WORKDIR /backend
RUN chown 1000:1000 ./ RUN chown 1000:1000 ./
COPY --from=builder --chown=1000:1000 /build/package ./package/ COPY --from=builder --chown=1000:1000 /build/package ./package/
COPY --from=builder --chown=1000:1000 /build/GeoIP ./GeoIP/
COPY --from=builder --chown=1000:1000 /build/mempool-config.json /build/start.sh /build/wait-for-it.sh ./ COPY --from=builder --chown=1000:1000 /build/mempool-config.json /build/start.sh /build/wait-for-it.sh ./
USER 1000 USER 1000

View File

@@ -26,7 +26,8 @@
"ADVANCED_GBT_AUDIT": __MEMPOOL_ADVANCED_GBT_AUDIT__, "ADVANCED_GBT_AUDIT": __MEMPOOL_ADVANCED_GBT_AUDIT__,
"ADVANCED_GBT_MEMPOOL": __MEMPOOL_ADVANCED_GBT_MEMPOOL__, "ADVANCED_GBT_MEMPOOL": __MEMPOOL_ADVANCED_GBT_MEMPOOL__,
"CPFP_INDEXING": __MEMPOOL_CPFP_INDEXING__, "CPFP_INDEXING": __MEMPOOL_CPFP_INDEXING__,
"MAX_BLOCKS_BULK_QUERY": __MEMPOOL_MAX_BLOCKS_BULK_QUERY__ "MAX_BLOCKS_BULK_QUERY": __MEMPOOL_MAX_BLOCKS_BULK_QUERY__,
"DISK_CACHE_BLOCK_INTERVAL": __MEMPOOL_DISK_CACHE_BLOCK_INTERVAL__
}, },
"CORE_RPC": { "CORE_RPC": {
"HOST": "__CORE_RPC_HOST__", "HOST": "__CORE_RPC_HOST__",
@@ -107,5 +108,11 @@
"LIQUID_ONION": "__EXTERNAL_DATA_SERVER_LIQUID_ONION__", "LIQUID_ONION": "__EXTERNAL_DATA_SERVER_LIQUID_ONION__",
"BISQ_URL": "__EXTERNAL_DATA_SERVER_BISQ_URL__", "BISQ_URL": "__EXTERNAL_DATA_SERVER_BISQ_URL__",
"BISQ_ONION": "__EXTERNAL_DATA_SERVER_BISQ_ONION__" "BISQ_ONION": "__EXTERNAL_DATA_SERVER_BISQ_ONION__"
},
"MAXMIND": {
"ENABLED": __MAXMIND_ENABLED__,
"GEOLITE2_CITY": "__MAXMIND_GEOLITE2_CITY__",
"GEOLITE2_ASN": "__MAXMIND_GEOLITE2_ASN__",
"GEOIP2_ISP": "__MAXMIND_GEOIP2_ISP__"
} }
} }

View File

@@ -22,7 +22,6 @@ __MEMPOOL_EXTERNAL_MAX_RETRY__=${MEMPOOL_EXTERNAL_MAX_RETRY:=1}
__MEMPOOL_EXTERNAL_RETRY_INTERVAL__=${MEMPOOL_EXTERNAL_RETRY_INTERVAL:=0} __MEMPOOL_EXTERNAL_RETRY_INTERVAL__=${MEMPOOL_EXTERNAL_RETRY_INTERVAL:=0}
__MEMPOOL_USER_AGENT__=${MEMPOOL_USER_AGENT:=mempool} __MEMPOOL_USER_AGENT__=${MEMPOOL_USER_AGENT:=mempool}
__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__=${MEMPOOL_STDOUT_LOG_MIN_PRIORITY:=info} __MEMPOOL_STDOUT_LOG_MIN_PRIORITY__=${MEMPOOL_STDOUT_LOG_MIN_PRIORITY:=info}
__MEMPOOL_INDEXING_BLOCKS_AMOUNT__=${MEMPOOL_INDEXING_BLOCKS_AMOUNT:=false}
__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__=${MEMPOOL_AUTOMATIC_BLOCK_REINDEXING:=false} __MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__=${MEMPOOL_AUTOMATIC_BLOCK_REINDEXING:=false}
__MEMPOOL_POOLS_JSON_URL__=${MEMPOOL_POOLS_JSON_URL:=https://raw.githubusercontent.com/mempool/mining-pools/master/pools-v2.json} __MEMPOOL_POOLS_JSON_URL__=${MEMPOOL_POOLS_JSON_URL:=https://raw.githubusercontent.com/mempool/mining-pools/master/pools-v2.json}
__MEMPOOL_POOLS_JSON_TREE_URL__=${MEMPOOL_POOLS_JSON_TREE_URL:=https://api.github.com/repos/mempool/mining-pools/git/trees/master} __MEMPOOL_POOLS_JSON_TREE_URL__=${MEMPOOL_POOLS_JSON_TREE_URL:=https://api.github.com/repos/mempool/mining-pools/git/trees/master}
@@ -31,6 +30,7 @@ __MEMPOOL_ADVANCED_GBT_AUDIT__=${MEMPOOL_ADVANCED_GBT_AUDIT:=false}
__MEMPOOL_ADVANCED_GBT_MEMPOOL__=${MEMPOOL_ADVANCED_GBT_MEMPOOL:=false} __MEMPOOL_ADVANCED_GBT_MEMPOOL__=${MEMPOOL_ADVANCED_GBT_MEMPOOL:=false}
__MEMPOOL_CPFP_INDEXING__=${MEMPOOL_CPFP_INDEXING:=false} __MEMPOOL_CPFP_INDEXING__=${MEMPOOL_CPFP_INDEXING:=false}
__MEMPOOL_MAX_BLOCKS_BULK_QUERY__=${MEMPOOL_MAX_BLOCKS_BULK_QUERY:=0} __MEMPOOL_MAX_BLOCKS_BULK_QUERY__=${MEMPOOL_MAX_BLOCKS_BULK_QUERY:=0}
__MEMPOOL_DISK_CACHE_BLOCK_INTERVAL__=${MEMPOOL_DISK_CACHE_BLOCK_INTERVAL:=6}
# CORE_RPC # CORE_RPC
__CORE_RPC_HOST__=${CORE_RPC_HOST:=127.0.0.1} __CORE_RPC_HOST__=${CORE_RPC_HOST:=127.0.0.1}
@@ -112,6 +112,13 @@ __LND_REST_API_URL__=${LND_REST_API_URL:="https://localhost:8080"}
# CLN # CLN
__CLIGHTNING_SOCKET__=${CLIGHTNING_SOCKET:=""} __CLIGHTNING_SOCKET__=${CLIGHTNING_SOCKET:=""}
# MAXMIND
__MAXMIND_ENABLED__=${MAXMIND_ENABLED:=true}
__MAXMIND_GEOLITE2_CITY__=${MAXMIND_GEOLITE2_CITY:="/backend/GeoIP/GeoLite2-City.mmdb"}
__MAXMIND_GEOLITE2_ASN__=${MAXMIND_GEOLITE2_ASN:="/backend/GeoIP/GeoLite2-ASN.mmdb"}
__MAXMIND_GEOIP2_ISP__=${MAXMIND_GEOIP2_ISP:=""}
mkdir -p "${__MEMPOOL_CACHE_DIR__}" mkdir -p "${__MEMPOOL_CACHE_DIR__}"
sed -i "s/__MEMPOOL_NETWORK__/${__MEMPOOL_NETWORK__}/g" mempool-config.json sed -i "s/__MEMPOOL_NETWORK__/${__MEMPOOL_NETWORK__}/g" mempool-config.json
@@ -135,7 +142,6 @@ sed -i "s!__MEMPOOL_EXTERNAL_MAX_RETRY__!${__MEMPOOL_EXTERNAL_MAX_RETRY__}!g" me
sed -i "s!__MEMPOOL_EXTERNAL_RETRY_INTERVAL__!${__MEMPOOL_EXTERNAL_RETRY_INTERVAL__}!g" mempool-config.json sed -i "s!__MEMPOOL_EXTERNAL_RETRY_INTERVAL__!${__MEMPOOL_EXTERNAL_RETRY_INTERVAL__}!g" mempool-config.json
sed -i "s!__MEMPOOL_USER_AGENT__!${__MEMPOOL_USER_AGENT__}!g" mempool-config.json sed -i "s!__MEMPOOL_USER_AGENT__!${__MEMPOOL_USER_AGENT__}!g" mempool-config.json
sed -i "s/__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__/${__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__}/g" mempool-config.json sed -i "s/__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__/${__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__}/g" mempool-config.json
sed -i "s/__MEMPOOL_INDEXING_BLOCKS_AMOUNT__/${__MEMPOOL_INDEXING_BLOCKS_AMOUNT__}/g" mempool-config.json
sed -i "s/__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__/${__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__}/g" mempool-config.json sed -i "s/__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__/${__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__}/g" mempool-config.json
sed -i "s!__MEMPOOL_POOLS_JSON_URL__!${__MEMPOOL_POOLS_JSON_URL__}!g" mempool-config.json sed -i "s!__MEMPOOL_POOLS_JSON_URL__!${__MEMPOOL_POOLS_JSON_URL__}!g" mempool-config.json
sed -i "s!__MEMPOOL_POOLS_JSON_TREE_URL__!${__MEMPOOL_POOLS_JSON_TREE_URL__}!g" mempool-config.json sed -i "s!__MEMPOOL_POOLS_JSON_TREE_URL__!${__MEMPOOL_POOLS_JSON_TREE_URL__}!g" mempool-config.json
@@ -144,6 +150,7 @@ sed -i "s!__MEMPOOL_ADVANCED_GBT_MEMPOOL__!${__MEMPOOL_ADVANCED_GBT_MEMPOOL__}!g
sed -i "s!__MEMPOOL_ADVANCED_GBT_AUDIT__!${__MEMPOOL_ADVANCED_GBT_AUDIT__}!g" mempool-config.json sed -i "s!__MEMPOOL_ADVANCED_GBT_AUDIT__!${__MEMPOOL_ADVANCED_GBT_AUDIT__}!g" mempool-config.json
sed -i "s!__MEMPOOL_CPFP_INDEXING__!${__MEMPOOL_CPFP_INDEXING__}!g" mempool-config.json sed -i "s!__MEMPOOL_CPFP_INDEXING__!${__MEMPOOL_CPFP_INDEXING__}!g" mempool-config.json
sed -i "s!__MEMPOOL_MAX_BLOCKS_BULK_QUERY__!${__MEMPOOL_MAX_BLOCKS_BULK_QUERY__}!g" mempool-config.json sed -i "s!__MEMPOOL_MAX_BLOCKS_BULK_QUERY__!${__MEMPOOL_MAX_BLOCKS_BULK_QUERY__}!g" mempool-config.json
sed -i "s!__MEMPOOL_DISK_CACHE_BLOCK_INTERVAL__!${__MEMPOOL_DISK_CACHE_BLOCK_INTERVAL__}!g" mempool-config.json
sed -i "s/__CORE_RPC_HOST__/${__CORE_RPC_HOST__}/g" mempool-config.json sed -i "s/__CORE_RPC_HOST__/${__CORE_RPC_HOST__}/g" mempool-config.json
sed -i "s/__CORE_RPC_PORT__/${__CORE_RPC_PORT__}/g" mempool-config.json sed -i "s/__CORE_RPC_PORT__/${__CORE_RPC_PORT__}/g" mempool-config.json
@@ -215,4 +222,11 @@ sed -i "s!__LND_REST_API_URL__!${__LND_REST_API_URL__}!g" mempool-config.json
# CLN # CLN
sed -i "s!__CLIGHTNING_SOCKET__!${__CLIGHTNING_SOCKET__}!g" mempool-config.json sed -i "s!__CLIGHTNING_SOCKET__!${__CLIGHTNING_SOCKET__}!g" mempool-config.json
# MAXMIND
sed -i "s!__MAXMIND_ENABLED__!${__MAXMIND_ENABLED__}!g" mempool-config.json
sed -i "s!__MAXMIND_GEOLITE2_CITY__!${__MAXMIND_GEOLITE2_CITY__}!g" mempool-config.json
sed -i "s!__MAXMIND_GEOLITE2_ASN__!${__MAXMIND_GEOLITE2_ASN__}!g" mempool-config.json
sed -i "s!__MAXMIND_GEOIP2_ISP__!${__MAXMIND_GEOIP2_ISP__}!g" mempool-config.json
node /backend/package/index.js node /backend/package/index.js

View File

@@ -3,6 +3,11 @@
#backend #backend
cp ./docker/backend/* ./backend/ cp ./docker/backend/* ./backend/
#geoip-data
mkdir -p ./backend/GeoIP/
wget -O ./backend/GeoIP/GeoLite2-City.mmdb https://raw.githubusercontent.com/mempool/geoip-data/master/GeoLite2-City.mmdb
wget -O ./backend/GeoIP/GeoLite2-ASN.mmdb https://raw.githubusercontent.com/mempool/geoip-data/master/GeoLite2-ASN.mmdb
#frontend #frontend
localhostIP="127.0.0.1" localhostIP="127.0.0.1"
cp ./docker/frontend/* ./frontend cp ./docker/frontend/* ./frontend

3
frontend/.gitignore vendored
View File

@@ -54,7 +54,8 @@ src/resources/assets-testnet.json
src/resources/assets-testnet.minimal.json src/resources/assets-testnet.minimal.json
src/resources/pools.json src/resources/pools.json
src/resources/mining-pools/* src/resources/mining-pools/*
src/resources/*.mp4 src/resources/**/*.mp4
src/resources/**/*.vtt
# environment config # environment config
mempool-frontend-config.json mempool-frontend-config.json

View File

@@ -111,7 +111,7 @@ https://www.transifex.com/mempool/mempool/dashboard/
* Spanish @maxhodler @bisqes * Spanish @maxhodler @bisqes
* Persian @techmix * Persian @techmix
* French @Bayernatoor * French @Bayernatoor
* Korean @kcalvinalvinn * Korean @kcalvinalvinn @sogoagain
* Italian @HodlBits * Italian @HodlBits
* Hebrew @rapidlab309 * Hebrew @rapidlab309
* Georgian @wyd_idk * Georgian @wyd_idk

View File

@@ -139,26 +139,87 @@ export const specialBlocks = {
'0': { '0': {
labelEvent: 'Genesis', labelEvent: 'Genesis',
labelEventCompleted: 'The Genesis of Bitcoin', labelEventCompleted: 'The Genesis of Bitcoin',
networks: ['mainnet', 'testnet'],
}, },
'210000': { '210000': {
labelEvent: 'Bitcoin\'s 1st Halving', labelEvent: 'Bitcoin\'s 1st Halving',
labelEventCompleted: 'Block Subsidy has halved to 25 BTC per block', labelEventCompleted: 'Block Subsidy has halved to 25 BTC per block',
networks: ['mainnet', 'testnet'],
}, },
'420000': { '420000': {
labelEvent: 'Bitcoin\'s 2nd Halving', labelEvent: 'Bitcoin\'s 2nd Halving',
labelEventCompleted: 'Block Subsidy has halved to 12.5 BTC per block', labelEventCompleted: 'Block Subsidy has halved to 12.5 BTC per block',
networks: ['mainnet', 'testnet'],
}, },
'630000': { '630000': {
labelEvent: 'Bitcoin\'s 3rd Halving', labelEvent: 'Bitcoin\'s 3rd Halving',
labelEventCompleted: 'Block Subsidy has halved to 6.25 BTC per block', labelEventCompleted: 'Block Subsidy has halved to 6.25 BTC per block',
networks: ['mainnet', 'testnet'],
}, },
'709632': { '709632': {
labelEvent: 'Taproot 🌱 activation', labelEvent: 'Taproot 🌱 activation',
labelEventCompleted: 'Taproot 🌱 has been activated!', labelEventCompleted: 'Taproot 🌱 has been activated!',
networks: ['mainnet'],
}, },
'840000': { '840000': {
labelEvent: 'Bitcoin\'s 4th Halving', labelEvent: 'Bitcoin\'s 4th Halving',
labelEventCompleted: 'Block Subsidy has halved to 3.125 BTC per block', labelEventCompleted: 'Block Subsidy has halved to 3.125 BTC per block',
networks: ['mainnet', 'testnet'],
},
'1050000': {
labelEvent: 'Bitcoin\'s 5th Halving',
labelEventCompleted: 'Block Subsidy has halved to 1.5625 BTC per block',
networks: ['mainnet', 'testnet'],
},
'1260000': {
labelEvent: 'Bitcoin\'s 6th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.78125 BTC per block',
networks: ['mainnet', 'testnet'],
},
'1470000': {
labelEvent: 'Bitcoin\'s 7th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.390625 BTC per block',
networks: ['mainnet', 'testnet'],
},
'1680000': {
labelEvent: 'Bitcoin\'s 8th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.1953125 BTC per block',
networks: ['mainnet', 'testnet'],
},
'1890000': {
labelEvent: 'Bitcoin\'s 9th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.09765625 BTC per block',
networks: ['mainnet', 'testnet'],
},
'2100000': {
labelEvent: 'Bitcoin\'s 10th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.04882812 BTC per block',
networks: ['mainnet', 'testnet'],
},
'2310000': {
labelEvent: 'Bitcoin\'s 11th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.02441406 BTC per block',
networks: ['mainnet', 'testnet'],
},
'2520000': {
labelEvent: 'Bitcoin\'s 12th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.01220703 BTC per block',
networks: ['mainnet', 'testnet'],
},
'2730000': {
labelEvent: 'Bitcoin\'s 13th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.00610351 BTC per block',
networks: ['mainnet', 'testnet'],
},
'2940000': {
labelEvent: 'Bitcoin\'s 14th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.00305175 BTC per block',
networks: ['mainnet', 'testnet'],
},
'3150000': {
labelEvent: 'Bitcoin\'s 15th Halving',
labelEventCompleted: 'Block Subsidy has halved to 0.00152587 BTC per block',
networks: ['mainnet', 'testnet'],
} }
}; };

View File

@@ -13,7 +13,23 @@
<p i18n>Our mempool and blockchain explorer for the Bitcoin community, focusing on the transaction fee market and multi-layer ecosystem, completely self-hosted without any trusted third-parties.</p> <p i18n>Our mempool and blockchain explorer for the Bitcoin community, focusing on the transaction fee market and multi-layer ecosystem, completely self-hosted without any trusted third-parties.</p>
</div> </div>
<video src="/resources/mempool-promo.mp4" poster="/resources/mempool-promo.jpg" controls loop playsinline [autoplay]="true" [muted]="true"></video> <video src="/resources/promo-video/mempool-promo.mp4" poster="/resources/promo-video/mempool-promo.jpg" controls loop playsinline [autoplay]="true" [muted]="true">
<track label="English" kind="captions" srclang="en" src="/resources/promo-video/en.vtt" [attr.default]="showSubtitles('en') ? '' : null">
<track label="日本語" kind="captions" srclang="ja" src="/resources/promo-video/ja.vtt" [attr.default]="showSubtitles('ja') ? '' : null">
<track label="中文" kind="captions" srclang="zh" src="/resources/promo-video/zh.vtt" [attr.default]="showSubtitles('zh') ? '' : null">
<track label="Svenska" kind="captions" srclang="sv" src="/resources/promo-video/sv.vtt" [attr.default]="showSubtitles('sv') ? '' : null">
<track label="Čeština" kind="captions" srclang="cs" src="/resources/promo-video/cs.vtt" [attr.default]="showSubtitles('cs') ? '' : null">
<track label="Suomi" kind="captions" srclang="fi" src="/resources/promo-video/fi.vtt" [attr.default]="showSubtitles('fi') ? '' : null">
<track label="Français" kind="captions" srclang="fr" src="/resources/promo-video/fr.vtt" [attr.default]="showSubtitles('fr') ? '' : null">
<track label="Deutsch" kind="captions" srclang="de" src="/resources/promo-video/de.vtt" [attr.default]="showSubtitles('de') ? '' : null">
<track label="Italiano" kind="captions" srclang="it" src="/resources/promo-video/it.vtt" [attr.default]="showSubtitles('it') ? '' : null">
<track label="Lietuvių" kind="captions" srclang="lt" src="/resources/promo-video/lt.vtt" [attr.default]="showSubtitles('lt') ? '' : null">
<track label="Norsk" kind="captions" srclang="nb" src="/resources/promo-video/nb.vtt" [attr.default]="showSubtitles('nb') ? '' : null">
<track label="فارسی" kind="captions" srclang="fa" src="/resources/promo-video/fa.vtt" [attr.default]="showSubtitles('fa') ? '' : null">
<track label="Polski" kind="captions" srclang="pl" src="/resources/promo-video/pl.vtt" [attr.default]="showSubtitles('pl') ? '' : null">
<track label="Română" kind="captions" srclang="ro" src="/resources/promo-video/ro.vtt" [attr.default]="showSubtitles('ro') ? '' : null">
<track label="Português" kind="captions" srclang="pt" src="/resources/promo-video/pt.vtt" [attr.default]="showSubtitles('pt') ? '' : null">
</video>
<div class="enterprise-sponsor" id="enterprise-sponsors"> <div class="enterprise-sponsor" id="enterprise-sponsors">
<h3 i18n="about.sponsors.enterprise.withRocket">Enterprise Sponsors 🚀</h3> <h3 i18n="about.sponsors.enterprise.withRocket">Enterprise Sponsors 🚀</h3>

View File

@@ -68,7 +68,7 @@ export class AboutComponent implements OnInit {
tap(() => this.goToAnchor()) tap(() => this.goToAnchor())
); );
} }
ngAfterViewInit() { ngAfterViewInit() {
this.goToAnchor(); this.goToAnchor();
} }
@@ -90,4 +90,8 @@ export class AboutComponent implements OnInit {
this.showNavigateToSponsor = true; this.showNavigateToSponsor = true;
} }
} }
showSubtitles(language) {
return ( this.locale.startsWith( language ) && !this.locale.startsWith('en') );
}
} }

View File

@@ -6,7 +6,7 @@
<div [attr.data-cy]="'bitcoin-block-offset-' + offset + '-index-' + i" <div [attr.data-cy]="'bitcoin-block-offset-' + offset + '-index-' + i"
class="text-center bitcoin-block mined-block blockchain-blocks-offset-{{ offset }}-index-{{ i }}" class="text-center bitcoin-block mined-block blockchain-blocks-offset-{{ offset }}-index-{{ i }}"
id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]" id="bitcoin-block-{{ block.height }}" [ngStyle]="blockStyles[i]"
[class.blink-bg]="(specialBlocks[block.height] !== undefined)"> [class.blink-bg]="isSpecial(block.height)">
<a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }" <a draggable="false" [routerLink]="['/block/' | relativeUrl, block.id]" [state]="{ data: { block: block } }"
class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}">&nbsp;</a> class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}">&nbsp;</a>
<div [attr.data-cy]="'bitcoin-block-' + i + '-height'" class="block-height"> <div [attr.data-cy]="'bitcoin-block-' + i + '-height'" class="block-height">

View File

@@ -269,6 +269,10 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
this.cd.markForCheck(); this.cd.markForCheck();
} }
isSpecial(height: number): boolean {
return this.specialBlocks[height]?.networks.includes(this.stateService.network || 'mainnet') ? true : false;
}
getStyleForBlock(block: BlockchainBlock, index: number, animateEnterFrom: number = 0) { getStyleForBlock(block: BlockchainBlock, index: number, animateEnterFrom: number = 0) {
if (!block || block.placeholder) { if (!block || block.placeholder) {
return this.getStyleForPlaceholderBlock(index, animateEnterFrom); return this.getStyleForPlaceholderBlock(index, animateEnterFrom);

View File

@@ -26,7 +26,7 @@
</thead> </thead>
<tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''"> <tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock"> <tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
<td class="text-left" [class]="widget ? 'widget' : ''"> <td class="height text-left" [class]="widget ? 'widget' : ''">
<a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a> <a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a>
</td> </td>
<td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
@@ -89,7 +89,6 @@
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<img width="1" height="25" style="opacity: 0">
<span class="skeleton-loader" style="max-width: 125px"></span> <span class="skeleton-loader" style="max-width: 125px"></span>
</td> </td>
<td class="timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'"> <td class="timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
@@ -98,7 +97,7 @@
<td class="mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'"> <td class="mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 125px"></span> <span class="skeleton-loader" style="max-width: 125px"></span>
</td> </td>
<td *ngIf="auditAvailable" class="health text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">

View File

@@ -51,7 +51,12 @@ tr, td, th {
.pool.widget { .pool.widget {
width: 40%; width: 40%;
padding-left: 24px; padding-left: 24px;
@media (max-width: 376px) { @media (min-width: 768px) AND (max-width: 926px) {
padding-left: 0px;
width: 60%;
}
@media (max-width: 430px) {
padding-left: 0px;
width: 60%; width: 60%;
} }
} }
@@ -59,6 +64,10 @@ tr, td, th {
display: inline-block; display: inline-block;
vertical-align: text-top; vertical-align: text-top;
padding-left: 10px; padding-left: 10px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
max-width: 160px;
} }
.height { .height {
@@ -69,6 +78,12 @@ tr, td, th {
@media (max-width: 576px) { @media (max-width: 576px) {
width: 10%; width: 10%;
} }
@media (min-width: 768px) AND (max-width: 926px) {
width: 30%;
}
@media (max-width: 430px) {
width: 30%;
}
} }
.height.legacy { .height.legacy {
width: 15%; width: 15%;
@@ -92,7 +107,7 @@ tr, td, th {
.mined { .mined {
width: 13%; width: 13%;
@media (max-width: 576px) { @media (max-width: 730px) {
display: none; display: none;
} }
} }
@@ -138,7 +153,7 @@ tr, td, th {
.fees { .fees {
width: 8%; width: 8%;
@media (max-width: 650px) { @media (max-width: 820px) {
display: none; display: none;
} }
} }
@@ -163,6 +178,16 @@ tr, td, th {
width: 30%; width: 30%;
padding-right: 0; padding-right: 0;
} }
@media (min-width: 768px) AND (max-width: 926px) {
overflow: hidden;
text-overflow: ellipsis;
max-width: 90px;
}
@media (max-width: 430px) {
overflow: hidden;
text-overflow: ellipsis;
max-width: 90px;
}
} }
.size { .size {
@@ -189,10 +214,10 @@ tr, td, th {
.health { .health {
width: 10%; width: 10%;
@media (max-width: 1000px) { @media (max-width: 1105px) {
width: 13%; width: 13%;
} }
@media (max-width: 950px) { @media (max-width: 560px) {
display: none; display: none;
} }
@@ -202,7 +227,7 @@ tr, td, th {
} }
.health.widget { .health.widget {
width: 25%; width: 25%;
@media (max-width: 1000px) { @media (max-width: 1105px) {
display: none; display: none;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
@@ -242,4 +267,4 @@ tr, td, th {
vertical-align: middle; vertical-align: middle;
max-width: 50vw; max-width: 50vw;
text-align: left; text-align: left;
} }

View File

@@ -2,17 +2,18 @@
<table class="table latest-adjustments"> <table class="table latest-adjustments">
<thead> <thead>
<tr> <tr>
<th class="d-none d-md-block" i18n="block.height">Height</th> <th class="" i18n="block.height">Height</th>
<th i18n="mining.adjusted" class="text-left">Adjusted</th> <th class="date text-left" i18n="mining.adjusted">Adjusted</th>
<th i18n="mining.difficulty" class="text-right">Difficulty</th> <th class="text-right" i18n="mining.difficulty">Difficulty</th>
<th i18n="mining.change" class="text-right">Change</th> <th class="text-right" i18n="mining.change">Change</th>
</tr> </tr>
</thead> </thead>
<tbody *ngIf="(hashrateObservable$ | async) as data"> <tbody *ngIf="(hashrateObservable$ | async) as data">
<tr *ngFor="let diffChange of data"> <tr *ngFor="let diffChange of data">
<td class="d-none d-md-block"><a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height <td class="">
}}</a></td> <a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height }}</a>
<td class="text-left"> </td>
<td class="date text-left">
<app-time kind="since" [time]="diffChange.timestamp" [fastRender]="true"></app-time> <app-time kind="since" [time]="diffChange.timestamp" [fastRender]="true"></app-time>
</td> </td>
<td class="text-right">{{ diffChange.difficultyShorten }}</td> <td class="text-right">{{ diffChange.difficultyShorten }}</td>
@@ -23,8 +24,8 @@
</tbody> </tbody>
<tbody *ngIf="isLoading"> <tbody *ngIf="isLoading">
<tr *ngFor="let item of [1,2,3,4,5,6]"> <tr *ngFor="let item of [1,2,3,4,5,6]">
<td class="d-none d-md-block w-75"><span class="skeleton-loader"></span></td> <td class=""><span class="skeleton-loader"></span></td>
<td class="text-left"><span class="skeleton-loader w-75"></span></td> <td class="date text-left"><span class="skeleton-loader w-75"></span></td>
<td class="text-right"><span class="skeleton-loader w-75"></span></td> <td class="text-right"><span class="skeleton-loader w-75"></span></td>
<td class="text-right"><span class="skeleton-loader w-75"></span></td> <td class="text-right"><span class="skeleton-loader w-75"></span></td>
</tr> </tr>

View File

@@ -17,3 +17,12 @@
} }
} }
} }
.date {
@media (min-width: 767px) AND (max-width: 991px) {
display: none;
}
@media (max-width: 500px) {
display: none;
}
}

View File

@@ -2,7 +2,7 @@
<div class="mempool-blocks-container" [class.time-ltr]="timeLtr" *ngIf="(difficultyAdjustments$ | async) as da;"> <div class="mempool-blocks-container" [class.time-ltr]="timeLtr" *ngIf="(difficultyAdjustments$ | async) as da;">
<div class="flashing"> <div class="flashing">
<ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn"> <ng-template ngFor let-projectedBlock [ngForOf]="mempoolBlocks$ | async" let-i="index" [ngForTrackBy]="trackByFn">
<div [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink"> <div @blockEntryTrigger [@.disabled]="!animateEntry" [attr.data-cy]="'mempool-block-' + i" class="bitcoin-block text-center mempool-block" id="mempool-block-{{ i }}" [ngStyle]="mempoolBlockStyles[i]" [class.blink-bg]="projectedBlock.blink">
<a draggable="false" [routerLink]="['/mempool-block/' | relativeUrl, i]" <a draggable="false" [routerLink]="['/mempool-block/' | relativeUrl, i]"
class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}">&nbsp;</a> class="blockLink" [ngClass]="{'disabled': (this.stateService.blockScrolling$ | async)}">&nbsp;</a>
<div class="block-body"> <div class="block-body">

View File

@@ -1,5 +1,5 @@
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core'; import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { Subscription, Observable, fromEvent, merge, of, combineLatest, timer } from 'rxjs'; import { Subscription, Observable, fromEvent, merge, of, combineLatest } from 'rxjs';
import { MempoolBlock } from '../../interfaces/websocket.interface'; import { MempoolBlock } from '../../interfaces/websocket.interface';
import { StateService } from '../../services/state.service'; import { StateService } from '../../services/state.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
@@ -9,11 +9,18 @@ import { specialBlocks } from '../../app.constants';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
import { Location } from '@angular/common'; import { Location } from '@angular/common';
import { DifficultyAdjustment } from '../../interfaces/node-api.interface'; import { DifficultyAdjustment } from '../../interfaces/node-api.interface';
import { animate, style, transition, trigger } from '@angular/animations';
@Component({ @Component({
selector: 'app-mempool-blocks', selector: 'app-mempool-blocks',
templateUrl: './mempool-blocks.component.html', templateUrl: './mempool-blocks.component.html',
styleUrls: ['./mempool-blocks.component.scss'], styleUrls: ['./mempool-blocks.component.scss'],
animations: [trigger('blockEntryTrigger', [
transition(':enter', [
style({ transform: 'translateX(-155px)' }),
animate('2s 0s ease', style({ transform: '' })),
]),
])],
changeDetection: ChangeDetectionStrategy.OnPush, changeDetection: ChangeDetectionStrategy.OnPush,
}) })
export class MempoolBlocksComponent implements OnInit, OnDestroy { export class MempoolBlocksComponent implements OnInit, OnDestroy {
@@ -32,12 +39,14 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
isLoadingWebsocketSubscription: Subscription; isLoadingWebsocketSubscription: Subscription;
blockSubscription: Subscription; blockSubscription: Subscription;
networkSubscription: Subscription; networkSubscription: Subscription;
chainTipSubscription: Subscription;
network = ''; network = '';
now = new Date().getTime(); now = new Date().getTime();
timeOffset = 0; timeOffset = 0;
showMiningInfo = false; showMiningInfo = false;
timeLtrSubscription: Subscription; timeLtrSubscription: Subscription;
timeLtr: boolean; timeLtr: boolean;
animateEntry: boolean = false;
blockWidth = 125; blockWidth = 125;
blockPadding = 30; blockPadding = 30;
@@ -53,6 +62,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
resetTransitionTimeout: number; resetTransitionTimeout: number;
chainTip: number = -1;
blockIndex = 1; blockIndex = 1;
constructor( constructor(
@@ -69,6 +79,8 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
} }
ngOnInit() { ngOnInit() {
this.chainTip = this.stateService.latestBlockHeight;
if (['', 'testnet', 'signet'].includes(this.stateService.network)) { if (['', 'testnet', 'signet'].includes(this.stateService.network)) {
this.enabledMiningInfoIfNeeded(this.location.path()); this.enabledMiningInfoIfNeeded(this.location.path());
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url)); this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
@@ -116,9 +128,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
mempoolBlocks.forEach((block, i) => { mempoolBlocks.forEach((block, i) => {
block.index = this.blockIndex + i; block.index = this.blockIndex + i;
block.height = lastBlock.height + i + 1; block.height = lastBlock.height + i + 1;
if (this.stateService.network === '') { block.blink = specialBlocks[block.height]?.networks.includes(this.stateService.network || 'mainnet') ? true : false;
block.blink = specialBlocks[block.height] ? true : false;
}
}); });
const stringifiedBlocks = JSON.stringify(mempoolBlocks); const stringifiedBlocks = JSON.stringify(mempoolBlocks);
@@ -155,11 +165,24 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
this.blockSubscription = this.stateService.blocks$ this.blockSubscription = this.stateService.blocks$
.subscribe(([block]) => { .subscribe(([block]) => {
if (block?.extras?.matchRate >= 66 && !this.tabHidden) { if (this.chainTip === -1) {
this.animateEntry = block.height === this.stateService.latestBlockHeight;
} else {
this.animateEntry = block.height > this.chainTip;
}
this.chainTip = this.stateService.latestBlockHeight;
if ((block?.extras?.similarity == null || block?.extras?.similarity > 0.5) && !this.tabHidden) {
this.blockIndex++; this.blockIndex++;
} }
}); });
this.chainTipSubscription = this.stateService.chainTip$.subscribe((height) => {
if (this.chainTip === -1) {
this.chainTip = height;
}
});
this.networkSubscription = this.stateService.networkChanged$ this.networkSubscription = this.stateService.networkChanged$
.subscribe((network) => this.network = network); .subscribe((network) => this.network = network);
@@ -195,11 +218,12 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
this.blockSubscription.unsubscribe(); this.blockSubscription.unsubscribe();
this.networkSubscription.unsubscribe(); this.networkSubscription.unsubscribe();
this.timeLtrSubscription.unsubscribe(); this.timeLtrSubscription.unsubscribe();
this.chainTipSubscription.unsubscribe();
clearTimeout(this.resetTransitionTimeout); clearTimeout(this.resetTransitionTimeout);
} }
trackByFn(index: number, block: MempoolBlock) { trackByFn(index: number, block: MempoolBlock) {
return block.index; return (block.isStack) ? 'stack' : block.index;
} }
reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] { reduceMempoolBlocksToFitScreen(blocks: MempoolBlock[]): MempoolBlock[] {
@@ -216,6 +240,9 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
lastBlock.medianFee = this.median(lastBlock.feeRange); lastBlock.medianFee = this.median(lastBlock.feeRange);
lastBlock.totalFees += block.totalFees; lastBlock.totalFees += block.totalFees;
} }
if (blocks.length) {
blocks[blocks.length - 1].isStack = blocks[blocks.length - 1].blockVSize > this.stateService.blockVSize;
}
return blocks; return blocks;
} }
@@ -334,4 +361,4 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
} }
return emptyBlocks; return emptyBlocks;
} }
} }

View File

@@ -86,11 +86,6 @@ export class PoolPreviewComponent implements OnInit {
regexes += regex + '", "'; regexes += regex + '", "';
} }
poolStats.pool.regexes = regexes.slice(0, -3); poolStats.pool.regexes = regexes.slice(0, -3);
poolStats.pool.addresses = poolStats.pool.addresses;
if (poolStats.reportedHashrate) {
poolStats.luck = poolStats.estimatedHashrate / poolStats.reportedHashrate * 100;
}
this.openGraphService.waitOver('pool-stats-' + this.slug); this.openGraphService.waitOver('pool-stats-' + this.slug);

View File

@@ -38,12 +38,12 @@
<tr *ngIf="!isMobile()" class="taller-row"> <tr *ngIf="!isMobile()" class="taller-row">
<td class="label addresses" i18n="mining.addresses">Addresses</td> <td class="label addresses" i18n="mining.addresses">Addresses</td>
<td *ngIf="poolStats.pool.addresses.length else nodata" style="padding-top: 25px"> <td *ngIf="poolStats.pool.addresses.length else nodata" style="padding-top: 25px">
<a [routerLink]="['/address' | relativeUrl, poolStats.pool.addresses[0]]" class="first-address"> <a class="addresses-data" [routerLink]="['/address' | relativeUrl, poolStats.pool.addresses[0]]">
{{ poolStats.pool.addresses[0] }} {{ poolStats.pool.addresses[0] }}
</a> </a>
<div> <div>
<div #collapse="ngbCollapse" [(ngbCollapse)]="gfg"> <div #collapse="ngbCollapse" [(ngbCollapse)]="gfg">
<a *ngFor="let address of poolStats.pool.addresses | slice: 1" <a class="addresses-data" *ngFor="let address of poolStats.pool.addresses | slice: 1"
[routerLink]="['/address' | relativeUrl, address]">{{ [routerLink]="['/address' | relativeUrl, address]">{{
address }}<br></a> address }}<br></a>
</div> </div>
@@ -67,13 +67,13 @@
[attr.aria-expanded]="!gfg" aria-controls="collapseExample"> [attr.aria-expanded]="!gfg" aria-controls="collapseExample">
<span i18n="show-all">Show all</span> ({{ poolStats.pool.addresses.length }}) <span i18n="show-all">Show all</span> ({{ poolStats.pool.addresses.length }})
</button> </button>
<a [routerLink]="['/address' | relativeUrl, poolStats.pool.addresses[0]]"> <a class="addresses-data" [routerLink]="['/address' | relativeUrl, poolStats.pool.addresses[0]]">
{{ poolStats.pool.addresses[0] | shortenString: 40 }} {{ poolStats.pool.addresses[0] | shortenString: 30 }}
</a> </a>
<div #collapse="ngbCollapse" [(ngbCollapse)]="gfg" style="width: 100%"> <div #collapse="ngbCollapse" [(ngbCollapse)]="gfg" style="width: 100%">
<a *ngFor="let address of poolStats.pool.addresses | slice: 1" <a class="addresses-data" *ngFor="let address of poolStats.pool.addresses | slice: 1"
[routerLink]="['/address' | relativeUrl, address]">{{ [routerLink]="['/address' | relativeUrl, address]">{{
address | shortenString: 40 }}<br></a> address | shortenString: 30 }}<br></a>
</div> </div>
</div> </div>
</td> </td>
@@ -88,22 +88,25 @@
<!-- Hashrate desktop --> <!-- Hashrate desktop -->
<tr *ngIf="!isMobile()" class="taller-row"> <tr *ngIf="!isMobile()" class="taller-row">
<td class="label" i18n="mining.hashrate-24h">Hashrate (24h)</td>
<td class="data"> <td class="data">
<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" style="width: 37%" i18n="mining.estimated">Estimated</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.reward">Reward</th>
<th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th>
<th scope="col" class="block-count-title" style="width: 26%" i18n="mining.luck">Luck</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="latest-blocks.avg_health">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td>{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</td> <td class="text-center"><app-amount [satoshis]="poolStats.totalReward" digitsInfo="1.0-0" [noFiat]="true"></app-amount></td>
<ng-template *ngIf="poolStats.luck; else noreported"> <td class="text-center">{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</td>
<td>{{ poolStats.reportedHashrate | amountShortener : 1 : 'H/s' }}</td> <td class="text-center"><span class="health-badge badge" [class.badge-success]="poolStats.avgBlockHealth >= 99"
<td>{{ formatNumber(poolStats.luck, this.locale, '1.2-2') }}%</td> [class.badge-warning]="poolStats.avgBlockHealth >= 75 && poolStats.avgBlockHealth < 99" [class.badge-danger]="poolStats.avgBlockHealth < 75"
</ng-template> *ngIf="poolStats.avgBlockHealth != null; else nullHealth">{{ poolStats.avgBlockHealth }}%</span>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
</tbody> </tbody>
</table> </table>
</td> </td>
@@ -111,49 +114,46 @@
<!-- Hashrate mobile --> <!-- Hashrate mobile -->
<tr *ngIf="isMobile()"> <tr *ngIf="isMobile()">
<td colspan="2"> <td colspan="2">
<span class="label" i18n="mining.hashrate-24h">Hashrate (24h)</span>
<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" style="width: 33%" i18n="mining.estimated">Estimated</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.reward">Reward</th>
<th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th>
<th scope="col" class="block-count-title" style="width: 30%" i18n="mining.luck">Luck</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="latest-blocks.avg_health">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td>{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</td> <td class="text-center"><app-amount [satoshis]="poolStats.totalReward" digitsInfo="1.0-0" [noFiat]="true"></app-amount></td>
<ng-template *ngIf="poolStats.luck; else noreported"> <td class="text-center">{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</td>
<td>{{ poolStats.reportedHashrate | amountShortener : 1 : 'H/s' }}</td> <td class="text-center"><span class="health-badge badge" [class.badge-success]="poolStats.avgBlockHealth >= 99"
<td>{{ formatNumber(poolStats.luck, this.locale, '1.2-2') }}%</td> [class.badge-warning]="poolStats.avgBlockHealth >= 75 && poolStats.avgBlockHealth < 99" [class.badge-danger]="poolStats.avgBlockHealth < 75"
</ng-template> *ngIf="poolStats.avgBlockHealth != null; else nullHealth">{{ poolStats.avgBlockHealth }}%</span>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
</tbody> </tbody>
</table> </table>
</td> </td>
</tr> </tr>
<ng-template #noreported>
<td>~</td>
<td>~</td>
</ng-template>
<!-- Mined blocks desktop --> <!-- Mined blocks desktop -->
<tr *ngIf="!isMobile()" class="taller-row"> <tr *ngIf="!isMobile()" class="taller-row">
<td class="label" i18n="mining.mined-blocks">Mined blocks</td>
<td class="data"> <td class="data">
<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" style="width: 37%" i18n="24h">24h</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title" style="width: 37%" i18n="1w">1w</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title" style="width: 26%" i18n="all">All</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td>{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 * <td class="text-center">{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td> poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td>
<td>{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 * <td class="text-center">{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td> poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td>
<td>{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 * <td class="text-center">{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td> poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td>
</tbody> </tbody>
</table> </table>
@@ -162,21 +162,20 @@
<!-- Mined blocks mobile --> <!-- Mined blocks mobile -->
<tr *ngIf="isMobile()"> <tr *ngIf="isMobile()">
<td colspan=2> <td colspan=2>
<span class="label" i18n="mining.mined-blocks">Mined blocks</span>
<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" style="width: 33%" i18n="24h">24h</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title" style="width: 37%" i18n="1w">1w</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title" style="width: 30%" i18n="all">All</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td>{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 * <td class="text-center">{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td> poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td>
<td>{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 * <td class="text-center">{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td> poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td>
<td>{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 * <td class="text-center">{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td> poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td>
</tbody> </tbody>
</table> </table>
@@ -213,8 +212,9 @@
<th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th> <th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th>
<th class="mined" i18n="latest-blocks.mined">Mined</th> <th class="mined" i18n="latest-blocks.mined">Mined</th>
<th class="coinbase text-left" i18n="latest-blocks.coinbasetag">Coinbase tag</th> <th class="coinbase text-left" i18n="latest-blocks.coinbasetag">Coinbase tag</th>
<th *ngIf="auditAvailable" class="health text-right" i18n="latest-blocks.health">Health</th>
<th class="reward text-right" i18n="latest-blocks.reward">Reward</th> <th class="reward text-right" i18n="latest-blocks.reward">Reward</th>
<th class="fees text-right" i18n="latest-blocks.fees">Fees</th> <th *ngIf="!auditAvailable" class="fees text-right" i18n="latest-blocks.fees">Fees</th>
<th class="txs text-right" i18n="dashboard.txs">TXs</th> <th class="txs text-right" i18n="dashboard.txs">TXs</th>
<th class="size" i18n="latest-blocks.size">Size</th> <th class="size" i18n="latest-blocks.size">Size</th>
</thead> </thead>
@@ -234,10 +234,24 @@
{{ block.extras.coinbaseRaw | hex2ascii }} {{ block.extras.coinbaseRaw | hex2ascii }}
</span> </span>
</td> </td>
<td *ngIf="auditAvailable" class="health text-right">
<a
class="health-badge badge"
[class.badge-success]="block.extras.matchRate >= 99"
[class.badge-warning]="block.extras.matchRate >= 75 && block.extras.matchRate < 99"
[class.badge-danger]="block.extras.matchRate < 75"
[routerLink]="block.extras.matchRate != null ? ['/block/' | relativeUrl, block.id] : null"
[state]="{ data: { block: block } }"
*ngIf="block.extras.matchRate != null; else nullHealth"
>{{ block.extras.matchRate }}%</a>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
<td class="reward text-right"> <td class="reward text-right">
<app-amount [satoshis]="block.extras.reward" digitsInfo="1.2-2" [noFiat]="true"></app-amount> <app-amount [satoshis]="block.extras.reward" digitsInfo="1.2-2" [noFiat]="true"></app-amount>
</td> </td>
<td class="fees text-right"> <td *ngIf="!auditAvailable" class="fees text-right">
<app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-2" [noFiat]="true"></app-amount> <app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-2" [noFiat]="true"></app-amount>
</td> </td>
<td class="txs text-right"> <td class="txs text-right">
@@ -364,24 +378,23 @@
<!-- Hashrate desktop --> <!-- Hashrate desktop -->
<tr *ngIf="!isMobile()" class="taller-row"> <tr *ngIf="!isMobile()" class="taller-row">
<td class="label" i18n="mining.hashrate-24h">Hashrate (24h)</td>
<td class="data"> <td class="data">
<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" style="width: 37%" i18n="mining.estimated">Estimated</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.total-reward">Reward</th>
<th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="block-count-title" style="width: 26%" i18n="mining.luck">Luck</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.luck">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
</tbody> </tbody>
@@ -391,23 +404,22 @@
<!-- Hashrate mobile --> <!-- Hashrate mobile -->
<tr *ngIf="isMobile()"> <tr *ngIf="isMobile()">
<td colspan="2"> <td colspan="2">
<span class="label" i18n="mining.hashrate-24h">Hashrate (24h)</span>
<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" style="width: 33%" i18n="mining.estimated">Estimated</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.total-reward">Reward</th>
<th scope="col" class="block-count-title" style="width: 37%" i18n="mining.reported">Reported</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="block-count-title" style="width: 30%" i18n="mining.luck">Luck</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="mining.luck">Avg Health</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
</tbody> </tbody>
@@ -417,24 +429,23 @@
<!-- Mined blocks desktop --> <!-- Mined blocks desktop -->
<tr *ngIf="!isMobile()" class="taller-row"> <tr *ngIf="!isMobile()" class="taller-row">
<td class="label" i18n="mining.mined-blocks">Mined blocks</td>
<td class="data"> <td class="data">
<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" style="width: 37%">24h</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title" style="width: 37%">1w</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title" style="width: 26%" i18n="all">All</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
</tbody> </tbody>
@@ -444,23 +455,22 @@
<!-- Mined blocks mobile --> <!-- Mined blocks mobile -->
<tr *ngIf="isMobile()"> <tr *ngIf="isMobile()">
<td colspan=2> <td colspan=2>
<span class="label" i18n="mining.mined-blocks">Mined blocks</span>
<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" style="width: 33%">24h</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="24h">Blocks 24h</th>
<th scope="col" class="block-count-title" style="width: 37%">1w</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="block-count-title" style="width: 30%" i18n="all">All</th> <th scope="col" class="block-count-title text-center" style="width: 33%" i18n="all">All</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
<td> <td class="text-center">
<div class="skeleton-loader data"></div> <div class="skeleton-loader data"></div>
</td> </td>
</tbody> </tbody>

View File

@@ -68,6 +68,11 @@ div.scrollable {
vertical-align: top; vertical-align: top;
padding-top: 25px; padding-top: 25px;
} }
.addresses-data {
vertical-align: top;
font-family: monospace;
font-size: 14px;
}
.data { .data {
text-align: right; text-align: right;
@@ -100,7 +105,7 @@ div.scrollable {
@media (max-width: 875px) { @media (max-width: 875px) {
padding-left: 50px; padding-left: 50px;
} }
@media (max-width: 650px) { @media (max-width: 685px) {
display: none; display: none;
} }
} }
@@ -118,7 +123,7 @@ div.scrollable {
padding-right: 10px; padding-right: 10px;
} }
@media (max-width: 875px) { @media (max-width: 875px) {
padding-right: 50px; padding-right: 20px;
} }
@media (max-width: 567px) { @media (max-width: 567px) {
padding-right: 10px; padding-right: 10px;
@@ -186,10 +191,6 @@ div.scrollable {
.block-count-title { .block-count-title {
color: #4a68b9; color: #4a68b9;
font-size: 14px; font-size: 14px;
text-align: left;
@media (max-width: 767.98px) {
text-align: center;
}
} }
.table-data tr { .table-data tr {

View File

@@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { EChartsOption, graphic } from 'echarts'; import { EChartsOption, graphic } from 'echarts';
import { BehaviorSubject, Observable, timer } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
import { distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; import { distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators';
import { BlockExtended, PoolStat } from '../../interfaces/node-api.interface'; import { BlockExtended, PoolStat } from '../../interfaces/node-api.interface';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';
@@ -35,6 +35,8 @@ export class PoolComponent implements OnInit {
blocks: BlockExtended[] = []; blocks: BlockExtended[] = [];
slug: string = undefined; slug: string = undefined;
auditAvailable = false;
loadMoreSubject: BehaviorSubject<number> = new BehaviorSubject(this.blocks[this.blocks.length - 1]?.height); loadMoreSubject: BehaviorSubject<number> = new BehaviorSubject(this.blocks[this.blocks.length - 1]?.height);
constructor( constructor(
@@ -44,6 +46,7 @@ export class PoolComponent implements OnInit {
public stateService: StateService, public stateService: StateService,
private seoService: SeoService, private seoService: SeoService,
) { ) {
this.auditAvailable = this.stateService.env.AUDIT;
} }
ngOnInit(): void { ngOnInit(): void {
@@ -74,11 +77,6 @@ export class PoolComponent implements OnInit {
regexes += regex + '", "'; regexes += regex + '", "';
} }
poolStats.pool.regexes = regexes.slice(0, -3); poolStats.pool.regexes = regexes.slice(0, -3);
poolStats.pool.addresses = poolStats.pool.addresses;
if (poolStats.reportedHashrate) {
poolStats.luck = poolStats.estimatedHashrate / poolStats.reportedHashrate * 100;
}
return Object.assign({ return Object.assign({
logo: `/resources/mining-pools/` + poolStats.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg' logo: `/resources/mining-pools/` + poolStats.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'

View File

@@ -85,21 +85,20 @@ export class StartComponent implements OnInit, OnDestroy {
}); });
this.stateService.blocks$ this.stateService.blocks$
.subscribe((blocks: any) => { .subscribe((blocks: any) => {
if (this.stateService.network !== '') {
return;
}
this.countdown = 0; this.countdown = 0;
const block = blocks[0]; const block = blocks[0];
for (const sb in specialBlocks) { for (const sb in specialBlocks) {
const height = parseInt(sb, 10); if (specialBlocks[sb].networks.includes(this.stateService.network || 'mainnet')) {
const diff = height - block.height; const height = parseInt(sb, 10);
if (diff > 0 && diff <= 1008) { const diff = height - block.height;
this.countdown = diff; if (diff > 0 && diff <= 1008) {
this.eventName = specialBlocks[sb].labelEvent; this.countdown = diff;
this.eventName = specialBlocks[sb].labelEvent;
}
} }
} }
if (specialBlocks[block.height]) { if (specialBlocks[block.height] && specialBlocks[block.height].networks.includes(this.stateService.network || 'mainnet')) {
this.specialEvent = true; this.specialEvent = true;
this.eventName = specialBlocks[block.height].labelEventCompleted; this.eventName = specialBlocks[block.height].labelEventCompleted;
setTimeout(() => { setTimeout(() => {

View File

@@ -8859,6 +8859,21 @@ export const faqData = [
fragment: "what-is-full-mempool", fragment: "what-is-full-mempool",
title: "What does it mean for the mempool to be \"full\"?", title: "What does it mean for the mempool to be \"full\"?",
}, },
{
type: "endpoint",
category: "advanced",
showConditions: bitcoinNetworks,
fragment: "how-big-is-mempool-used-by-mempool.space",
title: "How big is the mempool used by mempool.space?",
options: { officialOnly: true },
},
{
type: "endpoint",
category: "advanced",
showConditions: bitcoinNetworks,
fragment: "what-is-memory-usage",
title: "What is memory usage?",
},
{ {
type: "endpoint", type: "endpoint",
category: "advanced", category: "advanced",

View File

@@ -1,4 +1,4 @@
<div *ngFor="let item of tabData"> <div *ngFor="let item of tabData">
<p *ngIf="( item.type === 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )">{{ item.title }}</p> <p *ngIf="( item.type === 'category' ) && ( item.showConditions.indexOf(network.val) > -1 )">{{ item.title }}</p>
<a *ngIf="( item.type !== 'category' ) && ( item.showConditions.indexOf(network.val) > -1 ) && ( !item.hasOwnProperty('options') || ( item.hasOwnProperty('options') && item.options.hasOwnProperty('auditOnly') && item.options.auditOnly && auditEnabled ) )" [routerLink]="['./']" fragment="{{ item.fragment }}" (click)="navLinkClick($event)">{{ item.title }}</a> <a *ngIf="( item.type !== 'category' ) && ( item.showConditions.indexOf(network.val) > -1 ) && ( !item.hasOwnProperty('options') || ( item.hasOwnProperty('options') && item.options.hasOwnProperty('officialOnly') && item.options.officialOnly && officialMempoolInstance ) || ( item.hasOwnProperty('options') && item.options.hasOwnProperty('auditOnly') && item.options.auditOnly && auditEnabled ) )" [routerLink]="['./']" fragment="{{ item.fragment }}" (click)="navLinkClick($event)">{{ item.title }}</a>
</div> </div>

View File

@@ -16,6 +16,7 @@ export class ApiDocsNavComponent implements OnInit {
env: Env; env: Env;
tabData: any[]; tabData: any[];
auditEnabled: boolean; auditEnabled: boolean;
officialMempoolInstance: boolean;
constructor( constructor(
private stateService: StateService private stateService: StateService
@@ -23,6 +24,7 @@ export class ApiDocsNavComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.env = this.stateService.env; this.env = this.stateService.env;
this.officialMempoolInstance = this.env.OFFICIAL_MEMPOOL_SPACE;
this.auditEnabled = this.env.AUDIT; this.auditEnabled = this.env.AUDIT;
if (this.whichTab === 'rest') { if (this.whichTab === 'rest') {
this.tabData = restApiDocsData; this.tabData = restApiDocsData;

View File

@@ -16,7 +16,7 @@
</div> </div>
<div class="doc-item-container" *ngFor="let item of faq"> <div class="doc-item-container" *ngFor="let item of faq">
<div *ngIf="!item.hasOwnProperty('options') || ( item.hasOwnProperty('options') && item.options.hasOwnProperty('auditOnly') && item.options.auditOnly && auditEnabled )"> <div *ngIf="!item.hasOwnProperty('options') || ( item.hasOwnProperty('options') && item.options.hasOwnProperty('officialOnly') && item.options.officialOnly && officialMempoolInstance ) || ( item.hasOwnProperty('options') && item.options.hasOwnProperty('auditOnly') && item.options.auditOnly && auditEnabled )">
<h3 *ngIf="item.type === 'category'">{{ item.title }}</h3> <h3 *ngIf="item.type === 'category'">{{ item.title }}</h3>
<div *ngIf="item.type !== 'category'" class="endpoint-container" id="{{ item.fragment }}"> <div *ngIf="item.type !== 'category'" class="endpoint-container" id="{{ item.fragment }}">
<a id="{{ item.fragment + '-tab-header' }}" class="section-header" (click)="anchorLinkClick( $event )" [routerLink]="['./']" fragment="{{ item.fragment }}"><table><tr><td>{{ item.title }}</td><td><span>{{ item.category }}</span></td></tr></table></a> <a id="{{ item.fragment + '-tab-header' }}" class="section-header" (click)="anchorLinkClick( $event )" [routerLink]="['./']" fragment="{{ item.fragment }}"><table><tr><td>{{ item.title }}</td><td><span>{{ item.category }}</span></td></tr></table></a>
@@ -207,6 +207,18 @@
<p>When a Bitcoin transaction is made, it is stored in a Bitcoin node's mempool before it is confirmed into a block. When the rate of incoming transactions exceeds the rate transactions are confirmed, the mempool grows in size.</p><p>By default, Bitcoin Core allocates 300MB of memory for its mempool, so when a node's mempool grows big enough to use all 300MB of allocated memory, we say it's "full".</p><p>Once a node's mempool is using all of its allocated memory, it will start rejecting new transactions below a certain feerate threshold—so when this is the case, be extra sure to set a feerate that (at a minimum) exceeds that threshold. The current threshold feerate (and memory usage) are displayed right on Mempool's front page.</p> <p>When a Bitcoin transaction is made, it is stored in a Bitcoin node's mempool before it is confirmed into a block. When the rate of incoming transactions exceeds the rate transactions are confirmed, the mempool grows in size.</p><p>By default, Bitcoin Core allocates 300MB of memory for its mempool, so when a node's mempool grows big enough to use all 300MB of allocated memory, we say it's "full".</p><p>Once a node's mempool is using all of its allocated memory, it will start rejecting new transactions below a certain feerate threshold—so when this is the case, be extra sure to set a feerate that (at a minimum) exceeds that threshold. The current threshold feerate (and memory usage) are displayed right on Mempool's front page.</p>
</ng-template> </ng-template>
<ng-template type="how-big-is-mempool-used-by-mempool.space">
<p>mempool.space uses multiple Bitcoin nodes to obtain data: some with the default 300MB mempool memory limit (call these Small Nodes) and others with a much larger mempool memory limit (call these Big Nodes).</p>
<p>Many nodes on the Bitcoin network are configured to run with the default 300MB mempool memory setting. When all 300MB of memory are used up, such nodes will reject transactions below a certain threshold feerate. Running Small Nodes allows mempool.space to tell you what this threshold feerate is—this is the "Purging" feerate that shows on the front page when mempools are full, which you can use to be reasonably sure that your transaction will be widely propagated.</p>
<p>Big Node mempools are so big that they don't need to reject (or purge) transactions. Such nodes allow for mempool.space to provide you with information on any pending transaction it has received—no matter how congested the mempool is, and no matter how low-feerate or low-priority the transaction is.</p>
</ng-template>
<ng-template type="what-is-memory-usage">
<p>Memory usage on the front page refers to the real-time amount of system memory used by a Bitcoin node's mempool. This memory usage number is always higher than the total size of all pending transactions in the mempool due to indexes, pointers, and other overhead used by Bitcoin Core for storage and processing.</p>
<p>mempool.space shows the memory usage of a Bitcoin node that has a very high mempool memory limit. As a result, when mempools fill up, you may notice memory usage on mempool.space go beyond 300MB. This is not a mistake—this memory usage figure is high because it's for a Bitcoin node that isn't rejecting (or evicting) transactions. Consider it to be another data point to give you an idea of how congested the mempool is relative to the default memory limit of 300MB.</p>
<p>A Bitcoin node running the default 300MB mempool memory limit, like most Raspberry Pi nodes, will never go past 300MB of memory usage.</p>
</ng-template>
<ng-template type="why-empty-blocks"> <ng-template type="why-empty-blocks">
<p>When a new block is found, mining pools send miners a block template with no transactions so they can start searching for the next block as soon as possible. They send a block template full of transactions right afterward, but a full block template is a bigger data transfer and takes slightly longer to reach miners.</p><p>In this intervening time, which is usually no more than 1-2 seconds, miners sometimes get lucky and find a new block using the empty block template.</p> <p>When a new block is found, mining pools send miners a block template with no transactions so they can start searching for the next block as soon as possible. They send a block template full of transactions right afterward, but a full block template is a bigger data transfer and takes slightly longer to reach miners.</p><p>In this intervening time, which is usually no more than 1-2 seconds, miners sometimes get lucky and find a new block using the empty block template.</p>
</ng-template> </ng-template>

View File

@@ -107,8 +107,8 @@ export interface PoolStat {
'1w': number, '1w': number,
}; };
estimatedHashrate: number; estimatedHashrate: number;
reportedHashrate: number; avgBlockHealth: number;
luck?: number; totalReward: number;
} }
export interface BlockExtension { export interface BlockExtension {
@@ -118,6 +118,7 @@ export interface BlockExtension {
reward?: number; reward?: number;
coinbaseRaw?: string; coinbaseRaw?: string;
matchRate?: number; matchRate?: number;
similarity?: number;
pool?: { pool?: {
id: number; id: number;
name: string; name: string;

View File

@@ -43,6 +43,7 @@ export interface MempoolBlock {
totalFees: number; totalFees: number;
feeRange: number[]; feeRange: number[];
index: number; index: number;
isStack?: boolean;
} }
export interface MempoolBlockWithTransactions extends MempoolBlock { export interface MempoolBlockWithTransactions extends MempoolBlock {

View File

@@ -487,7 +487,7 @@
</trans-unit> </trans-unit>
<trans-unit id="bisq-block.component.browser-title" datatype="html"> <trans-unit id="bisq-block.component.browser-title" datatype="html">
<source>Block <x id="BLOCK_HEIGHT" equiv-text="block.height"/>: <x id="BLOCK_HASH" equiv-text="block.hash"/></source> <source>Block <x id="BLOCK_HEIGHT" equiv-text="block.height"/>: <x id="BLOCK_HASH" equiv-text="block.hash"/></source>
<target>Bloc <x id="BLOCK_HEIGHT" equiv-text="block.height"/> : <x id="BLOCK_HASH" equiv-text="block.hash"/></target> <target>Bloc <x id="BLOCK_HEIGHT" equiv-text="block.height"/>: <x id="BLOCK_HASH" equiv-text="block.hash"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/bisq/bisq-block/bisq-block.component.ts</context> <context context-type="sourcefile">src/app/bisq/bisq-block/bisq-block.component.ts</context>
<context context-type="linenumber">89</context> <context context-type="linenumber">89</context>
@@ -842,7 +842,7 @@
</trans-unit> </trans-unit>
<trans-unit id="74d80a5b284beb81e8aeb3b8efca0f78cd4b7560" datatype="html"> <trans-unit id="74d80a5b284beb81e8aeb3b8efca0f78cd4b7560" datatype="html">
<source>Amount (<x id="INTERPOLATION" equiv-text="{{ i }}"/>)</source> <source>Amount (<x id="INTERPOLATION" equiv-text="{{ i }}"/>)</source>
<target>Montant ( <x id="INTERPOLATION" equiv-text="{{ i }}"/> )</target> <target>Montant (<x id="INTERPOLATION" equiv-text="{{ i }}"/>)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/bisq/bisq-market/bisq-market.component.html</context> <context context-type="sourcefile">src/app/bisq/bisq-market/bisq-market.component.html</context>
<context context-type="linenumber">112,113</context> <context context-type="linenumber">112,113</context>
@@ -1109,7 +1109,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8e623d3cfecb7c560c114390db53c1f430ffd0de" datatype="html"> <trans-unit id="8e623d3cfecb7c560c114390db53c1f430ffd0de" datatype="html">
<source><x id="INTERPOLATION" equiv-text="confirmation&lt;/ng-template&gt; &lt;ng-template #confirmationPlural let-i i18n=&quot;shared.confirmation-count.plural|Transaction plural confir"/> confirmation</source> <source><x id="INTERPOLATION" equiv-text="confirmation&lt;/ng-template&gt; &lt;ng-template #confirmationPlural let-i i18n=&quot;shared.confirmation-count.plural|Transaction plural confir"/> confirmation</source>
<target> <x id="INTERPOLATION" equiv-text="confirmation&lt;/ng-template&gt; &lt;ng-template #confirmationPlural let-i i18n=&quot;shared.confirmation-count.plural|Transaction plural confir"/> confirmation</target> <target><x id="INTERPOLATION" equiv-text="confirmation&lt;/ng-template&gt; &lt;ng-template #confirmationPlural let-i i18n=&quot;shared.confirmation-count.plural|Transaction plural confir"/> confirmation</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/bisq/bisq-transaction/bisq-transaction.component.html</context> <context context-type="sourcefile">src/app/bisq/bisq-transaction/bisq-transaction.component.html</context>
<context context-type="linenumber">20,21</context> <context context-type="linenumber">20,21</context>
@@ -1131,7 +1131,7 @@
</trans-unit> </trans-unit>
<trans-unit id="bc5b0a2631f0b7bc71aaec6aa6f01af21f9a80d4" datatype="html"> <trans-unit id="bc5b0a2631f0b7bc71aaec6aa6f01af21f9a80d4" datatype="html">
<source><x id="INTERPOLATION" equiv-text="confirmations&lt;/ng-template&gt; &lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;clearfix&quot;&gt;&lt;/div&gt; &lt;div class=&quot;box tran"/> confirmations</source> <source><x id="INTERPOLATION" equiv-text="confirmations&lt;/ng-template&gt; &lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;clearfix&quot;&gt;&lt;/div&gt; &lt;div class=&quot;box tran"/> confirmations</source>
<target> <x id="INTERPOLATION" equiv-text="confirmations&lt;/ng-template&gt; &lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;clearfix&quot;&gt;&lt;/div&gt; &lt;div class=&quot;box tran"/> confirmations</target> <target><x id="INTERPOLATION" equiv-text="confirmations&lt;/ng-template&gt; &lt;/button&gt; &lt;/div&gt; &lt;/div&gt; &lt;div class=&quot;clearfix&quot;&gt;&lt;/div&gt; &lt;div class=&quot;box tran"/> confirmations</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/bisq/bisq-transaction/bisq-transaction.component.html</context> <context context-type="sourcefile">src/app/bisq/bisq-transaction/bisq-transaction.component.html</context>
<context context-type="linenumber">21,22</context> <context context-type="linenumber">21,22</context>
@@ -1234,7 +1234,7 @@
</trans-unit> </trans-unit>
<trans-unit id="bisq.transaction.browser-title" datatype="html"> <trans-unit id="bisq.transaction.browser-title" datatype="html">
<source>Transaction: <x id="INTERPOLATION" equiv-text="this.txId"/></source> <source>Transaction: <x id="INTERPOLATION" equiv-text="this.txId"/></source>
<target>Transaction : <x id="INTERPOLATION" equiv-text="this.txId"/></target> <target>Transaction: <x id="INTERPOLATION" equiv-text="this.txId"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/bisq/bisq-transaction/bisq-transaction.component.ts</context> <context context-type="sourcefile">src/app/bisq/bisq-transaction/bisq-transaction.component.ts</context>
<context context-type="linenumber">50</context> <context context-type="linenumber">50</context>
@@ -1611,7 +1611,7 @@
</trans-unit> </trans-unit>
<trans-unit id="address.component.browser-title" datatype="html"> <trans-unit id="address.component.browser-title" datatype="html">
<source>Address: <x id="INTERPOLATION" equiv-text="this.addressString"/></source> <source>Address: <x id="INTERPOLATION" equiv-text="this.addressString"/></source>
<target>Adresse : <x id="INTERPOLATION" equiv-text="this.addressString"/></target> <target>Adresse: <x id="INTERPOLATION" equiv-text="this.addressString"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/address/address-preview.component.ts</context> <context context-type="sourcefile">src/app/components/address/address-preview.component.ts</context>
<context context-type="linenumber">70</context> <context context-type="linenumber">70</context>
@@ -1800,7 +1800,7 @@
</trans-unit> </trans-unit>
<trans-unit id="asset.component.asset-browser-title" datatype="html"> <trans-unit id="asset.component.asset-browser-title" datatype="html">
<source>Asset: <x id="INTERPOLATION" equiv-text="this.assetString"/></source> <source>Asset: <x id="INTERPOLATION" equiv-text="this.assetString"/></source>
<target>Actif : <x id="INTERPOLATION" equiv-text="this.assetString"/></target> <target>Actif: <x id="INTERPOLATION" equiv-text="this.assetString"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/asset/asset.component.ts</context> <context context-type="sourcefile">src/app/components/asset/asset.component.ts</context>
<context context-type="linenumber">75</context> <context context-type="linenumber">75</context>
@@ -3203,7 +3203,7 @@
</trans-unit> </trans-unit>
<trans-unit id="0c65c3ee0ce537e507e0b053b479012e5803d2cf" datatype="html"> <trans-unit id="0c65c3ee0ce537e507e0b053b479012e5803d2cf" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks expected</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks expected</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs attendus</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs attendus</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@@ -3221,7 +3221,7 @@
</trans-unit> </trans-unit>
<trans-unit id="b89cb92adf0a831d4a263ecdba02139abbda02ae" datatype="html"> <trans-unit id="b89cb92adf0a831d4a263ecdba02139abbda02ae" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks mined</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks mined</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs trouvés</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs trouvés</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">18</context> <context context-type="linenumber">18</context>
@@ -3230,7 +3230,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4f7e823fd45c6def13a3f15f678888c7fe254fa5" datatype="html"> <trans-unit id="4f7e823fd45c6def13a3f15f678888c7fe254fa5" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block mined</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block mined</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc trouvé</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc trouvé</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">19</context> <context context-type="linenumber">19</context>
@@ -3239,7 +3239,7 @@
</trans-unit> </trans-unit>
<trans-unit id="229dfb17b342aa8b9a1db27557069445ea1a7051" datatype="html"> <trans-unit id="229dfb17b342aa8b9a1db27557069445ea1a7051" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks remaining</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks remaining</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs restants</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs restants</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">24</context> <context context-type="linenumber">24</context>
@@ -3248,7 +3248,7 @@
</trans-unit> </trans-unit>
<trans-unit id="13ff0d092caf85cd23815f0235e316dc3a6d1bbe" datatype="html"> <trans-unit id="13ff0d092caf85cd23815f0235e316dc3a6d1bbe" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block remaining</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block remaining</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc restant</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc restant</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">25</context> <context context-type="linenumber">25</context>
@@ -3257,7 +3257,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4f78348af343fb64016891d67b53bdab473f9dbf" datatype="html"> <trans-unit id="4f78348af343fb64016891d67b53bdab473f9dbf" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks ahead</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks ahead</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs d'avance</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs d'avance</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">29</context> <context context-type="linenumber">29</context>
@@ -3266,7 +3266,7 @@
</trans-unit> </trans-unit>
<trans-unit id="15c5f3475966bf3be381378b046a65849f0f6bb6" datatype="html"> <trans-unit id="15c5f3475966bf3be381378b046a65849f0f6bb6" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block ahead</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block ahead</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc d'avance</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc d'avance</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">30</context> <context context-type="linenumber">30</context>
@@ -3275,7 +3275,7 @@
</trans-unit> </trans-unit>
<trans-unit id="697b8cb1caaf1729809bc5c065d4dd873810550a" datatype="html"> <trans-unit id="697b8cb1caaf1729809bc5c065d4dd873810550a" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks behind</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks behind</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs de retard</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocs de retard</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">34</context>
@@ -3284,7 +3284,7 @@
</trans-unit> </trans-unit>
<trans-unit id="32137887e3f5a25b3a016eb03357f4e363fccb0b" datatype="html"> <trans-unit id="32137887e3f5a25b3a016eb03357f4e363fccb0b" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block behind</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block behind</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc de retard</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> bloc de retard</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">35</context>
@@ -4578,7 +4578,7 @@
</trans-unit> </trans-unit>
<trans-unit id="time-until" datatype="html"> <trans-unit id="time-until" datatype="html">
<source>In ~<x id="DATE" equiv-text="dateStrings.i18nYear"/></source> <source>In ~<x id="DATE" equiv-text="dateStrings.i18nYear"/></source>
<target>Dans ~ <x id="DATE" equiv-text="dateStrings.i18nYear"/></target> <target>Dans ~<x id="DATE" equiv-text="dateStrings.i18nYear"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/time/time.component.ts</context> <context context-type="sourcefile">src/app/components/time/time.component.ts</context>
<context context-type="linenumber">126</context> <context context-type="linenumber">126</context>
@@ -5200,7 +5200,7 @@
</trans-unit> </trans-unit>
<trans-unit id="47b821c7df420c96de0b22844a88c04d52628540" datatype="html"> <trans-unit id="47b821c7df420c96de0b22844a88c04d52628540" datatype="html">
<source>This transaction uses Taproot and already saved at least <x id="INTERPOLATION" equiv-text="{{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}"/>% on fees, but could save an additional <x id="INTERPOLATION_1" equiv-text="{{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}"/>% by fully using Taproot</source> <source>This transaction uses Taproot and already saved at least <x id="INTERPOLATION" equiv-text="{{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}"/>% on fees, but could save an additional <x id="INTERPOLATION_1" equiv-text="{{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}"/>% by fully using Taproot</source>
<target>Cette transaction utilise Taproot et a déjà économisé au moins <x id="INTERPOLATION" equiv-text="{{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}"/> % sur les frais, mais pourrait économiser <x id="INTERPOLATION_1" equiv-text="{{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}"/> % supplémentaires en utilisant pleinement Taproot</target> <target>Cette transaction utilise Taproot et a déjà économisé au moins <x id="INTERPOLATION" equiv-text="{{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}"/>% sur les frais, mais pourrait économiser <x id="INTERPOLATION_1" equiv-text="{{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}"/>% supplémentaires en utilisant pleinement Taproot</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/tx-features/tx-features.component.html</context> <context context-type="sourcefile">src/app/components/tx-features/tx-features.component.html</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">14</context>
@@ -5578,7 +5578,7 @@
</trans-unit> </trans-unit>
<trans-unit id="205c1b86ac1cc419c4d0cca51fdde418c4ffdc20" datatype="html"> <trans-unit id="205c1b86ac1cc419c4d0cca51fdde418c4ffdc20" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> channels</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> channels</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> canaux</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> canaux</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/channel-box/channel-box.component.html</context> <context context-type="sourcefile">src/app/lightning/channel/channel-box/channel-box.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">79</context>
@@ -5864,7 +5864,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6008566722612122663" datatype="html"> <trans-unit id="6008566722612122663" datatype="html">
<source>Channel: <x id="PH" equiv-text="value.short_id"/></source> <source>Channel: <x id="PH" equiv-text="value.short_id"/></source>
<target>Canal : <x id="PH" equiv-text="value.short_id"/></target> <target>Canal: <x id="PH" equiv-text="value.short_id"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/channel.component.ts</context> <context context-type="sourcefile">src/app/lightning/channel/channel.component.ts</context>
<context context-type="linenumber">37</context> <context context-type="linenumber">37</context>

View File

@@ -3203,7 +3203,7 @@
</trans-unit> </trans-unit>
<trans-unit id="0c65c3ee0ce537e507e0b053b479012e5803d2cf" datatype="html"> <trans-unit id="0c65c3ee0ce537e507e0b053b479012e5803d2cf" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks expected</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks expected</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi previsti</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi previsti</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@@ -3221,7 +3221,7 @@
</trans-unit> </trans-unit>
<trans-unit id="b89cb92adf0a831d4a263ecdba02139abbda02ae" datatype="html"> <trans-unit id="b89cb92adf0a831d4a263ecdba02139abbda02ae" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks mined</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks mined</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi minati</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi minati</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">18</context> <context context-type="linenumber">18</context>
@@ -3230,7 +3230,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4f7e823fd45c6def13a3f15f678888c7fe254fa5" datatype="html"> <trans-unit id="4f7e823fd45c6def13a3f15f678888c7fe254fa5" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block mined</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block mined</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco estratto</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco estratto</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">19</context> <context context-type="linenumber">19</context>
@@ -3239,7 +3239,7 @@
</trans-unit> </trans-unit>
<trans-unit id="229dfb17b342aa8b9a1db27557069445ea1a7051" datatype="html"> <trans-unit id="229dfb17b342aa8b9a1db27557069445ea1a7051" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks remaining</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks remaining</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi rimanenti</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi rimanenti</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">24</context> <context context-type="linenumber">24</context>
@@ -3248,7 +3248,7 @@
</trans-unit> </trans-unit>
<trans-unit id="13ff0d092caf85cd23815f0235e316dc3a6d1bbe" datatype="html"> <trans-unit id="13ff0d092caf85cd23815f0235e316dc3a6d1bbe" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block remaining</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block remaining</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco rimanente</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco rimanente</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">25</context> <context context-type="linenumber">25</context>
@@ -3257,7 +3257,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4f78348af343fb64016891d67b53bdab473f9dbf" datatype="html"> <trans-unit id="4f78348af343fb64016891d67b53bdab473f9dbf" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks ahead</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks ahead</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi avanti</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi avanti</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">29</context> <context context-type="linenumber">29</context>
@@ -3266,7 +3266,7 @@
</trans-unit> </trans-unit>
<trans-unit id="15c5f3475966bf3be381378b046a65849f0f6bb6" datatype="html"> <trans-unit id="15c5f3475966bf3be381378b046a65849f0f6bb6" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block ahead</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block ahead</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco avanti</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco avanti</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">30</context> <context context-type="linenumber">30</context>
@@ -3275,7 +3275,7 @@
</trans-unit> </trans-unit>
<trans-unit id="697b8cb1caaf1729809bc5c065d4dd873810550a" datatype="html"> <trans-unit id="697b8cb1caaf1729809bc5c065d4dd873810550a" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks behind</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks behind</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi dietro</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocchi dietro</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">34</context>
@@ -3284,7 +3284,7 @@
</trans-unit> </trans-unit>
<trans-unit id="32137887e3f5a25b3a016eb03357f4e363fccb0b" datatype="html"> <trans-unit id="32137887e3f5a25b3a016eb03357f4e363fccb0b" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block behind</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block behind</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco dietro</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocco dietro</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">35</context>
@@ -3995,7 +3995,7 @@
</trans-unit> </trans-unit>
<trans-unit id="312539377512157124" datatype="html"> <trans-unit id="312539377512157124" datatype="html">
<source><x id="INTERPOLATION" equiv-text="i"/> blocks</source> <source><x id="INTERPOLATION" equiv-text="i"/> blocks</source>
<target> <x id="INTERPOLATION" equiv-text="i"/> blocchi</target> <target><x id="INTERPOLATION" equiv-text="i"/> blocchi</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context> <context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context>
<context context-type="linenumber">165,163</context> <context context-type="linenumber">165,163</context>
@@ -4452,7 +4452,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2abc4d0d3ae0b49fa9e94a2efb8c2e1a47e680f4" datatype="html"> <trans-unit id="2abc4d0d3ae0b49fa9e94a2efb8c2e1a47e680f4" datatype="html">
<source>Go to &quot;<x id="INTERPOLATION" equiv-text="{{ x }}"/>&quot;</source> <source>Go to &quot;<x id="INTERPOLATION" equiv-text="{{ x }}"/>&quot;</source>
<target>Vai a &amp;quot;<x id="INTERPOLATION" equiv-text="{{ x }}"/>&amp;quot;</target> <target>Vai a &quot;<x id="INTERPOLATION" equiv-text="{{ x }}"/>&quot;</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">52</context> <context context-type="linenumber">52</context>
@@ -4518,7 +4518,7 @@
</trans-unit> </trans-unit>
<trans-unit id="time-since" datatype="html"> <trans-unit id="time-since" datatype="html">
<source><x id="DATE" equiv-text="dateStrings.i18nYear"/> ago</source> <source><x id="DATE" equiv-text="dateStrings.i18nYear"/> ago</source>
<target> <x id="DATE" equiv-text="dateStrings.i18nYear"/> fa</target> <target><x id="DATE" equiv-text="dateStrings.i18nYear"/> fa</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/time/time.component.ts</context> <context context-type="sourcefile">src/app/components/time/time.component.ts</context>
<context context-type="linenumber">103</context> <context context-type="linenumber">103</context>
@@ -5067,7 +5067,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ea7c261363dc5f6134b7bacba2a1ef97f4ff7859" datatype="html"> <trans-unit id="ea7c261363dc5f6134b7bacba2a1ef97f4ff7859" datatype="html">
<source><x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/> remaining</source> <source><x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/> remaining</source>
<target> <x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/> rimanente</target> <target><x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/> rimanente</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context> <context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">332,333</context> <context context-type="linenumber">332,333</context>
@@ -5578,7 +5578,7 @@
</trans-unit> </trans-unit>
<trans-unit id="205c1b86ac1cc419c4d0cca51fdde418c4ffdc20" datatype="html"> <trans-unit id="205c1b86ac1cc419c4d0cca51fdde418c4ffdc20" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> channels</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> channels</source>
<target> <x id="INTERPOLATION" equiv-text="{{ i }}"/> canali</target> <target><x id="INTERPOLATION" equiv-text="{{ i }}"/> canali</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/channel-box/channel-box.component.html</context> <context context-type="sourcefile">src/app/lightning/channel/channel-box/channel-box.component.html</context>
<context context-type="linenumber">79</context> <context context-type="linenumber">79</context>
@@ -6775,7 +6775,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5222540403093176126" datatype="html"> <trans-unit id="5222540403093176126" datatype="html">
<source><x id="PH" equiv-text="nodeCount"/> nodes</source> <source><x id="PH" equiv-text="nodeCount"/> nodes</source>
<target> <x id="PH" equiv-text="nodeCount"/> nodi</target> <target><x id="PH" equiv-text="nodeCount"/> nodi</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts</context>
<context context-type="linenumber">104,103</context> <context context-type="linenumber">104,103</context>
@@ -6795,7 +6795,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7032954508645880700" datatype="html"> <trans-unit id="7032954508645880700" datatype="html">
<source><x id="PH" equiv-text="this.amountShortenerPipe.transform(country.capacity / 100000000, 2)"/> BTC capacity</source> <source><x id="PH" equiv-text="this.amountShortenerPipe.transform(country.capacity / 100000000, 2)"/> BTC capacity</source>
<target> <x id="PH" equiv-text="this.amountShortenerPipe.transform(country.capacity / 100000000, 2)"/> Capacità BTC</target> <target><x id="PH" equiv-text="this.amountShortenerPipe.transform(country.capacity / 100000000, 2)"/> Capacità BTC</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts</context>
<context context-type="linenumber">105,103</context> <context context-type="linenumber">105,103</context>
@@ -6913,7 +6913,7 @@
</trans-unit> </trans-unit>
<trans-unit id="3627306100664959238" datatype="html"> <trans-unit id="3627306100664959238" datatype="html">
<source><x id="PH" equiv-text="this.amountShortenerPipe.transform(isp[2] / 100000000, 2)"/> BTC</source> <source><x id="PH" equiv-text="this.amountShortenerPipe.transform(isp[2] / 100000000, 2)"/> BTC</source>
<target> <x id="PH" equiv-text="this.amountShortenerPipe.transform(isp[2] / 100000000, 2)"/> BTC</target> <target><x id="PH" equiv-text="this.amountShortenerPipe.transform(isp[2] / 100000000, 2)"/> BTC</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.ts</context>
<context context-type="linenumber">159,157</context> <context context-type="linenumber">159,157</context>
@@ -7038,7 +7038,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.year" datatype="html"> <trans-unit id="date-base.year" datatype="html">
<source><x id="DATE" equiv-text="counter"/> year</source> <source><x id="DATE" equiv-text="counter"/> year</source>
<target> <x id="DATE" equiv-text="counter"/> anno</target> <target><x id="DATE" equiv-text="counter"/> anno</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">3</context> <context context-type="linenumber">3</context>
@@ -7046,7 +7046,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.years" datatype="html"> <trans-unit id="date-base.years" datatype="html">
<source><x id="DATE" equiv-text="counter"/> years</source> <source><x id="DATE" equiv-text="counter"/> years</source>
<target> <x id="DATE" equiv-text="counter"/> anni</target> <target><x id="DATE" equiv-text="counter"/> anni</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">4</context> <context context-type="linenumber">4</context>
@@ -7054,7 +7054,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.month" datatype="html"> <trans-unit id="date-base.month" datatype="html">
<source><x id="DATE" equiv-text="counter"/> month</source> <source><x id="DATE" equiv-text="counter"/> month</source>
<target> <x id="DATE" equiv-text="counter"/> mese</target> <target><x id="DATE" equiv-text="counter"/> mese</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">5</context> <context context-type="linenumber">5</context>
@@ -7062,7 +7062,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.months" datatype="html"> <trans-unit id="date-base.months" datatype="html">
<source><x id="DATE" equiv-text="counter"/> months</source> <source><x id="DATE" equiv-text="counter"/> months</source>
<target> <x id="DATE" equiv-text="counter"/> mesi</target> <target><x id="DATE" equiv-text="counter"/> mesi</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">6</context> <context context-type="linenumber">6</context>
@@ -7070,7 +7070,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.week" datatype="html"> <trans-unit id="date-base.week" datatype="html">
<source><x id="DATE" equiv-text="counter"/> week</source> <source><x id="DATE" equiv-text="counter"/> week</source>
<target> <x id="DATE" equiv-text="counter"/> settimana</target> <target><x id="DATE" equiv-text="counter"/> settimana</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">7</context> <context context-type="linenumber">7</context>
@@ -7078,7 +7078,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.weeks" datatype="html"> <trans-unit id="date-base.weeks" datatype="html">
<source><x id="DATE" equiv-text="counter"/> weeks</source> <source><x id="DATE" equiv-text="counter"/> weeks</source>
<target> <x id="DATE" equiv-text="counter"/> settimane</target> <target><x id="DATE" equiv-text="counter"/> settimane</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">8</context> <context context-type="linenumber">8</context>
@@ -7086,7 +7086,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.day" datatype="html"> <trans-unit id="date-base.day" datatype="html">
<source><x id="DATE" equiv-text="counter"/> day</source> <source><x id="DATE" equiv-text="counter"/> day</source>
<target> <x id="DATE" equiv-text="counter"/> giorno</target> <target><x id="DATE" equiv-text="counter"/> giorno</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">9</context> <context context-type="linenumber">9</context>
@@ -7094,7 +7094,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.days" datatype="html"> <trans-unit id="date-base.days" datatype="html">
<source><x id="DATE" equiv-text="counter"/> days</source> <source><x id="DATE" equiv-text="counter"/> days</source>
<target> <x id="DATE" equiv-text="counter"/> giorni</target> <target><x id="DATE" equiv-text="counter"/> giorni</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">10</context> <context context-type="linenumber">10</context>
@@ -7102,7 +7102,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.hour" datatype="html"> <trans-unit id="date-base.hour" datatype="html">
<source><x id="DATE" equiv-text="counter"/> hour</source> <source><x id="DATE" equiv-text="counter"/> hour</source>
<target> <x id="DATE" equiv-text="counter"/> ora</target> <target><x id="DATE" equiv-text="counter"/> ora</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">11</context> <context context-type="linenumber">11</context>
@@ -7110,7 +7110,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.hours" datatype="html"> <trans-unit id="date-base.hours" datatype="html">
<source><x id="DATE" equiv-text="counter"/> hours</source> <source><x id="DATE" equiv-text="counter"/> hours</source>
<target> <x id="DATE" equiv-text="counter"/> ore</target> <target><x id="DATE" equiv-text="counter"/> ore</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
@@ -7118,7 +7118,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.minute" datatype="html"> <trans-unit id="date-base.minute" datatype="html">
<source><x id="DATE" equiv-text="counter"/> minute</source> <source><x id="DATE" equiv-text="counter"/> minute</source>
<target> <x id="DATE" equiv-text="counter"/> minuto</target> <target><x id="DATE" equiv-text="counter"/> minuto</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@@ -7126,7 +7126,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.minutes" datatype="html"> <trans-unit id="date-base.minutes" datatype="html">
<source><x id="DATE" equiv-text="counter"/> minutes</source> <source><x id="DATE" equiv-text="counter"/> minutes</source>
<target> <x id="DATE" equiv-text="counter"/> minuti</target> <target><x id="DATE" equiv-text="counter"/> minuti</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">14</context>
@@ -7134,7 +7134,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.second" datatype="html"> <trans-unit id="date-base.second" datatype="html">
<source><x id="DATE" equiv-text="counter"/> second</source> <source><x id="DATE" equiv-text="counter"/> second</source>
<target> <x id="DATE" equiv-text="counter"/> secondo</target> <target><x id="DATE" equiv-text="counter"/> secondo</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">15</context>
@@ -7142,7 +7142,7 @@
</trans-unit> </trans-unit>
<trans-unit id="date-base.seconds" datatype="html"> <trans-unit id="date-base.seconds" datatype="html">
<source><x id="DATE" equiv-text="counter"/> seconds</source> <source><x id="DATE" equiv-text="counter"/> seconds</source>
<target> <x id="DATE" equiv-text="counter"/> secondi</target> <target><x id="DATE" equiv-text="counter"/> secondi</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/shared/i18n/dates.ts</context> <context context-type="sourcefile">src/app/shared/i18n/dates.ts</context>
<context context-type="linenumber">16</context> <context context-type="linenumber">16</context>

File diff suppressed because it is too large Load Diff

View File

@@ -148,7 +148,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ngb.progressbar.value" datatype="html"> <trans-unit id="ngb.progressbar.value" datatype="html">
<source><x id="INTERPOLATION" equiv-text="* The maximal"/></source> <source><x id="INTERPOLATION" equiv-text="* The maximal"/></source>
<target><x id="INTERPOLATION" equiv-text="Максимумот"/></target> <target><x id="INTERPOLATION" equiv-text="* The maximal"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">node_modules/src/progressbar/progressbar.ts</context> <context context-type="sourcefile">node_modules/src/progressbar/progressbar.ts</context>
<context context-type="linenumber">30,33</context> <context context-type="linenumber">30,33</context>
@@ -3995,6 +3995,7 @@
</trans-unit> </trans-unit>
<trans-unit id="312539377512157124" datatype="html"> <trans-unit id="312539377512157124" datatype="html">
<source><x id="INTERPOLATION" equiv-text="i"/> blocks</source> <source><x id="INTERPOLATION" equiv-text="i"/> blocks</source>
<target><x id="INTERPOLATION" equiv-text="i"/> блокови</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context> <context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context>
<context context-type="linenumber">165,163</context> <context context-type="linenumber">165,163</context>

View File

@@ -2365,6 +2365,7 @@
</trans-unit> </trans-unit>
<trans-unit id="f0136f1a1d77aa656e0ebd0f3c023118dd2a2776" datatype="html"> <trans-unit id="f0136f1a1d77aa656e0ebd0f3c023118dd2a2776" datatype="html">
<source>Marginal fee rate</source> <source>Marginal fee rate</source>
<target>边际费率</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-overview-tooltip/block-overview-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/block-overview-tooltip/block-overview-tooltip.component.html</context>
<context context-type="linenumber">40</context> <context context-type="linenumber">40</context>
@@ -2377,6 +2378,7 @@
</trans-unit> </trans-unit>
<trans-unit id="d702ad6f00c620c9658ac1ad8184d5fe5bc099fb" datatype="html"> <trans-unit id="d702ad6f00c620c9658ac1ad8184d5fe5bc099fb" datatype="html">
<source>Recently broadcasted</source> <source>Recently broadcasted</source>
<target>最近播出</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-overview-tooltip/block-overview-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/block-overview-tooltip/block-overview-tooltip.component.html</context>
<context context-type="linenumber">41</context> <context context-type="linenumber">41</context>
@@ -2537,6 +2539,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4786852746659896870" datatype="html"> <trans-unit id="4786852746659896870" datatype="html">
<source>Size per weight</source> <source>Size per weight</source>
<target>尺寸/权重</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts</context> <context context-type="sourcefile">src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts</context>
<context context-type="linenumber">200,199</context> <context context-type="linenumber">200,199</context>
@@ -2747,6 +2750,7 @@
</trans-unit> </trans-unit>
<trans-unit id="a1c8a44428c774facdd0b1e3ae42468c25666367" datatype="html"> <trans-unit id="a1c8a44428c774facdd0b1e3ae42468c25666367" datatype="html">
<source>Subsidy + fees</source> <source>Subsidy + fees</source>
<target>补贴+费用</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">153,156</context> <context context-type="linenumber">153,156</context>
@@ -2760,6 +2764,7 @@
</trans-unit> </trans-unit>
<trans-unit id="23fa95fce7b4badf5ad584d4a1712d558266266f" datatype="html"> <trans-unit id="23fa95fce7b4badf5ad584d4a1712d558266266f" datatype="html">
<source>Expected</source> <source>Expected</source>
<target>预计区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">216</context> <context context-type="linenumber">216</context>
@@ -2781,6 +2786,7 @@
</trans-unit> </trans-unit>
<trans-unit id="1da6d9283e3222148d76c10c8e37abeeb66c93cb" datatype="html"> <trans-unit id="1da6d9283e3222148d76c10c8e37abeeb66c93cb" datatype="html">
<source>Actual</source> <source>Actual</source>
<target>实际区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">218,222</context> <context context-type="linenumber">218,222</context>
@@ -2789,6 +2795,7 @@
</trans-unit> </trans-unit>
<trans-unit id="97577daae15cc7f30ab4d0f4f4dfb8045477aefd" datatype="html"> <trans-unit id="97577daae15cc7f30ab4d0f4f4dfb8045477aefd" datatype="html">
<source>Expected Block</source> <source>Expected Block</source>
<target>预计区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">222</context> <context context-type="linenumber">222</context>
@@ -2797,6 +2804,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6efa73f0d6f0844a1e0c341c9b88323f51852d91" datatype="html"> <trans-unit id="6efa73f0d6f0844a1e0c341c9b88323f51852d91" datatype="html">
<source>Actual Block</source> <source>Actual Block</source>
<target>实际区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">231</context> <context context-type="linenumber">231</context>
@@ -2870,6 +2878,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ccf00caac258749fa1c5fd488fb15368fa6fce37" datatype="html"> <trans-unit id="ccf00caac258749fa1c5fd488fb15368fa6fce37" datatype="html">
<source>Audit</source> <source>Audit</source>
<target>审计</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">297,301</context> <context context-type="linenumber">297,301</context>
@@ -2930,6 +2939,7 @@
</trans-unit> </trans-unit>
<trans-unit id="9f63968580fcea609d6b9e7a5b6ba7180b54e18f" datatype="html"> <trans-unit id="9f63968580fcea609d6b9e7a5b6ba7180b54e18f" datatype="html">
<source>Why is this block empty?</source> <source>Why is this block empty?</source>
<target>为什么这个区块是空的?</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context> <context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">384,390</context> <context context-type="linenumber">384,390</context>
@@ -3193,6 +3203,7 @@
</trans-unit> </trans-unit>
<trans-unit id="0c65c3ee0ce537e507e0b053b479012e5803d2cf" datatype="html"> <trans-unit id="0c65c3ee0ce537e507e0b053b479012e5803d2cf" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks expected</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks expected</source>
<target>预计<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@@ -3201,6 +3212,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ec9f27d00a7778cd1cfe1806105d2ca3314fa506" datatype="html"> <trans-unit id="ec9f27d00a7778cd1cfe1806105d2ca3314fa506" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block expected</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block expected</source>
<target> 预计<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">14</context> <context context-type="linenumber">14</context>
@@ -3209,6 +3221,7 @@
</trans-unit> </trans-unit>
<trans-unit id="b89cb92adf0a831d4a263ecdba02139abbda02ae" datatype="html"> <trans-unit id="b89cb92adf0a831d4a263ecdba02139abbda02ae" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks mined</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks mined</source>
<target>已挖<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">18</context> <context context-type="linenumber">18</context>
@@ -3217,6 +3230,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4f7e823fd45c6def13a3f15f678888c7fe254fa5" datatype="html"> <trans-unit id="4f7e823fd45c6def13a3f15f678888c7fe254fa5" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block mined</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block mined</source>
<target>已挖<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">19</context> <context context-type="linenumber">19</context>
@@ -3225,6 +3239,7 @@
</trans-unit> </trans-unit>
<trans-unit id="229dfb17b342aa8b9a1db27557069445ea1a7051" datatype="html"> <trans-unit id="229dfb17b342aa8b9a1db27557069445ea1a7051" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks remaining</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks remaining</source>
<target> 剩余<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">24</context> <context context-type="linenumber">24</context>
@@ -3233,6 +3248,7 @@
</trans-unit> </trans-unit>
<trans-unit id="13ff0d092caf85cd23815f0235e316dc3a6d1bbe" datatype="html"> <trans-unit id="13ff0d092caf85cd23815f0235e316dc3a6d1bbe" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block remaining</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block remaining</source>
<target>剩余<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">25</context> <context context-type="linenumber">25</context>
@@ -3241,6 +3257,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4f78348af343fb64016891d67b53bdab473f9dbf" datatype="html"> <trans-unit id="4f78348af343fb64016891d67b53bdab473f9dbf" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks ahead</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks ahead</source>
<target>领先<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">29</context> <context context-type="linenumber">29</context>
@@ -3249,6 +3266,7 @@
</trans-unit> </trans-unit>
<trans-unit id="15c5f3475966bf3be381378b046a65849f0f6bb6" datatype="html"> <trans-unit id="15c5f3475966bf3be381378b046a65849f0f6bb6" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block ahead</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block ahead</source>
<target>领先<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">30</context> <context context-type="linenumber">30</context>
@@ -3257,6 +3275,7 @@
</trans-unit> </trans-unit>
<trans-unit id="697b8cb1caaf1729809bc5c065d4dd873810550a" datatype="html"> <trans-unit id="697b8cb1caaf1729809bc5c065d4dd873810550a" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks behind</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> blocks behind</source>
<target>落后<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">34</context> <context context-type="linenumber">34</context>
@@ -3265,6 +3284,7 @@
</trans-unit> </trans-unit>
<trans-unit id="32137887e3f5a25b3a016eb03357f4e363fccb0b" datatype="html"> <trans-unit id="32137887e3f5a25b3a016eb03357f4e363fccb0b" datatype="html">
<source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block behind</source> <source><x id="INTERPOLATION" equiv-text="{{ i }}"/> block behind</source>
<target>落后<x id="INTERPOLATION" equiv-text="{{ i }}"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty-tooltip.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">35</context>
@@ -3273,6 +3293,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5e78899c9b98f29856ce3c7c265e1344bc7a5a18" datatype="html"> <trans-unit id="5e78899c9b98f29856ce3c7c265e1344bc7a5a18" datatype="html">
<source>Average block time</source> <source>Average block time</source>
<target>平均出块时间</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/difficulty/difficulty.component.html</context> <context context-type="sourcefile">src/app/components/difficulty/difficulty.component.html</context>
<context context-type="linenumber">42,45</context> <context context-type="linenumber">42,45</context>
@@ -3917,6 +3938,7 @@
</trans-unit> </trans-unit>
<trans-unit id="c16d236667af327bd474b149cb909d1cd06fa50c" datatype="html"> <trans-unit id="c16d236667af327bd474b149cb909d1cd06fa50c" datatype="html">
<source>Avg Health</source> <source>Avg Health</source>
<target>平均健康</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.html</context> <context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.html</context>
<context context-type="linenumber">96,97</context> <context context-type="linenumber">96,97</context>
@@ -3973,6 +3995,7 @@
</trans-unit> </trans-unit>
<trans-unit id="312539377512157124" datatype="html"> <trans-unit id="312539377512157124" datatype="html">
<source><x id="INTERPOLATION" equiv-text="i"/> blocks</source> <source><x id="INTERPOLATION" equiv-text="i"/> blocks</source>
<target><x id="INTERPOLATION" equiv-text="i"/>个区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context> <context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context>
<context context-type="linenumber">165,163</context> <context context-type="linenumber">165,163</context>
@@ -3992,6 +4015,7 @@
</trans-unit> </trans-unit>
<trans-unit id="3666195172774554282" datatype="html"> <trans-unit id="3666195172774554282" datatype="html">
<source>Other (<x id="PH" equiv-text="percentage"/>)</source> <source>Other (<x id="PH" equiv-text="percentage"/>)</source>
<target>其他 (<x id="PH" equiv-text="percentage"/>)</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context> <context context-type="sourcefile">src/app/components/pool-ranking/pool-ranking.component.ts</context>
<context context-type="linenumber">201</context> <context context-type="linenumber">201</context>
@@ -4270,6 +4294,7 @@
</trans-unit> </trans-unit>
<trans-unit id="1d9f405ab98a5f79d98b439de29fc8baca46b97c" datatype="html"> <trans-unit id="1d9f405ab98a5f79d98b439de29fc8baca46b97c" datatype="html">
<source>Avg Block Fees</source> <source>Avg Block Fees</source>
<target>平均区块费用</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/reward-stats/reward-stats.component.html</context> <context context-type="sourcefile">src/app/components/reward-stats/reward-stats.component.html</context>
<context context-type="linenumber">17</context> <context context-type="linenumber">17</context>
@@ -4282,6 +4307,7 @@
</trans-unit> </trans-unit>
<trans-unit id="a0d4ab5b063e7be1c9ea980f5fd6ce1b5384ad0b" datatype="html"> <trans-unit id="a0d4ab5b063e7be1c9ea980f5fd6ce1b5384ad0b" datatype="html">
<source>Average fees per block in the past 144 blocks</source> <source>Average fees per block in the past 144 blocks</source>
<target>过去144个区块中每个区块的平均费用</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/reward-stats/reward-stats.component.html</context> <context context-type="sourcefile">src/app/components/reward-stats/reward-stats.component.html</context>
<context context-type="linenumber">18,20</context> <context context-type="linenumber">18,20</context>
@@ -4363,6 +4389,7 @@
</trans-unit> </trans-unit>
<trans-unit id="0673b255ba8db0bc5e2cccd5962d31dc88c24578" datatype="html"> <trans-unit id="0673b255ba8db0bc5e2cccd5962d31dc88c24578" datatype="html">
<source>Bitcoin Block Height</source> <source>Bitcoin Block Height</source>
<target>比特币区块高度</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">3</context> <context context-type="linenumber">3</context>
@@ -4371,6 +4398,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8b786a14d8c948e31bfb84369f123847a21dbf50" datatype="html"> <trans-unit id="8b786a14d8c948e31bfb84369f123847a21dbf50" datatype="html">
<source>Bitcoin Transaction</source> <source>Bitcoin Transaction</source>
<target>比特币交易</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">9</context> <context context-type="linenumber">9</context>
@@ -4379,6 +4407,7 @@
</trans-unit> </trans-unit>
<trans-unit id="aacf72635ebf6cfe00590e3a426ea6002c43a729" datatype="html"> <trans-unit id="aacf72635ebf6cfe00590e3a426ea6002c43a729" datatype="html">
<source>Bitcoin Address</source> <source>Bitcoin Address</source>
<target>比特币地址</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">15</context> <context context-type="linenumber">15</context>
@@ -4387,6 +4416,7 @@
</trans-unit> </trans-unit>
<trans-unit id="97089c008af92d87389ff1ec5fb2cc96a6ecef0e" datatype="html"> <trans-unit id="97089c008af92d87389ff1ec5fb2cc96a6ecef0e" datatype="html">
<source>Bitcoin Block</source> <source>Bitcoin Block</source>
<target>比特币区块</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">21</context> <context context-type="linenumber">21</context>
@@ -4395,6 +4425,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e89c09d708a1da5f6a59ba6c38ba3db78031fe0e" datatype="html"> <trans-unit id="e89c09d708a1da5f6a59ba6c38ba3db78031fe0e" datatype="html">
<source>Bitcoin Addresses</source> <source>Bitcoin Addresses</source>
<target>比特币地址</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">27</context> <context context-type="linenumber">27</context>
@@ -4403,6 +4434,7 @@
</trans-unit> </trans-unit>
<trans-unit id="67f25165b857428d046fe5eb67fc44c5c3d94e87" datatype="html"> <trans-unit id="67f25165b857428d046fe5eb67fc44c5c3d94e87" datatype="html">
<source>Lightning Nodes</source> <source>Lightning Nodes</source>
<target>闪电网络节点</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">35</context> <context context-type="linenumber">35</context>
@@ -4411,6 +4443,7 @@
</trans-unit> </trans-unit>
<trans-unit id="db5ca37068eaee3f8b909d3b8b476164527cd8c3" datatype="html"> <trans-unit id="db5ca37068eaee3f8b909d3b8b476164527cd8c3" datatype="html">
<source>Lightning Channels</source> <source>Lightning Channels</source>
<target>闪电网络通道</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context> <context context-type="sourcefile">src/app/components/search-form/search-results/search-results.component.html</context>
<context context-type="linenumber">43</context> <context context-type="linenumber">43</context>
@@ -4675,6 +4708,7 @@
</trans-unit> </trans-unit>
<trans-unit id="72cfda88d5ab4851cba76abb402cae8f03ab6c6b" datatype="html"> <trans-unit id="72cfda88d5ab4851cba76abb402cae8f03ab6c6b" datatype="html">
<source>This transaction replaced:</source> <source>This transaction replaced:</source>
<target>此交易取代:</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/transaction/transaction.component.html</context> <context context-type="sourcefile">src/app/components/transaction/transaction.component.html</context>
<context context-type="linenumber">10,12</context> <context context-type="linenumber">10,12</context>
@@ -4684,6 +4718,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ed1b6bfe4b7beca445156e6bb92a76d3cdebe945" datatype="html"> <trans-unit id="ed1b6bfe4b7beca445156e6bb92a76d3cdebe945" datatype="html">
<source>Replaced</source> <source>Replaced</source>
<target>已更换</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/transaction/transaction.component.html</context> <context context-type="sourcefile">src/app/components/transaction/transaction.component.html</context>
<context context-type="linenumber">36,39</context> <context context-type="linenumber">36,39</context>
@@ -5023,6 +5058,7 @@
</trans-unit> </trans-unit>
<trans-unit id="d70397ee91f6c9ec91f1c1dff88126f8f9b7c2c4" datatype="html"> <trans-unit id="d70397ee91f6c9ec91f1c1dff88126f8f9b7c2c4" datatype="html">
<source>Show more inputs to reveal fee data</source> <source>Show more inputs to reveal fee data</source>
<target>显示更多输入以显示费用数据</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context> <context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">290,293</context> <context context-type="linenumber">290,293</context>
@@ -5031,6 +5067,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ea7c261363dc5f6134b7bacba2a1ef97f4ff7859" datatype="html"> <trans-unit id="ea7c261363dc5f6134b7bacba2a1ef97f4ff7859" datatype="html">
<source><x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/> remaining</source> <source><x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/> remaining</source>
<target>剩余<x id="INTERPOLATION" equiv-text="remaining&lt;/ng-template&gt;"/></target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context> <context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">332,333</context> <context context-type="linenumber">332,333</context>
@@ -5181,6 +5218,7 @@
</trans-unit> </trans-unit>
<trans-unit id="b0fb884cf71b19e3a4d146146d260ccedd9d50a5" datatype="html"> <trans-unit id="b0fb884cf71b19e3a4d146146d260ccedd9d50a5" datatype="html">
<source>This transaction does not use Taproot</source> <source>This transaction does not use Taproot</source>
<target>此交易不使用Taproot</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/components/tx-features/tx-features.component.html</context> <context context-type="sourcefile">src/app/components/tx-features/tx-features.component.html</context>
<context context-type="linenumber">18</context> <context context-type="linenumber">18</context>
@@ -5324,6 +5362,7 @@
</trans-unit> </trans-unit>
<trans-unit id="8f2791f5d9656271dd6c385f5ad572716e90f4a2" datatype="html"> <trans-unit id="8f2791f5d9656271dd6c385f5ad572716e90f4a2" datatype="html">
<source><x id="START_BOLD_TEXT" ctype="x-b" equiv-text="mempool.space merely provides data about the Bitcoin network.&lt;/b&gt; It cannot help you with"/>mempool.space merely provides data about the Bitcoin network.<x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="&lt;/b&gt;"/> It cannot help you with retrieving funds, confirming your transaction quicker, etc.</source> <source><x id="START_BOLD_TEXT" ctype="x-b" equiv-text="mempool.space merely provides data about the Bitcoin network.&lt;/b&gt; It cannot help you with"/>mempool.space merely provides data about the Bitcoin network.<x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="&lt;/b&gt;"/> It cannot help you with retrieving funds, confirming your transaction quicker, etc.</source>
<target><x id="START_BOLD_TEXT" ctype="x-b" equiv-text="mempool.space merely provides data about the Bitcoin network.&lt;/b&gt; It cannot help you with"/> mempool.space 仅提供有关比特币网络的数据。 <x id="CLOSE_BOLD_TEXT" ctype="x-b" equiv-text="&lt;/b&gt;"/> 它无法帮助您取回资金、更快地确认您的交易等。</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/docs/api-docs/api-docs.component.html</context> <context context-type="sourcefile">src/app/docs/api-docs/api-docs.component.html</context>
<context context-type="linenumber">13</context> <context context-type="linenumber">13</context>
@@ -5556,6 +5595,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4e64e04c01e8f5fc09c41cb8942dcc3af0398b28" datatype="html"> <trans-unit id="4e64e04c01e8f5fc09c41cb8942dcc3af0398b28" datatype="html">
<source>Starting balance</source> <source>Starting balance</source>
<target>期初余额</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/channel-close-box/channel-close-box.component.html</context> <context context-type="sourcefile">src/app/lightning/channel/channel-close-box/channel-close-box.component.html</context>
<context context-type="linenumber">6</context> <context context-type="linenumber">6</context>
@@ -5565,6 +5605,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5c4bfd47a4f4d7cb99912f028494fe2530d36d57" datatype="html"> <trans-unit id="5c4bfd47a4f4d7cb99912f028494fe2530d36d57" datatype="html">
<source>Closing balance</source> <source>Closing balance</source>
<target>期末余额</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/channel-close-box/channel-close-box.component.html</context> <context context-type="sourcefile">src/app/lightning/channel/channel-close-box/channel-close-box.component.html</context>
<context context-type="linenumber">12</context> <context context-type="linenumber">12</context>
@@ -5796,6 +5837,7 @@
</trans-unit> </trans-unit>
<trans-unit id="1f0b0f2c90de4f3f0eb2c138eed38f4e9ac7a13e" datatype="html"> <trans-unit id="1f0b0f2c90de4f3f0eb2c138eed38f4e9ac7a13e" datatype="html">
<source>Closed by</source> <source>Closed by</source>
<target>关闭者</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context> <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
<context context-type="linenumber">59,61</context> <context context-type="linenumber">59,61</context>
@@ -5830,6 +5872,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2408280550320842855" datatype="html"> <trans-unit id="2408280550320842855" datatype="html">
<source>Mutually closed</source> <source>Mutually closed</source>
<target>相互封闭</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/closing-type/closing-type.component.ts</context> <context context-type="sourcefile">src/app/lightning/channel/closing-type/closing-type.component.ts</context>
<context context-type="linenumber">20</context> <context context-type="linenumber">20</context>
@@ -5837,6 +5880,7 @@
</trans-unit> </trans-unit>
<trans-unit id="4610828009441770083" datatype="html"> <trans-unit id="4610828009441770083" datatype="html">
<source>Force closed</source> <source>Force closed</source>
<target>强制关闭</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/closing-type/closing-type.component.ts</context> <context context-type="sourcefile">src/app/lightning/channel/closing-type/closing-type.component.ts</context>
<context context-type="linenumber">24</context> <context context-type="linenumber">24</context>
@@ -5844,6 +5888,7 @@
</trans-unit> </trans-unit>
<trans-unit id="96508700250272816" datatype="html"> <trans-unit id="96508700250272816" datatype="html">
<source>Force closed with penalty</source> <source>Force closed with penalty</source>
<target>强制关闭并受到惩罚</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channel/closing-type/closing-type.component.ts</context> <context context-type="sourcefile">src/app/lightning/channel/closing-type/closing-type.component.ts</context>
<context context-type="linenumber">28</context> <context context-type="linenumber">28</context>
@@ -5977,6 +6022,7 @@
</trans-unit> </trans-unit>
<trans-unit id="cfcc7201138b0ef9901e9604c35f550e91629295" datatype="html"> <trans-unit id="cfcc7201138b0ef9901e9604c35f550e91629295" datatype="html">
<source>avg</source> <source>avg</source>
<target>平均</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channels-statistics/channels-statistics.component.html</context> <context context-type="sourcefile">src/app/lightning/channels-statistics/channels-statistics.component.html</context>
<context context-type="linenumber">3,5</context> <context context-type="linenumber">3,5</context>
@@ -5985,6 +6031,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ba9117dcc11814c44437cf9d7561874ba8b98a2a" datatype="html"> <trans-unit id="ba9117dcc11814c44437cf9d7561874ba8b98a2a" datatype="html">
<source>med</source> <source>med</source>
<target>中位</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/channels-statistics/channels-statistics.component.html</context> <context context-type="sourcefile">src/app/lightning/channels-statistics/channels-statistics.component.html</context>
<context context-type="linenumber">6,9</context> <context context-type="linenumber">6,9</context>
@@ -6370,6 +6417,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7b8687bbc13bbf62288689606dcab9784a3eb53b" datatype="html"> <trans-unit id="7b8687bbc13bbf62288689606dcab9784a3eb53b" datatype="html">
<source>Fee distribution</source> <source>Fee distribution</source>
<target>费用分配</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node-fee-chart/node-fee-chart.component.html</context> <context context-type="sourcefile">src/app/lightning/node-fee-chart/node-fee-chart.component.html</context>
<context context-type="linenumber">2</context> <context context-type="linenumber">2</context>
@@ -6378,6 +6426,7 @@
</trans-unit> </trans-unit>
<trans-unit id="7254919336112973896" datatype="html"> <trans-unit id="7254919336112973896" datatype="html">
<source>Outgoing Fees</source> <source>Outgoing Fees</source>
<target>支出费用</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node-fee-chart/node-fee-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/node-fee-chart/node-fee-chart.component.ts</context>
<context context-type="linenumber">170</context> <context context-type="linenumber">170</context>
@@ -6389,6 +6438,7 @@
</trans-unit> </trans-unit>
<trans-unit id="484887099976974152" datatype="html"> <trans-unit id="484887099976974152" datatype="html">
<source>Incoming Fees</source> <source>Incoming Fees</source>
<target>进场费</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node-fee-chart/node-fee-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/node-fee-chart/node-fee-chart.component.ts</context>
<context context-type="linenumber">178</context> <context context-type="linenumber">178</context>
@@ -6478,6 +6528,7 @@
</trans-unit> </trans-unit>
<trans-unit id="008e9fb48f07f545af73b3f676dc60cc3a829765" datatype="html"> <trans-unit id="008e9fb48f07f545af73b3f676dc60cc3a829765" datatype="html">
<source>Avg channel distance</source> <source>Avg channel distance</source>
<target>平均频道距离</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">59,60</context> <context context-type="linenumber">59,60</context>
@@ -6517,6 +6568,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e128630e07a4c467f51b246a31c5734d5fb1a2c2" datatype="html"> <trans-unit id="e128630e07a4c467f51b246a31c5734d5fb1a2c2" datatype="html">
<source>Liquidity ad</source> <source>Liquidity ad</source>
<target>流动性广告</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">141,144</context> <context context-type="linenumber">141,144</context>
@@ -6525,6 +6577,7 @@
</trans-unit> </trans-unit>
<trans-unit id="bc84b5a9a70217104a53c7139e30b392be6520b7" datatype="html"> <trans-unit id="bc84b5a9a70217104a53c7139e30b392be6520b7" datatype="html">
<source>Lease fee rate</source> <source>Lease fee rate</source>
<target>租赁费率</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">147,150</context> <context context-type="linenumber">147,150</context>
@@ -6534,6 +6587,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ee807dd54b4a45eeba284744c64774de1ab5e4f1" datatype="html"> <trans-unit id="ee807dd54b4a45eeba284744c64774de1ab5e4f1" datatype="html">
<source>Lease base fee</source> <source>Lease base fee</source>
<target>租赁基本费</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">155,157</context> <context context-type="linenumber">155,157</context>
@@ -6542,6 +6596,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5e348f3d51c3bb283c16572bee1e293ea991cf49" datatype="html"> <trans-unit id="5e348f3d51c3bb283c16572bee1e293ea991cf49" datatype="html">
<source>Funding weight</source> <source>Funding weight</source>
<target>资金权重</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">161,162</context> <context context-type="linenumber">161,162</context>
@@ -6569,6 +6624,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e8e09fa12864e94f094a2a7c8c97cfdf0cff8aab" datatype="html"> <trans-unit id="e8e09fa12864e94f094a2a7c8c97cfdf0cff8aab" datatype="html">
<source>Compact lease</source> <source>Compact lease</source>
<target>协议合约</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">191,193</context> <context context-type="linenumber">191,193</context>
@@ -6577,6 +6633,7 @@
</trans-unit> </trans-unit>
<trans-unit id="aa687f4987e2d4e0010be692d402174962ece70e" datatype="html"> <trans-unit id="aa687f4987e2d4e0010be692d402174962ece70e" datatype="html">
<source>TLV extension records</source> <source>TLV extension records</source>
<target>TLV 扩展记录</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/node/node.component.html</context> <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
<context context-type="linenumber">202,205</context> <context context-type="linenumber">202,205</context>
@@ -6657,6 +6714,7 @@
</trans-unit> </trans-unit>
<trans-unit id="6391724349488018234" datatype="html"> <trans-unit id="6391724349488018234" datatype="html">
<source>Indexing in progress</source> <source>Indexing in progress</source>
<target>正在编制索引</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
<context context-type="linenumber">121,116</context> <context context-type="linenumber">121,116</context>
@@ -6668,6 +6726,7 @@
</trans-unit> </trans-unit>
<trans-unit id="599038141003770125" datatype="html"> <trans-unit id="599038141003770125" datatype="html">
<source>Clearnet and Darknet</source> <source>Clearnet and Darknet</source>
<target>明网和暗网</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
<context context-type="linenumber">164,161</context> <context context-type="linenumber">164,161</context>
@@ -6679,6 +6738,7 @@
</trans-unit> </trans-unit>
<trans-unit id="1282458597026430784" datatype="html"> <trans-unit id="1282458597026430784" datatype="html">
<source>Clearnet Only (IPv4, IPv6)</source> <source>Clearnet Only (IPv4, IPv6)</source>
<target>仅限明网IPv4、IPv6</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
<context context-type="linenumber">185,182</context> <context context-type="linenumber">185,182</context>
@@ -6690,6 +6750,7 @@
</trans-unit> </trans-unit>
<trans-unit id="2165336009914523952" datatype="html"> <trans-unit id="2165336009914523952" datatype="html">
<source>Darknet Only (Tor, I2P, cjdns)</source> <source>Darknet Only (Tor, I2P, cjdns)</source>
<target>仅限暗网Tor、I2P、cjdns</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
<context context-type="linenumber">206,203</context> <context context-type="linenumber">206,203</context>
@@ -6714,6 +6775,7 @@
</trans-unit> </trans-unit>
<trans-unit id="5222540403093176126" datatype="html"> <trans-unit id="5222540403093176126" datatype="html">
<source><x id="PH" equiv-text="nodeCount"/> nodes</source> <source><x id="PH" equiv-text="nodeCount"/> nodes</source>
<target><x id="PH" equiv-text="nodeCount"/>个节点</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts</context> <context context-type="sourcefile">src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts</context>
<context context-type="linenumber">104,103</context> <context context-type="linenumber">104,103</context>
@@ -6924,6 +6986,7 @@
</trans-unit> </trans-unit>
<trans-unit id="e422817608e8d55e08b45a1da2e118eb42815af4" datatype="html"> <trans-unit id="e422817608e8d55e08b45a1da2e118eb42815af4" datatype="html">
<source>Active nodes</source> <source>Active nodes</source>
<target>活跃节点</target>
<context-group purpose="location"> <context-group purpose="location">
<context context-type="sourcefile">src/app/lightning/nodes-per-isp/nodes-per-isp.component.html</context> <context context-type="sourcefile">src/app/lightning/nodes-per-isp/nodes-per-isp.component.html</context>
<context context-type="linenumber">14,18</context> <context context-type="linenumber">14,18</context>

View File

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

@@ -81,8 +81,10 @@ if (configContent.BASE_MODULE && configContent.BASE_MODULE === 'liquid') {
const testnetAssetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.json'; const testnetAssetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.json';
const testnetAssetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.minimal.json'; const testnetAssetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.minimal.json';
const promoVideo = PATH + 'mempool-promo.mp4'; const promoPrefix = PATH + 'promo-video/';
const promoVideoFile = promoPrefix + 'mempool-promo.mp4';
const promoVideoUrl = 'https://raw.githubusercontent.com/mempool/mempool-promo/master/promo.mp4'; const promoVideoUrl = 'https://raw.githubusercontent.com/mempool/mempool-promo/master/promo.mp4';
const promoVideoLanguages = ['en','sv','ja','zh','cs','fi','fr','de','it','lt','nb','fa','pl','ro','pt'];
console.log('Downloading assets'); console.log('Downloading assets');
download(PATH + 'assets.json', assetsJsonUrl); download(PATH + 'assets.json', assetsJsonUrl);
@@ -92,9 +94,13 @@ console.log('Downloading testnet assets');
download(PATH + 'assets-testnet.json', testnetAssetsJsonUrl); download(PATH + 'assets-testnet.json', testnetAssetsJsonUrl);
console.log('Downloading testnet assets minimal'); console.log('Downloading testnet assets minimal');
download(PATH + 'assets-testnet.minimal.json', testnetAssetsMinimalJsonUrl); download(PATH + 'assets-testnet.minimal.json', testnetAssetsMinimalJsonUrl);
if (!fs.existsSync(promoVideo)) { if (!fs.existsSync(promoVideoFile)) {
console.log('Downloading promo video'); console.log('Downloading promo video');
download(promoVideo, promoVideoUrl); download(promoVideoFile, promoVideoUrl);
}
console.log('Downloading promo video subtitles');
for( const l of promoVideoLanguages ) {
download(promoPrefix + l + ".vtt", "https://raw.githubusercontent.com/mempool/mempool-promo/master/subtitles/" + l + ".vtt");
} }
console.log('Downloading mining pool logos'); console.log('Downloading mining pool logos');
downloadMiningPoolLogos(); downloadMiningPoolLogos();

View File

@@ -13,6 +13,7 @@ validatepegin=1
mainchainrpcport=8332 mainchainrpcport=8332
[liquidtestnet] [liquidtestnet]
rpcport=7040
validatepegin=0 validatepegin=0
anyonecanspendaremine=0 anyonecanspendaremine=0
initialfreecoins=2100000000000000 initialfreecoins=2100000000000000

View File

@@ -357,7 +357,7 @@ ELEMENTS_REPO_URL=https://github.com/ElementsProject/elements
ELEMENTS_REPO_NAME=elements ELEMENTS_REPO_NAME=elements
ELEMENTS_REPO_BRANCH=master ELEMENTS_REPO_BRANCH=master
#ELEMENTS_LATEST_RELEASE=$(curl -s https://api.github.com/repos/ElementsProject/elements/releases/latest|grep tag_name|head -1|cut -d '"' -f4) #ELEMENTS_LATEST_RELEASE=$(curl -s https://api.github.com/repos/ElementsProject/elements/releases/latest|grep tag_name|head -1|cut -d '"' -f4)
ELEMENTS_LATEST_RELEASE=elements-0.21.0.2 ELEMENTS_LATEST_RELEASE=elements-22.1
echo -n '.' echo -n '.'
BITCOIN_ELECTRS_REPO_URL=https://github.com/blockstream/electrs BITCOIN_ELECTRS_REPO_URL=https://github.com/blockstream/electrs

View File

@@ -6,7 +6,8 @@
"MINED_BLOCKS_CACHE": 144, "MINED_BLOCKS_CACHE": 144,
"SPAWN_CLUSTER_PROCS": 0, "SPAWN_CLUSTER_PROCS": 0,
"API_URL_PREFIX": "/api/v1/", "API_URL_PREFIX": "/api/v1/",
"POLL_RATE_MS": 1000 "POLL_RATE_MS": 1000,
"DISK_CACHE_BLOCK_INTERVAL": 1
}, },
"SYSLOG" : { "SYSLOG" : {
"MIN_PRIORITY": "debug" "MIN_PRIORITY": "debug"

View File

@@ -6,7 +6,8 @@
"MINED_BLOCKS_CACHE": 144, "MINED_BLOCKS_CACHE": 144,
"SPAWN_CLUSTER_PROCS": 0, "SPAWN_CLUSTER_PROCS": 0,
"API_URL_PREFIX": "/api/v1/", "API_URL_PREFIX": "/api/v1/",
"POLL_RATE_MS": 1000 "POLL_RATE_MS": 1000,
"DISK_CACHE_BLOCK_INTERVAL": 1
}, },
"SYSLOG" : { "SYSLOG" : {
"MIN_PRIORITY": "debug" "MIN_PRIORITY": "debug"

View File

@@ -14,7 +14,8 @@
"CPFP_INDEXING": true, "CPFP_INDEXING": true,
"ADVANCED_GBT_AUDIT": true, "ADVANCED_GBT_AUDIT": true,
"ADVANCED_GBT_MEMPOOL": true, "ADVANCED_GBT_MEMPOOL": true,
"USE_SECOND_NODE_FOR_MINFEE": true "USE_SECOND_NODE_FOR_MINFEE": true,
"DISK_CACHE_BLOCK_INTERVAL": 1
}, },
"SYSLOG" : { "SYSLOG" : {
"MIN_PRIORITY": "debug" "MIN_PRIORITY": "debug"

View File

@@ -10,7 +10,8 @@
"AUDIT": true, "AUDIT": true,
"ADVANCED_GBT_AUDIT": true, "ADVANCED_GBT_AUDIT": true,
"ADVANCED_GBT_MEMPOOL": true, "ADVANCED_GBT_MEMPOOL": true,
"POLL_RATE_MS": 1000 "POLL_RATE_MS": 1000,
"DISK_CACHE_BLOCK_INTERVAL": 1
}, },
"SYSLOG" : { "SYSLOG" : {
"MIN_PRIORITY": "debug" "MIN_PRIORITY": "debug"

View File

@@ -10,7 +10,8 @@
"AUDIT": true, "AUDIT": true,
"ADVANCED_GBT_AUDIT": true, "ADVANCED_GBT_AUDIT": true,
"ADVANCED_GBT_MEMPOOL": true, "ADVANCED_GBT_MEMPOOL": true,
"POLL_RATE_MS": 1000 "POLL_RATE_MS": 1000,
"DISK_CACHE_BLOCK_INTERVAL": 1
}, },
"SYSLOG" : { "SYSLOG" : {
"MIN_PRIORITY": "debug" "MIN_PRIORITY": "debug"