Add testnet4 frontend support

This commit is contained in:
Mononaut
2024-05-06 15:40:32 +00:00
parent 8ec5dd70e0
commit 1e5a55917c
24 changed files with 133 additions and 36 deletions

View File

@@ -151,7 +151,7 @@ export function nextRoundNumber(num: number): number {
export function seoDescriptionNetwork(network: string): string {
if( network === 'liquidtestnet' || network === 'testnet' ) {
return ' Testnet';
} else if( network === 'signet' || network === 'testnet' ) {
} else if( network === 'signet' || network === 'testnet' || network === 'testnet4') {
return ' ' + network.charAt(0).toUpperCase() + network.slice(1);
}
return '';

View File

@@ -4,5 +4,6 @@
<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 === 'testnet4'">t-</ng-template>
<ng-template [ngIf]="network === 'signet'">s-</ng-template>{{ unit }}
</span>

View File

@@ -62,10 +62,11 @@
<p><a [routerLink]="['/docs/faq' | relativeUrl]" i18n="faq.more-faq">More FAQs &raquo;</a></p>
</div>
<div class="links" *ngIf="officialMempoolSpace || env.TESTNET_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.LIQUID_TESTNET_ENABLED else toolBox" >
<div class="links" *ngIf="officialMempoolSpace || env.TESTNET_ENABLED || env.TESTNET4_ENABLED || env.SIGNET_ENABLED || env.LIQUID_ENABLED || env.LIQUID_TESTNET_ENABLED else toolBox" >
<p class="category" i18n="footer.networks">Networks</p>
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== '') && (currentNetwork !== 'mainnet')"><a [href]="networkLink('mainnet')" i18n="footer.mainnet-explorer">Mainnet Explorer</a></p>
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'testnet') && env.TESTNET_ENABLED"><a [href]="networkLink('testnet')" i18n="footer.testnet-explorer">Testnet Explorer</a></p>
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'testnet') && env.TESTNET_ENABLED"><a [href]="networkLink('testnet')" i18n="footer.testnet3-explorer">Testnet3 Explorer</a></p>
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'testnet4') && env.TESTNET4_ENABLED"><a [href]="networkLink('testnet4')" i18n="footer.testnet4-explorer">Testnet4 Explorer</a></p>
<p *ngIf="(officialMempoolSpace || (env.BASE_MODULE === 'mempool')) && (currentNetwork !== 'signet') && env.SIGNET_ENABLED"><a [href]="networkLink('signet')" i18n="footer.signet-explorer">Signet Explorer</a></p>
<p *ngIf="(officialMempoolSpace || env.LIQUID_ENABLED) && (currentNetwork !== 'liquidtestnet')"><a [href]="networkLink('liquidtestnet')" i18n="footer.liquid-testnet-explorer">Liquid Testnet Explorer</a></p>
<p *ngIf="(officialMempoolSpace || env.LIQUID_ENABLED) && (currentNetwork !== 'liquid')"><a [href]="networkLink('liquid')" i18n="footer.liquid-explorer">Liquid Explorer</a></p>

View File

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

View File

@@ -4,5 +4,6 @@
<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 === 'testnet4'">t-</ng-template>
<ng-template [ngIf]="network === 'signet'">s-</ng-template>sats
</span>

View File

@@ -62,6 +62,20 @@ const ADDRESS_CHARS: {
+ `{20,100}`
+ `)`,
},
testnet4: {
base58: `[mn2]` // Starts with a single m, n, or 2 (P2PKH is m or n, 2 is P2SH)
+ BASE58_CHARS
+ `{33,34}`, // m|n is 34 length, 2 is 35 length (We match the first letter separately)
bech32: `(?:`
+ `tb1` // Starts with tb1
+ BECH32_CHARS_LW
+ `{20,100}` // As per bech32, 6 char checksum is minimum
+ `|`
+ `TB1` // All upper case version
+ BECH32_CHARS_UP
+ `{20,100}`
+ `)`,
},
signet: {
base58: `[mn2]`
+ BASE58_CHARS
@@ -128,7 +142,7 @@ const ADDRESS_CHARS: {
type RegexTypeNoAddrNoBlockHash = | `transaction` | `blockheight` | `date` | `timestamp`;
export type RegexType = `address` | `blockhash` | RegexTypeNoAddrNoBlockHash;
export const NETWORKS = [`testnet`, `signet`, `liquid`, `liquidtestnet`, `mainnet`] as const;
export const NETWORKS = [`testnet`, `testnet4`, `signet`, `liquid`, `liquidtestnet`, `mainnet`] as const;
export type Network = typeof NETWORKS[number]; // Turn const array into union type
export const ADDRESS_REGEXES: [RegExp, Network][] = NETWORKS
@@ -144,6 +158,8 @@ function isNetworkAvailable(network: Network, env: Env): boolean {
switch (network) {
case 'testnet':
return env.TESTNET_ENABLED === true;
case 'testnet4':
return env.TESTNET4_ENABLED === true;
case 'signet':
return env.SIGNET_ENABLED === true;
case 'liquid':
@@ -160,7 +176,7 @@ function isNetworkAvailable(network: Network, env: Env): boolean {
export function needBaseModuleChange(fromBaseModule: 'mempool' | 'liquid', toNetwork: Network): boolean {
if (!toNetwork) return false; // No target network means no change needed
if (fromBaseModule === 'mempool') {
return toNetwork !== 'mainnet' && toNetwork !== 'testnet' && toNetwork !== 'signet';
return toNetwork !== 'mainnet' && toNetwork !== 'testnet' && toNetwork !== 'testnet4' && toNetwork !== 'signet';
}
if (fromBaseModule === 'liquid') {
return toNetwork !== 'liquid' && toNetwork !== 'liquidtestnet';
@@ -175,7 +191,7 @@ export function getTargetUrl(toNetwork: Network, address: string, env: Env): str
targetUrl += '/address/';
targetUrl += address;
}
if (toNetwork === 'mainnet' || toNetwork === 'testnet' || toNetwork === 'signet') {
if (toNetwork === 'mainnet' || toNetwork === 'testnet' || toNetwork === 'testnet4' || toNetwork === 'signet') {
targetUrl = env.MEMPOOL_WEBSITE_URL;
targetUrl += (toNetwork === 'mainnet' ? '' : `/${toNetwork}`);
targetUrl += '/address/';
@@ -209,6 +225,9 @@ export function getRegex(type: RegexType, network?: Network): RegExp {
case `testnet`:
leadingZeroes = 8; // Assumes at least 32 bits of difficulty
break;
case `testnet4`:
leadingZeroes = 8; // Assumes at least 32 bits of difficulty
break;
case `signet`:
leadingZeroes = 5;
break;
@@ -261,6 +280,15 @@ export function getRegex(type: RegexType, network?: Network): RegExp {
regex += `|`; // OR
regex += `(?:02|03)${HEX_CHARS}{64}`; // Compressed pubkey
break;
case `testnet4`:
regex += ADDRESS_CHARS.testnet.base58;
regex += `|`; // OR
regex += ADDRESS_CHARS.testnet.bech32;
regex += `|`; // OR
regex += `04${HEX_CHARS}{128}`; // Uncompressed pubkey
regex += `|`; // OR
regex += `(?:02|03)${HEX_CHARS}{64}`; // Compressed pubkey
break;
case `signet`:
regex += ADDRESS_CHARS.signet.base58;
regex += `|`; // OR