Adding Liquid Testnet as frontend option

fixes #976
This commit is contained in:
softsimon 2021-12-27 22:54:45 +04:00
parent dd767f9468
commit fd34761a93
No known key found for this signature in database
GPG Key ID: 488D7DCFB5A430D7
38 changed files with 342 additions and 72 deletions

View File

@ -2,6 +2,7 @@
"TESTNET_ENABLED": false,
"SIGNET_ENABLED": false,
"LIQUID_ENABLED": false,
"LIQUID_TESTNET_ENABLED": false,
"BISQ_ENABLED": false,
"BISQ_SEPARATE_BACKEND": false,
"ITEMS_PER_PAGE": 10,

View File

@ -24,6 +24,7 @@ PROXY_CONFIG = [
'/api/**', '!/api/v1/ws',
'!/bisq', '!/bisq/**', '!/bisq/',
'!/liquid', '!/liquid/**', '!/liquid/',
'!/liquidtestnet', '!/liquidtestnet/**', '!/liquidtestnet/',
'/testnet/api/**', '/signet/api/**'
],
target: "https://mempool.space",
@ -57,6 +58,16 @@ PROXY_CONFIG = [
ws: true,
secure: false,
changeOrigin: true
},
{
context: ['/api/liquidtestnet**', '/liquidtestnet/api/**'],
target: "https://liquid.network/testnet",
pathRewrite: {
"^/api/liquidtestnet/": "/liquidtestnet/api"
},
ws: true,
secure: false,
changeOrigin: true
}
];

View File

@ -105,6 +105,91 @@ let routes: Routes = [
},
],
},
{
path: 'liquidtestnet',
children: [
{
path: '',
component: MasterPageComponent,
children: [
{
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: '',
component: StartComponent,
children: [
{
path: '',
component: DashboardComponent
},
{
path: 'tx/:id',
component: TransactionComponent
},
{
path: 'block/:id',
component: BlockComponent
},
{
path: 'mempool-block/:id',
component: MempoolBlockComponent
},
],
},
{
path: 'blocks',
component: LatestBlocksComponent,
},
{
path: 'graphs',
component: StatisticsComponent,
},
{
path: 'address/:id',
component: AddressComponent
},
{
path: 'asset/:id',
component: AssetComponent
},
{
path: 'assets',
component: AssetsComponent,
},
{
path: 'docs/api/:type',
component: DocsComponent
},
{
path: 'docs/api',
redirectTo: 'docs/api/rest'
},
{
path: 'docs',
redirectTo: 'docs/api/rest'
},
{
path: 'api',
redirectTo: 'docs/api/rest'
},
],
},
{
path: 'tv',
component: TelevisionComponent
},
{
path: 'status',
component: StatusViewComponent
},
{
path: '**',
redirectTo: ''
},
]
},
{
path: 'liquid',
children: [
@ -466,6 +551,94 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
},
],
},
{
path: 'testnet',
component: LiquidMasterPageComponent,
children: [
{
path: '',
component: StartComponent,
children: [
{
path: '',
component: DashboardComponent
},
{
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'tx/:id',
component: TransactionComponent
},
{
path: 'block/:id',
component: BlockComponent
},
{
path: 'mempool-block/:id',
component: MempoolBlockComponent
},
],
},
{
path: 'blocks',
component: LatestBlocksComponent,
},
{
path: 'graphs',
component: StatisticsComponent,
},
{
path: 'address/:id',
component: AddressComponent
},
{
path: 'asset/:id',
component: AssetComponent
},
{
path: 'assets',
component: AssetsComponent,
},
{
path: 'docs/api/:type',
component: DocsComponent
},
{
path: 'docs/api',
redirectTo: 'docs/api/rest'
},
{
path: 'docs',
redirectTo: 'docs/api/rest'
},
{
path: 'api',
redirectTo: 'docs/api/rest'
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'terms-of-service',
component: TermsOfServiceComponent
},
{
path: 'privacy-policy',
component: PrivacyPolicyComponent
},
{
path: 'trademark-policy',
component: TrademarkPolicyComponent
},
{
path: 'sponsor',
component: SponsorComponent,
},
],
},
{
path: 'tv',
component: TelevisionComponent

View File

@ -99,7 +99,7 @@ export class AddressComponent implements OnInit, OnDestroy {
.pipe(
filter((address) => !!address),
tap((address: Address) => {
if (this.stateService.network === 'liquid' && /^([m-zA-HJ-NP-Z1-9]{26,35}|[a-z]{2,5}1[ac-hj-np-z02-9]{8,100}|[a-km-zA-HJ-NP-Z1-9]{80})$/.test(address.address)) {
if ((this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') && /^([m-zA-HJ-NP-Z1-9]{26,35}|[a-z]{2,5}1[ac-hj-np-z02-9]{8,100}|[a-km-zA-HJ-NP-Z1-9]{80})$/.test(address.address)) {
this.apiService.validateAddress$(address.address)
.subscribe((addressInfo) => {
this.addressInfo = addressInfo;

View File

@ -2,12 +2,13 @@
<span class="fiat">{{ conversions.USD * (satoshis / 100000000) | currency:'USD':'symbol':'1.2-2' }}</span>
</ng-container>
<ng-template #viewFiatVin>
<ng-template [ngIf]="network === 'liquid' && (satoshis === undefined || satoshis === null)" [ngIfElse]="default">
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && (satoshis === undefined || satoshis === null)" [ngIfElse]="default">
<span i18n="shared.confidential">Confidential</span>
</ng-template>
<ng-template #default>
&lrm;{{ satoshis / 100000000 | number : digitsInfo }}
<span class="symbol"><ng-template [ngIf]="network === 'liquid'">L-</ng-template>
<ng-template [ngIf]="network === 'liquidtestnet'">tL-</ng-template>
<ng-template [ngIf]="network === 'testnet'">t</ng-template>
<ng-template [ngIf]="network === 'signet'">s</ng-template>BTC</span>
</ng-template>

View File

@ -10,7 +10,7 @@
</ng-container>
</a>
<div ngbDropdown (window:resize)="onResize($event)" class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED">
<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">
<button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split" aria-haspopup="true">
<img src="./resources/bisq-logo.png" style="width: 25px; height: 25px;" class="mr-1">
</button>
@ -21,6 +21,7 @@
<h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6>
<button ngbDropdownItem class="mainnet active" routerLink="/"><img src="./resources/bisq-logo.png" style="width: 30px;" class="mr-1"> Bisq</button>
<a href="https://liquid.network" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid"><img src="./resources/liquid-logo.png" style="width: 30px;" class="mr-1"> Liquid</a>
<a href="https://liquid.network/testnet" ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED" class="liquidtestnet"><img src="./resources/liquidtestnet-logo.png" style="width: 30px;" class="mr-1"> Liquid Testnet</a>
</div>
</div>

View File

@ -102,6 +102,10 @@ nav {
background-color: #116761;
}
.liquidtestnet.active {
background-color: #494a4a;
}
.testnet.active {
background-color: #1d486f;
}

View File

@ -81,12 +81,12 @@
<ng-template [ngIf]="fees !== undefined" [ngIfElse]="loadingFees">
<tr>
<td i18n="block.total-fees|Total fees in a block">Total fees</td>
<td *ngIf="network !== 'liquid'; else liquidTotalFees"><app-amount [satoshis]="fees * 100000000" digitsInfo="1.2-2" [noFiat]="true"></app-amount> <span class="fiat"><app-fiat [value]="fees * 100000000" digitsInfo="1.0-0"></app-fiat></span></td>
<td *ngIf="network !== 'liquid' && network !== 'liquidtestnet'; else liquidTotalFees"><app-amount [satoshis]="fees * 100000000" digitsInfo="1.2-2" [noFiat]="true"></app-amount> <span class="fiat"><app-fiat [value]="fees * 100000000" digitsInfo="1.0-0"></app-fiat></span></td>
<ng-template #liquidTotalFees>
<td>{{ fees * 100000000 | number }} L-sat (<app-fiat [value]="fees * 100000000" digitsInfo="1.2-2"></app-fiat>)</td>
<td><app-amount [satoshis]="fees * 100000000" digitsInfo="1.2-2" [noFiat]="true"></app-amount>&nbsp; <app-fiat [value]="fees * 100000000" digitsInfo="1.2-2"></app-fiat></td>
</ng-template>
</tr>
<tr *ngIf="network !== 'liquid'">
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td i18n="block.subsidy-and-fees|Total subsidy and fees in a block">Subsidy + fees:</td>
<td>
<app-amount [satoshis]="(blockSubsidy + fees) * 100000000" digitsInfo="1.2-2" [noFiat]="true"></app-amount> <span class="fiat"><app-fiat [value]="(blockSubsidy + fees) * 100000000" digitsInfo="1.0-0"></app-fiat></span>
@ -98,7 +98,7 @@
<td i18n="block.total-fees|Total fees in a block">Total fees</td>
<td style="width: 75%;"><span class="skeleton-loader"></span></td>
</tr>
<tr *ngIf="network !== 'liquid'">
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td i18n="block.subsidy-and-fees|Total subsidy and fees in a block">Subsidy + fees:</td>
<td><span class="skeleton-loader"></span></td>
</tr>
@ -125,7 +125,7 @@
<td class="td-width" i18n="transaction.version">Version</td>
<td>{{ block.version | decimal2hex }} <span *ngIf="displayTaprootStatus() && hasTaproot(block.version)" class="badge badge-success ml-1" >Taproot</span></td>
</tr>
<tr *ngIf="network !== 'liquid'">
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td i18n="block.bits">Bits</td>
<td>{{ block.bits | decimal2hex }}</td>
</tr>
@ -136,7 +136,7 @@
</tbody>
</table>
</div>
<div class="col-sm" *ngIf="network !== 'liquid'">
<div class="col-sm" *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<table class="table table-borderless table-striped">
<tbody>
<tr>

View File

@ -210,7 +210,7 @@ export class BlockComponent implements OnInit, OnDestroy {
}
setBlockSubsidy() {
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
this.blockSubsidy = 0;
return;
}

View File

@ -36,6 +36,7 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy {
'': ['#9339f4', '#105fb0'],
bisq: ['#9339f4', '#105fb0'],
liquid: ['#116761', '#183550'],
'liquidtestnet': ['#494a4a', '#272e46'],
testnet: ['#1d486f', '#183550'],
signet: ['#6f1d5d', '#471850'],
};
@ -47,7 +48,7 @@ export class BlockchainBlocksComponent implements OnInit, OnDestroy {
) { }
ngOnInit() {
if (this.stateService.network === 'liquid') {
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
this.feeRounding = '1.0-1';
}
this.emptyBlocks.forEach((b) => this.emptyBlockStyles.push(this.getStyleForEmptyBlock(b)));

View File

@ -31,7 +31,7 @@
top: 75px;
}
.position-container.liquid {
.position-container.liquid, .position-container.liquidtestnet {
left: 420px;
}
@ -39,7 +39,7 @@
.position-container {
left: 95%;
}
.position-container.liquid {
.position-container.liquid, .position-container.liquidtestnet {
left: 50%;
}
.position-container.loading {

View File

@ -27,7 +27,7 @@
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-address-transactions-mempool" (click)="collapseItem.toggle()">GET Address Transactions Mempool</a>
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-address-utxo" (click)="collapseItem.toggle()">GET Address UTXO</a>
<ng-template [ngIf]="network.val === 'liquid'">
<ng-template [ngIf]="network.val === 'liquid' || network.val === 'liquidtestnet'">
<p>Assets</p>
<a [routerLink]="['./']" fragment="get-assets" (click)="collapseItem.toggle()">GET Assets</a>
<a [routerLink]="['./']" fragment="get-assets-icons" (click)="collapseItem.toggle()">GET Assets Icons</a>
@ -66,7 +66,7 @@
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-cpfp" (click)="collapseItem.toggle()">GET Children Pay for Parent</a>
<a [routerLink]="['./']" fragment="get-transaction" (click)="collapseItem.toggle()">GET Transaction</a>
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-transaction-hex" (click)="collapseItem.toggle()">GET Transaction Hex</a>
<a *ngIf="network.val !== 'bisq' && network.val !== 'liquid'" [routerLink]="['./']" fragment="get-transaction-merkleblock-proof" (click)="collapseItem.toggle()">GET Transaction Merkleblock Proof</a>
<a *ngIf="network.val !== 'bisq' && network.val !== 'liquid' && network.val !== 'liquidtestnet'" [routerLink]="['./']" fragment="get-transaction-merkleblock-proof" (click)="collapseItem.toggle()">GET Transaction Merkleblock Proof</a>
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-transaction-merkle-proof" (click)="collapseItem.toggle()">GET Transaction Merkle Proof</a>
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-transaction-outspend" (click)="collapseItem.toggle()">GET Transaction Outspend</a>
<a *ngIf="network.val !== 'bisq'" [routerLink]="['./']" fragment="get-transaction-outspends" (click)="collapseItem.toggle()">GET Transaction Outspends</a>

View File

@ -24,7 +24,7 @@
<div id="mobile-top-doc-nav" #mobileFixedApiNav class="hide-on-desktop"><app-api-docs-nav [network]="{ val: network$ | async }"></app-api-docs-nav></div>
<div class="api-category" *ngIf="network.val !== 'bisq' && network.val !== 'liquid'">
<div class="api-category" *ngIf="network.val !== 'bisq' && network.val !== 'liquid' && network.val !== 'liquidtestnet'">
<div class="endpoint-container" id="get-difficulty-adjustment">
<a class="section-header" [routerLink]="['./']" fragment="get-difficulty-adjustment">GET Difficulty Adjustment <span>General</span></a>
@ -228,14 +228,14 @@
</div>
<div class="description">
<div class="subtitle" i18n>Description</div>
<div i18n>Get the list of unspent transaction outputs associated with the address/scripthash. Available fields: <code>txid</code>, <code>vout</code>, <code>value</code>, and <code>status</code> (with the status of the funding tx).<ng-container *ngIf="network.val === 'liquid'">There is also a <code>valuecommitment</code> field that may appear in place of <code>value</code>, plus the following additional fields: <code>asset</code>/<code>assetcommitment</code>, <code>nonce</code>/<code>noncecommitment</code>, <code>surjection_proof</code>, and <code>range_proof</code>.</ng-container></div>
<div i18n>Get the list of unspent transaction outputs associated with the address/scripthash. Available fields: <code>txid</code>, <code>vout</code>, <code>value</code>, and <code>status</code> (with the status of the funding tx).<ng-container *ngIf="network.val === 'liquid' || network.val === 'liquidtestnet'">There is also a <code>valuecommitment</code> field that may appear in place of <code>value</code>, plus the following additional fields: <code>asset</code>/<code>assetcommitment</code>, <code>nonce</code>/<code>noncecommitment</code>, <code>surjection_proof</code>, and <code>range_proof</code>.</ng-container></div>
</div>
<app-code-template [hostname]="hostname" [code]="code.addressUTXO" [network]="network.val" ></app-code-template>
</div>
</div>
<div class="api-category" *ngIf="network.val === 'liquid'">
<div class="api-category" *ngIf="network.val === 'liquid' || network.val === 'liquidtestnet'">
<div class="endpoint-container" id="get-assets">
<a class="section-header" [routerLink]="['./']" fragment="get-assets">GET Assets <span>Assets</span></a>
@ -313,7 +313,7 @@
</div>
<div class="description">
<div class="subtitle" i18n>Description</div>
<div i18n>Returns details about a block. Available fields: <code>id</code>, <code>height</code>, <code>version</code>, <code>timestamp</code>, <code>bits</code>, <code>nonce</code>, <code>merkle_root</code>, <code>tx_count</code>, <code>size</code>, <code>weight</code>,<ng-container *ngIf="network.val === 'liquid'"> <code>proof</code>,</ng-container> and <code>previousblockhash</code>.</div>
<div i18n>Returns details about a block. Available fields: <code>id</code>, <code>height</code>, <code>version</code>, <code>timestamp</code>, <code>bits</code>, <code>nonce</code>, <code>merkle_root</code>, <code>tx_count</code>, <code>size</code>, <code>weight</code>,<ng-container *ngIf="network.val === 'liquid' || network.val === 'liquidtestnet'"> <code>proof</code>,</ng-container> and <code>previousblockhash</code>.</div>
</div>
<app-code-template [hostname]="hostname" [code]="code.block" [network]="network.val" ></app-code-template>
</div>
@ -577,7 +577,7 @@
<app-code-template [hostname]="hostname" [code]="code.transactionHex" [network]="network.val" ></app-code-template>
</div>
<div class="endpoint-container" *ngIf="network.val !== 'bisq' && network.val !== 'liquid'" id="get-transaction-merkleblock-proof">
<div class="endpoint-container" *ngIf="network.val !== 'bisq' && network.val !== 'liquid' && network.val !== 'liquidtestnet'" id="get-transaction-merkleblock-proof">
<a class="section-header" [routerLink]="['./']" fragment="get-transaction-merkleblock-proof">GET Transaction Merkleblock Proof <span>Transactions</span></a>
<div class="endpoint">
<div class="subtitle" i18n="Api docs endpoint">Endpoint</div>

View File

@ -3663,7 +3663,7 @@ export class ApiDocsComponent implements OnInit {
};
this.network$.subscribe((network) => {
this.active = (network === 'liquid') ? 2 : 0;
this.active = (network === 'liquid' || network === 'liquidtestnet') ? 2 : 0;
});
}
@ -3679,7 +3679,7 @@ export class ApiDocsComponent implements OnInit {
if (network === 'signet') {
curlResponse = code.codeSampleSignet.curl;
}
if (network === 'liquid') {
if (network === 'liquid' || network === 'liquidtestnet') {
curlResponse = code.codeSampleLiquid.curl;
}
if (network === 'bisq') {

View File

@ -26,7 +26,7 @@ export class CodeTemplateComponent implements OnInit {
if (this.network === 'bisq') {
npmLink = `https://github.com/mempool/mempool.js/tree/main/npm-bisq-js`;
}
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
npmLink = `https://github.com/mempool/mempool.js/tree/main/npm-liquid-js`;
}
return npmLink;
@ -37,7 +37,7 @@ export class CodeTemplateComponent implements OnInit {
if (this.network === 'bisq') {
npmLink = `https://www.npmjs.org/package/@mempool/bisq.js`;
}
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
npmLink = `https://www.npmjs.org/package/@mempool/liquid.js`;
}
return npmLink;
@ -50,7 +50,7 @@ export class CodeTemplateComponent implements OnInit {
} else {
codeText = codeText.replace('%{0}', 'bitcoin');
}
if(['', 'main', 'liquid', 'bisq'].includes(this.network)) {
if(['', 'main', 'liquid', 'bisq', 'liquidtestnet'].includes(this.network)) {
codeText = codeText.replace('mempoolJS();', `mempoolJS({
hostname: '${document.location.hostname}'
});`);
@ -119,7 +119,7 @@ export class CodeTemplateComponent implements OnInit {
if (this.network === 'signet') {
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleSignet.esModule);
}
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleLiquid.esModule);
}
if (this.network === 'bisq') {
@ -157,7 +157,7 @@ init();`;
if (this.network === 'signet') {
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleSignet.esModule);
}
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
codeText = this.replaceJSPlaceholder(codeText, code.codeSampleLiquid.esModule);
}
if (this.network === 'bisq') {
@ -237,7 +237,7 @@ yarn add @mempool/liquid.js`;
if (this.network === 'signet') {
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleSignet);
}
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
return this.replaceCurlPlaceholder(code.codeTemplate.curl, code.codeSampleLiquid);
}
if (this.network === 'bisq') {
@ -259,7 +259,7 @@ yarn add @mempool/liquid.js`;
if (this.network === 'signet') {
return code.codeSampleSignet.response;
}
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
return code.codeSampleLiquid.response;
}
if (this.network === 'bisq') {

View File

@ -26,7 +26,7 @@ export class FeesBoxComponent implements OnInit {
) { }
ngOnInit(): void {
this.defaultFee = this.stateService.network === 'liquid' ? 0.1 : 1;
this.defaultFee = this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet' ? 0.1 : 1;
this.isLoadingWebSocket$ = this.stateService.isLoadingWebSocket$;
this.feeEstimations$ = this.stateService.mempoolBlocks$

View File

@ -1,3 +1,4 @@
<ng-container *ngIf="{ val: network$ | async } as network">
<header>
<nav class="navbar navbar-expand-md navbar-dark bg-dark">
<a class="navbar-brand" [routerLink]="['/' | relativeUrl]" style="position: relative;">
@ -10,9 +11,9 @@
</ng-container>
</a>
<div ngbDropdown (window:resize)="onResize($event)" class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED">
<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">
<button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split" aria-haspopup="true">
<img src="./resources/liquid-logo.png" style="width: 25px; height: 25px;" class="mr-1">
<img src="./resources/{{ network.val === '' ? 'liquid' : network.val }}-logo.png" style="width: 25px; height: 25px;" class="mr-1">
</button>
<div ngbDropdownMenu [ngClass]="{'dropdown-menu-right' : isMobile}">
<a href="https://mempool.space" ngbDropdownItem class="mainnet"><img src="./resources/bitcoin-logo.png" style="width: 30px;" class="mr-1"> Mainnet</a>
@ -20,7 +21,8 @@
<a href="https://mempool.space/testnet" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><img src="./resources/testnet-logo.png" style="width: 30px;" class="mr-1"> Testnet</a>
<h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6>
<a href="https://bisq.markets" ngbDropdownItem class="mainnet"><img src="./resources/bisq-logo.png" style="width: 30px;" class="mr-1"> Bisq</a>
<button ngbDropdownItem class="liquid active" routerLink="/"><img src="./resources/liquid-logo.png" style="width: 30px;" class="mr-1"> Liquid</button>
<button ngbDropdownItem class="liquid" [class.active]="network.val === 'liquid'" routerLink="/"><img src="./resources/liquid-logo.png" style="width: 30px;" class="mr-1"> Liquid</button>
<button ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED" class="liquidtestnet" [class.active]="network.val === 'liquidtestnet'" routerLink="/testnet"><img src="./resources/liquidtestnet-logo.png" style="width: 30px;" class="mr-1"> Liquid Testnet</button>
</div>
</div>
@ -41,7 +43,7 @@
</li>
-->
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" [routerLink]="['/assets']" (click)="collapse()"><fa-icon [icon]="['fas', 'database']" [fixedWidth]="true" i18n-title="master-page.assets" title="Assets"></fa-icon></a>
<a class="nav-link" [routerLink]="['/assets' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'database']" [fixedWidth]="true" i18n-title="master-page.assets" title="Assets"></fa-icon></a>
</li>
<li [hidden]="isMobile" class="nav-item mr-2" routerLinkActive="active">
<a class="nav-link" [routerLink]="['/docs' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'book']" [fixedWidth]="true" i18n-title="master-page.docs" title="Docs"></fa-icon></a>
@ -60,3 +62,4 @@
<router-outlet></router-outlet>
<br>
</ng-container>

View File

@ -102,6 +102,10 @@ nav {
background-color: #116761;
}
.liquidtestnet.active {
background-color: #494a4a;
}
.testnet.active {
background-color: #1d486f;
}

View File

@ -1,6 +1,6 @@
import { Component, OnInit } from '@angular/core';
import { Env, StateService } from '../../services/state.service';
import { Observable} from 'rxjs';
import { merge, Observable, of} from 'rxjs';
@Component({
selector: 'app-liquid-master-page',
@ -13,6 +13,7 @@ export class LiquidMasterPageComponent implements OnInit {
navCollapsed = false;
isMobile = window.innerWidth <= 767.98;
officialMempoolSpace = this.stateService.env.OFFICIAL_MEMPOOL_SPACE;
network$: Observable<string>;
constructor(
private stateService: StateService,
@ -21,6 +22,7 @@ export class LiquidMasterPageComponent implements OnInit {
ngOnInit() {
this.env = this.stateService.env;
this.connectionState$ = this.stateService.connectionState$;
this.network$ = merge(of(''), this.stateService.networkChanged$);
}
collapse(): void {

View File

@ -11,7 +11,7 @@
</ng-container>
</a>
<div (window:resize)="onResize($event)" ngbDropdown class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED">
<div (window:resize)="onResize($event)" ngbDropdown class="dropdown-container" *ngIf="env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.BISQ_ENABLED || env.LIQUID_TESTNET_ENABLED">
<button ngbDropdownToggle type="button" class="btn btn-secondary dropdown-toggle-split" aria-haspopup="true">
<img src="./resources/{{ network.val === '' ? 'bitcoin' : network.val }}-logo.png" style="width: 25px; height: 25px;" class="mr-1">
</button>
@ -24,6 +24,8 @@
<button ngbDropdownItem *ngIf="env.BISQ_ENABLED && !env.OFFICIAL_MEMPOOL_SPACE" class="bisq" [class.active]="network.val === 'bisq'" routerLink="/bisq"><img src="./resources/bisq-logo.png" style="width: 30px;" class="mr-1"> Bisq</button>
<a href="https://liquid.network" ngbDropdownItem *ngIf="env.LIQUID_ENABLED && env.OFFICIAL_MEMPOOL_SPACE" class="liquid" [class.active]="network.val === 'liquid'"><img src="./resources/liquid-logo.png" style="width: 30px;" class="mr-1"> Liquid</a>
<button ngbDropdownItem *ngIf="env.LIQUID_ENABLED && !env.OFFICIAL_MEMPOOL_SPACE" class="liquid" [class.active]="network.val === 'liquid'" routerLink="/liquid"><img src="./resources/liquid-logo.png" style="width: 30px;" class="mr-1"> Liquid</button>
<a href="https://liquid.network/testnet" ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED && env.OFFICIAL_MEMPOOL_SPACE" class="liquidtestnet" [class.active]="network.val === 'liquid'"><img src="./resources/liquidtestnet-logo.png" style="width: 30px;" class="mr-1"> Liquid Testnet</a>
<button ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED && !env.OFFICIAL_MEMPOOL_SPACE" class="liquidtestnet" [class.active]="network.val === 'liquidtestnet'" routerLink="/liquidtestnet"><img src="./resources/liquidtestnet-logo.png" style="width: 30px;" class="mr-1"> Liquid Testnet</button>
</div>
</div>
@ -54,8 +56,8 @@
<a class="nav-link" [routerLink]="['/tv' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tv']" [fixedWidth]="true" i18n-title="master-page.tvview" title="TV view"></fa-icon></a>
</li>
</ng-template>
<li *ngIf="network.val === 'liquid'" class="nav-item" routerLinkActive="active">
<a class="nav-link" [routerLink]="['/liquid/assets']" (click)="collapse()"><fa-icon [icon]="['fas', 'database']" [fixedWidth]="true" i18n-title="master-page.assets" title="Assets"></fa-icon></a>
<li *ngIf="network.val === 'liquid' || network.val === 'liquidtestnet'" class="nav-item" routerLinkActive="active">
<a class="nav-link" [routerLink]="['/assets' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'database']" [fixedWidth]="true" i18n-title="master-page.assets" title="Assets"></fa-icon></a>
</li>
<li class="nav-item" routerLinkActive="active">
<a class="nav-link" [routerLink]="['/docs' | relativeUrl ]" (click)="collapse()"><fa-icon [icon]="['fas', 'book']" [fixedWidth]="true" i18n-title="documentation.title" title="Documentation"></fa-icon></a>

View File

@ -110,6 +110,10 @@ nav {
background-color: #116761;
}
.liquidtestnet.active {
background-color: #494a4a;
}
.testnet.active {
background-color: #1d486f;
}

View File

@ -19,7 +19,7 @@
<ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} transactions</ng-template>
</div>
<div class="time-difference" *ngIf="projectedBlock.blockVSize <= stateService.blockVSize; else mergedBlock">
<ng-template [ngIf]="network === 'liquid'" [ngIfElse]="timeDiffMainnet">
<ng-template [ngIf]="network === 'liquid' || network === 'liquidtestnet'" [ngIfElse]="timeDiffMainnet">
<app-time-until [time]="(1 * i) + now + 61000" [fastRender]="false" [fixedRender]="true"></app-time-until>
</ng-template>
<ng-template #timeDiffMainnet>

View File

@ -55,7 +55,7 @@ export class MempoolBlocksComponent implements OnInit, OnDestroy {
) { }
ngOnInit() {
if (this.stateService.network === 'liquid') {
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
this.feeRounding = '1.0-1';
}
this.mempoolEmptyBlocks.forEach((b) => {

View File

@ -371,7 +371,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
this.feeLimitIndex = i;
}
if (feeLevels[i] <= this.limitFee) {
if (this.stateService.network === 'liquid') {
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
this.feeLevelsOrdered.push(`${(feeLevels[i] / 10).toFixed(1)} - ${(feeLevels[i + 1] / 10).toFixed(1)}`);
} else {
this.feeLevelsOrdered.push(`${feeLevels[i]} - ${feeLevels[i + 1]}`);

View File

@ -48,7 +48,7 @@ export class SearchFormComponent implements OnInit {
searchText: ['', Validators.required],
});
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
this.assetsService.getAssetsMinimalJson$
.subscribe((assets) => {
this.assets = assets;
@ -101,7 +101,7 @@ export class SearchFormComponent implements OnInit {
this.navigate('/block/', searchText);
} else if (this.regexTransaction.test(searchText)) {
const matches = this.regexTransaction.exec(searchText);
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
if (this.assets[matches[1]]) {
this.navigate('/asset/', matches[1]);
}

View File

@ -117,7 +117,7 @@
</ng-template>
<ng-template [ngIf]="paymentForm.get('method').value === 'lbtc'">
<ng-template [ngIf]="paymentForm.get('method').value === 'lbtc' || paymentForm.get('method').value === 'tlbtc'">
<div class="qr-wrapper">
<a [href]="bypassSecurityTrustUrl('liquidnetwork:' + donationObj.addresses.LBTC + '?amount=' + donationObj.amount + '&assetid=6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d')" target="_blank">

View File

@ -66,7 +66,7 @@
<td><app-time-span [time]="tx.status.block_time - transactionTime" [fastRender]="true"></app-time-span></td>
</tr>
</ng-template>
<tr *ngIf="network !== 'liquid'">
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td class="td-width" i18n="transaction.features|Transaction features">Features</td>
<td>
<app-tx-features [tx]="tx"></app-tx-features>
@ -114,7 +114,7 @@
<span i18n="transaction.eta.in-several-hours|Transaction ETA in several hours or more">In several hours (or more)</span>
</ng-template>
<ng-template #belowBlockLimit>
<ng-template [ngIf]="network === 'liquid'" [ngIfElse]="timeEstimateDefault">
<ng-template [ngIf]="network === 'liquid' || network === 'liquidtestnet'" [ngIfElse]="timeEstimateDefault">
<app-time-until [time]="(60 * 1000 * txInBlockIndex) + now" [fastRender]="false" [fixedRender]="true"></app-time-until>
</ng-template>
<ng-template #timeEstimateDefault>
@ -124,7 +124,7 @@
</ng-template>
</td>
</tr>
<tr *ngIf="network !== 'liquid'">
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td class="td-width" i18n="transaction.features|Transaction Features">Features</td>
<td>
<app-tx-features [tx]="tx"></app-tx-features>

View File

@ -159,7 +159,7 @@ export class TransactionComponent implements OnInit, OnDestroy {
);
}),
switchMap((tx) => {
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
return from(this.liquidUnblinding.checkUnblindedTx(tx))
.pipe(
catchError((error) => {

View File

@ -48,7 +48,7 @@
</td>
<td>
<div [ngSwitch]="true">
<ng-container *ngSwitchCase="vin.is_coinbase"><span i18n="transactions-list.coinbase">Coinbase</span><ng-template [ngIf]="network !== 'liquid'">&nbsp;<span i18n="transactions-list.newly-generated-coins">(Newly Generated Coins)</span></ng-template><br /><a placement="bottom" [ngbTooltip]="vin.scriptsig | hex2ascii"><span class="badge badge-secondary scriptmessage longer">{{ vin.scriptsig | hex2ascii }}</span></a></ng-container>
<ng-container *ngSwitchCase="vin.is_coinbase"><span i18n="transactions-list.coinbase">Coinbase</span><ng-template [ngIf]="network !== 'liquid' && network !== 'liquidtestnet'">&nbsp;<span i18n="transactions-list.newly-generated-coins">(Newly Generated Coins)</span></ng-template><br /><a placement="bottom" [ngbTooltip]="vin.scriptsig | hex2ascii"><span class="badge badge-secondary scriptmessage longer">{{ vin.scriptsig | hex2ascii }}</span></a></ng-container>
<ng-container *ngSwitchCase="vin.is_pegin">
<span i18n="transactions-list.peg-in">Peg-in</span>
</ng-container>
@ -244,7 +244,7 @@
&nbsp;
</span>
<button type="button" class="btn btn-sm btn-primary mt-2" (click)="switchCurrency()">
<ng-template [ngIf]="network === 'liquid'" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
<ng-template [ngIf]="network === 'liquid' || network === 'liquidtestnet'" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
<ng-template #defaultAmount>
<app-amount [satoshis]="getTotalTxOutput(tx)"></app-amount>
</ng-template>

View File

@ -41,7 +41,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
this.latestBlock$ = this.stateService.blocks$.pipe(map(([block]) => block));
this.stateService.networkChanged$.subscribe((network) => this.network = network);
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
this.assetsService.getAssetsMinimalJson$.subscribe((assets) => {
this.assetsMinimal = assets;
});
@ -99,7 +99,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
}
switchCurrency() {
if (this.network === 'liquid') {
if (this.network === 'liquid' || this.network === 'liquidtestnet') {
return;
}
const oldvalue = !this.stateService.viewFiat$.value;

View File

@ -2,7 +2,7 @@
<div class="container-xl dashboard-container">
<div class="row row-cols-1 row-cols-md-2" *ngIf="{ value: (mempoolInfoData$ | async) } as mempoolInfoData">
<ng-template [ngIf]="collapseLevel === 'three'" [ngIfElse]="expanded">
<div class="col card-wrapper" *ngIf="(network$ | async) !== 'liquid'">
<div class="col card-wrapper" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'">
<div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div>
<div class="card">
<div class="card-body">
@ -10,7 +10,7 @@
</div>
</div>
</div>
<div class="col" *ngIf="(network$ | async) !== 'liquid'">
<div class="col" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'">
<ng-container *ngTemplateOutlet="difficultyEpoch"></ng-container>
</div>
<div class="col">
@ -23,13 +23,13 @@
<div class="col">
<div class="card">
<div class="card-body">
<ng-container *ngTemplateOutlet="stateService.network === 'liquid' ? lbtcPegs : txPerSecond; context: { $implicit: mempoolInfoData }"></ng-container>
<ng-container *ngTemplateOutlet="stateService.network === 'liquid' || stateService.network === 'liquidtestnet' ? lbtcPegs : txPerSecond; context: { $implicit: mempoolInfoData }"></ng-container>
</div>
</div>
</div>
</ng-template>
<ng-template #expanded>
<div class="col card-wrapper" *ngIf="(network$ | async) !== 'liquid'">
<div class="col card-wrapper" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'">
<div class="main-title" i18n="fees-box.transaction-fees">Transaction Fees</div>
<div class="card">
<div class="card-body">
@ -37,7 +37,7 @@
</div>
</div>
</div>
<div class="col" *ngIf="(network$ | async) !== 'liquid'">
<div class="col" *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'">
<ng-container *ngTemplateOutlet="difficultyEpoch"></ng-container>
</div>
<div class="col">
@ -64,9 +64,9 @@
<div class="col">
<div class="card graph-card">
<div class="card-body">
<ng-container *ngTemplateOutlet="stateService.network === 'liquid' ? lbtcPegs : txPerSecond; context: { $implicit: mempoolInfoData }"></ng-container>
<ng-container *ngTemplateOutlet="stateService.network === 'liquid' || stateService.network === 'liquidtestnet' ? lbtcPegs : txPerSecond; context: { $implicit: mempoolInfoData }"></ng-container>
<hr>
<div class="mempool-graph" *ngIf="stateService.network === 'liquid'; else mempoolGraph">
<div class="mempool-graph" *ngIf="stateService.network === 'liquid' || stateService.network === 'liquidtestnet'; else mempoolGraph">
<app-lbtc-pegs-graph [data]="liquidPegsMonth$ | async"></app-lbtc-pegs-graph>
</div>
<ng-template #mempoolGraph>
@ -125,7 +125,7 @@
<tbody>
<tr *ngFor="let transaction of transactions$ | async; let i = index;">
<td class="table-cell-txid"><a [routerLink]="['/tx' | relativeUrl, transaction.txid]">{{ transaction.txid | shortenString : 10 }}</a></td>
<td class="table-cell-satoshis"><app-amount *ngIf="(network$ | async) !== 'liquid'; else liquidAmount" [satoshis]="transaction.value" digitsInfo="1.2-4" [noFiat]="true"></app-amount><ng-template #liquidAmount i18n="shared.confidential">Confidential</ng-template></td>
<td class="table-cell-satoshis"><app-amount *ngIf="(network$ | async) !== 'liquid' && (network$ | async) !== 'liquidtestnet'; else liquidAmount" [satoshis]="transaction.value" digitsInfo="1.2-4" [noFiat]="true"></app-amount><ng-template #liquidAmount i18n="shared.confidential">Confidential</ng-template></td>
<td class="table-cell-fiat" *ngIf="(network$ | async) === ''" ><app-fiat [value]="transaction.value" digitsInfo="1.0-0"></app-fiat></td>
<td class="table-cell-fees">{{ transaction.fee / transaction.vsize | feeRounding }} <span class="symbol" i18n="shared.sat-vbyte|sat/vB">sat/vB</span></td>
</tr>

View File

@ -262,7 +262,7 @@ export class DashboardComponent implements OnInit {
share(),
);
if (this.stateService.network === 'liquid') {
if (this.stateService.network === 'liquid' || this.stateService.network === 'liquidtestnet') {
this.liquidPegsMonth$ = this.apiService.listLiquidPegsMonth$()
.pipe(
map((pegs) => {

View File

@ -29,6 +29,8 @@ export class SeoService {
getTitle(): string {
if (this.network === 'liquid')
return 'mempool - Liquid Network';
if (this.network === 'liquidtestnet')
return 'mempool - Liquid Network Testnet';
if (this.network === 'bisq')
return 'mempool - Bisq Markets';
return 'mempool - ' + (this.network ? this.ucfirst(this.network) : 'Bitcoin') + ' Explorer';

View File

@ -19,6 +19,7 @@ export interface Env {
TESTNET_ENABLED: boolean;
SIGNET_ENABLED: boolean;
LIQUID_ENABLED: boolean;
LIQUID_TESTNET_ENABLED: boolean;
BISQ_ENABLED: boolean;
BISQ_SEPARATE_BACKEND: boolean;
ITEMS_PER_PAGE: number;
@ -38,6 +39,7 @@ const defaultEnv: Env = {
'TESTNET_ENABLED': false,
'SIGNET_ENABLED': false,
'LIQUID_ENABLED': false,
'LIQUID_TESTNET_ENABLED': false,
'BASE_MODULE': 'mempool',
'BISQ_ENABLED': false,
'BISQ_SEPARATE_BACKEND': false,
@ -116,7 +118,7 @@ export class StateService {
this.blocks$ = new ReplaySubject<[Block, boolean]>(this.env.KEEP_BLOCKS_AMOUNT);
if (this.env.BASE_MODULE !== 'mempool') {
if (this.env.BASE_MODULE === 'bisq') {
this.network = this.env.BASE_MODULE;
this.networkChanged$.next(this.env.BASE_MODULE);
}
@ -125,10 +127,10 @@ export class StateService {
}
setNetworkBasedonUrl(url: string) {
if (this.env.BASE_MODULE !== 'mempool') {
if (this.env.BASE_MODULE !== 'mempool' && this.env.BASE_MODULE !== 'liquid') {
return;
}
const networkMatches = url.match(/\/(bisq|testnet|liquid|signet)/);
const networkMatches = url.match(/\/(bisq|testnet|liquidtestnet|liquid|signet)/);
switch (networkMatches && networkMatches[1]) {
case 'liquid':
if (this.network !== 'liquid') {
@ -136,6 +138,12 @@ export class StateService {
this.networkChanged$.next('liquid');
}
return;
case 'liquidtestnet':
if (this.network !== 'liquidtestnet') {
this.network = 'liquidtestnet';
this.networkChanged$.next('liquidtestnet');
}
return;
case 'signet':
if (this.network !== 'signet') {
this.network = 'signet';
@ -144,8 +152,13 @@ export class StateService {
return;
case 'testnet':
if (this.network !== 'testnet') {
this.network = 'testnet';
this.networkChanged$.next('testnet');
if (this.env.BASE_MODULE === 'liquid') {
this.network = 'liquidtestnet';
this.networkChanged$.next('liquidtestnet');
} else {
this.network = 'testnet';
this.networkChanged$.next('testnet');
}
}
return;
case 'bisq':
@ -155,9 +168,14 @@ export class StateService {
}
return;
default:
if (this.network !== '') {
this.network = '';
this.networkChanged$.next('');
if (this.env.BASE_MODULE !== 'mempool' && this.network !== this.env.BASE_MODULE) {
this.network = this.env.BASE_MODULE;
this.networkChanged$.next(this.env.BASE_MODULE);
} else {
if (this.network !== '') {
this.network = '';
this.networkChanged$.next('');
}
}
}
}

View File

@ -11,10 +11,13 @@ export class RelativeUrlPipe implements PipeTransform {
) { }
transform(value: string): string {
if (this.stateService.env.BASE_MODULE !== 'mempool') {
return '/' + value;
let network = this.stateService.network;
if (this.stateService.env.BASE_MODULE === 'liquid' && network === 'liquidtestnet') {
network = 'testnet';
} else if (this.stateService.env.BASE_MODULE !== 'mempool') {
network = '';
}
return (this.stateService.network ? '/' + this.stateService.network : '') + value;
return (network ? '/' + network : '') + value;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,39 @@
{
"MEMPOOL": {
"NETWORK": "liquid",
"BACKEND": "esplora",
"HTTP_PORT": 8998,
"MINED_BLOCKS_CACHE": 144,
"SPAWN_CLUSTER_PROCS": 0,
"API_URL_PREFIX": "/api/v1/",
"WEBSOCKET_REFRESH_RATE_MS": 2000
},
"SYSLOG" : {
"MIN_PRIORITY": "debug"
},
"CORE_RPC": {
"PORT": 7041,
"USERNAME": "foo",
"PASSWORD": "bar"
},
"SECOND_CORE_RPC": {
"PORT": 8332,
"USERNAME": "foo",
"PASSWORD": "bar"
},
"ESPLORA": {
"REST_API_URL": "http://127.0.0.1:4001"
},
"DATABASE": {
"ENABLED": true,
"HOST": "127.0.0.1",
"PORT": 3306,
"USERNAME": "lmempool",
"PASSWORD": "lmempool",
"DATABASE": "lmempool"
},
"STATISTICS": {
"ENABLED": true,
"TX_PER_SECOND_SAMPLE_PERIOD": 150
}
}

View File

@ -1,6 +1,7 @@
{
"TESTNET_ENABLED": true,
"LIQUID_ENABLED": true,
"LIQUID_TESTNET_ENABLED": true,
"BISQ_ENABLED": true,
"BISQ_SEPARATE_BACKEND": true,
"SIGNET_ENABLED": true,