Merge branch 'master' into simon/add-4y
This commit is contained in:
		
						commit
						ae1e2dcb50
					
				@ -220,18 +220,17 @@ class BitcoinRoutes {
 | 
			
		||||
      let cpfpInfo;
 | 
			
		||||
      if (config.DATABASE.ENABLED) {
 | 
			
		||||
        cpfpInfo = await transactionRepository.$getCpfpInfo(req.params.txId);
 | 
			
		||||
      }
 | 
			
		||||
      if (cpfpInfo) {
 | 
			
		||||
        res.json(cpfpInfo);
 | 
			
		||||
        return;
 | 
			
		||||
      } else {
 | 
			
		||||
        res.json({
 | 
			
		||||
          ancestors: []
 | 
			
		||||
        });
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
      if (cpfpInfo) {
 | 
			
		||||
        res.json(cpfpInfo);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    res.status(404).send(`Transaction has no CPFP info available.`);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private getBackendInfo(req: Request, res: Response) {
 | 
			
		||||
@ -652,7 +651,7 @@ class BitcoinRoutes {
 | 
			
		||||
      if (result) {
 | 
			
		||||
        res.json(result);
 | 
			
		||||
      } else {
 | 
			
		||||
        res.status(404).send('not found');
 | 
			
		||||
        res.status(204).send();
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      res.status(500).send(e instanceof Error ? e.message : e);
 | 
			
		||||
 | 
			
		||||
@ -1037,7 +1037,7 @@ class DatabaseMigration {
 | 
			
		||||
    await this.$executeQuery('DELETE FROM `pools`');
 | 
			
		||||
    await this.$executeQuery('ALTER TABLE pools AUTO_INCREMENT = 1');
 | 
			
		||||
    await this.$executeQuery(`UPDATE state SET string = NULL WHERE name = 'pools_json_sha'`);
 | 
			
		||||
}
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private async $convertCompactCpfpTables(): Promise<void> {
 | 
			
		||||
    try {
 | 
			
		||||
 | 
			
		||||
@ -62,7 +62,7 @@ class DiskCache {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  wipeCache() {
 | 
			
		||||
    logger.notice(`Wipping nodejs backend cache/cache*.json files`);
 | 
			
		||||
    logger.notice(`Wiping nodejs backend cache/cache*.json files`);
 | 
			
		||||
    try {
 | 
			
		||||
      fs.unlinkSync(DiskCache.FILE_NAME);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
 | 
			
		||||
@ -263,7 +263,7 @@ class MiningRoutes {
 | 
			
		||||
      const audit = await BlocksAuditsRepository.$getBlockAudit(req.params.hash);
 | 
			
		||||
 | 
			
		||||
      if (!audit) {
 | 
			
		||||
        res.status(404).send(`This block has not been audited.`);
 | 
			
		||||
        res.status(204).send(`This block has not been audited.`);
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -117,7 +117,7 @@ class Mining {
 | 
			
		||||
      poolsStatistics['lastEstimatedHashrate'] = await bitcoinClient.getNetworkHashPs(totalBlock24h);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      poolsStatistics['lastEstimatedHashrate'] = 0;
 | 
			
		||||
      logger.debug('Bitcoin Core is not available, using zeroed value for current hashrate');
 | 
			
		||||
      logger.debug('Bitcoin Core is not available, using zeroed value for current hashrate', logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return poolsStatistics;
 | 
			
		||||
@ -145,7 +145,7 @@ class Mining {
 | 
			
		||||
    try {
 | 
			
		||||
      currentEstimatedHashrate = await bitcoinClient.getNetworkHashPs(totalBlock24h);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.debug('Bitcoin Core is not available, using zeroed value for current hashrate');
 | 
			
		||||
      logger.debug('Bitcoin Core is not available, using zeroed value for current hashrate', logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
@ -208,7 +208,7 @@ class Mining {
 | 
			
		||||
      const startedAt = new Date().getTime() / 1000;
 | 
			
		||||
      let timer = new Date().getTime() / 1000;
 | 
			
		||||
 | 
			
		||||
      logger.debug(`Indexing weekly mining pool hashrate`);
 | 
			
		||||
      logger.debug(`Indexing weekly mining pool hashrate`, logger.tags.mining);
 | 
			
		||||
      loadingIndicators.setProgress('weekly-hashrate-indexing', 0);
 | 
			
		||||
 | 
			
		||||
      while (toTimestamp > genesisTimestamp && toTimestamp > oldestConsecutiveBlockTimestamp) {
 | 
			
		||||
@ -245,7 +245,7 @@ class Mining {
 | 
			
		||||
            });
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          newlyIndexed += hashrates.length;
 | 
			
		||||
          newlyIndexed += hashrates.length / Math.max(1, pools.length);
 | 
			
		||||
          await HashratesRepository.$saveHashrates(hashrates);
 | 
			
		||||
          hashrates.length = 0;
 | 
			
		||||
        }
 | 
			
		||||
@ -256,7 +256,7 @@ class Mining {
 | 
			
		||||
          const weeksPerSeconds = Math.max(1, Math.round(indexedThisRun / elapsedSeconds));
 | 
			
		||||
          const progress = Math.round(totalIndexed / totalWeekIndexed * 10000) / 100;
 | 
			
		||||
          const formattedDate = new Date(fromTimestamp).toUTCString();
 | 
			
		||||
          logger.debug(`Getting weekly pool hashrate for ${formattedDate} | ~${weeksPerSeconds.toFixed(2)} weeks/sec | total: ~${totalIndexed}/${Math.round(totalWeekIndexed)} (${progress}%) | elapsed: ${runningFor} seconds`);
 | 
			
		||||
          logger.debug(`Getting weekly pool hashrate for ${formattedDate} | ~${weeksPerSeconds.toFixed(2)} weeks/sec | total: ~${totalIndexed}/${Math.round(totalWeekIndexed)} (${progress}%) | elapsed: ${runningFor} seconds`, logger.tags.mining);
 | 
			
		||||
          timer = new Date().getTime() / 1000;
 | 
			
		||||
          indexedThisRun = 0;
 | 
			
		||||
          loadingIndicators.setProgress('weekly-hashrate-indexing', progress, false);
 | 
			
		||||
@ -268,14 +268,14 @@ class Mining {
 | 
			
		||||
      }
 | 
			
		||||
      this.lastWeeklyHashrateIndexingDate = new Date().getUTCDate();
 | 
			
		||||
      if (newlyIndexed > 0) {
 | 
			
		||||
        logger.notice(`Weekly mining pools hashrates indexing completed: indexed ${newlyIndexed}`, logger.tags.mining);
 | 
			
		||||
        logger.info(`Weekly mining pools hashrates indexing completed: indexed ${newlyIndexed} weeks`, logger.tags.mining);
 | 
			
		||||
      } else {
 | 
			
		||||
        logger.debug(`Weekly mining pools hashrates indexing completed: indexed ${newlyIndexed}`, logger.tags.mining);
 | 
			
		||||
        logger.debug(`Weekly mining pools hashrates indexing completed: indexed ${newlyIndexed} weeks`, logger.tags.mining);
 | 
			
		||||
      }
 | 
			
		||||
      loadingIndicators.setProgress('weekly-hashrate-indexing', 100);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      loadingIndicators.setProgress('weekly-hashrate-indexing', 100);
 | 
			
		||||
      logger.err(`Weekly mining pools hashrates indexing failed. Trying again in 10 seconds. Reason: ${(e instanceof Error ? e.message : e)}`);
 | 
			
		||||
      logger.err(`Weekly mining pools hashrates indexing failed. Trying again in 10 seconds. Reason: ${(e instanceof Error ? e.message : e)}`, logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -308,7 +308,7 @@ class Mining {
 | 
			
		||||
      const startedAt = new Date().getTime() / 1000;
 | 
			
		||||
      let timer = new Date().getTime() / 1000;
 | 
			
		||||
 | 
			
		||||
      logger.debug(`Indexing daily network hashrate`);
 | 
			
		||||
      logger.debug(`Indexing daily network hashrate`, logger.tags.mining);
 | 
			
		||||
      loadingIndicators.setProgress('daily-hashrate-indexing', 0);
 | 
			
		||||
 | 
			
		||||
      while (toTimestamp > genesisTimestamp && toTimestamp > oldestConsecutiveBlockTimestamp) {
 | 
			
		||||
@ -346,7 +346,7 @@ class Mining {
 | 
			
		||||
          const daysPerSeconds = Math.max(1, Math.round(indexedThisRun / elapsedSeconds));
 | 
			
		||||
          const progress = Math.round(totalIndexed / totalDayIndexed * 10000) / 100;
 | 
			
		||||
          const formattedDate = new Date(fromTimestamp).toUTCString();
 | 
			
		||||
          logger.debug(`Getting network daily hashrate for ${formattedDate} | ~${daysPerSeconds.toFixed(2)} days/sec | total: ~${totalIndexed}/${Math.round(totalDayIndexed)} (${progress}%) | elapsed: ${runningFor} seconds`);
 | 
			
		||||
          logger.debug(`Getting network daily hashrate for ${formattedDate} | ~${daysPerSeconds.toFixed(2)} days/sec | total: ~${totalIndexed}/${Math.round(totalDayIndexed)} (${progress}%) | elapsed: ${runningFor} seconds`, logger.tags.mining);
 | 
			
		||||
          timer = new Date().getTime() / 1000;
 | 
			
		||||
          indexedThisRun = 0;
 | 
			
		||||
          loadingIndicators.setProgress('daily-hashrate-indexing', progress);
 | 
			
		||||
@ -373,14 +373,14 @@ class Mining {
 | 
			
		||||
 | 
			
		||||
      this.lastHashrateIndexingDate = new Date().getUTCDate();
 | 
			
		||||
      if (newlyIndexed > 0) {
 | 
			
		||||
        logger.notice(`Daily network hashrate indexing completed: indexed ${newlyIndexed} days`, logger.tags.mining);
 | 
			
		||||
        logger.info(`Daily network hashrate indexing completed: indexed ${newlyIndexed} days`, logger.tags.mining);
 | 
			
		||||
      } else {
 | 
			
		||||
        logger.debug(`Daily network hashrate indexing completed: indexed ${newlyIndexed} days`, logger.tags.mining);
 | 
			
		||||
      }
 | 
			
		||||
      loadingIndicators.setProgress('daily-hashrate-indexing', 100);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      loadingIndicators.setProgress('daily-hashrate-indexing', 100);
 | 
			
		||||
      logger.err(`Daily network hashrate indexing failed. Trying again in 10 seconds. Reason: ${(e instanceof Error ? e.message : e)}`, logger.tags.mining);
 | 
			
		||||
      logger.err(`Daily network hashrate indexing failed. Trying again later. Reason: ${(e instanceof Error ? e.message : e)}`, logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -446,13 +446,13 @@ class Mining {
 | 
			
		||||
      const elapsedSeconds = Math.max(1, Math.round((new Date().getTime() / 1000) - timer));
 | 
			
		||||
      if (elapsedSeconds > 5) {
 | 
			
		||||
        const progress = Math.round(totalBlockChecked / blocks.length * 100);
 | 
			
		||||
        logger.info(`Indexing difficulty adjustment at block #${block.height} | Progress: ${progress}%`);
 | 
			
		||||
        logger.info(`Indexing difficulty adjustment at block #${block.height} | Progress: ${progress}%`, logger.tags.mining);
 | 
			
		||||
        timer = new Date().getTime() / 1000;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (totalIndexed > 0) {
 | 
			
		||||
      logger.notice(`Indexed ${totalIndexed} difficulty adjustments`, logger.tags.mining);
 | 
			
		||||
      logger.info(`Indexed ${totalIndexed} difficulty adjustments`, logger.tags.mining);
 | 
			
		||||
    } else {
 | 
			
		||||
      logger.debug(`Indexed ${totalIndexed} difficulty adjustments`, logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
@ -499,7 +499,7 @@ class Mining {
 | 
			
		||||
          if (blocksWithoutPrices.length > 200000) {
 | 
			
		||||
            logStr += ` | Progress ${Math.round(totalInserted / blocksWithoutPrices.length * 100)}%`;
 | 
			
		||||
          }
 | 
			
		||||
          logger.debug(logStr);
 | 
			
		||||
          logger.debug(logStr, logger.tags.mining);
 | 
			
		||||
          await BlocksRepository.$saveBlockPrices(blocksPrices);
 | 
			
		||||
          blocksPrices.length = 0;
 | 
			
		||||
        }
 | 
			
		||||
@ -511,7 +511,7 @@ class Mining {
 | 
			
		||||
        if (blocksWithoutPrices.length > 200000) {
 | 
			
		||||
          logStr += ` | Progress ${Math.round(totalInserted / blocksWithoutPrices.length * 100)}%`;
 | 
			
		||||
        }
 | 
			
		||||
        logger.debug(logStr);
 | 
			
		||||
        logger.debug(logStr, logger.tags.mining);
 | 
			
		||||
        await BlocksRepository.$saveBlockPrices(blocksPrices);
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,8 @@
 | 
			
		||||
import logger from '../logger';
 | 
			
		||||
import * as WebSocket from 'ws';
 | 
			
		||||
import {
 | 
			
		||||
  BlockExtended, TransactionExtended, WebsocketResponse, MempoolBlock, MempoolBlockDelta,
 | 
			
		||||
  OptimizedStatistic, ILoadingIndicators, IConversionRates
 | 
			
		||||
  BlockExtended, TransactionExtended, WebsocketResponse,
 | 
			
		||||
  OptimizedStatistic, ILoadingIndicators
 | 
			
		||||
} from '../mempool.interfaces';
 | 
			
		||||
import blocks from './blocks';
 | 
			
		||||
import memPool from './mempool';
 | 
			
		||||
@ -20,6 +20,7 @@ import BlocksSummariesRepository from '../repositories/BlocksSummariesRepository
 | 
			
		||||
import Audit from './audit';
 | 
			
		||||
import { deepClone } from '../utils/clone';
 | 
			
		||||
import priceUpdater from '../tasks/price-updater';
 | 
			
		||||
import { ApiPrice } from '../repositories/PricesRepository';
 | 
			
		||||
 | 
			
		||||
class WebsocketHandler {
 | 
			
		||||
  private wss: WebSocket.Server | undefined;
 | 
			
		||||
@ -193,7 +194,7 @@ class WebsocketHandler {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleNewConversionRates(conversionRates: IConversionRates) {
 | 
			
		||||
  handleNewConversionRates(conversionRates: ApiPrice) {
 | 
			
		||||
    if (!this.wss) {
 | 
			
		||||
      throw new Error('WebSocket.Server is not set');
 | 
			
		||||
    }
 | 
			
		||||
@ -214,7 +215,7 @@ class WebsocketHandler {
 | 
			
		||||
      'mempoolInfo': memPool.getMempoolInfo(),
 | 
			
		||||
      'vBytesPerSecond': memPool.getVBytesPerSecond(),
 | 
			
		||||
      'blocks': _blocks,
 | 
			
		||||
      'conversions': priceUpdater.latestPrices,
 | 
			
		||||
      'conversions': priceUpdater.getLatestPrices(),
 | 
			
		||||
      'mempool-blocks': mempoolBlocks.getMempoolBlocks(),
 | 
			
		||||
      'transactions': memPool.getLatestTransactions(),
 | 
			
		||||
      'backendInfo': backendInfo.getBackendInfo(),
 | 
			
		||||
 | 
			
		||||
@ -38,6 +38,8 @@ import forensicsService from './tasks/lightning/forensics.service';
 | 
			
		||||
import priceUpdater from './tasks/price-updater';
 | 
			
		||||
import chainTips from './api/chain-tips';
 | 
			
		||||
import { AxiosError } from 'axios';
 | 
			
		||||
import v8 from 'v8';
 | 
			
		||||
import { formatBytes, getBytesUnit } from './utils/format';
 | 
			
		||||
 | 
			
		||||
class Server {
 | 
			
		||||
  private wss: WebSocket.Server | undefined;
 | 
			
		||||
@ -45,6 +47,11 @@ class Server {
 | 
			
		||||
  private app: Application;
 | 
			
		||||
  private currentBackendRetryInterval = 5;
 | 
			
		||||
 | 
			
		||||
  private maxHeapSize: number = 0;
 | 
			
		||||
  private heapLogInterval: number = 60;
 | 
			
		||||
  private warnedHeapCritical: boolean = false;
 | 
			
		||||
  private lastHeapLogTime: number | null = null;
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.app = express();
 | 
			
		||||
 | 
			
		||||
@ -137,6 +144,8 @@ class Server {
 | 
			
		||||
      this.runMainUpdateLoop();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    setInterval(() => { this.healthCheck(); }, 2500);
 | 
			
		||||
 | 
			
		||||
    if (config.BISQ.ENABLED) {
 | 
			
		||||
      bisq.startBisqService();
 | 
			
		||||
      bisq.setPriceCallbackFunction((price) => websocketHandler.setExtraInitProperties('bsq-price', price));
 | 
			
		||||
@ -255,6 +264,26 @@ class Server {
 | 
			
		||||
      channelsRoutes.initRoutes(this.app);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  healthCheck(): void {
 | 
			
		||||
    const now = Date.now();
 | 
			
		||||
    const stats = v8.getHeapStatistics();
 | 
			
		||||
    this.maxHeapSize = Math.max(stats.used_heap_size, this.maxHeapSize);
 | 
			
		||||
    const warnThreshold = 0.8 * stats.heap_size_limit;
 | 
			
		||||
 | 
			
		||||
    const byteUnits = getBytesUnit(Math.max(this.maxHeapSize, stats.heap_size_limit));
 | 
			
		||||
 | 
			
		||||
    if (!this.warnedHeapCritical && this.maxHeapSize > warnThreshold) {
 | 
			
		||||
      this.warnedHeapCritical = true;
 | 
			
		||||
      logger.warn(`Used ${(this.maxHeapSize / stats.heap_size_limit).toFixed(2)}% of heap limit (${formatBytes(this.maxHeapSize, byteUnits, true)} / ${formatBytes(stats.heap_size_limit, byteUnits)})!`);
 | 
			
		||||
    }
 | 
			
		||||
    if (this.lastHeapLogTime === null || (now - this.lastHeapLogTime) > (this.heapLogInterval * 1000)) {
 | 
			
		||||
      logger.debug(`Memory usage: ${formatBytes(this.maxHeapSize, byteUnits)} / ${formatBytes(stats.heap_size_limit, byteUnits)}`);
 | 
			
		||||
      this.warnedHeapCritical = false;
 | 
			
		||||
      this.maxHeapSize = 0;
 | 
			
		||||
      this.lastHeapLogTime = now;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
((): Server => new Server())();
 | 
			
		||||
 | 
			
		||||
@ -76,13 +76,13 @@ class Indexer {
 | 
			
		||||
      this.tasksRunning.push(task);
 | 
			
		||||
      const lastestPriceId = await PricesRepository.$getLatestPriceId();
 | 
			
		||||
      if (priceUpdater.historyInserted === false || lastestPriceId === null) {
 | 
			
		||||
        logger.debug(`Blocks prices indexer is waiting for the price updater to complete`);
 | 
			
		||||
        logger.debug(`Blocks prices indexer is waiting for the price updater to complete`, logger.tags.mining);
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          this.tasksRunning = this.tasksRunning.filter(runningTask => runningTask !== task);
 | 
			
		||||
          this.runSingleTask('blocksPrices');
 | 
			
		||||
        }, 10000);
 | 
			
		||||
      } else {
 | 
			
		||||
        logger.debug(`Blocks prices indexer will run now`);
 | 
			
		||||
        logger.debug(`Blocks prices indexer will run now`, logger.tags.mining);
 | 
			
		||||
        await mining.$indexBlockPrices();
 | 
			
		||||
        this.tasksRunning = this.tasksRunning.filter(runningTask => runningTask !== task);
 | 
			
		||||
      }
 | 
			
		||||
@ -112,7 +112,7 @@ class Indexer {
 | 
			
		||||
    this.runIndexer = false;
 | 
			
		||||
    this.indexerRunning = true;
 | 
			
		||||
 | 
			
		||||
    logger.info(`Running mining indexer`);
 | 
			
		||||
    logger.debug(`Running mining indexer`);
 | 
			
		||||
 | 
			
		||||
    await this.checkAvailableCoreIndexes();
 | 
			
		||||
 | 
			
		||||
@ -122,7 +122,7 @@ class Indexer {
 | 
			
		||||
      const chainValid = await blocks.$generateBlockDatabase();
 | 
			
		||||
      if (chainValid === false) {
 | 
			
		||||
        // Chain of block hash was invalid, so we need to reindex. Stop here and continue at the next iteration
 | 
			
		||||
        logger.warn(`The chain of block hash is invalid, re-indexing invalid data in 10 seconds.`);
 | 
			
		||||
        logger.warn(`The chain of block hash is invalid, re-indexing invalid data in 10 seconds.`, logger.tags.mining);
 | 
			
		||||
        setTimeout(() => this.reindex(), 10000);
 | 
			
		||||
        this.indexerRunning = false;
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
@ -293,7 +293,6 @@ interface RequiredParams {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface ILoadingIndicators { [name: string]: number; }
 | 
			
		||||
export interface IConversionRates { [currency: string]: number; }
 | 
			
		||||
 | 
			
		||||
export interface IBackendInfo {
 | 
			
		||||
  hostname: string;
 | 
			
		||||
 | 
			
		||||
@ -20,9 +20,9 @@ class DifficultyAdjustmentsRepository {
 | 
			
		||||
      await DB.query(query, params);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      if (e.errno === 1062) { // ER_DUP_ENTRY - This scenario is possible upon node backend restart
 | 
			
		||||
        logger.debug(`Cannot save difficulty adjustment at block ${adjustment.height}, already indexed, ignoring`);
 | 
			
		||||
        logger.debug(`Cannot save difficulty adjustment at block ${adjustment.height}, already indexed, ignoring`, logger.tags.mining);
 | 
			
		||||
      } else {
 | 
			
		||||
        logger.err(`Cannot save difficulty adjustment at block ${adjustment.height}. Reason: ${e instanceof Error ? e.message : e}`);
 | 
			
		||||
        logger.err(`Cannot save difficulty adjustment at block ${adjustment.height}. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining);
 | 
			
		||||
        throw e;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@ -54,7 +54,7 @@ class DifficultyAdjustmentsRepository {
 | 
			
		||||
      const [rows] = await DB.query(query);
 | 
			
		||||
      return rows as IndexedDifficultyAdjustment[];
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(`Cannot get difficulty adjustments from the database. Reason: ` + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err(`Cannot get difficulty adjustments from the database. Reason: ` + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -83,7 +83,7 @@ class DifficultyAdjustmentsRepository {
 | 
			
		||||
      const [rows] = await DB.query(query);
 | 
			
		||||
      return rows as IndexedDifficultyAdjustment[];
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(`Cannot get difficulty adjustments from the database. Reason: ` + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err(`Cannot get difficulty adjustments from the database. Reason: ` + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -93,27 +93,27 @@ class DifficultyAdjustmentsRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(`SELECT height FROM difficulty_adjustments`);
 | 
			
		||||
      return rows.map(block => block.height);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      logger.err(`Cannot get difficulty adjustment block heights. Reason: ${e instanceof Error ? e.message : e}`);
 | 
			
		||||
      logger.err(`Cannot get difficulty adjustment block heights. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $deleteAdjustementsFromHeight(height: number): Promise<void> {
 | 
			
		||||
    try {
 | 
			
		||||
      logger.info(`Delete newer difficulty adjustments from height ${height} from the database`);
 | 
			
		||||
      logger.info(`Delete newer difficulty adjustments from height ${height} from the database`, logger.tags.mining);
 | 
			
		||||
      await DB.query(`DELETE FROM difficulty_adjustments WHERE height >= ?`, [height]);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      logger.err(`Cannot delete difficulty adjustments from the database. Reason: ${e instanceof Error ? e.message : e}`);
 | 
			
		||||
      logger.err(`Cannot delete difficulty adjustments from the database. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $deleteLastAdjustment(): Promise<void> {
 | 
			
		||||
    try {
 | 
			
		||||
      logger.info(`Delete last difficulty adjustment from the database`);
 | 
			
		||||
      logger.info(`Delete last difficulty adjustment from the database`, logger.tags.mining);
 | 
			
		||||
      await DB.query(`DELETE FROM difficulty_adjustments ORDER BY time LIMIT 1`);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      logger.err(`Cannot delete last difficulty adjustment from the database. Reason: ${e instanceof Error ? e.message : e}`);
 | 
			
		||||
      logger.err(`Cannot delete last difficulty adjustment from the database. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -25,7 +25,7 @@ class HashratesRepository {
 | 
			
		||||
    try {
 | 
			
		||||
      await DB.query(query);
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
      logger.err('Cannot save indexed hashrate into db. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot save indexed hashrate into db. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -51,7 +51,7 @@ class HashratesRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(query);
 | 
			
		||||
      return rows;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot fetch network hashrate history. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot fetch network hashrate history. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -78,7 +78,7 @@ class HashratesRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(query);
 | 
			
		||||
      return rows;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot fetch network hashrate history. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot fetch network hashrate history. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -93,7 +93,7 @@ class HashratesRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(query);
 | 
			
		||||
      return rows.map(row => row.timestamp);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot retreive indexed weekly hashrate timestamps. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot retreive indexed weekly hashrate timestamps. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -128,7 +128,7 @@ class HashratesRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(query);
 | 
			
		||||
      return rows;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot fetch weekly pools hashrate history. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot fetch weekly pools hashrate history. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -158,7 +158,7 @@ class HashratesRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(query, [pool.id]);
 | 
			
		||||
      boundaries = rows[0];
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot fetch hashrate start/end timestamps for this pool. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot fetch hashrate start/end timestamps for this pool. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Get hashrates entries between boundaries
 | 
			
		||||
@ -173,7 +173,7 @@ class HashratesRepository {
 | 
			
		||||
      const [rows]: any[] = await DB.query(query, [boundaries.firstTimestamp, boundaries.lastTimestamp, pool.id]);
 | 
			
		||||
      return rows;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot fetch pool hashrate history for this pool. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot fetch pool hashrate history for this pool. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -192,7 +192,7 @@ class HashratesRepository {
 | 
			
		||||
      }
 | 
			
		||||
      return rows[0]['number'];
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(`Cannot retrieve last indexing run for ${key}. Reason: ` + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err(`Cannot retrieve last indexing run for ${key}. Reason: ` + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@ -201,7 +201,7 @@ class HashratesRepository {
 | 
			
		||||
   * Delete most recent data points for re-indexing
 | 
			
		||||
   */
 | 
			
		||||
  public async $deleteLastEntries() {
 | 
			
		||||
    logger.info(`Delete latest hashrates data points from the database`);
 | 
			
		||||
    logger.info(`Delete latest hashrates data points from the database`, logger.tags.mining);
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const [rows]: any[] = await DB.query(`SELECT MAX(hashrate_timestamp) as timestamp FROM hashrates GROUP BY type`);
 | 
			
		||||
@ -212,7 +212,7 @@ class HashratesRepository {
 | 
			
		||||
      mining.lastHashrateIndexingDate = null;
 | 
			
		||||
      mining.lastWeeklyHashrateIndexingDate = null;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot delete latest hashrates data points. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot delete latest hashrates data points. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
@ -228,7 +228,7 @@ class HashratesRepository {
 | 
			
		||||
      mining.lastHashrateIndexingDate = null;
 | 
			
		||||
      mining.lastWeeklyHashrateIndexingDate = null;
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot delete latest hashrates data points. Reason: ' + (e instanceof Error ? e.message : e));
 | 
			
		||||
      logger.err('Cannot delete latest hashrates data points. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,5 @@
 | 
			
		||||
import DB from '../database';
 | 
			
		||||
import logger from '../logger';
 | 
			
		||||
import { IConversionRates } from '../mempool.interfaces';
 | 
			
		||||
import priceUpdater from '../tasks/price-updater';
 | 
			
		||||
 | 
			
		||||
export interface ApiPrice {
 | 
			
		||||
@ -13,6 +12,16 @@ export interface ApiPrice {
 | 
			
		||||
  AUD: number,
 | 
			
		||||
  JPY: number,
 | 
			
		||||
}
 | 
			
		||||
const ApiPriceFields = `
 | 
			
		||||
  UNIX_TIMESTAMP(time) as time,
 | 
			
		||||
  USD,
 | 
			
		||||
  EUR,
 | 
			
		||||
  GBP,
 | 
			
		||||
  CAD,
 | 
			
		||||
  CHF,
 | 
			
		||||
  AUD,
 | 
			
		||||
  JPY
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
export interface ExchangeRates {
 | 
			
		||||
  USDEUR: number,
 | 
			
		||||
@ -39,7 +48,7 @@ export const MAX_PRICES = {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class PricesRepository {
 | 
			
		||||
  public async $savePrices(time: number, prices: IConversionRates): Promise<void> {
 | 
			
		||||
  public async $savePrices(time: number, prices: ApiPrice): Promise<void> {
 | 
			
		||||
    if (prices.USD === -1) {
 | 
			
		||||
      // Some historical price entries have no USD prices, so we just ignore them to avoid future UX issues
 | 
			
		||||
      // As of today there are only 4 (on 2013-09-05, 2013-0909, 2013-09-12 and 2013-09-26) so that's fine
 | 
			
		||||
@ -60,77 +69,115 @@ class PricesRepository {
 | 
			
		||||
        VALUE             (FROM_UNIXTIME(?), ?,   ?,   ?,   ?,   ?,   ?,   ?  )`,
 | 
			
		||||
        [time, prices.USD, prices.EUR, prices.GBP, prices.CAD, prices.CHF, prices.AUD, prices.JPY]
 | 
			
		||||
      );
 | 
			
		||||
    } catch (e: any) {
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(`Cannot save exchange rate into db. Reason: ` + (e instanceof Error ? e.message : e));
 | 
			
		||||
      throw e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getOldestPriceTime(): Promise<number> {
 | 
			
		||||
    const [oldestRow] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != 0 ORDER BY time LIMIT 1`);
 | 
			
		||||
    const [oldestRow] = await DB.query(`
 | 
			
		||||
      SELECT UNIX_TIMESTAMP(time) AS time
 | 
			
		||||
      FROM prices
 | 
			
		||||
      ORDER BY time
 | 
			
		||||
      LIMIT 1
 | 
			
		||||
    `);
 | 
			
		||||
    return oldestRow[0] ? oldestRow[0].time : 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getLatestPriceId(): Promise<number | null> {
 | 
			
		||||
    const [oldestRow] = await DB.query(`SELECT id from prices WHERE USD != 0 ORDER BY time DESC LIMIT 1`);
 | 
			
		||||
    return oldestRow[0] ? oldestRow[0].id : null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getLatestPriceTime(): Promise<number> {
 | 
			
		||||
    const [oldestRow] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != 0 ORDER BY time DESC LIMIT 1`);
 | 
			
		||||
    return oldestRow[0] ? oldestRow[0].time : 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getPricesTimes(): Promise<number[]> {
 | 
			
		||||
    const [times]: any[] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time from prices WHERE USD != 0 ORDER BY time`);
 | 
			
		||||
    return times.map(time => time.time);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getPricesTimesAndId(): Promise<number[]> {
 | 
			
		||||
    const [times]: any[] = await DB.query(`SELECT UNIX_TIMESTAMP(time) as time, id, USD from prices ORDER BY time`);
 | 
			
		||||
    return times;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getLatestConversionRates(): Promise<any> {
 | 
			
		||||
    const [rates]: any[] = await DB.query(`
 | 
			
		||||
      SELECT USD, EUR, GBP, CAD, CHF, AUD, JPY
 | 
			
		||||
    const [oldestRow] = await DB.query(`
 | 
			
		||||
      SELECT id
 | 
			
		||||
      FROM prices
 | 
			
		||||
      ORDER BY time DESC
 | 
			
		||||
      LIMIT 1`
 | 
			
		||||
    );
 | 
			
		||||
    if (!rates || rates.length === 0) {
 | 
			
		||||
    return oldestRow[0] ? oldestRow[0].id : null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getLatestPriceTime(): Promise<number> {
 | 
			
		||||
    const [oldestRow] = await DB.query(`
 | 
			
		||||
      SELECT UNIX_TIMESTAMP(time) AS time
 | 
			
		||||
      FROM prices
 | 
			
		||||
      ORDER BY time DESC
 | 
			
		||||
      LIMIT 1`
 | 
			
		||||
    );
 | 
			
		||||
    return oldestRow[0] ? oldestRow[0].time : 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getPricesTimes(): Promise<number[]> {
 | 
			
		||||
    const [times] = await DB.query(`
 | 
			
		||||
      SELECT UNIX_TIMESTAMP(time) AS time
 | 
			
		||||
      FROM prices
 | 
			
		||||
      WHERE USD != -1
 | 
			
		||||
      ORDER BY time
 | 
			
		||||
    `);
 | 
			
		||||
    if (!Array.isArray(times)) {
 | 
			
		||||
      return [];
 | 
			
		||||
    }
 | 
			
		||||
    return times.map(time => time.time);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getPricesTimesAndId(): Promise<{time: number, id: number, USD: number}[]> {
 | 
			
		||||
    const [times] = await DB.query(`
 | 
			
		||||
      SELECT
 | 
			
		||||
        UNIX_TIMESTAMP(time) AS time,
 | 
			
		||||
        id,
 | 
			
		||||
        USD
 | 
			
		||||
      FROM prices
 | 
			
		||||
      ORDER BY time
 | 
			
		||||
    `);
 | 
			
		||||
    return times as {time: number, id: number, USD: number}[];
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getLatestConversionRates(): Promise<ApiPrice> {
 | 
			
		||||
    const [rates] = await DB.query(`
 | 
			
		||||
      SELECT ${ApiPriceFields}
 | 
			
		||||
      FROM prices
 | 
			
		||||
      ORDER BY time DESC
 | 
			
		||||
      LIMIT 1`
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    if (!Array.isArray(rates) || rates.length === 0) {
 | 
			
		||||
      return priceUpdater.getEmptyPricesObj();
 | 
			
		||||
    }
 | 
			
		||||
    return rates[0];
 | 
			
		||||
    return rates[0] as ApiPrice;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $getNearestHistoricalPrice(timestamp: number | undefined): Promise<Conversion | null> {
 | 
			
		||||
    try {
 | 
			
		||||
      const [rates]: any[] = await DB.query(`
 | 
			
		||||
        SELECT *, UNIX_TIMESTAMP(time) AS time
 | 
			
		||||
      const [rates] = await DB.query(`
 | 
			
		||||
        SELECT ${ApiPriceFields}
 | 
			
		||||
        FROM prices
 | 
			
		||||
        WHERE UNIX_TIMESTAMP(time) < ?
 | 
			
		||||
        ORDER BY time DESC
 | 
			
		||||
        LIMIT 1`,
 | 
			
		||||
        [timestamp]
 | 
			
		||||
      );
 | 
			
		||||
      if (!rates) {
 | 
			
		||||
      if (!Array.isArray(rates)) {
 | 
			
		||||
        throw Error(`Cannot get single historical price from the database`);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Compute fiat exchange rates
 | 
			
		||||
      const latestPrice = await this.$getLatestConversionRates();
 | 
			
		||||
      let latestPrice = rates[0] as ApiPrice;
 | 
			
		||||
      if (latestPrice.USD === -1) {
 | 
			
		||||
        latestPrice = priceUpdater.getEmptyPricesObj();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const computeFx = (usd: number, other: number): number =>
 | 
			
		||||
        Math.round(Math.max(other, 0) / Math.max(usd, 1) * 100) / 100;
 | 
			
		||||
      
 | 
			
		||||
      const exchangeRates: ExchangeRates = {
 | 
			
		||||
        USDEUR: Math.round(latestPrice.EUR / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDGBP: Math.round(latestPrice.GBP / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDCAD: Math.round(latestPrice.CAD / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDCHF: Math.round(latestPrice.CHF / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDAUD: Math.round(latestPrice.AUD / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDJPY: Math.round(latestPrice.JPY / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDEUR: computeFx(latestPrice.USD, latestPrice.EUR),
 | 
			
		||||
        USDGBP: computeFx(latestPrice.USD, latestPrice.GBP),
 | 
			
		||||
        USDCAD: computeFx(latestPrice.USD, latestPrice.CAD),
 | 
			
		||||
        USDCHF: computeFx(latestPrice.USD, latestPrice.CHF),
 | 
			
		||||
        USDAUD: computeFx(latestPrice.USD, latestPrice.AUD),
 | 
			
		||||
        USDJPY: computeFx(latestPrice.USD, latestPrice.JPY),
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        prices: rates,
 | 
			
		||||
        prices: rates as ApiPrice[],
 | 
			
		||||
        exchangeRates: exchangeRates
 | 
			
		||||
      };
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
@ -141,28 +188,35 @@ class PricesRepository {
 | 
			
		||||
 | 
			
		||||
  public async $getHistoricalPrices(): Promise<Conversion | null> {
 | 
			
		||||
    try {
 | 
			
		||||
      const [rates]: any[] = await DB.query(`
 | 
			
		||||
        SELECT *, UNIX_TIMESTAMP(time) AS time
 | 
			
		||||
      const [rates] = await DB.query(`
 | 
			
		||||
        SELECT ${ApiPriceFields}
 | 
			
		||||
        FROM prices
 | 
			
		||||
        ORDER BY time DESC
 | 
			
		||||
      `);
 | 
			
		||||
      if (!rates) {
 | 
			
		||||
      if (!Array.isArray(rates)) {
 | 
			
		||||
        throw Error(`Cannot get average historical price from the database`);
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // Compute fiat exchange rates
 | 
			
		||||
      const latestPrice: ApiPrice = rates[0];
 | 
			
		||||
      let latestPrice = rates[0] as ApiPrice;
 | 
			
		||||
      if (latestPrice.USD === -1) {
 | 
			
		||||
        latestPrice = priceUpdater.getEmptyPricesObj();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const computeFx = (usd: number, other: number): number =>
 | 
			
		||||
        Math.round(Math.max(other, 0) / Math.max(usd, 1) * 100) / 100;
 | 
			
		||||
      
 | 
			
		||||
      const exchangeRates: ExchangeRates = {
 | 
			
		||||
        USDEUR: Math.round(latestPrice.EUR / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDGBP: Math.round(latestPrice.GBP / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDCAD: Math.round(latestPrice.CAD / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDCHF: Math.round(latestPrice.CHF / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDAUD: Math.round(latestPrice.AUD / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDJPY: Math.round(latestPrice.JPY / latestPrice.USD * 100) / 100,
 | 
			
		||||
        USDEUR: computeFx(latestPrice.USD, latestPrice.EUR),
 | 
			
		||||
        USDGBP: computeFx(latestPrice.USD, latestPrice.GBP),
 | 
			
		||||
        USDCAD: computeFx(latestPrice.USD, latestPrice.CAD),
 | 
			
		||||
        USDCHF: computeFx(latestPrice.USD, latestPrice.CHF),
 | 
			
		||||
        USDAUD: computeFx(latestPrice.USD, latestPrice.AUD),
 | 
			
		||||
        USDJPY: computeFx(latestPrice.USD, latestPrice.JPY),
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      return {
 | 
			
		||||
        prices: rates,
 | 
			
		||||
        prices: rates as ApiPrice[],
 | 
			
		||||
        exchangeRates: exchangeRates
 | 
			
		||||
      };
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
 | 
			
		||||
@ -411,7 +411,7 @@ class LightningStatsImporter {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (totalProcessed > 0) {
 | 
			
		||||
        logger.notice(`Lightning network stats historical import completed`, logger.tags.ln);
 | 
			
		||||
        logger.info(`Lightning network stats historical import completed`, logger.tags.ln);
 | 
			
		||||
      }
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err(`Lightning network stats historical failed. Reason: ${e instanceof Error ? e.message : e}`, logger.tags.ln);
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,7 @@ import * as https from 'https';
 | 
			
		||||
 */
 | 
			
		||||
class PoolsUpdater {
 | 
			
		||||
  lastRun: number = 0;
 | 
			
		||||
  currentSha: string | undefined = undefined;
 | 
			
		||||
  currentSha: string | null = null;
 | 
			
		||||
  poolsUrl: string = config.MEMPOOL.POOLS_JSON_URL;
 | 
			
		||||
  treeUrl: string = config.MEMPOOL.POOLS_JSON_TREE_URL;
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@ class PoolsUpdater {
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      const githubSha = await this.fetchPoolsSha(); // Fetch pools-v2.json sha from github
 | 
			
		||||
      if (githubSha === undefined) {
 | 
			
		||||
      if (githubSha === null) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
@ -42,12 +42,12 @@ class PoolsUpdater {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      logger.debug(`pools-v2.json sha | Current: ${this.currentSha} | Github: ${githubSha}`);
 | 
			
		||||
      if (this.currentSha !== undefined && this.currentSha === githubSha) {
 | 
			
		||||
      if (this.currentSha !== null && this.currentSha === githubSha) {
 | 
			
		||||
        return;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // See backend README for more details about the mining pools update process
 | 
			
		||||
      if (this.currentSha !== undefined && // If we don't have any mining pool, download it at least once
 | 
			
		||||
      if (this.currentSha !== null && // If we don't have any mining pool, download it at least once
 | 
			
		||||
        config.MEMPOOL.AUTOMATIC_BLOCK_REINDEXING !== true && // Automatic pools update is disabled
 | 
			
		||||
        !process.env.npm_config_update_pools // We're not manually updating mining pool
 | 
			
		||||
      ) {
 | 
			
		||||
@ -57,7 +57,7 @@ class PoolsUpdater {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      const network = config.SOCKS5PROXY.ENABLED ? 'tor' : 'clearnet';
 | 
			
		||||
      if (this.currentSha === undefined) {
 | 
			
		||||
      if (this.currentSha === null) {
 | 
			
		||||
        logger.info(`Downloading pools-v2.json for the first time from ${this.poolsUrl} over ${network}`, logger.tags.mining);
 | 
			
		||||
      } else {
 | 
			
		||||
        logger.warn(`pools-v2.json is outdated, fetch latest from ${this.poolsUrl} over ${network}`, logger.tags.mining);
 | 
			
		||||
@ -82,7 +82,7 @@ class PoolsUpdater {
 | 
			
		||||
        logger.err(`Could not migrate mining pools, rolling back. Exception: ${JSON.stringify(e)}`, logger.tags.mining);
 | 
			
		||||
        await DB.query('ROLLBACK;');
 | 
			
		||||
      }
 | 
			
		||||
      logger.notice('PoolsUpdater completed');
 | 
			
		||||
      logger.info('PoolsUpdater completed');
 | 
			
		||||
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      this.lastRun = now - (oneWeek - oneDay); // Try again in 24h instead of waiting next week
 | 
			
		||||
@ -108,20 +108,20 @@ class PoolsUpdater {
 | 
			
		||||
  /**
 | 
			
		||||
   * Fetch our latest pools-v2.json sha from the db
 | 
			
		||||
   */
 | 
			
		||||
  private async getShaFromDb(): Promise<string | undefined> {
 | 
			
		||||
  private async getShaFromDb(): Promise<string | null> {
 | 
			
		||||
    try {
 | 
			
		||||
      const [rows]: any[] = await DB.query('SELECT string FROM state WHERE name="pools_json_sha"');
 | 
			
		||||
      return (rows.length > 0 ? rows[0].string : undefined);
 | 
			
		||||
      return (rows.length > 0 ? rows[0].string : null);
 | 
			
		||||
    } catch (e) {
 | 
			
		||||
      logger.err('Cannot fetch pools-v2.json sha from db. Reason: ' + (e instanceof Error ? e.message : e), logger.tags.mining);
 | 
			
		||||
      return undefined;
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Fetch our latest pools-v2.json sha from github
 | 
			
		||||
   */
 | 
			
		||||
  private async fetchPoolsSha(): Promise<string | undefined> {
 | 
			
		||||
  private async fetchPoolsSha(): Promise<string | null> {
 | 
			
		||||
    const response = await this.query(this.treeUrl);
 | 
			
		||||
 | 
			
		||||
    if (response !== undefined) {
 | 
			
		||||
@ -133,7 +133,7 @@ class PoolsUpdater {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    logger.err(`Cannot find "pools-v2.json" in git tree (${this.treeUrl})`, logger.tags.mining);
 | 
			
		||||
    return undefined;
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
 | 
			
		||||
@ -8,9 +8,6 @@ class BitfinexApi implements PriceFeed {
 | 
			
		||||
  public url: string = 'https://api.bitfinex.com/v1/pubticker/BTC';
 | 
			
		||||
  public urlHist: string = 'https://api-pub.bitfinex.com/v2/candles/trade:{GRANULARITY}:tBTC{CURRENCY}/hist';
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public async $fetchPrice(currency): Promise<number> {
 | 
			
		||||
    const response = await query(this.url + currency);
 | 
			
		||||
    if (response && response['last_price']) {
 | 
			
		||||
 | 
			
		||||
@ -98,7 +98,7 @@ class KrakenApi implements PriceFeed {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (Object.keys(priceHistory).length > 0) {
 | 
			
		||||
      logger.notice(`Inserted ${Object.keys(priceHistory).length} Kraken EUR, USD, GBP, JPY, CAD, CHF and AUD weekly price history into db`, logger.tags.mining);
 | 
			
		||||
      logger.info(`Inserted ${Object.keys(priceHistory).length} Kraken EUR, USD, GBP, JPY, CAD, CHF and AUD weekly price history into db`, logger.tags.mining);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -2,8 +2,7 @@ import * as fs from 'fs';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
import config from '../config';
 | 
			
		||||
import logger from '../logger';
 | 
			
		||||
import { IConversionRates } from '../mempool.interfaces';
 | 
			
		||||
import PricesRepository, { MAX_PRICES } from '../repositories/PricesRepository';
 | 
			
		||||
import PricesRepository, { ApiPrice, MAX_PRICES } from '../repositories/PricesRepository';
 | 
			
		||||
import BitfinexApi from './price-feeds/bitfinex-api';
 | 
			
		||||
import BitflyerApi from './price-feeds/bitflyer-api';
 | 
			
		||||
import CoinbaseApi from './price-feeds/coinbase-api';
 | 
			
		||||
@ -21,18 +20,18 @@ export interface PriceFeed {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface PriceHistory {
 | 
			
		||||
  [timestamp: number]: IConversionRates;
 | 
			
		||||
  [timestamp: number]: ApiPrice;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class PriceUpdater {
 | 
			
		||||
  public historyInserted = false;
 | 
			
		||||
  lastRun = 0;
 | 
			
		||||
  lastHistoricalRun = 0;
 | 
			
		||||
  running = false;
 | 
			
		||||
  feeds: PriceFeed[] = [];
 | 
			
		||||
  currencies: string[] = ['USD', 'EUR', 'GBP', 'CAD', 'CHF', 'AUD', 'JPY'];
 | 
			
		||||
  latestPrices: IConversionRates;
 | 
			
		||||
  private ratesChangedCallback: ((rates: IConversionRates) => void) | undefined;
 | 
			
		||||
  private lastRun = 0;
 | 
			
		||||
  private lastHistoricalRun = 0;
 | 
			
		||||
  private running = false;
 | 
			
		||||
  private feeds: PriceFeed[] = [];
 | 
			
		||||
  private currencies: string[] = ['USD', 'EUR', 'GBP', 'CAD', 'CHF', 'AUD', 'JPY'];
 | 
			
		||||
  private latestPrices: ApiPrice;
 | 
			
		||||
  private ratesChangedCallback: ((rates: ApiPrice) => void) | undefined;
 | 
			
		||||
 | 
			
		||||
  constructor() {
 | 
			
		||||
    this.latestPrices = this.getEmptyPricesObj();
 | 
			
		||||
@ -44,8 +43,13 @@ class PriceUpdater {
 | 
			
		||||
    this.feeds.push(new GeminiApi());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getEmptyPricesObj(): IConversionRates {
 | 
			
		||||
  public getLatestPrices(): ApiPrice {
 | 
			
		||||
    return this.latestPrices;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getEmptyPricesObj(): ApiPrice {
 | 
			
		||||
    return {
 | 
			
		||||
      time: 0,
 | 
			
		||||
      USD: -1,
 | 
			
		||||
      EUR: -1,
 | 
			
		||||
      GBP: -1,
 | 
			
		||||
@ -56,7 +60,7 @@ class PriceUpdater {
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public setRatesChangedCallback(fn: (rates: IConversionRates) => void) {
 | 
			
		||||
  public setRatesChangedCallback(fn: (rates: ApiPrice) => void): void {
 | 
			
		||||
    this.ratesChangedCallback = fn;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -156,6 +160,10 @@ class PriceUpdater {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.lastRun = new Date().getTime() / 1000;
 | 
			
		||||
 | 
			
		||||
    if (this.latestPrices.USD === -1) {
 | 
			
		||||
      this.latestPrices = await PricesRepository.$getLatestConversionRates();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
@ -224,7 +232,7 @@ class PriceUpdater {
 | 
			
		||||
 | 
			
		||||
    // Group them by timestamp and currency, for example
 | 
			
		||||
    // grouped[123456789]['USD'] = [1, 2, 3, 4];
 | 
			
		||||
    const grouped: any = {};
 | 
			
		||||
    const grouped = {};
 | 
			
		||||
    for (const historicalEntry of historicalPrices) {
 | 
			
		||||
      for (const time in historicalEntry) {
 | 
			
		||||
        if (existingPriceTimes.includes(parseInt(time, 10))) {
 | 
			
		||||
@ -249,7 +257,7 @@ class PriceUpdater {
 | 
			
		||||
    // Average prices and insert everything into the db
 | 
			
		||||
    let totalInserted = 0;
 | 
			
		||||
    for (const time in grouped) {
 | 
			
		||||
      const prices: IConversionRates = this.getEmptyPricesObj();
 | 
			
		||||
      const prices: ApiPrice = this.getEmptyPricesObj();
 | 
			
		||||
      for (const currency in grouped[time]) {
 | 
			
		||||
        if (grouped[time][currency].length === 0) {
 | 
			
		||||
          continue;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										29
									
								
								backend/src/utils/format.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								backend/src/utils/format.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
const byteUnits = ['B', 'kB', 'MB', 'GB', 'TB'];
 | 
			
		||||
 | 
			
		||||
export function getBytesUnit(bytes: number): string {
 | 
			
		||||
  if (isNaN(bytes) || !isFinite(bytes)) {
 | 
			
		||||
    return 'B';
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  let unitIndex = 0;
 | 
			
		||||
  while (unitIndex < byteUnits.length && bytes > 1024) {
 | 
			
		||||
    unitIndex++;
 | 
			
		||||
    bytes /= 1024;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return byteUnits[unitIndex];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function formatBytes(bytes: number, toUnit: string, skipUnit = false): string {
 | 
			
		||||
  if (isNaN(bytes) || !isFinite(bytes)) {
 | 
			
		||||
    return `${bytes}`;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  let unitIndex = 0;
 | 
			
		||||
  while (unitIndex < byteUnits.length && (toUnit && byteUnits[unitIndex] !== toUnit || (!toUnit && bytes > 1024))) {
 | 
			
		||||
    unitIndex++;
 | 
			
		||||
    bytes /= 1024;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  return `${bytes.toFixed(2)}${skipUnit ? '' : ' ' + byteUnits[unitIndex]}`;
 | 
			
		||||
}
 | 
			
		||||
@ -24,7 +24,7 @@
 | 
			
		||||
                <td>
 | 
			
		||||
                  ‎{{ block.time | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
                  <div class="lg-inline">
 | 
			
		||||
                    <i class="symbol">(<app-time-since [time]="block.time / 1000" [fastRender]="true"></app-time-since>)</i>
 | 
			
		||||
                    <i class="symbol">(<app-time kind="since" [time]="block.time / 1000" [fastRender]="true"></app-time>)</i>
 | 
			
		||||
                  </div>
 | 
			
		||||
                </td>
 | 
			
		||||
              </tr>
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
      <tbody *ngIf="blocks.value; else loadingTmpl">
 | 
			
		||||
        <tr *ngFor="let block of blocks.value[0]; trackBy: trackByFn">
 | 
			
		||||
          <td><a [routerLink]="['/block/' | relativeUrl, block.hash]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
 | 
			
		||||
          <td><app-time-since [time]="block.time / 1000" [fastRender]="true"></app-time-since></td>
 | 
			
		||||
          <td><app-time kind="since" [time]="block.time / 1000" [fastRender]="true"></app-time></td>
 | 
			
		||||
          <td>{{ calculateTotalOutput(block) / 100 | number: '1.2-2' }} <span class="symbol">BSQ</span></td>
 | 
			
		||||
          <td class="d-none d-md-block">{{ block.txs.length }}</td>
 | 
			
		||||
        </tr> 
 | 
			
		||||
 | 
			
		||||
@ -35,7 +35,7 @@
 | 
			
		||||
                  <td>
 | 
			
		||||
                    ‎{{ bisqTx.time | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
                    <div class="lg-inline">
 | 
			
		||||
                      <i class="symbol">(<app-time-since [time]="bisqTx.time / 1000" [fastRender]="true"></app-time-since>)</i>
 | 
			
		||||
                      <i class="symbol">(<app-time kind="since" [time]="bisqTx.time / 1000" [fastRender]="true"></app-time>)</i>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,7 @@
 | 
			
		||||
            {{ calculateTotalOutput(tx.outputs) / 100 | number: '1.2-2' }} <span class="d-none d-md-inline symbol">BSQ</span>
 | 
			
		||||
          </ng-template>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td><app-time-since [time]="tx.time / 1000" [fastRender]="true"></app-time-since></td>
 | 
			
		||||
        <td><app-time kind="since" [time]="tx.time / 1000" [fastRender]="true"></app-time></td>
 | 
			
		||||
        <td class="d-none d-md-block"><a [routerLink]="['/block/' | relativeUrl, tx.blockHash]" [state]="{ data: { blockHeight: tx.blockHeight } }">{{ tx.blockHeight }}</a></td>
 | 
			
		||||
      </tr>
 | 
			
		||||
    </tbody>
 | 
			
		||||
 | 
			
		||||
@ -3,13 +3,15 @@
 | 
			
		||||
    {{ addPlus && satoshis >= 0 ? '+' : '' }}
 | 
			
		||||
    {{
 | 
			
		||||
      (
 | 
			
		||||
        (blockConversion.price[currency] >= 0 ? blockConversion.price[currency] : null) ??
 | 
			
		||||
        (blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency]) ?? 0
 | 
			
		||||
        (blockConversion.price[currency] > -1 ? blockConversion.price[currency] : null) ??
 | 
			
		||||
        (blockConversion.price['USD']    > -1 ? blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency] : null) ?? 0
 | 
			
		||||
      ) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency
 | 
			
		||||
    }}
 | 
			
		||||
  </span>
 | 
			
		||||
  <ng-template #noblockconversion>
 | 
			
		||||
    <span class="fiat">{{ addPlus && satoshis >= 0 ? '+' : '' }}{{ (conversions ? conversions[currency] : 0) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency }}</span>
 | 
			
		||||
    <span class="fiat">{{ addPlus && satoshis >= 0 ? '+' : '' }}
 | 
			
		||||
      {{ (conversions[currency] > -1 ? conversions[currency] : 0) * satoshis / 100000000 | fiatCurrency : digitsInfo : currency }}
 | 
			
		||||
    </span>
 | 
			
		||||
  </ng-template>
 | 
			
		||||
</ng-container>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -54,31 +54,6 @@
 | 
			
		||||
  max-height: 270px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.disabled {
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
 | 
			
		||||
@ -54,31 +54,6 @@
 | 
			
		||||
  max-height: 270px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.disabled {
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
 | 
			
		||||
@ -54,31 +54,6 @@
 | 
			
		||||
  max-height: 270px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.disabled {
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
 | 
			
		||||
@ -54,31 +54,6 @@
 | 
			
		||||
  max-height: 270px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 1130px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 1130px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.disabled {
 | 
			
		||||
  pointer-events: none;
 | 
			
		||||
  opacity: 0.5;
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@
 | 
			
		||||
            <ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} transactions</ng-template>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div [attr.data-cy]="'bitcoin-block-' + offset + '-index-' + i + '-time'" class="time-difference">
 | 
			
		||||
            <app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since></div>
 | 
			
		||||
            <app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time></div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="animated" [class]="showMiningInfo ? 'show' : 'hide'" *ngIf="block.extras?.pool != undefined">
 | 
			
		||||
          <a [attr.data-cy]="'bitcoin-block-' + offset + '-index-' + i + '-pool'" class="badge badge-primary"
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@
 | 
			
		||||
            ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
 | 
			
		||||
            <app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since>
 | 
			
		||||
            <app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
 | 
			
		||||
            <a
 | 
			
		||||
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
        <td class="d-none d-md-block"><a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height
 | 
			
		||||
            }}</a></td>
 | 
			
		||||
        <td class="text-left">
 | 
			
		||||
          <app-time-since [time]="diffChange.timestamp" [fastRender]="true"></app-time-since>
 | 
			
		||||
          <app-time kind="since" [time]="diffChange.timestamp" [fastRender]="true"></app-time>
 | 
			
		||||
        </td>
 | 
			
		||||
        <td class="text-right">{{ diffChange.difficultyShorten }}</td>
 | 
			
		||||
        <td class="text-right" [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'">
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,7 @@
 | 
			
		||||
            <ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} <span class="shared-block">blocks</span></ng-template>
 | 
			
		||||
            <ng-template #blocksSingular let-i i18n="shared.block">{{ i }} <span class="shared-block">block</span></ng-template>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="symbol"><app-time-until [time]="epochData.estimatedRetargetDate" [fastRender]="true"></app-time-until></div>
 | 
			
		||||
          <div class="symbol"><app-time kind="until" [time]="epochData.estimatedRetargetDate" [fastRender]="true"></app-time></div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="item">
 | 
			
		||||
          <h5 class="card-title" i18n="difficulty-box.estimate">Estimate</h5>
 | 
			
		||||
@ -53,7 +53,7 @@
 | 
			
		||||
            <ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} <span class="shared-block">blocks</span></ng-template>
 | 
			
		||||
            <ng-template #blocksSingular let-i i18n="shared.block">{{ i }} <span class="shared-block">block</span></ng-template>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div class="symbol"><app-time-until [time]="epochData.timeUntilHalving" [fastRender]="true"></app-time-until></div>
 | 
			
		||||
          <div class="symbol"><app-time kind="until" [time]="epochData.timeUntilHalving" [fastRender]="true"></app-time></div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
@ -1,10 +1,9 @@
 | 
			
		||||
<div *ngIf="stateService.env.MINING_DASHBOARD || stateService.env.LIGHTNING" class="mb-3 d-flex menu"
 | 
			
		||||
  style="padding: 0px 35px;">
 | 
			
		||||
<div *ngIf="stateService.env.MINING_DASHBOARD || stateService.env.LIGHTNING" class="mb-3 d-flex menu">
 | 
			
		||||
 | 
			
		||||
  <a routerLinkActive="active" class="btn btn-primary mr-1" [class]="padding"
 | 
			
		||||
  <a routerLinkActive="active" class="btn btn-primary" [class]="padding"
 | 
			
		||||
    [routerLink]="['/graphs/mempool' | relativeUrl]">Mempool</a>
 | 
			
		||||
 | 
			
		||||
  <div ngbDropdown class="mr-1" [class]="padding" *ngIf="stateService.env.MINING_DASHBOARD">
 | 
			
		||||
  <div ngbDropdown [class]="padding" *ngIf="stateService.env.MINING_DASHBOARD">
 | 
			
		||||
    <button class="btn btn-primary w-100" id="dropdownBasic1" ngbDropdownToggle i18n="mining">Mining</button>
 | 
			
		||||
    <div ngbDropdownMenu aria-labelledby="dropdownBasic1">
 | 
			
		||||
      <a class="dropdown-item" routerLinkActive="active" [routerLink]="['/graphs/mining/pools' | relativeUrl]"
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,15 @@
 | 
			
		||||
.menu {
 | 
			
		||||
  flex-grow: 1;
 | 
			
		||||
  padding: 0 35px;
 | 
			
		||||
  @media (min-width: 576px) {
 | 
			
		||||
    max-width: 400px;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  & > * {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    margin-inline-end: 0.25rem;
 | 
			
		||||
    &.last-child {
 | 
			
		||||
      margin-inline-end: 0;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -54,31 +54,6 @@
 | 
			
		||||
  height: 240px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pool-distribution {
 | 
			
		||||
  min-height: 56px;
 | 
			
		||||
  display: block;
 | 
			
		||||
 | 
			
		||||
@ -48,31 +48,6 @@
 | 
			
		||||
  max-height: 293px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.loadingGraphs {
 | 
			
		||||
  position: absolute;
 | 
			
		||||
  top: 50%;
 | 
			
		||||
 | 
			
		||||
@ -23,10 +23,10 @@
 | 
			
		||||
            </div>
 | 
			
		||||
            <div [attr.data-cy]="'mempool-block-' + i + '-time'" class="time-difference" *ngIf="projectedBlock.blockVSize <= stateService.blockVSize; else mergedBlock">
 | 
			
		||||
              <ng-template [ngIf]="network === 'liquid' || network === 'liquidtestnet'" [ngIfElse]="timeDiffMainnet">
 | 
			
		||||
                <app-time-until [time]="(1 * i) + now + 61000" [fastRender]="false" [fixedRender]="true"></app-time-until>
 | 
			
		||||
                <app-time kind="until" [time]="(1 * i) + now + 61000" [fastRender]="false" [fixedRender]="true"></app-time>
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <ng-template #timeDiffMainnet>
 | 
			
		||||
                <app-time-until [time]="da.timeAvg * (i + 1) + now + da.timeOffset" [fastRender]="false" [fixedRender]="true" [forceFloorOnTimeIntervals]="['hour']"></app-time-until>
 | 
			
		||||
                <app-time kind="until" [time]="da.timeAvg * (i + 1) + now + da.timeOffset" [fastRender]="false" [fixedRender]="true" [forceFloorOnTimeIntervals]="['hour']"></app-time>
 | 
			
		||||
              </ng-template>
 | 
			
		||||
            </div>
 | 
			
		||||
            <ng-template #mergedBlock>
 | 
			
		||||
 | 
			
		||||
@ -33,31 +33,6 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bottom-padding {
 | 
			
		||||
  @media (max-width: 992px) {
 | 
			
		||||
    padding-bottom: 65px
 | 
			
		||||
 | 
			
		||||
@ -227,7 +227,7 @@
 | 
			
		||||
            ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="mined">
 | 
			
		||||
            <app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since>
 | 
			
		||||
            <app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time>
 | 
			
		||||
          </td>
 | 
			
		||||
          <td class="coinbase">
 | 
			
		||||
            <span class="badge badge-secondary scriptmessage longer">
 | 
			
		||||
 | 
			
		||||
@ -25,6 +25,12 @@
 | 
			
		||||
      </defs>
 | 
			
		||||
    </svg>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
  <ng-container *ngSwitchCase="'warning'">
 | 
			
		||||
    <svg [class]="class" [style]="style" [attr.width]="width" [attr.height]="height" [attr.viewBox]="viewBox" fill="none" xmlns="http://www.w3.org/2000/svg">  
 | 
			
		||||
      <path d="M135.3 34.474c-15.62 27.306-54.206 95.63-85.21 150.534L9.075 257.583C5.382 264.08 6.76 269.217 7.908 271.7c2.326 5.028 7.29 7.537 11.155 8.215l.78.133 264.698.006-.554-.02c4.152.255 9.664-1.24 12.677-6.194 1.926-3.18 3.31-8.589-1.073-16.278L213.637 114.37l-45.351-79.205c-5.681-9.932-12.272-12.022-16.8-12.022-4.42 0-10.818 1.964-16.181 11.331h-.006zm-69.072 159.94c30.997-54.885 69.563-123.184 85.16-150.446l.186-.297c.2.303.393.582.618.981l45.363 79.22s72.377 126.47 78.569 137.283l-247.618-.007 37.719-66.734" style="fill:#ffc107;fill-opacity:1"/>
 | 
			
		||||
      <path d="M152.597 247.445c8.02 0 14.518-6.728 14.518-15.025 0-8.29-6.499-15.018-14.518-15.018-8.031 0-14.529 6.728-14.529 15.018 0 8.297 6.498 15.025 14.53 15.025m-.001-147.18c11.586 0 22.23 10.958 20.977 21.7l-9.922 75.564c-.966 6.601-4.95 11.433-11.055 11.433s-10.102-4.832-11.056-11.433l-9.927-75.564c-1.26-10.742 9.39-21.7 20.983-21.7" style="fill:#ffc107;fill-opacity:1"/>
 | 
			
		||||
    </svg>
 | 
			
		||||
  </ng-container>
 | 
			
		||||
  <ng-container *ngSwitchCase="'mempoolSpace'">
 | 
			
		||||
    <svg [class]="class" [style]="style" [attr.width]="width" [attr.height]="height" [attr.viewBox]="viewBox" fill="none" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
      <path d="M 219.548 86.198 L 219.548 63.833 C 219.548 60.359 218.746 57.686 217.163 55.919 C 215.601 54.151 213.237 53.267 210.195 53.267 C 206.762 53.267 203.946 54.377 202.013 56.453 C 200.081 58.55 199.053 61.633 199.053 65.395 L 199.053 86.219 L 191.447 86.219 L 191.447 63.833 C 191.447 56.823 188.282 53.267 182.032 53.267 C 178.6 53.267 175.783 54.377 173.851 56.453 C 171.919 58.55 170.891 61.633 170.891 65.395 L 170.891 86.219 L 163.285 86.219 L 163.285 46.422 L 170.685 46.422 L 170.685 50.759 C 173.687 47.799 178.003 46.175 182.999 46.175 C 188.96 46.175 193.667 48.498 196.36 52.753 C 199.608 48.559 204.85 46.175 210.955 46.175 C 215.93 46.175 219.877 47.614 222.693 50.43 C 225.632 53.39 227.174 57.871 227.154 63.36 L 227.154 86.198 L 219.548 86.198 Z" fill="white"/>
 | 
			
		||||
@ -104,4 +110,4 @@
 | 
			
		||||
      </g>
 | 
			
		||||
    </g>
 | 
			
		||||
  </svg>
 | 
			
		||||
</ng-template>
 | 
			
		||||
</ng-template>
 | 
			
		||||
 | 
			
		||||
@ -13,4 +13,5 @@ export class SvgImagesComponent {
 | 
			
		||||
  @Input() width: string;
 | 
			
		||||
  @Input() height: string;
 | 
			
		||||
  @Input() viewBox: string;
 | 
			
		||||
  @Input() fill: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,98 +0,0 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { dates } from '../../shared/i18n/dates';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-time-since',
 | 
			
		||||
  template: `{{ text }}`,
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush
 | 
			
		||||
})
 | 
			
		||||
export class TimeSinceComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  interval: number;
 | 
			
		||||
  text: string;
 | 
			
		||||
  intervals = {};
 | 
			
		||||
 | 
			
		||||
  @Input() time: number;
 | 
			
		||||
  @Input() dateString: number;
 | 
			
		||||
  @Input() fastRender = false;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private ref: ChangeDetectorRef,
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
  ) {
 | 
			
		||||
      this.intervals = {
 | 
			
		||||
        year: 31536000,
 | 
			
		||||
        month: 2592000,
 | 
			
		||||
        week: 604800,
 | 
			
		||||
        day: 86400,
 | 
			
		||||
        hour: 3600,
 | 
			
		||||
        minute: 60,
 | 
			
		||||
        second: 1
 | 
			
		||||
      };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    if (!this.stateService.isBrowser) {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.interval = window.setInterval(() => {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
    }, 1000 * (this.fastRender ? 1 : 60));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.text = this.calculate();
 | 
			
		||||
    this.ref.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    clearInterval(this.interval);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculate() {
 | 
			
		||||
    let date: Date;
 | 
			
		||||
    if (this.dateString) {
 | 
			
		||||
      date = new Date(this.dateString)
 | 
			
		||||
    } else {
 | 
			
		||||
      date = new Date(this.time * 1000);
 | 
			
		||||
    }
 | 
			
		||||
    const seconds = Math.floor((+new Date() - +date) / 1000);
 | 
			
		||||
    if (seconds < 60) {
 | 
			
		||||
      return $localize`:@@date-base.just-now:Just now`;
 | 
			
		||||
    }
 | 
			
		||||
    let counter: number;
 | 
			
		||||
    for (const i in this.intervals) {
 | 
			
		||||
      if (this.intervals.hasOwnProperty(i)) {
 | 
			
		||||
        counter = Math.floor(seconds / this.intervals[i]);
 | 
			
		||||
        const dateStrings = dates(counter);
 | 
			
		||||
        if (counter > 0) {
 | 
			
		||||
          if (counter === 1) {
 | 
			
		||||
            switch (i) { // singular (1 day)
 | 
			
		||||
              case 'year': return $localize`:@@time-since:${dateStrings.i18nYear}:DATE: ago`; break;
 | 
			
		||||
              case 'month': return $localize`:@@time-since:${dateStrings.i18nMonth}:DATE: ago`; break;
 | 
			
		||||
              case 'week': return $localize`:@@time-since:${dateStrings.i18nWeek}:DATE: ago`; break;
 | 
			
		||||
              case 'day': return $localize`:@@time-since:${dateStrings.i18nDay}:DATE: ago`; break;
 | 
			
		||||
              case 'hour': return $localize`:@@time-since:${dateStrings.i18nHour}:DATE: ago`; break;
 | 
			
		||||
              case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinute}:DATE: ago`; break;
 | 
			
		||||
              case 'second': return $localize`:@@time-since:${dateStrings.i18nSecond}:DATE: ago`; break;
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            switch (i) { // plural (2 days)
 | 
			
		||||
              case 'year': return $localize`:@@time-since:${dateStrings.i18nYears}:DATE: ago`; break;
 | 
			
		||||
              case 'month': return $localize`:@@time-since:${dateStrings.i18nMonths}:DATE: ago`; break;
 | 
			
		||||
              case 'week': return $localize`:@@time-since:${dateStrings.i18nWeeks}:DATE: ago`; break;
 | 
			
		||||
              case 'day': return $localize`:@@time-since:${dateStrings.i18nDays}:DATE: ago`; break;
 | 
			
		||||
              case 'hour': return $localize`:@@time-since:${dateStrings.i18nHours}:DATE: ago`; break;
 | 
			
		||||
              case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinutes}:DATE: ago`; break;
 | 
			
		||||
              case 'second': return $localize`:@@time-since:${dateStrings.i18nSeconds}:DATE: ago`; break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,91 +0,0 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { dates } from '../../shared/i18n/dates';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-time-span',
 | 
			
		||||
  template: `{{ text }}`,
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush
 | 
			
		||||
})
 | 
			
		||||
export class TimeSpanComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  interval: number;
 | 
			
		||||
  text: string;
 | 
			
		||||
  intervals = {};
 | 
			
		||||
 | 
			
		||||
  @Input() time: number;
 | 
			
		||||
  @Input() fastRender = false;
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private ref: ChangeDetectorRef,
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
  ) {
 | 
			
		||||
      this.intervals = {
 | 
			
		||||
        year: 31536000,
 | 
			
		||||
        month: 2592000,
 | 
			
		||||
        week: 604800,
 | 
			
		||||
        day: 86400,
 | 
			
		||||
        hour: 3600,
 | 
			
		||||
        minute: 60,
 | 
			
		||||
        second: 1
 | 
			
		||||
      };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    if (!this.stateService.isBrowser) {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.interval = window.setInterval(() => {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
    }, 1000 * (this.fastRender ? 1 : 60));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.text = this.calculate();
 | 
			
		||||
    this.ref.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    clearInterval(this.interval);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculate() {
 | 
			
		||||
    const seconds = Math.floor(this.time);
 | 
			
		||||
    if (seconds < 60) {
 | 
			
		||||
      return $localize`:@@date-base.just-now:Just now`;
 | 
			
		||||
    }
 | 
			
		||||
    let counter: number;
 | 
			
		||||
    for (const i in this.intervals) {
 | 
			
		||||
      if (this.intervals.hasOwnProperty(i)) {
 | 
			
		||||
        counter = Math.floor(seconds / this.intervals[i]);
 | 
			
		||||
        const dateStrings = dates(counter);
 | 
			
		||||
        if (counter > 0) {
 | 
			
		||||
          if (counter === 1) {
 | 
			
		||||
            switch (i) { // singular (1 day)
 | 
			
		||||
              case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYear}:DATE:`; break;
 | 
			
		||||
              case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonth}:DATE:`; break;
 | 
			
		||||
              case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeek}:DATE:`; break;
 | 
			
		||||
              case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDay}:DATE:`; break;
 | 
			
		||||
              case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHour}:DATE:`; break;
 | 
			
		||||
              case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinute}:DATE:`; break;
 | 
			
		||||
              case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSecond}:DATE:`; break;
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            switch (i) { // plural (2 days)
 | 
			
		||||
              case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYears}:DATE:`; break;
 | 
			
		||||
              case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonths}:DATE:`; break;
 | 
			
		||||
              case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeeks}:DATE:`; break;
 | 
			
		||||
              case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDays}:DATE:`; break;
 | 
			
		||||
              case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHours}:DATE:`; break;
 | 
			
		||||
              case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinutes}:DATE:`; break;
 | 
			
		||||
              case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSeconds}:DATE:`; break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -1,104 +0,0 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { dates } from '../../shared/i18n/dates';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-time-until',
 | 
			
		||||
  template: `{{ text }}`,
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush
 | 
			
		||||
})
 | 
			
		||||
export class TimeUntilComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  interval: number;
 | 
			
		||||
  text: string;
 | 
			
		||||
  intervals = {};
 | 
			
		||||
 | 
			
		||||
  @Input() time: number;
 | 
			
		||||
  @Input() fastRender = false;
 | 
			
		||||
  @Input() fixedRender = false;
 | 
			
		||||
  @Input() forceFloorOnTimeIntervals: string[];
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private ref: ChangeDetectorRef,
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
  ) {
 | 
			
		||||
      this.intervals = {
 | 
			
		||||
        year: 31536000,
 | 
			
		||||
        month: 2592000,
 | 
			
		||||
        week: 604800,
 | 
			
		||||
        day: 86400,
 | 
			
		||||
        hour: 3600,
 | 
			
		||||
        minute: 60,
 | 
			
		||||
        second: 1
 | 
			
		||||
      };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    if(this.fixedRender){
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    if (!this.stateService.isBrowser) {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.interval = window.setInterval(() => {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
    }, 1000 * (this.fastRender ? 1 : 60));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.text = this.calculate();
 | 
			
		||||
    this.ref.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    clearInterval(this.interval);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculate() {
 | 
			
		||||
    const seconds = (+new Date(this.time) - +new Date()) / 1000;
 | 
			
		||||
 | 
			
		||||
    if (seconds < 60) {
 | 
			
		||||
      const dateStrings = dates(1);
 | 
			
		||||
      return $localize`:@@time-until:In ~${dateStrings.i18nMinute}:DATE:`;
 | 
			
		||||
    }
 | 
			
		||||
    let counter: number;
 | 
			
		||||
    for (const i in this.intervals) {
 | 
			
		||||
      if (this.intervals.hasOwnProperty(i)) {
 | 
			
		||||
        if (this.forceFloorOnTimeIntervals && this.forceFloorOnTimeIntervals.indexOf(i) > -1) {
 | 
			
		||||
          counter = Math.floor(seconds / this.intervals[i]);
 | 
			
		||||
        } else {
 | 
			
		||||
          counter = Math.round(seconds / this.intervals[i]);
 | 
			
		||||
        }
 | 
			
		||||
        const dateStrings = dates(counter);
 | 
			
		||||
        if (counter > 0) {
 | 
			
		||||
          if (counter === 1) {
 | 
			
		||||
            switch (i) { // singular (In ~1 day)
 | 
			
		||||
              case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYear}:DATE:`; break;
 | 
			
		||||
              case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonth}:DATE:`; break;
 | 
			
		||||
              case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeek}:DATE:`; break;
 | 
			
		||||
              case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDay}:DATE:`; break;
 | 
			
		||||
              case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHour}:DATE:`; break;
 | 
			
		||||
              case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinute}:DATE:`;
 | 
			
		||||
              case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSecond}:DATE:`;
 | 
			
		||||
            }
 | 
			
		||||
          } else {
 | 
			
		||||
            switch (i) { // plural (In ~2 days)
 | 
			
		||||
              case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYears}:DATE:`; break;
 | 
			
		||||
              case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonths}:DATE:`; break;
 | 
			
		||||
              case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeeks}:DATE:`; break;
 | 
			
		||||
              case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDays}:DATE:`; break;
 | 
			
		||||
              case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHours}:DATE:`; break;
 | 
			
		||||
              case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinutes}:DATE:`; break;
 | 
			
		||||
              case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSeconds}:DATE:`; break;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										190
									
								
								frontend/src/app/components/time/time.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								frontend/src/app/components/time/time.component.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,190 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { dates } from '../../shared/i18n/dates';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-time',
 | 
			
		||||
  template: `{{ text }}`,
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush
 | 
			
		||||
})
 | 
			
		||||
export class TimeComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
  interval: number;
 | 
			
		||||
  text: string;
 | 
			
		||||
  intervals = {};
 | 
			
		||||
 | 
			
		||||
  @Input() time: number;
 | 
			
		||||
  @Input() dateString: number;
 | 
			
		||||
  @Input() kind: 'plain' | 'since' | 'until' | 'span' = 'plain';
 | 
			
		||||
  @Input() fastRender = false;
 | 
			
		||||
  @Input() fixedRender = false;
 | 
			
		||||
  @Input() relative = false;
 | 
			
		||||
  @Input() forceFloorOnTimeIntervals: string[];
 | 
			
		||||
 | 
			
		||||
  constructor(
 | 
			
		||||
    private ref: ChangeDetectorRef,
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
  ) {
 | 
			
		||||
      this.intervals = {
 | 
			
		||||
        year: 31536000,
 | 
			
		||||
        month: 2592000,
 | 
			
		||||
        week: 604800,
 | 
			
		||||
        day: 86400,
 | 
			
		||||
        hour: 3600,
 | 
			
		||||
        minute: 60,
 | 
			
		||||
        second: 1
 | 
			
		||||
      };
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
    if(this.fixedRender){
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.stateService.isBrowser) {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    this.interval = window.setInterval(() => {
 | 
			
		||||
      this.text = this.calculate();
 | 
			
		||||
      this.ref.markForCheck();
 | 
			
		||||
    }, 1000 * (this.fastRender ? 1 : 60));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnChanges() {
 | 
			
		||||
    this.text = this.calculate();
 | 
			
		||||
    this.ref.markForCheck();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngOnDestroy() {
 | 
			
		||||
    clearInterval(this.interval);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  calculate() {
 | 
			
		||||
    let seconds: number;
 | 
			
		||||
    switch (this.kind) {
 | 
			
		||||
      case 'since':
 | 
			
		||||
        seconds = Math.floor((+new Date() - +new Date(this.dateString || this.time * 1000)) / 1000);
 | 
			
		||||
        break;
 | 
			
		||||
      case 'until':
 | 
			
		||||
        seconds = (+new Date(this.time) - +new Date()) / 1000;
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        seconds = Math.floor(this.time);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (seconds < 60) {
 | 
			
		||||
      if (this.relative || this.kind === 'since') {
 | 
			
		||||
        return $localize`:@@date-base.just-now:Just now`;
 | 
			
		||||
      } else if (this.kind === 'until') {
 | 
			
		||||
        seconds = 60;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let counter: number;
 | 
			
		||||
    for (const i in this.intervals) {
 | 
			
		||||
      if (this.kind !== 'until' || this.forceFloorOnTimeIntervals && this.forceFloorOnTimeIntervals.indexOf(i) > -1) {
 | 
			
		||||
        counter = Math.floor(seconds / this.intervals[i]);
 | 
			
		||||
      } else {
 | 
			
		||||
        counter = Math.round(seconds / this.intervals[i]);
 | 
			
		||||
      }
 | 
			
		||||
      const dateStrings = dates(counter);
 | 
			
		||||
      if (counter > 0) {
 | 
			
		||||
        switch (this.kind) {
 | 
			
		||||
          case 'since':
 | 
			
		||||
            if (counter === 1) {
 | 
			
		||||
              switch (i) { // singular (1 day)
 | 
			
		||||
                case 'year': return $localize`:@@time-since:${dateStrings.i18nYear}:DATE: ago`; break;
 | 
			
		||||
                case 'month': return $localize`:@@time-since:${dateStrings.i18nMonth}:DATE: ago`; break;
 | 
			
		||||
                case 'week': return $localize`:@@time-since:${dateStrings.i18nWeek}:DATE: ago`; break;
 | 
			
		||||
                case 'day': return $localize`:@@time-since:${dateStrings.i18nDay}:DATE: ago`; break;
 | 
			
		||||
                case 'hour': return $localize`:@@time-since:${dateStrings.i18nHour}:DATE: ago`; break;
 | 
			
		||||
                case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinute}:DATE: ago`; break;
 | 
			
		||||
                case 'second': return $localize`:@@time-since:${dateStrings.i18nSecond}:DATE: ago`; break;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              switch (i) { // plural (2 days)
 | 
			
		||||
                case 'year': return $localize`:@@time-since:${dateStrings.i18nYears}:DATE: ago`; break;
 | 
			
		||||
                case 'month': return $localize`:@@time-since:${dateStrings.i18nMonths}:DATE: ago`; break;
 | 
			
		||||
                case 'week': return $localize`:@@time-since:${dateStrings.i18nWeeks}:DATE: ago`; break;
 | 
			
		||||
                case 'day': return $localize`:@@time-since:${dateStrings.i18nDays}:DATE: ago`; break;
 | 
			
		||||
                case 'hour': return $localize`:@@time-since:${dateStrings.i18nHours}:DATE: ago`; break;
 | 
			
		||||
                case 'minute': return $localize`:@@time-since:${dateStrings.i18nMinutes}:DATE: ago`; break;
 | 
			
		||||
                case 'second': return $localize`:@@time-since:${dateStrings.i18nSeconds}:DATE: ago`; break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          case 'until':
 | 
			
		||||
            if (counter === 1) {
 | 
			
		||||
              switch (i) { // singular (In ~1 day)
 | 
			
		||||
                case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYear}:DATE:`; break;
 | 
			
		||||
                case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonth}:DATE:`; break;
 | 
			
		||||
                case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeek}:DATE:`; break;
 | 
			
		||||
                case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDay}:DATE:`; break;
 | 
			
		||||
                case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHour}:DATE:`; break;
 | 
			
		||||
                case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinute}:DATE:`;
 | 
			
		||||
                case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSecond}:DATE:`;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              switch (i) { // plural (In ~2 days)
 | 
			
		||||
                case 'year': return $localize`:@@time-until:In ~${dateStrings.i18nYears}:DATE:`; break;
 | 
			
		||||
                case 'month': return $localize`:@@time-until:In ~${dateStrings.i18nMonths}:DATE:`; break;
 | 
			
		||||
                case 'week': return $localize`:@@time-until:In ~${dateStrings.i18nWeeks}:DATE:`; break;
 | 
			
		||||
                case 'day': return $localize`:@@time-until:In ~${dateStrings.i18nDays}:DATE:`; break;
 | 
			
		||||
                case 'hour': return $localize`:@@time-until:In ~${dateStrings.i18nHours}:DATE:`; break;
 | 
			
		||||
                case 'minute': return $localize`:@@time-until:In ~${dateStrings.i18nMinutes}:DATE:`; break;
 | 
			
		||||
                case 'second': return $localize`:@@time-until:In ~${dateStrings.i18nSeconds}:DATE:`; break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          case 'span':
 | 
			
		||||
            if (counter === 1) {
 | 
			
		||||
              switch (i) { // singular (1 day)
 | 
			
		||||
                case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYear}:DATE:`; break;
 | 
			
		||||
                case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonth}:DATE:`; break;
 | 
			
		||||
                case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeek}:DATE:`; break;
 | 
			
		||||
                case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDay}:DATE:`; break;
 | 
			
		||||
                case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHour}:DATE:`; break;
 | 
			
		||||
                case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinute}:DATE:`; break;
 | 
			
		||||
                case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSecond}:DATE:`; break;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              switch (i) { // plural (2 days)
 | 
			
		||||
                case 'year': return $localize`:@@time-span:After ${dateStrings.i18nYears}:DATE:`; break;
 | 
			
		||||
                case 'month': return $localize`:@@time-span:After ${dateStrings.i18nMonths}:DATE:`; break;
 | 
			
		||||
                case 'week': return $localize`:@@time-span:After ${dateStrings.i18nWeeks}:DATE:`; break;
 | 
			
		||||
                case 'day': return $localize`:@@time-span:After ${dateStrings.i18nDays}:DATE:`; break;
 | 
			
		||||
                case 'hour': return $localize`:@@time-span:After ${dateStrings.i18nHours}:DATE:`; break;
 | 
			
		||||
                case 'minute': return $localize`:@@time-span:After ${dateStrings.i18nMinutes}:DATE:`; break;
 | 
			
		||||
                case 'second': return $localize`:@@time-span:After ${dateStrings.i18nSeconds}:DATE:`; break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
          default:
 | 
			
		||||
            if (counter === 1) {
 | 
			
		||||
              switch (i) { // singular (1 day)
 | 
			
		||||
                case 'year': return dateStrings.i18nYear; break;
 | 
			
		||||
                case 'month': return dateStrings.i18nMonth; break;
 | 
			
		||||
                case 'week': return dateStrings.i18nWeek; break;
 | 
			
		||||
                case 'day': return dateStrings.i18nDay; break;
 | 
			
		||||
                case 'hour': return dateStrings.i18nHour; break;
 | 
			
		||||
                case 'minute': return dateStrings.i18nMinute; break;
 | 
			
		||||
                case 'second': return dateStrings.i18nSecond; break;
 | 
			
		||||
              }
 | 
			
		||||
            } else {
 | 
			
		||||
              switch (i) { // plural (2 days)
 | 
			
		||||
                case 'year': return dateStrings.i18nYears; break;
 | 
			
		||||
                case 'month': return dateStrings.i18nMonths; break;
 | 
			
		||||
                case 'week': return dateStrings.i18nWeeks; break;
 | 
			
		||||
                case 'day': return dateStrings.i18nDays; break;
 | 
			
		||||
                case 'hour': return dateStrings.i18nHours; break;
 | 
			
		||||
                case 'minute': return dateStrings.i18nMinutes; break;
 | 
			
		||||
                case 'second': return dateStrings.i18nSeconds; break;
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -57,14 +57,14 @@
 | 
			
		||||
                  <td>
 | 
			
		||||
                    ‎{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
                    <div class="lg-inline">
 | 
			
		||||
                      <i class="symbol">(<app-time-since [time]="tx.status.block_time" [fastRender]="true"></app-time-since>)</i>
 | 
			
		||||
                      <i class="symbol">(<app-time kind="since" [time]="tx.status.block_time" [fastRender]="true"></app-time>)</i>
 | 
			
		||||
                    </div>
 | 
			
		||||
                  </td>
 | 
			
		||||
                </tr>
 | 
			
		||||
                <ng-template [ngIf]="transactionTime > 0">
 | 
			
		||||
                  <tr>
 | 
			
		||||
                    <td i18n="transaction.confirmed|Transaction Confirmed state">Confirmed</td>
 | 
			
		||||
                    <td><app-time-span [time]="tx.status.block_time - transactionTime" [fastRender]="true"></app-time-span></td>
 | 
			
		||||
                    <td><app-time kind="span" [time]="tx.status.block_time - transactionTime" [fastRender]="true" [relative]="true"></app-time></td>
 | 
			
		||||
                  </tr>
 | 
			
		||||
                </ng-template>
 | 
			
		||||
                <tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
 | 
			
		||||
@ -100,7 +100,7 @@
 | 
			
		||||
                  <ng-template #firstSeenTmpl>
 | 
			
		||||
                    <tr>
 | 
			
		||||
                      <td i18n="transaction.first-seen|Transaction first seen">First seen</td>
 | 
			
		||||
                      <td><i><app-time-since [time]="transactionTime" [fastRender]="true"></app-time-since></i></td>
 | 
			
		||||
                      <td><i><app-time kind="since" [time]="transactionTime" [fastRender]="true"></app-time></i></td>
 | 
			
		||||
                    </tr>
 | 
			
		||||
                  </ng-template>
 | 
			
		||||
                </ng-template>
 | 
			
		||||
@ -116,10 +116,10 @@
 | 
			
		||||
                      </ng-template>
 | 
			
		||||
                      <ng-template #belowBlockLimit>
 | 
			
		||||
                        <ng-template [ngIf]="network === 'liquid' || network === 'liquidtestnet'" [ngIfElse]="timeEstimateDefault">
 | 
			
		||||
                          <app-time-until [time]="(60 * 1000 * txInBlockIndex) + now" [fastRender]="false" [fixedRender]="true"></app-time-until>
 | 
			
		||||
                          <app-time kind="until" [time]="(60 * 1000 * txInBlockIndex) + now" [fastRender]="false" [fixedRender]="true"></app-time>
 | 
			
		||||
                        </ng-template>
 | 
			
		||||
                        <ng-template #timeEstimateDefault>
 | 
			
		||||
                          <app-time-until *ngIf="(timeAvg$ | async) as timeAvg;" [time]="(timeAvg * txInBlockIndex) + now + timeAvg" [fastRender]="false" [fixedRender]="true" [forceFloorOnTimeIntervals]="['hour']"></app-time-until>
 | 
			
		||||
                          <app-time kind="until" *ngIf="(timeAvg$ | async) as timeAvg;" [time]="(timeAvg * txInBlockIndex) + now + timeAvg" [fastRender]="false" [fixedRender]="true" [forceFloorOnTimeIntervals]="['hour']"></app-time>
 | 
			
		||||
                        </ng-template>
 | 
			
		||||
                      </ng-template>
 | 
			
		||||
                    </ng-template>
 | 
			
		||||
@ -210,6 +210,7 @@
 | 
			
		||||
        <div class="graph-container" #graphContainer>
 | 
			
		||||
          <tx-bowtie-graph
 | 
			
		||||
            [tx]="tx"
 | 
			
		||||
            [cached]="isCached"
 | 
			
		||||
            [width]="graphWidth"
 | 
			
		||||
            [height]="graphHeight"
 | 
			
		||||
            [lineLimit]="inOutLimit"
 | 
			
		||||
@ -250,7 +251,7 @@
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    <app-transactions-list #txList [transactions]="[tx]" [errorUnblinded]="errorUnblinded" [inputIndex]="inputIndex" [outputIndex]="outputIndex" [transactionPage]="true"></app-transactions-list>
 | 
			
		||||
    <app-transactions-list #txList [transactions]="[tx]" [cached]="isCached" [errorUnblinded]="errorUnblinded" [inputIndex]="inputIndex" [outputIndex]="outputIndex" [transactionPage]="true"></app-transactions-list>
 | 
			
		||||
 | 
			
		||||
    <div class="title text-left">
 | 
			
		||||
      <h2 i18n="transaction.details">Details</h2>
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
  fetchCpfp$ = new Subject<string>();
 | 
			
		||||
  fetchRbfHistory$ = new Subject<string>();
 | 
			
		||||
  fetchCachedTx$ = new Subject<string>();
 | 
			
		||||
  isCached: boolean = false;
 | 
			
		||||
  now = new Date().getTime();
 | 
			
		||||
  timeAvg$: Observable<number>;
 | 
			
		||||
  liquidUnblinding = new LiquidUnblinding();
 | 
			
		||||
@ -196,6 +197,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      this.tx = tx;
 | 
			
		||||
      this.isCached = true;
 | 
			
		||||
      if (tx.fee === undefined) {
 | 
			
		||||
        this.tx.fee = 0;
 | 
			
		||||
      }
 | 
			
		||||
@ -289,6 +291,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          this.tx = tx;
 | 
			
		||||
          this.isCached = false;
 | 
			
		||||
          if (tx.fee === undefined) {
 | 
			
		||||
            this.tx.fee = 0;
 | 
			
		||||
          }
 | 
			
		||||
@ -362,7 +365,6 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
			
		||||
        this.waitingForTransaction = false;
 | 
			
		||||
      }
 | 
			
		||||
      this.rbfTransaction = rbfTransaction;
 | 
			
		||||
      this.cacheService.setTxCache([this.rbfTransaction]);
 | 
			
		||||
      this.replaced = true;
 | 
			
		||||
      if (rbfTransaction && !this.tx) {
 | 
			
		||||
        this.fetchCachedTx$.next(this.txId);
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@
 | 
			
		||||
    <div>
 | 
			
		||||
      <ng-template [ngIf]="tx.status.confirmed">‎{{ tx.status.block_time * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-template>
 | 
			
		||||
      <ng-template [ngIf]="!tx.status.confirmed && tx.firstSeen">
 | 
			
		||||
        <i><app-time-since [time]="tx.firstSeen" [fastRender]="true"></app-time-since></i>
 | 
			
		||||
        <i><app-time kind="since" [time]="tx.firstSeen" [fastRender]="true"></app-time></i>
 | 
			
		||||
      </ng-template>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { Component, OnInit, Input, ChangeDetectionStrategy, OnChanges, Output, EventEmitter, ChangeDetectorRef } from '@angular/core';
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { CacheService } from '../../services/cache.service';
 | 
			
		||||
import { Observable, ReplaySubject, BehaviorSubject, merge, Subscription } from 'rxjs';
 | 
			
		||||
import { Observable, ReplaySubject, BehaviorSubject, merge, Subscription, of } from 'rxjs';
 | 
			
		||||
import { Outspend, Transaction, Vin, Vout } from '../../interfaces/electrs.interface';
 | 
			
		||||
import { ElectrsApiService } from '../../services/electrs-api.service';
 | 
			
		||||
import { environment } from '../../../environments/environment';
 | 
			
		||||
@ -23,6 +23,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
			
		||||
  showMoreIncrement = 1000;
 | 
			
		||||
 | 
			
		||||
  @Input() transactions: Transaction[];
 | 
			
		||||
  @Input() cached: boolean = false;
 | 
			
		||||
  @Input() showConfirmations = false;
 | 
			
		||||
  @Input() transactionPage = false;
 | 
			
		||||
  @Input() errorUnblinded = false;
 | 
			
		||||
@ -67,7 +68,13 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
			
		||||
    this.outspendsSubscription = merge(
 | 
			
		||||
      this.refreshOutspends$
 | 
			
		||||
        .pipe(
 | 
			
		||||
          switchMap((txIds) => this.apiService.getOutspendsBatched$(txIds)),
 | 
			
		||||
          switchMap((txIds) => {
 | 
			
		||||
            if (!this.cached) {
 | 
			
		||||
              return this.apiService.getOutspendsBatched$(txIds);
 | 
			
		||||
            } else {
 | 
			
		||||
              return of([]);
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
          tap((outspends: Outspend[][]) => {
 | 
			
		||||
            if (!this.transactions) {
 | 
			
		||||
              return;
 | 
			
		||||
@ -155,7 +162,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
 | 
			
		||||
        ).subscribe();
 | 
			
		||||
      });
 | 
			
		||||
      const txIds = this.transactions.filter((tx) => !tx._outspends).map((tx) => tx.txid);
 | 
			
		||||
      if (txIds.length) {
 | 
			
		||||
      if (txIds.length && !this.cached) {
 | 
			
		||||
        this.refreshOutspends$.next(txIds);
 | 
			
		||||
      }
 | 
			
		||||
      if (this.stateService.env.LIGHTNING) {
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ import { Component, OnInit, Input, OnChanges, HostListener, Inject, LOCALE_ID }
 | 
			
		||||
import { StateService } from '../../services/state.service';
 | 
			
		||||
import { Outspend, Transaction } from '../../interfaces/electrs.interface';
 | 
			
		||||
import { Router } from '@angular/router';
 | 
			
		||||
import { ReplaySubject, merge, Subscription } from 'rxjs';
 | 
			
		||||
import { ReplaySubject, merge, Subscription, of } from 'rxjs';
 | 
			
		||||
import { tap, switchMap } from 'rxjs/operators';
 | 
			
		||||
import { ApiService } from '../../services/api.service';
 | 
			
		||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
 | 
			
		||||
@ -40,6 +40,7 @@ interface Xput {
 | 
			
		||||
export class TxBowtieGraphComponent implements OnInit, OnChanges {
 | 
			
		||||
  @Input() tx: Transaction;
 | 
			
		||||
  @Input() network: string;
 | 
			
		||||
  @Input() cached: boolean = false;
 | 
			
		||||
  @Input() width = 1200;
 | 
			
		||||
  @Input() height = 600;
 | 
			
		||||
  @Input() lineLimit = 250;
 | 
			
		||||
@ -107,7 +108,13 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
 | 
			
		||||
    this.outspendsSubscription = merge(
 | 
			
		||||
      this.refreshOutspends$
 | 
			
		||||
        .pipe(
 | 
			
		||||
          switchMap((txid) => this.apiService.getOutspendsBatched$([txid])),
 | 
			
		||||
          switchMap((txid) => {
 | 
			
		||||
            if (!this.cached) {
 | 
			
		||||
              return this.apiService.getOutspendsBatched$([txid]);
 | 
			
		||||
            } else {
 | 
			
		||||
              return of(null);
 | 
			
		||||
            }
 | 
			
		||||
          }),
 | 
			
		||||
          tap((outspends: Outspend[][]) => {
 | 
			
		||||
            if (!this.tx || !outspends || !outspends.length) {
 | 
			
		||||
              return;
 | 
			
		||||
@ -132,7 +139,9 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
 | 
			
		||||
 | 
			
		||||
  ngOnChanges(): void {
 | 
			
		||||
    this.initGraph();
 | 
			
		||||
    this.refreshOutspends$.next(this.tx.txid);
 | 
			
		||||
    if (!this.cached) {
 | 
			
		||||
      this.refreshOutspends$.next(this.tx.txid);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  initGraph(): void {
 | 
			
		||||
 | 
			
		||||
@ -93,7 +93,7 @@
 | 
			
		||||
            <tbody>
 | 
			
		||||
              <tr *ngFor="let block of blocks$ | async; let i = index; trackBy: trackByBlock">
 | 
			
		||||
                <td class="table-cell-height" ><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
 | 
			
		||||
                <td *ngIf="!stateService.env.MINING_DASHBOARD" class="table-cell-mined" ><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since></td>
 | 
			
		||||
                <td *ngIf="!stateService.env.MINING_DASHBOARD" class="table-cell-mined" ><app-time kind="since" [time]="block.timestamp" [fastRender]="true"></app-time></td>
 | 
			
		||||
                <td *ngIf="stateService.env.MINING_DASHBOARD" class="table-cell-mined pl-lg-4">
 | 
			
		||||
                  <a class="clear-link" [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]">
 | 
			
		||||
                    <img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
 | 
			
		||||
 | 
			
		||||
@ -10,7 +10,8 @@
 | 
			
		||||
      <div class="doc-content">
 | 
			
		||||
 | 
			
		||||
        <div id="disclaimer">
 | 
			
		||||
          <table><tr><td><svg viewBox="0 0 304 304" xmlns="http://www.w3.org/2000/svg"><g fill-rule="evenodd" style="fill:#ffc107;fill-opacity:1"><path d="M135.3 34.474c-15.62 27.306-54.206 95.63-85.21 150.534L9.075 257.583C5.382 264.08 6.76 269.217 7.908 271.7c2.326 5.028 7.29 7.537 11.155 8.215l.78.133 264.698.006-.554-.02c4.152.255 9.664-1.24 12.677-6.194 1.926-3.18 3.31-8.589-1.073-16.278L213.637 114.37l-45.351-79.205c-5.681-9.932-12.272-12.022-16.8-12.022-4.42 0-10.818 1.964-16.181 11.331h-.006zm-69.072 159.94c30.997-54.885 69.563-123.184 85.16-150.446l.186-.297c.2.303.393.582.618.981l45.363 79.22s72.377 126.47 78.569 137.283l-247.618-.007 37.719-66.734" style="fill:#ffc107;fill-opacity:1"/><path d="M152.597 247.445c8.02 0 14.518-6.728 14.518-15.025 0-8.29-6.499-15.018-14.518-15.018-8.031 0-14.529 6.728-14.529 15.018 0 8.297 6.498 15.025 14.53 15.025m-.001-147.18c11.586 0 22.23 10.958 20.977 21.7l-9.922 75.564c-.966 6.601-4.95 11.433-11.055 11.433s-10.102-4.832-11.056-11.433l-9.927-75.564c-1.26-10.742 9.39-21.7 20.983-21.7" style="fill:#ffc107;fill-opacity:1"/></g></svg></td><td><p i18n="faq.big-disclaimer"><b>mempool.space merely provides data about the Bitcoin network.</b> It cannot help you with retrieving funds, confirming your transaction quicker, etc.</p><p>For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc).</p></td></tr></table>
 | 
			
		||||
          <table *ngIf="!mobileViewport"><tr><td><app-svg-images name="warning" class="disclaimer-warning" viewBox="0 0 304 304" fill="#ffc107" width="50" height="50"></app-svg-images></td><td><p i18n="faq.big-disclaimer"><b>mempool.space merely provides data about the Bitcoin network.</b> It cannot help you with retrieving funds, confirming your transaction quicker, etc.</p><p>For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc).</p></td></tr></table>
 | 
			
		||||
          <div *ngIf="mobileViewport"><app-svg-images name="warning" class="disclaimer-warning" viewBox="0 0 304 304" fill="#ffc107" width="50" height="50"></app-svg-images><p i18n="faq.big-disclaimer"><b>mempool.space merely provides data about the Bitcoin network.</b> It cannot help you with retrieving funds, confirming your transaction quicker, etc.</p><p>For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc).</p></div>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -274,10 +274,8 @@ h3 {
 | 
			
		||||
  margin: 24px 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#disclaimer svg {
 | 
			
		||||
  width: 50px;
 | 
			
		||||
  height: auto;
 | 
			
		||||
  margin-right: 32px;
 | 
			
		||||
.disclaimer-warning {
 | 
			
		||||
  margin-right: 50px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#disclaimer p:last-child {
 | 
			
		||||
@ -294,6 +292,12 @@ h3 {
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .disclaimer-warning {
 | 
			
		||||
    display: block;
 | 
			
		||||
    margin: 2px auto 16px;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .doc-content {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    float: unset;
 | 
			
		||||
@ -332,6 +336,10 @@ h3 {
 | 
			
		||||
  .doc-welcome-note {
 | 
			
		||||
    font-size: 0.85rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  #disclaimer table {
 | 
			
		||||
    display: none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@media (min-width: 992px) {
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,7 @@ export class ApiDocsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
  screenWidth: number;
 | 
			
		||||
  officialMempoolInstance: boolean;
 | 
			
		||||
  auditEnabled: boolean;
 | 
			
		||||
  mobileViewport: boolean = false;
 | 
			
		||||
 | 
			
		||||
  @ViewChildren(FaqTemplateDirective) faqTemplates: QueryList<FaqTemplateDirective>;
 | 
			
		||||
  dict = {};
 | 
			
		||||
@ -43,6 +44,7 @@ export class ApiDocsComponent implements OnInit, AfterViewInit {
 | 
			
		||||
      this.faqTemplates.forEach((x) => this.dict[x.type] = x.template);
 | 
			
		||||
    }
 | 
			
		||||
    this.desktopDocsNavPosition = ( window.pageYOffset > 182 ) ? "fixed" : "relative";
 | 
			
		||||
    this.mobileViewport = window.innerWidth <= 992;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ngAfterViewInit() {
 | 
			
		||||
 | 
			
		||||
@ -1,14 +1,14 @@
 | 
			
		||||
<span class="green-color" *ngIf="blockConversion; else noblockconversion">
 | 
			
		||||
  {{
 | 
			
		||||
    (
 | 
			
		||||
      (blockConversion.price[currency] >= 0 ? blockConversion.price[currency] : null) ??
 | 
			
		||||
      (blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency]) ?? 0
 | 
			
		||||
      (blockConversion.price[currency] > -1 ? blockConversion.price[currency] : null) ??
 | 
			
		||||
      (blockConversion.price['USD']    > -1 ? blockConversion.price['USD'] * blockConversion.exchangeRates['USD' + currency] : null) ?? 0
 | 
			
		||||
    ) * value / 100000000 | fiatCurrency : digitsInfo : currency
 | 
			
		||||
  }}
 | 
			
		||||
</span>
 | 
			
		||||
 | 
			
		||||
<ng-template #noblockconversion>
 | 
			
		||||
  <span class="green-color" *ngIf="(conversions$ | async) as conversions">
 | 
			
		||||
    {{ (conversions[currency] ?? conversions['USD'] ?? 0) * value / 100000000 | fiatCurrency : digitsInfo : currency }}
 | 
			
		||||
    {{ (conversions[currency] > -1 ? conversions[currency] : 0) * value / 100000000 | fiatCurrency : digitsInfo : currency }}
 | 
			
		||||
  </span>
 | 
			
		||||
</ng-template>
 | 
			
		||||
@ -20,7 +20,7 @@
 | 
			
		||||
  <div class="clearfix"></div>
 | 
			
		||||
 | 
			
		||||
  <div *ngIf="error" class="d-flex flex-column justify-content-around align-items-center mt-5 w-100" style="min-height: 100px">
 | 
			
		||||
    <span class="text-center" i18n="lightning.channel-not-found">No channel found for short id "{{ channel.short_id }}"</span>
 | 
			
		||||
    <span class="text-center">No channel found for ID "{{ channel.short_id }}"</span>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <app-nodes-channels-map *ngIf="!error && (channelGeo$ | async) as channelGeo" [style]="'channelpage'"
 | 
			
		||||
 | 
			
		||||
@ -78,5 +78,5 @@ h3 {
 | 
			
		||||
 | 
			
		||||
.details-button {
 | 
			
		||||
  align-self: center;
 | 
			
		||||
  margin-left: auto;
 | 
			
		||||
  margin-inline-start: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,14 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:host-context(.rtl-layout) .formRadioGroup {
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
  @media (min-width: 435px) {
 | 
			
		||||
    right: unset;
 | 
			
		||||
    left: 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-group {
 | 
			
		||||
  @media (max-width: 435px) {
 | 
			
		||||
    flex-grow: 1;
 | 
			
		||||
 | 
			
		||||
@ -92,7 +92,7 @@
 | 
			
		||||
              </ng-template>
 | 
			
		||||
              <input type="text" class="form-control" aria-label="Text input with dropdown button"
 | 
			
		||||
                [value]="node.socketsObject[selectedSocketIndex].socket">
 | 
			
		||||
              <button class="btn btn-secondary ml-1" type="button" id="inputGroupFileAddon04" (mouseover)="qrCodeVisible[i] = 1"
 | 
			
		||||
              <button class="btn btn-secondary" type="button" id="inputGroupFileAddon04" (mouseover)="qrCodeVisible[i] = 1"
 | 
			
		||||
                (mouseout)="qrCodeVisible[i] = 0">
 | 
			
		||||
                <fa-icon [icon]="['fas', 'qrcode']" [fixedWidth]="true"></fa-icon>
 | 
			
		||||
                <div class="qr-wrapper" [hidden]="!qrCodeVisible[i]">
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
h1 {
 | 
			
		||||
  margin-left: 15px;
 | 
			
		||||
  margin-inline-start: 15px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.qr-wrapper {
 | 
			
		||||
@ -57,3 +57,17 @@ h1 {
 | 
			
		||||
.description-text {
 | 
			
		||||
  white-space: break-spaces;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.timestamp-first .input-group {
 | 
			
		||||
  input {
 | 
			
		||||
    margin-inline-end: .25rem;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
:host-context(.rtl-layout) {
 | 
			
		||||
  .timestamp-first .input-group {
 | 
			
		||||
    button {
 | 
			
		||||
      margin-inline-end: .25rem;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@ -17,7 +17,7 @@
 | 
			
		||||
  <div class="clearfix"></div>
 | 
			
		||||
 | 
			
		||||
  <div *ngIf="error" class="d-flex flex-column justify-content-around align-items-center mt-5 w-100" style="min-height: 100px">
 | 
			
		||||
    <span class="text-center" i18n="lightning.node-not-found">No node found for public key "{{ node.public_key | shortenString : 12}}"</span>
 | 
			
		||||
    <span class="text-center">No node found for public key "{{ node.public_key | shortenString : 12}}"</span>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="box" *ngIf="!error">
 | 
			
		||||
@ -57,7 +57,7 @@
 | 
			
		||||
            </tr>
 | 
			
		||||
            <tr *ngIf="(avgChannelDistance$ | async) as avgDistance;">
 | 
			
		||||
              <td i18n="lightning.avg-distance" class="text-truncate">Avg channel distance</td>
 | 
			
		||||
              <td>{{ avgDistance | number : '1.0-0' }} <span class="symbol">km</span> <span class="separator">/</span> {{ kmToMiles(avgDistance) | number : '1.0-0' }} <span class="symbol">mi</span></td>
 | 
			
		||||
              <td class="direction-ltr">{{ avgDistance | number : '1.0-0' }} <span class="symbol">km</span> <span class="separator">/</span> {{ kmToMiles(avgDistance) | number : '1.0-0' }} <span class="symbol">mi</span></td>
 | 
			
		||||
            </tr>
 | 
			
		||||
          </tbody>
 | 
			
		||||
        </table>
 | 
			
		||||
 | 
			
		||||
@ -4,10 +4,6 @@
 | 
			
		||||
  &.widget {
 | 
			
		||||
    height: 250px;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &.graph {
 | 
			
		||||
    height: auto;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.card-header {
 | 
			
		||||
 | 
			
		||||
@ -229,6 +229,7 @@ export class NodesChannelsMap implements OnInit {
 | 
			
		||||
      title: title ?? undefined,
 | 
			
		||||
      tooltip: {},
 | 
			
		||||
      geo: {
 | 
			
		||||
        top: 75,
 | 
			
		||||
        animation: false,
 | 
			
		||||
        silent: true,
 | 
			
		||||
        center: this.center,
 | 
			
		||||
 | 
			
		||||
@ -53,31 +53,6 @@
 | 
			
		||||
  height: 145px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pool-distribution {
 | 
			
		||||
  min-height: 56px;
 | 
			
		||||
  display: block;
 | 
			
		||||
 | 
			
		||||
@ -182,7 +182,7 @@ export class NodesNetworksChartComponent implements OnInit {
 | 
			
		||||
      {
 | 
			
		||||
        zlevel: 1,
 | 
			
		||||
        yAxisIndex: 0,
 | 
			
		||||
        name: $localize`Clearnet (IPv4, IPv6)`,
 | 
			
		||||
        name: $localize`Clearnet Only (IPv4, IPv6)`,
 | 
			
		||||
        showSymbol: false,
 | 
			
		||||
        symbol: 'none',
 | 
			
		||||
        data: data.clearnet_nodes,
 | 
			
		||||
@ -292,7 +292,7 @@ export class NodesNetworksChartComponent implements OnInit {
 | 
			
		||||
            icon: 'roundRect',
 | 
			
		||||
          },
 | 
			
		||||
          {
 | 
			
		||||
            name: $localize`Clearnet (IPv4, IPv6)`,
 | 
			
		||||
            name: $localize`Clearnet Only (IPv4, IPv6)`,
 | 
			
		||||
            inactiveColor: 'rgb(110, 112, 121)',
 | 
			
		||||
            textStyle: {
 | 
			
		||||
              color: 'white',
 | 
			
		||||
@ -318,7 +318,7 @@ export class NodesNetworksChartComponent implements OnInit {
 | 
			
		||||
        ],
 | 
			
		||||
        selected: this.widget ? undefined : JSON.parse(this.storageService.getValue('nodes_networks_legend'))  ?? {
 | 
			
		||||
          '$localize`Darknet Only (Tor, I2P, cjdns)`': true,
 | 
			
		||||
          '$localize`Clearnet (IPv4, IPv6)`': true,
 | 
			
		||||
          '$localize`Clearnet Only (IPv4, IPv6)`': true,
 | 
			
		||||
          '$localize`Clearnet and Darknet`': true,
 | 
			
		||||
          '$localize`:@@e5d8bb389c702588877f039d72178f219453a72d:Unknown`': true,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -34,31 +34,6 @@
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.bottom-padding {
 | 
			
		||||
  @media (max-width: 992px) {
 | 
			
		||||
    padding-bottom: 65px
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@
 | 
			
		||||
        <th class="pool text-left" i18n="nodes.alias" [ngClass]="{'widget': widget}">Alias</th>
 | 
			
		||||
        <th class="liquidity text-right" i18n="node.channels">Channels</th>
 | 
			
		||||
        <th *ngIf="!widget" class="d-none d-md-table-cell channels text-right" i18n="lightning.channels">Capacity</th>
 | 
			
		||||
        <th *ngIf="!widget" class="d-none d-md-table-cell text-right" i18n="node.liquidity">{{ currency$ | async }}</th>
 | 
			
		||||
        <th *ngIf="!widget" class="d-none d-md-table-cell text-right">{{ currency$ | async }}</th>
 | 
			
		||||
        <th *ngIf="!widget" class="d-none d-md-table-cell timestamp text-right" i18n="transaction.first-seen|Transaction first seen">First seen</th>
 | 
			
		||||
        <th *ngIf="!widget" class="d-none d-md-table-cell timestamp text-right" i18n="lightning.last_update">Last update</th>
 | 
			
		||||
        <th class="geolocation d-table-cell text-right" i18n="lightning.location">Location</th>
 | 
			
		||||
 | 
			
		||||
@ -53,31 +53,6 @@
 | 
			
		||||
  height: 145px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.pool-distribution {
 | 
			
		||||
  min-height: 56px;
 | 
			
		||||
  display: block;
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,7 @@ export class PriceService {
 | 
			
		||||
      return this.singlePriceObservable$.pipe(
 | 
			
		||||
        map((conversion) => {
 | 
			
		||||
          if (conversion.prices.length <= 0) {
 | 
			
		||||
            return this.getEmptyPrice();
 | 
			
		||||
            return undefined;
 | 
			
		||||
          }
 | 
			
		||||
          return {
 | 
			
		||||
            price: {
 | 
			
		||||
@ -113,7 +113,7 @@ export class PriceService {
 | 
			
		||||
 | 
			
		||||
      return this.priceObservable$.pipe(
 | 
			
		||||
        map((conversion) => {
 | 
			
		||||
          if (!blockTimestamp) {
 | 
			
		||||
          if (!blockTimestamp || !conversion) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,6 @@
 | 
			
		||||
<span *ngIf="seconds !== undefined">
 | 
			
		||||
  ‎{{ seconds * 1000 | date: customFormat ?? 'yyyy-MM-dd HH:mm' }}
 | 
			
		||||
  <div class="lg-inline" *ngIf="!hideTimeSince">
 | 
			
		||||
    <i class="symbol">(<app-time-since [time]="seconds" [fastRender]="true"></app-time-since>)</i>
 | 
			
		||||
    <i class="symbol">(<app-time kind="since" [time]="seconds" [fastRender]="true"></app-time>)</i>
 | 
			
		||||
  </div>
 | 
			
		||||
</span>
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,7 @@ import { BytesPipe } from './pipes/bytes-pipe/bytes.pipe';
 | 
			
		||||
import { WuBytesPipe } from './pipes/bytes-pipe/wubytes.pipe';
 | 
			
		||||
import { FiatCurrencyPipe } from './pipes/fiat-currency.pipe';
 | 
			
		||||
import { BlockchainComponent } from '../components/blockchain/blockchain.component';
 | 
			
		||||
import { TimeSinceComponent } from '../components/time-since/time-since.component';
 | 
			
		||||
import { TimeUntilComponent } from '../components/time-until/time-until.component';
 | 
			
		||||
import { TimeComponent } from '../components/time/time.component';
 | 
			
		||||
import { ClipboardComponent } from '../components/clipboard/clipboard.component';
 | 
			
		||||
import { QrcodeComponent } from '../components/qrcode/qrcode.component';
 | 
			
		||||
import { FiatComponent } from '../fiat/fiat.component';
 | 
			
		||||
@ -53,7 +52,6 @@ import { AddressComponent } from '../components/address/address.component';
 | 
			
		||||
import { SearchFormComponent } from '../components/search-form/search-form.component';
 | 
			
		||||
import { AddressLabelsComponent } from '../components/address-labels/address-labels.component';
 | 
			
		||||
import { FooterComponent } from '../components/footer/footer.component';
 | 
			
		||||
import { TimeSpanComponent } from '../components/time-span/time-span.component';
 | 
			
		||||
import { AssetComponent } from '../components/asset/asset.component';
 | 
			
		||||
import { AssetsComponent } from '../components/assets/assets.component';
 | 
			
		||||
import { AssetsNavComponent } from '../components/assets/assets-nav/assets-nav.component';
 | 
			
		||||
@ -88,8 +86,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
 | 
			
		||||
@NgModule({
 | 
			
		||||
  declarations: [
 | 
			
		||||
    ClipboardComponent,
 | 
			
		||||
    TimeSinceComponent,
 | 
			
		||||
    TimeUntilComponent,
 | 
			
		||||
    TimeComponent,
 | 
			
		||||
    QrcodeComponent,
 | 
			
		||||
    FiatComponent,
 | 
			
		||||
    TxFeaturesComponent,
 | 
			
		||||
@ -129,7 +126,6 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
 | 
			
		||||
    TransactionsListComponent,
 | 
			
		||||
    AddressComponent,
 | 
			
		||||
    SearchFormComponent,
 | 
			
		||||
    TimeSpanComponent,
 | 
			
		||||
    AddressLabelsComponent,
 | 
			
		||||
    FooterComponent,
 | 
			
		||||
    AssetComponent,
 | 
			
		||||
@ -195,8 +191,7 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
 | 
			
		||||
    NgbCollapseModule,
 | 
			
		||||
    InfiniteScrollModule,
 | 
			
		||||
    FontAwesomeModule,
 | 
			
		||||
    TimeSinceComponent,
 | 
			
		||||
    TimeUntilComponent,
 | 
			
		||||
    TimeComponent,
 | 
			
		||||
    ClipboardComponent,
 | 
			
		||||
    QrcodeComponent,
 | 
			
		||||
    FiatComponent,
 | 
			
		||||
@ -232,7 +227,6 @@ import { GeolocationComponent } from '../shared/components/geolocation/geolocati
 | 
			
		||||
    TransactionsListComponent,
 | 
			
		||||
    AddressComponent,
 | 
			
		||||
    SearchFormComponent,
 | 
			
		||||
    TimeSpanComponent,
 | 
			
		||||
    AddressLabelsComponent,
 | 
			
		||||
    FooterComponent,
 | 
			
		||||
    AssetComponent,
 | 
			
		||||
 | 
			
		||||
@ -775,7 +775,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">385,389</context>
 | 
			
		||||
          <context context-type="linenumber">375,378</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/mining-dashboard/mining-dashboard.component.html</context>
 | 
			
		||||
@ -1452,7 +1452,7 @@
 | 
			
		||||
        <target>Unser Mempool- und Blockchain-Explorer für die Bitcoin-Community, der sich auf den Markt für Transaktionsgebühren und das mehrschichtige Ökosystem konzentriert und vollständig selbst gehostet wird, ohne vertrauenswürdige Drittanbieter.</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,17</context>
 | 
			
		||||
          <context context-type="linenumber">13,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="a24b1c6a9c4334ba204e4cec2dd9f32ea33d043f" datatype="html">
 | 
			
		||||
@ -1460,7 +1460,7 @@
 | 
			
		||||
        <target>Unternehmenssponsoren</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">29,32</context>
 | 
			
		||||
          <context context-type="linenumber">19,22</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.sponsors.enterprise.withRocket</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1469,7 +1469,7 @@
 | 
			
		||||
        <target>Community-Sponsoren ❤️</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">177,180</context>
 | 
			
		||||
          <context context-type="linenumber">167,170</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.sponsors.withHeart</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1478,7 +1478,7 @@
 | 
			
		||||
        <target>Community Integrationen</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">191,193</context>
 | 
			
		||||
          <context context-type="linenumber">181,183</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.community-integrations</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1487,7 +1487,7 @@
 | 
			
		||||
        <target>Community-Allianzen</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">285,287</context>
 | 
			
		||||
          <context context-type="linenumber">275,277</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.alliances</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1496,7 +1496,7 @@
 | 
			
		||||
        <target>Projektübersetzer</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">301,303</context>
 | 
			
		||||
          <context context-type="linenumber">291,293</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.translators</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1505,7 +1505,7 @@
 | 
			
		||||
        <target>Projektmitwirkende</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">315,317</context>
 | 
			
		||||
          <context context-type="linenumber">305,307</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.contributors</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1514,7 +1514,7 @@
 | 
			
		||||
        <target>Projektmitglieder</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">327,329</context>
 | 
			
		||||
          <context context-type="linenumber">317,319</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.project_members</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1523,7 +1523,7 @@
 | 
			
		||||
        <target>Projektbetreuer</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">340,342</context>
 | 
			
		||||
          <context context-type="linenumber">330,332</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.maintainers</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1532,7 +1532,7 @@
 | 
			
		||||
        <target>Über</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">39</context>
 | 
			
		||||
          <context context-type="linenumber">42</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/bisq-master-page/bisq-master-page.component.html</context>
 | 
			
		||||
@ -1581,7 +1581,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/amount/amount.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">18,21</context>
 | 
			
		||||
          <context context-type="linenumber">20,23</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/asset-circulation/asset-circulation.component.html</context>
 | 
			
		||||
@ -2686,11 +2686,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">52,55</context>
 | 
			
		||||
          <context context-type="linenumber">55,58</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">96,100</context>
 | 
			
		||||
          <context context-type="linenumber">99,103</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
@ -2895,15 +2895,15 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">86,88</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">96,98</context>
 | 
			
		||||
          <context context-type="linenumber">103,105</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">218,222</context>
 | 
			
		||||
          <context context-type="linenumber">221,225</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Transaction Details</note>
 | 
			
		||||
        <note priority="1" from="meaning">transaction.details</note>
 | 
			
		||||
@ -2923,10 +2923,6 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel-preview.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">70,75</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">109,115</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node-preview.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">66,69</context>
 | 
			
		||||
@ -4614,7 +4610,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">67,70</context>
 | 
			
		||||
          <context context-type="linenumber">70,73</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -4630,11 +4626,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,15</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,15</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Transaction first seen</note>
 | 
			
		||||
        <note priority="1" from="meaning">transaction.first-seen</note>
 | 
			
		||||
@ -5370,7 +5366,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">180,182</context>
 | 
			
		||||
          <context context-type="linenumber">183,185</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">shared.m-sats</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5488,7 +5484,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5505,7 +5501,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5522,7 +5518,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5543,7 +5539,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">29,30</context>
 | 
			
		||||
          <context context-type="linenumber">36,37</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.created</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5556,7 +5552,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">48,49</context>
 | 
			
		||||
          <context context-type="linenumber">55,56</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5590,6 +5586,10 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-isp/nodes-per-isp.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">60,62</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">202,201</context>
 | 
			
		||||
@ -5626,11 +5626,11 @@
 | 
			
		||||
        <target>Lightning-Kanal</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">2,5</context>
 | 
			
		||||
          <context context-type="linenumber">4,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">117,119</context>
 | 
			
		||||
          <context context-type="linenumber">116,118</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.channel</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5639,11 +5639,11 @@
 | 
			
		||||
        <target>Letzte Aktualisierung</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">33,34</context>
 | 
			
		||||
          <context context-type="linenumber">40,41</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">73,75</context>
 | 
			
		||||
          <context context-type="linenumber">76,78</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -5659,11 +5659,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
          <context context-type="linenumber">16,17</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
          <context context-type="linenumber">16,17</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.last-update</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5672,7 +5672,7 @@
 | 
			
		||||
        <target>Schließdatum</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">37,38</context>
 | 
			
		||||
          <context context-type="linenumber">44,45</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5685,7 +5685,7 @@
 | 
			
		||||
        <target>Geschlossen von</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">52,54</context>
 | 
			
		||||
          <context context-type="linenumber">59,61</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.closed_by</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5694,7 +5694,7 @@
 | 
			
		||||
        <target>Öffnende Transaktion</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">84,85</context>
 | 
			
		||||
          <context context-type="linenumber">91,92</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.opening-transaction</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5703,7 +5703,7 @@
 | 
			
		||||
        <target>Schließende Transaktion</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
          <context context-type="linenumber">100,102</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.closing-transaction</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5786,11 +5786,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">10,11</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">10,12</context>
 | 
			
		||||
          <context context-type="linenumber">11,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.alias</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6064,10 +6064,6 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.liquidity</note>
 | 
			
		||||
@ -6121,11 +6117,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts</context>
 | 
			
		||||
@ -6163,7 +6159,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">47,49</context>
 | 
			
		||||
          <context context-type="linenumber">50,52</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -6179,11 +6175,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">15,17</context>
 | 
			
		||||
          <context context-type="linenumber">17,20</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">15,17</context>
 | 
			
		||||
          <context context-type="linenumber">17,20</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.location</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6221,9 +6217,17 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/lightning-dashboard/lightning-dashboard.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">62</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">4,9</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">29</context>
 | 
			
		||||
          <context context-type="linenumber">33</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">4,9</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-rankings-dashboard/nodes-rankings-dashboard.component.html</context>
 | 
			
		||||
@ -6303,11 +6307,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">2,4</context>
 | 
			
		||||
          <context context-type="linenumber">4,6</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">260,262</context>
 | 
			
		||||
          <context context-type="linenumber">263,265</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.node</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6320,7 +6324,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">27,30</context>
 | 
			
		||||
          <context context-type="linenumber">30,33</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-capacity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6333,7 +6337,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">34,38</context>
 | 
			
		||||
          <context context-type="linenumber">37,41</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6346,21 +6350,12 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">country</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="674378571ab7e72a386f27fd3281558bae821d9d" datatype="html">
 | 
			
		||||
        <source>No node found for public key "<x id="INTERPOLATION" equiv-text="{{ node.public_key | shortenString : 12}}"/>"</source>
 | 
			
		||||
        <target>Keinen Node gefunden für Public-Key &quot;<x id="INTERPOLATION" equiv-text="{{ node.public_key | shortenString : 12}}"/>&quot;</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">17,19</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.node-not-found</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="43b48b9c15083a164b401bf3775a4b99f3917699" datatype="html">
 | 
			
		||||
        <source>Average channel size</source>
 | 
			
		||||
        <target>Durchschnittliche Kanalgröße</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">40,43</context>
 | 
			
		||||
          <context context-type="linenumber">43,46</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-channels-avg</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6369,7 +6364,7 @@
 | 
			
		||||
        <target>Durchschn. Kanalentfernung</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">56,57</context>
 | 
			
		||||
          <context context-type="linenumber">59,60</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.avg-distance</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6378,7 +6373,7 @@
 | 
			
		||||
        <target>Farbe</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">79,81</context>
 | 
			
		||||
          <context context-type="linenumber">82,84</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.color</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6387,7 +6382,7 @@
 | 
			
		||||
        <target>ISP</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">86,87</context>
 | 
			
		||||
          <context context-type="linenumber">89,90</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html</context>
 | 
			
		||||
@ -6400,7 +6395,7 @@
 | 
			
		||||
        <target>Ausschließlich auf Tor</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
          <context context-type="linenumber">96,98</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">tor</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6409,7 +6404,7 @@
 | 
			
		||||
        <target>Liquiditätswerbung</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">138,141</context>
 | 
			
		||||
          <context context-type="linenumber">141,144</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">node.liquidity-ad</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6418,7 +6413,7 @@
 | 
			
		||||
        <target>Lease Gebührensatz</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">144,147</context>
 | 
			
		||||
          <context context-type="linenumber">147,150</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Liquidity ad lease fee rate</note>
 | 
			
		||||
        <note priority="1" from="meaning">liquidity-ad.lease-fee-rate</note>
 | 
			
		||||
@ -6428,7 +6423,7 @@
 | 
			
		||||
        <target>Lease Basisgebühr</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">152,154</context>
 | 
			
		||||
          <context context-type="linenumber">155,157</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.lease-base-fee</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6437,7 +6432,7 @@
 | 
			
		||||
        <target>Finanzierungsgewicht</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">158,159</context>
 | 
			
		||||
          <context context-type="linenumber">161,162</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.funding-weight</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6446,7 +6441,7 @@
 | 
			
		||||
        <target>Kanal-Gebührenrate</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">168,171</context>
 | 
			
		||||
          <context context-type="linenumber">171,174</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Liquidity ad channel fee rate</note>
 | 
			
		||||
        <note priority="1" from="meaning">liquidity-ad.channel-fee-rate</note>
 | 
			
		||||
@ -6456,7 +6451,7 @@
 | 
			
		||||
        <target>Kanal-Basisgebühr</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">176,178</context>
 | 
			
		||||
          <context context-type="linenumber">179,181</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.channel-base-fee</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6465,7 +6460,7 @@
 | 
			
		||||
        <target>Compact_lease</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">188,190</context>
 | 
			
		||||
          <context context-type="linenumber">191,193</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.compact-lease</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6474,7 +6469,7 @@
 | 
			
		||||
        <target>LV Erweiterungs-Datensätze</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">199,202</context>
 | 
			
		||||
          <context context-type="linenumber">202,205</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">node.tlv.records</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6483,7 +6478,7 @@
 | 
			
		||||
        <target>Offene Kanäle</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">240,243</context>
 | 
			
		||||
          <context context-type="linenumber">243,246</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.open-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6492,7 +6487,7 @@
 | 
			
		||||
        <target>Geschlossene Kanäle</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">244,247</context>
 | 
			
		||||
          <context context-type="linenumber">247,250</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.open-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6562,9 +6557,9 @@
 | 
			
		||||
          <context context-type="linenumber">112,107</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="1055322764280599360" datatype="html">
 | 
			
		||||
        <source>Reachable on Clearnet Only</source>
 | 
			
		||||
        <target>Nur im Klarnetz erreichbar</target>
 | 
			
		||||
      <trans-unit id="599038141003770125" datatype="html">
 | 
			
		||||
        <source>Clearnet and Darknet</source>
 | 
			
		||||
        <target>Clearnet und Darknet</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">164,161</context>
 | 
			
		||||
@ -6574,9 +6569,9 @@
 | 
			
		||||
          <context context-type="linenumber">303,302</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="2760682261176173881" datatype="html">
 | 
			
		||||
        <source>Reachable on Clearnet and Darknet</source>
 | 
			
		||||
        <target>Im Klarnetz und Darknet erreichbar</target>
 | 
			
		||||
      <trans-unit id="1282458597026430784" datatype="html">
 | 
			
		||||
        <source>Clearnet Only (IPv4, IPv6)</source>
 | 
			
		||||
        <target>Nur Clearnet (IPv4, IPv6)</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">185,182</context>
 | 
			
		||||
@ -6586,9 +6581,9 @@
 | 
			
		||||
          <context context-type="linenumber">295,294</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="1191036460161514668" datatype="html">
 | 
			
		||||
        <source>Reachable on Darknet Only</source>
 | 
			
		||||
        <target>Nur im Darknet erreichbar</target>
 | 
			
		||||
      <trans-unit id="2165336009914523952" datatype="html">
 | 
			
		||||
        <source>Darknet Only (Tor, I2P, cjdns)</source>
 | 
			
		||||
        <target>Nur Darknet (Tor, I2P, cjdns)</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">206,203</context>
 | 
			
		||||
@ -6844,24 +6839,6 @@
 | 
			
		||||
          <context context-type="linenumber">27</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="71bb1ed9da9ebb92cf35925bc6fe0a8fbc325625" datatype="html">
 | 
			
		||||
        <source>Top 100 nodes liquidity ranking</source>
 | 
			
		||||
        <target>Top 100 Nodes nach Liquidität</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">3,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.top-100-liquidity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="99786bd2106b708e4514d0121964affb19bee636" datatype="html">
 | 
			
		||||
        <source>Top 100 nodes connectivity ranking</source>
 | 
			
		||||
        <target>Top 100 Nodes nach Anbindung</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">3,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.top-100-connectivity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="47a30fc5a836252f8fe03e2949756b150684d934" datatype="html">
 | 
			
		||||
        <source>Oldest nodes</source>
 | 
			
		||||
        <target>Älteste Nodes</target>
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -775,7 +775,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">385,389</context>
 | 
			
		||||
          <context context-type="linenumber">375,378</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/mining-dashboard/mining-dashboard.component.html</context>
 | 
			
		||||
@ -1452,7 +1452,7 @@
 | 
			
		||||
        <target>Notre explorateur mempool et blockchain pour la communauté Bitcoin, axé sur le marché des frais de transaction et l'écosystème multicouche, entièrement auto-hébergé sans aucun tiers de confiance.</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,17</context>
 | 
			
		||||
          <context context-type="linenumber">13,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="a24b1c6a9c4334ba204e4cec2dd9f32ea33d043f" datatype="html">
 | 
			
		||||
@ -1460,7 +1460,7 @@
 | 
			
		||||
        <target>Entreprises sponsors 🚀</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">29,32</context>
 | 
			
		||||
          <context context-type="linenumber">19,22</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.sponsors.enterprise.withRocket</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1469,7 +1469,7 @@
 | 
			
		||||
        <target>Sponsors de la communauté ❤️</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">177,180</context>
 | 
			
		||||
          <context context-type="linenumber">167,170</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.sponsors.withHeart</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1478,7 +1478,7 @@
 | 
			
		||||
        <target>Intégrations communautaires</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">191,193</context>
 | 
			
		||||
          <context context-type="linenumber">181,183</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.community-integrations</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1487,7 +1487,7 @@
 | 
			
		||||
        <target>Alliances communautaires</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">285,287</context>
 | 
			
		||||
          <context context-type="linenumber">275,277</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.alliances</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1496,7 +1496,7 @@
 | 
			
		||||
        <target>Traducteurs</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">301,303</context>
 | 
			
		||||
          <context context-type="linenumber">291,293</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.translators</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1505,7 +1505,7 @@
 | 
			
		||||
        <target>Contributeurs au projet</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">315,317</context>
 | 
			
		||||
          <context context-type="linenumber">305,307</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.contributors</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1514,7 +1514,7 @@
 | 
			
		||||
        <target>Membres du projet</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">327,329</context>
 | 
			
		||||
          <context context-type="linenumber">317,319</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.project_members</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1523,7 +1523,7 @@
 | 
			
		||||
        <target>Mainteneurs de projet</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">340,342</context>
 | 
			
		||||
          <context context-type="linenumber">330,332</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.maintainers</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1532,7 +1532,7 @@
 | 
			
		||||
        <target>A propos</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">39</context>
 | 
			
		||||
          <context context-type="linenumber">42</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/bisq-master-page/bisq-master-page.component.html</context>
 | 
			
		||||
@ -1581,7 +1581,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/amount/amount.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">18,21</context>
 | 
			
		||||
          <context context-type="linenumber">20,23</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/asset-circulation/asset-circulation.component.html</context>
 | 
			
		||||
@ -2686,11 +2686,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">52,55</context>
 | 
			
		||||
          <context context-type="linenumber">55,58</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">96,100</context>
 | 
			
		||||
          <context context-type="linenumber">99,103</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
@ -2895,15 +2895,15 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">86,88</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">96,98</context>
 | 
			
		||||
          <context context-type="linenumber">103,105</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">218,222</context>
 | 
			
		||||
          <context context-type="linenumber">221,225</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Transaction Details</note>
 | 
			
		||||
        <note priority="1" from="meaning">transaction.details</note>
 | 
			
		||||
@ -2923,10 +2923,6 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel-preview.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">70,75</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">109,115</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node-preview.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">66,69</context>
 | 
			
		||||
@ -4614,7 +4610,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">67,70</context>
 | 
			
		||||
          <context context-type="linenumber">70,73</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -4630,11 +4626,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,15</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,15</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Transaction first seen</note>
 | 
			
		||||
        <note priority="1" from="meaning">transaction.first-seen</note>
 | 
			
		||||
@ -5370,7 +5366,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">180,182</context>
 | 
			
		||||
          <context context-type="linenumber">183,185</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">shared.m-sats</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5488,7 +5484,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5505,7 +5501,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5522,7 +5518,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5543,7 +5539,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">29,30</context>
 | 
			
		||||
          <context context-type="linenumber">36,37</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.created</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5556,7 +5552,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">48,49</context>
 | 
			
		||||
          <context context-type="linenumber">55,56</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5590,6 +5586,10 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-isp/nodes-per-isp.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">60,62</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">202,201</context>
 | 
			
		||||
@ -5626,11 +5626,11 @@
 | 
			
		||||
        <target>Canal Lightning</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">2,5</context>
 | 
			
		||||
          <context context-type="linenumber">4,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">117,119</context>
 | 
			
		||||
          <context context-type="linenumber">116,118</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.channel</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5639,11 +5639,11 @@
 | 
			
		||||
        <target>Dernière mise à jour</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">33,34</context>
 | 
			
		||||
          <context context-type="linenumber">40,41</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">73,75</context>
 | 
			
		||||
          <context context-type="linenumber">76,78</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -5659,11 +5659,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
          <context context-type="linenumber">16,17</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
          <context context-type="linenumber">16,17</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.last-update</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5672,7 +5672,7 @@
 | 
			
		||||
        <target>Date de clôture</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">37,38</context>
 | 
			
		||||
          <context context-type="linenumber">44,45</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5685,7 +5685,7 @@
 | 
			
		||||
        <target>Fermée par</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">52,54</context>
 | 
			
		||||
          <context context-type="linenumber">59,61</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.closed_by</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5694,7 +5694,7 @@
 | 
			
		||||
        <target>Transaction d'ouverture</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">84,85</context>
 | 
			
		||||
          <context context-type="linenumber">91,92</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.opening-transaction</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5703,7 +5703,7 @@
 | 
			
		||||
        <target>Transaction de clôture</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
          <context context-type="linenumber">100,102</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.closing-transaction</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5786,11 +5786,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">10,11</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">10,12</context>
 | 
			
		||||
          <context context-type="linenumber">11,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.alias</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6064,10 +6064,6 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.liquidity</note>
 | 
			
		||||
@ -6121,11 +6117,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts</context>
 | 
			
		||||
@ -6163,7 +6159,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">47,49</context>
 | 
			
		||||
          <context context-type="linenumber">50,52</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -6179,11 +6175,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">15,17</context>
 | 
			
		||||
          <context context-type="linenumber">17,20</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">15,17</context>
 | 
			
		||||
          <context context-type="linenumber">17,20</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.location</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6221,9 +6217,17 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/lightning-dashboard/lightning-dashboard.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">62</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">4,9</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">29</context>
 | 
			
		||||
          <context context-type="linenumber">33</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">4,9</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-rankings-dashboard/nodes-rankings-dashboard.component.html</context>
 | 
			
		||||
@ -6303,11 +6307,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">2,4</context>
 | 
			
		||||
          <context context-type="linenumber">4,6</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">260,262</context>
 | 
			
		||||
          <context context-type="linenumber">263,265</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.node</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6320,7 +6324,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">27,30</context>
 | 
			
		||||
          <context context-type="linenumber">30,33</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-capacity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6333,7 +6337,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">34,38</context>
 | 
			
		||||
          <context context-type="linenumber">37,41</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6346,21 +6350,12 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">country</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="674378571ab7e72a386f27fd3281558bae821d9d" datatype="html">
 | 
			
		||||
        <source>No node found for public key "<x id="INTERPOLATION" equiv-text="{{ node.public_key | shortenString : 12}}"/>"</source>
 | 
			
		||||
        <target>Aucun nœud trouvé pour la clé publique &quot; <x id="INTERPOLATION" equiv-text="{{ node.public_key | shortenString : 12}}"/> &quot;</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">17,19</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.node-not-found</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="43b48b9c15083a164b401bf3775a4b99f3917699" datatype="html">
 | 
			
		||||
        <source>Average channel size</source>
 | 
			
		||||
        <target>Taille moyenne du canal</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">40,43</context>
 | 
			
		||||
          <context context-type="linenumber">43,46</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-channels-avg</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6369,7 +6364,7 @@
 | 
			
		||||
        <target>Distance moyenne des canaux</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">56,57</context>
 | 
			
		||||
          <context context-type="linenumber">59,60</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.avg-distance</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6378,7 +6373,7 @@
 | 
			
		||||
        <target>Couleur</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">79,81</context>
 | 
			
		||||
          <context context-type="linenumber">82,84</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.color</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6387,7 +6382,7 @@
 | 
			
		||||
        <target>FAI</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">86,87</context>
 | 
			
		||||
          <context context-type="linenumber">89,90</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html</context>
 | 
			
		||||
@ -6400,7 +6395,7 @@
 | 
			
		||||
        <target>Exclusivement sur Tor</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
          <context context-type="linenumber">96,98</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">tor</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6409,7 +6404,7 @@
 | 
			
		||||
        <target>Annonce de liquidité</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">138,141</context>
 | 
			
		||||
          <context context-type="linenumber">141,144</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">node.liquidity-ad</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6418,7 +6413,7 @@
 | 
			
		||||
        <target>Taux de frais de location</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">144,147</context>
 | 
			
		||||
          <context context-type="linenumber">147,150</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Liquidity ad lease fee rate</note>
 | 
			
		||||
        <note priority="1" from="meaning">liquidity-ad.lease-fee-rate</note>
 | 
			
		||||
@ -6428,7 +6423,7 @@
 | 
			
		||||
        <target>Frais de base de location</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">152,154</context>
 | 
			
		||||
          <context context-type="linenumber">155,157</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.lease-base-fee</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6437,7 +6432,7 @@
 | 
			
		||||
        <target>Poids du financement</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">158,159</context>
 | 
			
		||||
          <context context-type="linenumber">161,162</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.funding-weight</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6446,7 +6441,7 @@
 | 
			
		||||
        <target>Taux de frais de canal</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">168,171</context>
 | 
			
		||||
          <context context-type="linenumber">171,174</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Liquidity ad channel fee rate</note>
 | 
			
		||||
        <note priority="1" from="meaning">liquidity-ad.channel-fee-rate</note>
 | 
			
		||||
@ -6456,7 +6451,7 @@
 | 
			
		||||
        <target>Frais de base du canal</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">176,178</context>
 | 
			
		||||
          <context context-type="linenumber">179,181</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.channel-base-fee</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6465,7 +6460,7 @@
 | 
			
		||||
        <target>Location compacte</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">188,190</context>
 | 
			
		||||
          <context context-type="linenumber">191,193</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.compact-lease</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6474,7 +6469,7 @@
 | 
			
		||||
        <target>Enregistrements d'extension TLV</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">199,202</context>
 | 
			
		||||
          <context context-type="linenumber">202,205</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">node.tlv.records</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6483,7 +6478,7 @@
 | 
			
		||||
        <target>Canaux ouverts</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">240,243</context>
 | 
			
		||||
          <context context-type="linenumber">243,246</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.open-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6492,7 +6487,7 @@
 | 
			
		||||
        <target>Canaux fermés</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">244,247</context>
 | 
			
		||||
          <context context-type="linenumber">247,250</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.open-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6562,9 +6557,9 @@
 | 
			
		||||
          <context context-type="linenumber">112,107</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="1055322764280599360" datatype="html">
 | 
			
		||||
        <source>Reachable on Clearnet Only</source>
 | 
			
		||||
        <target>Accessible uniquement sur Clearnet</target>
 | 
			
		||||
      <trans-unit id="599038141003770125" datatype="html">
 | 
			
		||||
        <source>Clearnet and Darknet</source>
 | 
			
		||||
        <target>Clearnet et Darknet</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">164,161</context>
 | 
			
		||||
@ -6574,9 +6569,9 @@
 | 
			
		||||
          <context context-type="linenumber">303,302</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="2760682261176173881" datatype="html">
 | 
			
		||||
        <source>Reachable on Clearnet and Darknet</source>
 | 
			
		||||
        <target>Accessible sur Clearnet et Darknet</target>
 | 
			
		||||
      <trans-unit id="1282458597026430784" datatype="html">
 | 
			
		||||
        <source>Clearnet Only (IPv4, IPv6)</source>
 | 
			
		||||
        <target>Clearnet seulement (IPv4, IPv6)</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">185,182</context>
 | 
			
		||||
@ -6586,9 +6581,9 @@
 | 
			
		||||
          <context context-type="linenumber">295,294</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="1191036460161514668" datatype="html">
 | 
			
		||||
        <source>Reachable on Darknet Only</source>
 | 
			
		||||
        <target>Accessible uniquement sur Darknet</target>
 | 
			
		||||
      <trans-unit id="2165336009914523952" datatype="html">
 | 
			
		||||
        <source>Darknet Only (Tor, I2P, cjdns)</source>
 | 
			
		||||
        <target>Darknet seulement (Tor, I2P, cjdns)</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">206,203</context>
 | 
			
		||||
@ -6844,24 +6839,6 @@
 | 
			
		||||
          <context context-type="linenumber">27</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="71bb1ed9da9ebb92cf35925bc6fe0a8fbc325625" datatype="html">
 | 
			
		||||
        <source>Top 100 nodes liquidity ranking</source>
 | 
			
		||||
        <target>Classement des 100 meilleurs nœuds par liquidité</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">3,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.top-100-liquidity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="99786bd2106b708e4514d0121964affb19bee636" datatype="html">
 | 
			
		||||
        <source>Top 100 nodes connectivity ranking</source>
 | 
			
		||||
        <target>Classement des 100 meilleurs nœuds par connectivité</target>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">3,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.top-100-connectivity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="47a30fc5a836252f8fe03e2949756b150684d934" datatype="html">
 | 
			
		||||
        <source>Oldest nodes</source>
 | 
			
		||||
        <target>Nœuds les plus anciens</target>
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -715,7 +715,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">385,389</context>
 | 
			
		||||
          <context context-type="linenumber">375,378</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/mining-dashboard/mining-dashboard.component.html</context>
 | 
			
		||||
@ -1349,14 +1349,14 @@
 | 
			
		||||
        <source>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.</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,17</context>
 | 
			
		||||
          <context context-type="linenumber">13,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="a24b1c6a9c4334ba204e4cec2dd9f32ea33d043f" datatype="html">
 | 
			
		||||
        <source>Enterprise Sponsors 🚀</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">29,32</context>
 | 
			
		||||
          <context context-type="linenumber">19,22</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.sponsors.enterprise.withRocket</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1364,7 +1364,7 @@
 | 
			
		||||
        <source>Community Sponsors ❤️</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">177,180</context>
 | 
			
		||||
          <context context-type="linenumber">167,170</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.sponsors.withHeart</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1372,7 +1372,7 @@
 | 
			
		||||
        <source>Community Integrations</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">191,193</context>
 | 
			
		||||
          <context context-type="linenumber">181,183</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.community-integrations</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1380,7 +1380,7 @@
 | 
			
		||||
        <source>Community Alliances</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">285,287</context>
 | 
			
		||||
          <context context-type="linenumber">275,277</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.alliances</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1388,7 +1388,7 @@
 | 
			
		||||
        <source>Project Translators</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">301,303</context>
 | 
			
		||||
          <context context-type="linenumber">291,293</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.translators</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1396,7 +1396,7 @@
 | 
			
		||||
        <source>Project Contributors</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">315,317</context>
 | 
			
		||||
          <context context-type="linenumber">305,307</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.contributors</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1404,7 +1404,7 @@
 | 
			
		||||
        <source>Project Members</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">327,329</context>
 | 
			
		||||
          <context context-type="linenumber">317,319</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.project_members</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1412,7 +1412,7 @@
 | 
			
		||||
        <source>Project Maintainers</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">340,342</context>
 | 
			
		||||
          <context context-type="linenumber">330,332</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">about.maintainers</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -1420,7 +1420,7 @@
 | 
			
		||||
        <source>About</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/about/about.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">39</context>
 | 
			
		||||
          <context context-type="linenumber">42</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/bisq-master-page/bisq-master-page.component.html</context>
 | 
			
		||||
@ -1466,7 +1466,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/amount/amount.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">18,21</context>
 | 
			
		||||
          <context context-type="linenumber">20,23</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/components/asset-circulation/asset-circulation.component.html</context>
 | 
			
		||||
@ -2502,11 +2502,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">52,55</context>
 | 
			
		||||
          <context context-type="linenumber">55,58</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">96,100</context>
 | 
			
		||||
          <context context-type="linenumber">99,103</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
@ -2696,15 +2696,15 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">86,88</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">96,98</context>
 | 
			
		||||
          <context context-type="linenumber">103,105</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">218,222</context>
 | 
			
		||||
          <context context-type="linenumber">221,225</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Transaction Details</note>
 | 
			
		||||
        <note priority="1" from="meaning">transaction.details</note>
 | 
			
		||||
@ -2723,10 +2723,6 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel-preview.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">70,75</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">109,115</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node-preview.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">66,69</context>
 | 
			
		||||
@ -4294,7 +4290,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">67,70</context>
 | 
			
		||||
          <context context-type="linenumber">70,73</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -4310,11 +4306,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,15</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,15</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Transaction first seen</note>
 | 
			
		||||
        <note priority="1" from="meaning">transaction.first-seen</note>
 | 
			
		||||
@ -4982,7 +4978,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">180,182</context>
 | 
			
		||||
          <context context-type="linenumber">183,185</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">shared.m-sats</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5088,7 +5084,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5104,7 +5100,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5120,7 +5116,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
          <context context-type="linenumber">15,16</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5140,7 +5136,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">29,30</context>
 | 
			
		||||
          <context context-type="linenumber">36,37</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.created</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5152,7 +5148,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">48,49</context>
 | 
			
		||||
          <context context-type="linenumber">55,56</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5186,6 +5182,10 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-isp/nodes-per-isp.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">60,62</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">13,14</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">202,201</context>
 | 
			
		||||
@ -5220,11 +5220,11 @@
 | 
			
		||||
        <source>Lightning channel</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">2,5</context>
 | 
			
		||||
          <context context-type="linenumber">4,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">117,119</context>
 | 
			
		||||
          <context context-type="linenumber">116,118</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.channel</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5232,11 +5232,11 @@
 | 
			
		||||
        <source>Last update</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">33,34</context>
 | 
			
		||||
          <context context-type="linenumber">40,41</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">73,75</context>
 | 
			
		||||
          <context context-type="linenumber">76,78</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -5252,11 +5252,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
          <context context-type="linenumber">16,17</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
          <context context-type="linenumber">16,17</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.last-update</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5264,7 +5264,7 @@
 | 
			
		||||
        <source>Closing date</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">37,38</context>
 | 
			
		||||
          <context context-type="linenumber">44,45</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channels-list/channels-list.component.html</context>
 | 
			
		||||
@ -5276,7 +5276,7 @@
 | 
			
		||||
        <source>Closed by</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">52,54</context>
 | 
			
		||||
          <context context-type="linenumber">59,61</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.closed_by</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5284,7 +5284,7 @@
 | 
			
		||||
        <source>Opening transaction</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">84,85</context>
 | 
			
		||||
          <context context-type="linenumber">91,92</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.opening-transaction</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5292,7 +5292,7 @@
 | 
			
		||||
        <source>Closing transaction</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/channel/channel.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
          <context context-type="linenumber">100,102</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.closing-transaction</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5368,11 +5368,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">10,11</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">10,12</context>
 | 
			
		||||
          <context context-type="linenumber">11,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.alias</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5628,10 +5628,6 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.liquidity</note>
 | 
			
		||||
@ -5684,11 +5680,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
          <context context-type="linenumber">14,15</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">11,12</context>
 | 
			
		||||
          <context context-type="linenumber">12,13</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts</context>
 | 
			
		||||
@ -5724,7 +5720,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">47,49</context>
 | 
			
		||||
          <context context-type="linenumber">50,52</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-country/nodes-per-country.component.html</context>
 | 
			
		||||
@ -5740,11 +5736,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">15,17</context>
 | 
			
		||||
          <context context-type="linenumber">17,20</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">15,17</context>
 | 
			
		||||
          <context context-type="linenumber">17,20</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.location</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5778,9 +5774,17 @@
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/lightning-dashboard/lightning-dashboard.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">62</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">4,9</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">29</context>
 | 
			
		||||
          <context context-type="linenumber">33</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">4,9</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-rankings-dashboard/nodes-rankings-dashboard.component.html</context>
 | 
			
		||||
@ -5854,11 +5858,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">2,4</context>
 | 
			
		||||
          <context context-type="linenumber">4,6</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">260,262</context>
 | 
			
		||||
          <context context-type="linenumber">263,265</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.node</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5870,7 +5874,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">27,30</context>
 | 
			
		||||
          <context context-type="linenumber">30,33</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-capacity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5882,7 +5886,7 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">34,38</context>
 | 
			
		||||
          <context context-type="linenumber">37,41</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5894,19 +5898,11 @@
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">country</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="674378571ab7e72a386f27fd3281558bae821d9d" datatype="html">
 | 
			
		||||
        <source>No node found for public key "<x id="INTERPOLATION" equiv-text="{{ node.public_key | shortenString : 12}}"/>"</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">17,19</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.node-not-found</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="43b48b9c15083a164b401bf3775a4b99f3917699" datatype="html">
 | 
			
		||||
        <source>Average channel size</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">40,43</context>
 | 
			
		||||
          <context context-type="linenumber">43,46</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.active-channels-avg</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5914,7 +5910,7 @@
 | 
			
		||||
        <source>Avg channel distance</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">56,57</context>
 | 
			
		||||
          <context context-type="linenumber">59,60</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.avg-distance</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5922,7 +5918,7 @@
 | 
			
		||||
        <source>Color</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">79,81</context>
 | 
			
		||||
          <context context-type="linenumber">82,84</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.color</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5930,7 +5926,7 @@
 | 
			
		||||
        <source>ISP</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">86,87</context>
 | 
			
		||||
          <context context-type="linenumber">89,90</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-per-isp-chart/nodes-per-isp-chart.component.html</context>
 | 
			
		||||
@ -5942,7 +5938,7 @@
 | 
			
		||||
        <source>Exclusively on Tor</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">93,95</context>
 | 
			
		||||
          <context context-type="linenumber">96,98</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">tor</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5950,7 +5946,7 @@
 | 
			
		||||
        <source>Liquidity ad</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">138,141</context>
 | 
			
		||||
          <context context-type="linenumber">141,144</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">node.liquidity-ad</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5958,7 +5954,7 @@
 | 
			
		||||
        <source>Lease fee rate</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">144,147</context>
 | 
			
		||||
          <context context-type="linenumber">147,150</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Liquidity ad lease fee rate</note>
 | 
			
		||||
        <note priority="1" from="meaning">liquidity-ad.lease-fee-rate</note>
 | 
			
		||||
@ -5967,7 +5963,7 @@
 | 
			
		||||
        <source>Lease base fee</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">152,154</context>
 | 
			
		||||
          <context context-type="linenumber">155,157</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.lease-base-fee</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5975,7 +5971,7 @@
 | 
			
		||||
        <source>Funding weight</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">158,159</context>
 | 
			
		||||
          <context context-type="linenumber">161,162</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.funding-weight</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -5983,7 +5979,7 @@
 | 
			
		||||
        <source>Channel fee rate</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">168,171</context>
 | 
			
		||||
          <context context-type="linenumber">171,174</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">Liquidity ad channel fee rate</note>
 | 
			
		||||
        <note priority="1" from="meaning">liquidity-ad.channel-fee-rate</note>
 | 
			
		||||
@ -5992,7 +5988,7 @@
 | 
			
		||||
        <source>Channel base fee</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">176,178</context>
 | 
			
		||||
          <context context-type="linenumber">179,181</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.channel-base-fee</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6000,7 +5996,7 @@
 | 
			
		||||
        <source>Compact lease</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">188,190</context>
 | 
			
		||||
          <context context-type="linenumber">191,193</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">liquidity-ad.compact-lease</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6008,7 +6004,7 @@
 | 
			
		||||
        <source>TLV extension records</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">199,202</context>
 | 
			
		||||
          <context context-type="linenumber">202,205</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">node.tlv.records</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6016,7 +6012,7 @@
 | 
			
		||||
        <source>Open channels</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">240,243</context>
 | 
			
		||||
          <context context-type="linenumber">243,246</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.open-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6024,7 +6020,7 @@
 | 
			
		||||
        <source>Closed channels</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/node/node.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">244,247</context>
 | 
			
		||||
          <context context-type="linenumber">247,250</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.open-channels</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
@ -6088,8 +6084,8 @@
 | 
			
		||||
          <context context-type="linenumber">112,107</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="1055322764280599360" datatype="html">
 | 
			
		||||
        <source>Reachable on Clearnet Only</source>
 | 
			
		||||
      <trans-unit id="599038141003770125" datatype="html">
 | 
			
		||||
        <source>Clearnet and Darknet</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">164,161</context>
 | 
			
		||||
@ -6099,8 +6095,8 @@
 | 
			
		||||
          <context context-type="linenumber">303,302</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="2760682261176173881" datatype="html">
 | 
			
		||||
        <source>Reachable on Clearnet and Darknet</source>
 | 
			
		||||
      <trans-unit id="1282458597026430784" datatype="html">
 | 
			
		||||
        <source>Clearnet Only (IPv4, IPv6)</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">185,182</context>
 | 
			
		||||
@ -6110,8 +6106,8 @@
 | 
			
		||||
          <context context-type="linenumber">295,294</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="1191036460161514668" datatype="html">
 | 
			
		||||
        <source>Reachable on Darknet Only</source>
 | 
			
		||||
      <trans-unit id="2165336009914523952" datatype="html">
 | 
			
		||||
        <source>Darknet Only (Tor, I2P, cjdns)</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts</context>
 | 
			
		||||
          <context context-type="linenumber">206,203</context>
 | 
			
		||||
@ -6343,22 +6339,6 @@
 | 
			
		||||
          <context context-type="linenumber">27</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="71bb1ed9da9ebb92cf35925bc6fe0a8fbc325625" datatype="html">
 | 
			
		||||
        <source>Top 100 nodes liquidity ranking</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">3,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.top-100-liquidity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="99786bd2106b708e4514d0121964affb19bee636" datatype="html">
 | 
			
		||||
        <source>Top 100 nodes connectivity ranking</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
          <context context-type="sourcefile">src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.html</context>
 | 
			
		||||
          <context context-type="linenumber">3,7</context>
 | 
			
		||||
        </context-group>
 | 
			
		||||
        <note priority="1" from="description">lightning.top-100-connectivity</note>
 | 
			
		||||
      </trans-unit>
 | 
			
		||||
      <trans-unit id="47a30fc5a836252f8fe03e2949756b150684d934" datatype="html">
 | 
			
		||||
        <source>Oldest nodes</source>
 | 
			
		||||
        <context-group purpose="location">
 | 
			
		||||
 | 
			
		||||
@ -746,7 +746,37 @@ th {
 | 
			
		||||
  font-family: monospace;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.full-container .card-header .formRadioGroup {
 | 
			
		||||
  margin-top: 6px;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  @media (min-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: -100px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) and (max-width: 991px) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  @media (min-width: 830px) {
 | 
			
		||||
    flex-direction: row;
 | 
			
		||||
    float: right;
 | 
			
		||||
    margin-top: 0px;
 | 
			
		||||
  }
 | 
			
		||||
  .btn-sm {
 | 
			
		||||
    font-size: 9px;
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      font-size: 14px;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.direction-ltr {
 | 
			
		||||
  direction: ltr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rtl-layout {
 | 
			
		||||
  text-align: start;
 | 
			
		||||
 | 
			
		||||
  .navbar-brand {
 | 
			
		||||
    margin-right: 0px;
 | 
			
		||||
@ -882,19 +912,25 @@ th {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .container-graph {
 | 
			
		||||
  .chart {
 | 
			
		||||
    direction: ltr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .formRadioGroup {
 | 
			
		||||
    @media (min-width: 830px) {
 | 
			
		||||
      float: left;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .container-graph, .full-container, .toggle-holder {
 | 
			
		||||
    @extend .container-graph;
 | 
			
		||||
    .formRadioGroup {
 | 
			
		||||
      @extend .formRadioGroup;
 | 
			
		||||
      direction: ltr;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .full-container {
 | 
			
		||||
    @extend .full-container;
 | 
			
		||||
    .formRadioGroup {
 | 
			
		||||
      @extend .formRadioGroup;
 | 
			
		||||
      direction: ltr;
 | 
			
		||||
    .card-header, h1, h2, h3 {
 | 
			
		||||
      direction: rtl;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user