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