Merge pull request #1052 from mempool/simon/liquid-testnet
Adding Liquid Testnet as frontend option
This commit is contained in:
		
						commit
						a2b1669f94
					
				@ -1,7 +1,9 @@
 | 
			
		||||
import { CpfpInfo, TransactionExtended, TransactionStripped } from '../mempool.interfaces';
 | 
			
		||||
import config from '../config';
 | 
			
		||||
export class Common {
 | 
			
		||||
  static nativeAssetId = '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d';
 | 
			
		||||
  static nativeAssetId = config.MEMPOOL.NETWORK === 'liquidtestnet' ?
 | 
			
		||||
    '144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49'
 | 
			
		||||
  : '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d';
 | 
			
		||||
 | 
			
		||||
  static median(numbers: number[]) {
 | 
			
		||||
    let medianNr = 0;
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,7 @@ const configFile = require('../mempool-config.json');
 | 
			
		||||
 | 
			
		||||
interface IConfig {
 | 
			
		||||
  MEMPOOL: {
 | 
			
		||||
    NETWORK: 'mainnet' | 'testnet' | 'signet' | 'liquid';
 | 
			
		||||
    NETWORK: 'mainnet' | 'testnet' | 'signet' | 'liquid' | 'liquidtestnet';
 | 
			
		||||
    BACKEND: 'esplora' | 'electrum' | 'none';
 | 
			
		||||
    HTTP_PORT: number;
 | 
			
		||||
    SPAWN_CLUSTER_PROCS: number;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								frontend/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								frontend/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -50,6 +50,8 @@ Thumbs.db
 | 
			
		||||
 | 
			
		||||
src/resources/assets.json
 | 
			
		||||
src/resources/assets.minimal.json
 | 
			
		||||
src/resources/assets-testnet.json
 | 
			
		||||
src/resources/assets-testnet.minimal.json
 | 
			
		||||
src/resources/pools.json
 | 
			
		||||
 | 
			
		||||
# environment config
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
    }
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import { ActivatedRoute, Router } from '@angular/router';
 | 
			
		||||
import { merge, combineLatest, Observable } from 'rxjs';
 | 
			
		||||
import { AssetExtended } from '../interfaces/electrs.interface';
 | 
			
		||||
import { SeoService } from '../services/seo.service';
 | 
			
		||||
import { StateService } from '../services/state.service';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-assets',
 | 
			
		||||
@ -15,7 +16,8 @@ import { SeoService } from '../services/seo.service';
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush
 | 
			
		||||
})
 | 
			
		||||
export class AssetsComponent implements OnInit {
 | 
			
		||||
  nativeAssetId = environment.nativeAssetId;
 | 
			
		||||
  nativeAssetId = this.stateService.network === 'liquidtestnet' ? environment.nativeTestAssetId : environment.nativeAssetId;
 | 
			
		||||
 | 
			
		||||
  assets: AssetExtended[];
 | 
			
		||||
  assetsCache: AssetExtended[];
 | 
			
		||||
  searchForm: FormGroup;
 | 
			
		||||
@ -34,6 +36,7 @@ export class AssetsComponent implements OnInit {
 | 
			
		||||
    private route: ActivatedRoute,
 | 
			
		||||
    private router: Router,
 | 
			
		||||
    private seoService: SeoService,
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
@ -52,12 +55,22 @@ export class AssetsComponent implements OnInit {
 | 
			
		||||
      take(1),
 | 
			
		||||
      mergeMap(([assets, qp]) => {
 | 
			
		||||
        this.assets = Object.values(assets);
 | 
			
		||||
        // @ts-ignore
 | 
			
		||||
        this.assets.push({
 | 
			
		||||
          name: 'Liquid Bitcoin',
 | 
			
		||||
          ticker: 'L-BTC',
 | 
			
		||||
          asset_id: this.nativeAssetId,
 | 
			
		||||
        });
 | 
			
		||||
        if (this.stateService.network === 'liquid') {
 | 
			
		||||
          // @ts-ignore
 | 
			
		||||
          this.assets.push({
 | 
			
		||||
            name: 'Liquid Bitcoin',
 | 
			
		||||
            ticker: 'L-BTC',
 | 
			
		||||
            asset_id: this.nativeAssetId,
 | 
			
		||||
          });
 | 
			
		||||
        } else if (this.stateService.network === 'liquidtestnet') {
 | 
			
		||||
          // @ts-ignore
 | 
			
		||||
          this.assets.push({
 | 
			
		||||
            name: 'Test Liquid Bitcoin',
 | 
			
		||||
            ticker: 'tL-BTC',
 | 
			
		||||
            asset_id: this.nativeAssetId,
 | 
			
		||||
          });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.assets = this.assets.sort((a: any, b: any) => a.name.localeCompare(b.name));
 | 
			
		||||
        this.assetsCache = this.assets;
 | 
			
		||||
        this.searchForm.get('searchText').enable();
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
    ‎{{ 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>
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,7 @@ import { moveDec } from 'src/app/bitcoin.utils';
 | 
			
		||||
})
 | 
			
		||||
export class AssetComponent implements OnInit, OnDestroy {
 | 
			
		||||
  network = '';
 | 
			
		||||
  nativeAssetId = environment.nativeAssetId;
 | 
			
		||||
  nativeAssetId = this.stateService.network === 'liquidtestnet' ? environment.nativeTestAssetId : environment.nativeAssetId;
 | 
			
		||||
 | 
			
		||||
  asset: Asset;
 | 
			
		||||
  blindedIssuance: boolean;
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -102,6 +102,10 @@ nav {
 | 
			
		||||
  background-color: #116761;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.liquidtestnet.active {
 | 
			
		||||
  background-color: #494a4a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.testnet.active {
 | 
			
		||||
  background-color: #1d486f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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>  <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>
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -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)));
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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') {
 | 
			
		||||
 | 
			
		||||
@ -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') {
 | 
			
		||||
 | 
			
		||||
@ -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$
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
@ -102,6 +102,10 @@ nav {
 | 
			
		||||
  background-color: #116761;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.liquidtestnet.active {
 | 
			
		||||
  background-color: #494a4a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.testnet.active {
 | 
			
		||||
  background-color: #1d486f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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 {
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -110,6 +110,10 @@ nav {
 | 
			
		||||
  background-color: #116761;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.liquidtestnet.active {
 | 
			
		||||
  background-color: #494a4a;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.testnet.active {
 | 
			
		||||
  background-color: #1d486f;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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) => {
 | 
			
		||||
 | 
			
		||||
@ -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]}`);
 | 
			
		||||
 | 
			
		||||
@ -7,11 +7,13 @@ import { Observable, of, Subject, merge } from 'rxjs';
 | 
			
		||||
import { debounceTime, distinctUntilChanged, switchMap, filter, catchError, map } from 'rxjs/operators';
 | 
			
		||||
import { ElectrsApiService } from 'src/app/services/electrs-api.service';
 | 
			
		||||
import { NgbTypeahead } from '@ng-bootstrap/ng-bootstrap';
 | 
			
		||||
import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
  selector: 'app-search-form',
 | 
			
		||||
  templateUrl: './search-form.component.html',
 | 
			
		||||
  styleUrls: ['./search-form.component.scss'],
 | 
			
		||||
  providers: [RelativeUrlPipe],
 | 
			
		||||
  changeDetection: ChangeDetectionStrategy.OnPush
 | 
			
		||||
})
 | 
			
		||||
export class SearchFormComponent implements OnInit {
 | 
			
		||||
@ -38,6 +40,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
    private assetsService: AssetsService,
 | 
			
		||||
    private stateService: StateService,
 | 
			
		||||
    private electrsApiService: ElectrsApiService,
 | 
			
		||||
    private relativeUrlPipe: RelativeUrlPipe,
 | 
			
		||||
  ) { }
 | 
			
		||||
 | 
			
		||||
  ngOnInit() {
 | 
			
		||||
@ -48,7 +51,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 +104,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]);
 | 
			
		||||
          }
 | 
			
		||||
@ -125,7 +128,7 @@ export class SearchFormComponent implements OnInit {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  navigate(url: string, searchText: string, extras?: any) {
 | 
			
		||||
    this.router.navigate([(this.network && this.stateService.env.BASE_MODULE === 'mempool' ? '/' + this.network : '') + url, searchText], extras);
 | 
			
		||||
    this.router.navigate([this.relativeUrlPipe.transform(url), searchText], extras);
 | 
			
		||||
    this.searchTriggered.emit();
 | 
			
		||||
    this.searchForm.setValue({
 | 
			
		||||
      searchText: '',
 | 
			
		||||
 | 
			
		||||
@ -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">
 | 
			
		||||
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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) => {
 | 
			
		||||
 | 
			
		||||
@ -48,13 +48,16 @@
 | 
			
		||||
                </td>
 | 
			
		||||
                <td>
 | 
			
		||||
                  <div [ngSwitch]="true">
 | 
			
		||||
                    <ng-container *ngSwitchCase="vin.is_coinbase"><span i18n="transactions-list.coinbase">Coinbase</span><ng-template [ngIf]="network !== 'liquid'"> <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'"> <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>
 | 
			
		||||
                    <ng-container *ngSwitchCase="vin.prevout && vin.prevout.scriptpubkey_type === 'p2pk'">
 | 
			
		||||
                      <span>P2PK</span>
 | 
			
		||||
                    </ng-container>
 | 
			
		||||
                    <ng-container *ngSwitchCase="!vin.prevout">
 | 
			
		||||
                      <span>{{ vin.issuance ? 'Issuance' : 'UNKNOWN' }}</span>
 | 
			
		||||
                    </ng-container>
 | 
			
		||||
                    <ng-container *ngSwitchDefault>
 | 
			
		||||
                      <a [routerLink]="['/address/' | relativeUrl, vin.prevout.scriptpubkey_address]" title="{{ vin.prevout.scriptpubkey_address }}">
 | 
			
		||||
                        <span class="d-block d-lg-none">{{ vin.prevout.scriptpubkey_address | shortenString : 16 }}</span>
 | 
			
		||||
@ -244,7 +247,7 @@
 | 
			
		||||
           
 | 
			
		||||
        </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>
 | 
			
		||||
 | 
			
		||||
@ -15,7 +15,7 @@ import { map } from 'rxjs/operators';
 | 
			
		||||
})
 | 
			
		||||
export class TransactionsListComponent implements OnInit, OnChanges {
 | 
			
		||||
  network = '';
 | 
			
		||||
  nativeAssetId = environment.nativeAssetId;
 | 
			
		||||
  nativeAssetId = this.stateService.network === 'liquidtestnet' ? environment.nativeTestAssetId : environment.nativeAssetId;
 | 
			
		||||
  displayDetails = false;
 | 
			
		||||
 | 
			
		||||
  @Input() transactions: Transaction[];
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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">
 | 
			
		||||
@ -29,7 +29,7 @@
 | 
			
		||||
      </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">
 | 
			
		||||
@ -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>
 | 
			
		||||
 | 
			
		||||
@ -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) => {
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { Injectable } from '@angular/core';
 | 
			
		||||
import { HttpClient } from '@angular/common/http';
 | 
			
		||||
import { Observable } from 'rxjs';
 | 
			
		||||
import { shareReplay } from 'rxjs/operators';
 | 
			
		||||
import { shareReplay, switchMap } from 'rxjs/operators';
 | 
			
		||||
import { StateService } from './state.service';
 | 
			
		||||
 | 
			
		||||
@Injectable({
 | 
			
		||||
@ -21,8 +21,16 @@ export class AssetsService {
 | 
			
		||||
      apiBaseUrl = this.stateService.env.NGINX_PROTOCOL + '://' + this.stateService.env.NGINX_HOSTNAME + ':' + this.stateService.env.NGINX_PORT;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.getAssetsJson$ = this.httpClient.get(apiBaseUrl + '/resources/assets.json').pipe(shareReplay());
 | 
			
		||||
    this.getAssetsMinimalJson$ = this.httpClient.get(apiBaseUrl + '/resources/assets.minimal.json').pipe(shareReplay());
 | 
			
		||||
    this.getMiningPools$ = this.httpClient.get(apiBaseUrl + '/resources/pools.json').pipe(shareReplay());
 | 
			
		||||
    this.getAssetsJson$ = this.stateService.networkChanged$
 | 
			
		||||
      .pipe(
 | 
			
		||||
        switchMap(() => this.httpClient.get(`${apiBaseUrl}/resources/assets${this.stateService.network === 'liquidtestnet' ? '-testnet' : ''}.json`)),
 | 
			
		||||
        shareReplay(1),
 | 
			
		||||
      );
 | 
			
		||||
    this.getAssetsMinimalJson$ = this.stateService.networkChanged$
 | 
			
		||||
    .pipe(
 | 
			
		||||
      switchMap(() => this.httpClient.get(`${apiBaseUrl}/resources/assets${this.stateService.network === 'liquidtestnet' ? '-testnet' : ''}.minimal.json`)),
 | 
			
		||||
      shareReplay(1),
 | 
			
		||||
    );
 | 
			
		||||
    this.getMiningPools$ = this.httpClient.get(apiBaseUrl + '/resources/pools.json').pipe(shareReplay(1));
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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';
 | 
			
		||||
 | 
			
		||||
@ -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,7 +168,12 @@ export class StateService {
 | 
			
		||||
        }
 | 
			
		||||
        return;
 | 
			
		||||
      default:
 | 
			
		||||
        if (this.network !== '') {
 | 
			
		||||
        if (this.env.BASE_MODULE !== 'mempool') {
 | 
			
		||||
          if (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('');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
export const environment = {
 | 
			
		||||
  production: true,
 | 
			
		||||
  nativeAssetId: '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d',
 | 
			
		||||
  nativeTestAssetId: '144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -5,6 +5,7 @@
 | 
			
		||||
export const environment = {
 | 
			
		||||
  production: false,
 | 
			
		||||
  nativeAssetId: '6f0279e9ed041c3d710a9f57d0c02928416460c4b722ae3457a11eec381c526d',
 | 
			
		||||
  nativeTestAssetId: '144c654344aa716d6f3abcc1ca90e5641e4e2a7f633bc09fe3baf64585819a49',
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								frontend/src/resources/liquidtestnet-logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								frontend/src/resources/liquidtestnet-logo.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 14 KiB  | 
@ -42,9 +42,17 @@ if (configContent.BASE_MODULE && configContent.BASE_MODULE === 'liquid') {
 | 
			
		||||
  assetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.minimal.json';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const testnetAssetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.json';
 | 
			
		||||
const testnetAssetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.minimal.json';
 | 
			
		||||
 | 
			
		||||
console.log('Downloading assets');
 | 
			
		||||
download(PATH + 'assets.json', assetsJsonUrl);
 | 
			
		||||
console.log('Downloading assets minimal');
 | 
			
		||||
download(PATH + 'assets.minimal.json', assetsMinimalJsonUrl);
 | 
			
		||||
console.log('Downloading mining pools info');
 | 
			
		||||
download(PATH + 'pools.json', poolsJsonUrl);
 | 
			
		||||
console.log('Downloading testnet assets');
 | 
			
		||||
download(PATH + 'assets-testnet.json', testnetAssetsJsonUrl);
 | 
			
		||||
console.log('Downloading testnet assets minimal');
 | 
			
		||||
download(PATH + 'assets-testnet.minimal.json', testnetAssetsMinimalJsonUrl);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user