Merge branch 'master' into breathe-effect-framerate
This commit is contained in:
commit
c7014fc6c8
74
.github/workflows/ci.yml
vendored
74
.github/workflows/ci.yml
vendored
@ -1,48 +1,88 @@
|
||||
name: CI Pipeline for the Backend and Frontend
|
||||
|
||||
on:
|
||||
push:
|
||||
env:
|
||||
NODE_VERSION: 16.15.0
|
||||
|
||||
jobs:
|
||||
build_backend:
|
||||
name: Build backend
|
||||
runs-on: ubuntu-latest
|
||||
backend:
|
||||
strategy:
|
||||
matrix:
|
||||
flavor: ['dev', 'prod']
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
name: Backend (${{ matrix.flavor }})
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ${{ matrix.flavor }}
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- name: Install
|
||||
|
||||
- name: Install
|
||||
if: ${{ matrix.flavor == 'dev'}}
|
||||
run: npm install
|
||||
working-directory: ${{ matrix.flavor }}/backend
|
||||
|
||||
- name: Install (Prod dependencies only)
|
||||
if: ${{ matrix.flavor == 'prod'}}
|
||||
run: npm install --prod
|
||||
working-directory: backend
|
||||
# - name: Lint
|
||||
# run: npm run lint
|
||||
working-directory: ${{ matrix.flavor }}/backend
|
||||
|
||||
- name: Lint
|
||||
if: ${{ matrix.flavor == 'dev'}}
|
||||
run: npm run lint
|
||||
working-directory: ${{ matrix.flavor }}/backend
|
||||
|
||||
# - name: Test
|
||||
# run: npm run test
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
working-directory: backend
|
||||
build_frontend:
|
||||
name: Build frontend
|
||||
runs-on: ubuntu-latest
|
||||
working-directory: ${{ matrix.flavor }}/backend
|
||||
|
||||
frontend:
|
||||
strategy:
|
||||
matrix:
|
||||
flavor: ['dev', 'prod']
|
||||
runs-on: 'ubuntu-latest'
|
||||
|
||||
name: Frontend (${{ matrix.flavor }})
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ${{ matrix.flavor }}
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- name: Install
|
||||
run: npm install --prod
|
||||
working-directory: frontend
|
||||
# - name: Lint
|
||||
# run: npm run lint
|
||||
|
||||
- name: Install (Prod dependencies only)
|
||||
run: npm install
|
||||
if: ${{ matrix.flavor == 'prod'}}
|
||||
working-directory: ${{ matrix.flavor }}/frontend
|
||||
|
||||
- name: Install
|
||||
if: ${{ matrix.flavor == 'dev'}}
|
||||
run: npm install
|
||||
working-directory: ${{ matrix.flavor }}/frontend
|
||||
|
||||
- name: Lint
|
||||
run: npm run lint
|
||||
working-directory: ${{ matrix.flavor }}/frontend
|
||||
|
||||
# - name: Test
|
||||
# run: npm run test
|
||||
|
||||
- name: Build
|
||||
run: npm run build
|
||||
working-directory: frontend
|
||||
working-directory: ${{ matrix.flavor }}/frontend
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ sitemap
|
||||
data
|
||||
docker-compose.yml
|
||||
backend/mempool-config.json
|
||||
*.swp
|
||||
|
2
backend/.eslintignore
Normal file
2
backend/.eslintignore
Normal file
@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
dist
|
32
backend/.eslintrc
Normal file
32
backend/.eslintrc
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/ban-ts-comment": 1,
|
||||
"@typescript-eslint/ban-types": 1,
|
||||
"@typescript-eslint/no-empty-function": 1,
|
||||
"@typescript-eslint/no-explicit-any": 1,
|
||||
"@typescript-eslint/no-inferrable-types": 1,
|
||||
"@typescript-eslint/no-namespace": 1,
|
||||
"@typescript-eslint/no-this-alias": 1,
|
||||
"@typescript-eslint/no-var-requires": 1,
|
||||
"no-console": 1,
|
||||
"no-constant-condition": 1,
|
||||
"no-dupe-else-if": 1,
|
||||
"no-empty": 1,
|
||||
"no-prototype-builtins": 1,
|
||||
"no-self-assign": 1,
|
||||
"no-useless-catch": 1,
|
||||
"no-var": 1,
|
||||
"prefer-const": 1,
|
||||
"prefer-rest-params": 1
|
||||
}
|
||||
}
|
2591
backend/package-lock.json
generated
2591
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -24,7 +24,9 @@
|
||||
"build": "npm run tsc",
|
||||
"start": "node --max-old-space-size=2048 dist/index.js",
|
||||
"start-production": "node --max-old-space-size=4096 dist/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "./node_modules/.bin/eslint . --ext .ts",
|
||||
"lint:fix": "./node_modules/.bin/eslint . --ext .ts --fix"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mempool/electrum-client": "^1.1.7",
|
||||
@ -43,6 +45,9 @@
|
||||
"@types/compression": "^1.7.2",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/ws": "~8.5.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"eslint": "^8.19.0",
|
||||
"tslint": "^6.1.0"
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ export interface AbstractBitcoinApi {
|
||||
$getRawMempool(): Promise<IEsploraApi.Transaction['txid'][]>;
|
||||
$getRawTransaction(txId: string, skipConversion?: boolean, addPrevout?: boolean, lazyPrevouts?: boolean): Promise<IEsploraApi.Transaction>;
|
||||
$getBlockHeightTip(): Promise<number>;
|
||||
$getBlockHashTip(): Promise<string>;
|
||||
$getTxIdsForBlock(hash: string): Promise<string[]>;
|
||||
$getBlockHash(height: number): Promise<string>;
|
||||
$getBlockHeader(hash: string): Promise<string>;
|
||||
|
@ -64,6 +64,13 @@ class BitcoinApi implements AbstractBitcoinApi {
|
||||
});
|
||||
}
|
||||
|
||||
$getBlockHashTip(): Promise<string> {
|
||||
return this.bitcoindClient.getChainTips()
|
||||
.then((result: IBitcoinApi.ChainTips[]) => {
|
||||
return result.find(tip => tip.status === 'active')!.hash;
|
||||
});
|
||||
}
|
||||
|
||||
$getTxIdsForBlock(hash: string): Promise<string[]> {
|
||||
return this.bitcoindClient.getBlock(hash, 1)
|
||||
.then((rpcBlock: IBitcoinApi.Block) => rpcBlock.tx);
|
||||
|
@ -25,6 +25,11 @@ class ElectrsApi implements AbstractBitcoinApi {
|
||||
.then((response) => response.data);
|
||||
}
|
||||
|
||||
$getBlockHashTip(): Promise<string> {
|
||||
return axios.get<string>(config.ESPLORA.REST_API_URL + '/blocks/tip/hash', this.axiosConfig)
|
||||
.then((response) => response.data);
|
||||
}
|
||||
|
||||
$getTxIdsForBlock(hash: string): Promise<string[]> {
|
||||
return axios.get<string[]>(config.ESPLORA.REST_API_URL + '/block/' + hash + '/txids', this.axiosConfig)
|
||||
.then((response) => response.data);
|
||||
|
@ -19,6 +19,9 @@ import HashratesRepository from '../repositories/HashratesRepository';
|
||||
import indexer from '../indexer';
|
||||
import poolsParser from './pools-parser';
|
||||
import BlocksSummariesRepository from '../repositories/BlocksSummariesRepository';
|
||||
import mining from './mining';
|
||||
import DifficultyAdjustmentsRepository from '../repositories/DifficultyAdjustmentsRepository';
|
||||
import difficultyAdjustment from './difficulty-adjustment';
|
||||
|
||||
class Blocks {
|
||||
private blocks: BlockExtended[] = [];
|
||||
@ -300,12 +303,8 @@ class Blocks {
|
||||
* [INDEXING] Index all blocks metadata for the mining dashboard
|
||||
*/
|
||||
public async $generateBlockDatabase(): Promise<boolean> {
|
||||
const blockchainInfo = await bitcoinClient.getBlockchainInfo();
|
||||
if (blockchainInfo.blocks !== blockchainInfo.headers) { // Wait for node to sync
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
const blockchainInfo = await bitcoinClient.getBlockchainInfo();
|
||||
let currentBlockHeight = blockchainInfo.blocks;
|
||||
|
||||
let indexingBlockAmount = Math.min(config.MEMPOOL.INDEXING_BLOCKS_AMOUNT, blockchainInfo.blocks);
|
||||
@ -449,7 +448,10 @@ class Blocks {
|
||||
const newBlock = await this.$indexBlock(lastBlock['height'] - i);
|
||||
await this.$getStrippedBlockTransactions(newBlock.id, true, true);
|
||||
}
|
||||
logger.info(`Re-indexed 10 blocks and summaries`);
|
||||
await mining.$indexDifficultyAdjustments();
|
||||
await DifficultyAdjustmentsRepository.$deleteLastAdjustment();
|
||||
logger.info(`Re-indexed 10 blocks and summaries. Also re-indexed the last difficulty adjustments. Will re-index latest hashrates in a few seconds.`);
|
||||
indexer.reindex();
|
||||
}
|
||||
await blocksRepository.$saveBlockInDatabase(blockExtended);
|
||||
|
||||
@ -461,6 +463,15 @@ class Blocks {
|
||||
}
|
||||
|
||||
if (block.height % 2016 === 0) {
|
||||
if (Common.indexingEnabled()) {
|
||||
await DifficultyAdjustmentsRepository.$saveAdjustments({
|
||||
time: block.timestamp,
|
||||
height: block.height,
|
||||
difficulty: block.difficulty,
|
||||
adjustment: Math.round((block.difficulty / this.currentDifficulty) * 1000000) / 1000000, // Remove float point noise
|
||||
});
|
||||
}
|
||||
|
||||
this.previousDifficultyRetarget = (block.difficulty - this.currentDifficulty) / this.currentDifficulty * 100;
|
||||
this.lastDifficultyAdjustmentTime = block.timestamp;
|
||||
this.currentDifficulty = block.difficulty;
|
||||
|
@ -4,7 +4,7 @@ import logger from '../logger';
|
||||
import { Common } from './common';
|
||||
|
||||
class DatabaseMigration {
|
||||
private static currentVersion = 21;
|
||||
private static currentVersion = 22;
|
||||
private queryTimeout = 120000;
|
||||
private statisticsAddedIndexed = false;
|
||||
private uniqueLogs: string[] = [];
|
||||
@ -226,6 +226,11 @@ class DatabaseMigration {
|
||||
await this.$executeQuery('DROP TABLE IF EXISTS `rates`');
|
||||
await this.$executeQuery(this.getCreatePricesTableQuery(), await this.$checkIfTableExists('prices'));
|
||||
}
|
||||
|
||||
if (databaseSchemaVersion < 22 && isBitcoin === true) {
|
||||
await this.$executeQuery('DROP TABLE IF EXISTS `difficulty_adjustments`');
|
||||
await this.$executeQuery(this.getCreateDifficultyAdjustmentsTableQuery(), await this.$checkIfTableExists('difficulty_adjustments'));
|
||||
}
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
@ -513,7 +518,7 @@ class DatabaseMigration {
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
|
||||
}
|
||||
|
||||
private getCreateRatesTableQuery(): string {
|
||||
private getCreateRatesTableQuery(): string { // This table has been replaced by the prices table
|
||||
return `CREATE TABLE IF NOT EXISTS rates (
|
||||
height int(10) unsigned NOT NULL,
|
||||
bisq_rates JSON NOT NULL,
|
||||
@ -539,6 +544,17 @@ class DatabaseMigration {
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
|
||||
}
|
||||
|
||||
private getCreateDifficultyAdjustmentsTableQuery(): string {
|
||||
return `CREATE TABLE IF NOT EXISTS difficulty_adjustments (
|
||||
time timestamp NOT NULL,
|
||||
height int(10) unsigned NOT NULL,
|
||||
difficulty double unsigned NOT NULL,
|
||||
adjustment float NOT NULL,
|
||||
PRIMARY KEY (height),
|
||||
INDEX (time)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;`;
|
||||
}
|
||||
|
||||
public async $truncateIndexedData(tables: string[]) {
|
||||
const allowedTables = ['blocks', 'hashrates', 'prices'];
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { PoolInfo, PoolStats, RewardStats } from '../mempool.interfaces';
|
||||
import { IndexedDifficultyAdjustment, PoolInfo, PoolStats, RewardStats } from '../mempool.interfaces';
|
||||
import BlocksRepository from '../repositories/BlocksRepository';
|
||||
import PoolsRepository from '../repositories/PoolsRepository';
|
||||
import HashratesRepository from '../repositories/HashratesRepository';
|
||||
@ -7,6 +7,7 @@ import logger from '../logger';
|
||||
import { Common } from './common';
|
||||
import loadingIndicators from './loading-indicators';
|
||||
import { escape } from 'mysql2';
|
||||
import DifficultyAdjustmentsRepository from '../repositories/DifficultyAdjustmentsRepository';
|
||||
|
||||
class Mining {
|
||||
constructor() {
|
||||
@ -377,6 +378,48 @@ class Mining {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Index difficulty adjustments
|
||||
*/
|
||||
public async $indexDifficultyAdjustments(): Promise<void> {
|
||||
const indexedHeightsArray = await DifficultyAdjustmentsRepository.$getAdjustmentsHeights();
|
||||
const indexedHeights = {};
|
||||
for (const height of indexedHeightsArray) {
|
||||
indexedHeights[height] = true;
|
||||
}
|
||||
|
||||
const blocks: any = await BlocksRepository.$getBlocksDifficulty();
|
||||
|
||||
let currentDifficulty = 0;
|
||||
let totalIndexed = 0;
|
||||
|
||||
for (const block of blocks) {
|
||||
if (block.difficulty !== currentDifficulty) {
|
||||
if (block.height === 0 || indexedHeights[block.height] === true) { // Already indexed
|
||||
currentDifficulty = block.difficulty;
|
||||
continue;
|
||||
}
|
||||
|
||||
let adjustment = block.difficulty / Math.max(1, currentDifficulty);
|
||||
adjustment = Math.round(adjustment * 1000000) / 1000000; // Remove float point noise
|
||||
|
||||
await DifficultyAdjustmentsRepository.$saveAdjustments({
|
||||
time: block.time,
|
||||
height: block.height,
|
||||
difficulty: block.difficulty,
|
||||
adjustment: adjustment,
|
||||
});
|
||||
|
||||
totalIndexed++;
|
||||
currentDifficulty = block.difficulty;
|
||||
}
|
||||
}
|
||||
|
||||
if (totalIndexed > 0) {
|
||||
logger.notice(`Indexed ${totalIndexed} difficulty adjustments`);
|
||||
}
|
||||
}
|
||||
|
||||
private getDateMidnight(date: Date): Date {
|
||||
date.setUTCHours(0);
|
||||
date.setUTCMinutes(0);
|
||||
|
@ -290,6 +290,7 @@ class Server {
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/rewards/:interval', routes.$getHistoricalBlockRewards)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/fee-rates/:interval', routes.$getHistoricalBlockFeeRates)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/blocks/sizes-weights/:interval', routes.$getHistoricalBlockSizeAndWeight)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'mining/difficulty-adjustments/:interval', routes.$getDifficultyAdjustments)
|
||||
;
|
||||
}
|
||||
|
||||
@ -332,6 +333,7 @@ class Server {
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'tx/:txId/outspends', routes.getTransactionOutspends)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/header', routes.getBlockHeader)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'blocks/tip/height', routes.getBlockTipHeight)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'blocks/tip/hash', routes.getBlockTipHash)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/txs', routes.getBlockTransactions)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/txs/:index', routes.getBlockTransactions)
|
||||
.get(config.MEMPOOL.API_URL_PREFIX + 'block/:hash/txids', routes.getTxIdsForBlock)
|
||||
|
@ -4,6 +4,7 @@ import mempool from './api/mempool';
|
||||
import mining from './api/mining';
|
||||
import logger from './logger';
|
||||
import HashratesRepository from './repositories/HashratesRepository';
|
||||
import bitcoinClient from './api/bitcoin/bitcoin-client';
|
||||
|
||||
class Indexer {
|
||||
runIndexer = true;
|
||||
@ -25,6 +26,12 @@ class Indexer {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do not attempt to index anything unless Bitcoin Core is fully synced
|
||||
const blockchainInfo = await bitcoinClient.getBlockchainInfo();
|
||||
if (blockchainInfo.blocks !== blockchainInfo.headers) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.runIndexer = false;
|
||||
this.indexerRunning = true;
|
||||
|
||||
@ -36,6 +43,7 @@ class Indexer {
|
||||
return;
|
||||
}
|
||||
|
||||
await mining.$indexDifficultyAdjustments();
|
||||
await this.$resetHashratesIndexingState();
|
||||
await mining.$generateNetworkHashrateHistory();
|
||||
await mining.$generatePoolHashrateHistory();
|
||||
|
@ -224,6 +224,13 @@ export interface IDifficultyAdjustment {
|
||||
timeOffset: number;
|
||||
}
|
||||
|
||||
export interface IndexedDifficultyAdjustment {
|
||||
time: number; // UNIX timestamp
|
||||
height: number; // Block height
|
||||
difficulty: number;
|
||||
adjustment: number;
|
||||
}
|
||||
|
||||
export interface RewardStats {
|
||||
totalReward: number;
|
||||
totalFee: number;
|
||||
|
@ -7,6 +7,7 @@ import PoolsRepository from './PoolsRepository';
|
||||
import HashratesRepository from './HashratesRepository';
|
||||
import { escape } from 'mysql2';
|
||||
import BlocksSummariesRepository from './BlocksSummariesRepository';
|
||||
import DifficultyAdjustmentsRepository from './DifficultyAdjustmentsRepository';
|
||||
|
||||
class BlocksRepository {
|
||||
/**
|
||||
@ -381,48 +382,9 @@ class BlocksRepository {
|
||||
/**
|
||||
* Return blocks difficulty
|
||||
*/
|
||||
public async $getBlocksDifficulty(interval: string | null): Promise<object[]> {
|
||||
interval = Common.getSqlInterval(interval);
|
||||
|
||||
// :D ... Yeah don't ask me about this one https://stackoverflow.com/a/40303162
|
||||
// Basically, using temporary user defined fields, we are able to extract all
|
||||
// difficulty adjustments from the blocks tables.
|
||||
// This allow use to avoid indexing it in another table.
|
||||
let query = `
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
UNIX_TIMESTAMP(blockTimestamp) as timestamp, difficulty, height,
|
||||
IF(@prevStatus = YT.difficulty, @rn := @rn + 1,
|
||||
IF(@prevStatus := YT.difficulty, @rn := 1, @rn := 1)
|
||||
) AS rn
|
||||
FROM blocks YT
|
||||
CROSS JOIN
|
||||
(
|
||||
SELECT @prevStatus := -1, @rn := 1
|
||||
) AS var
|
||||
`;
|
||||
|
||||
if (interval) {
|
||||
query += ` WHERE blockTimestamp BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`;
|
||||
}
|
||||
|
||||
query += `
|
||||
ORDER BY YT.height
|
||||
) AS t
|
||||
WHERE t.rn = 1
|
||||
ORDER BY t.height
|
||||
`;
|
||||
|
||||
public async $getBlocksDifficulty(): Promise<object[]> {
|
||||
try {
|
||||
const [rows]: any[] = await DB.query(query);
|
||||
|
||||
for (const row of rows) {
|
||||
delete row['rn'];
|
||||
}
|
||||
|
||||
const [rows]: any[] = await DB.query(`SELECT UNIX_TIMESTAMP(blockTimestamp) as time, height, difficulty FROM blocks`);
|
||||
return rows;
|
||||
} catch (e) {
|
||||
logger.err('Cannot generate difficulty history. Reason: ' + (e instanceof Error ? e.message : e));
|
||||
@ -452,26 +414,6 @@ class BlocksRepository {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the last 10 blocks chain is valid
|
||||
*/
|
||||
public async $validateRecentBlocks(): Promise<boolean> {
|
||||
try {
|
||||
const [lastBlocks]: any[] = await DB.query(`SELECT height, hash, previous_block_hash FROM blocks ORDER BY height DESC LIMIT 10`);
|
||||
|
||||
for (let i = 0; i < lastBlocks.length - 1; ++i) {
|
||||
if (lastBlocks[i].previous_block_hash !== lastBlocks[i + 1].hash) {
|
||||
logger.warn(`Chain divergence detected at block ${lastBlocks[i].height}, re-indexing most recent data`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return true; // Don't do anything if there is a db error
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the chain of block hash is valid and delete data from the stale branch if needed
|
||||
*/
|
||||
@ -498,6 +440,7 @@ class BlocksRepository {
|
||||
await this.$deleteBlocksFrom(blocks[idx - 1].height);
|
||||
await BlocksSummariesRepository.$deleteBlocksFrom(blocks[idx - 1].height);
|
||||
await HashratesRepository.$deleteHashratesFromTimestamp(blocks[idx - 1].timestamp - 604800);
|
||||
await DifficultyAdjustmentsRepository.$deleteAdjustementsFromHeight(blocks[idx - 1].height);
|
||||
return false;
|
||||
}
|
||||
++idx;
|
||||
|
88
backend/src/repositories/DifficultyAdjustmentsRepository.ts
Normal file
88
backend/src/repositories/DifficultyAdjustmentsRepository.ts
Normal file
@ -0,0 +1,88 @@
|
||||
import { Common } from '../api/common';
|
||||
import DB from '../database';
|
||||
import logger from '../logger';
|
||||
import { IndexedDifficultyAdjustment } from '../mempool.interfaces';
|
||||
|
||||
class DifficultyAdjustmentsRepository {
|
||||
public async $saveAdjustments(adjustment: IndexedDifficultyAdjustment): Promise<void> {
|
||||
if (adjustment.height === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const query = `INSERT INTO difficulty_adjustments(time, height, difficulty, adjustment) VALUE (FROM_UNIXTIME(?), ?, ?, ?)`;
|
||||
const params: any[] = [
|
||||
adjustment.time,
|
||||
adjustment.height,
|
||||
adjustment.difficulty,
|
||||
adjustment.adjustment,
|
||||
];
|
||||
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`);
|
||||
} else {
|
||||
logger.err(`Cannot save difficulty adjustment at block ${adjustment.height}. Reason: ${e instanceof Error ? e.message : e}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async $getAdjustments(interval: string | null, descOrder: boolean = false): Promise<IndexedDifficultyAdjustment[]> {
|
||||
interval = Common.getSqlInterval(interval);
|
||||
|
||||
let query = `SELECT UNIX_TIMESTAMP(time) as time, height, difficulty, adjustment
|
||||
FROM difficulty_adjustments`;
|
||||
|
||||
if (interval) {
|
||||
query += ` WHERE time BETWEEN DATE_SUB(NOW(), INTERVAL ${interval}) AND NOW()`;
|
||||
}
|
||||
|
||||
if (descOrder === true) {
|
||||
query += ` ORDER BY time DESC`;
|
||||
} else {
|
||||
query += ` ORDER BY time`;
|
||||
}
|
||||
|
||||
try {
|
||||
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));
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public async $getAdjustmentsHeights(): Promise<number[]> {
|
||||
try {
|
||||
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}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public async $deleteAdjustementsFromHeight(height: number): Promise<void> {
|
||||
try {
|
||||
logger.info(`Delete newer difficulty adjustments from height ${height} from the database`);
|
||||
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}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
public async $deleteLastAdjustment(): Promise<void> {
|
||||
try {
|
||||
logger.info(`Delete last difficulty adjustment from the database`);
|
||||
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}`);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new DifficultyAdjustmentsRepository();
|
||||
|
@ -26,6 +26,7 @@ import mining from './api/mining';
|
||||
import BlocksRepository from './repositories/BlocksRepository';
|
||||
import HashratesRepository from './repositories/HashratesRepository';
|
||||
import difficultyAdjustment from './api/difficulty-adjustment';
|
||||
import DifficultyAdjustmentsRepository from './repositories/DifficultyAdjustmentsRepository';
|
||||
|
||||
class Routes {
|
||||
constructor() {}
|
||||
@ -653,7 +654,7 @@ class Routes {
|
||||
|
||||
try {
|
||||
const hashrates = await HashratesRepository.$getNetworkDailyHashrate(req.params.interval);
|
||||
const difficulty = await BlocksRepository.$getBlocksDifficulty(req.params.interval);
|
||||
const difficulty = await DifficultyAdjustmentsRepository.$getAdjustments(req.params.interval, false);
|
||||
const blockCount = await BlocksRepository.$blockCount(null, null);
|
||||
res.header('Pragma', 'public');
|
||||
res.header('Cache-control', 'public');
|
||||
@ -730,6 +731,18 @@ class Routes {
|
||||
}
|
||||
}
|
||||
|
||||
public async $getDifficultyAdjustments(req: Request, res: Response) {
|
||||
try {
|
||||
const difficulty = await DifficultyAdjustmentsRepository.$getAdjustments(req.params.interval, true);
|
||||
res.header('Pragma', 'public');
|
||||
res.header('Cache-control', 'public');
|
||||
res.setHeader('Expires', new Date(Date.now() + 1000 * 300).toUTCString());
|
||||
res.json(difficulty.map(adj => [adj.time, adj.height, adj.difficulty, adj.adjustment]));
|
||||
} catch (e) {
|
||||
res.status(500).send(e instanceof Error ? e.message : e);
|
||||
}
|
||||
}
|
||||
|
||||
public async getBlock(req: Request, res: Response) {
|
||||
try {
|
||||
const block = await blocks.$getBlock(req.params.hash);
|
||||
@ -925,6 +938,16 @@ class Routes {
|
||||
}
|
||||
}
|
||||
|
||||
public async getBlockTipHash(req: Request, res: Response) {
|
||||
try {
|
||||
const result = await bitcoinApi.$getBlockHashTip();
|
||||
res.setHeader('content-type', 'text/plain');
|
||||
res.send(result);
|
||||
} catch (e) {
|
||||
res.status(500).send(e instanceof Error ? e.message : e);
|
||||
}
|
||||
}
|
||||
|
||||
public async getTxIdsForBlock(req: Request, res: Response) {
|
||||
try {
|
||||
const result = await bitcoinApi.$getTxIdsForBlock(req.params.hash);
|
||||
|
3
frontend/.eslintignore
Normal file
3
frontend/.eslintignore
Normal file
@ -0,0 +1,3 @@
|
||||
node_modules
|
||||
dist
|
||||
frontend
|
34
frontend/.eslintrc
Normal file
34
frontend/.eslintrc
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/ban-ts-comment": 1,
|
||||
"@typescript-eslint/ban-types": 1,
|
||||
"@typescript-eslint/no-empty-function": 1,
|
||||
"@typescript-eslint/no-explicit-any": 1,
|
||||
"@typescript-eslint/no-inferrable-types": 1,
|
||||
"@typescript-eslint/no-namespace": 1,
|
||||
"@typescript-eslint/no-this-alias": 1,
|
||||
"@typescript-eslint/no-var-requires": 1,
|
||||
"no-case-declarations": 1,
|
||||
"no-console": 1,
|
||||
"no-constant-condition": 1,
|
||||
"no-dupe-else-if": 1,
|
||||
"no-empty": 1,
|
||||
"no-extra-boolean-cast": 1,
|
||||
"no-prototype-builtins": 1,
|
||||
"no-self-assign": 1,
|
||||
"no-useless-catch": 1,
|
||||
"no-var": 1,
|
||||
"prefer-const": 1,
|
||||
"prefer-rest-params": 1
|
||||
}
|
||||
}
|
1642
frontend/package-lock.json
generated
1642
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -42,7 +42,8 @@
|
||||
"build-mempool-bisq-js": "browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index-bisq.js --standalone bisqJS > ./dist/mempool/browser/en-US/bisq.js",
|
||||
"build-mempool-liquid-js": "browserify -p tinyify ./node_modules/@mempool/mempool.js/lib/index-liquid.js --standalone liquidJS > ./dist/mempool/browser/en-US/liquid.js",
|
||||
"test": "npm run ng -- test",
|
||||
"lint": "npm run ng -- lint",
|
||||
"lint": "./node_modules/.bin/eslint . --ext .ts",
|
||||
"lint:fix": "./node_modules/.bin/eslint . --ext .ts --fix",
|
||||
"e2e": "npm run generate-config && npm run ng -- e2e",
|
||||
"e2e:ci": "npm run cypress:run:ci",
|
||||
"config:defaults:mempool": "node update-config.js TESTNET_ENABLED=true SIGNET_ENABLED=true LIQUID_ENABLED=true LIQUID_TESTNET_ENABLED=true BISQ_ENABLED=true ITEMS_PER_PAGE=25 BASE_MODULE=mempool BLOCK_WEIGHT_UNITS=4000000 && npm run generate-config",
|
||||
@ -107,7 +108,10 @@
|
||||
"@types/jasmine": "~4.0.3",
|
||||
"@types/jasminewd2": "~2.0.10",
|
||||
"@types/node": "^12.11.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.30.5",
|
||||
"@typescript-eslint/parser": "^5.30.5",
|
||||
"codelyzer": "~6.0.2",
|
||||
"eslint": "^8.19.0",
|
||||
"http-proxy-middleware": "^1.0.5",
|
||||
"jasmine-core": "~4.1.0",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
|
@ -31,7 +31,7 @@ export class BisqTransfersComponent implements OnInit, OnChanges {
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.totalOutput = this.tx.outputs.filter((output) => output.isVerified).reduce((acc, output) => acc + output.bsqAmount, 0);;
|
||||
this.totalOutput = this.tx.outputs.filter((output) => output.isVerified).reduce((acc, output) => acc + output.bsqAmount, 0);
|
||||
}
|
||||
|
||||
switchCurrency() {
|
||||
|
@ -130,7 +130,7 @@
|
||||
<span i18n="address.error.loading-address-data">Error loading address data.</span>
|
||||
<br>
|
||||
<ng-template #displayServerError><i class="small">({{ error.error }})</i></ng-template>
|
||||
<ng-template [ngIf]="error.status === 413 || error.status === 405" [ngIfElse]="displayServerError">
|
||||
<ng-template [ngIf]="error.status === 413 || error.status === 405 || error.status === 504" [ngIfElse]="displayServerError">
|
||||
<ng-container i18n="Electrum server limit exceeded error">
|
||||
<i>There many transactions on this address, more than your backend can handle. See more on <a href="/docs/faq#address-lookup-issues">setting up a stronger backend</a>.</i>
|
||||
<br><br>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]"> ALL
|
||||
</label>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]"> ALL
|
||||
</label>
|
||||
</div>
|
||||
|
@ -36,7 +36,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]"> ALL
|
||||
</label>
|
||||
</div>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]"> ALL
|
||||
</label>
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody *ngIf="(hashrateObservable$ | async) as data">
|
||||
<tr *ngFor="let diffChange of data.difficulty">
|
||||
<tr *ngFor="let diffChange of data">
|
||||
<td class="d-none d-md-block"><a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height
|
||||
}}</a></td>
|
||||
<td class="text-left">
|
||||
@ -17,7 +17,7 @@
|
||||
</td>
|
||||
<td class="text-right">{{ diffChange.difficultyShorten }}</td>
|
||||
<td class="text-right" [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'">
|
||||
{{ diffChange.change >= 0 ? '+' : '' }}{{ diffChange.change | amountShortener }}%
|
||||
{{ diffChange.change >= 0 ? '+' : '' }}{{ diffChange.change | amountShortener: 2 }}%
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -30,27 +30,24 @@ export class DifficultyAdjustmentsTable implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.hashrateObservable$ = this.apiService.getHistoricalHashrate$('1y')
|
||||
this.hashrateObservable$ = this.apiService.getDifficultyAdjustments$('3m')
|
||||
.pipe(
|
||||
map((response) => {
|
||||
const data = response.body;
|
||||
const tableData = [];
|
||||
for (let i = data.difficulty.length - 1; i > 0; --i) {
|
||||
const selectedPowerOfTen: any = selectPowerOfTen(data.difficulty[i].difficulty);
|
||||
const change = (data.difficulty[i].difficulty / data.difficulty[i - 1].difficulty - 1) * 100;
|
||||
|
||||
tableData.push(Object.assign(data.difficulty[i], {
|
||||
change: Math.round(change * 100) / 100,
|
||||
for (const adjustment of data) {
|
||||
const selectedPowerOfTen: any = selectPowerOfTen(adjustment[2]);
|
||||
tableData.push({
|
||||
height: adjustment[1],
|
||||
timestamp: adjustment[0],
|
||||
change: (adjustment[3] - 1) * 100,
|
||||
difficultyShorten: formatNumber(
|
||||
data.difficulty[i].difficulty / selectedPowerOfTen.divider,
|
||||
adjustment[2] / selectedPowerOfTen.divider,
|
||||
this.locale, '1.2-2') + selectedPowerOfTen.unit
|
||||
}));
|
||||
});
|
||||
}
|
||||
this.isLoading = false;
|
||||
|
||||
return {
|
||||
difficulty: tableData.slice(0, 6),
|
||||
};
|
||||
return tableData.slice(0, 6);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
@ -5,8 +5,8 @@
|
||||
</div>
|
||||
<div class="band-separator fill"></div>
|
||||
<div class="fee-progress-bar priority" [style.background]="gradient">
|
||||
<span class="fee-label prority" i18n="fees-box.low-priority" i18n-ngbTooltip="Transaction feerate tooltip (low priority)" ngbTooltip="Places your transaction in between the second and third mempool blocks" placement="top">Low Priority</span>
|
||||
<span class="fee-label prority" i18n="fees-box.medium-priority" i18n-ngbTooltip="Transaction feerate tooltip (medium priority)" ngbTooltip="Places your transaction in between the first and second mempool blocks" placement="top">Medium Priority</span>
|
||||
<span class="fee-label prority" i18n="fees-box.low-priority" i18n-ngbTooltip="Transaction feerate tooltip (low priority)" ngbTooltip="Usually places your transaction in between the second and third mempool blocks" placement="top">Low Priority</span>
|
||||
<span class="fee-label prority" i18n="fees-box.medium-priority" i18n-ngbTooltip="Transaction feerate tooltip (medium priority)" ngbTooltip="Usually places your transaction in between the first and second mempool blocks" placement="top">Medium Priority</span>
|
||||
<span class="fee-label prority" i18n="fees-box.high-priority" i18n-ngbTooltip="Transaction feerate tooltip (high priority)" ngbTooltip="Places your transaction in the first mempool block" placement="top">High Priority</span>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -42,7 +42,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]"> ALL
|
||||
</label>
|
||||
</div>
|
||||
|
@ -95,6 +95,7 @@ export class HashrateChartComponent implements OnInit {
|
||||
.pipe(
|
||||
tap((response) => {
|
||||
const data = response.body;
|
||||
|
||||
// We generate duplicated data point so the tooltip works nicely
|
||||
const diffFixed = [];
|
||||
let diffIndex = 1;
|
||||
@ -112,7 +113,7 @@ export class HashrateChartComponent implements OnInit {
|
||||
}
|
||||
|
||||
while (hashIndex < data.hashrates.length && diffIndex < data.difficulty.length &&
|
||||
data.hashrates[hashIndex].timestamp <= data.difficulty[diffIndex].timestamp
|
||||
data.hashrates[hashIndex].timestamp <= data.difficulty[diffIndex].time
|
||||
) {
|
||||
diffFixed.push({
|
||||
timestamp: data.hashrates[hashIndex].timestamp,
|
||||
|
@ -21,7 +21,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]"> ALL
|
||||
</label>
|
||||
</div>
|
||||
|
@ -66,7 +66,7 @@
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 157680">
|
||||
<input ngbButton type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools' | relativeUrl]"> 3Y
|
||||
</label>
|
||||
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.totalBlockCount > 157680">
|
||||
<label ngbButtonLabel class="btn-primary btn-sm">
|
||||
<input ngbButton type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools' | relativeUrl]"><span i18n>All</span>
|
||||
</label>
|
||||
</div>
|
||||
|
@ -17,15 +17,15 @@ export class ApiDocsNavComponent implements OnInit {
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
if( this.whichTab === 'rest' ) {
|
||||
if (this.whichTab === 'rest') {
|
||||
this.tabData = restApiDocsData;
|
||||
} else if( this.whichTab = 'faq' ) {
|
||||
} else if (this.whichTab === 'faq') {
|
||||
this.tabData = faqData;
|
||||
}
|
||||
}
|
||||
|
||||
navLinkClick( event ) {
|
||||
this.navLinkClickEvent.emit( event );
|
||||
|
||||
navLinkClick(event) {
|
||||
this.navLinkClickEvent.emit(event);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
<h2 i18n="documentation.title">Documentation</h2>
|
||||
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTab" class="nav-tabs" role="tablist">
|
||||
<ul ngbNav #nav="ngbNav" [animation]="false" [(activeId)]="activeTab" class="nav-tabs" role="tablist">
|
||||
|
||||
<li [ngbNavItem]="0" *ngIf="showFaqTab" role="presentation">
|
||||
<a ngbNavLink [routerLink]="['/docs/faq' | relativeUrl]" role="tab">FAQ</a>
|
||||
|
@ -140,7 +140,7 @@ export class ApiService {
|
||||
this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/pools` +
|
||||
(interval !== undefined ? `/${interval}` : ''), { observe: 'response' }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getPoolStats$(slug: string): Observable<PoolStat> {
|
||||
return this.httpClient.get<PoolStat>(this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/pool/${slug}`);
|
||||
@ -172,6 +172,13 @@ export class ApiService {
|
||||
return this.httpClient.get<TransactionStripped[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/block/' + hash + '/summary');
|
||||
}
|
||||
|
||||
getDifficultyAdjustments$(interval: string | undefined): Observable<any> {
|
||||
return this.httpClient.get<any[]>(
|
||||
this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/difficulty-adjustments` +
|
||||
(interval !== undefined ? `/${interval}` : ''), { observe: 'response' }
|
||||
);
|
||||
}
|
||||
|
||||
getHistoricalHashrate$(interval: string | undefined): Observable<any> {
|
||||
return this.httpClient.get<any[]>(
|
||||
this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/hashrate` +
|
||||
|
@ -180,7 +180,7 @@ case $OS in
|
||||
TOR_PKG=tor
|
||||
TOR_USER=_tor
|
||||
TOR_GROUP=_tor
|
||||
CERTBOT_PKG=py38-certbot
|
||||
CERTBOT_PKG=py39-certbot
|
||||
;;
|
||||
|
||||
Debian)
|
||||
@ -191,9 +191,9 @@ case $OS in
|
||||
TOR_CONFIGURATION=/etc/tor/torrc
|
||||
TOR_RESOURCES=/var/lib/tor
|
||||
TOR_PKG=tor
|
||||
TOR_USER=tor-debian
|
||||
TOR_GROUP=tor-debian
|
||||
CERTBOT_PKG=python-certbot
|
||||
TOR_USER=debian-tor
|
||||
TOR_GROUP=debian-tor
|
||||
CERTBOT_PKG=python3-certbot-nginx
|
||||
NGINX_CONFIGURATION=/etc/nginx/nginx.conf
|
||||
;;
|
||||
esac
|
||||
@ -320,19 +320,19 @@ LIQUIDTESTNET_ASSET_REGISTRY_DB_NAME=asset_registry_testnet_db
|
||||
|
||||
# packages needed for mempool ecosystem
|
||||
DEBIAN_PKG=()
|
||||
DEBIAN_PKG+=(zsh vim curl screen openssl python3)
|
||||
DEBIAN_PKG+=(zsh vim curl screen openssl python3 dialog cron)
|
||||
DEBIAN_PKG+=(build-essential git git-lfs clang cmake jq)
|
||||
DEBIAN_PKG+=(autotools-dev autoconf automake pkg-config bsdmainutils)
|
||||
DEBIAN_PKG+=(libevent-dev libdb-dev libssl-dev libtool-dev autotools-dev)
|
||||
DEBIAN_PKG+=(libevent-dev libdb-dev libssl-dev libtool autotools-dev)
|
||||
DEBIAN_PKG+=(libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-test-dev libboost-thread-dev)
|
||||
DEBIAN_PKG+=(nodejs npm mariadb-server nginx-core python-certbot-nginx rsync ufw)
|
||||
DEBIAN_PKG+=(nodejs npm mariadb-server nginx-core python3-certbot-nginx rsync ufw)
|
||||
|
||||
# packages needed for mempool ecosystem
|
||||
FREEBSD_PKG=()
|
||||
FREEBSD_PKG+=(zsh sudo git screen curl wget calc neovim)
|
||||
FREEBSD_PKG+=(openssh-portable py38-pip rust llvm90 jq base64 libzmq4)
|
||||
FREEBSD_PKG+=(openssh-portable py39-pip rust llvm90 jq base64 libzmq4)
|
||||
FREEBSD_PKG+=(boost-libs autoconf automake gmake gcc libevent libtool pkgconf)
|
||||
FREEBSD_PKG+=(nginx rsync py38-certbot-nginx mariadb105-server keybase)
|
||||
FREEBSD_PKG+=(nginx rsync py39-certbot-nginx mariadb105-server keybase)
|
||||
|
||||
#############################
|
||||
##### utility functions #####
|
||||
@ -403,15 +403,31 @@ osPackageInstallAll()
|
||||
esac
|
||||
}
|
||||
|
||||
# osUserCreate username home_directory main_groupname [additional_group]
|
||||
osUserCreate()
|
||||
{
|
||||
case $OS in
|
||||
FreeBSD)
|
||||
# pw useradd -d /mempool -g mempool -n mempool
|
||||
osSudo "${ROOT_USER}" pw useradd $*
|
||||
# pw useradd -d /mempool -g mempool [-G additional_group] -n mampool
|
||||
if [ $# -eq 3 ] ; then
|
||||
osSudo "${ROOT_USER}" pw useradd -d "$2" -g "$3" -n "$1"
|
||||
elif [ $# -eq 4 ]; then
|
||||
osSudo "${ROOT_USER}" pw useradd -d "$2" -g "$3" -G "$4" -n "$1"
|
||||
else
|
||||
echo "Illegal number of parameters"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" useradd $*
|
||||
# useradd -d /mempool -g mempool [-G additional_group] mempool
|
||||
if [ $# -eq 3 ] ; then
|
||||
osSudo "${ROOT_USER}" useradd -d "$2" -g "$3" "$1"
|
||||
elif [ $# -eq 4 ]; then
|
||||
osSudo "${ROOT_USER}" useradd -d "$2" -g "$3" -G "$4" "$1"
|
||||
else
|
||||
echo "Illegal number of parameters"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
@ -536,6 +552,86 @@ zfsCreateFilesystems()
|
||||
fi
|
||||
}
|
||||
|
||||
ext4CreateDir()
|
||||
{
|
||||
mkdir -p "/backup" "${ELEMENTS_HOME}" "${BITCOIN_HOME}" "${MINFEE_HOME}" "${ELECTRS_HOME}" "${MEMPOOL_HOME}" "${MYSQL_HOME}" "${BITCOIN_ELECTRS_HOME}" "${ELEMENTS_HOME}/liquidv1" "${ELEMENTS_ELECTRS_HOME}"
|
||||
# Bitcoin Mainnet
|
||||
if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then
|
||||
for folder in chainstate indexes blocks
|
||||
do
|
||||
mkdir -p "${BITCOIN_HOME}/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Bitcoin Testnet
|
||||
if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then
|
||||
mkdir -p "${BITCOIN_TESTNET_DATA}"
|
||||
for folder in chainstate indexes blocks
|
||||
do
|
||||
mkdir -p "${BITCOIN_TESTNET_DATA}/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# Bitcoin Signet
|
||||
if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then
|
||||
mkdir -p "${BITCOIN_SIGNET_DATA}"
|
||||
for folder in chainstate indexes blocks
|
||||
do
|
||||
mkdir -p "${BITCOIN_SIGNET_DATA}/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# electrs mainnet data
|
||||
if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then
|
||||
mkdir -p "${ELECTRS_MAINNET_DATA}"
|
||||
for folder in cache history txstore
|
||||
do
|
||||
mkdir -p "${ELECTRS_MAINNET_DATA}/newindex/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# electrs testnet data
|
||||
if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then
|
||||
mkdir -p "${ELECTRS_TESTNET_DATA}"
|
||||
for folder in cache history txstore
|
||||
do
|
||||
mkdir -p "${ELECTRS_TESTNET_DATA}/newindex/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# electrs signet data
|
||||
if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then
|
||||
mkdir -p "${ELECTRS_SIGNET_DATA}"
|
||||
for folder in cache history txstore
|
||||
do
|
||||
mkdir -p "${ELECTRS_SIGNET_DATA}/newindex/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# electrs liquid data
|
||||
if [ "${ELEMENTS_LIQUID_ENABLE}" = ON ];then
|
||||
mkdir -p "${ELECTRS_LIQUID_DATA}"
|
||||
for folder in cache history txstore
|
||||
do
|
||||
mkdir -p "${ELECTRS_LIQUID_DATA}/newindex/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
# electrs liquidtestnet data
|
||||
if [ "${ELEMENTS_LIQUIDTESTNET_ENABLE}" = ON ];then
|
||||
mkdir -p "${ELECTRS_LIQUIDTESTNET_DATA}"
|
||||
for folder in cache history txstore
|
||||
do
|
||||
mkdir -p "${ELECTRS_LIQUIDTESTNET_DATA}/newindex/${folder}"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "${BISQ_INSTALL}" = ON ];then
|
||||
mkdir -p "${BISQ_HOME}"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
##### Perform sanity checks before trying anything
|
||||
|
||||
# what OS running, what FS partitions, etc.
|
||||
@ -683,99 +779,42 @@ HOSTNAME=$(cat $tempfile)
|
||||
|
||||
$DIALOG --ok-label "Submit" \
|
||||
--backtitle "$backtitle" "$@" \
|
||||
--form "Your fullnode will be installed as follows:" 30 70 0 \
|
||||
"BISQ_BLOCKNOTIFY_PORT" 1 1 "${BISQ_BLOCKNOTIFY_PORT}" 1 35 35 0 \
|
||||
"BISQ_GROUP" 2 1 "${BISQ_GROUP}" 2 35 35 0 \
|
||||
"BISQ_HOME" 3 1 "${BISQ_HOME}" 3 35 35 0 \
|
||||
"BISQ_INSTALL" 4 1 "${BISQ_INSTALL}" 4 35 35 0 \
|
||||
"BISQ_LATEST_RELEASE" 5 1 "${BISQ_LATEST_RELEASE}" 5 35 35 0 \
|
||||
"BISQ_MAINNET_ENABLE" 6 1 "${BISQ_MAINNET_ENABLE}" 6 35 35 0 \
|
||||
"BISQ_REPO_BRANCH" 7 1 "${BISQ_REPO_BRANCH}" 7 35 35 0 \
|
||||
"BISQ_REPO_NAME" 8 1 "${BISQ_REPO_NAME}" 8 35 35 0 \
|
||||
"BISQ_REPO_URL" 9 1 "${BISQ_REPO_URL}" 9 35 35 0 \
|
||||
"BISQ_USER" 10 1 "${BISQ_USER}" 10 35 35 0 \
|
||||
"BITCOIN_ELECTRS_COMPACTION" 11 1 "${BITCOIN_ELECTRS_COMPACTION}" 11 35 35 0 \
|
||||
"BITCOIN_ELECTRS_HOME" 12 1 "${BITCOIN_ELECTRS_HOME}" 12 35 35 0 \
|
||||
"BITCOIN_ELECTRS_LATEST_RELEASE" 13 1 "${BITCOIN_ELECTRS_LATEST_RELEASE}" 13 35 35 0 \
|
||||
"BITCOIN_ELECTRS_LIGHT_MODE" 14 1 "${BITCOIN_ELECTRS_LIGHT_MODE}" 14 35 35 0 \
|
||||
"BITCOIN_ELECTRS_REPO_BRANCH" 15 1 "${BITCOIN_ELECTRS_REPO_BRANCH}" 15 35 35 0 \
|
||||
"BITCOIN_ELECTRS_REPO_NAME" 16 1 "${BITCOIN_ELECTRS_REPO_NAME}" 16 35 35 0 \
|
||||
"BITCOIN_ELECTRS_REPO_URL" 17 1 "${BITCOIN_ELECTRS_REPO_URL}" 17 35 35 0 \
|
||||
"BITCOIN_GROUP" 18 1 "${BITCOIN_GROUP}" 18 35 35 0 \
|
||||
"BITCOIN_HOME" 19 1 "${BITCOIN_HOME}" 19 35 35 0 \
|
||||
"BITCOIN_INSTALL" 20 1 "${BITCOIN_INSTALL}" 20 35 35 0 \
|
||||
"BITCOIN_LATEST_RELEASE" 21 1 "${BITCOIN_LATEST_RELEASE}" 21 35 35 0 \
|
||||
"BITCOIN_MAINNET_ENABLE" 22 1 "${BITCOIN_MAINNET_ENABLE}" 22 35 35 0 \
|
||||
"BITCOIN_MAINNET_P2P_HOST" 23 1 "${BITCOIN_MAINNET_P2P_HOST}" 23 35 35 0 \
|
||||
"BITCOIN_MAINNET_P2P_PORT" 24 1 "${BITCOIN_MAINNET_P2P_PORT}" 24 35 35 0 \
|
||||
"BITCOIN_MAINNET_RPC_HOST" 25 1 "${BITCOIN_MAINNET_RPC_HOST}" 25 35 35 0 \
|
||||
"BITCOIN_MAINNET_RPC_PORT" 26 1 "${BITCOIN_MAINNET_RPC_PORT}" 26 35 35 0 \
|
||||
"BITCOIN_RPC_PASS" 27 1 "${BITCOIN_RPC_PASS}" 27 35 35 0 \
|
||||
"BITCOIN_RPC_USER" 28 1 "${BITCOIN_RPC_USER}" 28 35 35 0 \
|
||||
"BITCOIN_REPO_BRANCH" 29 1 "${BITCOIN_REPO_BRANCH}" 29 35 35 0 \
|
||||
"BITCOIN_REPO_NAME" 30 1 "${BITCOIN_REPO_NAME}" 30 35 35 0 \
|
||||
"BITCOIN_REPO_URL" 31 1 "${BITCOIN_REPO_URL}" 31 35 35 0 \
|
||||
"BITCOIN_TESTNET_DATA" 32 1 "${BITCOIN_TESTNET_DATA}" 32 35 35 0 \
|
||||
"BITCOIN_TESTNET_ENABLE" 33 1 "${BITCOIN_TESTNET_ENABLE}" 33 35 35 0 \
|
||||
"BITCOIN_TESTNET_P2P_HOST" 34 1 "${BITCOIN_TESTNET_P2P_HOST}" 34 35 35 0 \
|
||||
"BITCOIN_TESTNET_P2P_PORT" 35 1 "${BITCOIN_TESTNET_P2P_PORT}" 35 35 35 0 \
|
||||
"BITCOIN_TESTNET_RPC_HOST" 36 1 "${BITCOIN_TESTNET_RPC_HOST}" 36 35 35 0 \
|
||||
"BITCOIN_TESTNET_RPC_PORT" 38 1 "${BITCOIN_TESTNET_RPC_PORT}" 38 35 35 0 \
|
||||
"BITCOIN_USER" 40 1 "${BITCOIN_USER}" 40 35 35 0 \
|
||||
"ELECTRS_DATA_ROOT" 41 1 "${ELECTRS_DATA_ROOT}" 41 35 35 0 \
|
||||
"ELECTRS_LIQUID_DATA" 42 1 "${ELECTRS_LIQUID_DATA}" 42 35 35 0 \
|
||||
"ELECTRS_LIQUID_HTTP_HOST" 43 1 "${ELECTRS_LIQUID_HTTP_HOST}" 43 35 35 0 \
|
||||
"ELECTRS_LIQUID_HTTP_PORT" 44 1 "${ELECTRS_LIQUID_HTTP_PORT}" 44 35 35 0 \
|
||||
"ELECTRS_LIQUID_ZPOOL" 45 1 "${ELECTRS_LIQUID_ZPOOL}" 45 35 35 0 \
|
||||
"ELECTRS_MAINNET_DATA" 46 1 "${ELECTRS_MAINNET_DATA}" 46 35 35 0 \
|
||||
"ELECTRS_MAINNET_HTTP_HOST" 47 1 "${ELECTRS_MAINNET_HTTP_HOST}" 47 35 35 0 \
|
||||
"ELECTRS_MAINNET_HTTP_PORT" 48 1 "${ELECTRS_MAINNET_HTTP_PORT}" 48 35 35 0 \
|
||||
"ELECTRS_MAINNET_ZPOOL" 49 1 "${ELECTRS_MAINNET_ZPOOL}" 49 35 35 0 \
|
||||
"ELECTRS_TESTNET_DATA" 50 1 "${ELECTRS_TESTNET_DATA}" 50 35 35 0 \
|
||||
"ELECTRS_TESTNET_HTTP_HOST" 51 1 "${ELECTRS_TESTNET_HTTP_HOST}" 51 35 35 0 \
|
||||
"ELECTRS_TESTNET_HTTP_PORT" 52 1 "${ELECTRS_TESTNET_HTTP_PORT}" 52 35 35 0 \
|
||||
"ELECTRS_TESTNET_ZPOOL" 53 1 "${ELECTRS_TESTNET_ZPOOL}" 53 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_COMPACTION" 54 1 "${ELEMENTS_ELECTRS_COMPACTION}" 54 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_HOME" 55 1 "${ELEMENTS_ELECTRS_HOME}" 55 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_LATEST_RELEASE" 56 1 "${ELEMENTS_ELECTRS_LATEST_RELEASE}" 56 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_LIGHT_MODE" 57 1 "${ELEMENTS_ELECTRS_LIGHT_MODE}" 57 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_REPO_BRANCH" 58 1 "${ELEMENTS_ELECTRS_REPO_BRANCH}" 58 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_REPO_NAME" 59 1 "${ELEMENTS_ELECTRS_REPO_NAME}" 59 35 35 0 \
|
||||
"ELEMENTS_ELECTRS_REPO_URL" 60 1 "${ELEMENTS_ELECTRS_REPO_URL}" 60 35 35 0 \
|
||||
"ELEMENTS_GROUP" 61 1 "${ELEMENTS_GROUP}" 61 35 35 0 \
|
||||
"ELEMENTS_HOME" 62 1 "${ELEMENTS_HOME}" 62 35 35 0 \
|
||||
"ELEMENTS_INSTALL" 63 1 "${ELEMENTS_INSTALL}" 63 35 35 0 \
|
||||
"ELEMENTS_LATEST_RELEASE" 64 1 "${ELEMENTS_LATEST_RELEASE}" 64 35 35 0 \
|
||||
"ELEMENTS_LIQUID_ENABLE" 65 1 "${ELEMENTS_LIQUID_ENABLE}" 65 35 35 0 \
|
||||
"ELEMENTS_LIQUID_P2P_HOST" 66 1 "${ELEMENTS_LIQUID_P2P_HOST}" 66 35 35 0 \
|
||||
"ELEMENTS_LIQUID_P2P_PORT" 67 1 "${ELEMENTS_LIQUID_P2P_PORT}" 67 35 35 0 \
|
||||
"ELEMENTS_LIQUID_RPC_HOST" 68 1 "${ELEMENTS_LIQUID_RPC_HOST}" 68 35 35 0 \
|
||||
"ELEMENTS_RPC_PASS" 69 1 "${ELEMENTS_RPC_PASS}" 69 35 35 0 \
|
||||
"ELEMENTS_LIQUID_RPC_PORT" 70 1 "${ELEMENTS_LIQUID_RPC_PORT}" 70 35 35 0 \
|
||||
"ELEMENTS_RPC_USER" 71 1 "${ELEMENTS_RPC_USER}" 71 35 35 0 \
|
||||
"ELEMENTS_REPO_BRANCH" 72 1 "${ELEMENTS_REPO_BRANCH}" 72 35 35 0 \
|
||||
"ELEMENTS_REPO_NAME" 73 1 "${ELEMENTS_REPO_NAME}" 73 35 35 0 \
|
||||
"ELEMENTS_REPO_URL" 74 1 "${ELEMENTS_REPO_URL}" 74 35 35 0 \
|
||||
"ELEMENTS_USER" 75 1 "${ELEMENTS_USER}" 75 35 35 0 \
|
||||
"MEMPOOL_BISQ_HTTP_HOST" 76 1 "${MEMPOOL_BISQ_HTTP_HOST}" 76 35 35 0 \
|
||||
"MEMPOOL_BISQ_HTTP_PORT" 77 1 "${MEMPOOL_BISQ_HTTP_PORT}" 77 35 35 0 \
|
||||
"MEMPOOL_GROUP" 78 1 "${MEMPOOL_GROUP}" 78 35 35 0 \
|
||||
"MEMPOOL_HOME" 79 1 "${MEMPOOL_HOME}" 79 35 35 0 \
|
||||
"MEMPOOL_LATEST_RELEASE" 80 1 "${MEMPOOL_LATEST_RELEASE}" 80 35 35 0 \
|
||||
"MEMPOOL_LIQUID_HTTP_HOST" 81 1 "${MEMPOOL_LIQUID_HTTP_HOST}" 81 35 35 0 \
|
||||
"MEMPOOL_LIQUID_HTTP_PORT" 82 1 "${MEMPOOL_LIQUID_HTTP_PORT}" 82 35 35 0 \
|
||||
"MEMPOOL_MAINNET_HTTP_HOST" 83 1 "${MEMPOOL_MAINNET_HTTP_HOST}" 83 35 35 0 \
|
||||
"MEMPOOL_MAINNET_HTTP_PORT" 84 1 "${MEMPOOL_MAINNET_HTTP_PORT}" 84 35 35 0 \
|
||||
"MEMPOOL_REPO_BRANCH" 85 1 "${MEMPOOL_REPO_BRANCH}" 85 35 35 0 \
|
||||
"MEMPOOL_REPO_NAME" 86 1 "${MEMPOOL_REPO_NAME}" 86 35 35 0 \
|
||||
"MEMPOOL_REPO_URL" 87 1 "${MEMPOOL_REPO_URL}" 87 35 35 0 \
|
||||
"MEMPOOL_TESTNET_HTTP_HOST" 88 1 "${MEMPOOL_TESTNET_HTTP_HOST}" 88 35 35 0 \
|
||||
"MEMPOOL_TESTNET_HTTP_PORT" 89 1 "${MEMPOOL_TESTNET_HTTP_PORT}" 89 35 35 0 \
|
||||
"MEMPOOL_TOR_HS" 90 1 "${MEMPOOL_TOR_HS}" 90 35 35 0 \
|
||||
"MEMPOOL_USER" 91 1 "${MEMPOOL_USER}" 91 35 35 0 \
|
||||
"HOSTNAME" 92 1 "${HOSTNAME}" 92 35 35 0 \
|
||||
"TOR_INSTALL" 93 1 "${TOR_INSTALL}" 93 35 35 0 \
|
||||
"CERTBOT_INSTALL" 94 1 "${CERTBOT_INSTALL}" 94 35 35 0 \
|
||||
--form "Your fullnode will be installed as follows:" 0 0 0 \
|
||||
"BISQ_LATEST_RELEASE" 1 1 "${BISQ_LATEST_RELEASE}" 1 35 35 0 \
|
||||
"BISQ_REPO_BRANCH" 2 1 "${BISQ_REPO_BRANCH}" 2 35 35 0 \
|
||||
"BISQ_REPO_NAME" 3 1 "${BISQ_REPO_NAME}" 3 35 35 0 \
|
||||
"BISQ_REPO_URL" 4 1 "${BISQ_REPO_URL}" 4 35 35 0 \
|
||||
"BITCOIN_ELECTRS_LATEST_RELEASE" 5 1 "${BITCOIN_ELECTRS_LATEST_RELEASE}" 5 35 35 0 \
|
||||
"BITCOIN_ELECTRS_LIGHT_MODE" 6 1 "${BITCOIN_ELECTRS_LIGHT_MODE}" 6 35 35 0 \
|
||||
"BITCOIN_ELECTRS_REPO_BRANCH" 7 1 "${BITCOIN_ELECTRS_REPO_BRANCH}" 7 35 35 0 \
|
||||
"BITCOIN_ELECTRS_REPO_NAME" 8 1 "${BITCOIN_ELECTRS_REPO_NAME}" 8 35 35 0 \
|
||||
"BITCOIN_ELECTRS_REPO_URL" 9 1 "${BITCOIN_ELECTRS_REPO_URL}" 9 35 35 0 \
|
||||
"BITCOIN_LATEST_RELEASE" 10 1 "${BITCOIN_LATEST_RELEASE}" 10 35 35 0 \
|
||||
"BITCOIN_MAINNET_ENABLE" 11 1 "${BITCOIN_MAINNET_ENABLE}" 11 35 35 0 \
|
||||
"BITCOIN_REPO_BRANCH" 12 1 "${BITCOIN_REPO_BRANCH}" 12 35 35 0 \
|
||||
"BITCOIN_REPO_NAME" 13 1 "${BITCOIN_REPO_NAME}" 13 35 35 0 \
|
||||
"BITCOIN_REPO_URL" 14 1 "${BITCOIN_REPO_URL}" 14 35 35 0 \
|
||||
"BITCOIN_TESTNET_ENABLE" 15 1 "${BITCOIN_TESTNET_ENABLE}" 15 35 35 0 \
|
||||
"ELEMENTS_INSTALL" 16 1 "${ELEMENTS_INSTALL}" 16 35 35 0 \
|
||||
"ELEMENTS_LATEST_RELEASE" 17 1 "${ELEMENTS_LATEST_RELEASE}" 17 35 35 0 \
|
||||
"ELEMENTS_LIQUID_ENABLE" 18 1 "${ELEMENTS_LIQUID_ENABLE}" 18 35 35 0 \
|
||||
"ELEMENTS_REPO_BRANCH" 19 1 "${ELEMENTS_REPO_BRANCH}" 19 35 35 0 \
|
||||
"ELEMENTS_REPO_NAME" 20 1 "${ELEMENTS_REPO_NAME}" 20 35 35 0 \
|
||||
"ELEMENTS_REPO_URL" 21 1 "${ELEMENTS_REPO_URL}" 21 35 35 0 \
|
||||
"MEMPOOL_LATEST_RELEASE" 22 1 "${MEMPOOL_LATEST_RELEASE}" 22 35 35 0 \
|
||||
"MEMPOOL_LIQUID_HTTP_HOST" 23 1 "${MEMPOOL_LIQUID_HTTP_HOST}" 23 35 35 0 \
|
||||
"MEMPOOL_LIQUID_HTTP_PORT" 24 1 "${MEMPOOL_LIQUID_HTTP_PORT}" 24 35 35 0 \
|
||||
"MEMPOOL_MAINNET_HTTP_HOST" 25 1 "${MEMPOOL_MAINNET_HTTP_HOST}" 25 35 35 0 \
|
||||
"MEMPOOL_MAINNET_HTTP_PORT" 26 1 "${MEMPOOL_MAINNET_HTTP_PORT}" 26 35 35 0 \
|
||||
"MEMPOOL_REPO_BRANCH" 27 1 "${MEMPOOL_REPO_BRANCH}" 27 35 35 0 \
|
||||
"MEMPOOL_REPO_NAME" 28 1 "${MEMPOOL_REPO_NAME}" 28 35 35 0 \
|
||||
"MEMPOOL_REPO_URL" 29 1 "${MEMPOOL_REPO_URL}" 29 35 35 0 \
|
||||
"MEMPOOL_TESTNET_HTTP_HOST" 30 1 "${MEMPOOL_TESTNET_HTTP_HOST}" 30 35 35 0 \
|
||||
"MEMPOOL_TESTNET_HTTP_PORT" 31 1 "${MEMPOOL_TESTNET_HTTP_PORT}" 31 35 35 0 \
|
||||
"MEMPOOL_TOR_HS" 32 1 "${MEMPOOL_TOR_HS}" 32 35 35 0 \
|
||||
"HOSTNAME" 33 1 "${HOSTNAME}" 33 35 35 0 \
|
||||
"TOR_INSTALL" 34 1 "${TOR_INSTALL}" 34 35 35 0 \
|
||||
"CERTBOT_INSTALL" 35 1 "${CERTBOT_INSTALL}" 35 35 35 0 \
|
||||
2> $tempfile
|
||||
|
||||
retval=$?
|
||||
@ -802,6 +841,9 @@ case $OS in
|
||||
FreeBSD)
|
||||
zfsCreateFilesystems
|
||||
;;
|
||||
Debian)
|
||||
ext4CreateDir
|
||||
;;
|
||||
esac
|
||||
|
||||
###############################
|
||||
@ -818,7 +860,7 @@ osPackageInstallAll
|
||||
|
||||
echo "[*] Creating Mempool user with Tor access"
|
||||
osGroupCreate "${MEMPOOL_GROUP}"
|
||||
osUserCreate -d "${MEMPOOL_HOME}" -g "${MEMPOOL_GROUP}" -n "${MEMPOOL_USER}"
|
||||
osUserCreate "${MEMPOOL_USER}" "${MEMPOOL_HOME}" "${MEMPOOL_GROUP}"
|
||||
osSudo "${ROOT_USER}" chsh -s `which zsh` "${MEMPOOL_USER}"
|
||||
id "${MEMPOOL_USER}"
|
||||
|
||||
@ -895,12 +937,12 @@ if [ "${BITCOIN_INSTALL}" = ON ];then
|
||||
|
||||
echo "[*] Creating Bitcoin user with Tor access"
|
||||
osGroupCreate "${BITCOIN_GROUP}"
|
||||
osUserCreate -d "${BITCOIN_HOME}" -g "${BITCOIN_GROUP}" -G "${TOR_GROUP}" -n "${BITCOIN_USER}"
|
||||
osUserCreate "${BITCOIN_USER}" "${BITCOIN_HOME}" "${BITCOIN_GROUP}" "${TOR_GROUP}"
|
||||
osSudo "${ROOT_USER}" chsh -s `which zsh` "${BITCOIN_USER}"
|
||||
|
||||
echo "[*] Creating Bitcoin minfee user with Tor access"
|
||||
osGroupCreate "${MINFEE_GROUP}"
|
||||
osUserCreate -d "${MINFEE_HOME}" -g "${MINFEE_GROUP}" -G "${TOR_GROUP}" -n "${MINFEE_USER}"
|
||||
osUserCreate "${MINFEE_USER}" "${MINFEE_HOME}" "${MINFEE_GROUP}" "${TOR_GROUP}"
|
||||
osSudo "${ROOT_USER}" chown -R "${MINFEE_USER}:${MINFEE_GROUP}" "${MINFEE_HOME}"
|
||||
osSudo "${ROOT_USER}" chsh -s `which zsh` "${MINFEE_USER}"
|
||||
osSudo "${MINFEE_USER}" touch "${MINFEE_HOME}/.zshrc"
|
||||
@ -934,10 +976,10 @@ if [ "${BITCOIN_INSTALL}" = ON ];then
|
||||
osSudo "${ROOT_USER}" install -c -o "${MINFEE_USER}" -g "${MINFEE_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/bitcoin.minfee.conf" "${MINFEE_HOME}/bitcoin.conf"
|
||||
|
||||
echo "[*] Installing Bitcoin RPC credentials"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${MINFEE_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${MINFEE_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${MINFEE_HOME}/bitcoin.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${MINFEE_HOME}/bitcoin.conf"
|
||||
fi
|
||||
|
||||
#########################
|
||||
@ -948,7 +990,7 @@ if [ "${ELEMENTS_INSTALL}" = ON ];then
|
||||
|
||||
echo "[*] Creating Elements user with Tor access"
|
||||
osGroupCreate "${ELEMENTS_GROUP}"
|
||||
osUserCreate -d "${ELEMENTS_HOME}" -g "${ELEMENTS_GROUP}" -G "${TOR_GROUP}" -n "${ELEMENTS_USER}"
|
||||
osUserCreate "${ELEMENTS_USER}" "${ELEMENTS_HOME}" "${ELEMENTS_GROUP}" "${TOR_GROUP}"
|
||||
osSudo "${ROOT_USER}" chsh -s `which zsh` "${ELEMENTS_USER}"
|
||||
|
||||
echo "[*] Creating Elements data folder"
|
||||
@ -976,10 +1018,10 @@ if [ "${ELEMENTS_INSTALL}" = ON ];then
|
||||
osSudo "${ROOT_USER}" install -c -o "${ELEMENTS_USER}" -g "${ELEMENTS_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/elements.conf" "${ELEMENTS_HOME}/elements.conf"
|
||||
|
||||
echo "[*] Configuring Elements Liquid RPC credentials in elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
fi
|
||||
|
||||
###################################
|
||||
@ -1013,10 +1055,16 @@ esac
|
||||
echo "[*] Building Bitcoin Electrs release binary"
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd ${BITCOIN_ELECTRS_HOME} && cargo run --release --bin electrs -- --version" || true
|
||||
|
||||
echo "[*] Patching Bitcoin Electrs code for FreeBSD"
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_HOME}/.cargo/registry/src/github.com-1ecc6299db9ec823/sysconf-0.3.4\" && patch -p1 < \"${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/freebsd/sysconf.patch\""
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_ELECTRS_HOME}/src/new_index/\" && sed -i .bak -e s/Snappy/None/ db.rs && rm db.rs.bak"
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_ELECTRS_HOME}/src/bin/\" && sed -i .bak -e 's/from_secs(5)/from_secs(1)/' electrs.rs && rm electrs.rs.bak"
|
||||
case $OS in
|
||||
FreeBSD)
|
||||
echo "[*] Patching Bitcoin Electrs code for FreeBSD"
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_HOME}/.cargo/registry/src/github.com-1ecc6299db9ec823/sysconf-0.3.4\" && patch -p1 < \"${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/freebsd/sysconf.patch\""
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_ELECTRS_HOME}/src/new_index/\" && sed -i.bak -e s/Snappy/None/ db.rs && rm db.rs.bak"
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd \"${BITCOIN_ELECTRS_HOME}/src/bin/\" && sed -i.bak -e 's/from_secs(5)/from_secs(1)/' electrs.rs && rm electrs.rs.bak"
|
||||
;;
|
||||
Debian)
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Building Bitcoin Electrs release binary"
|
||||
osSudo "${BITCOIN_USER}" sh -c "cd ${BITCOIN_ELECTRS_HOME} && cargo run --release --bin electrs -- --version"
|
||||
@ -1059,8 +1107,14 @@ esac
|
||||
echo "[*] Building Liquid Electrs release binary"
|
||||
osSudo "${ELEMENTS_USER}" sh -c "cd ${ELEMENTS_ELECTRS_HOME} && cargo run --release --features liquid --bin electrs -- --network liquid --version" || true
|
||||
|
||||
echo "[*] Patching Liquid Electrs code for FreeBSD"
|
||||
osSudo "${ELEMENTS_USER}" sh -c "cd \"${ELEMENTS_HOME}/.cargo/registry/src/github.com-1ecc6299db9ec823/sysconf-0.3.4\" && patch -p1 < \"${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/freebsd/sysconf.patch\""
|
||||
case $OS in
|
||||
FreeBSD)
|
||||
echo "[*] Patching Liquid Electrs code for FreeBSD"
|
||||
osSudo "${ELEMENTS_USER}" sh -c "cd \"${ELEMENTS_HOME}/.cargo/registry/src/github.com-1ecc6299db9ec823/sysconf-0.3.4\" && patch -p1 < \"${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/freebsd/sysconf.patch\""
|
||||
;;
|
||||
Debian)
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "[*] Building Liquid Electrs release binary"
|
||||
osSudo "${ELEMENTS_USER}" sh -c "cd ${ELEMENTS_ELECTRS_HOME} && cargo run --release --features liquid --bin electrs -- --network liquid --version" || true
|
||||
@ -1073,7 +1127,7 @@ if [ "${BISQ_INSTALL}" = ON ];then
|
||||
|
||||
echo "[*] Creating Bisq user with Tor access"
|
||||
osGroupCreate "${BISQ_GROUP}"
|
||||
osUserCreate -d "${BISQ_HOME}" -g "${BISQ_GROUP}" -G "${TOR_GROUP}" -n "${BISQ_USER}"
|
||||
osUserCreate "${BISQ_USER}" "${BISQ_HOME}" "${BISQ_GROUP}" "${TOR_GROUP}"
|
||||
osSudo "${ROOT_USER}" chsh -s `which zsh` "${BISQ_USER}"
|
||||
|
||||
echo "[*] Creating Bisq data folder"
|
||||
@ -1092,8 +1146,8 @@ if [ "${BISQ_INSTALL}" = ON ];then
|
||||
echo "[*] Cloning Bisq top-level repo"
|
||||
osSudo "${BISQ_USER}" git clone --branch "${BISQ_REPO_BRANCH}" "${BISQ_REPO_URL}" "${BISQ_HOME}/${BISQ_REPO_NAME}"
|
||||
|
||||
echo "[*] Installing OpenJDK 10.0.2 from Bisq install_java.sh script"
|
||||
osSudo "${ROOT_USER}" "${BISQ_HOME}/${BISQ_REPO_NAME}/scripts/install_java.sh"
|
||||
echo "[*] Installing OpenJDK from Bisq install_java_linux.sh script"
|
||||
osSudo "${ROOT_USER}" "${BISQ_HOME}/${BISQ_REPO_NAME}/scripts/install_java_linux.sh"
|
||||
|
||||
echo "[*] Checking out Bisq ${BISQ_LATEST_RELEASE}"
|
||||
osSudo "${BISQ_USER}" sh -c "cd ${BISQ_HOME}/${BISQ_REPO_NAME} && git checkout ${BISQ_LATEST_RELEASE}"
|
||||
@ -1116,26 +1170,26 @@ if [ "${BISQ_INSTALL}" = ON ];then
|
||||
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${BISQ_HOME}/${BISQ_REPO_NAME}/seednode/bisq.service" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/#Requires=bitcoin.service/Requires=bitcoin.service/" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/#BindsTo=bitcoin.service/BindsTo=bitcoin.service/" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BISQ_REPO_NAME__/${BISQ_REPO_NAME}/" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__BISQ_HOME__!${BISQ_HOME}!" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/#Requires=bitcoin.service/Requires=bitcoin.service/" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/#BindsTo=bitcoin.service/BindsTo=bitcoin.service/" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BISQ_REPO_NAME__/${BISQ_REPO_NAME}/" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__BISQ_HOME__!${BISQ_HOME}!" "${DEBIAN_SERVICE_HOME}/bisq.service"
|
||||
|
||||
echo "[*] Installing Bisq environment file"
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${BISQ_HOME}/${BISQ_REPO_NAME}/seednode/bisq.env" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__BISQ_APP_NAME__!${BISQ_APP_NAME}!" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__BISQ_HOME__!${BISQ_HOME}!" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__BISQ_APP_NAME__!${BISQ_APP_NAME}!" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__BISQ_HOME__!${BISQ_HOME}!" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
|
||||
echo "[*] Configuring Bisq environment file with Bitcoin RPC credentials"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_P2P_HOST__/${BITCOIN_MAINNET_P2P_HOST}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_P2P_PORT__/${BITCOIN_MAINNET_P2P_PORT}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_HOST__/${BITCOIN_MAINNET_RPC_HOST}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PORT__/${BITCOIN_MAINNET_RPC_PORT}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_P2P_HOST__/${BITCOIN_MAINNET_P2P_HOST}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_P2P_PORT__/${BITCOIN_MAINNET_P2P_PORT}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_HOST__/${BITCOIN_MAINNET_RPC_HOST}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PORT__/${BITCOIN_MAINNET_RPC_PORT}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${DEBIAN_ENV_HOME}/bisq.env"
|
||||
|
||||
#echo "[*] Updating Bitcoin configuration for Bisq"
|
||||
#osSudo "${ROOT_USER}" sed -i .orig "s/#blocknotify/blocknotify/" "${BITCOIN_HOME}/bitcoin.conf"
|
||||
#osSudo "${ROOT_USER}" sed -i.orig "s/#blocknotify/blocknotify/" "${BITCOIN_HOME}/bitcoin.conf"
|
||||
#osSudo "${BITCOIN_USER}" install -c -o "${BITCOIN_USER}" -g "${BITCOIN_GROUP}" -m 755 "${BISQ_HOME}/${BISQ_REPO_NAME}/seednode/blocknotify.sh" "${BITCOIN_HOME}/blocknotify.sh"
|
||||
;;
|
||||
|
||||
@ -1155,7 +1209,61 @@ if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then
|
||||
;;
|
||||
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/bitcoin-mainnet.service" "${DEBIAN_SERVICE_HOME}"
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/linux/bitcoin.service" "${DEBIAN_SERVICE_HOME}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
################################
|
||||
# Bitcoin instance for Testnet #
|
||||
################################
|
||||
|
||||
if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then
|
||||
echo "[*] Installing Bitcoin Testnet service"
|
||||
case $OS in
|
||||
|
||||
FreeBSD)
|
||||
echo "[*] FIXME: Bitcoin Testnet service must be installed manually on FreeBSD"
|
||||
;;
|
||||
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/linux/bitcoin-testnet.service" "${DEBIAN_SERVICE_HOME}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
###############################
|
||||
# Bitcoin instance for Signet #
|
||||
###############################
|
||||
|
||||
if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then
|
||||
echo "[*] Installing Bitcoin Signet service"
|
||||
case $OS in
|
||||
|
||||
FreeBSD)
|
||||
echo "[*] FIXME: Bitcoin Signet service must be installed manually on FreeBSD"
|
||||
;;
|
||||
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/linux/bitcoin-signet.service" "${DEBIAN_SERVICE_HOME}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
###############################
|
||||
# Bitcoin instance for Liquid #
|
||||
###############################
|
||||
|
||||
if [ "${ELEMENTS_LIQUID_ENABLE}" = ON ];then
|
||||
echo "[*] Installing Bitcoin Liquid service"
|
||||
case $OS in
|
||||
|
||||
FreeBSD)
|
||||
echo "[*] FIXME: Bitcoin Liquid service must be installed manually on FreeBSD"
|
||||
;;
|
||||
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/linux/liquid.service" "${DEBIAN_SERVICE_HOME}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
@ -1174,9 +1282,9 @@ if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" crontab -u "${MINFEE_USER}" "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/minfee.crontab"
|
||||
|
||||
echo "[*] Configuring Bitcoin Mainnet RPC credentials in electrs start script"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-mainnet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-mainnet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${BITCOIN_ELECTRS_HOME}/electrs-start-mainnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-mainnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-mainnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${BITCOIN_ELECTRS_HOME}/electrs-start-mainnet"
|
||||
fi
|
||||
|
||||
########################################
|
||||
@ -1188,9 +1296,9 @@ if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" install -c -o "${BITCOIN_USER}" -g "${BITCOIN_GROUP}" -m 755 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/electrs-start-testnet" "${BITCOIN_ELECTRS_HOME}"
|
||||
|
||||
echo "[*] Configuring Bitcoin Testnet RPC credentials in electrs start script"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-testnet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-testnet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${BITCOIN_ELECTRS_HOME}/electrs-start-testnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-testnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-testnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${BITCOIN_ELECTRS_HOME}/electrs-start-testnet"
|
||||
fi
|
||||
|
||||
#######################################
|
||||
@ -1202,9 +1310,9 @@ if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" install -c -o "${BITCOIN_USER}" -g "${BITCOIN_GROUP}" -m 755 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/electrs-start-signet" "${BITCOIN_ELECTRS_HOME}"
|
||||
|
||||
echo "[*] Configuring Bitcoin Signet RPC credentials in electrs start script"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-signet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-signet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${BITCOIN_ELECTRS_HOME}/electrs-start-signet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-signet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${BITCOIN_ELECTRS_HOME}/electrs-start-signet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${BITCOIN_ELECTRS_HOME}/electrs-start-signet"
|
||||
fi
|
||||
|
||||
########################################
|
||||
@ -1220,9 +1328,9 @@ if [ "${ELEMENTS_LIQUID_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" crontab -u "${ELEMENTS_USER}" "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/elements.crontab"
|
||||
|
||||
echo "[*] Configuring Elements Liquid RPC credentials in electrs start script"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquid"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquid"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquid"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquid"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquid"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquid"
|
||||
fi
|
||||
|
||||
################################################
|
||||
@ -1234,15 +1342,15 @@ if [ "${ELEMENTS_LIQUIDTESTNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" install -c -o "${ELEMENTS_USER}" -g "${ELEMENTS_GROUP}" -m 755 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/electrs-start-liquidtestnet" "${ELEMENTS_ELECTRS_HOME}"
|
||||
|
||||
echo "[*] Installing Elements Liquid Testnet RPC credentials"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_USER__/${BITCOIN_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__BITCOIN_RPC_PASS__/${BITCOIN_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_HOME}/elements.conf"
|
||||
|
||||
echo "[*] Configuring Elements LiquidTestnet RPC credentials in electrs start script"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquidtestnet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquidtestnet"
|
||||
osSudo "${ROOT_USER}" sed -i .orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquidtestnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_USER__/${ELEMENTS_RPC_USER}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquidtestnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s/__ELEMENTS_RPC_PASS__/${ELEMENTS_RPC_PASS}/" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquidtestnet"
|
||||
osSudo "${ROOT_USER}" sed -i.orig "s!__ELECTRS_DATA_ROOT__!${ELECTRS_DATA_ROOT}!" "${ELEMENTS_ELECTRS_HOME}/electrs-start-liquidtestnet"
|
||||
fi
|
||||
|
||||
#####################################
|
||||
@ -1351,7 +1459,7 @@ case $OS in
|
||||
;;
|
||||
|
||||
Debian)
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/nginx.conf" "${NGINX_CONFIGURATION}"
|
||||
osSudo "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${MEMPOOL_HOME}/${MEMPOOL_REPO_NAME}/production/nginx/nginx.conf" "${NGINX_CONFIGURATION}"
|
||||
#echo "[*] Restarting Nginx"
|
||||
#osSudo "${ROOT_USER}" service nginx restart
|
||||
;;
|
||||
@ -1372,21 +1480,22 @@ case $OS in
|
||||
fi
|
||||
if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" systemctl enable bitcoin.service
|
||||
osSudo "${ROOT_USER}" systemctl enable electrs.service
|
||||
osSudo "${ROOT_USER}" systemctl enable mempool.service
|
||||
fi
|
||||
if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" systemctl enable bitcoin-testnet.service
|
||||
osSudo "${ROOT_USER}" systemctl enable electrs-testnet.service
|
||||
osSudo "${ROOT_USER}" systemctl enable mempool-testnet.service
|
||||
fi
|
||||
if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" systemctl enable bitcoin-signet.service
|
||||
osSudo "${ROOT_USER}" systemctl enable mempool-signet.service
|
||||
fi
|
||||
if [ "${BISQ_MAINNET_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" systemctl enable bisq.service
|
||||
osSudo "${ROOT_USER}" systemctl enable mempool-bisq.service
|
||||
fi
|
||||
if [ "${ELEMENTS_LIQUID_ENABLE}" = ON ];then
|
||||
osSudo "${ROOT_USER}" systemctl enable liquid.service
|
||||
osSudo "${ROOT_USER}" systemctl enable electrs-liquid.service
|
||||
osSudo "${ROOT_USER}" systemctl enable mempool-liquid.service
|
||||
fi
|
||||
;;
|
||||
|
22
production/linux/bitcoin-signet.service
Normal file
22
production/linux/bitcoin-signet.service
Normal file
@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Bitcoind-signet
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/bitcoind -conf=bitcoin-signet.conf -daemon -signet -printtoconsole -pid=/bitcoin/bitcoind-signet.pid
|
||||
ExecStop=/usr/local/bin/bitcoin-cli -signet stop
|
||||
|
||||
Type=forking
|
||||
PIDFile=/bitcoin/bitcoind-signet.pid
|
||||
Restart=on-failure
|
||||
|
||||
User=bitcoin
|
||||
Group=bitcoin
|
||||
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
22
production/linux/bitcoin-testnet.service
Normal file
22
production/linux/bitcoin-testnet.service
Normal file
@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Bitcoind-testnet
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/bitcoind -conf=bitcoin-testnet.conf -daemon -testnet -printtoconsole -pid=/bitcoin/bitcoind-testnet.pid
|
||||
ExecStop=/usr/local/bin/bitcoin-cli -testnet stop
|
||||
|
||||
Type=forking
|
||||
PIDFile=/bitcoin/bitcoind-testnet.pid
|
||||
Restart=on-failure
|
||||
|
||||
User=bitcoin
|
||||
Group=bitcoin
|
||||
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
22
production/linux/bitcoin.service
Normal file
22
production/linux/bitcoin.service
Normal file
@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Bitcoind
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/bitcoind -daemon -printtoconsole -pid=/bitcoin/bitcoind.pid
|
||||
ExecStop=/usr/local/bin/bitcoin-cli stop
|
||||
|
||||
Type=forking
|
||||
PIDFile=/bitcoin/bitcoind.pid
|
||||
Restart=on-failure
|
||||
|
||||
User=bitcoin
|
||||
Group=bitcoin
|
||||
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
22
production/linux/liquid.service
Normal file
22
production/linux/liquid.service
Normal file
@ -0,0 +1,22 @@
|
||||
[Unit]
|
||||
Description=Liquid
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/local/bin/elementsd -daemon -printtoconsole -pid=/liquid/liquid.pid
|
||||
ExecStop=/usr/local/bin/elements-cli stop
|
||||
|
||||
Type=forking
|
||||
PIDFile=/liquid/liquid.pid
|
||||
Restart=on-failure
|
||||
|
||||
User=liquid
|
||||
Group=liquid
|
||||
|
||||
PrivateTmp=true
|
||||
ProtectSystem=full
|
||||
NoNewPrivileges=true
|
||||
PrivateDevices=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -67,6 +67,16 @@ do for url in / \
|
||||
'/api/v1/mining/blocks/fee-rates/2y' \
|
||||
'/api/v1/mining/blocks/fee-rates/3y' \
|
||||
'/api/v1/mining/blocks/fee-rates/all' \
|
||||
'/api/v1/mining/difficulty-adjustments/24h' \
|
||||
'/api/v1/mining/difficulty-adjustments/3d' \
|
||||
'/api/v1/mining/difficulty-adjustments/1w' \
|
||||
'/api/v1/mining/difficulty-adjustments/1m' \
|
||||
'/api/v1/mining/difficulty-adjustments/3m' \
|
||||
'/api/v1/mining/difficulty-adjustments/6m' \
|
||||
'/api/v1/mining/difficulty-adjustments/1y' \
|
||||
'/api/v1/mining/difficulty-adjustments/2y' \
|
||||
'/api/v1/mining/difficulty-adjustments/3y' \
|
||||
'/api/v1/mining/difficulty-adjustments/all' \
|
||||
|
||||
do
|
||||
curl -s "https://${hostname}${url}" >/dev/null
|
||||
|
Loading…
x
Reference in New Issue
Block a user