Add regtest network support

This commit is contained in:
Mononaut 2023-07-11 14:18:05 +09:00
parent e2fdacfddd
commit 60c50fc47e
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
32 changed files with 182 additions and 26 deletions

View File

@ -414,7 +414,7 @@ class BitcoinRoutes {
private async getBlocks(req: Request, res: Response) { private async getBlocks(req: Request, res: Response) {
try { try {
if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { // Bitcoin if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) { // Bitcoin
const height = req.params.height === undefined ? undefined : parseInt(req.params.height, 10); const height = req.params.height === undefined ? undefined : parseInt(req.params.height, 10);
res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString());
res.json(await blocks.$getBlocks(height, 15)); res.json(await blocks.$getBlocks(height, 15));
@ -428,7 +428,7 @@ class BitcoinRoutes {
private async getBlocksByBulk(req: Request, res: Response) { private async getBlocksByBulk(req: Request, res: Response) {
try { try {
if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK) === false) { // Liquid, Bisq - Not implemented if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK) === false) { // Liquid, Bisq - Not implemented
return res.status(404).send(`This API is only available for Bitcoin networks`); return res.status(404).send(`This API is only available for Bitcoin networks`);
} }
if (config.MEMPOOL.MAX_BLOCKS_BULK_QUERY <= 0) { if (config.MEMPOOL.MAX_BLOCKS_BULK_QUERY <= 0) {

View File

@ -263,7 +263,7 @@ class Blocks {
extras.totalInputAmt = null; extras.totalInputAmt = null;
} }
if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) {
let pool: PoolTag; let pool: PoolTag;
if (coinbaseTx !== undefined) { if (coinbaseTx !== undefined) {
pool = await this.$findBlockMiner(coinbaseTx); pool = await this.$findBlockMiner(coinbaseTx);
@ -845,7 +845,7 @@ class Blocks {
} }
// Not Bitcoin network, return the block as it from the bitcoin backend // Not Bitcoin network, return the block as it from the bitcoin backend
if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK) === false) { if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK) === false) {
return await bitcoinCoreApi.$getBlock(hash); return await bitcoinCoreApi.$getBlock(hash);
} }
@ -1061,7 +1061,7 @@ class Blocks {
} }
public async $getBlockAuditSummary(hash: string): Promise<any> { public async $getBlockAuditSummary(hash: string): Promise<any> {
if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) {
return BlocksAuditsRepository.$getBlockAudit(hash); return BlocksAuditsRepository.$getBlockAudit(hash);
} else { } else {
return null; return null;

View File

@ -239,7 +239,7 @@ export class Common {
static indexingEnabled(): boolean { static indexingEnabled(): boolean {
return ( return (
['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK) && ['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK) &&
config.DATABASE.ENABLED === true && config.DATABASE.ENABLED === true &&
config.MEMPOOL.INDEXING_BLOCKS_AMOUNT !== 0 config.MEMPOOL.INDEXING_BLOCKS_AMOUNT !== 0
); );

View File

@ -104,7 +104,7 @@ class DatabaseMigration {
private async $createMissingTablesAndIndexes(databaseSchemaVersion: number) { private async $createMissingTablesAndIndexes(databaseSchemaVersion: number) {
await this.$setStatisticsAddedIndexedFlag(databaseSchemaVersion); await this.$setStatisticsAddedIndexedFlag(databaseSchemaVersion);
const isBitcoin = ['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK); const isBitcoin = ['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK);
await this.$executeQuery(this.getCreateElementsTableQuery(), await this.$checkIfTableExists('elements_pegs')); await this.$executeQuery(this.getCreateElementsTableQuery(), await this.$checkIfTableExists('elements_pegs'));
await this.$executeQuery(this.getCreateStatisticsQuery(), await this.$checkIfTableExists('statistics')); await this.$executeQuery(this.getCreateStatisticsQuery(), await this.$checkIfTableExists('statistics'));
@ -512,7 +512,7 @@ class DatabaseMigration {
await this.updateToSchemaVersion(58); await this.updateToSchemaVersion(58);
} }
if (databaseSchemaVersion < 59 && (config.MEMPOOL.NETWORK === 'signet' || config.MEMPOOL.NETWORK === 'testnet')) { if (databaseSchemaVersion < 59 && ['testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) {
// https://github.com/mempool/mempool/issues/3360 // https://github.com/mempool/mempool/issues/3360
await this.$executeQuery(`TRUNCATE prices`); await this.$executeQuery(`TRUNCATE prices`);
} }
@ -656,7 +656,7 @@ class DatabaseMigration {
*/ */
private getMigrationQueriesFromVersion(version: number): string[] { private getMigrationQueriesFromVersion(version: number): string[] {
const queries: string[] = []; const queries: string[] = [];
const isBitcoin = ['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK); const isBitcoin = ['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK);
if (version < 1) { if (version < 1) {
if (config.MEMPOOL.NETWORK !== 'liquid' && config.MEMPOOL.NETWORK !== 'liquidtestnet') { if (config.MEMPOOL.NETWORK !== 'liquid' && config.MEMPOOL.NETWORK !== 'liquidtestnet') {

View File

@ -131,7 +131,7 @@ class PoolsParser {
let firstKnownBlockPool = 130635; // https://mempool.space/block/0000000000000a067d94ff753eec72830f1205ad3a4c216a08a80c832e551a52 let firstKnownBlockPool = 130635; // https://mempool.space/block/0000000000000a067d94ff753eec72830f1205ad3a4c216a08a80c832e551a52
if (config.MEMPOOL.NETWORK === 'testnet') { if (config.MEMPOOL.NETWORK === 'testnet') {
firstKnownBlockPool = 21106; // https://mempool.space/testnet/block/0000000070b701a5b6a1b965f6a38e0472e70b2bb31b973e4638dec400877581 firstKnownBlockPool = 21106; // https://mempool.space/testnet/block/0000000070b701a5b6a1b965f6a38e0472e70b2bb31b973e4638dec400877581
} else if (config.MEMPOOL.NETWORK === 'signet') { } else if (config.MEMPOOL.NETWORK === 'signet' || config.MEMPOOL.NETWORK === 'regtest') {
firstKnownBlockPool = 0; firstKnownBlockPool = 0;
} }
@ -159,7 +159,7 @@ class PoolsParser {
let firstKnownBlockPool = 130635; // https://mempool.space/block/0000000000000a067d94ff753eec72830f1205ad3a4c216a08a80c832e551a52 let firstKnownBlockPool = 130635; // https://mempool.space/block/0000000000000a067d94ff753eec72830f1205ad3a4c216a08a80c832e551a52
if (config.MEMPOOL.NETWORK === 'testnet') { if (config.MEMPOOL.NETWORK === 'testnet') {
firstKnownBlockPool = 21106; // https://mempool.space/testnet/block/0000000070b701a5b6a1b965f6a38e0472e70b2bb31b973e4638dec400877581 firstKnownBlockPool = 21106; // https://mempool.space/testnet/block/0000000070b701a5b6a1b965f6a38e0472e70b2bb31b973e4638dec400877581
} else if (config.MEMPOOL.NETWORK === 'signet') { } else if (config.MEMPOOL.NETWORK === 'signet' || config.MEMPOOL.NETWORK === 'regtest') {
firstKnownBlockPool = 0; firstKnownBlockPool = 0;
} }

View File

@ -5,7 +5,7 @@ const configFromFile = require(
interface IConfig { interface IConfig {
MEMPOOL: { MEMPOOL: {
ENABLED: boolean; ENABLED: boolean;
NETWORK: 'mainnet' | 'testnet' | 'signet' | 'liquid' | 'liquidtestnet'; NETWORK: 'mainnet' | 'testnet' | 'signet' | 'regtest' | 'liquid' | 'liquidtestnet';
BACKEND: 'esplora' | 'electrum' | 'none'; BACKEND: 'esplora' | 'electrum' | 'none';
HTTP_PORT: number; HTTP_PORT: number;
SPAWN_CLUSTER_PROCS: number; SPAWN_CLUSTER_PROCS: number;

View File

@ -99,7 +99,7 @@ class PoolsRepository {
if (parse) { if (parse) {
rows[0].regexes = JSON.parse(rows[0].regexes); rows[0].regexes = JSON.parse(rows[0].regexes);
} }
if (['testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { if (['testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) {
rows[0].addresses = []; // pools-v2.json only contains mainnet addresses rows[0].addresses = []; // pools-v2.json only contains mainnet addresses
} else if (parse) { } else if (parse) {
rows[0].addresses = JSON.parse(rows[0].addresses); rows[0].addresses = JSON.parse(rows[0].addresses);
@ -131,7 +131,7 @@ class PoolsRepository {
if (parse) { if (parse) {
rows[0].regexes = JSON.parse(rows[0].regexes); rows[0].regexes = JSON.parse(rows[0].regexes);
} }
if (['testnet', 'signet'].includes(config.MEMPOOL.NETWORK)) { if (['testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) {
rows[0].addresses = []; // pools.json only contains mainnet addresses rows[0].addresses = []; // pools.json only contains mainnet addresses
} else if (parse) { } else if (parse) {
rows[0].addresses = JSON.parse(rows[0].addresses); rows[0].addresses = JSON.parse(rows[0].addresses);

View File

@ -17,7 +17,7 @@ class PoolsUpdater {
treeUrl: string = config.MEMPOOL.POOLS_JSON_TREE_URL; treeUrl: string = config.MEMPOOL.POOLS_JSON_TREE_URL;
public async updatePoolsJson(): Promise<void> { public async updatePoolsJson(): Promise<void> {
if (['mainnet', 'testnet', 'signet'].includes(config.MEMPOOL.NETWORK) === false || if (['mainnet', 'testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK) === false ||
config.MEMPOOL.ENABLED === false config.MEMPOOL.ENABLED === false
) { ) {
return; return;

View File

@ -73,7 +73,7 @@ class PriceUpdater {
} }
public async $run(): Promise<void> { public async $run(): Promise<void> {
if (config.MEMPOOL.NETWORK === 'signet' || config.MEMPOOL.NETWORK === 'testnet') { if (['testnet', 'signet', 'regtest'].includes(config.MEMPOOL.NETWORK)) {
// Coins have no value on testnet/signet, so we want to always show 0 // Coins have no value on testnet/signet, so we want to always show 0
return; return;
} }

View File

@ -18,6 +18,7 @@ fi
__TESTNET_ENABLED__=${TESTNET_ENABLED:=false} __TESTNET_ENABLED__=${TESTNET_ENABLED:=false}
__SIGNET_ENABLED__=${SIGNET_ENABLED:=false} __SIGNET_ENABLED__=${SIGNET_ENABLED:=false}
__REGTEST_ENABLED__=${REGTEST_ENABLED:=false}
__LIQUID_ENABLED__=${LIQUID_EANBLED:=false} __LIQUID_ENABLED__=${LIQUID_EANBLED:=false}
__LIQUID_TESTNET_ENABLED__=${LIQUID_TESTNET_ENABLED:=false} __LIQUID_TESTNET_ENABLED__=${LIQUID_TESTNET_ENABLED:=false}
__BISQ_ENABLED__=${BISQ_ENABLED:=false} __BISQ_ENABLED__=${BISQ_ENABLED:=false}
@ -44,6 +45,7 @@ __HISTORICAL_PRICE__=${HISTORICAL_PRICE:=true}
# Export as environment variables to be used by envsubst # Export as environment variables to be used by envsubst
export __TESTNET_ENABLED__ export __TESTNET_ENABLED__
export __SIGNET_ENABLED__ export __SIGNET_ENABLED__
export __REGTEST_ENABLED__
export __LIQUID_ENABLED__ export __LIQUID_ENABLED__
export __LIQUID_TESTNET_ENABLED__ export __LIQUID_TESTNET_ENABLED__
export __BISQ_ENABLED__ export __BISQ_ENABLED__

View File

@ -1,6 +1,7 @@
{ {
"TESTNET_ENABLED": false, "TESTNET_ENABLED": false,
"SIGNET_ENABLED": false, "SIGNET_ENABLED": false,
"REGTEST_ENABLED": false,
"LIQUID_ENABLED": false, "LIQUID_ENABLED": false,
"LIQUID_TESTNET_ENABLED": false, "LIQUID_TESTNET_ENABLED": false,
"BISQ_ENABLED": false, "BISQ_ENABLED": false,

View File

@ -249,6 +249,115 @@ let routes: Routes = [
}, },
] ]
}, },
{
path: 'regtest',
children: [
{
path: 'mining/blocks',
redirectTo: 'blocks',
pathMatch: 'full'
},
{
path: '',
pathMatch: 'full',
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
},
{
path: '',
component: MasterPageComponent,
children: [
{
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'blocks',
component: BlocksList,
},
{
path: 'rbf',
component: RbfList,
},
{
path: 'terms-of-service',
component: TermsOfServiceComponent
},
{
path: 'privacy-policy',
component: PrivacyPolicyComponent
},
{
path: 'trademark-policy',
component: TrademarkPolicyComponent
},
{
path: 'address/:id',
children: [],
component: AddressComponent,
data: {
ogImage: true,
networkSpecific: true,
}
},
{
path: 'tx',
data: { networkSpecific: true },
component: StartComponent,
children: [
{
path: ':id',
component: TransactionComponent
},
],
},
{
path: 'block',
data: { networkSpecific: true },
component: StartComponent,
children: [
{
path: ':id',
component: BlockComponent,
data: {
ogImage: true
}
},
],
},
{
path: 'docs',
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
},
{
path: 'api',
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
},
{
path: 'lightning',
data: { networks: ['bitcoin'] },
loadChildren: () => import('./lightning/lightning.module').then(m => m.LightningModule)
},
],
},
{
path: 'status',
data: { networks: ['bitcoin', 'liquid'] },
component: StatusViewComponent
},
{
path: '',
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
},
{
path: '**',
redirectTo: '/signet'
},
]
},
{ {
path: '', path: '',
pathMatch: 'full', pathMatch: 'full',

View File

@ -271,6 +271,11 @@ const featureActivation = {
segwit: 0, segwit: 0,
taproot: 0, taproot: 0,
}, },
regtest: {
rbf: 0,
segwit: 0,
taproot: 0,
},
}; };
export function isFeatureActive(network: string, height: number, feature: 'rbf' | 'segwit' | 'taproot'): boolean { export function isFeatureActive(network: string, height: number, feature: 'rbf' | 'segwit' | 'taproot'): boolean {

View File

@ -39,7 +39,7 @@
</ng-container> </ng-container>
</a> </a>
<div ngbDropdown (window:resize)="onResize($event)" class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED"> <div ngbDropdown (window:resize)="onResize($event)" class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.REGTEST_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED">
<button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split d-flex justify-content-center align-items-center" aria-haspopup="true"> <button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split d-flex justify-content-center align-items-center" aria-haspopup="true">
<app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" name="bisq" width="20" height="20" viewBox="0 0 80 80"></app-svg-images> <app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" name="bisq" width="20" height="20" viewBox="0 0 80 80"></app-svg-images>
</button> </button>
@ -47,6 +47,7 @@
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['mainnet'] || '/')" ngbDropdownItem class="mainnet"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a> <a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['mainnet'] || '/')" ngbDropdownItem class="mainnet"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['signet'] || '/signet')" ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a> <a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['signet'] || '/signet')" ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet'] || '/testnet')" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet</a> <a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet'] || '/testnet')" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['regtest'] || '/regtest')" ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Regtest</a>
<h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6> <h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6>
<a ngbDropdownItem class="mainnet active" [routerLink]="networkPaths['bisq'] || '/'"><app-svg-images name="bisq" width="20" height="20" viewBox="0 0 75 75" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Bisq</a> <a ngbDropdownItem class="mainnet active" [routerLink]="networkPaths['bisq'] || '/'"><app-svg-images name="bisq" width="20" height="20" viewBox="0 0 75 75" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Bisq</a>
<a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquid'] || '/')" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a> <a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquid'] || '/')" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a>

View File

@ -120,6 +120,10 @@ nav {
background-color: #6f1d5d; background-color: #6f1d5d;
} }
.regtest.active {
background-color: #a5a5a5;
}
.dropdown-divider { .dropdown-divider {
border-top: 1px solid #121420; border-top: 1px solid #121420;
} }

View File

@ -676,6 +676,7 @@ export class BlockComponent implements OnInit, OnDestroy {
} }
break; break;
case 'signet': case 'signet':
case 'regtest':
if (blockHeight < this.stateService.env.SIGNET_BLOCK_AUDIT_START_HEIGHT) { if (blockHeight < this.stateService.env.SIGNET_BLOCK_AUDIT_START_HEIGHT) {
return false; return false;
} }

View File

@ -68,6 +68,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
'liquidtestnet': ['#494a4a', '#272e46'], 'liquidtestnet': ['#494a4a', '#272e46'],
testnet: ['#1d486f', '#183550'], testnet: ['#1d486f', '#183550'],
signet: ['#6f1d5d', '#471850'], signet: ['#6f1d5d', '#471850'],
regtest: ['#9339f4', '#105fb0'],
}; };
constructor( constructor(
@ -86,7 +87,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
ngOnInit() { ngOnInit() {
this.dynamicBlocksAmount = Math.min(8, this.stateService.env.KEEP_BLOCKS_AMOUNT); this.dynamicBlocksAmount = Math.min(8, this.stateService.env.KEEP_BLOCKS_AMOUNT);
if (['', 'testnet', 'signet'].includes(this.stateService.network)) { if (['', 'testnet', 'signet', 'regtest'].includes(this.stateService.network)) {
this.enabledMiningInfoIfNeeded(this.location.path()); this.enabledMiningInfoIfNeeded(this.location.path());
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url)); this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
} }

View File

@ -38,6 +38,7 @@ export class ClockComponent implements OnInit {
'liquidtestnet': ['#494a4a', '#272e46'], 'liquidtestnet': ['#494a4a', '#272e46'],
testnet: ['#1d486f', '#183550'], testnet: ['#1d486f', '#183550'],
signet: ['#6f1d5d', '#471850'], signet: ['#6f1d5d', '#471850'],
regtest: ['#9339f4', '#105fb0'],
}; };
constructor( constructor(

View File

@ -44,7 +44,7 @@
</ng-container> </ng-container>
</a> </a>
<div ngbDropdown (window:resize)="onResize()" class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED"> <div ngbDropdown (window:resize)="onResize()" class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.REGTEST_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED">
<button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split d-flex justify-content-center align-items-center" aria-haspopup="true"> <button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split d-flex justify-content-center align-items-center" aria-haspopup="true">
<app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" [name]="network.val === '' ? 'liquid' : network.val" width="20" height="20" viewBox="0 0 125 125"></app-svg-images> <app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" [name]="network.val === '' ? 'liquid' : network.val" width="20" height="20" viewBox="0 0 125 125"></app-svg-images>
</button> </button>
@ -52,6 +52,7 @@
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['mainnet'] || '')" ngbDropdownItem class="mainnet"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a> <a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['mainnet'] || '')" ngbDropdownItem class="mainnet"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['signet'] || '/signet')" ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a> <a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['signet'] || '/signet')" ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet'] || '/testnet')" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet</a> <a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet'] || '/testnet')" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['regtest'] || '/regtest')" ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Regtest</a>
<h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6> <h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6>
<a [href]="env.BISQ_WEBSITE_URL + urlLanguage + (networkPaths['bisq'] || '')" ngbDropdownItem class="mainnet"><app-svg-images name="bisq" width="22" height="22" viewBox="0 0 75 75" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Bisq</a> <a [href]="env.BISQ_WEBSITE_URL + urlLanguage + (networkPaths['bisq'] || '')" ngbDropdownItem class="mainnet"><app-svg-images name="bisq" width="22" height="22" viewBox="0 0 75 75" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Bisq</a>
<a ngbDropdownItem class="liquid mr-1" [class.active]="network.val === 'liquid'" [routerLink]="networkPaths['liquid'] || '/'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a> <a ngbDropdownItem class="liquid mr-1" [class.active]="network.val === 'liquid'" [routerLink]="networkPaths['liquid'] || '/'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a>

View File

@ -114,6 +114,10 @@ nav {
background-color: #6f1d5d; background-color: #6f1d5d;
} }
.regtest.active {
background-color: #a5a5a5;
}
.dropdown-divider { .dropdown-divider {
border-top: 1px solid #121420; border-top: 1px solid #121420;
} }

View File

@ -9,6 +9,7 @@
<div [ngSwitch]="network.val"> <div [ngSwitch]="network.val">
<span *ngSwitchCase="'signet'" class="network signet"><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Signet</span> <span *ngSwitchCase="'signet'" class="network signet"><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Signet</span>
<span *ngSwitchCase="'testnet'" class="network testnet"><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span> <span *ngSwitchCase="'testnet'" class="network testnet"><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span>
<span *ngSwitchCase="'regtest'" class="network regtest"><app-svg-images name="regtest" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Regtest</span>
<span *ngSwitchCase="'bisq'" class="network bisq"><app-svg-images name="bisq" width="35" height="35" viewBox="0 0 75 75" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Bisq</span> <span *ngSwitchCase="'bisq'" class="network bisq"><app-svg-images name="bisq" width="35" height="35" viewBox="0 0 75 75" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Bisq</span>
<span *ngSwitchCase="'liquid'" class="network liquid"><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span> <span *ngSwitchCase="'liquid'" class="network liquid"><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span>
<span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span> <span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span>

View File

@ -17,7 +17,7 @@
</ng-container> </ng-container>
</a> </a>
<div (window:resize)="onResize()" ngbDropdown class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED"> <div (window:resize)="onResize()" ngbDropdown class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.REGTEST_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED">
<button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split d-flex justify-content-center align-items-center" aria-haspopup="true"> <button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split d-flex justify-content-center align-items-center" aria-haspopup="true">
<app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" [name]="network.val === '' ? 'bitcoin' : network.val" width="20" height="20" viewBox="0 0 65 65"></app-svg-images> <app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" [name]="network.val === '' ? 'bitcoin' : network.val" width="20" height="20" viewBox="0 0 65 65"></app-svg-images>
</button> </button>
@ -25,6 +25,7 @@
<a ngbDropdownItem class="mainnet" [routerLink]="networkPaths['mainnet'] || '/'"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a> <a ngbDropdownItem class="mainnet" [routerLink]="networkPaths['mainnet'] || '/'"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a>
<a ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet" [class.active]="network.val === 'signet'" [routerLink]="networkPaths['signet'] || '/signet'"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a> <a ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet" [class.active]="network.val === 'signet'" [routerLink]="networkPaths['signet'] || '/signet'"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a>
<a ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet" [class.active]="network.val === 'testnet'" [routerLink]="networkPaths['testnet'] || '/testnet'"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet</a> <a ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet" [class.active]="network.val === 'testnet'" [routerLink]="networkPaths['testnet'] || '/testnet'"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet</a>
<a ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest" [class.active]="network.val === 'regtest'" [routerLink]="networkPaths['regtest'] || '/regtest'"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Regtest</a>
<h6 *ngIf="env.LIQUID_ENABLED || env.BISQ_ENABLED" class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6> <h6 *ngIf="env.LIQUID_ENABLED || env.BISQ_ENABLED" class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6>
<a [href]="env.BISQ_WEBSITE_URL + urlLanguage + (networkPaths['bisq'] || '')" ngbDropdownItem *ngIf="env.BISQ_ENABLED" class="bisq"><app-svg-images name="bisq" width="20" height="20" viewBox="0 0 75 75" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Bisq</a> <a [href]="env.BISQ_WEBSITE_URL + urlLanguage + (networkPaths['bisq'] || '')" ngbDropdownItem *ngIf="env.BISQ_ENABLED" class="bisq"><app-svg-images name="bisq" width="20" height="20" viewBox="0 0 75 75" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Bisq</a>
<a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquid'] || '')" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid" [class.active]="network.val === 'liquid'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a> <a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquid'] || '')" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid" [class.active]="network.val === 'liquid'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a>
@ -62,7 +63,7 @@
</nav> </nav>
</header> </header>
<app-testnet-alert *ngIf="network.val === 'testnet' || network.val === 'signet'"></app-testnet-alert> <app-testnet-alert *ngIf="network.val === 'testnet' || network.val === 'signet' || network.val === 'regtest'"></app-testnet-alert>
<main> <main>
<router-outlet></router-outlet> <router-outlet></router-outlet>

View File

@ -131,6 +131,10 @@ nav {
background-color: #6f1d5d; background-color: #6f1d5d;
} }
.regtest.active {
background-color: #a5a5a5;
}
.dropdown-divider { .dropdown-divider {
border-top: 1px solid #121420; border-top: 1px solid #121420;
} }

View File

@ -93,7 +93,7 @@ export class MempoolBlocksComponent implements OnInit, OnChanges, OnDestroy {
ngOnInit() { ngOnInit() {
this.chainTip = this.stateService.latestBlockHeight; this.chainTip = this.stateService.latestBlockHeight;
if (['', 'testnet', 'signet'].includes(this.stateService.network)) { if (['', 'testnet', 'signet', 'regtest'].includes(this.stateService.network)) {
this.enabledMiningInfoIfNeeded(this.location.path()); this.enabledMiningInfoIfNeeded(this.location.path());
this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url)); this.location.onUrlChange((url) => this.enabledMiningInfoIfNeeded(url));
} }

View File

@ -60,6 +60,9 @@
<ng-container *ngSwitchCase="'testnet'"> <ng-container *ngSwitchCase="'testnet'">
<ng-component *ngTemplateOutlet="bitcoinLogo; context: {$implicit: '#5fd15c', width, height, viewBox}"></ng-component> <ng-component *ngTemplateOutlet="bitcoinLogo; context: {$implicit: '#5fd15c', width, height, viewBox}"></ng-component>
</ng-container> </ng-container>
<ng-container *ngSwitchCase="'regtest'">
<ng-component *ngTemplateOutlet="bitcoinLogo; context: {$implicit: '#a5a5a5', width, height, viewBox}"></ng-component>
</ng-container>
<ng-container *ngSwitchCase="'bisq'"> <ng-container *ngSwitchCase="'bisq'">
<svg xmlns="http://www.w3.org/2000/svg" [attr.width]="width" [attr.height]="height" [attr.viewBox]="viewBox"><path id="Combined-Shape" fill="#25b135" d="M62.6 18.2c2.6 5.7 3.2 6.8 5.2 12.6 1.1 3.6-1.2 9-10.6 4.4-6.8-3.2-11.7-5.5-7.6-10.9 2-2.6 4.2-5 6.6-7.3 2.5-2.2 4.1-3.6 6.4 1.2zm-2.3 36.4c5-4.9 11.9.6 7.1 7.1C57.6 75 40.7 80.3 25.5 74.9S0 55 0 38.3c0-10 3.3-18.4 9.6-25.9C15.7 5.6 24.8.1 33.8 0 46.4 0 52 11 47.6 17.2c-5 6.8-10.7 6.3-15 3.3 0 0-5.9-4.2-7.6-5.6-2.7-2.1-5.6-2.1-6.7 1.3-1.9 6-2.8 9.8-4.3 15.8-.7 3-1 6.1-1.1 9.2 0 5.7 2.5 11.1 6.8 14.6 3 2.8 6.1 5.3 9.5 7.5 2.7 1.9 5.9 2.9 9.1 2.9h.3c3.2-.1 6.4-1.1 9.1-2.9 4.4-2.6 8.6-5.5 12.6-8.7zm-35.4-7c-1.8-.7-5.8-4.2-4.6-6.8.5-1.4 3.9-1.8 5-1.8 6.2-.1 6.5 11.1-.4 8.6zm11.1 12c-.8-.7-2.3-2.2-3.6-3.4-.4-.4-.4-1-.2-1.4.3-.5.8-.8 1.4-.7 2.4-.1 4.8-.1 7.1 0 .6 0 1 .4 1.2.8.2.5.1 1-.3 1.3-1.3 1.2-2.8 2.7-3.5 3.4-.3.3-.7.4-1.1.4-.4 0-.7-.1-1-.4zm14.1-12c-6.9 2.5-6.7-8.8-.4-8.6 1.1 0 4.4.4 5 1.8 1.3 2.7-2.8 6.2-4.6 6.8z"/></svg> <svg xmlns="http://www.w3.org/2000/svg" [attr.width]="width" [attr.height]="height" [attr.viewBox]="viewBox"><path id="Combined-Shape" fill="#25b135" d="M62.6 18.2c2.6 5.7 3.2 6.8 5.2 12.6 1.1 3.6-1.2 9-10.6 4.4-6.8-3.2-11.7-5.5-7.6-10.9 2-2.6 4.2-5 6.6-7.3 2.5-2.2 4.1-3.6 6.4 1.2zm-2.3 36.4c5-4.9 11.9.6 7.1 7.1C57.6 75 40.7 80.3 25.5 74.9S0 55 0 38.3c0-10 3.3-18.4 9.6-25.9C15.7 5.6 24.8.1 33.8 0 46.4 0 52 11 47.6 17.2c-5 6.8-10.7 6.3-15 3.3 0 0-5.9-4.2-7.6-5.6-2.7-2.1-5.6-2.1-6.7 1.3-1.9 6-2.8 9.8-4.3 15.8-.7 3-1 6.1-1.1 9.2 0 5.7 2.5 11.1 6.8 14.6 3 2.8 6.1 5.3 9.5 7.5 2.7 1.9 5.9 2.9 9.1 2.9h.3c3.2-.1 6.4-1.1 9.1-2.9 4.4-2.6 8.6-5.5 12.6-8.7zm-35.4-7c-1.8-.7-5.8-4.2-4.6-6.8.5-1.4 3.9-1.8 5-1.8 6.2-.1 6.5 11.1-.4 8.6zm11.1 12c-.8-.7-2.3-2.2-3.6-3.4-.4-.4-.4-1-.2-1.4.3-.5.8-.8 1.4-.7 2.4-.1 4.8-.1 7.1 0 .6 0 1 .4 1.2.8.2.5.1 1-.3 1.3-1.3 1.2-2.8 2.7-3.5 3.4-.3.3-.7.4-1.1.4-.4 0-.7-.1-1-.4zm14.1-12c-6.9 2.5-6.7-8.8-.4-8.6 1.1 0 4.4.4 5 1.8 1.3 2.7-2.8 6.2-4.6 6.8z"/></svg>
</ng-container> </ng-container>

View File

@ -92,6 +92,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
testnet: ['#4edf77', '#10a0af', '#4edf7700'], testnet: ['#4edf77', '#10a0af', '#4edf7700'],
// signet: ['#6f1d5d', '#471850'], // signet: ['#6f1d5d', '#471850'],
signet: ['#d24fc8', '#a84fd2', '#d24fc800'], signet: ['#d24fc8', '#a84fd2', '#d24fc800'],
regtest: ['#9339f4', '#105fb0', '#9339f400'],
}; };
gradient: string[] = ['#105fb0', '#105fb0']; gradient: string[] = ['#105fb0', '#105fb0'];

View File

@ -38,6 +38,7 @@ export class EnterpriseService {
this.stateService.env.LIQUID_ENABLED = false; this.stateService.env.LIQUID_ENABLED = false;
this.stateService.env.LIQUID_TESTNET_ENABLED = false; this.stateService.env.LIQUID_TESTNET_ENABLED = false;
this.stateService.env.SIGNET_ENABLED = false; this.stateService.env.SIGNET_ENABLED = false;
this.stateService.env.REGTEST_ENABLED = false;
this.stateService.env.BISQ_ENABLED = false; this.stateService.env.BISQ_ENABLED = false;
} }

View File

@ -10,6 +10,7 @@ const networkModules = {
{ name: 'mainnet', path: '' }, { name: 'mainnet', path: '' },
{ name: 'testnet', path: '/testnet' }, { name: 'testnet', path: '/testnet' },
{ name: 'signet', path: '/signet' }, { name: 'signet', path: '/signet' },
{ name: 'regtest', path: '/regtest' },
], ],
}, },
liquid: { liquid: {
@ -73,7 +74,7 @@ export class NavigationService {
} }
if (route.url?.length) { if (route.url?.length) {
path = [path, ...route.url.map(segment => segment.path).filter(path => { path = [path, ...route.url.map(segment => segment.path).filter(path => {
return path.length && !['testnet', 'signet'].includes(path); return path.length && !['testnet', 'signet', 'regtest'].includes(path);
})].join('/'); })].join('/');
} }
route = route.firstChild; route = route.firstChild;

View File

@ -41,6 +41,8 @@ export class SeoService {
return this.baseTitle + ' - Bitcoin Testnet'; return this.baseTitle + ' - Bitcoin Testnet';
if (this.network === 'signet') if (this.network === 'signet')
return this.baseTitle + ' - Bitcoin Signet'; return this.baseTitle + ' - Bitcoin Signet';
if (this.network === 'regtest')
return this.baseTitle + ' - Bitcoin Regtest';
if (this.network === 'liquid') if (this.network === 'liquid')
return this.baseTitle + ' - Liquid Network'; return this.baseTitle + ' - Liquid Network';
if (this.network === 'liquidtestnet') if (this.network === 'liquidtestnet')

View File

@ -21,6 +21,7 @@ export interface ILoadingIndicators { [name: string]: number; }
export interface Env { export interface Env {
TESTNET_ENABLED: boolean; TESTNET_ENABLED: boolean;
SIGNET_ENABLED: boolean; SIGNET_ENABLED: boolean;
REGTEST_ENABLED: boolean;
LIQUID_ENABLED: boolean; LIQUID_ENABLED: boolean;
LIQUID_TESTNET_ENABLED: boolean; LIQUID_TESTNET_ENABLED: boolean;
BISQ_ENABLED: boolean; BISQ_ENABLED: boolean;
@ -51,6 +52,7 @@ export interface Env {
const defaultEnv: Env = { const defaultEnv: Env = {
'TESTNET_ENABLED': false, 'TESTNET_ENABLED': false,
'SIGNET_ENABLED': false, 'SIGNET_ENABLED': false,
'REGTEST_ENABLED': false,
'LIQUID_ENABLED': false, 'LIQUID_ENABLED': false,
'LIQUID_TESTNET_ENABLED': false, 'LIQUID_TESTNET_ENABLED': false,
'BASE_MODULE': 'mempool', 'BASE_MODULE': 'mempool',
@ -247,9 +249,9 @@ export class StateService {
// /^\/ starts with a forward slash... // /^\/ starts with a forward slash...
// (?:[a-z]{2}(?:-[A-Z]{2})?\/)? optional locale prefix (non-capturing) // (?:[a-z]{2}(?:-[A-Z]{2})?\/)? optional locale prefix (non-capturing)
// (?:preview\/)? optional "preview" prefix (non-capturing) // (?:preview\/)? optional "preview" prefix (non-capturing)
// (bisq|testnet|liquidtestnet|liquid|signet)/ network string (captured as networkMatches[1]) // (bisq|testnet|liquidtestnet|liquid|signet|regtest)/ network string (captured as networkMatches[1])
// ($|\/) network string must end or end with a slash // ($|\/) network string must end or end with a slash
const networkMatches = url.match(/^\/(?:[a-z]{2}(?:-[A-Z]{2})?\/)?(?:preview\/)?(bisq|testnet|liquidtestnet|liquid|signet)($|\/)/); const networkMatches = url.match(/^\/(?:[a-z]{2}(?:-[A-Z]{2})?\/)?(?:preview\/)?(bisq|testnet|liquidtestnet|liquid|signet|regtest)($|\/)/);
switch (networkMatches && networkMatches[1]) { switch (networkMatches && networkMatches[1]) {
case 'liquid': case 'liquid':
if (this.network !== 'liquid') { if (this.network !== 'liquid') {
@ -269,6 +271,12 @@ export class StateService {
this.networkChanged$.next('signet'); this.networkChanged$.next('signet');
} }
return; return;
case 'regtest':
if (this.network !== 'regtest') {
this.network = 'regtest';
this.networkChanged$.next('regtest');
}
return;
case 'testnet': case 'testnet':
if (this.network !== 'testnet') { if (this.network !== 'testnet') {
if (this.env.BASE_MODULE === 'liquid') { if (this.env.BASE_MODULE === 'liquid') {

View File

@ -55,7 +55,7 @@ export class GlobalFooterComponent implements OnInit {
networkLink(network) { networkLink(network) {
const thisNetwork = network || 'mainnet'; const thisNetwork = network || 'mainnet';
if( network === '' || network === 'mainnet' || network === 'testnet' || network === 'signet' ) { if( network === '' || network === 'mainnet' || network === 'testnet' || network === 'signet' || network === 'regtest' ) {
return (this.env.BASE_MODULE === 'mempool' ? '' : this.env.MEMPOOL_WEBSITE_URL + this.urlLanguage) + this.networkPaths[thisNetwork] || '/'; return (this.env.BASE_MODULE === 'mempool' ? '' : this.env.MEMPOOL_WEBSITE_URL + this.urlLanguage) + this.networkPaths[thisNetwork] || '/';
} }
if( network === 'liquid' || network === 'liquidtestnet' ) { if( network === 'liquid' || network === 'liquidtestnet' ) {

View File

@ -111,6 +111,10 @@ main {
background-color: #6f1d5d !important; background-color: #6f1d5d !important;
} }
.navbar-nav.regtest > .active {
background-color: #a5a5a5 !important;
}
.navbar-nav.liquidtestnet > .active { .navbar-nav.liquidtestnet > .active {
background-color: #494a4a !important; background-color: #494a4a !important;
} }