From 125b9e4525132304ca11c24eca871bd392adbc05 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 24 May 2023 15:49:35 -0400 Subject: [PATCH 01/80] Restore liquid max block weight to defaults --- production/mempool-frontend-config.liquid.json | 1 - 1 file changed, 1 deletion(-) diff --git a/production/mempool-frontend-config.liquid.json b/production/mempool-frontend-config.liquid.json index 6a7c79d52..1a4fc2998 100644 --- a/production/mempool-frontend-config.liquid.json +++ b/production/mempool-frontend-config.liquid.json @@ -11,7 +11,6 @@ "LIQUID_WEBSITE_URL": "https://liquid.network", "BISQ_WEBSITE_URL": "https://bisq.markets", "ITEMS_PER_PAGE": 25, - "BLOCK_WEIGHT_UNITS": 300000, "MEMPOOL_BLOCKS_AMOUNT": 2, "KEEP_BLOCKS_AMOUNT": 16 } From 1339b98281b235b6e4a5a15db041df835b37a686 Mon Sep 17 00:00:00 2001 From: junderw Date: Sat, 27 Aug 2022 16:35:20 +0900 Subject: [PATCH 02/80] Feature: Readable RegExp constructor --- frontend/src/app/shared/common.utils.ts | 69 ++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/shared/common.utils.ts b/frontend/src/app/shared/common.utils.ts index 7d206f4b5..6cbe35386 100644 --- a/frontend/src/app/shared/common.utils.ts +++ b/frontend/src/app/shared/common.utils.ts @@ -119,6 +119,7 @@ export function convertRegion(input, to: 'name' | 'abbreviated'): string { } } + export function haversineDistance(lat1: number, lon1: number, lat2: number, lon2: number): number { const rlat1 = lat1 * Math.PI / 180; const rlon1 = lon1 * Math.PI / 180; @@ -135,4 +136,70 @@ export function haversineDistance(lat1: number, lon1: number, lat2: number, lon2 export function kmToMiles(km: number): number { return km * 0.62137119; -} \ No newline at end of file +} + +// all base58 characters +const BASE58_CHARS = '[a-km-zA-HJ-NP-Z1-9]'; +// all bech32 characters (after the separator) +const BECH32_CHARS = '[ac-hj-np-z02-9]'; +// All characters usable in bech32 human readable portion (before the 1 separator) +// Note: Technically the spec says "all US ASCII characters" but in practice only alphabet is used. +// Note: If HRP contains the separator (1) then the separator is "the last instance of separator" +const BECH32_HRP_CHARS = '[a-zA-Z0-9]'; +// Hex characters +const HEX_CHARS = '[a-fA-F0-9]'; +// A regex to say "A single 0 OR any number with no leading zeroes" +// (?: // Start a non-capturing group +// 0 // A single 0 +// | // OR +// [1-9][0-9]* // Any succession of numbers starting with 1-9 +// ) // End the non-capturing group. +const ZERO_INDEX_NUMBER_CHARS = '(?:0|[1-9][0-9]*)'; +export type RegexType = 'address' | 'blockhash' | 'transaction' | 'blockheight'; +export type Network = 'testnet' | 'signet' | 'liquid' | 'bisq' | 'mainnet'; +export function getRegex(type: RegexType, network: Network): RegExp { + let regex = '^'; // ^ = Start of string + switch (type) { + // Match a block height number + // [Testing Order]: any order is fine + case 'blockheight': + regex += ZERO_INDEX_NUMBER_CHARS; // block height is a 0 indexed number + break; + // Match a 32 byte block hash in hex. Assumes at least 32 bits of difficulty. + // [Testing Order]: Must always be tested before 'transaction' + case 'blockhash': + regex += '0{8}'; // Starts with exactly 8 zeroes in a row + regex += `${HEX_CHARS}{56}`; // Continues with exactly 56 hex letters/numbers + break; + // Match a 32 byte tx hash in hex. Contains optional output index specifier. + // [Testing Order]: Must always be tested after 'blockhash' + case 'transaction': + regex += `${HEX_CHARS}{64}`; // Exactly 64 hex letters/numbers + regex += '(?:'; // Start a non-capturing group + regex += ':'; // 1 instances of the symbol ":" + regex += ZERO_INDEX_NUMBER_CHARS; // A zero indexed number + regex += ')?'; // End the non-capturing group. This group appears 0 or 1 times + break; + case 'address': + // TODO + switch (network) { + case 'mainnet': + break; + case 'testnet': + break; + case 'signet': + break; + case 'liquid': + break; + case 'bisq': + break; + default: + throw new Error('Invalid Network (Unreachable error in TypeScript)'); + } + break; + default: + throw new Error('Invalid RegexType (Unreachable error in TypeScript)'); + } + regex += '$'; // $ = End of string + return new RegExp(regex); +} From c0d3f295eec2f483e8006b6f06de6fd8b3650a5b Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 28 Aug 2022 00:07:13 +0900 Subject: [PATCH 03/80] Finished Regex portion --- .../search-form/search-form.component.ts | 25 ++- frontend/src/app/shared/common.utils.ts | 191 ++++++++++++++---- 2 files changed, 178 insertions(+), 38 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index ab42fe1f7..8031195f0 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -9,6 +9,7 @@ import { ElectrsApiService } from '../../services/electrs-api.service'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { ApiService } from '../../services/api.service'; import { SearchResultsComponent } from './search-results/search-results.component'; +import { ADDRESS_REGEXES, getRegex } from '../../shared/common.utils'; @Component({ selector: 'app-search-form', @@ -38,6 +39,7 @@ export class SearchFormComponent implements OnInit { regexBlockhash = /^[0]{8}[a-fA-F0-9]{56}$/; regexTransaction = /^([a-fA-F0-9]{64})(:\d+)?$/; regexBlockheight = /^[0-9]{1,9}$/; + focus$ = new Subject(); click$ = new Subject(); @@ -58,8 +60,13 @@ export class SearchFormComponent implements OnInit { private elementRef: ElementRef, ) { } - ngOnInit(): void { - this.stateService.networkChanged$.subscribe((network) => this.network = network); + + ngOnInit() { + this.stateService.networkChanged$.subscribe((network) => { + this.network = network; + // TODO: Eventually change network type here from string to enum of consts + this.regexAddress = getRegex('address', network as any); + }); this.searchForm = this.formBuilder.group({ searchText: ['', Validators.required], @@ -203,6 +210,20 @@ export class SearchFormComponent implements OnInit { this.isSearching = true; if (!this.regexTransaction.test(searchText) && this.regexAddress.test(searchText)) { this.navigate('/address/', searchText); + } else if ( + // If the search text matches any other network besides this one + ADDRESS_REGEXES + .filter(([, network]) => network !== this.network) + .some(([regex]) => regex.test(searchText)) + ) { + // Gather all network matches as string[] + const networks = ADDRESS_REGEXES.filter(([regex, network]) => + network !== this.network && + regex.test(searchText) + ).map(([, network]) => network); + // ############################################### + // TODO: Create the search items for the drop down + // ############################################### } else if (this.regexBlockhash.test(searchText) || this.regexBlockheight.test(searchText)) { this.navigate('/block/', searchText); } else if (this.regexTransaction.test(searchText)) { diff --git a/frontend/src/app/shared/common.utils.ts b/frontend/src/app/shared/common.utils.ts index 6cbe35386..bbc9143c0 100644 --- a/frontend/src/app/shared/common.utils.ts +++ b/frontend/src/app/shared/common.utils.ts @@ -139,67 +139,186 @@ export function kmToMiles(km: number): number { } // all base58 characters -const BASE58_CHARS = '[a-km-zA-HJ-NP-Z1-9]'; +const BASE58_CHARS = `[a-km-zA-HJ-NP-Z1-9]`; + // all bech32 characters (after the separator) -const BECH32_CHARS = '[ac-hj-np-z02-9]'; -// All characters usable in bech32 human readable portion (before the 1 separator) -// Note: Technically the spec says "all US ASCII characters" but in practice only alphabet is used. -// Note: If HRP contains the separator (1) then the separator is "the last instance of separator" -const BECH32_HRP_CHARS = '[a-zA-Z0-9]'; +const BECH32_CHARS_LW = `[ac-hj-np-z02-9]`; +const BECH32_CHARS_UP = `[AC-HJ-NP-Z02-9]`; + // Hex characters -const HEX_CHARS = '[a-fA-F0-9]'; +const HEX_CHARS = `[a-fA-F0-9]`; + // A regex to say "A single 0 OR any number with no leading zeroes" -// (?: // Start a non-capturing group -// 0 // A single 0 -// | // OR -// [1-9][0-9]* // Any succession of numbers starting with 1-9 -// ) // End the non-capturing group. -const ZERO_INDEX_NUMBER_CHARS = '(?:0|[1-9][0-9]*)'; -export type RegexType = 'address' | 'blockhash' | 'transaction' | 'blockheight'; -export type Network = 'testnet' | 'signet' | 'liquid' | 'bisq' | 'mainnet'; -export function getRegex(type: RegexType, network: Network): RegExp { - let regex = '^'; // ^ = Start of string +// (?: // Start a non-capturing group +// 0 // A single 0 +// | // OR +// [1-9]\d* // Any succession of numbers starting with 1-9 +// ) // End the non-capturing group. +const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9]\d*)`; + +// Formatting of the address regex is for readability, +// We should ignore formatting it with automated formatting tools like prettier. +// +// prettier-ignore +const ADDRESS_CHARS = { + mainnet: { + base58: `[13]` // Starts with a single 1 or 3 + + BASE58_CHARS + + `{26,33}`, // Repeat the previous char 26-33 times. + // Version byte 0x00 (P2PKH) can be as short as 27 characters, up to 34 length + // P2SH must be 34 length + bech32: `(?:` + + `bc1` // Starts with bc1 + + BECH32_CHARS_LW + + `{6,100}` // As per bech32, 6 char checksum is minimum + + `|` + + `BC1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + testnet: { + 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 bc1 + + BECH32_CHARS_LW + + `{6,100}` // As per bech32, 6 char checksum is minimum + + `|` + + `TB1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + signet: { + base58: `[mn2]` + + BASE58_CHARS + + `{33,34}`, + bech32: `(?:` + + `tb1` // Starts with tb1 + + BECH32_CHARS_LW + + `{6,100}` + + `|` + + `TB1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + liquid: { + base58: `[GHPQ]` // G|H is P2PKH, P|Q is P2SH + + BASE58_CHARS + + `{33}`, // All min-max lengths are 34 + bech32: `(?:` + + `(?:` // bech32 liquid starts with ex or lq + + `ex` + + `|` + + `lq` + + `)` + + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. + + `{6,100}` + + `|` + + `(?:` // Same as above but all upper case + + `EX` + + `|` + + `LQ` + + `)` + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + bisq: { + base58: `B1` // bisq base58 addrs start with B1 + + BASE58_CHARS + + `{33}`, // always length 35 + bech32: `(?:` + + `bbc1` // Starts with bbc1 + + BECH32_CHARS_LW + + `{6,100}` + + `|` + + `BBC1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, +} +type RegexTypeNoAddr = `blockhash` | `transaction` | `blockheight`; +export type RegexType = `address` | RegexTypeNoAddr; + +export const NETWORKS = [`testnet`, `signet`, `liquid`, `bisq`, `mainnet`] as const; +export type Network = typeof NETWORKS[number]; // Turn const array into union type + +export const ADDRESS_REGEXES: [RegExp, string][] = NETWORKS + .map(network => [getRegex('address', network), network]) + +export function getRegex(type: RegexTypeNoAddr): RegExp; +export function getRegex(type: 'address', network: Network): RegExp; +export function getRegex(type: RegexType, network?: Network): RegExp { + let regex = `^`; // ^ = Start of string switch (type) { // Match a block height number // [Testing Order]: any order is fine - case 'blockheight': + case `blockheight`: regex += ZERO_INDEX_NUMBER_CHARS; // block height is a 0 indexed number break; // Match a 32 byte block hash in hex. Assumes at least 32 bits of difficulty. - // [Testing Order]: Must always be tested before 'transaction' - case 'blockhash': - regex += '0{8}'; // Starts with exactly 8 zeroes in a row + // [Testing Order]: Must always be tested before `transaction` + case `blockhash`: + regex += `0{8}`; // Starts with exactly 8 zeroes in a row regex += `${HEX_CHARS}{56}`; // Continues with exactly 56 hex letters/numbers break; // Match a 32 byte tx hash in hex. Contains optional output index specifier. - // [Testing Order]: Must always be tested after 'blockhash' - case 'transaction': + // [Testing Order]: Must always be tested after `blockhash` + case `transaction`: regex += `${HEX_CHARS}{64}`; // Exactly 64 hex letters/numbers - regex += '(?:'; // Start a non-capturing group - regex += ':'; // 1 instances of the symbol ":" + regex += `(?:`; // Start a non-capturing group + regex += `:`; // 1 instances of the symbol ":" regex += ZERO_INDEX_NUMBER_CHARS; // A zero indexed number - regex += ')?'; // End the non-capturing group. This group appears 0 or 1 times + regex += `)?`; // End the non-capturing group. This group appears 0 or 1 times break; - case 'address': - // TODO + // Match any one of the many address types + // [Testing Order]: While possible that a bech32 address happens to be 64 hex + // characters in the future (current lengths are not 64), it is highly unlikely + // Order therefore, does not matter. + case `address`: + if (!network) { + throw new Error(`Must pass network when type is address`); + } + regex += `(?:`; // Start a non-capturing group (each network has multiple options) switch (network) { - case 'mainnet': + case `mainnet`: + regex += ADDRESS_CHARS.mainnet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.mainnet.bech32; break; - case 'testnet': + case `testnet`: + regex += ADDRESS_CHARS.testnet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.testnet.bech32; break; - case 'signet': + case `signet`: + regex += ADDRESS_CHARS.signet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.signet.bech32; break; - case 'liquid': + case `liquid`: + regex += ADDRESS_CHARS.liquid.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.liquid.bech32; break; - case 'bisq': + case `bisq`: + regex += ADDRESS_CHARS.bisq.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.bisq.bech32; break; default: - throw new Error('Invalid Network (Unreachable error in TypeScript)'); + throw new Error(`Invalid Network ${network} (Unreachable error in TypeScript)`); } + regex += `)`; // End the non-capturing group break; default: - throw new Error('Invalid RegexType (Unreachable error in TypeScript)'); + throw new Error(`Invalid RegexType ${type} (Unreachable error in TypeScript)`); } - regex += '$'; // $ = End of string + regex += `$`; // $ = End of string return new RegExp(regex); } From 0a51b752e62d82b6986c8177cc63a48991383fcb Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 28 Aug 2022 16:07:46 +0900 Subject: [PATCH 04/80] Improve types and add liquidtestnet for regex --- frontend/src/app/shared/common.utils.ts | 38 +++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/shared/common.utils.ts b/frontend/src/app/shared/common.utils.ts index bbc9143c0..288fc0362 100644 --- a/frontend/src/app/shared/common.utils.ts +++ b/frontend/src/app/shared/common.utils.ts @@ -160,7 +160,12 @@ const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9]\d*)`; // We should ignore formatting it with automated formatting tools like prettier. // // prettier-ignore -const ADDRESS_CHARS = { +const ADDRESS_CHARS: { + [k in Network]: { + base58: string; + bech32: string; + }; +} = { mainnet: { base58: `[13]` // Starts with a single 1 or 3 + BASE58_CHARS @@ -227,6 +232,28 @@ const ADDRESS_CHARS = { + `{6,100}` + `)`, }, + liquidtestnet: { + base58: `[89]` // ???(TODO: find version) is P2PKH, 8|9 is P2SH + + BASE58_CHARS + + `{33}`, // P2PKH is ???(TODO: find size), P2SH is 34 + bech32: `(?:` + + `(?:` // bech32 liquid testnet starts with tex or tlq + + `tex` // TODO: Why does mempool use this and not ert|el like in the elements source? + + `|` + + `tlq` // TODO: does this exist? + + `)` + + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. + + `{6,100}` + + `|` + + `(?:` // Same as above but all upper case + + `TEX` + + `|` + + `TLQ` + + `)` + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, bisq: { base58: `B1` // bisq base58 addrs start with B1 + BASE58_CHARS @@ -245,10 +272,10 @@ const ADDRESS_CHARS = { type RegexTypeNoAddr = `blockhash` | `transaction` | `blockheight`; export type RegexType = `address` | RegexTypeNoAddr; -export const NETWORKS = [`testnet`, `signet`, `liquid`, `bisq`, `mainnet`] as const; +export const NETWORKS = [`testnet`, `signet`, `liquid`, `liquidtestnet`, `bisq`, `mainnet`] as const; export type Network = typeof NETWORKS[number]; // Turn const array into union type -export const ADDRESS_REGEXES: [RegExp, string][] = NETWORKS +export const ADDRESS_REGEXES: [RegExp, Network][] = NETWORKS .map(network => [getRegex('address', network), network]) export function getRegex(type: RegexTypeNoAddr): RegExp; @@ -306,6 +333,11 @@ export function getRegex(type: RegexType, network?: Network): RegExp { regex += `|`; // OR regex += ADDRESS_CHARS.liquid.bech32; break; + case `liquidtestnet`: + regex += ADDRESS_CHARS.liquidtestnet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.liquidtestnet.bech32; + break; case `bisq`: regex += ADDRESS_CHARS.bisq.base58; regex += `|`; // OR From 3d900a38497d7d6b588abba8d06c2af2c8c5d663 Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 28 Aug 2022 16:28:42 +0900 Subject: [PATCH 05/80] Fix: Prevent regex clash with channel IDs --- frontend/src/app/shared/common.utils.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/shared/common.utils.ts b/frontend/src/app/shared/common.utils.ts index 288fc0362..8b914beda 100644 --- a/frontend/src/app/shared/common.utils.ts +++ b/frontend/src/app/shared/common.utils.ts @@ -149,12 +149,13 @@ const BECH32_CHARS_UP = `[AC-HJ-NP-Z02-9]`; const HEX_CHARS = `[a-fA-F0-9]`; // A regex to say "A single 0 OR any number with no leading zeroes" -// (?: // Start a non-capturing group -// 0 // A single 0 -// | // OR -// [1-9]\d* // Any succession of numbers starting with 1-9 -// ) // End the non-capturing group. -const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9]\d*)`; +// Capped at 13 digits so as to not be confused with lightning channel IDs (which are around 17 digits) +// (?: // Start a non-capturing group +// 0 // A single 0 +// | // OR +// [1-9][0-9]{0,12} // Any succession of numbers up to 13 digits starting with 1-9 +// ) // End the non-capturing group. +const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9][0-9]{0,12})`; // Formatting of the address regex is for readability, // We should ignore formatting it with automated formatting tools like prettier. From d825143b3562c4ab493f56ae67a4eadcfde7a469 Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 4 Sep 2022 21:31:02 +0900 Subject: [PATCH 06/80] Search for full address in separate network if matches --- .../search-form/search-form.component.ts | 26 +- frontend/src/app/shared/common.utils.ts | 1 - .../pipes/relative-url/relative-url.pipe.ts | 4 +- frontend/src/app/shared/regex.utils.ts | 224 ++++++++++++++++++ 4 files changed, 235 insertions(+), 20 deletions(-) create mode 100644 frontend/src/app/shared/regex.utils.ts diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index 8031195f0..a9e31221a 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -9,7 +9,7 @@ import { ElectrsApiService } from '../../services/electrs-api.service'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { ApiService } from '../../services/api.service'; import { SearchResultsComponent } from './search-results/search-results.component'; -import { ADDRESS_REGEXES, getRegex } from '../../shared/common.utils'; +import { findOtherNetworks, getRegex } from '../../shared/regex.utils'; @Component({ selector: 'app-search-form', @@ -208,22 +208,13 @@ export class SearchFormComponent implements OnInit { const searchText = result || this.searchForm.value.searchText.trim(); if (searchText) { this.isSearching = true; + + const otherNetworks = findOtherNetworks(searchText, this.network as any); if (!this.regexTransaction.test(searchText) && this.regexAddress.test(searchText)) { this.navigate('/address/', searchText); - } else if ( - // If the search text matches any other network besides this one - ADDRESS_REGEXES - .filter(([, network]) => network !== this.network) - .some(([regex]) => regex.test(searchText)) - ) { - // Gather all network matches as string[] - const networks = ADDRESS_REGEXES.filter(([regex, network]) => - network !== this.network && - regex.test(searchText) - ).map(([, network]) => network); - // ############################################### - // TODO: Create the search items for the drop down - // ############################################### + } else if (otherNetworks.length > 0) { + // Change the network to the first match + this.navigate('/address/', searchText, undefined, otherNetworks[0]); } else if (this.regexBlockhash.test(searchText) || this.regexBlockheight.test(searchText)) { this.navigate('/block/', searchText); } else if (this.regexTransaction.test(searchText)) { @@ -252,8 +243,9 @@ export class SearchFormComponent implements OnInit { } } - navigate(url: string, searchText: string, extras?: any): void { - this.router.navigate([this.relativeUrlPipe.transform(url), searchText], extras); + + navigate(url: string, searchText: string, extras?: any, swapNetwork?: string) { + this.router.navigate([this.relativeUrlPipe.transform(url, swapNetwork), searchText], extras); this.searchTriggered.emit(); this.searchForm.setValue({ searchText: '', diff --git a/frontend/src/app/shared/common.utils.ts b/frontend/src/app/shared/common.utils.ts index 8b914beda..e50ba13b7 100644 --- a/frontend/src/app/shared/common.utils.ts +++ b/frontend/src/app/shared/common.utils.ts @@ -119,7 +119,6 @@ export function convertRegion(input, to: 'name' | 'abbreviated'): string { } } - export function haversineDistance(lat1: number, lon1: number, lat2: number, lon2: number): number { const rlat1 = lat1 * Math.PI / 180; const rlon1 = lon1 * Math.PI / 180; diff --git a/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts b/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts index d7fe612fe..83f5f20df 100644 --- a/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts +++ b/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts @@ -10,8 +10,8 @@ export class RelativeUrlPipe implements PipeTransform { private stateService: StateService, ) { } - transform(value: string): string { - let network = this.stateService.network; + transform(value: string, swapNetwork?: string): string { + let network = swapNetwork || this.stateService.network; if (this.stateService.env.BASE_MODULE === 'liquid' && network === 'liquidtestnet') { network = 'testnet'; } else if (this.stateService.env.BASE_MODULE !== 'mempool') { diff --git a/frontend/src/app/shared/regex.utils.ts b/frontend/src/app/shared/regex.utils.ts new file mode 100644 index 000000000..bac256c8d --- /dev/null +++ b/frontend/src/app/shared/regex.utils.ts @@ -0,0 +1,224 @@ +// all base58 characters +const BASE58_CHARS = `[a-km-zA-HJ-NP-Z1-9]`; + +// all bech32 characters (after the separator) +const BECH32_CHARS_LW = `[ac-hj-np-z02-9]`; +const BECH32_CHARS_UP = `[AC-HJ-NP-Z02-9]`; + +// Hex characters +const HEX_CHARS = `[a-fA-F0-9]`; + +// A regex to say "A single 0 OR any number with no leading zeroes" +// Capped at 13 digits so as to not be confused with lightning channel IDs (which are around 17 digits) +// (?: // Start a non-capturing group +// 0 // A single 0 +// | // OR +// [1-9][0-9]{0,12} // Any succession of numbers up to 13 digits starting with 1-9 +// ) // End the non-capturing group. +const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9][0-9]{0,12})`; + +// Formatting of the address regex is for readability, +// We should ignore formatting it with automated formatting tools like prettier. +// +// prettier-ignore +const ADDRESS_CHARS: { + [k in Network]: { + base58: string; + bech32: string; + }; +} = { + mainnet: { + base58: `[13]` // Starts with a single 1 or 3 + + BASE58_CHARS + + `{26,33}`, // Repeat the previous char 26-33 times. + // Version byte 0x00 (P2PKH) can be as short as 27 characters, up to 34 length + // P2SH must be 34 length + bech32: `(?:` + + `bc1` // Starts with bc1 + + BECH32_CHARS_LW + + `{6,100}` // As per bech32, 6 char checksum is minimum + + `|` + + `BC1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + testnet: { + 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 bc1 + + BECH32_CHARS_LW + + `{6,100}` // As per bech32, 6 char checksum is minimum + + `|` + + `TB1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + signet: { + base58: `[mn2]` + + BASE58_CHARS + + `{33,34}`, + bech32: `(?:` + + `tb1` // Starts with tb1 + + BECH32_CHARS_LW + + `{6,100}` + + `|` + + `TB1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + liquid: { + base58: `[GHPQ]` // G|H is P2PKH, P|Q is P2SH + + BASE58_CHARS + + `{33}`, // All min-max lengths are 34 + bech32: `(?:` + + `(?:` // bech32 liquid starts with ex or lq + + `ex` + + `|` + + `lq` + + `)` + + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. + + `{6,100}` + + `|` + + `(?:` // Same as above but all upper case + + `EX` + + `|` + + `LQ` + + `)` + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + liquidtestnet: { + base58: `[89]` // ???(TODO: find version) is P2PKH, 8|9 is P2SH + + BASE58_CHARS + + `{33}`, // P2PKH is ???(TODO: find size), P2SH is 34 + bech32: `(?:` + + `(?:` // bech32 liquid testnet starts with tex or tlq + + `tex` // TODO: Why does mempool use this and not ert|el like in the elements source? + + `|` + + `tlq` // TODO: does this exist? + + `)` + + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. + + `{6,100}` + + `|` + + `(?:` // Same as above but all upper case + + `TEX` + + `|` + + `TLQ` + + `)` + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, + bisq: { + base58: `B1` // bisq base58 addrs start with B1 + + BASE58_CHARS + + `{33}`, // always length 35 + bech32: `(?:` + + `bbc1` // Starts with bbc1 + + BECH32_CHARS_LW + + `{6,100}` + + `|` + + `BBC1` // All upper case version + + BECH32_CHARS_UP + + `{6,100}` + + `)`, + }, +} +type RegexTypeNoAddr = `blockhash` | `transaction` | `blockheight`; +export type RegexType = `address` | RegexTypeNoAddr; + +export const NETWORKS = [`testnet`, `signet`, `liquid`, `liquidtestnet`, `bisq`, `mainnet`] as const; +export type Network = typeof NETWORKS[number]; // Turn const array into union type + +export const ADDRESS_REGEXES: [RegExp, Network][] = NETWORKS + .map(network => [getRegex('address', network), network]) + +export function findOtherNetworks(address: string, skipNetwork: Network): Network[] { + return ADDRESS_REGEXES.filter(([regex, network]) => + network !== skipNetwork && + regex.test(address) + ).map(([, network]) => network); +} + +export function getRegex(type: RegexTypeNoAddr): RegExp; +export function getRegex(type: 'address', network: Network): RegExp; +export function getRegex(type: RegexType, network?: Network): RegExp { + let regex = `^`; // ^ = Start of string + switch (type) { + // Match a block height number + // [Testing Order]: any order is fine + case `blockheight`: + regex += ZERO_INDEX_NUMBER_CHARS; // block height is a 0 indexed number + break; + // Match a 32 byte block hash in hex. Assumes at least 32 bits of difficulty. + // [Testing Order]: Must always be tested before `transaction` + case `blockhash`: + regex += `0{8}`; // Starts with exactly 8 zeroes in a row + regex += `${HEX_CHARS}{56}`; // Continues with exactly 56 hex letters/numbers + break; + // Match a 32 byte tx hash in hex. Contains optional output index specifier. + // [Testing Order]: Must always be tested after `blockhash` + case `transaction`: + regex += `${HEX_CHARS}{64}`; // Exactly 64 hex letters/numbers + regex += `(?:`; // Start a non-capturing group + regex += `:`; // 1 instances of the symbol ":" + regex += ZERO_INDEX_NUMBER_CHARS; // A zero indexed number + regex += `)?`; // End the non-capturing group. This group appears 0 or 1 times + break; + // Match any one of the many address types + // [Testing Order]: While possible that a bech32 address happens to be 64 hex + // characters in the future (current lengths are not 64), it is highly unlikely + // Order therefore, does not matter. + case `address`: + if (!network) { + throw new Error(`Must pass network when type is address`); + } + regex += `(?:`; // Start a non-capturing group (each network has multiple options) + switch (network) { + case `mainnet`: + regex += ADDRESS_CHARS.mainnet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.mainnet.bech32; + break; + case `testnet`: + regex += ADDRESS_CHARS.testnet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.testnet.bech32; + break; + case `signet`: + regex += ADDRESS_CHARS.signet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.signet.bech32; + break; + case `liquid`: + regex += ADDRESS_CHARS.liquid.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.liquid.bech32; + break; + case `liquidtestnet`: + regex += ADDRESS_CHARS.liquidtestnet.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.liquidtestnet.bech32; + break; + case `bisq`: + regex += ADDRESS_CHARS.bisq.base58; + regex += `|`; // OR + regex += ADDRESS_CHARS.bisq.bech32; + break; + default: + throw new Error(`Invalid Network ${network} (Unreachable error in TypeScript)`); + } + regex += `)`; // End the non-capturing group + break; + default: + throw new Error(`Invalid RegexType ${type} (Unreachable error in TypeScript)`); + } + regex += `$`; // $ = End of string + return new RegExp(regex); +} From 2c59992d3fbc28f64312802c622564b97a946cd6 Mon Sep 17 00:00:00 2001 From: junderw Date: Sun, 4 Sep 2022 21:53:52 +0900 Subject: [PATCH 07/80] Fix E2E error --- .../search-form/search-form.component.ts | 2 +- frontend/src/app/shared/common.utils.ts | 218 ------------------ 2 files changed, 1 insertion(+), 219 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index a9e31221a..18b4048ef 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -65,7 +65,7 @@ export class SearchFormComponent implements OnInit { this.stateService.networkChanged$.subscribe((network) => { this.network = network; // TODO: Eventually change network type here from string to enum of consts - this.regexAddress = getRegex('address', network as any); + this.regexAddress = getRegex('address', network as any || 'mainnet'); }); this.searchForm = this.formBuilder.group({ diff --git a/frontend/src/app/shared/common.utils.ts b/frontend/src/app/shared/common.utils.ts index e50ba13b7..87c952c31 100644 --- a/frontend/src/app/shared/common.utils.ts +++ b/frontend/src/app/shared/common.utils.ts @@ -136,221 +136,3 @@ export function haversineDistance(lat1: number, lon1: number, lat2: number, lon2 export function kmToMiles(km: number): number { return km * 0.62137119; } - -// all base58 characters -const BASE58_CHARS = `[a-km-zA-HJ-NP-Z1-9]`; - -// all bech32 characters (after the separator) -const BECH32_CHARS_LW = `[ac-hj-np-z02-9]`; -const BECH32_CHARS_UP = `[AC-HJ-NP-Z02-9]`; - -// Hex characters -const HEX_CHARS = `[a-fA-F0-9]`; - -// A regex to say "A single 0 OR any number with no leading zeroes" -// Capped at 13 digits so as to not be confused with lightning channel IDs (which are around 17 digits) -// (?: // Start a non-capturing group -// 0 // A single 0 -// | // OR -// [1-9][0-9]{0,12} // Any succession of numbers up to 13 digits starting with 1-9 -// ) // End the non-capturing group. -const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9][0-9]{0,12})`; - -// Formatting of the address regex is for readability, -// We should ignore formatting it with automated formatting tools like prettier. -// -// prettier-ignore -const ADDRESS_CHARS: { - [k in Network]: { - base58: string; - bech32: string; - }; -} = { - mainnet: { - base58: `[13]` // Starts with a single 1 or 3 - + BASE58_CHARS - + `{26,33}`, // Repeat the previous char 26-33 times. - // Version byte 0x00 (P2PKH) can be as short as 27 characters, up to 34 length - // P2SH must be 34 length - bech32: `(?:` - + `bc1` // Starts with bc1 - + BECH32_CHARS_LW - + `{6,100}` // As per bech32, 6 char checksum is minimum - + `|` - + `BC1` // All upper case version - + BECH32_CHARS_UP - + `{6,100}` - + `)`, - }, - testnet: { - 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 bc1 - + BECH32_CHARS_LW - + `{6,100}` // As per bech32, 6 char checksum is minimum - + `|` - + `TB1` // All upper case version - + BECH32_CHARS_UP - + `{6,100}` - + `)`, - }, - signet: { - base58: `[mn2]` - + BASE58_CHARS - + `{33,34}`, - bech32: `(?:` - + `tb1` // Starts with tb1 - + BECH32_CHARS_LW - + `{6,100}` - + `|` - + `TB1` // All upper case version - + BECH32_CHARS_UP - + `{6,100}` - + `)`, - }, - liquid: { - base58: `[GHPQ]` // G|H is P2PKH, P|Q is P2SH - + BASE58_CHARS - + `{33}`, // All min-max lengths are 34 - bech32: `(?:` - + `(?:` // bech32 liquid starts with ex or lq - + `ex` - + `|` - + `lq` - + `)` - + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. - + `{6,100}` - + `|` - + `(?:` // Same as above but all upper case - + `EX` - + `|` - + `LQ` - + `)` - + BECH32_CHARS_UP - + `{6,100}` - + `)`, - }, - liquidtestnet: { - base58: `[89]` // ???(TODO: find version) is P2PKH, 8|9 is P2SH - + BASE58_CHARS - + `{33}`, // P2PKH is ???(TODO: find size), P2SH is 34 - bech32: `(?:` - + `(?:` // bech32 liquid testnet starts with tex or tlq - + `tex` // TODO: Why does mempool use this and not ert|el like in the elements source? - + `|` - + `tlq` // TODO: does this exist? - + `)` - + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. - + `{6,100}` - + `|` - + `(?:` // Same as above but all upper case - + `TEX` - + `|` - + `TLQ` - + `)` - + BECH32_CHARS_UP - + `{6,100}` - + `)`, - }, - bisq: { - base58: `B1` // bisq base58 addrs start with B1 - + BASE58_CHARS - + `{33}`, // always length 35 - bech32: `(?:` - + `bbc1` // Starts with bbc1 - + BECH32_CHARS_LW - + `{6,100}` - + `|` - + `BBC1` // All upper case version - + BECH32_CHARS_UP - + `{6,100}` - + `)`, - }, -} -type RegexTypeNoAddr = `blockhash` | `transaction` | `blockheight`; -export type RegexType = `address` | RegexTypeNoAddr; - -export const NETWORKS = [`testnet`, `signet`, `liquid`, `liquidtestnet`, `bisq`, `mainnet`] as const; -export type Network = typeof NETWORKS[number]; // Turn const array into union type - -export const ADDRESS_REGEXES: [RegExp, Network][] = NETWORKS - .map(network => [getRegex('address', network), network]) - -export function getRegex(type: RegexTypeNoAddr): RegExp; -export function getRegex(type: 'address', network: Network): RegExp; -export function getRegex(type: RegexType, network?: Network): RegExp { - let regex = `^`; // ^ = Start of string - switch (type) { - // Match a block height number - // [Testing Order]: any order is fine - case `blockheight`: - regex += ZERO_INDEX_NUMBER_CHARS; // block height is a 0 indexed number - break; - // Match a 32 byte block hash in hex. Assumes at least 32 bits of difficulty. - // [Testing Order]: Must always be tested before `transaction` - case `blockhash`: - regex += `0{8}`; // Starts with exactly 8 zeroes in a row - regex += `${HEX_CHARS}{56}`; // Continues with exactly 56 hex letters/numbers - break; - // Match a 32 byte tx hash in hex. Contains optional output index specifier. - // [Testing Order]: Must always be tested after `blockhash` - case `transaction`: - regex += `${HEX_CHARS}{64}`; // Exactly 64 hex letters/numbers - regex += `(?:`; // Start a non-capturing group - regex += `:`; // 1 instances of the symbol ":" - regex += ZERO_INDEX_NUMBER_CHARS; // A zero indexed number - regex += `)?`; // End the non-capturing group. This group appears 0 or 1 times - break; - // Match any one of the many address types - // [Testing Order]: While possible that a bech32 address happens to be 64 hex - // characters in the future (current lengths are not 64), it is highly unlikely - // Order therefore, does not matter. - case `address`: - if (!network) { - throw new Error(`Must pass network when type is address`); - } - regex += `(?:`; // Start a non-capturing group (each network has multiple options) - switch (network) { - case `mainnet`: - regex += ADDRESS_CHARS.mainnet.base58; - regex += `|`; // OR - regex += ADDRESS_CHARS.mainnet.bech32; - break; - case `testnet`: - regex += ADDRESS_CHARS.testnet.base58; - regex += `|`; // OR - regex += ADDRESS_CHARS.testnet.bech32; - break; - case `signet`: - regex += ADDRESS_CHARS.signet.base58; - regex += `|`; // OR - regex += ADDRESS_CHARS.signet.bech32; - break; - case `liquid`: - regex += ADDRESS_CHARS.liquid.base58; - regex += `|`; // OR - regex += ADDRESS_CHARS.liquid.bech32; - break; - case `liquidtestnet`: - regex += ADDRESS_CHARS.liquidtestnet.base58; - regex += `|`; // OR - regex += ADDRESS_CHARS.liquidtestnet.bech32; - break; - case `bisq`: - regex += ADDRESS_CHARS.bisq.base58; - regex += `|`; // OR - regex += ADDRESS_CHARS.bisq.bech32; - break; - default: - throw new Error(`Invalid Network ${network} (Unreachable error in TypeScript)`); - } - regex += `)`; // End the non-capturing group - break; - default: - throw new Error(`Invalid RegexType ${type} (Unreachable error in TypeScript)`); - } - regex += `$`; // $ = End of string - return new RegExp(regex); -} From 213800f563a2731a991cfbe2ce76b3ec419a92ad Mon Sep 17 00:00:00 2001 From: softsimon Date: Wed, 19 Jul 2023 16:46:02 +0900 Subject: [PATCH 08/80] Merge error fix --- .../app/components/search-form/search-form.component.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index 18b4048ef..eb8adbd83 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -35,10 +35,10 @@ export class SearchFormComponent implements OnInit { } } - regexAddress = /^([a-km-zA-HJ-NP-Z1-9]{26,35}|[a-km-zA-HJ-NP-Z1-9]{80}|[A-z]{2,5}1[a-zA-HJ-NP-Z0-9]{39,59})$/; - regexBlockhash = /^[0]{8}[a-fA-F0-9]{56}$/; - regexTransaction = /^([a-fA-F0-9]{64})(:\d+)?$/; - regexBlockheight = /^[0-9]{1,9}$/; + regexAddress = getRegex('address', 'mainnet'); // Default to mainnet + regexBlockhash = getRegex('blockhash'); + regexTransaction = getRegex('transaction'); + regexBlockheight = getRegex('blockheight'); focus$ = new Subject(); click$ = new Subject(); From f7ec5ca82ee95d0f9e5559a9f578ec463f77d083 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?dni=20=E2=9A=A1?= Date: Thu, 3 Aug 2023 17:47:30 +0200 Subject: [PATCH 09/80] Update liquid-master-page.component.html ngIf for BISQ_ENABLED was missing --- .../liquid-master-page/liquid-master-page.component.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/liquid-master-page/liquid-master-page.component.html b/frontend/src/app/components/liquid-master-page/liquid-master-page.component.html index 476c78622..50296b895 100644 --- a/frontend/src/app/components/liquid-master-page/liquid-master-page.component.html +++ b/frontend/src/app/components/liquid-master-page/liquid-master-page.component.html @@ -53,7 +53,7 @@ Signet Testnet - Bisq + Bisq Liquid Liquid Testnet @@ -98,4 +98,4 @@ - \ No newline at end of file + From b3f90e298127ad0199ca3c0312fb3022ecfd4a28 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Sun, 13 Aug 2023 08:23:57 +0900 Subject: [PATCH 10/80] Add mempool enterprise note to top-level readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index dd2e62478..9bc988970 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,9 @@ It is an open-source project developed and operated for the benefit of the Bitco Mempool can be self-hosted on a wide variety of your own hardware, ranging from a simple one-click installation on a Raspberry Pi full-node distro all the way to a robust production instance on a powerful FreeBSD server. -**Most people should use a one-click install method.** Other install methods are meant for developers and others with experience managing servers. +Most people should use a one-click install method. + +Other install methods are meant for developers and others with experience managing servers. If you want support for your own production instance of Mempool, or if you'd like to have your own instance of Mempool run by the mempool.space team on their own global ISP infrastructure—check out Mempool Enterprise®. ## One-Click Installation From 102579baa972b80e08b637d034dfe54804cb7b9b Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Sun, 13 Aug 2023 13:00:47 +0900 Subject: [PATCH 11/80] Add enterprise note to production readme --- production/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/production/README.md b/production/README.md index 87b8bb0a1..8e325bb1b 100644 --- a/production/README.md +++ b/production/README.md @@ -2,7 +2,9 @@ These instructions are for setting up a serious production Mempool website for Bitcoin (mainnet, testnet, signet), Liquid (mainnet, testnet), and Bisq. -Again, this setup is no joke—home users should use [one of the other installation methods](../#installation-methods). Support is only provided to [enterprise sponsors](https://mempool.space/enterprise). +Again, this setup is no joke—home users should use [one of the other installation methods](../#installation-methods). Support is only provided to project sponsors through [Mempool Enterprise®](https://mempool.space/enterprise). + +You can also have the mempool.space team run a highly-performant and highly-available instance of Mempool for you on their own global ISP infrastructure. See Mempool Enterprise® for more details. ### Server Hardware From 0a918b8fa84270754ee3afa47c5dd9acca4c54e7 Mon Sep 17 00:00:00 2001 From: hunicus <93150691+hunicus@users.noreply.github.com> Date: Sun, 13 Aug 2023 13:04:58 +0900 Subject: [PATCH 12/80] Add enterprise note to backend readme --- backend/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/README.md b/backend/README.md index 6a0cb821c..0582aca8c 100644 --- a/backend/README.md +++ b/backend/README.md @@ -2,7 +2,7 @@ These instructions are mostly intended for developers. -If you choose to use these instructions for a production setup, be aware that you will still probably need to do additional configuration for your specific OS, environment, use-case, etc. We do our best here to provide a good starting point, but only proceed if you know what you're doing. Mempool only provides support for custom setups to [enterprise sponsors](https://mempool.space/enterprise). +If you choose to use these instructions for a production setup, be aware that you will still probably need to do additional configuration for your specific OS, environment, use-case, etc. We do our best here to provide a good starting point, but only proceed if you know what you're doing. Mempool only provides support for custom setups to project sponsors through [Mempool Enterprise®](https://mempool.space/enterprise). See other ways to set up Mempool on [the main README](/../../#installation-methods). From 5ac432556b7a029689e5373e4b71dc2efa767e64 Mon Sep 17 00:00:00 2001 From: nymkappa <1612910616@pm.me> Date: Fri, 8 Dec 2023 17:00:36 +0100 Subject: [PATCH 13/80] [mining] show proper message when we have less than 2 weeks worth of mining pool hashrate data --- frontend/src/app/components/pool/pool.component.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/components/pool/pool.component.ts b/frontend/src/app/components/pool/pool.component.ts index e52abe433..4457814c3 100644 --- a/frontend/src/app/components/pool/pool.component.ts +++ b/frontend/src/app/components/pool/pool.component.ts @@ -115,13 +115,13 @@ export class PoolComponent implements OnInit { prepareChartOptions(data) { let title: object; - if (data.length === 0) { + if (data.length <= 1) { title = { textStyle: { color: 'grey', fontSize: 15 }, - text: $localize`:@@23555386d8af1ff73f297e89dd4af3f4689fb9dd:Indexing blocks`, + text: $localize`Not enough data yet`, left: 'center', top: 'center' }; @@ -172,14 +172,14 @@ export class PoolComponent implements OnInit { `; }.bind(this) }, - xAxis: data.length === 0 ? undefined : { + xAxis: data.length <= 1 ? undefined : { type: 'time', splitNumber: (this.isMobile()) ? 5 : 10, axisLabel: { hideOverlap: true, } }, - yAxis: data.length === 0 ? undefined : [ + yAxis: data.length <= 1 ? undefined : [ { min: (value) => { return value.min * 0.9; @@ -198,7 +198,7 @@ export class PoolComponent implements OnInit { } }, ], - series: data.length === 0 ? undefined : [ + series: data.length <= 1 ? undefined : [ { zlevel: 0, name: 'Hashrate', @@ -211,7 +211,7 @@ export class PoolComponent implements OnInit { }, }, ], - dataZoom: data.length === 0 ? undefined : [{ + dataZoom: data.length <= 1 ? undefined : [{ type: 'inside', realtime: true, zoomLock: true, From a4810b8be0438f512336a9ab93450f755d33fc09 Mon Sep 17 00:00:00 2001 From: Armin Sabouri Date: Fri, 17 Nov 2023 15:23:52 -0500 Subject: [PATCH 14/80] fix: incorrect `HTTP_PORT` docker compose field in docker README.md The override is [BACKEND_HTTP_PORT defined here](https://github.com/mempool/mempool/blob/59c513f2a52a96d125944b42230e1fb7b13b130e/docker/backend/start.sh#L7) --- docker/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/README.md b/docker/README.md index 8dc1f264a..444324af8 100644 --- a/docker/README.md +++ b/docker/README.md @@ -124,7 +124,7 @@ Corresponding `docker-compose.yml` overrides: environment: MEMPOOL_NETWORK: "" MEMPOOL_BACKEND: "" - MEMPOOL_HTTP_PORT: "" + BACKEND_HTTP_PORT: "" MEMPOOL_SPAWN_CLUSTER_PROCS: "" MEMPOOL_API_URL_PREFIX: "" MEMPOOL_POLL_RATE_MS: "" From 88d2a3a50d35418bf05ab555c92f361bdbe271f0 Mon Sep 17 00:00:00 2001 From: Armin Sabouri Date: Fri, 17 Nov 2023 15:31:39 -0500 Subject: [PATCH 15/80] sign CLA for 0xBEEFCAF3 --- contributors/0xBEEFCAF3.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 contributors/0xBEEFCAF3.txt diff --git a/contributors/0xBEEFCAF3.txt b/contributors/0xBEEFCAF3.txt new file mode 100644 index 000000000..e00999be1 --- /dev/null +++ b/contributors/0xBEEFCAF3.txt @@ -0,0 +1,3 @@ +I hereby accept the terms of the Contributor License Agreement in the CONTRIBUTING.md file of the mempool/mempool git repository as of November 17, 2023. + +Signed: 0xBEEFCAF3 From b0c02b16ff22058779a525ba9a02c0c34093a6ca Mon Sep 17 00:00:00 2001 From: natsee Date: Wed, 13 Dec 2023 19:22:46 +0100 Subject: [PATCH 16/80] Search result: do not offer Go to block --- .../app/components/search-form/search-form.component.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index a99dc084e..446d8be5a 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -174,7 +174,7 @@ export class SearchFormComponent implements OnInit { const addressPrefixSearchResults = result[0]; const lightningResults = result[1]; - const matchesBlockHeight = this.regexBlockheight.test(searchText); + const matchesBlockHeight = this.regexBlockheight.test(searchText) && parseInt(searchText) <= this.stateService.latestBlockHeight; const matchesDateTime = this.regexDate.test(searchText) && new Date(searchText).toString() !== 'Invalid Date'; const matchesUnixTimestamp = this.regexUnixTimestamp.test(searchText); const matchesTxId = this.regexTransaction.test(searchText) && !this.regexBlockhash.test(searchText); @@ -217,7 +217,7 @@ export class SearchFormComponent implements OnInit { selectedResult(result: any): void { if (typeof result === 'string') { this.search(result); - } else if (typeof result === 'number') { + } else if (typeof result === 'number' && result <= this.stateService.latestBlockHeight) { this.navigate('/block/', result.toString()); } else if (result.alias) { this.navigate('/lightning/node/', result.public_key); @@ -232,8 +232,10 @@ export class SearchFormComponent implements OnInit { this.isSearching = true; if (!this.regexTransaction.test(searchText) && this.regexAddress.test(searchText)) { this.navigate('/address/', searchText); - } else if (this.regexBlockhash.test(searchText) || this.regexBlockheight.test(searchText)) { + } else if (this.regexBlockhash.test(searchText)) { this.navigate('/block/', searchText); + } else if (this.regexBlockheight.test(searchText)) { + parseInt(searchText) <= this.stateService.latestBlockHeight ? this.navigate('/block/', searchText) : this.isSearching = false; } else if (this.regexTransaction.test(searchText)) { const matches = this.regexTransaction.exec(searchText); if (this.network === 'liquid' || this.network === 'liquidtestnet') { From eae044cf665ef3f5f3288298dbeae146b2a6506c Mon Sep 17 00:00:00 2001 From: natsee Date: Fri, 15 Dec 2023 15:38:02 +0100 Subject: [PATCH 17/80] Show blockhash copy button in block component --- frontend/src/app/components/block/block.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html index 8bcf23ace..e908d5b24 100644 --- a/frontend/src/app/components/block/block.component.html +++ b/frontend/src/app/components/block/block.component.html @@ -42,7 +42,7 @@ Hash - ‎{{ block.id | shortenString : 13 }} + ‎{{ block.id | shortenString : 13 }} Timestamp From b3a68a0db2adde67a73e1fb79f407bffcf60bab4 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 15 Dec 2023 15:04:26 +0000 Subject: [PATCH 18/80] Smoother goggles color change transition --- .../block-overview-graph/block-overview-graph.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts index 716ba540e..8a449a121 100644 --- a/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts +++ b/frontend/src/app/components/block-overview-graph/block-overview-graph.component.ts @@ -121,6 +121,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On } else { this.scene.setColorFunction(this.overrideColors); } + this.start(); } ngOnDestroy(): void { From 60144695136e09620e31163d70cc7e5d2fd5641a Mon Sep 17 00:00:00 2001 From: softsimon Date: Fri, 15 Dec 2023 23:09:24 +0700 Subject: [PATCH 19/80] Acceleration sounds --- .../accelerate-preview.component.ts | 3 +++ .../transaction/transaction.component.ts | 6 +++++- frontend/src/app/services/audio.service.ts | 2 +- .../resources/sounds/ascend-chime-cartoon.mp3 | Bin 0 -> 17105 bytes .../sounds/wind-chimes-harp-ascend.mp3 | Bin 0 -> 63185 bytes 5 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 frontend/src/resources/sounds/ascend-chime-cartoon.mp3 create mode 100644 frontend/src/resources/sounds/wind-chimes-harp-ascend.mp3 diff --git a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts index f2224841a..d8ebb3830 100644 --- a/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts +++ b/frontend/src/app/components/accelerate-preview/accelerate-preview.component.ts @@ -4,6 +4,7 @@ import { Subscription, catchError, of, tap } from 'rxjs'; import { StorageService } from '../../services/storage.service'; import { Transaction } from '../../interfaces/electrs.interface'; import { nextRoundNumber } from '../../shared/common.utils'; +import { AudioService } from '../../services/audio.service'; export type AccelerationEstimate = { txSummary: TxSummary; @@ -63,6 +64,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges constructor( private apiService: ApiService, private storageService: StorageService, + private audioService: AudioService, private cd: ChangeDetectorRef ) { } @@ -186,6 +188,7 @@ export class AcceleratePreviewComponent implements OnInit, OnDestroy, OnChanges this.userBid ).subscribe({ next: () => { + this.audioService.playSound('ascend-chime-cartoon'); this.showSuccess = true; this.scrollToPreviewWithTimeout('successAlert', 'center'); this.estimateSubscription.unsubscribe(); diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index ae3a950bd..f110c0435 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -439,7 +439,11 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { block_time: block.timestamp, }; this.stateService.markBlock$.next({ blockHeight: block.height }); - this.audioService.playSound('magic'); + if (this.accelerationInfo && ['accelerating', 'mined', 'completed'].includes(this.accelerationInfo.status)) { + this.audioService.playSound('wind-chimes-harp-ascend'); + } else { + this.audioService.playSound('magic'); + } this.fetchAcceleration$.next(block.id); } }); diff --git a/frontend/src/app/services/audio.service.ts b/frontend/src/app/services/audio.service.ts index a0b27d168..5b5ffbf07 100644 --- a/frontend/src/app/services/audio.service.ts +++ b/frontend/src/app/services/audio.service.ts @@ -13,7 +13,7 @@ export class AudioService { } catch (e) {} } - public playSound(name: 'magic' | 'chime' | 'cha-ching' | 'bright-harmony') { + public playSound(name: 'magic' | 'chime' | 'cha-ching' | 'bright-harmony' | 'wind-chimes-harp-ascend' | 'ascend-chime-cartoon') { if (this.isPlaying || !this.audio) { return; } diff --git a/frontend/src/resources/sounds/ascend-chime-cartoon.mp3 b/frontend/src/resources/sounds/ascend-chime-cartoon.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..614274324de204817ae044281e13bce0d748356c GIT binary patch literal 17105 zcmdtJWmHtr_xOEhs2RGY8M?c>yGu$+LPA19LWH4*9=au^V<x)?TaS3un68is0jHxvMXrQ+iI z&=qDD8W8B}9RSnuaR$t-tgP-D`R^K?eZ9S1eF6ak3w?7P0}XW@6_|>dnueh|Oilal z8K$OUYHnm?2on|o%+*c*bxC;lmZ-3ZxPY*jfUv}W`y#)q4fODKb?|p}bM<%iadriS z0dq4mjk`BU?%MR7p1Mg$3yR7JiU_ zn4J9HJq89A77h+xULkRDX=w!oRaGr5Jw0P%3kw^2duL~NcW>_}Po6$~_AD|oHZd_R zEi*GOuei9p{N>B~`j(E4?(W{+!NJkdiHX_S#l_`s-!?XOcMlJbk1sC%{>A(o%-xus z@5U@4{_o+xg&kY=e{NNoFV|Jx{I~l5^Xr}9TmT4JFs^dJZ*3$`)FY&@n=yV$9$T{$ zM}J#d-PtL08=wzFe&AduWp`fS#-4mZ9#8QYZo>(RwSuz<)8g5Q>^-{fkcg~V#h?=+ zF_>9H*0_hDz^}FbT8xwQ*<>!+wBiDZ*w9!l3UM#VeLKv5%0B0fH95cy!UYr><@>i| zC`j}_I*3ACG;x*u7RrW8%LXVwi%%H;V5JkhW)5B|BzQ+M-2UuCe-O^27#C=ZQ}9j& zFwhFn1lLBYV;7J(Tt;GQ1=lc_aNzN+b!{hN)~~wvnqQyH{j}`BP^6AE;@XrX@^n5G zqL7lnxkloEX0XFVrL9Y0O#-1@ATTvn6PRS!pE2!EqE+14zKsv7gkQ`W(qa z@|p>Y$i{;M_C6-f&Yk-GZAT_G=C8jCV^mhHxbE9-wGaiix;*cFK|Sp`Edi0nqc=%h z7L6!aRE9`DVrcoIzI@_aHQHmPj$gNXwJ&`Qt*kR7j+yx*f0U@i(C9^s*AE#iTJ(!F zF5WW2Tp8Q=?19Xal>u5q6d5}b`L1rd48|4xfE~v@o{r?fpZy06?_!T`xW6d<@-K06 z>}Hap#a>g%P`a6G%V!Fa!~B4A@d*`thnGN!!GidL2iPEL`PYSiBdb%?$<2~gwoap? zx-SXQ&##G<#YgkgYz;HOjnA^QUY~@Vd7ojqPh|$1ZjazUYek+g5j`^zE{)hWsM(5- z=V~#`6wW}9KH3M>%TTjY*~xmiPv)HjstoGBUTLbj43woM<593p=SWk#Dt1Bn+x%iD z6-vomg+qBpAW+i0kgkR;?dCY%5C4!O0LW3|X7e6ijgnQ%Q%*>sgUn2F}fL>$t;1b+#v zmWeM!Y(`?n`Sh-tCy|&vE6~@n{GX0AJR+A6<*0b~ueK7ZEh9i-Av;$UOM*XI@4H`5 z62%Y;%_&6;vD90|HiVsCc!BYuQYZUpKfx0iXXO;tPXR8^`!Jt?E#_x@kmmX^$UVFm zPAber4*&||wL)TD4t)P^&N1_l9A6XJJ1-DoaNWk$oaCZu^QhQdmK{6QM;nh6!(MuD zH-kiW7Ziw2*kq*&|AjJs^!gog>d+`rMe&6LBV)9Bbz!~hJ~IM7XL%^Ue}u{A&B!jX zm&uMVB#lxw>J<_mJ~rQp&ijk%c|&oG%#JL!iRtZxvVijs$6{qL*<>C!+qYJK%6=kV zzyL4OtV{sv$5>*|P1D8(ajY|;O2n-`nUOmf!|uy?lfJXNLBYHZ(Ix7s<20!BC!dOB zrAS)2tjVAJYVd*0(4K&`DaeygP+PYS+k;=w_TD3*tC%WxUYC|2LB;P2!O}MO%Fn>T*O}D_c$fcCu7eUHT4`GEfLiPWl4|| zKYLsQg}*CwuE7={9kYpyx>609Zjh@53`!fLpV(m}j&DjY5Ngk}X4V3c2YW?zT!prW zZtaD(>9+^gxI+&o0EmQfa0md?C!Sj3nNufu_gKCpIi*wIl8;Cy;4xuvi7;gL?|7V! zkZ>gLZFkl1tv-eq05vA@bdmytBs0RwJwKEs;Li!lacl5prF8<77~HYq)bqde@0>h+ zJ!Z)EY4B3uO;1YU2}j)g6CPqhY{5wtzJO^KuS>Nz{Oy=gy-2m_V3#vZvAIJX^8FFSK$U z@N_oYs$V&4`VU6UT$x^oSvW`sWC((*Gs|MFbq?4p74Hqg0ExPSiq zUVRvAi}z{+07smC!0$AY~a;TkLWgOBgVc5V1Qn2CFn>yL3EHNB)fwv<_) z<4+J_+=8X4QA_FfjXxN2Fvxd!;+0iDEiqoRxN?r z05qTH3rh?b^tRKZQhA~Okb}a(KgFlz-sJo7tJCSaa;Oq;f6@}@IXZez#4D1^@WLuE zIM;DCikDb#%O!U(w}|m=y%P}sNs3dI8TsT5&m#-+Ie7TG3@l!6n?ubj0L;0qnfrFB zi;jXKC@kxiBTq+s?ObTOKt_E)7|c$2=TU*fgByw4%V(8LXz4b>Qb9-FHV>T)a>gT> z%F0>%5dms52bf)Xz@EagUzl9f>Xe%l22M~Vy64&1@)9*^FGCphqH(Ni*9D3rbVEw< z^FnOn;7a^yenRxinMhfttpcf?bP6>%|IKuCxxjctLSNemD@$tRyXx2!^OVBALTtd9 zU4aysj4yKTZ|>mEpkhjC^o)0-kbTl!qW9#v{8M@2kt-j0(sbJOEO=M!8u|@(bVI!S zS0unjFYSl?(P{jwp5p@mXp-vd0sz6bY;$&;@-_~r*o$%!At-7@=d>~&1740pq@-RKa1$rn zmObFdp|7J$yFq>91=zj$KM{0PBErmN4G zeu4gGmts_JDE~Vw_YPbY7PAuzJPbQ-Y|{w;!fMQ?`&?7ku;oS&x43Ka))PWbkj7 zJ_*l5FoXA#M7l}@Q|mcywuWA)n0Gy+horv=qV2nU9G&Z9C>|;8bKbp-kcNfQfh^^S z0T2NAD+83fm-mM%l!q;}pJcpFKY*8zA?K{H8L|l&`{!Wh>_QuHul}e+P6y1kN2(xQ zq;9v+Ln?4+8jf#2_7l0_MD?g>)fehxOKdnlCtI_0fQ#o``?y_xiz*7CjXj4%`@u;W*@Zc9Mwa#h`HZ6XOa)k? zui9A%94!bg5P|uKAY$KcBv?pue}E-Y<=)Co1>o03wuhYS>;%B1xIYPL;wcyXP?NBJ z>Haft5@_}xas&|YvEY>6vWFkU}3*jAdzVmqTcgB>2WJk1Y_?Np) z5ITn#Vxr%nyA+bn{OdZnKkUbM%Yv+Ss{%fJ*pAVrj!x+qZl4up>ze#SjJtF*7C@fT zw|Cnxb4B$Qa|Qsou~bNa&V~50aRnq~*2tQI6~$i^gx*!B7{LiGSJCYZbFgT3;N9I5jHm;c@@>Sx_~~xC&kU+L;=`X-vmiG ziKB~Il#TymB^60PLHrQEb z5{;dBDiOtnOM_t(v^t&20Bm@6A>3}^BD9dteQA5ezf?Sy_2PHSH*>FB0(b>O;p$#+ z3;^2zXsCrFpU_rC8J}K5q3x2FTA(8`sQ>0q9eh-Ry+Mj`4{Q=ZymY(I>8v}5&@qEn!=#M@o1d0WL^LmRf|?wHchlSRN}Fk zE>wRNEOL^Ud+9}vIM%^JmKLQZA55#Dzi%h0g9K)UwcM}Wg`zZ6b&lug#5^%XqIV7jv@woKo{T+xITQeUaEsP6tPw`_*OyF&GHeQ|IS7 z%Jo$11a3AJnj7ys(=jVPl z7q3R3Fkqubllr23!63c-eakDCZ+*xOU8RFSi~3#e>om69er)V|lGz`G2}}%O0;>Dk zjjfu=3GQB#m}nE6u^T0f*~32_GL@ef&)3H z8u5R8IViYAbiqr2@~fztC#^3R5j1wrq)Ea=cqz;CJf0y!-iXhu8b`D%t6Y(3OhLn` z?yvNSurxauU24Wk%8Ki&W2dQJn+AhDd)T(6F^@ZcW{f|#o#`-ZU(mp9Vt8lgbOF*9 zx{g|=a(0#-KwIa0e7aoZ3)W&7)`Xbd#(<1Zw6!UCX1$yO{evgMuVp+2A<)hJ;DvA- zojRA|=U$2iLjj@*&ev+M@zuxo*!1WXT)%kmn(Zr=?GwRmNCXy^lSUBWa-F|~4!rU` z^`gc{#bJCHncA z%K5%%X)@5$+YaArs>rpiJOKFa`5hb`5TiE4Ey(VrPAXG9ia;g?YCpB5s~AO*ul1$< zLyim{ohfcIk?$TZpf1biq3RF0nX_o@**fYc+S|)3_H+Z$spmT zUUb^RqSA%RYm=E$V;eV_lL{V@$Sv+?q`v#`P^szbOpnpurUA+8G5t>l0Bp{D8Updw zoS#k`+#|Jh6cxX!UYM|CQ6}`2mYg!;S~A|4i$A^39-I?-d#AD3wV7EdfGVX|*v16p z^UM+hWoOEE4}a)Bb!vm@V#+QA@lBn7$D*fU22d%3oAaN0D2ExO(Vja;gPF6|ga081 zLx8iy&AdXS(frOu0wNj~iO3qglpmExQ)CSi@!USoBV+}jBe`c&Vvp*|#kduV%2*3t zSPQ@bV&z2d&3m7Q{d1m0yT#OF)i5{I7y}`LX=r1Ag?FYn>6T-BSanDkD$lzULo}K&hn>NWuyD(qD=Xr!mnRgF6b5Wls)`b3HnNaWmF>U zIYu&f8xsZWn4BA+29*KQRj}p;!2M&8=Nykdq%-uKbEJFgkNACWA{@MM%)3soG8Y|h zM5qce=2fiF(c1NkBmkVPK(7pe%s66|kT;JY$O*Vq3yh4jU$!#V`+J3-FpSBJCQfw) zA$Y`@M+sg?=+|B+ct}$py_4E~li;`iZB>^~=E9c>z^X!iD+9{2a8Ol5=i`t&a4gn%K~ ziOc{OYp2FTd}EXPFX%u$m9~552K2MCIOteU61J!3WNf8>hm~QF3-zp50AtLM=_}#h zPbVddK@0pJ5>J6MBgU~0Wf;@-mxY(v)*ko-K7A&0A0u~V1;o%XL$5H2{Z2Sn+VW*$ z`v4p}32_G$3+czlh8Md-D;Lxwb@jZS?}ymQ{QaMP1+BbR8bHxSvq`vl>;5=rRqs4s zu2#PKXV}i&jfhZ~VF7Q&QyX+$2lZa%Mr3ufG569WtSx#;$LcNvid=>(bH$n#>!;-cw2*qzdOHsu5ORgSQpvE79L z{=E7}=Nf}tQW_>k#tbmF!RBfjjBGXLkQ)6v&J)178Ln~!9Ba(qua7ZR(bh+jF+sFl zcMq6V-!w}95lHy>KIkkH_bIE$v%oT|Z*`Od`?l2QdJxL!$a3R+ zZD(4vFr7=yDRcyLK1eV(&86#pdrBHb(StT-b5dO?Hi1Li9$*QdAZA`-DaI*uUqs24-c zGNkdh3Y$8s1lg^>8al+VhLfos~Er@oHczePmZ% zk36S-6}{H9);Ok%z_*R8LJR|jO?!xm(5iKISe+20iIrcDS0E7=1y)2g%F)&U$i6LF zJIvO|+SPFSg&6=qU$Ac=fu5PW)cKD@0%?0u$0ZgD7D6^oS)G}5X%|-KE9vl}nC_z% z3>T`WAdofh+87k2^5~}a%cR(L#&hVcqKEU!HBV&EgJJULj^rS|VJc&Q9+Y7-l{WE7 zea$we?HP0e7RoY$RY*djD-}aMc{17VEy|%s3XXqiCK6F z$)JUu_orNWB~mEoG@3msFUv{xTeGv9wVOGU^g8;J8GuP`fU+(E8r4mGjEid|7Ke(}$_Wdx(SjGVTKqGnqlrV0%>Z<}e|7x}3(GU@pkS>Jmh%d-s#cWw@p|t3|Zp5Ui`oAWyHP%jr~? zDcZgy`W`J44Ae}k(ALTuNAGTjB}G4^I-Pi8QutI93l70S}S2HGHVt z(%tK@-1?U_Y+SzF;fX~z8&G<5bS>Y0@U=3xsHN)!wNBa?t#C>1Kjid4WMswiuDSV2?~I+nN(G8Pq@1??(664ursH-t|~ zH_PO7oWKhEVnH!u1#uXyGdvNiN~49qsL2$EIo~?g4YMFJq8+@3Pqh<7g+Q5YWL=;> zGXXEkU7GWpNZHVg^5S}o%cS3&n0AdkKnm^nor`NRrs`t;&XWO4>u}@(v_HN=thfb* z>v>tkj9NQn8Wk5tlr&^arBnIr;chp4;jV+JFx{_@ay7$XHJt} zJy|nD#}1O!8241N9yPHFXSz!KTv`FBw9F@*Tl2zUDFeX)6Qs8yTW8kNTKrVL;r;oj zY#u26p2`t*L|+35^9~1w`j;_wEM@A4$8gA(FE9dIO8Dn}gSLOj8Ntb`#1{VwnS@KR z^D#Pc2_+TJTQmtY98Hq(-nnw`4w9Z;_LP$?zjjPX)0vtO2)eN|LeoJ;b=7HLS(vRZ z9&+I7N{Wl=%G!^711KzQa?aV8evFB1yZ%sL%yprDY<#zEotxq< zf=aa{Da_j8{J_eCR&JNIRDS8YQym%drLQ>3>FtqECjjb|Y(^}y|lgyvdO zAl89(Dw;Z2vi3U%DsxeXv!Uch7R+w@Qkb92m9yh;t1KMA=gA)f9Y_nN0-rctLt6e~$9`XhpM=udwq;%?FrG8z zmrl))MWW?NFlvbm@ppm)s!ZCggHWKvU$k;Aq{t}8p?NX>x0K1InGUye z`|YhsEl!juu7*0gVo;e|`_Xlc%Ae~9zb^^N&VpBdRz}N95a6XOgCzNiZWzYs#$F-s_#nHis zT`K#@iARI-quZ6|`S<(!a!7Xe?eOu{(Anh}x*>{q6E+K_6Anz?4btZxfDIUm7p8zX zq*+Ma+2Ytdvl^XEa!pQ^lm}M)z>}&m?St48y`{$7u!NCyvB`<>TMy>d;RPP-l z#O}O7Q_s#EQ9<2#S24y}jkMjKyU~5T!6B>MnsyWun;A5}d6tIs{#0W(nu7Vsg%xd} zU^`B!I1PzH4m^1`q~HkAqC&%LzlIelh_=4ulL9~mqx6ip<|5wG`!&a_)M zXdN}3$ph-VeV3PpYM8QJQWkVx*$L*BVExWX1x!B#HAPX-m$}pMC4{{V-)-9oLRk9{ zKNpiNz9_XV{?P1o@{Qg{?}VoJ8Glu+0V|u$g5-rE?;?A2BH2&e5Mo@DL>!EWJT_%~ zN9ji%%5Rli*L@5&$Vqg4KMY{-x8(=idE=gN(h09xtWTVCHyKZ_NSj`Nmb6zoNCi?Jb%fzz7eHi_z!Xj@_q5Un1D%MFgBUUar|D= z=Dg9JM{-o1>FJt~{Zwofdb#328b~6P8Ct8f{rB=Kd_^fq_xd?ob&pp!W%1k>!`I@` zIM{#nQxCo+F2tmSP;;#MMD^MDVobSqDONB`0G3?|ke^H0vp@NWGK-BavVK`^A(D;E zTi)wd8QfQlPa;!xGUYkL&Ts zgLZwpAsxo>$w{P6;lxpaLi*DHVo$hJM9Vc3l`^Lh`bqJE@0r5M7Ur0Eq-8jZIxucaIT<^e6tBBv61dwgLwnz#bne zR?i?xo)`E$Yh(YUEm4%Lrn-RZXEAJ_i%F3vY&QT7ooE@qe|U7BtHP8MPC7>?WK zJe{d#VeY20=NTWrx7qx_rN`{`GgsnFWj4~GJU(6gxZUu*LP0w2Mo#ScB!i_zQnnw| z&%DtANwKMWpOhm467H5+^~B3YyUZ`Nf=m13KjeG?@(9i)FC)(z@s0f^*HooM^HS@^ zR;{BULY|XML#e`cs&K!RU7(deoA`IxqV^h4*<};Wd_$DrjR+Q+wvlw7}o|l9m zq5=*#Nw5gG>Ihq0P6!#h#~ZVC30yoRT-3697j3j)==z1BnCMuJ{HP!?p9e3M&u1}{ zJu&9b;=XfPD@!@L?5o5A0CETiw32Jxw#dk{g&Q&`u=&X7Nokg;ir}SkC64gT6F8HU z*e-0907-#4VOtx6gCKQYZ4lsjbP4UOm^-NQE%_s?{M)o_MWf9Xb*q~nFOniNJ}7Qp zCAYayxbN92iN?l&T8%b^}g0*RF6mW{ny zN5d%%o$>M!UDsK6DLoqVnF4Y+< z%TIC3F*mz;Ykzgw%69K((h$jwUfrrjnS0Xp5ouo-*tHZgChV8a(<^` znRC&6$r*;FmFfNazMmbUI|3!Mj`^ybdvK!6y&%MPnW72JIN*Ro5b*&q@zv)&LL0tC zkV~M88xKd8WTu>syBp&d_%+R>&c!(%68@Ci9cc5@1 z4Zu~1^?xEksxTXgbbd=Ph;CD4q5mIpiI8Xn&%%L_?2X`t?34nxLSo>eWh1KLXdtbo`g*t)x|p;2^nKZvUXt8k zH`3A7`=ZOCqz+;igYEzUgB=uehn#vY09xa{e?VybRSrkC$w~MTf-=FPiGA-0kW=pw zmlJWzh{1Repofl90PykGUBHaBu7f)j$9!6A_J{ir!$C2g`<{;yDI_0N}sU;R76N=?TXdt69Am1l%f<3=b#Y z_mZ=k{Zwx}!7&h%Hl5J43Ly*+68?zoREf{rf;J<#?K?v4+$;mw#9Hji&;dvcRjf}x z8F_kam2&IT4|=kJLhmy8%1Kznds8Nh$%sfI)6#N_v>vZUL?I{sVCqv%_QFvR0F=Ap z4UjwrjaoK+BDCXYh)RKYZT$1)st}+<-Z^?-<4Z*i&o@qoj0yZr1_r|WsM}oLj`Lj3 zZaE*UcTg7(iK2U&OR|O&*k_*)Uuihib|>o>5Ov;qynG&cJ!!5QfIMzS67dOoVlVu{ z|HxAE)_-5e3M-kZBXtV&2&?B%D-OTrnAG4g=9U=yUL@uv@Fdt@rXRpsc{t6izNx)5 zZ;*J7?4*7Cs6P7Txx#zp`=oWq5~QADsxG#Q%#?RFV`BXQ<~$AbGZceP1>5Zd0F#uf zGC^ZMuE@G-oSgU!5e0pC^Gq`#JCgV)JamQXH{CaF?*g%XMP)Jit_x8-<1yD>9F~g3 zx1N$r@#rd92Y(M(&>JuSI&i@s##3&c(N*OF+K!|IU&CsKIVR{IpYIGmE1#d~*$|l* zXjPKh-<&nmv>n95;6(23-fejKsdo~PZSgIb=}Z4q&`4T!@-~QH=rm6ieu>(lu6IA} z+{RXx@UQKsl@cQw-X*To<|1OVA93|EdxXRsj(n60W8WR+%DpV@;+TEq^0ad8ib&V@ zccf@Dc7(!0GmfjK@S;dhH5cY|5;szddBl$f0$84BeB5!W8{;n`Krl#e4s_@E@ojx9 zxvJr@tdmFNN%auMf4XME9?o=8vJL}y-i!gtY-OAo?oXPW2R2kGgf~>21(sJ-tsw7; zAw8>|Sw>XpNw`fE7cq0K`XOMQ&~d!&kJ z)%{}2S;AM|J)B#%K6=D~6+H5myc8c|p;^pC!dSkBm^2C!Dj_R!bL-Zi^EKfpCCn5- zJ_Kv(Eji%!qFSSTa12j)&G(;`8wbc`1s3Lc9?MHr%IbI#(I<8<8X3sz9lcHUcv;Qe zY|Q;VW6qv=uSbCX2@5A-NQnv&woa(>x2e<2(gq1ltT}vxKW((5aSXqA0=FO7NGuA< z&^ZBM2|Vbn^FT}m2%d<8O}nSEUFfgmWX)73Wntvs!b`a$B3P~Jp%HvT%iL2H=5VRK zbLB}YSi=TL4}z?4eyK1MaZ?fWg6qt+-)vn5>&7LJu=$w{(jxCa{QP%Ai3iVj#HN^#=C=0pXOY)w}U`^7*{IZbiP zW41{mrDN8S_yx0uP>U@SQkfM?jDZ#*0D_LtIpTxM_ByDFue2c}te>!j*}xfG-LZ5Y zb0F;OoiVXgPif}Kx3O{U_D>@HnlPFP_dtjjFwF+i*0|YP{tfoC4*{L5<{EoU*~7St;`_9;Ep%yf9Ob5tb~XFmfp8 z>Pu3P#l86Z1Y`ZILgL;5;{mKP<0%ya*_+naGEvnd!MWCf+uXHlM4L_nU9#e zOK7}}8M6h$7C1Q%(alxJ$O_CYn`%#$k(f0N*tAiL8SsuW?sMnB8i`r3Lwa|3Rs5CH zc*7|*AepM=O}1z9{igDtuKorxKT3Qw^Obv`tf{N!15QZ(`Qa{L)jOKW+OLb}u5Q?$ zHfCgW)>%JQYS~w2$H;zRp{vS7;qb8%eb$WMI+-num28C^z59F+qoV=3!9^QX&T9C7 zGB2CVn3QZsWwV6JB9-2Cp0m0BI(8H;J!S;pHnuKz*!BDIZ{X=u`b!>+e0Khj6f1C< z2Yt7%d_P!iZbC5>6JYTLHhQ}~+H{?dGQl*Tp8hn!Exu~JO6bANh4aM9og;bS`T!us zo&)EEYDsEx@s}l}iGSsj@P0e({4mh36n*Ju#c{hY1KXr zP11T5b@wA;`3z_fE%`s>HUQ8*!~FvxnHw!Pn{frCLqbov>Cavb)Md8kYCQMT6)B4k zBiIg~s$d`XU6nBB^o(QYr9-5%2~D0Tkf33vc-b?Xlwz`MUi<#HW^KiE6Zm50{P97r z9~p#(hKG3kG_T0P(spipj$Q7AT-Qm&T!M?0m4S_^xfG&y35ykJ@`^`Kjk*;`1=9?1iwRhB`gQ{(A2F?l0*?J+7N@sdxI& z&{9qSCXzXE7rV;ibTEW5cuO_CpO~sO>tvia>h1PGUGylFq_Xriu4x<;?Y_v0S^ns& zQ(O$aJgt2(s-q$GSID>?&rIs37qk1dT#z*ODGKEIZFvb;2p3nw5K+NW;9n%kAOt8i zW=B#xoj9#i<@O8~l7Ak_Apo}LF*h@!2sg$JOL7%ROgMXKso(mt6+*}7kx<)b_AHOL z*|tAI+_?rV!(RKU5>kBaV)UF_!&TA4#gTw$GHhB0riwh---H+FJ{@`;lpfzr-yoe| zc`>K@8kg{|kTuol$nP)dB2$>Q#wt%v>-S1|T-SUrl(Fn~HyrUL3jL!u)qq`>GR&2jqe}6M0d}~2JENFj49j@~s&)FSBq^)mpvp20%!GdBMcta{3qf`lEYPJ%kh!}zn5gv|7 z+}C@g_3$1$y;}a8e^zb}4(^wnHw%&dsfe|FtHQ^HD1L6C-@13SlHtjilcT7~!or?m zO7f{nmno2#RP1WOpE!}R2>>2$X2AKooGJKuwHYi9N!rhf#`9X;C{_w&e@k%MF8#9q zw&m~V+5Xi<)Z9TsN(9Pd5Ek~OY7Xh!7@yG^O|pNnU+sCwlCs4|xOf*I;2JccKx94x z9)v##l1-nCKjj;|?(uub7Wn)rH@d)%k+i^&O5<6k*cJmDRi>8E?ye$-NX5BWQ4(A% zjb`d1a;*U)F%gP;1_wYOiv<8!9Sx7ww)F_p;Ji#J)d%;#e-}cAcyby0puq+FeCN!4 z%tFT{a=lI(05qi70Nw1sseOG3@s9&vRh7$U$ya+huqpJHjF}Jnl{0Id?Bs&9X}?z? zJ(&0#@#)+bJ9kt5A$I@=>k62g>3hj*Z51v%33wqoVzj+`U$%RLH|lrxUhtC7A1C_#jiR;F+rU zv-awBIP^TcE8-YIDuFHa=(!y>>E=aWU6rbtPUWp8)t$sR|4EF~(D`8*KF-eo`x=Y3 zf#FY8CbB-rR~^=f-EXq$V+!9&`pp7P$O8t!EcW}C(W$M~gdrJo1z&bQBjgtF6S)q~ z_S4Y!-wB+v-UYun{L=uAxab~UB42H5-bd?{@QmxhQw)z~EtmH$wPKuX0$$nevR-qH zv(Vu)$N=9wCb?!6_8y^@`-j{n5N$1S_j!>0DHKb0x8KE+w0WRs(5vJ3i?nVpul8N)qIGWL{qCj% zAyF1H+tr|{58{k@d-}WvVJmV~Iqht^s(4H=p}G>xr7yV(`Z!I=+ZHx zvY6M6^vG@*3LkqK;{YsmLmKYY*oy*&)qg3CJD z_x9{-#dd(`9da(a0C~Lll9v!~xTK5hs?#Hn z+GG0hOV@E@WV2=ciy~=8-b6RCZ^=lzR3*_?47hbZ*?^KcE~shNs5NwbLx+{iFlFSzW#cQ)mlcycQwv zuddDsl_Ytt1clh~KLn`Q0FV!@hboNJmsK%D{D3mC>lb5f zjc|>=HsmC7R&klA%7nJF5kzj#iv2nZPEJrWCE8PS|7<)y?DJC5=J}eqzz#sC_ z|B4BqNtmth{~@;pfF0Qv%{ZSoim=<<%4>)vXD@30a?(25%4qON$VP9MA~eFS=<1uM z7huiaU5gvH_JtEqHVqU-2)2g&#G%NiIei&lUx>k@8!1sRJlP6IrhNQ!VQO*qX1jyt zMF9%)5}2Gjg4t3~{~BsAM6^=)+fbh3(6BgA=G3I`co9y<{?^+OFUN#7wm39jwQ4^4 zIh|ehm|zCX<0b2tuLtL3b`p6WEblgdN7Mfix=41bE*WSo+7GszdZt`gVqZ29n70ml zFLQLKrrrR^)DcCBJy>t^+bmv$(A(TYboil;nuNq9chRcOVn}J1Vf>s)M#JxXT*{pI zF+dgI_(G>$3*ddy^A27v&xNwqsReI4P9t|Ih%l$U+x9*!H-7Q+D z4uMqE2;g-7Lv9-Y=W;EY38{vQW4{UZaP>&~xoCXYV|27iR_~Ee+)RdB^3vPRP90~z zB36x*WwPG%x($kBEi#A#=;`fEo&wO~$o|(4uAZrwnrPv1V-u>nj|=wj{Fu^vnW;o- zV$CaZgorU_pFLI{%4OvZj8&g(k@_gCG}-L5uUcg>(FDhDQEu#ih=nf$qYB6VhdbClt_VH%iHG6b9~1#j=<*PBeU{%YJE#X&?|+hR1{ki5;z z7H9$p1(IN5ciAjSI`N~n3ebw%gM0(wp!MJ4PZWbXjG-%KwWXh=ZgRt!s;o|}`*_1y zDY=6Qy9x zU{!%GM*zitkc%>vUSg-=_HY7+5XzQZzP^{l`vt{n1D6Tq4A>Yg9(7m${)dtb5*^RH|xAWi;yhP^Y8 z%uDS0UM#EC{XbR?Y%jhzZzTIm6?>n}i-6&Sa-OPpFM$b=?!lOVYOWginsbz`oLBt2 zXuMSKo4veibbpWi&nF)koeAA;4W)nQ*Z^^&CT%tV!K0Ap6r}pK^Hu`u+Z`EM*`g{Q zYXKBr^I&C(*BPGgho>_1X|p_7J@zs7EnQ36y+3s=23P<+Z%15Ifpc=&(Zh$)7Uc1| zCsuiK26}JI>!G?Sf}5dpyHe)Gdpo0hUi{pK+scUatbm!;HO>W#o?jz=44$+Pb zC3aa-;H(I8EUh61cP#(|aVlA07Pcp`aHzcNks&_GCy{*OBvDsJQsM;Lj6^{7d`;hN z+EdInckdr^+i>tx3DbEanH!ndWlyI#fh6sJ*`>Xs0}9^28;N-0ADZ5Vuuts9&b9?J z-+0L)WCQMVssm_a(AT|E()_iZmDNBvjV@tzg#Q3MuQ4+5!h&THZZ{K4b`~ z=9|iMgaeR)T zzUQFnWPhCR()rPOZJg?rgdDY(yXpfqRBnQphK%RJYP@CJGW69{*sW^C@}KmJJ#?S2 zH<|7wio8NI;%n!ZAz2W#j|SCg;H-QD+2(I!hB`pZABF#;JLt2U>sK=zNFZ zE-!wm`X61*Y~nVW53#-4Q~3uGBG*uRB6ha@l3S(j`-T^6eoU`spj;PcV+w zl~P03TZy$IL9(OVuYHI)7*z%Ry~kkMR%mz&YAJKKR&DU)cs;o6X(qoh?oH;A_tlk6 zb(=OP!=coqP?pdrW0FLPx`h2`V((M~eQsGskrRkAp-ORhtnh<%J`(K~j~nM(^n0&?SW4ACeedMUlf_8lcs*yn!qNC<%ltb549!Z#@42oTntm^9 zCsteScC*reqorSpx>3suDsr2p1n?3%<7Pj2f|W4`hkqdF3{f1R==ONXLhunrs7>1T zNbH}k?h}!R!X}IILn)Oup;@k}(TS)SK_7`+n(w65#e|Kb^=)bLEWn@u`J)Pv`#&2^ zSDinYzr~;}Lc80}vb7trE#-c;X9q~elg19f*qEcfbmyVeZ9L=*bF8$Mdo|T<+?g|T z)^Qv)nx}Y~;9{qR{?8U(BzWqp7-)$7`~SWE|1X7jg1$fmmO#ZiB#!mdky4hI)U(uH zcY5vM$kpfOw`Id^set8&$iM#mFari3jep4Pr+$R9jM2X~Ia1n?5%VJ9fj+RK*8c-T zY~wrQ^a!8ubVI*uY7ppw7YO(D=P9GdCC3m*%8ae>+?o@mlR-;e%rpjFx%P9|0WrehCNasFzG+l9m<}hVJf^?i3INgrP)AxB?$96^V;@>lK)n|0S63CHVFK$|6GC^>T2rHTST!v-PlbwYCL;LAp9Ra)>wZ5zkaD zee7NfalaDg<^_Wh_x>lq!~6eT{y%?}T#tJgvz;u6xb3QDT#TDtm1CT14aw(lHW-g|ia`hS81hebxmB_yY2WaZ`;mXuXi z*EKY?w6%YS_6`gVkB(2y%q_0`{YdvJ7mc6oF62!B!rp|dqY=hysCfBq*-=&$~J zc}=VD4ZZ*0?f>t;2*cTcK**u`BipEjAf`VUbcKj-Q#s{ydkG@Q#k7{8p#u>hwE9qp zE(st+6abQ;z&KFFHyOtQ!XV%EvW`Rv%Ts;3=Q%Xff$?L49&?0>X*W563Xf3Tvx9mv zu0j~)?~OD;{M;5ji4fZ#AT#s~Z)37$FTlnv;*hgo7C+ zbpOuqcxU1b9hh`_&LwUR816s17XW7>5|{}Aw@E%EtM4z;{uVaJ!MQ#S>1qLYl7?@i zYu`!Z7ju<99xA^`gm!c08R2zB)o)raa(`AY&znLt7xL8Rdp$={n*=2~BvEo@kmG1X z+!up{1mM9#7Apu@0X%)mD~T$*gWa{228#O1V_$;mxdh5$Z~0gKiq?&7GxU-xSHtsS zod06pN~>-8WWu%}TW22t@^E^qIta0Q)s+DN2ETfQ7QEpv^8ARu$7;F`yKd72B@>|G zw7yp)C%}3}#m0$K8H`HR$K*q8w12SN)!9trLF#g43;}MF?297X0N}Q<(RtWiOBq}kT5u}UjleO`{U_B}?MN;3tTIM6YM+QDH!qUPgUX@2 znbIPLA%#1lasqdJ*+#c?;nz{fiTxm1Hwh4^Qe(&DZ`WG^dg6&8*Wiw^YaiSF@PnmxF~fGMxT(w0imFq z>EA`l{^O83IDN^2jg#+f+HxI4J`h*ulR}4__SKen#^pPQS8h?fjv)A2JXyj2Xu%CM+VWw5QN#8LVlZqKM<1oxUaon zJZz8z5rTq-3$uHton+l-8B@4UVtTpHFNoxv0pOw_1%RhbFW{!Ae0?xUQbWQtk;^~h z)U00C+Yj*>cl=iV9Pd>~k2uz_YTru?;b@MmdsXh|`k&_|58In6Qx!_4eSq2&x{tWe ze*xJq{AY-nByOtfyl2+|I6_N+gC|!4$hNLshg?7CN@B*v2{6@YPcZ$)pBTxx z_W$;Z0AEw1cW0Zj!qKe&21UFC0EbZ{Fu4X?=C8*8FLHC1%O?n5eHns7 zJ%I4lG9CACDM18-7NW!*IBEtui8W&wjJW7Iu)Y-*n|62aU z=e1JE`Kkd}r7uzV$QxWZy!AK!cKS8{#eZrA&a@yv#R}X+MzP(cb;YGM=m|LxZi!}| z<)@PgfvIi}Y1E^ZHmqt8JJ`mM(KxcD4-UIBU_yAuiX{lOH02qpB0rYoo>;2xJn>f- zwdjF2Y}8VQma+=@6?ES|DPo$um`Z2>j;U+8?)&;RJ&zJNciU3Dtk^o*NmGq8;au!C zjN=nP15m;#KEz%;lHYDjnr!-enfmu4LJu$qX*w9y*7XayohPc1>v64B&bkXMebL@U zn`8{XzOa2A(TYVaOS0@p8 zJ;hsMJpGEsmdy0Pwz~Y1G9p~<>H&hNw{f-ou?B*nsJc|7IjIby!)00&8hkl`g-Iob zuJlk|2YaD1DH-=iXaYF;dx9!KLq-f*49w)8SKOi(K>9$++^woX%V|VhLsw!VY&M?* zQ(IX9j&`fAKX0k>b2CFT+%6CH1~qb8hSK&zmr|sarZLJfgVBhE=!cu)QoN*Qc;%H| zMd7H140QWYlx+8bL!g;_3%w!;6Cz`dnNHRQ7cQA4QNyBu5Wo~zC$~! zc`|v$a}PpPG|HnP_s|4zc$}BTPZF1Isd?KEkoNSKt-mU9gOG#&?2=HH(pk~m_W!Me z=A%`AvdEFh+1OlPMUPnay>H50x0w&3l%g(aY%=7o*;Ve+y>MrE#d=EV>py9Y#|bJc zN@%r8SKWoZh`ZTTI&*`Kx6A*X?H^aFt8{Xt+IJ#+T^Sj;FGm?EtYiPW?(~l~KFiOt z#y!vI5_{btA!IobGcc6RcIG(N=~XWr3(o{%F05m{&%@9&8YaMim)`61c?pcXcp3m zH`21mxElU_)B4d3^%Ph?eax4bg(M>0fO$`}0;b0Az>GO4Vgm^u>do>U4PEd)yD<$F zd@Hka9bzVfa zxxMkzu_H77=8bLKeGILVc|I*|P9$D*r?J)P9ax|VJe}zv0`H1MGvq+NOl7RlD1FCaRnjkX{`9|i3zZWh;)gq%bWvXs<{LnM_KtMZFaiCn!Jv8Tg{L#W>B zWXdyY?Zkmfn~Sq@8AwfA9k*dqsycWaLQ)Iq7lHo8y$M>V$}!ovLWfekv_}S4kfm+f z&An6rzKUd_=$0MaJIaEqkfH2cNj&T^tU%h__0NCzB4H(9Ndo}PdncOq*IimSur0_m zK?B^i3@@B_h$uHBftqd$Ni_fzGO+*^?MDkSeYCaa-@jsK0>jeHBT_YgMBri7tLI(NE=C z&2Ki3R}v($K+h1Cdv9Y1BJx#1I4dU;Cz444={`pEl!@DJ*2!c(=26Qvi50L9g8=_% zeL6^;Yv=jM1Bjcb|5F{ZYi% zy5sq`J$%}_ps8a)UV%iAu4*_zEPEqDi0PrHU)E`yR{I)NE`a?7$uo4t{APn~N-^Vx zf`!MDyA9fkOP@O^aLeVE3)d~Ub(;m4d>Sx6pF5X&6D3^qID_PJuoImN{3A5qyicUE zlU@3R$rTFRsh#^nfk(kAXu~!W9$%G@0Pit3wA&6w?X z8y<@sGyJH9Kj*XATHN9C;?g6=lHxBmgWat@+hX9FT}r0}-9hc)F>f$MP_NF{rJe<$ z#(O91CvBttEq_AJF$md7YI%QOw3Pkt11-2*A1fKdeuw<1rz-N8zqc%95$)MO^#)7n z6dcq@vW6{ZU<7&td4K@J93}DVCsIH#z9k_54&2##+o12OAEZ51v z0o`gwvY?L6Do>GOktGfo7#eLY#WXQsS?hk#Nzi&t-Tb>Fww zbf_R)D?Kw423)e%tl!tT+5sA(DvOKbiZ&!zf~y4puzfV&AW;1|?GPDlgsCt@SN*M! z5DSNB(Xn57BQ(TCQE}LH+%rXV_(dkBwp&3 zIUhg3zU};ZLM{-59BpQD7s@HgM!y0P!wil=@^#s5+#IS1clnTk$%ak;93`II>ML_X z@RqsM=3l9mR*vu4o~@*rRN%q0^yNBo(YN{3Q=RPf3VQQDG=S3?VE-DM?ce>X4Nl1VRS~XMqUMEJQwmX{FuYNv>Si{#bKt+t=W^fgs`+JnuWp@9isw z1IajMf*BGHlc-l=1dV%Thcv~j=|Ac6=L!ZQa}xDS>=wd_=JyVC!IR{*_Vfk775eTy zgv=pnBs9Mv^NJ5R6z{LEo+6n1hq}yyf`CiD%NNyY>J7UmP|t@Gz=2#mh}C1(zzhN5=aXZ zY^h3mLM|Z)+0pE+-w_9x!*a!3JOUGo{K}=Ayf&$usNu1PEGAx8-Lu=XH#rxx7Ws6wuo3m#EnVI?zuWZQ-LX=x-y19SWKwD3eg<6$@+X(FfL zY9H3_#FyO}6>Djp3_2ntC5RmiG5U1z;teb9mxvA;)Fplb&c6^d!Ihwom-Txz{>xE0 z^yB_HC)Fa%Uy}I(x}#iA$&jp+UW*1mt`MIe1|;^?bg76*o0!nN(W0kR;v=V&t1 zymU{<6$KGdiks{o5w`Hk<^tl(xY2XIPCJ;VK_w~g#gfxM-|pSLP$I%Uu$#>_0O?eJ zlx~}Y!k`HK5wdbZvVg;@mxV%jarG0Ha911aihD2J*I`Ax9jSL(aOwM8Gc|aSsXdo)d;AT&K&yDu%9Lr>p%0j;AmaYS z);YGT6AuTp@MV@HB}4yKf6-(fXSUYl)clI1i%^#*9(ZZ9oKKFDt{~_~+`1$nm{p!Ty`g+BUj6_v<-u`YZ31MN+oG%B{NGNamh5#++VnS>BBGKi~*#YQ;Kyf3~y|#Gz zteS~`dgRCbX5*5+W+HNlrfpwi*?d%>g#JjI-hRN{0Msa!u0j69aH5K-M&QX;2S6w! z#!GkmI+JX@of1qIK{&%sPP>iAJ$0zHkC$1Rd{8apm#~mD$FCS4bK8Tc|A444(R;%i z53r;SHSGjO!aL&`I4=VLH(*ko6#&k^p*uJ@G;o#P7A6BT_tL(pg9AGB=IjdXDSli_sBbG576aM30$+O=t zkqu{TD~)p6%u--13NX)KcS6&#aB-~q$UP!yIS9=JTvsr4C2DS2z3hGfw1)pzfLCX} zkn&@ZZvmLT^82Wx!h*&}Zny$)^C0?F0)c2VT-=+@A+svttt0_AXX%#008(XU#w|Fu z6YI5_f-Hkq*mwJYT!|Iqam%7h_Q6p#8vfgvi*GKNrTXtv-_1_R_O$wc_IyHaAQ(&o>O`+iP-6VFmGqbUycu-#?fnguB%33X~`89ogrF zbsWlR*oe?lVo;Hg!!WAP{>qpMBjKFMy=%~3ozvRkj~Y}x((f$x6R zKa$p8%x=OGC+oms*S0B+8XgxiVuw|FNsCq|Cq0B&7Dz#DDa|Eo3>TVvQmTj zQ4fb^Ol&D!`*H|AauAc`L@N%N)s!vfY_92OM;1gW(Y_jAW{oelA!MyniVZjT2r+B0 z{Of^%1KiO90QV`Pr^>XY{d1p2nwJwRj94gYl^RXi`hHYUHiYN*wAlV z9L(8UlZaS{!K072-A#WzG=Sswy&sFFteJj|RcAt>Nhwyz@!PpLRW0v^nITO{xdmSK zX9JQe`{E-Oxuc~IyDJTo(Amy_b)cH$d3?@+CToa{wYsjmUWyo_+ZBGK;3G7o+f2`B z=Q9;oAqZ5&Ppdh)HJB8Eh0ZD$FK5rY!#LcgGjRQ6&^;N(j55FY%`8TBdbZx97HtYe zCkOSu>PqKx6_(q|ib6hzFPCoZCzn%|Rw{P$3}S7JZU);YOlTbG%+4Le_kwQith4hE z5?2pFXZNdWjCThu@;ZpAo(l5~Xx!ewIOL z`i162iCyUU^b5{vIi7}x5k)$g0pgCxcw-wnP)_9jGc8>GjoncNf+yrMf{9s-jr_KC zdsw92@_@&f<6w#AKfkED^LefC&rfK@56 z(Y#G;B_-iL$x)4o0@IIHnYBnlBVF(U;sKlrJ}#@3}Aw{ z%lSor$SfWJA@%T%a5mMU87?j%g}AV?PrLre`U?Wt$y(Wu zodt0JbUBU42{lfWTHeusa3Y75(e2j%86sQdewHsD;Ixx(cb|~)xL{1OeZW)h?{?X- zGWn*VbgemB@Zd2;{D8=^?ULq8A$z`~+ei$jaID{WyNsQ$jW?$1dnUbIWk(8-Oi68p z<@kf<+?+Rkg)2TV;*I!*-Gw9CB#|9{CRs=zrk8|2km@FW4gW=wd_pcAM9gKj=y#-T z!4e!N!5l#v$E#z0^sE7to924^Fa4y4qRhgH^|@`!jrUCziYa=#-U?jdrP!+(zBO;w zJ3LE>wtq_py2D5l#r4teaQr)S6~Rl$7yKfTPqE49=Wpdi)6xa9Gb1b!nK2$p2-Z8* zC_{N^z2*=h!>_#M_2i6@-f+oJy9S5H>g((yeZ;D(tDi5!6v5Ha^sfAQaW}8bb;o2V z5}3o@;#RVeoHFtn9jK>@i#mN2dizseB$KrCvst3_E0pfVzTdl)Lp*z&03W=d1CS}u z$B&%8RTaG2C2RZQJdjX3Ifd5)vL*46W#X{*9(XA*RoyBuF!=V_`ne(mVIq3~UJ&JI z&7>b;%eI7uoF(Z`*3ahFM30{RF-~Z~N>P=9B>ZLCrZou&`=0#$e=!b56hT2;{^7NzTptd9Z~BaPfYqiV$y<5wXl2wMLBM_vH)}piFx}ayBzS ze)Y0J(@4KA$vq<*gJWw2C{f~h@UrF;2-xH~3hPP4XlzM6SM+Rb{Y;RQPT&3URsHy2 zX?gZyrG94!-FY8heq;RkLf`HB&&qoVQ|K-9{_7|7nZ1nyO%29?mG=|-lvJ>G-;2+0 z(n+mI|AtwDP}m!(wGIjJMN>MOa7^p6T2Kg~RX(Ob=F{8>06ct!KKh3l7!Q4oUm^iD zrLYk(cS`2Re@K-4wfDa0z}(Z$99AmFLUW;_jO%u$o{u&z_gq9_NPO?6lhJ*E^j{+% zuyVC0e-?juW<~rM3uwtB3LPr?sgJ8n#3>`gU5g%s`92-z^eM{Kfsj=+jqdh|>3I4& zC&XE;V_wTR?M8j+X^40))>9XuSC>rMv74bhc1R@;90WUdyYDnHGRs*zLjic_&3%9; z1lI8?8_8L{*Y%C+=T1E$-D}?5$wXyCu&-{|Z9Zyrtt;c*?FrT+a$?Qc z!lWH?WM6F#_80O615yO*$9Lw@f^ly82mQbv@F0lja{)p)0g1QHJ8vH~87vULYSR2= z@>=$+BAX7oYHezrwET^iyuNX~0=y0ioHUim+If4KYJpLw7guM6I>9@V#q`1(hSB&2 z&yTOkE^|^K!m@Q*rP6eX<*?UwR?-qWp#jI8HF?W=b4UO%eEks6Wqva!aS;zRJgz4Z zuBYzkI*k@SlLUblm{x-g)A;eekEc46-AVcKMh4ctT7N?BI|#YT+{EvQ{ryXZT&Q>? zUTk)vcSU23W(l_I;|0|+;Px9~_4^ydP@Q%5pmy?PueH$-OA1{RS@IZji~wyQsp4B| zRlNQ|xk_j#@_^3+Uw1gugV_qW=JlFK8fkmBvi^c;>>Is!Fc^N{AS>Mc$^!yGtl)Kf zt5Zc2=XXD#XH;!40D3RW7`!Uz_L_RhjSK{KEjZIck9Hv|_sZJ;*Eg@aBCHqVNUFjS zs&D6mun<95F$1B9y3_~eSiH|XVy5@$B4@(O@fgGcdt;MLj>XBpMlzRV9&&7oZ{ zE?!~vb0jzoLynBU3gxXRM-KyVx4hkp0QE}_z+kaCaB-{+CeZ*>l2P1d6c6ID+l>HvJ%?DD$-kEJ82NzbbCxY~;A~ z5Z~Rj%gLY!*H4#GTP33cEA7Q-Nh#l6(D8L)3#ZjqEXQpv#S5BJyYJHvyBcGzNSCr5? z$4PAiulDFWoaAQ=Sk&~Ifw@!`64ufZU2f_EKlkQjEK3w!jvp7p()f;6kU)d6C0-z<<{i3U+B0dT1h?C--=rGJ{0dS(La(RC?m(ApFdLG2wFEGn0ssx8m1$=Hly)qwi{`{~ zTB!W9FG$%^$m$S}s*v6Fohtzb>;@lygyI<6kN-z;o z4zmw_XR$T>M)K2JI~!nza|p`d*Gj(a#XM|Mbt+HqflNfa+l@xtpaF=T4&_2WtL#8w zI1t1<2K1a@)4`e-KC{cGXpp)@DZmA_DWI3$49J4>SoWgfL3&1?ALt5 zz$wko?#Q2`zS(YBd~TSzpVx~XrxWM>TxbWwTXdNp_9S4A*1)CP@k1K!zZypA?>#8* z2|-8;FW+PGdaw|%9vND)PH+rs;f-L5kpXK}r(Tqt{Ct$UN^~UCQW3QB^sX{!Y1P!+ zqc5DK?8cWrs1C*Jweew*(^0BCA-5QWf^3a2oS4n?!$({aWN0ib*!PH6J*hV8 zFHz^!$G(>PMD5@nsWSnvujuBc`L@QO#J1~ijUVD-PHh@tnZSK4WDD*)*#{H>;2v@A zm3OHikY-%rK%O$M(Slp$FNI|{0O(68k&7O(5(j}Shq37?tA4I!XS9s|@uQOCrixX? zs9!Q31m^o+nhNUptjTud>JX1OL`r>2QHo*NDWTZh@7Sy(cGFVRI4`+*IIF6b6;PYi zAii=oZ{<=6lNPsA_-;i~@I^{_zx&4}#8fr}{^d3M((8r?i01E+ga?}-5)h^~=qCd) z<}WAkH{(y8Vc-9x&QZZ-{W zv&*uVxmRh~=uololOx_M;^k1{vtc^$9*wTjTyo^*&8hDj9V24Nz)vyJlyp18Y;RLy z=aAo%?a{dN#*RhS#7XTt3JfTg%jcM%@U>)}Zx})-b+~tYdHn`>&Ui7NC+OKSkJ2M~ zmNyU+jb8IN(VokT>cyZb>D!mp?ISjOK!FFyKKwxq7JFX7U(L{@QX^nNM_|S#_b;Bo z)}&ik-#>190`#MZQG?630w-cYm6dhbt>NhI-ciuxy^X!+DGXsDoKJ2qL9uv0??68 z`qazSbF4i?c8=I@YP5T1_wEuHi%fh+6+&q8#`XWw$S0G`qKZ(l$5>@UGOtknZ8kUZ zvYVA(+PLkJKoDy=75k5;m1|?-d$tB2qV1iK=s;q%Bb}AXWynUo$}@I2+`l*tn?s*T z7CWW3)=5E+W)73&-ucQP@_7(LB;jqqx98^vp2y@WT8H33O(7Ep^$~$xeP>@W_9&kmrIEqG3nOHnx(VPNyvotho(ds{4)>;Iu%kD6D2L?7t zd|cW3l_5SYLWFujKoQm^qGp>}TdJh1cBHFAz0)D_tZBR6CgA(8L!W`ig|BwBBWT}C z+jg6STwC>Qv+ON;8Rzh$=)_)#1&pE2Ig0;|?&6HNJyrnBSN?tY=;o#X02Jo)TMjXY zKCVbnpeRhzpHrCHnO3-NdDy7@=koa@tVa#jBBitL5XMC|!ZD6b(s!2uA!YOR`cb0E zyI!$EK~99!a;znGPDyVzBq`XD`_?Kdfgdd0;XlnE<;eV@3%7@G`?HfR6MqU0=R|tU zmzIOy!iMS2kJ`G;jrT9}CwL|a3-HBZm7 zN=^@AKWd11cf_IX0s5cv3~5Rk`78GN^vw4|k#PxBc8=AzmYb_n#_woX&dK=!f zRd@3eqUq(n%sFr8Dz5?$j92!cYKws~vgD*+zHE)-EmSuYs6iJ)4`mMK9|wSGLAZwP z_iqs3aAH$+&_|NZLKBm~`@_8tCYRT*i_A$3@O0KxSHTi2aOvb2YOpQxUT?Ye?|c%a z7kC<%Yd1vo$ye8cPz>~!5#7TdW+X0dCV9g6a8swctfeF3uZsqowpGd$jZF^=xA9JSUOqV5G1lQByN~l)hZK&E!uo*T z=f@ATzLlP$-oB5VW>jvctV}TpCkI}|m1Ri>Q5Lk#TUMU-)|P#J5tE#&HMC~St%rhE zTW*&eyGH&UQI4^ape;#;iWQMs0Lmj{P#_@tl3T}^u4%{opcNMgmMNSL*tk~qR>ad|U85KOiM&ks;6d!8d=rQlj5&v+A z|0z)fZYtz@O4+7{P->v!{h6+j(U&E^wMTTFt(fdNuyBEV{wxFgE)3plXVp>xP0Fk}B6%R(Oc7BU11;ub# z2~ju_rsz>Khy@U5_P)YvysgF7Rb^?V&@it+&CX^0ndp9)QKQ>_M+W{V{_(nP&Dl&_ zG$sD_W@<_D&>i_V<@#du9Y-d>v77>(%e~}Tv^B!-w4~+qCjd;+=ARjFd{ex14YKrI^*}#R z1ttG_#H1x5`B@@Ga?aMV&;-;Qf7QwBh_bN(Nd#MwHPunRHFzyz%WCr* z2|aRjTXK=tj-@0v0GXn?VM|}JrQ45vZI>;pp5NB^?$~6VqeCIm;^4jIvKF&n=SAG7 z95z4kjwQSX&xw4c>80oh=YcI3x2X^PIqJ z?arD%-n&Hd|93<}bZubbzOUWGA`|-=j9h|KWbV6LraGC4;r1Z{SHNZG8Qb^2NmBsx zr-(V{&1{TFa@>ubwX$N7{Sr@0w#{>>5jM&^RO5=z9gZmmM}2+=52%yE0?arFH%45WWuk2-!c( z^*ub8wBE1R!*;c_L>#=xl2H1#M)fNq21j1%;zz6NTds7j_!U0AT5Xn>x#sUC+ih61 z&ElnxF5W#wxjhiEs=?CPj#D9bQRk_61a9mzbNAg!-JVJe@b`c5`V5=fWi-$+Du#-? z8Vo%`bTQ~?)P~0A^@}cy*xh(lh?TH<+!m;3tk-uc0lr9+os9$;m ztBWvc$zX5=HV*#xqvi0;Rp6rX7sS2_#4^uK+tt-Le&`WJqyM&)IN-_u#i z=SUlO7lZ%Xu_9M!uDb7tmcHCsfq;=MaG6c5e>QIR{CQC?){kYe^C8P?dyRKE6>Sia z6zk5%1brlI@*g4Pj!e2ShwINlV;wz*?|?$M8?f_e%FjP1+rPvoiIhsulH|-e_>+vu ziXeBT^VBtYx-+1yCLpHuDDdvNfI|g|H=6kzWMR4;8&Lk~GkzD9copIVR{4TUy>I=7 z{-rL1Rg?QJ@0kp6oZl$XGbqE6p?G!_wCHF zkuU0%GaEXAnymQGMYBF2P$$Tc$>t??RI~^0j>4Z2KTZ#|M6IRG^!^t-QUtRHsOVe~ zKJtj}!NX<)gj{ZI?7q*@!%bgf#vJ_$M>y7PH%$k$_}pFWGN0x`yyUj+nm6(_MLa>{ z_g<-A4%UO6)P{8dV;u8&ba9Ppm;kJf-j`79Sft>XB3F8vnqp-(qQYA2=moxsFd;o$J$Ie@M3x*G(F*$(<4#1tLX)dpk&xHnb(h1f46?(*`ew?4TH}t zY=1SB6SMao@Gb|t8gK0Z{e^1!H~IGvfOtot?rq*1mtvpEerj60)Q)Q;Mhg%sJ($%^ z7vq&ZionE76glB#B1z)GruaOM0bpOVZt|CqxtMCy3&~!(OkOIiM(1&izL5h3dq-UZ zdikT@{0X_uAmm=FRrh^SFh}vq1h`K(?u(B7&!{s{AO6d4*O(U1>w4N9V^6-s+*#H8 z2EO$uu`Eec&W6y8I$S@q>nho}Q@D6pa{-0xb-Rt6EzD+1C1#x-p0yTK!|orwE1Mo` z8b+VM!`>y<#&)w?}gRnlA{_1LTE&fY$;+5_xqaR_TjMy)aN|zthnr5UI8jy2rAX*@?y3)$(H04rmxuZ%KR^*w};_FnE4D|%gHrY!$6@@`-ih? zaWz+?l{QY8>c5(+l8>GyR?;PbVtiLVhd@;ME*YOQ`;2P!DEFUb3lLpwP+`=aY^5>o zX#fGidJNvXh9TUv2d}`~Q2;oGf$d^O;_RA0oNQik1CrAxRktQmy4-vL;Ge(aw27D$ z-(W?(d_wMT5V5GW*+(2s8`i&0iDE1kIL8prF{YErOdQwm7o?_ThYYb_Vz0ksXqhlZ z&*m%YEo>;b(PD3w@G2DxrE=C3k_L9Kbu^5^*Wy1fQ_?+u{M6l|_YXc7*7Q=Ri6AQG z=ma~EfHLS`AT7-^!&e;8Ts6Qr$&hXOUfTlzqaaP^x3{x-Jt_ZQV^bgH znOr9>PnJ8ciEmZ*U^d_IdpX>IcNY{_lc($puSk|^-yat77HukpEJL?0-7IoFE;Kk^ zq|Z&7U!THs#&{Om#G7A8Z==9P0KE&~fI~g(tJuyqo*Iq^^d)t6wjy&7GFlYqw$TmC z@RCI&Se-c7JNQS$)P3mu(*9H43eb+kXA8Qf^CO`%^=hWj1$}cDx27)5ljAAIas43Z z3?uUFdO{A7cRkmALT-RHc$J1Xgf)(y(PfP3XtFfc?OP8SvO6i6sqr7U*7UViA}{My z_2K!8wnA$TGqGCkgd3@fPET>s57~hHw%_13o|pu%>sN3`x|=aO^CHjW*NfABl(PTQaoq>(|mI6W4FjI|A zaiwb`I__d=%sQnXRjh1KR-W1`XWM4L&l+s94(^x4eHQD!+qe&^j&*w+h}v*oJ_@jkpj^kk5LjsM$_S7j zZ09P0=Q`{*8o$vGt4PMQr3=U-edTJ>R$o9m9GFoj-0%F>B17#8ILD8Gai^|l4%$aW zXMH$C0^$EzC5@20kYO69;*Ul$s;uV!k+ISc(b5)obI^&{OrvwnT$xj@zyU%^oB|1A z(yQrg&}GQyW3}-7O*9p;C66qvu;t{XooL;iBg+1H#dEtPr+oe&SoazW3|OK zxmyQ_fi|{Gv9nSC2Pzt~iMHwqq>6QHQj{KQ zl*kBWHTDjK8$(xVXQtnZN_It8`&?xR^;#L+l2>h){u!4^&Ka)(6(ozKROTu-qnM}t zXDkOop|M)Mz~ae{RqCmTY!bW7qM4}S6?FO6QEIkDsX1*|6KHBg zLGpLLlS3vnOH-hh|BV4$@Se(z^cf81r|?cp*0+&LjO*0tuI18Oh|H)4otMg&^Qhr< zb7QeA3g{K`4Ec-aa{AxpUWXdq2jJ}!6sDebUIyf^13*UuJbXwfXSmGQ7759bqR#`Z z*UXxWk5Lajg{YETNp93eqqg+Za*Eorq2HWG{v7hnWwh>?R*JUM{wO=;ULqah5 z`Q!C_k!}_UJdf|)tN4G%z$pAOAa)DuCMoP~*w1tWAKxf#?SIA>D*`yD_m2km+s{nX$$vdE*q~tiu#Xz7N5+x1z#dc;d?h`#4Mt^q zLT)_>1!Qe1MdX?FL={b?Fa*nSiR^Mz!C+?6#}RU*|;o=&pj$UL}c> zpcA?g41fc(?XU{}cv)P6PxGg|(XtE!AkGQkZY)=$wR9BZgSU-5a`!hx#zMv(q&8ry zlv0OLud~gTF7)z>IcOGNO_5u|^ZUmJc-c2#dva7H5fz@Jt(VPg4+3H4qJ$u4k;sOX z@+UCz1XzYYHwS>AcT{sZmag-a05sfEljb9&ZUg9T%0J{+R2Yi^g#97EAh}Nkl9uJ?Bu2AKN_Y{j6 zeIE-*1}C(%XsFc?C5?$id6oAV-IZRCmU`|4xQ4(?fqQQ)vs2D1dVhN#p(PL~A6afP z?*m!Ft13;LYToivB88?Zo~oNpP7DwX?I{H{3a#{5v>@z=4M zIqRX~8YU4Dt&JNG#j}Qibd1gY_I3YKrsB|yX*-0LmY*!%tY*h1ph9v`W+UEV! zBngw*ir=P~B>P{S0tz~5oGw4l-O}2g`tbVi15819?l!F-Ul+;N?rWZwwbqp9z5`x7 z`>aF9dry=j0qw-)_(#zRoIfCRg_<+Y+@{ta^tV5!~yS9!IZ8RSPPILsnL-WGm6 zDE#-Fv%2G))Jb*@ws-r-B(bK*bs=rkb2Qw>i4O}kz=frqg7QP^O30=We#vru$&;`C z1|i3qnfOHzC-I}zK*U3^u`RXScB7hu7N7BoU1BA;B+_)P*V=ITyZJKj9>3-}`!f74 zOzp>cL4Tc`LAN|)%t1XYY$ukUz+Ob*iG~ zo0^WF0W{R!1bm^AwVz%y=?QAvG4iGsvz8uMTu84Ta34?sr0T=lOhs^WvO$3>l1O26 zTgcR)>Af*lCbY^w-}8Z6zxvv}0c3as;^Yu)?OxM%O9yy5APn4L@*(LkGL#ZTJR$cd zhzMr!_HI+OkJmbmN37U7E&#FkK%pU7pTNU^9vu@H@ik5JyV}ck6~imGKbbW$so!6C zbG+qPk~;lmJH^&2GS&Q2d|S+QhEi;;q2z)xyo#;$bPB2wFQ!dl546R^16R~%r#CUOj8U%DdjX0x2jGc%{TeX*jX|+%l0&7@C4!;8hh)oG@TZpZ* z!<#aYhkGbO>0@9JQw)_oJ^F(O()5e}x0TAH;upLSZYHx1By{SNETk0JqUyV0RCwdUKv|n9j>&ZRaP6 z`wbhhVSkj1Aj{UP{lkIqx|e;e0(DCS)odZtq*IhUWB@R>|>%CA77swNG%Rwll zCMFN~!jk;koQdFKX&kg*w=wX+s zGr5HFd{-)>`aAN9Zz!e0Ao?_?!T7K75#V~M;Mk@OSwNiKswm7vR0piDTdi6>TfhPa7b2;+o&=)5!vV z?H6zA)c?BGU!|;VT!N(Y(p&?81^geHt}-sF?&}UicZVXD{{cS(tWNH<6~Ln+;$ zAkrxtQyQ`tG=-7>U~}CB_-47A^YfS)x#nW zvM?M;dF?K#wBnuT4@-s$dFZ%#Po6_*F`!`t-IW-g=FdyEx81(v7>-1=>yVV@y^T^T zHp~xw2M7C1B+lvAEGkj}j_7GrBt3A&4!rYhRmO^8!=!;gC>@z_!VOaS$n;yenK&@` z`HfyplrGa^8K;}xHq>S8wC^lz0Eh1f_D5Z(0U#4qy2XIy<0+A?3(Y8w&FZl>6(U)^ zB5>IK(ZBtwH*mJsHzXZ#Zu*3oxp0ooe#YmgtF_pI(bTl%RigV2a2hC6d~Lj6bsPaF zk^oR*NKRUn;!j4?zX1o%(`Fn3EwwPe*`v^vP?Ug6F{#FlyMhdyTG{nz9;rxNoC`|e@aqv``3iRW zR}@+*c=P*|K6iVIpTbB{eS#Z8`MDt~Qy|?i+==grSLl-x%ATy7 za`F1y3X%?5KI4y>r6R|-tQ@~y7UIY~m~TSOca|=CiUnlDc6_k8sT$C_Tb`+N=Q89K z6cMwiW|0i0;uoeue7(LA)gnl%VqJCCy!+z6iChK-F9W~`NdFYuUXF$7BOzkDzOB~i ziZ+S|5b}~u76_36*1TL+v=HG9(=JJZ#%uGarhl*eeWhW!cy4O$*j%{_$btLW1E9Xr z36`-r-FvxV2=tw)S-=jNu4HMIyA;$8*O1(At3(5`OY9nap84WkEE6V4I>{zo_(Yh> z2X7X00*^;bQY04RjQt@I#Y1!-v6nBtS?868Qm+nVERpl!-z-k1-07u#fyonhn&lgnJJ^_yPPYYc z;f|QnnAD8o+^uY#sw8?6NwPzUM|rLGVl?3@Rr{SQA{G06290PLdW51u`HsC&U>de) zoyFGgd&rGIpo*HWZr*X$KV35&m10(j`{M4mRsVTx9p4QZon`gAPdQ+dfn zY6BZFEa?6uZ_07IeHb=yll&>m{?$>y`(m_~nB4{$UA&`EXR-z!+suz zCS4-~=qm0gX5Vlg1KKDWPVa47h{YB7%#Gj&03z~J&6S6osI6HH2X3}H3;&0NBH0*2 zEL=iHhR>M7=ilnIh>HT?VYkf%f~wzZ)pGdi(y`~(uu&5T_|^zWJ)k7a>Bs?xIBSXMd9imwjj)m9* zT?PobF$ffH`WGY`)=L+g5lhxOCY!l8du1a4 zd^Lm~AQH-0QSBCw#PL#7y35 z|2097yql%Ngxv-?w+>Ydvd4tj%Zoau+Duy9{KHWSR| zeNLrSw=#jE4Hd;GA5#v$G>uBv=MCjYJ5zpq`5CaKoSEse9iZ+6T!!o}VGEb2Wfbs5 zuXuOBzlEQ!mJ&mCc$^6m_AroFJtdl4D5c9-q#&;3YecQ$yAl?fLd72pC0Luf_mCS5 zgQkIVb)QpLtU^LtipdC%$NfH`sd`w(Cp?D#91gJGKj~(bjbWJI^bBu=qCntY5@XnWv0*F(@SU3R|UVtr5x+P1vA{4M~a zG4}3YJ3r}ec>(N9jJzX8bv+Rv_|ip-CtcGG>4)G&$$3Sd&_ubUuoJl0*-S`25~lVS zlJN!{eWtx`hV!rV%jyuJiS%{1@Y4&#Yk5(JSGwHH4nbi9(7`eHd;v;TrkXDQFB^1w zxjy;IYWaiDq=RfCTxGWUM+2TB$M`hl{~IZ!rKUUvCVpo8c~E)2#d=h{nSaPUM4| z{l_egclxFIb6k5$S+!R(d(;=dITR??@AA%JUt&V9o%rv#W1x@;NvQf+qNhIE^I1(%U2cdCyC2fAOihid%R^y}<}nE7!@$fGsEA;~ zNP^MFO50Bi`tDe6hI(@}I`se=9zry9KBukyxc{?-OgaMO>fA#P0`;<3yxAjrEfK-x zF2!Yodk`P6Rj)mEM#2~Jj^Y$R!r@A=PLf`dX^MX~BxJfo%(AAN(nA=M<=DH*yDQ<6 zQiJjzGYWTWzEaR|xJEuvnE8w*?4;^5T3nF-ySJ6C3N{^n+Uo8I2TL_~Ztlssb280S z*zfgKWU2Hev@Y9$V_~!z-@a;c9 zE&+JAGeaKe13~DVGrBJV0`evy=v*B-`Z%HHs$d8H(hKVEY=TcIwrTG4HJFeJia|@{;74ni^OTC?nTBs< zp;cb<2kAU7pxmVg=BeT-#X9o@Sl?=bN`4eozq|=U3;iGD1g!qvY?BvA7X3=L+&CQWfvozYv0<2YiX(~H2<256Pc-7%{2oWWH#WPsbf5`Jb@Y}qgj%g4oU##E^%qEPC2ifDA{OKcbfbf_Zv z?FzoC!1}8nlLRJhM%h_2bd$HcKjvYYXW!w9>^JVp=E`+{Rju=Ho&k3oL`s5a51AEo z2V_OZPOrr@ag%MvyDdE^NAr+#Jgcx)2on4sf-=k48&dyMnRu9LV@1a6wu`a88tTcD1FU!qU2jma*fQiF=;8{XxAtVf!p9Mn+@?CBt zqT-nzfd;c!_n;|-^F-3$QtGSmoKZVZh=Aqm)n5tHJb@4|1R#vk_FR0@C)SK zCgeJbS}0qY^QE8&Z<_>9Li(p+H~7(=*vQ_MiGXZmA^|yrZ}QET>;C1v()o_bHA#5g z(eCXW5*u`_7BT=ZNp`WHP0G~RDiS73mOjykS6d{5Kaq*>TbCBrq$x2u&i)Kym z+O_g%|GFoW!Q?#6$~Zs0@GGm{ds`!M77ZJ{W)-aM>+lj4qo$0w5n}$xm@GnxO8-S6 z8CZ-IGK6+mBH=u{(*l3`AMN!GOrZS?>P0NzMV$+(aSQ?JWzR)KjEunERO(phy3@%- zpvjpJbI3!dF?t8fOR0AJQQGFSj;7$wp~epGmc!0q&=(`8r!y5;6>XKB7|K$63p<~_ zOir`&F7|A3I>;>4fP~mCAhfWe%IaK>>>rC`ZGNm+WhM%SBfrfr0~Qwgi>Ii%KbF^x z_H%bZyOb!LZX+87Y9=2nMg{)AQcFIrHzsz1J(8RqxM`uzN}yP94$-;B|Gt#rE76iNF}!HC2ofihIb7hd~`p7r~KxBdUn+F7;L&U*tX{IqRBA zbicc#*<6J(+dV~T?*B8@%%*yDf~AY?OPK$iHgCGbX{r8AGzAk2HvXUYb4p6_&GCK* zhW?wLTry_AHsNjspM!rtf>l}BZ#xI*Ov7)0n+^Dm-VT%AjN!ktMr$&Xwiju(KQn2X z?Bb#8^a2D_&8Svi?|M4L7lDcKe-26wx89ogW!W=gK(f^IWm;dSs&8nZ%iuhurHs(gn)<;knmjtN5XG`6%^`P zyTXRWz)1Po7QY~^)|C+pPlZ>YHIGa(R;8VNkf!kK$d%@2X##-A1dl@D8DB3_ssN^oy= z0aij^)b`U+QWi&_JoN^G0??6n&i4_?ECd>CY96pfQNYK1`&+UoC^pwMsJ~u2WtyDt z=_TbvjB}jr-}&31_1hbbz5sf@s17>w!$nJaaMZxrw+!_7(h)soXMTZ)_TmR;n?TWr zqHtns=~1Mnrk#XreP?cV4*)WqufpB2guI?m#@KV_L8d>f zw$eSf_6softvk)F#(k5fpt8w($gPG!wWSw>aJlM5BNk;W9sT0aTwOs@Fa*Hol{_s{ zeYHR-zgUZ47yhP+*8NWSrypsD!`xEw?=slTX)6%@WY2|(l!-}Tw>onFqc%FdGr{I9 z;wQ5vr_-w=bGIKV1$4E?Q+fjIboI`sb6Rjbpzr(Uf|iUqcYgW!h0f#QHP0Mcsr18U zkw1!PEEMfeer-QDe`=HdWyj9!vE$E{&b%<;+Q^=33h8xckHgGe&x8=?!!keEj=A4$ zTR`Jz^}^C(hiTM;J0A*8>I6%xS@zx{3yn7rwDW6e4U2_#-MnL?LR+O^;oeD~_#|5> ztW@$wA#O$4ILCx2t|+`X9oPea%W?pSnFPu*A=%R}5NKGq+OKJ2y`Qf+OjjJP!=Ewiu@ir=1Hmls8ER!mG&A@9~lmCf*_%J;PGpz%rJu4E0a>ShG88lc0h*R;5 zNwIpa?D#F{3hp8_%qZA?DKrfc$L*el>{lpKdLOJtYkG|P!5cbY#en=fAvA-xnh?wi zCc?;XHetFg(o*kT^y?F9*()ZK2K-F-YXd5J`!JglyX(1UJ2)&S5H?wHNeQ8|F@NW_ zDfkpRItQ|s2|AN?;Aa;4dVS&hb$f%)Suz7n(KsSGbP~d%IbwrW7riU>#clX-HlaTS ziTpU+#M%?MMt*T$Rbg0ENi`q`6$Xr*mUpG6Z_UH}k}0sxCOnSJBEO*zWab~R81jhfNf zMYo)vmyUeFkOyt;DZW3mM(G8$w7I+X+IZ?&Uzchx@OS}e`GW+sy{0R_$x-?$sYigy znD2Me-VDDLmsFqHRaX&9_U`%@!*RSTANbXbc3tVYb>!Vr@pM)6rA_DT?>I#Zl=$^; z+-7jAzV0@SfZ5-vE${OwzsBlw&>Dk4Oy1LKVxAk6N@UNaVj5|(7K@&8qhfazTDoVM zKPQ$Dws~)V^~sU?ngQe@b_~#7=jw-{H9TD1Pm;m9iO>xHv-*|+KP>6%VsgWC3}3VH zWXPPJWo&DyV1Z8TDG@O!<>G0x34vzmzVwKYl9l_hU?HiThU+Nj)t^wWyG(c}dHKkn zc5HZwZb!Gi_#6gxqwnc_c7>YNS(TAhVzcIDoZ$_j&syByRjTf>3pL4uTG43O~2Q2_eA_Y+NZ4aaz66!7!l3B`F-H zob=Mxn$&^U)xtqFDqyD19{$x2^p&Lvm^Oc3@yjyY@zIt)GKkmf)Mp?4P*1!enp}Yy z!qBlCv=Ajo#1)Y%p8a2&5;$2cbWH=+xVl8F<1M6^6!FHDK)S${kSmyA8|*qr&d1)ixC@(GTwxMEs0ik)Ti2glQ-9n0 z;OJxUGB{pViexpJ%UHqoK@kFT3jhFMyxX#vJ}Ro&7?=hO5;2ATF{a7Z!XI%`i<@2a zCUCxur(SI>Xbjkod|COGP_6mzm7v^pVQx+Mo}%TN?L^`AZ=JWzGBE%Wb_uHl7Nf$SnR&$Q&pLygBjKQwiEuxWr zXnf;ZL2h+L8sZM`&BDlV3??w3bgj=HDZsH~+iOT8T=M1Tru(#ib5;6WtPKF{VkiZB zOdd04gug)eX4kWO$Zdr|%S{&oKrbh5R|S*Yc#S)!;J%e$APbM?f7+krru`zr7ch1B8AraFeK*LBV*+sI6@CTt%ZvxC(^~YjA3yhZ+fQoVF|) z*-n-Jl|Fa-Q}dMN-plPnpf!3gZ&rC^#aY0m^oI?8u9D+c%s1JiTNl;~)JRO~mxyTeUZ|GGJaf$7onm8JvPs%S!E|UB07OW% zzoy@hUbxYnd-*>*)ThBG1F^DDMe;JHtfmC_PiP+lK3umL8VT+iseO1ucV~mrP*N*{ zZ`}bFGM_rZdc>U!aC8pqtNd!6ow4;JI#jR`q9xh|fs_s#nwSt=#}v`KSWd9N%i*VA zov&w(;-hc421~3ULo*EOY5LdkA5V{{4L(eA)eg6Y*{i&uQFrD2!Sz{YTpLQ`%kWId z;KlK)Rw0{U?P7iN?{|5fZ~!<~IW7*aI+t*`HlC=CmMGh=ONr%5>w(B)^Jc+pT-fI+ zNEz~fY794g0&t0npIgGQM*r3VF#!b2?w}C09RhYMe&F-xK>eU-@409g2S*CKYQ_Ru z2wgO(#AEwx!e`;CS`8x!p*8Po()igPIs4mX^zrIJvz-b5Rb3&ZLrnYY>V9wBi?*G? zt3t3*px{;crU5WFT(NKann1?M3L~K+wE^vsO8gUyuz;Kj7JsRJTaT!?+R*w3Qr#1n z7H0%JwrF+pzWxn~*;6wDcgPFW)O;eKbA1N8#|DSRE?tuzpLp#vQxEPaMngOQ@uIQk zxbHn5(utJH$`n??;@V3X?YE~BR4w~TrBA6T{<_{BJ zXwfIPwR6QKtnpT(1S@xoX;FgY8G=tadRy9Tp1YhPTAsa`f9C87>}iDtliSYh#-Wyg z3sjj~BA`NosJ#0M^K2GFz%Cx#5Gl|pqM1;-aIo-?sdnL78eE&@6U2P3WN}l=P2<~< zv_77|uDRjuNP2|#an5i8l*2>F0H2X9D!4v*MlU9%eotj! z{?O06xrf|(7_`oMac7msK&z5gMk-nrC#DJ{lBmf+N?h-L;-;9`yZys_s)0t|%-L3z zl?=8=H))a^gqV(4STvW{U8?{{+9O1Vh|@QL;*K>XnAE^sLwGT5bHyYUhJ*6w2>qu& zIFc!$dV=Ftb1s6s7AX%ottrtkkdcE!7WB&7v&%DFk{5u{uMOZ<;(WPvg2ddlFHBbH z`CU}Wh9vdu{6|)kmMHNmz1@ENfvV>iFC&fbyj55-j2XFp?*pA74`Ubl7ODck{R03f zU&8v8P}AL=|75lTeWt?3Qx^=B7;%RT#fiQ&#w$=(P$(!7Hxm$6(jhH3U&M}K&FoUW z96In5x<$c}5f)OA#hnMC&fF&xUKF@3$3GH+CA&D@9$v?}F)O-ehsdT)XVbL%uM& zjaquSbA*Cl^JSr)0!9|PMM)Wf&QcftgKAA{ulY;5A`B2&*F$nXdJo0`Et^zjZ1ZUv zCO5a33k~?~{krNcg6yCMKLMk2_wp;l8{PMGR6C87wJu6j^u>?9ix4xz-FI%(T?1b7D5cnUclJPdpZj{qKWS)@0_1C zc(8W}1J_HY;BrqUFUZ+Nn8VDh?xJ+tekxtl@@e5W$Cv6MpLv~?PQ8<0Fby1$T>hGU zVNiA5#T~FSPO?4*x#zA8UTAw4@2||F&ygcC+jx10=zi=2vDF6$f#;(3o)_dUxXxCqrrWA2?y* ztc+QYtiI*M9NpRZl>nS0Il-!_oeJaVKG)~-&lfFnWax?y$8c)CL85RrwWZB*=ftG` zZf9#+Ql(~6SL1kfR?{X>1?bTAhL&1cu_$N5i}@_Ry;$B_=pC=4&&JL4&JN5wHrX3Rm8eRSH(`36tRl!tU@AI24Q7)v5Zf|l88zi*9B5qMKL=8PahIznKRM_V^4p+^AX(wr2R zirnZ2dXlF8YP>z#yHIXcswGAtVlK~WQk<+v_(piCUKx>bwVino>Ik%WQsFMobHqn!Ryp5|2lU^MYcM)9+WQt;BL+H0oY{98@&(3?5OzhJg{Nsg`c*5vYaph zjA~(^w^`l-s$5jZy(PvtGrfG70`^kZJp1l+Lyv^dxkN#1-Wf)Likx6iAy|DdeF>(Q z#-yBRLnQk><5+PWx2nHD{@}PtUS!Sc_fz$Jsd``#XOvMs`B#C0^Xshmoss{*&+a_J zF??FrBhk8!SG)=zL$x$!K8z#3eh>al|EZ!x*>(N#(T23{((-5<%u6tAR)p7)I=H3j zg>V5yb~+X^{0txJ`+=K=K#NW1Z`OFi zo<`Ebq~adoi-19Jrmk#POkMjWw;dFcz`ET4@hzSl{H!7oVUzZ_fVGmTqpDA$nk)yzGakU0mrW-C=wYr^r(V2c zm2V;xb==H)_}*=iy|&tXjLHQ^at~Hxuk{hFJ)iZg=z3F(HMXpmWof=@pkm4Tqs<-7 zXgTbkZm~E0$O=;CXUN?$kxW$xEpRM@blq9wQY68*qtJy|`9J)L|Fvk)|MWWe{ViiN zFU{8#Z34c>|0-30V)kB+)Z&>hc42AI8{Jvw?Exo;FhuXutW(Jz{cY zK6z6ax@aQ&Ckl?`881lc@N0#Cek3a)MYHV+N{M$+Od6`Y{v1h^z1puX|5LgTX#8SM z(n(6Fl0&Gb($~a&e*Mj~uwCgoy3KtR25i9emYZ(|em^}9{f&J>q7{ZlP)`6gEwbeP zC*3wU8kLTBlK9n&{$v8%T~|gH6_KeCgH4NkmY47KLINxs1GliBl)r44`PqY>5x!ke z$-*fvvNju*>7OVV8Bx1U5ZIs*Gjn9zPz=fH{Y^QFh2*XA4=xZHOS^@BQ+ku(J;OtA zaj-lOzv;N6zmWlEK-$s;4zMR_fjFQUBnX?Al!XvH{obU}DUr`xDyRHubKDsLI=ya9mY{5?;p`9j@+o1lCZjeS+qa;+Jay3e%BVQNs;FIOR!Sn$7px zM{oVTh2CE=d65`B(RUyg54R0BiWOavUwoFjBFg;8>k;X}PRwZQ$wPYlz+~WY3<{N( z4_Ls;$2(-2fpt2R21@#GCM7AI&zL-kC7#GS3R6Bl9rHJXCF3@6aA8B%nPcUXP>kPi z80~6gtE3Fo8cyP`*b#gH0tNua4q&e)_|{^lworb>_30jRpp&cAeR;D($slAM598nP z!xNDMHPZCZAe3%*y_pl?;|Yq6tUV%7+kcErY0dr{3L#N%Tgrwr(4sg#6daE%VAc{Y zeGJZk!4SZB;|brX=iGaMLmb*qJan+QqT)tC8v0GJ3kgPkKn z^N}yZEzC7ZAbRa11~2UJbx(0xD64SE2xDy2sHZ+~vTsYK{xL6ojemh7sE#>#Qie`3 zXrm*RVeV(c{_O2GZ~;5D*bO|0k?m5{a)|xcOuhD>mkWcw(p_}ixTU~5#}v+})JsS(U$RLRe|TTHkh4>lJZUFuIJJ?@9vbFq+9 zy1|Zn6<-wG_ZpdhT@37TSo{g+=x2_Nij3tl!ZsS|8Dcy$K(djRzDP-I5hia{X|#p0 zTpeL^`Vn$MPpGd(>>$JcoTt`JTRv2Qv-JK&=(1F?{ku|y+Bhd(dM)(9#Wm%hVrxdn_iSaC zTu;%g-9%syYi3YlKeqz;Z79zV5(HYTI=WuY@RC4?1w0^a) zq(-4_nLFFe3p}Dq^}N8}<^BLoEB3Hn5HXV5JArG@!XViYY#m^44+T?RNWFk9fB{i+ zt{Omp9P?H249_OcF0trsSX4C01KF%`ODFxWja`0^8Z|ZseU0@PT;|@ejWn9RS z23S%rs>S7+)Adu;fw%x}?A>>*F+m;jH#Tz+Xv-_}fW7B-l0V~Rq&O9ES|2!WvQ&lB z6zxl1;E}MIn~~C*y<3$c^mqGNZ5Jsn;*~pb^JbuvtmRFL{c35w!0ev*<6C!*y^|4{ zwX8$3NpSQI_7=)5z)y=(IFKZoQ_A#Q)(*wbTvR?VCbUm5L&y>q(~S)_R=zf5-dIKd zp7yBo`5(a~t@jSE@r8iT<$<+r?}3Y3F=qt)^yM_dU)WzS*%qy>(a6*Mr35j{S3#Z> z{);9^Xg#huZ2{Bak%zL=Yz~ZO2o(Z5Dg*!ahL#^k9B_9v1;3+|5#-H%U{!BjJX1zKnb%#QO*1bRv&&46DD>_0L>pJSTKGM$jv9Z}6I zu)MQ=`M$q1tZ`AF^YN4knrHT?j7{r=_k#JFi8P?GK+F_p1qY*H`W2NOOKj&SC@}!2 z%oF>|{Z84=>C5~J2)k0tfWV=}hvD4_XW0|;%WIfZe^WzQws1jp2zNnG*7bkkQYy; zIAN^fd}Gsn@{~&CY=SeKB~gp=N1K`Y`w+601lgS5&?@VR^jGP&%@cJ-MrC&2MMITJ zvem#5Ly(-nPNSMXgAJDlZR~ZAq6i5{_RUgcU!SuPbDG3>;`J6zaA4V|Wv32Ar>TC`h~M4(VO8g9j^J25`tS zpg}+;CPbj2$opLEF>x4y-$N;WLw|e%5(@&j5ZM!-Df1Ki2J`$sCE4&m@}{|m=;HY( zQz?`efH3`g4>^#5BPMU+@s{qj945#^=TwWiyRzM?-VQrU-w*D2toz5}SKy!|x|^(> zeqkx&li{Tlj_B|&*1Z|?Lp_l4{`S$=EOQ3ZaHr#wFuFD^Go=}qOwrn{n0$Zw_g(Qg=fPMurd#rG9_pHG}zmly@lpT=OJ669F1|CfP6y zwWrqRiN^KCfN~h?0dOk=%f6_r7J@RGI;7z~dBcjKCHZILDupqgKsrj5TFG-@_jNOk zwV&`=S6!Y;rM3DRCZ3#i`>|T$%T0Rfkhk>^;4BPojoHiqm?ECe{ZjkQV$K zU&fkQQ2-q!A$TpEZ>AzCw~jgfcB$OP^ow+x+xK;F_ua{AybK(6ex&~KDvN0WpapMW zY~;9VugUsBl%f_h0V_RA#_9gX57wwU^e8J`0_B0Z%)i@_FQ$y9@QCBeJ$i1Ob3g1L zJ3LyDU`-21N5DY90vlC0%{}t3czRi(5Gsu>83FWu!?dCXhd7wG7WI(a98U+1fuw1r zY@nomTjqE6RD?Zh_T;J56$pD2@r=;q#VTk=T~+f>*DCTha;4fhx1>n^x4yLOOT~EB zt!HQ*J{ztoma3f3!m&T1v)S4!JX#K1gT(@_NP!&imoS-He%SYO;JBM)q_;EHmLK$T ziXeB1)!5`FoTpwDAD`gC>QgmBbBjI-{ch?iSIJ9C8h)svY6`mN4;^Bz=v+>6WlIlN zGGXs*Pgr72b81f-*=qH061=%oq~C<`sekDpupyKwRdw_gXyQz$YESt5g$b`Zgv3oG zoa4At9X%!r59g;MK1o~zn-lV8N&fd#KS$OMjn9e@5A*@_Ea#p zbHj&AU%XzW0}>Dbfa|Avv%WBd+MbJ}|2*H>ygt{&T$1spTVeHA8p4c2OIDu}_WoA9 zr2WgK8nGrGxXK^18}MfrSEyn*fLi=|SN{Iwry%L0#&u>s7FQ@>fgZfd9l@@V2Me3vGGI)ETqXe_rwFzw z;Tp|)#FG^$+P7HCX&yUX_%c&u3RCpj+8uB=FW zX4x0|(u7IM0!eFkY#GT+2mabz(6U*#ZPkAG9|quqMaW%f4h($2M95=hLF~2Ue%hM+ z8>E~5mv3LjspGvNMHk)n_Ac#Ww}rzrX0Fe6$`rch>uQ1lt@0 z%5KhaV7G>j|8P>2+G zcmXGaianRP0ION_%9e?pcB?B7Rk@QTTDM3wi(5AiYE5@aQq0}8b2D#hE$S~Q)LyeDGX!Z zIf_vnkHcthxmZGfdrSvFSr492!>){{9rM1=s8TX3IGsXB4x!yP#`L&h*C? z?sML~3EIy>!hb_GGyRG7pKj47P`TZOySE-#;lg(k=HcyE0P1(u9Jrewyi+T-Wg%69 zK;oX>J$%!ov5>0zuH@ZH+S8P7ax71yCF!KgvBnUjOf%}s{qis$1`W1;xktbyDuSLv zY`JQK$CKz-9&<7_pHb!iGj`yk!Iyl{AcU0?D$nA)A{*7p8E`)Hp_|~+wDRbJNUzb2 zw>liR{%L_|I=`G|KFtG~g#L$F3WJ4WMR}bxh7nheg1VGj%N(tK zAfZH8P)xI1(2y$dBG=ceSzu4!AY=IKn@kmOh8B2QE6x-{;-Q~j@Ao)JG2027i5+JV z&)bm%X*wq{vJU}^164Pd zQE>=EE>AHAIYW|CmbK@7&v|UW**35#eCiEP_OFg*SNm+Y`^2#1ONP%*X2$Oy!e0TT z+E6)wT(7F$02r^1ZjR0kgg!lMluQciaW1sZXdQ|o5s`1Td{Yp|pj4VRW%#NhV0D_% z3zxQ;>E(tF(jvzN4q5;#kPrxF{sxdb7x5z@4>#8WwqwPrZ{1}4!XiQ!o*c%Jm zy#5N(PYductAA8-H(8a+C)(uhpy~#rg~7rQ2)UgwsJRKK>dna_5nq)o4Bd%+tK(Xp zrJKsiCy50zf|1e5t9y8^`a=2q5&6G^WjM; zMNWkj-Sy86-mVXQ)4+pfy3L%+EMTK`@piu)KW~4;WNc}7dB_HQ1ukGI%%O%kIkpK>myL)MP;4)*u^$W)L@7Qt>FFf0NfaBUA{GaH_)BZ z(~|3Rjs3s5zs%6r?ndXAgTPT4FAn_P%Ym#fT+T(u4G9c+6?{N)H8s{8JZPk(I{ZO0 zPx~d~M{v+O7v1kC+q7QY4>8mBF zQDwaY1BI8Won@rIa@WH)_${9UIp61>eR#i+ankIO{Rbv-<__$g7|;W|gg3xs@5%Su z`*c?R=psEBZV@WkywlZVl7&)QHUu*ZHl{g=D+iP{Pdt0Y>qT@J5VVqAX`l3u`Gr*i zGptV#^c)L%aL^JIQf2|w2yBnEY?^2GD^Lnkst7^kKjB5apyqK(;g@%h5n-^$9$3qF z7t``Yt7k8A#kzw7U>EB>T@LMC=S-AH&&f;D=?%qX- zFCUx2Je$;}yNOX9`N(Ba7q@|Zk^-ve?q?j^3Fhql&Riqy%nud@F4vhlbUlERC=B0&!%*M*(7`EkKDik{X{6$N&Zs&26QdzCleL)pldQV>`mRDSc{P_<&x7^xGx@=f?tP0r5klAgV45qF+ zq(lHXI{<7Ibm+#=$?AMZP zS8;rs$(nm*2E%jzALO*G%>wqwh2@=`4kUZMqpJt)H(3;94=HPePpGVrlJmaXFZoa= z2pBxc$)d`0(foSn7JlQ7sw$QBB@=cUgVaU_k5W^U^M5vr_#ul!&hGU#m3=Ye>o+Xw z%-xOz`maaEa=6>47O*|d&{H3YgY+Xd68H;LIOBeU&6v2c^p2Y}hvE3?d%+i!4Uwg@;wqLch+M<_dt7-F8ij1n>0OMrCHsPpTY6 zZ(d24B2J$KZk>3XaAtqI*p7M5(Ax{4ruv2^<0EYvUGtK9r>{qaJ*!lGAyJrS0$&_Iqw8P!$Ylgg@Pz9Dez*eBZ zm+wuAT-6(4;y!#8U-9W!~ecmzWj84w-;P%W? zrt#j(fecM`mD!uvC&x1Eam!LrUz~sJVA*CXoSwP$V4@HDOK=-laJ7eDvYo z`*p+c$H_6OC#=~{JQ{Yl zyLahhfGa#)e484Wxqg&!jAUYPoFqq}rw#Ay`L(+)>xRCV`Y*2#mL#xcV}JY8#}mD5 zof@K7@w+WBKZ1AUv=M;vqpl_!`bq5S?}KfSRoDB2Z`$1`e}82gM*tQ1MYn%>v2 zeaX3$pC@wuk>~iSr7m!`#oy%tkqmd+^rHTYN0ITZK$HE0TM4iQJv;>V;jTBs-QZlS zIApNcxdHt-Q>#P@e%!&^Vpk)Hf>iNiQ z*I6b{kON7BxF+ttzf}T z2~$^fb>Q-GH#y%93jeygS0;@@CujRlmJ8R$u|wJ-SHXYYvb@r>$d6f48Mj%=q6L>E zrxO_YJ6C+z&brj-hoj;$b#*h_n(EjsjK>VzGqf#BR33mn7F-$-mQzU*+RP|T;=Y1< z&A8Yg(uv=2wdt^Wxnles{DXs3$Pcsl4+(4D-FAN{M-{RI2Sas+KNQ{h!#aby58;hL z(SL*!RHfwKye1flQG65y@|v|tc+nK|oazW({n}6a)PJmAie(vnTG6dHxQyEqnzGT^ zLXg#(Q0dVd!zc&8&?A@)c8iZ8=itd*qm>K0k-X5nK5Wh#gNb@_(ngrE;Na{p z{RUjGcj0kqeIny9BVfv97^A#icSi=oR)nKvfY-~Lil?fleSl`T(V*efawYF*-!hM! zm&sXvcx;bg)HNs z9tY0JiV7FopcB^$#(#!hAjy9vz&Bx@BCFNWc&?t!6E{X|ixrtZoyL^3yX-+ zEj`cfI_@n;ZFz{NFZoAdD)_b3#7E zTjND-Xi8Rzqw`QpMr%qe_iAG};4S4F5_@S>7fz=8c{w^H*d#Wcj$<6NjjlulX4I9%$zTx!tpxvkyyp6CnxCA6?|5cjH_SUf+8va%xnT$Btqw1w%AH zv-igj`;@%N3BB{C&LDBr^w~>P4z(ox^eXA~7InDx2i7v^Q>-4}ONd{~er=au!x-$c zC#HLRTo-?7XK;$L=)EP(6gE0WY{!W8oYeDMvv2Re>cb)`@lS;{$D&uF9008Jc&#(> zS2}Q(pCj-s*JOjB-Tt%xCj`=9dXpII^xd=WTUbQ^k?mrl61@su3fE7m0feW6n}i@~ z>Kp7I8((s6#;J(4!7x7}#FBuF=f zhDFTt(2iMXt0wfuk+zA|xr@Y0p^*;inJ3@lQkI`= zLmh8BcxdSwc%hX@pC$1TI%(18MCjNBJRsA_!G4k|ETrxPul&uvUfT|*T|s{V8iI$b zi+Sad)UbmlU1VEZ2WyDV^zIjFbe%Uu|L`8s*OJmGWdCeYYnIGskGzw$krXSe{x{5PCrY8uL5u-hxkPWVyb(S$6K@WCQf%UtrYNHBYhH13^5~ zTXfi!y%eNd!e-oMjpHz~Da)^$SRw^ZY06TOlwq+6P~cHf;kx$EvipQCT>7`k6sh0Q^)?&#bM-Z>Hc(FrsE%tD=h zUPFI-ywnRZtalF`Dk1*dZR=W=EJ~4C%s_0NTdPpv*u4YKHsJ4u)h79TZB@TMw^ooc z_se=$ndR_Rfe$3(lz^s)w>KAU=*H#C>1kfJUuNx*5p|S9nA1PXd*qg(FALx%jQrH? zp5IBTwKd%2?x1&9%z-lBLbXc}{K||#zA;cZ;%%2{U+a#;w-hC`Nv!*=l`iUQ{wG2? zPBoPNA*`KfBIlY4u{K|&QFOE-9*u_9S`K}fL>J>vKz|!kr5}!hxkIEc^8~r?5X3#b zS>Gd3IuVApF79m#OlK>rvf^XXb%N@S)7gF1sDUp zGPD?)=pDLxpNY{9-Z%WPl#89_KV+7>a)kq504OkL2F6e{nHOu$%;Zsna!CT0=F4~z zbCzuNVI^d2BR8T4DPin}k+(k6 zaB&zysCO7fT-)WF@*~{E0spSvF$`L@C%H&y#Tq7p-ye)9gp0jrzeIanS=soF{U~{; zFBi4fND4`>(|K6}09E7w82IaQAcWH4p(=>`pagUeWeP-xAd)>p2rw=Tt6*5UAXask zdN zKISSDE;+Y2B^!&f7`2J{Vz$S#=eJOd_`ke>+8glF7u1JAQ_niG@OTR1>=8!RjxHDR zA#3-LVRtlZjetnQw%z9U`qh7DUBM??2@&rCF1)WUB;c(P-3MjfkEJ{;FZy_O<{=xt zXm~4LE0!-t@%g$o=Ba$UKM}kS~G)zzZxptPE(D*$U>o_p_{~1*Nk^OSzXg^o@TV}J90a-QGONGVs4A4_5-9EL-#egs~NYgWk!&D9s^Y?{wJiNOn5?MUI zxLf@DlZ{T7Z6Y*NArQ)Fyfn^F8}-(H#1t1HyFGr9J|)?I@j9kD_iy0f94Q!+5V-RI zzD)yX#G2-V^3Bt4ADYTJ#TiH7Zn@917)|-B5eoIG7(oWN-1{3*?B^J-{Nj|h_Vk$2 zmKFf|k6ww!`y>CR#ai|;S3bBzmHim#v6?cQPRFqo1k_t%1EdOE?=3BoZh)yJ%>rn- z(Zd`qi!DpFGfO@szP7%u*@XO)&ak1tL-Qhj&Di117&re>B>tB6k1asNKKzx<)F`$0h0aGP}Xau<_rZ=i{NBuJqEW7_EX#F;VHZMBi-E1=o`*t zegz3B7p5TpuE!H5WA}r*@wpGUKv5;Fqe&Ti9bJh!ooXXf$sXPFS9oCc6 zx65`xQP}C1k-}`^2yc|%!Iq1fr<)IFmqamc?0bS-dN5+9@!Z`m;W=;L7jbb!j~JM{ z)ox}@@D$aNSaM<=Pd2eBulMVtk_3|bs&Cr3NaxQ|9r6k;X@yK;K!%n&ZII%E%ewyX z()48c32;3(b*J};Zsb;#zskx~{wmDMAI%asnu%HhSBqrcSLknPqQ%GL*uEeQ{;eV4 z;EN!jpbngJI7`6X0|Tn_YJr>O%XTG>G08uw!3;gtmQGU1w2KntKc#U|bPP+3l5k6w ztTM3qu6z3yY_Lf}YxkJ-3%|2a368HmY}Ne9wK|X3dAH$8NW9c@!rMXxp2a>4+74Wa zgtcJpj8xzVt~Vb~<)&Qjskq{qOC*@z3w+4=lXsOwrkNAjd@lglwOqS{VQ6Uyj7H+7e_OHd``)EU$%>S<2_4wGdlTo`Zq5|2S{-T#&0;(BcMxZPyoIP z2efLd9voX)_;qv`qS7@;)uzkM_pNC+tdrJbV{0cG?+D?QI;a9><+Trvz>-}1ApisA zP1ZKJ763xRu@&0hPVJ@RABhHIHzG^jwk>!Z?vvMok_A{@F8VjYBpqsU;a+N8( zFE=il(u1{>+QF!RrI9AAGw)=?NO_giZjdgu-0fP>`(D7k7(%k-wXbV!t7C&9389gE zR^+1k(^47VTu8va(@ioI_g<{G;x2NRFy)C!2a*#d?j0j^_4oyh=#iP?Qi_>M8>%Dl z)41P$h`PL0)T*8_`>n}D-j(?6TF?(HN#0v$K@j7OXYXP}xn5be0SuOUm}w?f`_L1Eznr~={D+oO=%3MKC-2n< z#Je|-!=?HzdA-7^L1yB690&Gq{odqJLPW7>$3zl8FRIJ4OeYAaF1!3qPfqnS zXx1a5Nu~r&)yN8XpaFh6sjHyS-WBo_qpga;*YoOIOgJ>j^NnwL$-~@F-p1x(Nixks~8yS5Br!ManclV{-fphrqK4 zO~bIZlaWNB5xDGm&3RlCI8+lA-+8{V_|B{!OY^8pYPw(@qgJmoG?Z{7k28+cPoH^( zdlS{9JJQn50cf6{EdaX9fThVc-1}zrCn#KTmWhw|<`3#Jdnx5&L%7f&-k!5DMf8L_Ppeg^gB#$;cMM5|f;0G*oQ`Ri?D4063Y+yy zn#tK(-9$?I))CIIw)-bM8yLzUk>sV=J=q709dEsd5eZqu0l?WrA>-{)sg+GcRb`*# zdvm-@=?KOwx|KI0;fLw>`4CqeBHxPD(3kB{c>%CB>QxSQ(f%~a67jRxgBrt$gUQ(q zy)h`2572O&O|MCn#(HNqVrA#fSOE$$+i_KsAf^;taVcgW#66#0SFpUqq~2I@x8=jm z@}E?l`1IfL96n}0$|(P?+l#`Zfk<)~UoB${HYmPlN0&F|_|5*7YHoA7tBBg{a*0D6 zoYQtTq);Z0_N-h}_| z_m@qEykqq2lZCOlwS&0~qQVdgx$aE!>Tz{v32sOZuLS_y`&Q46pX37jSHG`U?k6Ia zR#)Mlwctss%81rjqWr#~7PUBU3fZ0Zev}*ok3g^mgcon*JFPUUw6DSfl@ymkD~Ss7 zHSmrQsOrkvg0rd6n&g26Xr4s3eLIY*#>g_7q0c%$fvLI5CDe{z%6mz$qS$iwh2X{; zujVf4G1{jr2Py?8na$iq=$x`kEsk>|nxl)yS?p$3LAny1JNjaNRIS7*hEu~>r-44tQsCUq+{4`KX#o70+ep7;9kR=Cu$;B z%o4Zi40-kpg0t}|ht#Kl$@*ojJSawt`Di@whmog02|t1H zo$sEmHYhPPlZG)scqmif@Z-u3hStS*&a>3BijcuVz6?k`E7TI_FTdA89s#7sqeY=9 zOQtzx-jNxxhsaXTSxKedhP7Frc!YQa$d532(h+~Q8<<2eq~K`C>fgnPXz(x}bTQaGb%O26V%#T2^Qs>E)6n|qgq{zdbprr&f5URzKHyir z#?$Ko@R)OVe)XJ*5qFcVk&j-DFE|+ayZ^UiB838?*J#lg49td7sOT~mh9iY9mjUJE zy{VS6QtzALRYv_K065RH_nwa))9stb4+HH+kNSA&}SdZ$+ z>3AoXLp%!6wrYMMvM=Kf@Pwd;d{RMTK+-RKeY557bhi93zhxvt0@LxIeJ;WqmKP4npsnnhcEuHbgisqzn3po={~$!`t<}k zaQg7oZ1!$L=agrC37dOIE7lWgvKwCy*`@{?niO0%8y))6mq8X#VCr#b^Y}y!HGQUg zT;!eiaqU%*dr($O3g>2DG4d~7wyNq*OBPJz0b*A<^T3a!xS!XL*k8x2{@^K`?gwt2 zKiL653Ca0f&yfjXb{X{kg8=x{j|~S=zJ9*7+-L}DKU7Fc+)9G2Ej%Wj`oSvg$?!KU2mA;M5A z7bPkqczYLT6PcBtHFw5!!9HVaHo&`RRTo0piXQ`q74Q}O&JSb>8+EoCijPGP zKuYTB8I?I>^*6~`i|QsBjE4U z$;QKhfZ?-xAE!CmZA#C%mvcEz>eBdt9ys%v8ZvD)%j6!1A6bH98>)+?2kqUQy*CS# z=|8b(g2@#Ng^3oVla6>Bzm1Nd+Jq6T({(MzI_GrgPu?IeTEXI9fiyV@hltYN0@Ft%@~n8AkY>8AiKP*9wS3y-C&+CFBeJp1 z-R-}e;0di#r3}T2E1*{2Ek1#q6IWf@60vqAezD*>t|e!K_)J(|gV+61U#D9DS1uvQ ze*x6NhR7|Q3{N$06<2F;Fe;{>Fm|M#pj7r8z0=hjdex1=TmyKTbq%i{R8=Q40HJ1( z!6~b)>~%L_*kq$;8xe^Q!Gzf3Vc^Uq(K)W$-}SptnF?Wlq>|tJDouc?TYJ8oS`=yd z2Kr{d{a3Mc@c9xVc`{fyW&!XYU0 z%e=qsBaTP0wLtzidor>09gdmI4c;!7oGVQ(^d>^3$2v}`jb3+Kq6Yq;Ph=4*aR~Dn z$GTCw(2@*~79i-W;-LJPq%=vAoBTcqgkpkHV)A~Br-R!Cn>)fP0G@g-n3X0%x+zzeq$IN0!FXmcfn=s zR&P1abi0wdWQdLAT4QL;ye4Ap7CDb(@C!Cfr_!y!S0fB~wx9g=VLX7J`3H{GbMMKb zt(Q$+dJ#5`N)Y5I)_B(vO}UqQ#&LhkZWb~}!`ru3{Ob}?+*Gf+nCD3)g@#cIX_x-l z4P#5o*lz~BBb(siI;+lK84)KhHv`QFEHBUT9cEOi+b=l_I5)U1Gc$uI_YOuS2UPn-)FHxP3Y_SKMT|z$owAQrOzZs6@x0OE)SV57wi?te~ zZ$SFwrRIz#r6+zGDiR7-0Rq}yN!go)qst*X(FrbTwX^pV80k;3x(`8YG@JGfVj!78%2cZm@%;7CcMD+VL@_M^5Ce_ZZ7s(utQYD(R#J6Wq0Z;PT>U_`xN0KRFq& zKLFhTo$GHN&D&a$ps?;=2N^yNK6ddvv~@Ud3WZYKG(sUi<*Hxo712RK_!u$r zxa2%A7+-?(uIireQ5=s$pQTmKqa7*4lRh}|QcZl)C+{f$4y7xzaw>W~C~O?6I|qMh z@z9*)FJYX3xdKi9At;==YIcspT~dRaJXn&7BBHN;6xT?!H2mcV%HmZ*%Fw1%6zlL6 zwA&p_)4&FSX*b9_EZJR37-{L6L`a{p2n`rSEKqw@{w>sIlCK=;8{_W_8Wv6z5(H5C+G^DJ}97;v1M~1i-)kkeO16XuK?V;K2-^)-++U%5#N~RnrH~3V;B#Q zRKNB2IPQ&aIw%8P9TXfi_dR0cV(tCKDIRGa ze;lYfRIk!AM8w87lv>bO!5DCP?V{PaAo6);b!4sn z=JcwM8V22Jnl-tasbdN)d(*--;!=VCr-U~4kSm`}*}bbnx&VogWAXe>76A*)iNIGV zaGwMJ*OZ zX8wDzm;O1+3_l%s=jr2moU?L_FAE_b$t;vhkcvJhWRWCa&Ubmsn3&iyiL|6XVs?^j zlDi!H_yEqe!BPc)M=Z73`IKe7fj~xk-UVl|I~3j*a+WR6xmzc9zZHQ<^EC37W)L;h z?l++q^?zu`g^%w|0>41#=JS$izYqoRe*ERztuFNCHk&Hy2Z5M9a0Wd+Dyn=@#1~A5 zc9AC3SHJjRYlL)!nAF zo?p+ZF0V-)6)BZIEFYvf{%(+6_5DGpBv{1CxWm!UlJeHwPST;}zNvO*7j^O6y~@x? z^^N*nFw(FDyZe`lX;JKW_@YFg-_B9nVyHO-y{$$j1}{qM`dwNT6Ja7J$4G6F-2*cK z@7A|=n}cM6A>+Mz!!gnpo7vKlNE?z%QNkT7KcbCQAx+CwdSF#Onco^>$&0<2hR-hd z@9_38#t_C6ML9oiIL6~KvVhbJE!pzZNWCIXDkqG_{OH~-0eb;-XZ*vbMmqp95N6H+ zvsa5p5J@6_$^6StDHyySk0_r_iVFQ2y1h5e0Dla# zXDS$0&q`LSOnvh9Xvd1eHoOr%+@Ixtg4{X;F-K(voIcR7F=EuPBNk$(@yZPq)b+Hc zI`MrXYKVOtJWp{A#Y*b!j0#E&6*PctAIn5t3?uYpu<6?+J``|;y(V6%-6M2R*yHZv(g%j9_qcGol+`J=Y^S^6M^tXRyvL7|I5=i+`d$W%>%?lhW-|v399y7A3&WG?7a`mqPub=(o z^6q@aO;oGlX-RcC(tKhz*i?&dYD@M6IZ$_LN?G^rkZp}+8&jMCu`%8gs=FJ18C{6N zc6r%}=%yC0%AG$mJR)uv@H?>LR~LLW?cKD0KQ&+moPXUc=^RN10J|%&tgLC8s#V%FK=vp^Et_ePf&9J22BEeC8xCyp4JFu(M4S zp4C~s>4 z<+BF?1s<$ELz=m*N|qSk_Nq3#{jriK|5M^-)#U!KJGc)cQX{1s`BqO)&K>~*nX$WL zF|>Wt6c1U@_^KA4pxx+|+~O$ob?4xI*g@>R?IN`VQc7BX^+M~lOW*EdVjo_7o&yHC zVbpm^zFV;R1P{mkquv$t(Uj$gHEKoPU~Bzv0rj2?tOMBS_3_SVlJe=nBSp*_$yCcD z=xycG^T&LF_02s_j8x_uaNl_dO6_#D3c?KAFVRH1awOyxbn}cF6GxP2@cO3(Vo!sT z6q~ILQmwe!N_g0-FVI2}bHjX)M=KrQBds5->&ho&OlX*l3F^CbyTMgajvd5U zT=qiJ?f(uaa16eFzv@94Q=D=V-1MBJL)aQ8jXIghza7T}?tBr~`Urf~j7QG!D zoAl!^HH(xMpQXPCKI3!%>D2GRDj11fWAg4ubB%9DIf-jq17mlBl{eIaol2wXz-;0>}D4r(!+@ACkJyIc$r zs=Y`qAxze`HH#k-j|nzjP5MM>5NQT!b5u?Zb2ZYTv|-k0e@{6*m#?KG9}HWds>^xX zozqVDJfaM`6_GL4Z=HG}Azuh1H!UK`qmji;y9M>pXj$20HToq7Hm~|ArGxC`yi(Xu-9tHiQ#{ zluo^oDSnAHMIu*UmvowFB#~ugkf)xPy;1ykE-2~sZm~ZvB`0P~>a4Qm^65Ai_Ltr` zxzXW4Fb3bF`J~`X>VL!fZ}nj_7>USg+80#dXGW;PCZi)s@J-M!t9U+NhsoyA82yoa z^wVDhJPk=P_SY)8oxmnKfv5CR$sN(&BsUWE66?U5#5lZf{?HLV*PMxVdm6^$oEu>7 zV5NIR@YBh}g8px=tCHjjY_kduD<)f0OK^b+VvaEUOoIZiP}aQazFoD14J(%DvZqM^ zYyjN)l~pd@d`%b7gkY^%HKjj8E)c>?Ew=gVtMsQo_M+2kI3)Vi!5<9ijf?`>IrE})YVT~c{xdd={<=WybPHomPv?r%^%=dR_0#y2x9335M zFRK(mmcl|0vo!w+5m?yEQ?z1-C2sYn(5#l6ErAASFzO=U;at?2zos!p62YqcSw56Z zmh!DRQL2DmR=>$#-ZA=5Pmo&I+dR`c-KE<>rsX%Gmbo2^^#+3)mdA zm&ax}=!JqYtBz(t!S{PFjF!)l13i~8{ibZ^Jx0ZgX?D?KJE7{3l5 zVH*?!r}^!|$QV&{uErHXPw!r(QecPyz^kCOEkHtdEl{Q#8?9txZwcP28k2O0k^y8m zw3Adc95KOnm)5UnSU-^QZkx0*xa<~eVYHJa;eMMfHi3@x(=&&WeKYh88_Hf)yarAS zPOPwo%vR_24^}hA13U)h3Dcn;qj4x)r}%lFs~xS!CWm`OTUBlpV6BN!N0m?svroHy zb%U2|buOwG*Z(1(0a17 z3>^aZhC}n9-+=+B_z8N7LJ)uHO!;n$^{^qt=5ZBjVU&pKmZfSYH-3H9>sA7`l%77(toQ0fdskJZn1AF zd@ySP6}}kImcdC91&yC<`6>|PSz@fv8r<9%*3V*oJlJGpeSz?n z8A4bk05o7NccOvOnOEpyQMm3}%nu)B1k_Qy9yq=$cdq?U^=8e`H-bGNvpr|Bb`$7w7pdN{@C)=!Nq z?7y8?S_%dH#dXT5S`?@TCM;;d?_t&hGfyoXr>H_EAk zhPsF@`7pxe+JHxTpiylcxIXH@`}}%z%T~O{N8zvEqTeaRx{fjYBEfV@Q@X&o>6cJ%{bwTJqhzmJ?)+y=-Umoww)f)PAEr>lkNgd2j zBvazfb!JtQ__~Wm!@4pLB@_d*(?kJO;FtW9Q1QJFJ(`LaD#M@iB0)Ax z^(AGVq07*h_<^g-dvss1!aDliH0KNnVD2#YPVCCALDrb%rGnO!#J&0$R(e%sbVf{w zq%4H0k5ERADW5kPHP*Q9n#_frSg9{YjE;`@nwWC>5@>(z{p;#jH`^o4%RrY_^D`Qi zh0(WxnjO5~7I}F@LcThRxI}y*ZORWdZXz`nHPf78?}sifN)(g{igR_cro9&+VH+L6Y(GLsm@ZU}CRs1&}!#1qI{cYnxz z4Zg4E{VAFVT4`u|Jbm-w2Qrn<@_nX5KYC`3P;E_a_d~!?kt3JcMYp#4KjHE{_YO8b zQBjN@dnvsbM}qj|Gq>VZDR=pq%_O1QrcwH@>gSFCpgj)L0i`!uTH9KE-yuoj(Nr`c z&`9CRvXHa3l`ak|I~^co%fHkZJoYt9(;D80z4o8>#|TD>qU1Rw$I2hu`KEPsJAFp` zHF{JS1q8>UiZ8?wGS9me#+v4(l_*V2u zofLEDg&lvz88^OpdJ&+Jq{5TN_8Gc*Q(pbk<;` zY~1qpD=~&`AvKmz7Jts?VE22*$YY&0B5M%3b=^6?f9GD9V*!9Sv^ABQq$*&av17Heh5j{nN>rWA)H zwh_TurU6XiG9v}P61I}deOCoX#NCvA5i6m({QK{g?pqZsynf5Kk3H2Q?2xJ15vrF7 zXrA(Kwc@Iz(om3K&FXNzjDJ4Q)n5QduT}woCaY;RO#Ek@(+LObU0wdliBJIcIxiQH>AZ%& z86$2MGAg89USH1{>qlsoEGT7S4Cx`@WK4Pg{xYI|`-Y_cL`LMq2?k77^74Yx24Ere zQ>>w#^%F%fM2tI$e&T`?i{bGWm+9y&%XRdd^q;$pHE%o*9mS{dBi-j56u*B{GLol{ z`wwy;&(L5B-2csg73LVkg;J?R>x6bV#5RH%AT=kVkf zYEl>uy5A3Gq)4abxi&fL20~>nNR~9;x!+6pdVDL78cEsDDGwO(L(ruW!beAhgZne( zYSa;=(>=sgYTW3?ea4@m@V!#M%aL^T=I#~{a;rDf3iqs^BlK-OV?!W_xW6Ft{nm)X zC?DPxQ%~%OVioYcRWxSTJ`zD52_xct&0mselV;D-hw?aTV@ff?T%~vUxHN&BvQ1s@ zQ=QZep2nQ~)>6)wN1r6VNNL&yi=5Ag8W6|}jg&gYFfu+BdxdO?^uBrLG*?PRgXa~u z>J?j`bHO4U{3Nk$wvlB%zmbtN`}di@?ilE_`Me)`mo!DG7OPi?|E^KAS%J;1`M)9< zw97~|_~W}From|y_lgU#Ac4|Od?=T(96Eq0^8{gAGQn5RO#Nju-!v zQ36WEIq377U3&?bs-45LPQkvoqqVNN_O+p9~^`n?Xgiv$bgySIAtV*<=I59X^^MAmCo6--x|5JEd)jx_Vg&Py=wt8 zcv8VTaw}2`$Z2x_W8art_Vc7U{a4?-t|Z?*y3kCjk1ugpr+W=8Aq9N5Ez`Q&+AygEOdq=jQnMEe4 zmrR33Lq7E9PNO5XQfsKld16k#I^O35!MhKOL zLC0KNgy(C{x5+sl%_f`j4i~0$IbU$~-z7sNt8jzMy{I4;ALnsM(ZVoLG#v{5tL1`` z6b!~c>}XGLL@quBE7r2F0=WM>T$^wh(1WAQ`g<@EL*?HHub2`QtGmxxOVtnhne9OU zs};&&Hq(h9Y*vUS{Mc34TssF$-AgdTHDLkqQG0a5Y^9>CUgwArEa8wl!mt7%4>k=m z>LcEdO?$Q`-RxHXz6Ir=Xu~R3;j7>i=G}+Qv@Mm!@+c!BUP)RrmvTm}vzZXeeo|0e z_fXT~r2MW(p`hKb$!C_7QkKBIF`5G|y1fTDh>J@lW)AYdoZk4| zVZREP!Qg7~(`UZ=)-4V1ic*rLP`GsPC5hGo30Iv2F)>7PhHZE*9SR4D%>4W~E}z-a zbWbjT6J*f&^yUt8(I+ldctS`WLzfUWCblKXn9P)od_Mi2G)L zKyB(%wqC|$oW|g!IekUY);$w;Xb1W)cN>nbB{xmMz z3F*sCkE_D>fu^pH<-{-7{>7&=!g6*0T%ls_5g zj)C#>G*Z1kyG?p;Mm^pPv-J2?Ga=!8_enWh50S~T-o<7*M|5LDD%!h#36L9S2MNI zQ*|D6ux+2ievD0cn;5>T(CwL>@pYvJSn-dr&C+m&5Fd5O7b6jbWabfAc*{Ys)1hhT0aKfcr zHiZVQT?3yvQsd)Py_cMaOd#}{d!!7Yg<-{Mf3m3|SkB8b1z$M+X#pdOWd>$f&of~w zU=a**v;MSjE#Pci1rL|{K~3Y zCV18jlNcjOF(W{;LZY+ac69s4WDLl|yxfTO_;o~sL&Uu_!dbYFr!%Ggsk%wz)|G;$ zDZJ3@a1v%X69exCj@NEkX8$xC#3@(dAwy_g?FsF*1Xzd#`b_gr4^;Y`Sx?w}=G41k zdo)Ytu-6%&2@3W;j2ZwXsr|aIbp10v+sZ^nGsp?-JItaDxabFpjQ&T<7{7yvW`1*4IUF8K2W#SfjbpOE*PC&qsVgcT*YEJrtb; z9y@fZbq%#I!=#Z=sHBmFcEw5X^3g(G`2W`Dr|VS6GQKm{WLNQif*d%u={6g`z+zeB zL8(+{pbNr~dMC4+su{dY#S-ud?UeOQj+`wfJ7V2&RLUnliHUFpD@5w0?9AGU{uR38 zXVH6_5xD+=xWwG`J(#Vy;HDv8{A9OOd(e>)5-|2SEZAvFe$Ri03jfv67ay7r;gmnG zF6df?85n+tsyD6x$6GFf_7RS0S<$>E;RweNqF65V7{?2moEWVVed&rVLRb8nJG#`b z*Z#GGgu)y95!jtFRuoI?qwgX?M>2-#NB#2I!yT4=aq3!lD8dhJ0QhwbRQh%(-P?En z5^s1LCyRg+l11!@?{3UCiNb9%O`{uEmx6&vOmzwM(0XPy838$jPu47_@vm8Se#T1R z_qa)mPkZ+q`IQdczli*?@(+mBDw7UDW;?w4$Q2B-4Ezm-1-wsL4usrSLk&^>;RIVy#NV06kzdx}=-ET(sHS+rDCDk~#s5DdkwqA?6zgcux+4}!EG z37LWkHs0?tHKw9_`uC!LKEAq!r^TlGXKLF@vLNJBnF}?rsUvMSVG_NoZ*kN5r>(2} zO=W>ivDvOXFNdcs(J=naU>xb@7ZvRn9Rj1w@|m?iR3}Zs)gpY+3Go*pQW(~n-Zl2i zQ0_a8WS8!i`=E0cMhqpo1bG=2>&6rYg@%ucd+B)7=7(~r9~BZ_eVR4&I<~!jNx%|} z#3yG?Ez7__5q%Bu`aZQ%UhMtSWLZl*w|3trB-YO=D_9ots^`BRI%t^dojR1XNHZYaEg%l4 zG>9l5Aq*|up`>(6i%5sk64EWr(48~;-TXhlAKr7;v(7o|JkMV9X|I`Cd)@omzu&#D z`@XMBtz@!H49b(IeKmG8^ggRugnkF#cRe@z;rO^?^L)-wBRP4GHaI}X^f0JLO71NZ zxFB5sfV9(WccfZ9EM8<$|K zdjWVU{;TtcTrXDs>CjyC#o2v1=&|as$O^Yh$GcAu>1QUj9$MKNgm9bzn4M|GWGIPHIP4)56W-Qe%;>z*W=iXFw7a)? z>RE(+=_g>X&`jJUbN=c1F$@PU6F@9JiC#)N7zmo0nx`C=tI*gdGuZmA(6Jq#HoR`W zgjM|+FLn@ZCl&hwSiN)_YH+MAo76SOxy5`;(|PjDiNwExM^}SBMk04B*m$npG?~E1 zGZ0&cRNq2A8Idn=8zT1(pM`sQ#qCQPvI;h?PR0az;&A*s1chO$BY47WF0!dO4dHBm-RV#ECf`C2yV7 z!dhVv7^f`zlaE+$ZdSQJzT|{PT3*-=Z#Yo|+*qto!ZtJc^@>f|q_8c?u8`k)tynsd ziI{iZyb@oyuzK0$Jq_p36 z?pXZrX*n?&h-`eda2X&enpW)P{zSM#4F<)Q#k$NhvKlXqYPG-D__adMFqmpj3vl@b zpnEY96T4qMii)4gi?`xJxVz)$jX06>b-uWD!KzcuMCeIxb-lpSH@@0{`ZCIvex?9^ zY~7Y3s-Zwh-o=dp_BQiAh1SWwr@qr={w%TW%M^na5NS1M4bqmFH$FzIO4sEheLvt? zS#!p^6|xYVOKg|<7tUC+*ChJzM?NEA*>CQ#zqK>@C<;2fZif}6#=AUgg+iFc*$WQN zO(_b_-vt|2xlg9u1a90H8*Oxxk+8$s!nFi81j0kfl}ZKFW75KTKtV%BSaWXGe6qqE zVHnN{=mI8?+wh^e<9tHHh36++=8|sfV0=_;##q`x=9b~I1ajiw_$-kQ?5>H7_9@r- zc$9K`25p~!JIM?in(QyNzh$n;Nl3ag#yCdu*cjb%HPfl?Cn?Wx|Flfi1#=^e4Fu2WXgWDlgQICIpvQ+wk|Cn9S{KHh?c_^K4_+0o9= zzcXaN5{okGMFLq)j1K_d;LOgY+0k9btzna)EXfb&A+)%-7R?(gXmtD4se!U|l!R&D z)#=qp<|W5+bBkdC5;&>pttl?#Fo!^BKk!(yFhjm*k`V^+DVKjOQb7e@H}w*BX*7G| zGpbjO8)_QeY!5S_hoq^N7oPp%{WiODtj*iuoQ^W<>6NXSL3S>;b7=*-GX!QlRp>)l zOp#8Chh>EbY2PqaS!on|i%PK5+TGA}Z3*B6t+01N_n!J~P}j?@F$L>tGlwYUI0)7! zBD2st>eWeyYG#&y>tpU$L6Il ze)~Jo>@Czq@CXifj5A+}qSi~UT#CE2rI(yi5Zk$|$@R`AI?c)pR(Qd!r*-KwTOP*( zV_1sbK@ae5fW!yt9mf8miP-BRS8>MC&Z7zfxjp;w4(3)Qim)LrxyzkGjP2nT_uoF&oVKqZw1LHi) z<%(ZwhKH8hX&Q4`FZ5-1Bp_-ARU?#J%DWpw*Dk4BoX);p4`E?lRD33~kFm^GH57a9 zvv0|esQQcTEiZj}=D3nc9~JKAoN28w02ZYVJ-F-|JX3U?2-u-gUzDF}bzwPi5ao*e z(ZB~Y$n6B|%J!)kbIls}gsyqdQJ+zY2>MU&yzN*^g^lU}rBjCQh%kvSbsw2#%dg>G z9~PQJGpAYKg0=wM87SI?*I~+PkeC)m?|Jtka#{6fE#W6(f>YVtVyTb)UM=J$cd&?hPe(u&o3N*Ok^$S<99#)@xw<}^E1As zVS7BGVBr2CG>e~Wdu)sIKj`rE#`;JSp5-C7o~YB>OIR%8mp5%}D@Elzi*Pci7y{iZ zFc_iE(tt+f?7|wGcMB3ILL8re`(5WSu9$0HfrZ4qh^E6W$Ynhug9SOR;fkp>2S@Mb2MaFKg9I=_PIq&T}py6V@8`viu zFcGX8?Y_A)rn&yZSyAE%+x@62Jz9eI5T4yaiEF-%_ z?cP8RoFZ#A((;Ig4N2hIN#WeS6MEN7evQ4b^{O0Jb4*DVkb0$Zk}C9ubS~q|^cSMD zaAe|TTISh0W)%@Zad1f)muXu2b<)&4`H&!<(_j37T@}0SC?xuwE|s;VOcjlr&sG&T zX`v7jl~eOwD^UG4z)~>d(gG5|TWC79R|b}$HpvDWCNbFcZuc#F)&Zb3mg zTDm#1TjjIHHaU3-uu5p-@j2K%DLOF_kLSX*CRVmPEBLz18%IkEyVFP3(IsPyRX^pQ zMv`S;Yz-sL3l?5dQCt&mto2)A8fIea6*;~qWJSWqp`Pr-GwhKc_RT~_*n#ZR~3A1d409#T5~48GfD@pbnCr{6^C{)gWCx0EnfiJS4G z$)CXnA+-17x=^r@btN;oTYsKQ$<@Hd#Uua%*^;fKeY&Fyfu|1`+!=a|Bn!QB+~zmN zBfV$YIKbsLru_LfVPQDhG*$}$tVdyKhs4?32lqf4m-i6BWDXS^w$OSer=k>tLgK@c zjQ0cOHC-q}CFJ35?00vIAhFwc-%J+m)#wTCNPJBCsj5#te&VUKmAMkfSq=gh;}V$(?f_&l8^6 zv~&V>*3cxOt1?sZ*WUm=bd!Oo`{NMHRAtC5w@z#FZ^AJG5PzL^`TguB*XKfU`j5iu zo*n)kUSkPRSA9UsDI}o?WTnd^L1U|PEt(JWbYs8~32Ff_ykZg`(&+XiokkVHNiycXr1q4Ei_R2%L z2op801&#(VoglUDtx}E+(@zyFGUGOe%<5Mau`%pr6<-`*aaU{-1jZz7-mG$9A9}>| z{)-SvX8CTF1pz!4=wCC@Rd5*dJhebFp7PVqXil(WMEPk6(Jv&Njf93#IAst6_(*-% zYii7N1tN$}oIsuB8>w|IXBX>tMuCrOs-VP+1gr^?%1Y~Lr(a>LWF0Tl4drHbyBIpN z(bRq8UIy!qt1&`AT_5_g`ArC87}8=7ocRD}>Hs8ybJ^f&vQa@$x_T*FquS#iG^P3y z4_Y58$8+YeE0)@bkfPpSc2DnI-)nDr<29nvUS4|Qr1Sj!QZw1slH&=`b%g{lPMfP_ z8}G|I{h!lj+uBdC5zG2E9@eC>5)d9Ag{N6ms?)ZP4oFvt|0w`2 z&!y)9V7RLjxG+Ku*LqSo_prxO#Ig(~A|FLR6|@s`lb}N_&pJBq)q{|G0+}F8F2TIDm#Mm)OUo^ub>%ZZ2MZNV zee%Jep#d<#%w#z6^t|gf{#RtAiBupLad(D9g-!o8l^Ehwp#kT;l&7CDMg~MfIe5a7iif;mpaltPj?BKEC59ZJ?EQ& zopJ1LTFrEWP&pGWCc*^2KQG_ZB;5|RwIDK@I+jXYS@=Z)&WyZ$H4DL3eXi-j%JW7B zsq0L&LJZUZ?dsESXK+zDox zVZdcXRz2aj60j(5P~Q-=w)nPsi{ju}=)2G24Of57=8MyB7mgo#>kQ5Kw4gs^4B$Ta zf<(QR2O3O^M;eXQb4$OzfviEy&FqBcG|oQ2_po0k0H7{XMe`$17rZLF{XosxFg#4g=5Mo&OK!8zDDMp zzw8fH15RDGr|@26=y9MTQaetXo%daZu5%7KI?-*c@E+q?SG z)|?AG?XU2iy#(@Uid#46^N!8KLPlxl3_dG)BTr8b-80Jn@_}?(G??x`IJxkqMS!#D zNn0K;UxNATKugFQm8iyqR|Y1d=?ULw_D*v<_a1(HPPDc7&CbqHH>tU0?{v9YeO3g7 zC^(;XaEA6#D;HGxmgl4oXJ$#Z2b`Q$uTF(mJ>G>4ALMz*{gATi5A?0=Ul%Cedw9NX zn}P|G55T!HDFftK1OTY3_!u0oP{ga$(S?#>+15u{g-^!FMZ4zU z^x_XHFuu%YN+@BF+^+3wD9uv%ASa;YFq>Z^lA^*1zQ?C8QD-?l0Yxr17Ouu5dx`Mo z!xS!KQLSHRn#Z@um~S;@qEy=}f51ju*ZYsM2hIJVuQzBE zFZ9NT-IEVAJ3xRVGuNU9M1twBbs;2jUoUiI6VAnOG({rV?=x}+1T8#dROL(}3lKG$ z`?&CEG?Daf%MMT=n;d$J8|Rn;bXY@>Bd_&}FoBkBu@>on*GJM=`qKhX_@COp?!8-I zTAQYospZ!{LOJf)rU9pUwDnR1znu*WP{5T8=?43*F9z%?mpNR>aZ>xX)s#7Df!A9r zI%rOUV^pCK_KD{gxiaSJwpL!ow>8`sMWh4g!t>EvAW8Di#){BZ+4Pr^)d<`4=6#?Z z@)yoq0PYVLFb8lu~K4qm|R#~|qHije0)Pdy~ap~hp4KW^0zERKeV_RTk$Mm#74vXDH zRo@pv{_uy(13CWlnV*fcrWuT~_s4LJgsqac(-V0gcf=C)5U}bWi`Z{4ikn>d%vWQa zk5%}H^HIwF(;+fW*XzGQu49>91h~SqhOS=snX2`dgDx z-bYS3iF~h^rx<4GOaD8V_z|8mJ)c>ZST7#eE^9b+e@9wg3)6C?8W{FS)E;-TB=6LN_EgqeP6P{mX>d3N-9!%r&)n3e*P*RZD9Cs7ao267-1Osk+`fy2WuW6hZ?+GMQ~2y@;{8^egFMvp?q`?argQu>HkPrMpzdaWgW?psRL=7`smQ2-OHuUjo273x`LIl&o@V{bS8 zoj1C0Y?ztrwS`8mUsxNp?}e^1 zg4iBa}= zHVlS{S`Wc(UP<%oPjuLA9w2{whR2@)$QIGaq4%M6duTCPS2JT;>5bkirg2wFPx}qi{FOd zrM5F3zAi#4{l;o0{a8hCY~Hprg+N&Ip}@l6^1{T5i0^HqLI}eIea*(2I8LAVNH{w# zc}Abw{iF2=+W{9gi%nW{S9X=ZJEsx)uEZ@jklTS^`)Dina5!qK5o~PobiIW_XE^h| zl*yu5ID|P8HnLBFfkkpFyxWR6Z~bPbWJYst%8;Z-5?qjwT?pQzfS89IYKN(4o--)x zFCJ&i(Ri7MqjI@nXqw))M<*^+MK5JMy?vS#w4RcR4OwndqZ3=Q@(vM~>E(PBYe-o< zalMp-3R>M(`V7n@T|vFC;UqB_BOH&2%`6fIB3@u>`s zlf{-xk+yH}-ET_~$iX0iovS1}=Pn=@Vo(Hu{3Xt=k^gGS*)&_aY$^j~OWp{5FGy&~ z<-Sh9;Ni?O_Dj_tIe;m1%nW9VBeoPRT*fR6a9L*v0O*qwE{H~00{nGNHi2J~A1kFB zE0?5MhPC0ESc6csIF)W&pL|$Nl+$36D(D+Be9S$n>s1u_YwZdNitYf{MNYjo{kIr# zM&_zHaHI90)=}|AczKeM^EG2`Vp^4O+o=uXU-EL%YNTrek0X|`|NL2SibAkCDz3lz zV9e9eL{Q&fkFFS|5 zD#N^d2hexY0)S4lxfNzhdoq^(Eid0#LgTUD9|ee`vW#1dQ8X|Ib|yldgpQ?rKKLDL zoen&@W59_o#GPQDlL(*Co= z(!zI_Wu6!QS0eTm*R*$PMfDSr?mvVTTRO`wWw0mvy`Em4A2Q)}-JgZw!GJJi-?q#VMb!cH8Pp>i*4^Hzlt*Z4hi_ON5 zism34*?ZEk^#=lFjGGxPrP6C9PS4g>vtyhw68LR#zL;lxk746LMF<18l_$PO9=JZd z$B0Q?ReM9$c;ApqdKUIxRrHLWcR7IRI+Fx5O$iB18ONuL{iFLOWyPzskbTkO8#ksp zG0Hi9x>>hFC%H~kP-ir#*SNW*u3^JE#3TnJa)lh^?nD4{m|$$ns}U?^wt3#CTVhk> zHlZ!)FSTq;)^j*U$0@?kJl>V)zf0h~r?gY+;%fKFRG2R##^pzNC&uqRfO&$9NIuLQ z&atDCCB^l(9QCDb+8*qynW_qCs4-}sp<_kq*mA1KIm6vl=yx^>`9qpB-e);k8!sDG zh2)4p?QcBsV!DPCKp2 zMg8!u``ztFlDqa!$B!fo>nv5c6=t z(O=nMr%CjhdEgfju1K_WSUqL3e8-{%w*MG|dy4yU(XNnnL77jqL-+=#UBy$2(dT6e z$5)qPEkcs!dJnj(2tqR7tBaVv)I?+cVVngE2(U1 zJKF23v6^xb31Nwb^w*e@cT>=ZFU2MYVJ1qnjXin=Bt;8WbLU$|ZdCyeDC|A~ZJ#tU zp45iAvDXN_8T&c056Le_FV_+wb;3!pC_#1$q4x&yTtdIEuIPXJUwy6Dap4hgGP4p0 zzgiyGT;UUH7cx_HA_M9;fP$RjNOiLAySk<7trR@-EQc?mR+MaK-RjEUGW+mQ*a+yw z$3~guIL>K$Xn!kN$XhT(?R-+Jxt}Z|_h+s>;nZvkq5Si}0G+Ybw>!OHU-ZPh_$+wM zWP@I#sL|yMJDq|U<~UPIe=B88`hiLZ&W>Q{p#!}I4y~iXg4N!T>jjdcS-vYBP1kZ@ zhw3gg%uiB(K%4fvCQvr0^dAoWCSnmdkv`aJ1oe&WqP9)xpV{t&4yvEOz2dI5;Z zQTnp>GG%N~D;)xLmTw~ZjHI4~YsUoilw;>*h zl8Wiam4I6fO6@LebuUCBhk+MV_UB{yMp{B z(vf4sB`F6+16^X)=k{HCvTRbm0kQQ z=9bvS+b8^NB8_fGc|Y|hFK!@r;0tdPRjBwYL#nc&Y{9JR2^C(YW}(@IVAB4MzD;-E zE8Ml3V`kA9MfA62cC${ITFCTsGce)nVj?m%uGa7*neK3A6*#C;mpxpmMpjOLF493| z88xF(SOg(=oLP5Uli%^4@!V(UJggn>OPc&4oNXV1{bdBVvOeSdPjJUv`sWfg$BkJ> zD$kggubG^HWyZ79(|rTmxC-S*JSB_L}@Cir@_zw z4WTZid)<}9#n6?I$Q9xA{zG}_Oo*C-P~!8ZgeIF{0lOgZ++y1s0s_Gr2v%WY-{gHA zs=4t~vT^V+32c)ZCG5ozP4l+tO(Xs1=U_9YY)U=!P2rq0+^t? zveZ(JdR`xydsbBqCGInMKleY?e;-63H#y)%FjC@-x>Jo{LJW8_8SZaQ#6Jqk`_qjr zrS#rw`dETrgeb3AwuG@t1WJZw07>sYPB4FwH?k4N!%tabb%}VFUax4P%R#-Gc}9?vpO=xaK}g>*gP_)&aYsM64* zdub%hm(Rz~gtE0q*I;Z^btGQ|Au97=e)fUU6aCOLYn#*FmWJ58R)U$TOi3fD1=OMW)u-m&oUXZm=&AWBB{L3jRQzMG z5~O?_d7v9kO7fb+fkBR4Z)Iu;rWhBcx49XzJkiy`w_s#C29RGzWE`HGFd24ymAGy6 zm9H>zeZ`*np|R9MR=30&&tHa&j4DK7NhAugPkiq}K5|!aLGgm)bQ3H&-j>u%d^`4H z>c|&0TUO3wk zo<@0DH3rnctYvO{3p1p<&F|manGbaR5LYb>^&hS6MvZ?@7%($?dy&>(%T|v_lGTKI z=n9Uf2ARz$>}{i)dj9BcLQe~39{S7Jcp#8#JaI2%guuVb!EMl&^uSX(w9?zg(V3TAg(J$FtLQS*QxU1+j z9yBE)N!WwXRf|{LWxrCd?I+C*vVGg>vsaiy z`5_Qld`eAG&QEETsv0n>QPbo{O+RYL6twUod1LwHt#JKGx!WBb@9Qg~dD+Ffo>e)J zg?-BYc#oX8z0k{^l}FkjOKAnA#71PC_C|@3=aq11NMKp4K|-QOMme9ev|o>lm7@6>fk4HXZhq{>8L%vupJz=DY zE6hO}Z;H#f_t&lWr|DGl@ie=ZwJCpO<~hhTpcY%8?AHzI2d^MJBGBTzmA>+#lbI-h~7k*6&Dw^Va`k9wdw}?|kJt^>;enM`|9KJ)DDM$YH zZ1LESr2K*2uH7xut8X&9wJi-CfXg>biP4cp??7UaUClg79j>7u^iY7Gzxe;!0Wm!k z1Y%=j5BvB4z_JQ#?c}KjFjJOENOY1K&vj^GY1NcP>|}3io4$)Yn_*RHRZeV5Rc(?Q zeZ*&jBoJ~>4*djQut@t_&}FONO0LCaV^ofT96%z>v1lQtvUek}aH68Mdy<}xQU>43 z)=rTfhaiD}j`PA2N&Tm$qdYv^Ta=XNUn=SfP5vJU$p4``aRa$xlEXL8SYnvz;^b0ztg vMeg4QasMR2|H8l(|Jy|FKhNs_jAf1dj<+^*+r literal 0 HcmV?d00001 From c2f52ac1f31a1674d7e6457c0c5bee9fd719a0d4 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sun, 17 Dec 2023 09:57:15 +0000 Subject: [PATCH 20/80] Avoid repeated tx classification work --- backend/src/api/common.ts | 31 +++++++++++++++++++++---------- backend/src/mempool.interfaces.ts | 1 + 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/backend/src/api/common.ts b/backend/src/api/common.ts index 751bab5a3..4cd2b0873 100644 --- a/backend/src/api/common.ts +++ b/backend/src/api/common.ts @@ -222,7 +222,25 @@ export class Common { } static getTransactionFlags(tx: TransactionExtended): number { - let flags = 0n; + let flags = tx.flags ? BigInt(tx.flags) : 0n; + + // Update variable flags (CPFP, RBF) + if (tx.ancestors?.length) { + flags |= TransactionFlags.cpfp_child; + } + if (tx.descendants?.length) { + flags |= TransactionFlags.cpfp_parent; + } + if (rbfCache.getRbfTree(tx.txid)) { + flags |= TransactionFlags.replacement; + } + + // Already processed static flags, no need to do it again + if (tx.flags) { + return Number(flags); + } + + // Process static flags if (tx.version === 1) { flags |= TransactionFlags.v1; } else if (tx.version === 2) { @@ -306,15 +324,7 @@ export class Common { if (hasFakePubkey) { flags |= TransactionFlags.fake_pubkey; } - if (tx.ancestors?.length) { - flags |= TransactionFlags.cpfp_child; - } - if (tx.descendants?.length) { - flags |= TransactionFlags.cpfp_parent; - } - if (rbfCache.getRbfTree(tx.txid)) { - flags |= TransactionFlags.replacement; - } + // fast but bad heuristic to detect possible coinjoins // (at least 5 inputs and 5 outputs, less than half of which are unique amounts, with no address reuse) const addressReuse = Object.values(reusedAddresses).reduce((acc, count) => Math.max(acc, count), 0) > 1; @@ -335,6 +345,7 @@ export class Common { static classifyTransaction(tx: TransactionExtended): TransactionClassified { const flags = this.getTransactionFlags(tx); + tx.flags = flags; return { ...this.stripTransaction(tx), flags, diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts index 4a630f1e4..d5dfcbf14 100644 --- a/backend/src/mempool.interfaces.ts +++ b/backend/src/mempool.interfaces.ts @@ -95,6 +95,7 @@ export interface TransactionExtended extends IEsploraApi.Transaction { }; acceleration?: boolean; uid?: number; + flags?: number; } export interface MempoolTransactionExtended extends TransactionExtended { From a8fd2ac9dc2cb46cc8e7d99a767cffa824b89175 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sun, 17 Dec 2023 10:45:26 +0000 Subject: [PATCH 21/80] Preserve tx replacement flag --- backend/src/api/common.ts | 2 +- backend/src/api/disk-cache.ts | 1 + backend/src/api/rbf-cache.ts | 13 +++++++++---- backend/src/api/redis-cache.ts | 1 + backend/src/mempool.interfaces.ts | 1 + 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/backend/src/api/common.ts b/backend/src/api/common.ts index 4cd2b0873..358a98c98 100644 --- a/backend/src/api/common.ts +++ b/backend/src/api/common.ts @@ -231,7 +231,7 @@ export class Common { if (tx.descendants?.length) { flags |= TransactionFlags.cpfp_parent; } - if (rbfCache.getRbfTree(tx.txid)) { + if (tx.replacement) { flags |= TransactionFlags.replacement; } diff --git a/backend/src/api/disk-cache.ts b/backend/src/api/disk-cache.ts index 093f07f0d..202f8f4cb 100644 --- a/backend/src/api/disk-cache.ts +++ b/backend/src/api/disk-cache.ts @@ -256,6 +256,7 @@ class DiskCache { txs: rbfData.rbf.txs.map(([txid, entry]) => ({ value: entry })), trees: rbfData.rbf.trees, expiring: rbfData.rbf.expiring.map(([txid, value]) => ({ key: txid, value })), + mempool: memPool.getMempool(), }); } } catch (e) { diff --git a/backend/src/api/rbf-cache.ts b/backend/src/api/rbf-cache.ts index ad1762485..a087abbe0 100644 --- a/backend/src/api/rbf-cache.ts +++ b/backend/src/api/rbf-cache.ts @@ -97,6 +97,8 @@ class RbfCache { return; } + newTxExtended.replacement = true; + const newTx = Common.stripTransaction(newTxExtended) as RbfTransaction; const newTime = newTxExtended.firstSeen || (Date.now() / 1000); newTx.rbf = newTxExtended.vin.some((v) => v.sequence < 0xfffffffe); @@ -368,14 +370,14 @@ class RbfCache { }; } - public async load({ txs, trees, expiring }): Promise { + public async load({ txs, trees, expiring, mempool }): Promise { try { txs.forEach(txEntry => { this.txs.set(txEntry.value.txid, txEntry.value); }); this.staleCount = 0; for (const deflatedTree of trees) { - await this.importTree(deflatedTree.root, deflatedTree.root, deflatedTree, this.txs); + await this.importTree(mempool, deflatedTree.root, deflatedTree.root, deflatedTree, this.txs); } expiring.forEach(expiringEntry => { if (this.txs.has(expiringEntry.key)) { @@ -413,7 +415,7 @@ class RbfCache { return deflated; } - async importTree(root, txid, deflated, txs: Map, mined: boolean = false): Promise { + async importTree(mempool, root, txid, deflated, txs: Map, mined: boolean = false): Promise { const treeInfo = deflated[txid]; const replaces: RbfTree[] = []; @@ -426,9 +428,12 @@ class RbfCache { // recursively reconstruct child trees for (const childId of treeInfo.replaces) { - const replaced = await this.importTree(root, childId, deflated, txs, mined); + const replaced = await this.importTree(mempool, root, childId, deflated, txs, mined); if (replaced) { this.replacedBy.set(replaced.tx.txid, txid); + if (mempool[replaced.tx.txid]) { + mempool[replaced.tx.txid].replacement = true; + } replaces.push(replaced); if (replaced.mined) { mined = true; diff --git a/backend/src/api/redis-cache.ts b/backend/src/api/redis-cache.ts index 82ce34ad1..edfd2142b 100644 --- a/backend/src/api/redis-cache.ts +++ b/backend/src/api/redis-cache.ts @@ -222,6 +222,7 @@ class RedisCache { txs: rbfTxs, trees: rbfTrees.map(loadedTree => { loadedTree.value.key = loadedTree.key; return loadedTree.value; }), expiring: rbfExpirations, + mempool: memPool.getMempool(), }); } diff --git a/backend/src/mempool.interfaces.ts b/backend/src/mempool.interfaces.ts index d5dfcbf14..c93372ded 100644 --- a/backend/src/mempool.interfaces.ts +++ b/backend/src/mempool.interfaces.ts @@ -94,6 +94,7 @@ export interface TransactionExtended extends IEsploraApi.Transaction { vsize: number, }; acceleration?: boolean; + replacement?: boolean; uid?: number; flags?: number; } From bc89fd5b7c87ca8a1e5d05ce2d2ed8b87c5d7b95 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 15 Dec 2023 13:28:55 +0000 Subject: [PATCH 22/80] Goggles icon, beta tag and info tooltip --- .../block-filters.component.html | 8 +++-- .../block-filters.component.scss | 14 ++++++++ .../components/svg-icons/goggles.component.ts | 34 +++++++++++++++++++ frontend/src/app/shared/shared.module.ts | 6 +++- 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 frontend/src/app/shared/components/svg-icons/goggles.component.ts diff --git a/frontend/src/app/components/block-filters/block-filters.component.html b/frontend/src/app/components/block-filters/block-filters.component.html index 90b66ddc3..876a72ad1 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.html +++ b/frontend/src/app/components/block-filters/block-filters.component.html @@ -1,7 +1,11 @@
+ + beta + +
-
diff --git a/frontend/src/app/components/block-filters/block-filters.component.scss b/frontend/src/app/components/block-filters/block-filters.component.scss index 20b565293..6406a1d93 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.scss +++ b/frontend/src/app/components/block-filters/block-filters.component.scss @@ -20,7 +20,21 @@ margin-left: 0.5em; } + .info-badges { + display: flex; + flex-direction: row; + align-items: center; + float: right; + + &:hover, &:active { + text-decoration: none; + } + } + .menu-toggle { + width: 2em; + height: 2em; + padding: 0px 1px; opacity: 0; cursor: pointer; color: white; diff --git a/frontend/src/app/shared/components/svg-icons/goggles.component.ts b/frontend/src/app/shared/components/svg-icons/goggles.component.ts new file mode 100644 index 000000000..b045e6acb --- /dev/null +++ b/frontend/src/app/shared/components/svg-icons/goggles.component.ts @@ -0,0 +1,34 @@ +import { Component, Input } from '@angular/core'; + +@Component({ + selector: 'app-goggles-icon', + template: ` + + + + + + + `, +}) +export class GogglesIconComponent { + @Input() width: string = '100%'; + @Input() height: string = '100%'; +} diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index 9bcfb932c..f772c3fd3 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -5,6 +5,7 @@ import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontaweso import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, faChartArea, faCogs, faCubes, faHammer, faDatabase, faExchangeAlt, faInfoCircle, faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faClock, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown, faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft, faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck, faCircleCheck, faUserCircle, faCheck } from '@fortawesome/free-solid-svg-icons'; +import { GogglesIconComponent } from './components/svg-icons/goggles.component'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { MenuComponent } from '../components/menu/menu.component'; import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component'; @@ -200,6 +201,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir AccelerationsListComponent, AccelerationStatsComponent, PendingStatsComponent, + GogglesIconComponent, ], imports: [ CommonModule, @@ -322,7 +324,9 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir ClockFaceComponent, OnlyVsizeDirective, - OnlyWeightDirective + OnlyWeightDirective, + + GogglesIconComponent, ] }) export class SharedModule { From 8dbf879c37fc593531b2aa6d198fb611ebe6ba45 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 15 Dec 2023 13:29:29 +0000 Subject: [PATCH 23/80] Add Goggles FAQ entry --- .../src/app/docs/api-docs/api-docs-data.ts | 7 ++ .../app/docs/api-docs/api-docs.component.html | 89 +++++++++++++++++++ .../app/docs/api-docs/api-docs.component.scss | 41 +++++++++ 3 files changed, 137 insertions(+) diff --git a/frontend/src/app/docs/api-docs/api-docs-data.ts b/frontend/src/app/docs/api-docs/api-docs-data.ts index ce0b7eaef..97be0c2b1 100644 --- a/frontend/src/app/docs/api-docs/api-docs-data.ts +++ b/frontend/src/app/docs/api-docs/api-docs-data.ts @@ -8911,6 +8911,13 @@ export const faqData = [ fragment: "what-is-block-health", title: "What is block health?", }, + { + type: "endpoint", + category: "advanced", + showConditions: bitcoinNetworks, + fragment: "how-do-mempool-goggles-work", + title: "How do Mempool Goggles work?", + }, { type: "category", category: "self-hosting", diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index 49493d210..49b11ad7b 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -279,6 +279,95 @@

Because of this feature's resource usage and availability requirements, it is only supported on official mempool.space instances.

+ +

Mempool Goggles are a set of filters that can be applied to the mempool block visualizations to highlight different types of transactions.

+

There are currently 25 different Mempool Goggles filters, grouped into six categories:

+
+
Features
+
+
+
RBF enabled
+
The transaction opts-in to BIP-125 replaceability.
+
RBF disabled
+
The transaction does not opt-in to BIP-125 replaceability.
+
Version 1
+
The default version for most transactions.
+
Version 2
+
Required for transactions which use OP_CHECKSEQUENCEVERIFY relative timelocks.
+
+
+ +
Address Types
+
+
+
P2PK
+
Pay-to-public-key. A legacy output format most commonly found in old coinbase transactions.
+
Bare multisig
+
A legacy form of multisig, most commonly used for data embedding schemes (see also "Fake pubkey").
+
P2PKH
+
Pay-to-public-key-hash. A legacy address type that locks outputs to a public key.
+
P2SH
+
Pay-to-script-hash. A legacy address type that locks outputs to a redeem script.
+
P2WPKH
+
Pay-to-witness-public-key-hash. The SegWit version of P2PKH.
+
P2WSH
+
Pay-to-witness-script-hash. The SegWit version of P2SH.
+
Taproot
+
Addresses using the SegWit V1 format added in the Taproot upgrade.
+
+
+ +
Behavior
+
+
+
Paid for by child
+
The transaction's effective fee rate has been increased by a higher rate CPFP child.
+
Pays for parent
+
The transaction bumps the effective fee rate of a lower rate CPFP ancestor.
+
Replacement
+
The transaction replaced a prior version via RBF.
+
+
+ +
Data
+
+ Different methods of embedding arbitrary data in a Bitcoin transaction. +
+
OP_RETURN
+
Fake pubkey
+
Data may be embedded in an invalid public key in a P2PK or Bare multisig output. This is a heuristic filter and can be prone to false positives and false negatives.
+
Inscription
+
Data is embedded in the witness script of a taproot input.
+
+
+ +
Heuristics
+
+ These filters match common types of transactions according to subjective criteria. +
+
Coinjoin
+
A type of collaborative privacy-improving transaction.
+
Consolidation
+
The transaction condenses many inputs into a few outputs.
+
Batch payment
+
The transaction sends coins from a few inputs to many outputs.
+
+
+ +
Sighash Flags
+
+ Different ways of signing inputs to Bitcoin transactions. Note that selecting multiple sighash filters will highlight transactions in which each sighash flag is used, but not necessarily in the same input. +
+
sighash_all
+
sighash_none
+
sighash_single
+
sighash_default
+
sighash_anyonecanpay
+
+
+
+
+ The official mempool.space website is operated by The Mempool Open Source Project. See more information on our About page. There are also many unofficial instances of this website operated by individual members of the Bitcoin community. diff --git a/frontend/src/app/docs/api-docs/api-docs.component.scss b/frontend/src/app/docs/api-docs/api-docs.component.scss index f90274046..8a4150262 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.scss +++ b/frontend/src/app/docs/api-docs/api-docs.component.scss @@ -389,3 +389,44 @@ h3 { margin-bottom: 4rem; } } + +/* styles for nested definition lists */ +dl { + margin: 0; + padding: 0; +} + +dt { + font-weight: bold; + color: #4a68b9; + padding: 5px 0; +} + +dd { + padding: 2px 0; + + & > dl { + padding-left: 1em; + border-left: 2px solid #4a68b9; + margin-left: 1em; + margin-top: 5px; + } + + & > dl > dt { + display: inline; + font-weight: normal; + color: #e83e8c; + font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New; + text-transform: uppercase; + + &:before { + content: ""; + display: block; + } + } + + & > dl > dd { + display: inline; + margin-left: 1em; + } +} From 78857102f8cdaea05411e5cdfc38d8a7aeb7588e Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sun, 17 Dec 2023 10:56:11 +0000 Subject: [PATCH 24/80] Move goggles icon inside generic svg-images component --- .../block-filters.component.html | 2 +- .../svg-images/svg-images.component.html | 8 +++++ .../components/svg-icons/goggles.component.ts | 34 ------------------- frontend/src/app/shared/shared.module.ts | 4 --- 4 files changed, 9 insertions(+), 39 deletions(-) delete mode 100644 frontend/src/app/shared/components/svg-icons/goggles.component.ts diff --git a/frontend/src/app/components/block-filters/block-filters.component.html b/frontend/src/app/components/block-filters/block-filters.component.html index 876a72ad1..7b1c2f9e5 100644 --- a/frontend/src/app/components/block-filters/block-filters.component.html +++ b/frontend/src/app/components/block-filters/block-filters.component.html @@ -5,7 +5,7 @@
diff --git a/frontend/src/app/components/svg-images/svg-images.component.html b/frontend/src/app/components/svg-images/svg-images.component.html index 5e8d7d29f..11dfe1d79 100644 --- a/frontend/src/app/components/svg-images/svg-images.component.html +++ b/frontend/src/app/components/svg-images/svg-images.component.html @@ -84,6 +84,14 @@ + + + + + + + + diff --git a/frontend/src/app/shared/components/svg-icons/goggles.component.ts b/frontend/src/app/shared/components/svg-icons/goggles.component.ts deleted file mode 100644 index b045e6acb..000000000 --- a/frontend/src/app/shared/components/svg-icons/goggles.component.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Component, Input } from '@angular/core'; - -@Component({ - selector: 'app-goggles-icon', - template: ` - - - - - - - `, -}) -export class GogglesIconComponent { - @Input() width: string = '100%'; - @Input() height: string = '100%'; -} diff --git a/frontend/src/app/shared/shared.module.ts b/frontend/src/app/shared/shared.module.ts index f772c3fd3..f092e81bc 100644 --- a/frontend/src/app/shared/shared.module.ts +++ b/frontend/src/app/shared/shared.module.ts @@ -5,7 +5,6 @@ import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontaweso import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, faChartArea, faCogs, faCubes, faHammer, faDatabase, faExchangeAlt, faInfoCircle, faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faClock, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown, faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft, faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck, faCircleCheck, faUserCircle, faCheck } from '@fortawesome/free-solid-svg-icons'; -import { GogglesIconComponent } from './components/svg-icons/goggles.component'; import { InfiniteScrollModule } from 'ngx-infinite-scroll'; import { MenuComponent } from '../components/menu/menu.component'; import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component'; @@ -201,7 +200,6 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir AccelerationsListComponent, AccelerationStatsComponent, PendingStatsComponent, - GogglesIconComponent, ], imports: [ CommonModule, @@ -325,8 +323,6 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir OnlyVsizeDirective, OnlyWeightDirective, - - GogglesIconComponent, ] }) export class SharedModule { From 75b3bc62494b702f8101c6dacee4c432f921e69d Mon Sep 17 00:00:00 2001 From: natsee Date: Sun, 17 Dec 2023 19:15:23 +0100 Subject: [PATCH 25/80] Expand toggle for RBF history view --- .../rbf-timeline/rbf-timeline.component.html | 17 ++++++++++++++--- .../rbf-timeline/rbf-timeline.component.scss | 6 ++++++ .../rbf-timeline/rbf-timeline.component.ts | 6 ++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html index a2012d45f..8a750e624 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html @@ -1,7 +1,7 @@
-
-
+
+
@@ -13,7 +13,7 @@
-
+
+
+ + + + +
@@ -72,3 +81,5 @@ [isConnector]="hoverConnector" > -->
+ +{{ x }} remaining \ No newline at end of file diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss index be7aef2d6..8afc3f026 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss @@ -34,6 +34,12 @@ &::-webkit-scrollbar { display: none; } + + .toggle-wrapper { + width: 100%; + text-align: center; + margin: 1.25em 0 0; + } } .intervals, .nodes { diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.ts b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.ts index 474da7326..687a7dbfd 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.ts +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.ts @@ -25,7 +25,9 @@ function isTimelineCell(val: RbfTree | TimelineCell): boolean { export class RbfTimelineComponent implements OnInit, OnChanges { @Input() replacements: RbfTree; @Input() txid: string; + @Input() rowLimit: number = 5; // If explicitly set to 0, all timelines rows will be displayed by default rows: TimelineCell[][] = []; + timelineExpanded: boolean = this.rowLimit === 0; hoverInfo: RbfTree | null = null; tooltipPosition = null; @@ -191,6 +193,10 @@ export class RbfTimelineComponent implements OnInit, OnChanges { return rows; } + toggleTimeline(expand: boolean): void { + this.timelineExpanded = expand; + } + scrollToSelected() { const node = document.getElementById('node-' + this.txid); if (node) { From f72683dc197f34ce5a46b4e60bd1b9c51c909024 Mon Sep 17 00:00:00 2001 From: orangesurf Date: Mon, 18 Dec 2023 09:18:55 +0000 Subject: [PATCH 26/80] Add Mempool Goggles TM --- LICENSE | 8 ++++---- frontend/src/app/components/about/about.component.html | 2 +- .../trademark-policy/trademark-policy.component.html | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/LICENSE b/LICENSE index e5b707840..a5267e2e0 100644 --- a/LICENSE +++ b/LICENSE @@ -12,10 +12,10 @@ or any other contributor to The Mempool Open Source Project. The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full -Bitcoin ecosystem™, the mempool Logo, the mempool Square logo, the mempool Blocks -logo, the mempool Blocks 3 | 2 logo, the mempool.space Vertical Logo, and the -mempool.space Horizontal logo are registered trademarks or trademarks of Mempool -Space K.K in Japan, the United States, and/or other countries. +Bitcoin ecosystem™, Mempool Goggles™, the mempool Logo, the mempool Square logo, +the mempool Blocks logo, the mempool Blocks 3 | 2 logo, the mempool.space Vertical +Logo, and the mempool.space Horizontal logo are registered trademarks or trademarks +of MempoolSpace K.K in Japan, the United States, and/or other countries. See our full Trademark Policy and Guidelines for more details, published on . diff --git a/frontend/src/app/components/about/about.component.html b/frontend/src/app/components/about/about.component.html index 98dcb4c31..b1a3069a6 100644 --- a/frontend/src/app/components/about/about.component.html +++ b/frontend/src/app/components/about/about.component.html @@ -422,7 +422,7 @@ Trademark Notice

- The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries. + The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, Mempool Goggles™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries.

While our software is available under an open source software license, the copyright license does not include an implied right or license to use our trademarks. See our Trademark Policy and Guidelines for more details, published on <https://mempool.space/trademark-policy>. diff --git a/frontend/src/app/components/trademark-policy/trademark-policy.component.html b/frontend/src/app/components/trademark-policy/trademark-policy.component.html index 9d08c634d..b60e10f7b 100644 --- a/frontend/src/app/components/trademark-policy/trademark-policy.component.html +++ b/frontend/src/app/components/trademark-policy/trademark-policy.component.html @@ -62,6 +62,7 @@ mempool.space Be your own explorer Explore the full Bitcoin ecosystem + Mempool Goggles

@@ -314,7 +315,7 @@

Also, if you are using our Marks in a way described in the sections "Uses for Which We Are Granting a License," you must include the following trademark attribution at the foot of the webpage where you have used the Mark (or, if in a book, on the credits page), on any packaging or labeling, and on advertising or marketing materials:

-

"The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries, and are used with permission. Mempool Space K.K. has no affiliation with and does not sponsor or endorse the information provided herein."

+

"The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, Mempool Goggles™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries, and are used with permission. Mempool Space K.K. has no affiliation with and does not sponsor or endorse the information provided herein."

  • What to Do When You See Abuse

  • From 03b78015ba012201929609c3ba51876d590c122e Mon Sep 17 00:00:00 2001 From: orangesurf Date: Mon, 18 Dec 2023 09:22:28 +0000 Subject: [PATCH 27/80] Remove redundant semicolons --- frontend/src/app/components/about/about.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/about/about.component.html b/frontend/src/app/components/about/about.component.html index b1a3069a6..dd2a4ead2 100644 --- a/frontend/src/app/components/about/about.component.html +++ b/frontend/src/app/components/about/about.component.html @@ -422,7 +422,7 @@ Trademark Notice

    - The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, Mempool Goggles™, the mempool logo;, the mempool Square logo;, the mempool Blocks logo;, the mempool Blocks 3 | 2 logo;, the mempool.space Vertical Logo;, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries. + The Mempool Open Source Project®, Mempool Accelerator™, Mempool Enterprise®, Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, Mempool Goggles™, the mempool logo, the mempool Square logo, the mempool Blocks logo, the mempool Blocks 3 | 2 logo, the mempool.space Vertical Logo, and the mempool.space Horizontal logo are either registered trademarks or trademarks of Mempool Space K.K in Japan, the United States, and/or other countries.

    While our software is available under an open source software license, the copyright license does not include an implied right or license to use our trademarks. See our Trademark Policy and Guidelines for more details, published on <https://mempool.space/trademark-policy>. From 59f8a7199c45665107c5ff4fed441d0d67211348 Mon Sep 17 00:00:00 2001 From: orangesurf Date: Mon, 18 Dec 2023 09:35:14 +0000 Subject: [PATCH 28/80] Fix space --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index a5267e2e0..b6a09390a 100644 --- a/LICENSE +++ b/LICENSE @@ -15,7 +15,7 @@ Mempool Liquidity™, mempool.space®, Be your own explorer™, Explore the full Bitcoin ecosystem™, Mempool Goggles™, the mempool Logo, the mempool Square logo, the mempool Blocks logo, the mempool Blocks 3 | 2 logo, the mempool.space Vertical Logo, and the mempool.space Horizontal logo are registered trademarks or trademarks -of MempoolSpace K.K in Japan, the United States, and/or other countries. +of Mempool Space K.K in Japan, the United States, and/or other countries. See our full Trademark Policy and Guidelines for more details, published on . From bd07773b8d928b0715a7c45cde510ef019f5ca5d Mon Sep 17 00:00:00 2001 From: Pedro Date: Mon, 18 Dec 2023 12:05:05 +0000 Subject: [PATCH 29/80] Dot the i's on liquid logo --- .../liquid/liquid-network-preview.png | Bin 98482 -> 98357 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/frontend/src/resources/liquid/liquid-network-preview.png b/frontend/src/resources/liquid/liquid-network-preview.png index 72942110cd0e3dd4cf040d41d1456d9bde5ca25c..a66e9bb7aeb83f8394d2dadff914abfa499f293e 100644 GIT binary patch literal 98357 zcmeEt^2w;_#e5G>Qfj1T)IK{2f6>~`a1X{1olWp0mwnKEP!9mSj%h313-Qh<)JwV z0P+8I|DL>#CuDh)(&F!K9u8T&r^E066pNv<}_E_Joym}_dzx5HL0e4?<`*NaZSi2UAP{3X_K z$z_l&zN@*VL1vh5z?TfJ2V#-)mQt|9d6kf5@c0_TMYz{)gyS=l}aaSN@0SAOExR z|Bm;E+y5uMKaBW4<@|>c|7UxD6ypEqT4*oR{aFRP6_~boMy>wpjJ&VoXP+>(H;(&< zPd2ocCYwWkTIqjb9_l!c4|vg^ayLypJ2QO?efXBG z1|IPX^!CaC&&YowK(V&oLpFa?3uno_!OQRFFO5|2j7IBbc0+&x6`j9MR#}r@{Cw0y z2RqfA9pUs_xe8@99HX=JFTu_5kiV|qZ2SlP0G-9v#~%j8W({n{-skyBI=?-hvoxqA z2Ket4IsM1;pVN>qDcAd`vJ*6G*kj*Yz7!PKYwN63LAnS4W_kbmZ{qX%vFwTJ#5j>+ z^V~=Ll5~!WLlxjwo_`%aLhZ+N%&^`vQ)1Kx=X~am-uV`Wo-4=~AYr6|T6}+)hcJGV z)yC17aPXcMd78QV7PUpaSt^Ka_?!gA{k)D@K>5T@;O@af1YxHz%MgiGAJho@?d{i&VR4I z{{G#bhh{R8iqOcEF1^(R{oF9uN+JL#`4?UgD?=mUY1t#i6i3X-}6THWh?nY&gdlonE03U3pxp@ty5gCgj*^8a=K2w zSbV6CCH}mZtr7qrqW(jt+|on)$dbF@X?cvsX#wEvU%l=$U`iyz6+WA@$`DamIwMGC ziTeejW5l`t*fyfCOJt?Kfu(m2TD-f<2@0%E@jt>x(RaUqu@3u&%SI3x$q@l^=aVn| z(OaSTNE{0ks+r(k$AF{>52XHYYOZyCV=WVumTlO!1!d*^mwchudI>G`*fZEV)=$KA z;3a{-%zDAcI-V%9QkUaY^WS{XHUt;5Jq!T15B+=CmHFMdIqh6sNrd!71L(!2{@q0} z5NBo{xzQ2uI?nkS_yD6rt3PO&fAcIlpuUS%`jkO`9k^N0`9u&wo5lSlGMt5VSW4^y z3D)9}oDd=!8`HG@D9g3L2^R3rgD|a>KfmCk$%*cUrcU@e#QbyVwN~nXE@`M_bqI?^ zDS#3L%xeFNpHae~nDE4l8w(fzSz6agn@F6>c}iGkW17yN4Tx2osKe78^Z`IFL@Vph zkEA!n#BSFsTuju`pg?pfZi@qe%wKzsz9vTY;@N4uVE8NFU*P837se`h0N~1B$(mu> zcb~8%EK?^|E{n3bmgs?p9nPu@|%_rP1Xt69g!jq-+3=}I2Jl{yjH^pUyj!2 z{YlAJbqk{+3Uq8v5U;&Ez>Kws(*SacgA*g|9nGf1=_wBS6}E&>GjZw%h|@TRRAe?& zcKz;PF{W?RlKhlqws+G=1P9KN!V0`sAy#VWq(EeSsx0+^{$y<32>&Kf%!`X7x1CUM6x4uWD_zxttvL zF)WN&;5?l5402xCkl*Zy(7o|+hf>Gf*6iY?u9Xni$^@e2AM7Vxg)aDIc%|QXZ&uc3 z4ZD{Px_YYsNDu8vi=AmR^_Hj^=OIX6Ir%dC2lR&0OBl*rq{dCY!L6BKW=e?2cd3xQ zdl%!hFf1{xfrUY{b!WS2kM@hBcTMi}1_)GUOJRCwkI4Mz&549jH}|W}n!91f7%%A^ z2v9elH=StPD~_-tcN~q0z~zFzf8FgHHTozMxF#2f8*F^zGBf|aoh3dh3mtKn$ZTt# zpW-nYO>4?vaM^<(gW8U`r$6U+TWUAQ{dMrqTs9FS{wMH_vUxyxSVeY|W3P+-DEB#E z(a}M`eAP++$$k`=gNBn*p(WEI?>jlE0YX}3F1iiHhMYyyf7sTcYVJg$FVZip+ z>@j_P-lphH#K`C*?&?A!XJ z@EkHO8SIY07HCid37(0#$1PuA{p1ZW)MP_~Z4ef8^#K6ufr6n7yXxz%Q7VhlGeiJ~{`z&|uJc!Obz6_peRlP-gjpfq^^upr{>g*SR zj(+3nn;;-yfk=d?H5TpN(vkF@QfDcEKzUi&jrl&NFjd1>bH&#CoZo4U8ymabLA=m? z3ePEnk^+dyZub?W;6tYxeg?7yz`zVnusDQ$I641yrq8V6CD-ZbJ`kZ;?S%J#Z7O;B zxINX*=2Do=%F2q468;|G(JO?KJo!Ze;rAwW4tS&a0p=&RWsRR4tUelH`>}QbsGDe7 z8H(b2{b_1VNN(7UHex?!u>15dgG;`KX?H!Mtsf*6{f_xk~pZxx=6H`)8 z0c+jzNSBzZ3Jxi23h$jSk2Sdjq-HFtIcGor7JnH))T4|gflLepC=-;qZGp1$WLu9C z0J@nO;N}~=@`csw4R0RZpqe4?L3HVEi(^Ox0YHb(q2F&Y&UICS!zw)FqnzzSIH(+v zZ(lq!b8Uw;zyPlv!O+?Dk%#gy>4RSE7d5`a`^A$ih!@h^zXczCO-s&k_XdC>WQpxs zqRb5t3PL&^bdo_VA$UE3@ho`%aF_e4K}4ig_v;Ppo$soa;qGQd3wtKLom3LYTq(m9 zB{A^!=n`9YLkSLK6Uk69@vA$S3>h%mTkmd#2Z*`Yh26zK>>jizCMPCd66zuIpKN>- z%qhDQ91xyCjWWT30EBdRUKPwWr9TJ$;t?QMVZ89@^f2d9sV)XjCGOVC zb^;@Vhf}x7Uq+(5gtm?cWKV*YgEgmPWlKtJ07mL;g?>sCyu$cNQyO#}WP=H`*9)t@ zwf4RIDFm>^Wz&=Qi-Iw28I0guU$ciV4>Q(j+N8aH>Sra?XPtbgFuu}{LHax$+W{qs zlG%D0>!-K{`q~gmD^M*0%N7rR=bQBI4a5Nm`cenelr}KNRmvkG)fURIKpwNiC5h~j zga^c~_A6BhBFjv5HlCVG?kGQ@Gvh14g8Tc)CuYJt6A%EJYUZaWvBQ0zAFd7571qcv zxdXty93t`;OT2UgxYhpW?2#^`q4!UTovHdtD4N{bE$ksjHS7!3k$2w)?03r@`ivc! z8R^!Hisv%4%`fe*=s*Cu;ZGZPFP{n_xQvJukQ&XgtMY!=w*mlL0ZE$aK_w2!pNwgN z`A`$z)aZG~Twcof`-(zTZCmd6_|ey0ezp!&5Z{ zI%TsZXfDm2MMLataNPovVDyAvl~cJvjb{0_&r+8(|78Bm{0gf6^5o@CwnQALnJQUm z$rgqtbqxx@?(0FHniL+qXPzcDbN&pgUko8Q*Ik;*M{6Ztl_JaIp~8q> z-eCcCfkUn($!0=nTO7glPYDbWm5+ujUnD%a7Zogtx3j{(0_5na)!9CRq35Y#B`;yG zPWNy(YO}PnpcSQ4LnQFe?d%k8-lRSY=qM?kLP7wrZw6zxy9KVhz*S!l^vyb;Q}GdS zTYn44MN^~OTYIA)fNl(2cMl8_tV`~e)5W4Us>%sIOybP^038S#beWl%qa2x;m;PCp z65!?Z?BUCWKqA1SsD^_%*W@FA1&C;SK@N?-MA4NRkRmb{n#2iQC+u7#@8tA|$bJw6 z*Nec&)16`nHJYP^I3@qq|YR%6N|M&rcI9bDBg#v`5w0^$2K3_UjxjwYCxt*IF`|vZzesgmLflRr_aT|9R=AU36yKWQbNxuZ2 zkEel1?DwT8TpZ}0dPlOidN6j|E#GzV`Nb{vnA+X86H$t6(dQS#BQ*XIF*Mw4A9aTF z(zG)MVs_^Y=scHYiCnj`>0HmqbQ5d^C9bJ?QdRlNUkUpW z3cp-J9%aWod(`YQ*8$RLr!B!L5WKY>S*H$rjB{G2`oP;mUPzh~m*B8`KPmk;KUcY~ zT6!G^Gmz9l8Gn2Et$vLq?}MOjPQ|RKFkFvAo(Fh(R@BPID1Rv)NlC z;&PONpkU7cPtsC#Qi4zMsMqnbe)0!~B>%hAzac=Xiea&bCM(_J9`kBoVRBk)@yfyWrTO7{jD(1RYe6w9a)D*hGX_dI zlVu@uK{KG$5fPBO9Ep%zkJDq~A6#78I}IUr`u_I1HJiQInT-}%jXF{tISelO=u>jI zW9W|8z@_TAA13M>O=-!KQe+7Dy*78$*p!)3%gxf>8Sh+zD}wS6atMSp<5xKztyq<; ziEZUN(k;i27+8}RHE_@p9(CV(;SA4kfJA4eOZF|yD5!9oyRI~#rwV;Y^Lx{-4xe$$ zsD~LLnYH9~JcxnI%P@?d?S`1;K?kYB`Kj6*bDE-OMwxAOqQP9kc#=*A^q0IgK3lTK zsn)Zp?0ecg3c|6xg^?UNE6EVMmB~={*O+LDB&;k0$+78ich5%N1pu*VV>TvUaRs#Q z2AJ8!>*ih_mbxM)K932Qy06wx=GYtbhC%&~v`MEAc}#c+waqL1Qu1M$?;cH3jvJ8O z<`5_k$Vkg>v78)@ANj7lgvGL6JNnRt;RfW~?Aq{VIW@J{5EYc7BG-+oZ-U7Ix?z)& zfxHcjO_rxAqWi@1;K5WT%zk#{A``0r=ox@gE2#_`6Aji&?QtUlGS9Olegsh?SWrBR z;Aqv4wS98jL0ND<7(06F9w#?ws)47;rxO`dylr~l4?rzY!G2r4ETp86;p6Y}Mc+Hl zy3(KlF5h>0t|{SxL|IDmL+_i_?DeS`>9U2+I=FdlfjLYaY9oUk%p#eG3Xb}j$A~^T zQQ3bB*mLxs3u~saF~i^rcg8sZ1oBObq^z5|1SO2f3~&i3w{ICUHVI?r#qG~wc&K{));whSd0=RZwmHpwV6z-+DNH57T}MHn3hq5>9?)qbtfcUDzUNycMG~Jh|Ab3yD|ed*8Lr zn1}@?Ubje^O31gln=wq~x2M)gIW(bnXF-P~zpD>MDY+SfiV|-fIe~s`HW)lj>GvfoW=OqK*@ z`x!f{)k_=;sH5!|HEU;iz)rqJu-2_o)NiktIcN?%9X&zE<(7`dPLB6df*u+;@0Vlz z(u0Q*wjcHbGiL!+rbPdB1{v;g+$z~L!l%=M z+O`glV_)uA%ScN;k6PK1V&75{@J^~-Q(=p6Y!t%?r(;1Eb_~tJ=YORO!Xh3h;u35N z_L?mRcjrh3%bfBVP;>HB|!m;-bb<@20$WMzw4$mCE22c)r4kx^fnJz=ZPCXTLjT$x>c5F zus7ijV`cH=dxSgz%(d$ezk_+w`BF!+A=MV4abMdTlpVR>FM!Mib6tO7kY2rgf)NFx zQsN^6q%t{*OWya-ruGUBO{CTe#qrX4-+c}4+KV%4F*~WRJ>X|(1LUrX32+iXlL05i z&&oSl&So{v$HEJ|xdfR3%K#zbK#}sgUtcUer|MN61;KRWuqItjN-L>blC7sn=p^kF z&Nql}4uUZ6e1QW?9Shv;a6KY=Af7DA#1ktyG@!Kvhb8|8N zVId0cR8RU4p2N`kn?tHp=-$aj@~#a8A@aHr_m%EKJNj%VDcFnY|7@%X%j^KHZ~wH8 zWuVj|({C6p6rQ6v>y;E@8+Bp@Z;&%fBkY9rLh`=PPXcQWAUf)lu<})xu+|I{=jV`1 zRf2exdGln8q$z>sB`17JQI^#Hlj2^iLA^27eO^MZK(CibQYf^u75|&_d zAVHm-Mt3kBVD6;xwRbilHg>wxcRHf22nu@B^wUN;lqy^GNUo_qz693il#Pzhqegti zdi5ILEPAXsig`zK+z<*TiE`66mF^8Np%}dc)7q{qktm1JJ6SpjAcxMKHs+xbWTc%H z)#SayOqn)iq(bt&AZ_JGO=(H*Dtd5Z)*uGMnCk6GJ8HyNuzf!tOAK(o}iNGNSgy#zEq%a`lL=lUN> zS)4xp@~NnUGlwN)x3>f%Y<-S*r;{(C(CDOUKAHZk1`rLT=E7X%2?0e&;o^G_eLc(R zLtAH0O#;rWJ3ei?WNW(};5n1O`!C_8GCLo7&>YGYWB1aS7)8L40;RC;&EXji1hd%} z7@M9NFPoDJLNn;Z9;1147#Oak{ zQl=6d^~>Ran{on}bRxR$5$e?jlOX)Oubbqzf7ynMiVB3Y^r*;8mTv)|zf=A|D8PL> zjmg^jB4TM8py=zMr#>P=f4l4_LA*8voU;8@_$_D+S0junwsuzsM(nz+6UavkbQ(E( z*0?IPgMu%%Xc0Z>BO#;(i1Vji5~j7)$}CDuazq2}o4!L$-R{ryl!H6V0vpTv3GjE} z-X)U^L=Y%jwiu_B3eRkds41a94}^=H`gKoTy>BHPPg1J|7v}>gFgOvTdmxWdnrAT& zA80zEcR`;FY@hbEnR0*q`VGUH#E3u}gNdLqjiJ_GxiF<)C>zUThcxy6vS)KW{IA z$JBO5Qj!3_AOA_al#M-MJPy4%Aa)0F^ywL)y1L0(A|$p&?#jr-Y?nAv-j5IjoPnT$ z4T(T%IH7QkDxVJkb$}^5a}m}XQ-W3-?p>mSCg|y+RAhU=P#(_I01KC(Y8T}-3U?&b z^?;63sWaJ^d@ey}+V{p6c_*C+3Ugj0jJ6cISFqH%hVOQ*^i;a=7N zRND{fI7fL)N*RuNjgSir_;!eZ#@l14z~{vuu0$ z9uNn&)1*sRtq zl2?_#1uGm*ONGw;uEt1$HQxgLG%)nHqoLR@UUQ3}(bob_y9ne2z7am>=qJUM?|W>= z6EbVCKY$8*sYyF3@$9o9?fA=GTVWBIF&~XipNQU1j62`noz$==l=hdx?JTNy+{y-{ zJ66B#9L}u_SNDHZ2V-L9KP?D3g-|%Or);9Iut1LoBE_8w$S0p5Kueiga#&3c>->qOm7!xuWZWheB zP|q|pziwAa+{nKLuro&yZEoaq)3VoV`_@7k zlSwx{&Q98==WzJ=vXiVV+1hsP7%R8~a<>T_K(I={y)$$Jr0SU#KWhYt0>3X$isO-y zu;aehuKK&nh@-EQySu-iGrhIt2VrT$#-f+`!6iFXO%C#QpXle#YKHH*uoNnw=)$R2 zE8+?)u1p1tP2TohkzCxGCxU*;eN-laAFTYPLRN3 zgtE`qhAZFgCubKb$@`S47=%Ci%=&^4vTG~3ixo$hgR18Dx<%Z7x*+J`JjppCc`w`` z1>U!eO&Q|Nr_T9=4DszBMbfh**&jSu`%uz}ipg`|%G3I#`}A%OcJFaFwShei5ZEVP zA?F!+l)@7yES7d8z%^51k{p+G^_HW!eQ9pWzI*+CHnS*{ga#1)$68i=gQGKcN^jY{ z=xHKya}n)r_?lUzJ$HPG^?*eSAmssJKs^hCzxhu_EDL?U`CdRE*>vV+>w--)XG>&R z{eC$2kErvR#B$ZAJ)!2F#ot^*7fUmGH;8GfRQSCab1M=_=XH@-`wGt)c`(ipf0^{M zHrGU$FXothSp90*EZ&l1!;Ig^xcw%RT{*0hU$O^^GktwG5$YXmpDS3dJqV?Y z>o#;vWQ+N(cGS1cTs>S2me3fb{_*Hco+rzg!!J51RMCU>XM3$|8Bu~J+jv52NargR zq$1}UpcApq()c^#<(Ji_wjx`V+stu2k*sc5y$nN}I878aKzxdCnAUF(J)^?LLvS9=$QWx)Q> zqOd^?v0U)(br3Q!X({G$wFu^9#=|e#KzGM3ow0R0*LnHG*9Yvyr3V(G@+auYrKt6g?y?uv`~$E~wu zr%5RjH-FnvM<7D|)Bf}`9Wse@(Mqv)Gt^9HjO)97?8PyVb4lX-@}80PuNyWy9<&uWPks(6 zb)Xzl%4!$h>RDgQxy9eVXpmjtW~fg*Ft$7M+&87Q%SW>Xd%kx8Y%!c>2lTGKGhD-x zqWKiYcO0~$JT2XI548DSraxxhx#=OD{wNxG^S6pjcNMCf8gu~OuL!`F=$x8?Tg{_U zYtL{Qst)_;y;hHELFyx+!&Dy0JP&WS^4(r{wI6+JvQ6az-5_WaPPj|5p2yB-TiIT15b-)%9D8&8J&c;_`^F4 zUntzjJK62mpNs^q|L(!4M$6y~wVaZO5!a|Ov6`(-L193 zB*CzJDfp_JBqsmF^_&4K4Q`^rXhct+n8to7!(Xm9cl%qE7OTvUvQIoID?^f;QRkCV zU2J;2T%+c?@XICLBO!AZ)6+y?k+KI;M1Qgf+FADI47Ntw3!2G+Estf(`7Yoc=Xdmh zJ=gdFmH^&b*rL_u^HDALqUqaoy_WNLL>&%S%)7X@GBG$pkGhTKSX&wcGbpv-6q<;O zM@Db75)0gg<>fj}>s|EA9yj`s;Ar~6us??~{)Slot+~1&Ai66P_a>Gc&8*7T5TBGB z+d6oet37};tZ^%>(HT|a*>5{fhy2v8^ zfTfA|f@Q|*)yjt>q|TKqrk_XMYqwa~e|wpfZgehrCs~LIP5g|K&GM&RDHYIGyddd5 zXS`GWhT<#f0*mom1noI`iqt$pDiDOF`ds_C$TsX)Q=I;Y+DsjW8nmkxXisC9s2(M{C-1B1{(cPB$X=Fv8%qV9|E7zLjj;sBmk8~#?X=p*uCJm# zta+z#kGQ?>WPx%}^Z_%iCFGocQ zmMvPlDAImgr3-~Vt)uxLs$g7_Qe%p^en!e?*}H`{9Y2h|Qtc-swZ@%?(T*ru^tIdy zLD#PiP~RM~zvrI@-8rxLgjCL(HOxEtVC=r=RiL<;lNrR5YU~FCoX=_PUgdBM-|BWM zAx{~iq$f+QsFm5XWsg0=4<~ymu=#8qy?k+QUy8kn)|l^1*YvA(7G7posBWj99%+UA zet^w!oW$bG!OIOWosdl2e$V)g$DuS|d4`Gu$y3A;*&p4meQuIONK8Hkp)2%8wwd21 z%=E2%r}j$JNk`!|db6gsEftK2755BSy4K9Z2egdwCGTZ(K9~JrKYTJ_(|~(TwJ&vo zllAfYg3c(k_UYYVQE{^A#ccSDpC@BY{YT;f;sC&u&&@O7T(veGRDroK|hH0QK{dBM?dpn~=mbH|a{UTMTu-Pz%OP9*ZO1?fO>JuVELdgHt$h;mn* zf?Yv8Y~ln9r{G*vCY(@u3VfcWBa8dQ8Ny~KeJQw}DcvSdglpPIe*vsOy_5G`Youvf zDQAydCA+^97Lse=r8zGy1{R{+&LWP)F!oM4IIxRl#N^vP4p*a2mf}s-Y&^2q8KXP7 zOMk%k*FQRf-JBZyH#-xP82){x?G*VKQUe3~oZio1($9GD=v+GM`ywu6em5li>M4kL z0Vbs70mYu~@QJRSG{~?I8Dsm9+)9G!$%DO>aqrJv^~)$C*RR7XJN`R3V)A>VorSk~ zwpB*`60w2Hx8BmA6FdXX?Waxdb@`xwZjG2{yg~JZ4ST%^zJ`w?Ct669Qud6LCU?x) zHYhQzLw+PB{5~ z>8F}G=C1rK-ro)&8>h=vOc+8WOYXQ-t&o$<#nwG+@& z{Z<3%voI@WM;My$QgZC--^ofNk4}o zgp+`m!L$wjbo_0EC~r$ImJx0+=;h?6NzH0*1Orm<`-|ApCsL?@RQ}jwXSLo<5f47Y=fK|QUBm=KPWV38Y$SfH{T<& zGL(dL?tuIbJ8tjBuYw8U^p&H1dI=;rYQQT94ic#PZe&6|zjI6OYF^Gu(`y&{Yk>8Vw z8@qE%a_7Ms&7I*ftBre~wSc5@l_ z@`Y2wC^K6F-q$$u~Ve)0ym+1uCI@f*z z3QUUy`}ji2oX5+Rw>UpvfphGCSA9!urcH<~fXfg|&I03b?P31DuEf%@M1QB+kciQh zJoX{qq$MQ*md70_(@CPyq%wkUIx@er(=#P`#Av<(p%SgTieZT(ICQXqR{2PU)~Z=T zI@kSR!~*f^EvlTVWc;^$UxWSfTV2gg8i7OXCysswi;FG(Q)#n{y>q$>3o>2sz{TPX zseT7iw<=ZA*&;Wev`K&N-@q%`S9-ay&A2$QE8?CCjuPZr9_)vh6@lYcb_XC$)4-O8V7=8- zF2@g5Nb}9RLT63#!D{n>$^jI#uu3&b26!%;f3F$srk~qY0RK@|UtYpZ3fO7L^3i=Eo-L+Sycdp#RP#Z0P})z>Y5mxe;+Bp5PJnIY%jkH(Z#5w^e*%~*aX{ds%*OfJ3ma< zM2&M!+fyAG_c}7WWY@tC`L)`u6!@@81z(Xc*z(p%>~Fc1jE#~#wo$-cihFAG>f~p? zI~dYuhGs46ktDdn?xzzkiNW!cZ2CbXlk>~$RA}oTZ4 zM(R%Ev&KQ|)Xqe??8HdN>{2pz&nT%&!3&K;DiyLd`@PsHuN@!x#ur;PT==El-bKFj z&T0SLHvA*1<|TIwteSB;G<8}f>Z^GYwgPGT%E9}5vk70MO`BhqWcI6+3;EW*n{q5d zZlaY1?9GvUYSz=15tr18*V!-C;0I;Kf{{Cc%xcn`ZMwJjm2c| zhrw!6mJqaOeHqLnTg>CfGS7AR9|&sww1}!P#W(1|qXb6TE26euhH_=SUa9HoJiKG- zrHQUpDE9g=Xfc00&%*u#oKV0gAGW?>dBF2^TJRA(seCH}=d!f#Hb_$_d;E%JKVRi} zuE`PEi7KhmsrENZx8VCky{C~q1@Q6tvPw!1#)z7C?|J^Se!h=^X%_=D` zoo-w@?u5JgyS&+Xvzj_MsBr67O@QvUR}QPf7XA>&cOkBHWb2S+QVqTPI{;4ExrBoG zzFTJ*u5>dLG4cPf?wbsClJT*->u~uTz-YW*=$G8`NOw9fUOAvOQ7FD*+H- z8^ut7=0k?degOT{%Aa@Cz(HSB@FMPNrbruDw(m9{f!To};k6wvF7(8lQX-(8o9&&V z$|bN22fX-2y6~Y3o1K+gD{tt5A~_9jU=#f=-Qy2Bw;ck2Ow|@?nn>QW+L@rHJZN*? z77uw4I@y`2#2Z3{u!@V9zBuk+RL+&R4OM-OtNMiSYjOGKJY0=yv(>Bvsjm z)5ejU2{@=`x2bZFLb&6K7GDrj(#wcisg@bKME#qY04l-HwTXFY>oWu7&C)8LRt@hI zlviD4tXkMB7rT-I-i116KN_$G}TxwN3`}4a(u&Gr6qLun? zO%B|HG-y9HFmQgj55C>e=5j>AP!4fZ0Ega=7*4Q`ufmSgPGUP{n3PZ6u=Dsb_}ho$ z48q2lL#nOc^l)vajrn9auU7Xjdm5Nmo!ck~L!tzm-Y*0VPWiNP1mC!W7W6X}%Joc| z!f>9$Em@a7-P?NIv&v)V$K+1xt~E1f6sNGZw`q?wJ#c!nXJ1NFVvyi@q~V;Q7ArMq zvgd|oBkyq=bYCr>)=#u3D&sx&S&?d(k?XURm673SX{LF;_MkNDew4?DoUmHwg6W3w z}?35 zf>E;O7M=f6Hz{)(3wHK#Lgfpwr2A8$=>hOk z<8tk8exbI_6?_{>&DE)nTU-661)-n!W*Rq_eJV#pUQxT)TDcU4#opNp9N!Xinu|q` zON&(Xdludg#BrZP$8?k}aSe(T47V9Ss?1(-si^EQKCyE#->ev;#I@OsSX|={!8DIf z$rXavHc8)8ct&QM1wW@ur~FwEZ3OqiqI9ior40!2PLh;^uM3h2dqF zcvr)7`-d1)b#Q7;vk|xFzyG*E|IEDHK|43EHoS&%$+q-M#FR5eiN=TedIo+P*z6wt7W*$q`+IVM`K`S+xtlOl~pVlrQ}PaX-wQ zIWSRW`X=wjR3*-l=1gQM$-`W<&DFFbWZ#>Mba$lK*ute`bYviBRTo2i9 zVp5b<711msV?2 za!X1@>uPmxmZp|B2L_IkR&BH)PbF4Y^_^ox*@Y?tDhe+x;6>2KJp8TsNmA_B>+|82 zuRL{!_I3w&wamVFN{9NS1jE!Bu@fsALt+PAbg`#i`g0El^hAIwGcSvHRScedo|B!f37q`nM|4SWK&^W z{X&tI?qmvGyX8BFTZ7X!6G-V#HL}yc`+P@8n8+3V97%7rf+>0KQ!8cfZAjO*;cvrqdQY@IzvVX%= z_Ml5XBxjPYhQx4}mmG-jYZh0PX8*bXWu6<}lL*KewM^-$85yXPw(VlGYAvqi896vK zdcbxEp3IyXdSi{UG%iHCZ?o;j?098QVN2XaGkKHIo3d|B(E?gY%GD<s!)mCuf(u(_^-? zZBtw|gEx2Zk7m6yhFd7v>X&uWyVhRY98!(m>b``(NqJnoCuyFSpvG)1-CZi)bJ6;f zdI2A?HS#*c#W&@R(^qFxyao?8b2~Z&sqi=qcKm|G@QtlB^T3tm&yh1Wa4oX}F8|9T zd!|y)z?3uIa&eslY=}I`lPm=%lSRS|O9fZOxf^f+pBGsGes!Hx;?y?)D;%bnx9cN{ z>UH9oFWxJeG^&wyzf>X)$#`s;5Ykx^QA%DFGd3lK)xwzaI_}@#aC?iEY>$ALv9EDowrVhgNY5J2#dr z!x@5nvUhN8^UI3BM8Lv>_WJEB>mGS(^f8Vi%T!yx(K}{U1XQ+;^|)ERYwPtHZjuq3 zz?rtYgC$M?bv&oZ!mx~<+pqXOZl^_35hkM#=GJFvE5SjtIj_1^O+H{wVR)R1_> zT(;QE>*KqQjn*fv+}AZ4CwwPX)YBM#1qVCnsx?=-licWW4YU}Xs}8pOS=*PPU4j{m znH!Y);6Cm!Tj9t0kz1cBC$wo|SSE?Gt{PivV7haac+h+FJ;R$y-r!mCCPV9;J?}j~l!_-(aIS9N7!kT0;+3Yerp6E$Lzl>VImi z9vu1)9X8g6f{hc~-<&x}&@eqMs-1x^T zHt_tnzhSXwZT6j(3@S4*;A;T4K@CVDXaGez=r<@&C=|!L5u*CV%w%RJ+b$O_%@L!0 zU)ic}X16A(jm47ouO57G>~85f7#o>|z_ zu6SNMv@pCaIwr82a6LLQc16D=)I7(vva?ajFo|E>z2MFHaM7cp_#rXeN8bV4>+D9> z3`Fvym60A?_v)(5jtTVu5MjCCdzSpkLD5nISZDIGs8(=fQGt?fr?%67+R86V@fv zTpfMWZlQZ5u)ycH^;CnH*7Q_%PzLCbwx$@&k=!pY96+1SIn6%BhVLuzeTivxUc)CoT`Jyp10RoOw@o|f`X>!OIKaMcJGxBkg&A8*kyC{fd9X$`esj00WggvUn_ZfDR*1r>PmL{9rLx8#cD}U+)YKC;wsH^I$ zjt&iS(aLVO)!t@ry_NV}-_a_#A^x-A-FI+SWazh^uv+Suaxdp?s|RsC?n{@M(`;#m zG_tzDv6PQ@7)(-`SQ)P#D}~eyB7R4btdND>ysf@%QKX%CHy_7?`ue2Qc6=7T7CF8` z>R>*v6l627pl7$V6VMuCs%CY$)K#>#qO9Jwrmx>F-{gJOIC&QGZsF**%WzOy_GF{c zoi*2eaFZJqC9afi6K}dXBy>}&BzNPRX`+d@&ZntEMdohF7NvQT1FJSm zwJ2t5_=@i@-n^f@NpJ0{c4vIxtr=OD=^d)Z)OsqJ9^ z&siDH_Yuu8vTtHP7Z~`VJH^ds$!*-=UB@iFyxSIb?XWvT3<1Qe1v*kSh^CImGKDPd z;62hv#}iun9pq$O`yEwfT?c}%%zsI#Al>jbv0azB1kX;X3|X80Kz0Ut_2|fLD@o8< zcz^qjuQE6<1P1g6Z|)=C-aV3;BMWygoVwp&S2J0e5~Lno3$nF zsuc$RCEh?|q$gW|s7V!byHA2Fw*&LzM`(7k&uG8?6Sve8lGTcGW-eFvEErr~zGCtQ z<+Gk`r|I7JTt2NPj)|0%Rr*Z+(sny9zdMcY4!4f3nmZUdTNLChUfrm$hIm{^4{aVq z4)zCYEOH07n!3I-K~0$In7NqOZbahj#s}6V#~zqpvSP;i3X}(vSK*p29^Vldz||H> z6TowXjc4HT_nN`OlIV>x!sNz^vZqOP#-L&W?a|@aMHV-!JI$gFW3Lr9Zk>x#Sns&S zJziEG6EdsO7jb8%a?sm>?uYGwjK~;euiH=3Y?tJ?#P%BNR~LWlaMmy`KWF)tTjh6G zh7&jkz6Q5Hcj;|KZ#uqQs7jM|2pSM|c+sEW2J-4ubQ`ph{hG@jn zqoG+S-6POcc9Gt2G$|wl{r^}x^JpmF_m3w60k?mNkT;>?x$dkUhp&##qKs z*(zI+eM{N0uVWd5tjRK#tYbz@)-fgqgE8Ybeb4V7=lF+n?&rDh=en==`~A8a=0T*Y zCK2hl^j9#9lzm~vbIr%)DV`t7GI{mb^ZriJO_CpR{ zN?HKLKM9nkr=IPzr_ZY>nhBCzFj+3PJ4`S49a6ljz1iZCx_Se{5)g#L4iH}vi#*lx z8`0!r>o||8+VXFa*^a}=dlhX7*`Y?8vh6=TR`VGTIpn>}r}}3>oLTnFN(){Sj+{M0 z;lhr+kp}`np@8AR7S5b;uf`6n%8Mos#;53;GZnP)xISa5VVBljKHL#~Vb z(vu7NXV-FWi=Xd~z}tm(sQ%RS)Y2($t@A(G24eM@p@J0)c5n=AB!+OLRH&qlW1nH0 zQh2jV!7#2jf=v)0{Oe(U>T4P!^V&WuDlJG>QBvMdqziC4}~s)26^C znpg#RR$3<$=APqMI`QX8ISB|o#$#Xx%BeLEH6Btjr6k6zpE$&h+LB7Sc1W0h>)2!7)EwdTKAx)?GXNJB&;2 zvx7938sSOlHFPBiy!!BVkjeIvE05)Te9Lrm>~pAwy3mFAra{FPFR`xVkY!-rFuHIM z2ODWA)n|#Ir+Z&MrN2KYLX8UBc#_X^suSn2r+(cmA`KW~nkDOl4Uh6eW8(j|J&)z# zb=jYJ{2bvd=0VuQJXWh>YN@={fkKG$nX1^KZK}LdTf@`pxe53utV^$iX278zw+{X= zwHzG@GA>QrHy9z>*$k~U+IZ+M-W ze2Bc$|9XN&)8zeg{5>qk=K!+OA*;Rw^CySEz_qJC=KO}RR-0!l3sg-tvGVCJj>rM0 zdmC;d7@w!h_m7;McLF`q<=Cvdy=i2E3$w+eCeVi}eT~XOtq|?a#3rx0FP`CqC_Jv0 z^*;xXYY`%8;D8kNO%#GKGP7{#IQhw&6I{@f0H?j0M$Ays?x@FL&#CHwQ)Dv-POsGP zo)ZkZKJI*L$X?U}A#CYUKoTF^qHH71cP}aTEXX46w5HU<(3s`@l~w5`KRQ1C^pj$YjAmkB(_Cx}Ir@)q4a; zcCX9|`2Oyx$T5sk&! zc;0C{U}``TP3m6I!#{|9CZTR{#N-a+x2O>MO(&4{t9>3jJrZAi|0g!ofchY@4J+Fr zxS6%oOn&`PV++CStJ&|rc;H8Q%{v|&9T=EOr0%{uuD#?oxTTff;s3?=!z?8h7qTH& za=^=bwTpCo6gxuSMc01MJpuU0FqGA~jD)VoW$2*lJC&GK_kYRmxo2HF)=j z*MMdiv0_naa6#S6J%vikX$$y~qg`bcrBi;5)WOiSOpSv+>;0=sF+5t3vM(_7O-}Iv zTe+v~y}{o-E?XWEz}vT3iR;UVygg2FAv&wZuv)=-ZW{B6BIo@8< zT1~8!w!F|pTdt2wJ-ad6yfhNLiXG*QO4!y9-EK-6IJ>&l+WNXtaHDllI(b1`%jd19 zk|EL-R(*#~MRjT!SCXCJbiFf_(=0)NC_r0#)9^%8J49#)BbJ*K)xtHEh{+R@^{Z%~ ztkY~uJMy^)innpi^8w>~kHX)|wEVWsA$lFtE~6!+c+4qDLC5ZbI^=x5(+>JpD` z;d(C>Y_9_B5c4S5hm1|XpgboZU@N9G7dq?b*BUGa%>Pu@ zkAn;CTqm2SM@1M3^I?|ks<6=vn8DVkw?$4_nv3#7r~4qn`_Z$Og=1A$I(xZCbsrI4 zQumchDZJ=PNnZENU1rmEnc(o;H-EO}Ge57#MDsK5#Iq`XB~DGA8Bs$H+1vA>A+L9N zn7kI%XO{v8&I~?}D8c8an|51+RuK$~Gj{!eVY1NL#|bmPo~c1VwxR!J%X2%} zCd{%FEWvLfm+;InbZ}#JYPmmR?xOupzk60jNk2TpWEj*!s(LU`kTJ3_(t03}V(;O& z`GGBSchg_);otO{zt5Kc_o|tC?j3#)(aQ~Q_!3C{cU=NAS}HHs(9bwnn;)`SJqIGW zSy!HGnK&luj&1+iOXK_{;m$d>Ba}L}kkr2r!YPA&t@WEBC8ktWqyrwZ`ucG9aWmCe9MXh$r?7T>cAxGbmZ&)lKkBCjyrxNW;%2XCE+T|?Y z$`84PF?a`PNJ?tbZI2E;)=RPS>;D$CW+N<-L@A5UeZLuY>t$rdqF@ZV5Y-v!$v-$gb5#MLmz+&#I6c^Dr} z&DSlr+ZT|*J%7H^mmoAFnzS0aIERx=v%q3H7_FuVOaMc~ckJ=pQ-^}@oae!e`qb6m z^E$C^4b1-Ac6x#w>$>%aO+lzkrB?O1YdCoWv(2~SRbGB(Wrp|gp1uC=ZH@`|VpoQz z{S>S~2HW4)@4CDfcO1_QefRG|Q(lTarNpM3fU%hmnX5j;N}iIno;J!j8;Yu^;Y)UN z0@Br=UffM-a3R*2?&A(@I|@}n)5NEoB|$gwk9pI-+qy&qyw_|E zvXz2HXligzc{b;xrlV&4`GPP}v(SD0(XhXgI3LLBjjg(vEfr37%rhYWj4OK_Q!~bY zp>k>J1d2T$mLgrNDc+29nrA;3uUS57&vaXA%#1l)qQ^{=Nem-l(oJ?*@7}dM3x>Ca zq_NNe#Y2EFqKLe0b8bhls28KH*Y4d8jVs};2`+aU-ySqS%VbRq-!Jq- z6y>3I8wc&LIyTDFck|a=33-^c3UH20NC)J(9PaU*!*T~EMtav`f6vVdi?bJkJ_deZ zSy&P>Uux^OPuzXx*W{i7dpw{V@AviZ`~k@lu_X>S55L~E+i|%1ej&Yg-L;PIEQbAA5Ez+wKiE4LpL;rO_cZZ?MF zL%Q`Vc7!iWTCJ1{acHXg027jcMLNv?+`jTCr4cTk8FkQl_$ChaXM+GX=%0AcU;~|o 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 Tk*a}-)-d;b-NA;5i%wKQX1)QuN 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 Date: Tue, 19 Dec 2023 13:17:26 +0700 Subject: [PATCH 30/80] Update frontend/src/app/components/transaction/transaction.component.ts Co-authored-by: mononaut <83316221+mononaut@users.noreply.github.com> --- .../src/app/components/transaction/transaction.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/transaction/transaction.component.ts b/frontend/src/app/components/transaction/transaction.component.ts index f110c0435..1ee8a3ad6 100644 --- a/frontend/src/app/components/transaction/transaction.component.ts +++ b/frontend/src/app/components/transaction/transaction.component.ts @@ -439,7 +439,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy { block_time: block.timestamp, }; this.stateService.markBlock$.next({ blockHeight: block.height }); - if (this.accelerationInfo && ['accelerating', 'mined', 'completed'].includes(this.accelerationInfo.status)) { + if (this.tx.acceleration || (this.accelerationInfo && ['accelerating', 'mined', 'completed'].includes(this.accelerationInfo.status))) { this.audioService.playSound('wind-chimes-harp-ascend'); } else { this.audioService.playSound('magic'); From 7f488f5b01048dce6552a69c72daa42e3147dbe9 Mon Sep 17 00:00:00 2001 From: natsee Date: Tue, 19 Dec 2023 14:40:37 +0100 Subject: [PATCH 31/80] Fade out the bottom of collapsed rbf history --- .../rbf-timeline/rbf-timeline.component.html | 4 ++-- .../rbf-timeline/rbf-timeline.component.scss | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html index 8a750e624..9ff35d669 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html @@ -1,6 +1,6 @@
    -
    +
    @@ -37,7 +37,7 @@
    -
    +
    diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss index 8afc3f026..c0b38b59d 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss @@ -31,6 +31,19 @@ -ms-overflow-style: none; scrollbar-width: none; + .fade-out { + position: relative; + + &::before { + content: ''; + position: absolute; + width: 100%; + height: 100%; + background: linear-gradient(to bottom, rgba(36, 39, 62, 0) 0%, rgba(36, 39, 62, 1) 100%); + z-index: 1; + } + } + &::-webkit-scrollbar { display: none; } @@ -197,6 +210,10 @@ &.fullrbf { border-right: solid 10px #1bd8f4; } + &.last-pipe { + height: 150px; + bottom: -42px; + } } .corner { From fc36e04dc0500c0132c2dd90de65a7c7cc124a23 Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 19 Dec 2023 08:20:21 -0700 Subject: [PATCH 32/80] update start9 os and icon --- README.md | 2 +- .../app/docs/api-docs/api-docs.component.html | 2 +- frontend/src/resources/profile/start9.png | Bin 14008 -> 49886 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e5779416d..e272c6b39 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Mempool can be conveniently installed on the following full-node distros: - [RaspiBlitz](https://github.com/rootzoll/raspiblitz) - [RoninDojo](https://code.samourai.io/ronindojo/RoninDojo) - [myNode](https://github.com/mynodebtc/mynode) -- [Start9](https://github.com/Start9Labs/embassy-os) +- [Start9](https://github.com/Start9Labs/start-os) - [nix-bitcoin](https://github.com/fort-nix/nix-bitcoin/blob/a1eacce6768ca4894f365af8f79be5bbd594e1c3/examples/configuration.nix#L129) **We highly recommend you deploy your own Mempool instance this way.** No matter which option you pick, you'll be able to get your own fully-sovereign instance of Mempool up quickly without needing to fiddle with any settings. diff --git a/frontend/src/app/docs/api-docs/api-docs.component.html b/frontend/src/app/docs/api-docs/api-docs.component.html index 49b11ad7b..77cf01326 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.html +++ b/frontend/src/app/docs/api-docs/api-docs.component.html @@ -373,7 +373,7 @@
    - We support one-click installation on a number of Raspberry Pi full-node distros including Umbrel, RaspiBlitz, MyNode, RoninDojo, and Start9's Embassy. + We support one-click installation on a number of Raspberry Pi full-node distros including Umbrel, RaspiBlitz, MyNode, RoninDojo, and StartOS. diff --git a/frontend/src/resources/profile/start9.png b/frontend/src/resources/profile/start9.png index 2cfe19ded9b1372494b8b11836ac62e5e9c90ad4..345a9869cf355fe25f27fa4d52132458a0d3f3aa 100644 GIT binary patch literal 49886 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
    -
    +
    @@ -50,15 +50,16 @@
    -
    - - - - -
    +
    +
    +
    + + + +
    diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss index c0b38b59d..8962be63c 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.scss @@ -30,31 +30,32 @@ overflow-x: auto; -ms-overflow-style: none; scrollbar-width: none; - - .fade-out { - position: relative; - - &::before { - content: ''; - position: absolute; - width: 100%; - height: 100%; - background: linear-gradient(to bottom, rgba(36, 39, 62, 0) 0%, rgba(36, 39, 62, 1) 100%); - z-index: 1; - } - } - + &::-webkit-scrollbar { display: none; } + } - .toggle-wrapper { + .fade-out { + position: relative; + + &::before { + content: ''; + position: absolute; width: 100%; - text-align: center; - margin: 1.25em 0 0; + height: 70px; + top: -70px; + background: linear-gradient(to bottom, rgba(36, 39, 62, 0) 0%, rgba(36, 39, 62, 1) 100%); + z-index: 1; } } + .toggle-wrapper { + width: 100%; + text-align: center; + margin: 1.25em 0 0; + } + .intervals, .nodes { min-width: 100%; display: flex; From c3675d5b1c4d347a38204051302064d1b5f9e320 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Wed, 20 Dec 2023 18:30:19 +0000 Subject: [PATCH 35/80] Fix widget responsiveness on acceleration dashboard --- .../accelerations-list.component.html | 4 +- .../accelerations-list.component.scss | 67 ++++++++++++++++--- .../accelerator-dashboard.component.scss | 3 + 3 files changed, 61 insertions(+), 13 deletions(-) diff --git a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.html b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.html index 32012d363..f2265282f 100644 --- a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.html +++ b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.html @@ -1,10 +1,10 @@ -
    +

    Accelerations

    -
    +
    diff --git a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss index 69aae18cc..4182abb68 100644 --- a/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss +++ b/frontend/src/app/components/acceleration/accelerations-list/accelerations-list.component.scss @@ -14,11 +14,24 @@ .container-xl.legacy { max-width: 1140px; } +.container-xl.widget-container { + min-height: 335px; + @media (max-width: 767px) { + min-height: auto; + } +} .container { max-width: 100%; } +.acceleration-list { + min-height: 295px; + @media (max-width: 767px) { + min-height: auto; + } +} + tr, td, th { border: 0px; padding-top: 0.65rem !important; @@ -51,34 +64,63 @@ tr, td, th { .txid { width: 25%; - @media (max-width: 1100px) { - padding-right: 10px; - } - @media (max-width: 875px) { - display: none; - } overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 30%; + @media (max-width: 1060px) and (min-width: 768px) { + display: none; + } + @media (max-width: 500px) { + display: none; + } } -.fee { - width: 35%; -} - -.block { +.fee-rate { width: 20%; + @media (max-width: 1060px) and (min-width: 768px) { + text-align: start !important; + } + @media (max-width: 500px) { + text-align: start !important; + } + @media (max-width: 840px) and (min-width: 768px) { + display: none; + } + @media (max-width: 410px) { + display: none; + } } .bid { width: 30%; + min-width: 150px; + @media (max-width: 840px) and (min-width: 768px) { + text-align: start !important; + } + @media (max-width: 410px) { + text-align: start !important; + } } .time { width: 25%; } +.fee { + width: 35%; + @media (max-width: 1060px) and (min-width: 768px) { + text-align: start !important; + } + @media (max-width: 500px) { + text-align: start !important; + } +} + +.block { + width: 20%; +} + .status { width: 20% } @@ -122,4 +164,7 @@ tr, td, th { flex-direction: row; align-items: center; justify-content: center; + @media (max-width: 767px) { + height: 100px; + } } diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss index 0d1c3b1c0..145569342 100644 --- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss +++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.scss @@ -139,6 +139,9 @@ } .list-card { height: 410px; + @media (max-width: 767px) { + height: auto; + } } .mempool-block-wrapper { From 07f9410d457ce2273259e2e5c6243750c7d4381d Mon Sep 17 00:00:00 2001 From: wiz Date: Thu, 21 Dec 2023 05:05:59 +0900 Subject: [PATCH 36/80] ops: Fix elements unix socket path --- production/nginx/upstream-esplora.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/production/nginx/upstream-esplora.conf b/production/nginx/upstream-esplora.conf index 941f43566..b7fbbf163 100644 --- a/production/nginx/upstream-esplora.conf +++ b/production/nginx/upstream-esplora.conf @@ -2,7 +2,7 @@ upstream esplora-bitcoin-mainnet { server unix:/bitcoin/socket/esplora-bitcoin-mainnet fail_timeout=10s max_fails=10 weight=99999; } upstream esplora-liquid-mainnet { - server unix:/elements/socket/esplora-liquid-mainnet fail_timeout=10s max_fails=10 weight=99999; + server unix:/elements/socket/esplora-elements-liquid fail_timeout=10s max_fails=10 weight=99999; } upstream esplora-bitcoin-testnet { server unix:/bitcoin/socket/esplora-bitcoin-testnet fail_timeout=10s max_fails=10 weight=99999; @@ -11,5 +11,5 @@ upstream esplora-bitcoin-signet { server unix:/bitcoin/socket/esplora-bitcoin-signet fail_timeout=10s max_fails=10 weight=99999; } upstream esplora-liquid-testnet { - server unix:/elements/socket/esplora-liquid-testnet fail_timeout=10s max_fails=10 weight=99999; + server unix:/elements/socket/esplora-elements-liquidtestnet fail_timeout=10s max_fails=10 weight=99999; } From 0370cc896c50e2236e4b8abc815fb4a3d1e6e653 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Thu, 21 Dec 2023 13:06:52 +0000 Subject: [PATCH 37/80] Fix missing mempool fee chart when webgl disabled --- .../mempool-block/mempool-block.component.ts | 1 + frontend/src/app/services/websocket.service.ts | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/frontend/src/app/components/mempool-block/mempool-block.component.ts b/frontend/src/app/components/mempool-block/mempool-block.component.ts index bb6e7791f..197b07247 100644 --- a/frontend/src/app/components/mempool-block/mempool-block.component.ts +++ b/frontend/src/app/components/mempool-block/mempool-block.component.ts @@ -64,6 +64,7 @@ export class MempoolBlockComponent implements OnInit, OnDestroy { }), tap(() => { this.stateService.markBlock$.next({ mempoolBlockIndex: this.mempoolBlockIndex }); + this.websocketService.startTrackMempoolBlock(this.mempoolBlockIndex); }) ); diff --git a/frontend/src/app/services/websocket.service.ts b/frontend/src/app/services/websocket.service.ts index 1e7f528eb..3c72252db 100644 --- a/frontend/src/app/services/websocket.service.ts +++ b/frontend/src/app/services/websocket.service.ts @@ -183,14 +183,18 @@ export class WebsocketService { } startTrackMempoolBlock(block: number) { - this.websocketSubject.next({ 'track-mempool-block': block }); - this.isTrackingMempoolBlock = true - this.trackingMempoolBlock = block + // skip duplicate tracking requests + if (this.trackingMempoolBlock !== block) { + this.websocketSubject.next({ 'track-mempool-block': block }); + this.isTrackingMempoolBlock = true; + this.trackingMempoolBlock = block; + } } stopTrackMempoolBlock() { this.websocketSubject.next({ 'track-mempool-block': -1 }); - this.isTrackingMempoolBlock = false + this.isTrackingMempoolBlock = false; + this.trackingMempoolBlock = null; } startTrackRbf(mode: 'all' | 'fullRbf') { From 40f2d553e20db8f8054f7ad909b830a1c47c7459 Mon Sep 17 00:00:00 2001 From: natsee Date: Fri, 22 Dec 2023 10:39:40 +0100 Subject: [PATCH 38/80] Fix faq nav bar overflow --- frontend/src/app/docs/api-docs/api-docs.component.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/docs/api-docs/api-docs.component.scss b/frontend/src/app/docs/api-docs/api-docs.component.scss index 8a4150262..27dfec61d 100644 --- a/frontend/src/app/docs/api-docs/api-docs.component.scss +++ b/frontend/src/app/docs/api-docs/api-docs.component.scss @@ -157,7 +157,7 @@ ul.no-bull.block-audit code{ position: fixed; top: 80px; overflow-y: auto; - height: calc(100vh - 50px); + height: calc(100vh - 75px); scrollbar-color: #2d3348 #11131f; scrollbar-width: thin; } From 93b074edf09b44c56c0b30cc21bc6d338d7f1c0b Mon Sep 17 00:00:00 2001 From: natsee Date: Wed, 27 Dec 2023 18:50:41 +0100 Subject: [PATCH 39/80] Add endpoints to docs api --- .../src/app/docs/api-docs/api-docs-data.ts | 1181 ++++++++++++++++- 1 file changed, 1172 insertions(+), 9 deletions(-) diff --git a/frontend/src/app/docs/api-docs/api-docs-data.ts b/frontend/src/app/docs/api-docs/api-docs-data.ts index 97be0c2b1..c5319bf2a 100644 --- a/frontend/src/app/docs/api-docs/api-docs-data.ts +++ b/frontend/src/app/docs/api-docs/api-docs-data.ts @@ -209,6 +209,114 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "general", + httpRequestMethod: "GET", + fragment: "get-price", + title: "GET Price", + description: { + default: "Returns bitcoin latest price denominated in main currencies." + }, + urlString: "/v1/prices", + showConditions: [""], + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + commonJS: ``, + esModule: ``, + curl: `/api/v1/prices`, + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [], + response: `{ + time: 1703252411, + USD: 43753, + EUR: 40545, + GBP: 37528, + CAD: 58123, + CHF: 37438, + AUD: 64499, + JPY: 6218915 +}` + }, + codeSampleTestnet: emptyCodeSample, + codeSampleSignet: emptyCodeSample, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, + { + type: "endpoint", + category: "general", + httpRequestMethod: "GET", + fragment: "get-historical-price", + title: "GET Historical Price", + description: { + default: "Returns bitcoin historical price denominated in main currencies." + }, + urlString: "/v1/historical-price", + showConditions: [""], + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + commonJS: ``, + esModule: ``, + curl: `/api/v1/historical-price`, + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [], + response: `{ + prices: [ + { + time: 1703692800, + USD: 42972, + EUR: 39590, + GBP: 36803, + CAD: 56883, + CHF: 36486, + AUD: 63006, + JPY: 6124530 + }, + ... + { + time: 1279497600, + USD: 0.08584, + EUR: -1, + GBP: -1, + CAD: -1, + CHF: -1, + AUD: -1, + JPY: -1 + } + ], + exchangeRates: { + USDEUR: 0.92, + USDGBP: 0.86, + USDCAD: 1.32, + USDCHF: 0.85, + USDAUD: 1.47, + USDJPY: 142.52 + } +} +` + }, + codeSampleTestnet: emptyCodeSample, + codeSampleSignet: emptyCodeSample, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, { type: "endpoint", category: "general", @@ -1409,20 +1517,20 @@ export const restApiDocsData = [ ]` }, codeSampleSignet: { - esModule: [`1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv`], - commonJS: [`1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv`], - curl: [`1wiz18xYmhRX6xStj2b9t1rwWX4GKUgpv`], + esModule: [`tb1pu8ysre22dcl6qy5m5w7mjwutw73w4u24slcdh4myq06uhr6q29dqwc3ckt`], + commonJS: [`tb1pu8ysre22dcl6qy5m5w7mjwutw73w4u24slcdh4myq06uhr6q29dqwc3ckt`], + curl: [`tb1pu8ysre22dcl6qy5m5w7mjwutw73w4u24slcdh4myq06uhr6q29dqwc3ckt`], response: `[ { - txid: "e58b47f657b496a083ad9a4fb10c744d5e993028efd9cfba149885334d98bdf5", + txid: "c56a054302df8f8f80c5ac6b86b24ed52bf41d64de640659837c56bc33d10c9e", vout: 0, status: { confirmed: true, - block_height: 698571, - block_hash: "00000000000000000007536c0a664a7d2a01c31569623183eba0768d9a0c163d", - block_time: 1630520708 + block_height: 174923, + block_hash: "000000750e335ff355be2e3754fdada30d107d7d916aef07e2f5d014bec845e5", + block_time: 1703321003 }, - value: 642070789 + value: 546 }, ... ]` @@ -1470,6 +1578,65 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "addresses", + httpRequestMethod: "GET", + fragment: "get-address-validate", + title: "GET Address Validation", + description: { + default: "Returns whether an address is valid or not. Available fields: isvalid (boolean), address (string), scriptPubKey (string), isscript (boolean), iswitness (boolean), witness_version (numeric, optional), and witness_program (string, optional).", + }, + urlString: "/v1/validate-address/:address", + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/validate-address/%{1}`, + commonJS: ``, + esModule: ``, + }, + codeSampleMainnet: { + curl: [`1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY`], + response: `{ + isvalid: true, + address: "1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY", + scriptPubKey: "76a914c825a1ecf2a6830c4401620c3a16f1995057c2ab88ac", + isscript: false, + iswitness: false +}` + }, + codeSampleTestnet: { + curl: [`tb1q4kgratttzjvkxfmgd95z54qcq7y6hekdm3w56u`], + response: `{ + isvalid: true, + address: "tb1q4kgratttzjvkxfmgd95z54qcq7y6hekdm3w56u", + scriptPubKey: "0014ad903ead6b149963276869682a54180789abe6cd", + isscript: false, + iswitness: true, + witness_version: 0, + witness_program: "ad903ead6b149963276869682a54180789abe6cd" +}` + }, + codeSampleSignet: { + curl: [`tb1pu8ysre22dcl6qy5m5w7mjwutw73w4u24slcdh4myq06uhr6q29dqwc3ckt`], + response: `{ + isvalid: true, + address: "tb1pu8ysre22dcl6qy5m5w7mjwutw73w4u24slcdh4myq06uhr6q29dqwc3ckt", + scriptPubKey: "5120e1c901e54a6e3fa0129ba3bdb93b8b77a2eaf15587f0dbd76403f5cb8f40515a", + isscript: true, + iswitness: true, + witness_version: 1, + witness_program: "e1c901e54a6e3fa0129ba3bdb93b8b77a2eaf15587f0dbd76403f5cb8f40515a" +}` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, { type: "category", category: "assets", @@ -2109,6 +2276,61 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "blocks", + httpRequestMethod: "GET", + fragment: "get-block-timestamp", + title: "GET Block Timestamp", + description: { + default: "Returns the height and the hash of the block closest to the given :timestamp." + }, + urlString: "/v1/mining/blocks/timestamp/:timestamp", + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/mining/blocks/timestamp/%{1}`, + commonJS: ``, + esModule: `` + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: ['1672531200'], + response: `{ + height: 769786, + hash: "000000000000000000017f6405c2382de84944eb21be9cec0379a735813f137b", + timestamp: "2022-12-31T23:30:31.000Z" +}` + }, + codeSampleTestnet: { + esModule: [], + commonJS: [], + curl: ['1672531200'], + response: `{ + height: 2413838, + hash: "00000000000000082888e2353ea4baaea04d2e0e88f2ee054ad2bbcc1d6a5469", + timestamp: "2022-12-31T23:57:26.000Z" +}` + }, + codeSampleSignet: { + esModule: [], + commonJS: [], + curl: ['1672531200'], + response: `{ + height: 123713, + hash: "0000010c6df8ffe1684ab9d7cfac69836a4538c057fab4571b809120fe486c96", + timestamp: "2022-12-31T23:55:56.000Z" +}` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, { type: "endpoint", category: "blocks", @@ -4042,6 +4264,101 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "mining", + httpRequestMethod: "GET", + fragment: "get-difficulty-adjustments", + title: "GET Difficulty Adjustments", + description: { + default: "

    Returns the record of difficulty adjustments over the specified trailing :interval:

    • Block timestamp
    • Block height
    • Difficulty
    • Difficulty change

    If no time interval is specified, all available data is returned." + }, + urlString: "/v1/mining/difficulty-adjustments/[:interval]", + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/mining/difficulty-adjustments/1m`, + commonJS: ``, + esModule: `` + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [], + response: `[ + [ + 1703311464, + 822528, + 72006146478567.1, + 1.06983 + ], + [ + 1702180644, + 820512, + 67305906902031.39, + 0.990408 + ], + [ + 1700957763, + 818496, + 67957790298897.88, + 1.0507 + ] +]` + }, + codeSampleTestnet: { + esModule: [], + commonJS: [], + curl: [], + response: `[ + [ + 1703429523, + 2544008, + 105074715.9955905, + 105075000 + ], + [ + 1703426009, + 2544005, + 1, + 0 + ], + [ + 1703422944, + 2544000, + 105074715.9955905, + 105075000 + ], + ... +]` + }, + codeSampleSignet: { + esModule: [], + commonJS: [], + curl: [], + response: `[ + [ + 1702402252, + 173376, + 0.002967416960321784, + 1.01893 + ], + [ + 1701214807, + 171360, + 0.002912289751655253, + 0.9652 + ] +]` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, { type: "endpoint", category: "mining", @@ -4559,6 +4876,407 @@ export const restApiDocsData = [ }, ... ] +}` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, + { + type: "endpoint", + category: "mining", + httpRequestMethod: "GET", + fragment: "get-block-predictions", + title: "GET Block Predictions", + description: { + default: "

    Returns average block health in the specified :timePeriod, ordered oldest to newest. :timePeriod can be any of the following: " + miningTimeIntervals + ".

    For 24h and 3d time periods, every block is included and figures are exact (not averages). For the 1w time period, figures may be averages depending on how fast blocks were found around a particular timestamp. For other time periods, figures are averages.

    " + }, + urlString: ["/v1/mining/blocks/predictions/:timePeriod"], + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/mining/blocks/predictions/%{1}`, + commonJS: ``, + esModule: `` + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [`3y`], + response: `[ + [ + 1687247274, + 777625, + 100 + ], + [ + 1687066238, + 788621, + 99.85 + ], + [ + 1687263518, + 795182, + 99.46 + ], + [ + 1687312271, + 795260, + 100 + ], + ... +]` + }, + codeSampleTestnet: { + esModule: [], + commonJS: [], + curl: [`3y`], + response: `[ + [ + 1687246773, + 2429248, + 100 + ], + [ + 1687285500, + 2438380, + 100 + ], + [ + 1687342820, + 2438467, + 100 + ], + [ + 1687372143, + 2438522, + 100 + ], + ... +]` + }, + codeSampleSignet: { + esModule: [], + commonJS: [], + curl: [`3y`], + response: `[ + [ + 1687246696, + 129639, + 0 + ], + [ + 1687303289, + 148191, + 0 + ], + [ + 1687315093, + 148218, + 0 + ], + [ + 1687368211, + 148312, + 0 + ], + ... +]` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, + { + type: "endpoint", + category: "mining", + httpRequestMethod: "GET", + fragment: "get-block-audit-score", + title: "GET Block Audit Score", + description: { + default: "Returns the block audit score for the specified :blockHash. Available fields: hash, matchRate, expectedFees, and expectedWeight." + }, + urlString: ["/v1/mining/blocks/audit/score/:blockHash"], + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/mining/blocks/audit/score/%{1}`, + commonJS: ``, + esModule: `` + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [`000000000000000000032535698c5b0c48283b792cf86c1c6e36ff84464de785`], + response: `{ + hash: "000000000000000000032535698c5b0c48283b792cf86c1c6e36ff84464de785", + matchRate: 99.66, + expectedFees: 12090955, + expectedWeight: 3991988 +}` + }, + codeSampleTestnet: { + esModule: [], + commonJS: [], + curl: [`000000000000025a66f30a181e438b9f65ef33cec3014b7a4ff4c7578289cd6e`], + response: `{ + hash: "000000000000025a66f30a181e438b9f65ef33cec3014b7a4ff4c7578289cd6e", + matchRate: 100, + expectedFees: 579169, + expectedWeight: 12997 +}` + }, + codeSampleSignet: { + esModule: [], + commonJS: [], + curl: [`000000c1491d7d4229d4bf07e0dcaa7e396767b45be388e1174c7439a9490121`], + response: `{ + hash: "000000c1491d7d4229d4bf07e0dcaa7e396767b45be388e1174c7439a9490121", + matchRate: 100, + expectedFees: 80520, + expectedWeight: 16487 +}` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, + { + type: "endpoint", + category: "mining", + httpRequestMethod: "GET", + fragment: "get-blocks-audit-scores", + title: "GET Blocks Audit Scores", + description: { + default: "Returns blocks audit score for the past 16 blocks. If :startHeight is specified, the past 15 blocks before (and including) :startHeight are returned. Available fields: hash, matchRate, expectedFees, and expectedWeight." + }, + urlString: ["/v1/mining/blocks/audit/scores/:startHeight"], + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/mining/blocks/audit/scores/%{1}`, + commonJS: ``, + esModule: `` + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [`820000`], + response: `[ + { + hash: "000000000000000000034cd3689507da0386d3d1790dd56f2e6945e650e02c74", + matchRate: 100, + expectedFees: 225828975, + expectedWeight: 3991756 + }, + { + hash: "00000000000000000000b3ad97907e99c54e6b9145a8f77842e59d9c0c8377cf", + matchRate: 100, + expectedFees: 295107022, + expectedWeight: 3991752 + }, + ... +]` + }, + codeSampleTestnet: { + esModule: [], + commonJS: [], + curl: [`2566570`], + response: `[ + { + hash: "00000000000002e7e96e7b5ee04a5fbb3ef9575a9f4a99effb32a8a89d9d2f19", + matchRate: 100, + expectedFees: 964677, + expectedWeight: 24959 + }, + { + hash: "00000000000003bd3962806d0e06d9982eb2e06aeba912687b2bac3668db32aa", + matchRate: 100, + expectedFees: 631200, + expectedWeight: 15516 + }, + ... +]` + }, + codeSampleSignet: { + esModule: [], + commonJS: [], + curl: [`175504`], + response: `[ + { + hash: "00000012d54289925efc151f2e111e0775e80c3b6bb4b0dcd3ff01dec4bbc5d0", + matchRate: 100, + expectedFees: 4767, + expectedWeight: 2524 + }, + { + hash: "00000031e269cf0b567260b01ae11453175f4598fdb4f1908c5e2f4265b9d93a", + matchRate: 100, + expectedFees: 9090, + expectedWeight: 1851 + }, + ... +]` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, + { + type: "endpoint", + category: "mining", + httpRequestMethod: "GET", + fragment: "get-block-audit-summary", + title: "GET Block Audit Summary", + description: { + default: "Returns the block audit summary for the specified :blockHash. Available fields: height, id, timestamp, template, missingTxs, addedTxs, freshTxs, sigopTxs, fullrbfTxs, acceleratedTxs, matchRate, expectedFees, and expectedWeight." + }, + urlString: ["/v1/block/:blockHash/audit-summary"], + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/block/%{1}/audit-summary`, + commonJS: ``, + esModule: `` + }, + codeSampleMainnet: { + esModule: [], + commonJS: [], + curl: [`00000000000000000000f218ceda7a5d9c289040b9c3f05ef9f7c2f4930e0123`], + response: `{ + height: 822418, + id: "00000000000000000000f218ceda7a5d9c289040b9c3f05ef9f7c2f4930e0123", + timestamp: 1703262962, + template: [ + { + txid: "1de119e4fe0fb92378de74a59fec337c39d505bbc0d04d20d151cc3fb7a91bf0", + fee: 92000, + vsize: 140.25, + value: 354245800, + rate: 655.9714795008913, + flags: 1099511631881 + }, + ... + ], + missingTxs: [], + addedTxs: [ + "3036565d1af6c5b14876a255cdf06214aa350e62154d1ce8619c8e933d0526f8", + "aaa9d8e8f1de712574182a618b4d608f96f39bfc55e296d2e5904561cdef2e77", + ... + ], + freshTxs: [ + "8ede292d8f0319cbe79fff9fd47564cd7f78fad74d7c506d2b157399ff41d904" + ], + sigopTxs: [], + fullrbfTxs: [ + "271e7792910a4ea134c02c03c9d7477b32a8531a5dd92fbc4dbf3ca70614fcce", + "634a5b2de393f0f5b4eeb335bee75c1779b1f2308a07e86cafb95894aa4734d0", + ... + ], + acceleratedTxs: [], + matchRate: 100, + expectedFees: 169464627, + expectedWeight: 3991702 +}` + }, + codeSampleTestnet: { + esModule: [], + commonJS: [], + curl: [`000000000000007cfba94e051326b3546c968a188a7e12e340a78cefc586bfe3`], + response: `{ + height: 2566708, + id: "000000000000007cfba94e051326b3546c968a188a7e12e340a78cefc586bfe3", + timestamp: 1703684826, + template: [ + { + txid: "6556caa3c6bff537f04837a6f7182dd7a253f31a46de4f21dec9584720156d35", + fee: 109707, + vsize: 264.75, + value: 456855, + rate: 414.37960339943345, + flags: 9895621445642 + }, + { + txid: "53b7743b8cfa0108dbcdc7c2f5e661b9d8f56216845a439449d7f9dfc466b147", + fee: 74640, + vsize: 215.5, + value: 19063915, + rate: 348.5338491295938, + flags: 1099528491017 + }, + ... + ], + missingTxs: [ + "8f2eae756119e43054ce1014a06e81d612113794d8b519e6ff393d7e0023396a", + "012b44b0fc0fddc549a056c85850f03a83446c843504c588cd5829873b30f5a9", + ... + ], + addedTxs: [], + freshTxs: [ + "af36a8b88f6c19f997614dfc8a41395190eaf496a49e8db393dacb770999abd5", + "fdfa272c8fe069573b964ddad605d748d8c737e94dfcd09bddaae0ee0a2445df", + ... + ], + sigopTxs: [], + fullrbfTxs: [], + acceleratedTxs: [], + matchRate: 86.96, + expectedFees: 1541639, + expectedWeight: 26425 +}` + }, + codeSampleSignet: { + esModule: [], + commonJS: [], + curl: [`0000008acf5177d07f1d648f4d54f26095936a5d29a0a6145dd75a0415e63c0f`], + response: `{ + height: 175519, + id: "0000008acf5177d07f1d648f4d54f26095936a5d29a0a6145dd75a0415e63c0f", + timestamp: 1703682844, + template: [ + { + txid: "f95b38742c483b81dc4ff49a803bae7625f1596ec5756c944d7586dfe8b38250", + fee: 3766, + vsize: 172.25, + value: 115117171776, + rate: 21.86357039187228, + flags: 1099528425481 + }, + { + txid: "8665c4d05732c930c2037bc0220e4ab9b1b64ce3302363ff7d118827c7347b52", + fee: 3766, + vsize: 172.25, + value: 115116509429, + rate: 21.86357039187228, + flags: 1099528425481 + }, + ... + ], + missingTxs: [], + addedTxs: [], + freshTxs: [], + sigopTxs: [], + fullrbfTxs: [], + acceleratedTxs: [], + matchRate: 100, + expectedFees: 10494, + expectedWeight: 6582 }` }, codeSampleLiquid: emptyCodeSample, @@ -5127,6 +5845,267 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "mempool", + httpRequestMethod: "GET", + fragment: "get-mempool-rbf", + title: "GET Mempool RBF Transactions", + description: { + default: "Returns the list of mempool transactions that are part of a RBF chain." + }, + urlString: "/v1/replacements", + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/replacements`, + commonJS: ``, + esModule: ``, + }, + codeSampleMainnet: { + curl: [], + response: `[ + { + tx: { + txid: "1ca4b22006e57b1b13f5cc89a41cf7c9e99fe225aabf407251e4fe0268f22d93", + fee: 14983, + vsize: 141.5, + value: 343934, + rate: 105.886925795053, + rbf: true, + fullRbf: false + }, + time: 1703331467, + fullRbf: false, + replaces: [ + { + tx: { + txid: "9f8e30674af641bb153a35254d539468e1d847b16bbdc13ce23b5a970b0b11cf", + fee: 13664, + vsize: 141.25, + value: 345253, + rate: 96.7362831858407, + rbf: true + }, + time: 1703331398, + interval: 69, + fullRbf: false, + replaces: [] + } + ] + }, + ... +]` + }, + codeSampleTestnet: { + curl: [], + response: `[ + { + tx: { + txid: "7766e3f008011b776905f96fcad9d4a7b75d1b368d1e77db2901254f1fa8357d", + fee: 9101, + vsize: 317, + value: 147706698, + rate: 28.709779179810724, + rbf: true, + fullRbf: false + }, + time: 1703331325, + fullRbf: false, + replaces: [ + { + tx: { + txid: "43055f6e5750c6aa0c2214e59e99f367398d96bde935e7666c3e648d249a4e40", + fee: 7000, + vsize: 317, + value: 147708799, + rate: 22.082018927444796, + rbf: true + }, + time: 1703331154, + interval: 171, + fullRbf: false, + replaces: [] + } + ] + }, + ... +]` + }, + codeSampleSignet: { + curl: [], + response: `[ + { + tx: { + txid: "13985a5717a1ea54ce720cd6b70421b1667061be491a6799acf6dea01c551248", + fee: 5040, + vsize: 215.5, + value: 762745, + rate: 23.387470997679813, + rbf: true, + fullRbf: false, + mined: true + }, + time: 1703316271, + fullRbf: false, + replaces: [ + { + tx: { + txid: "eac5ec8487414c955f4a5d3b2e516c351aec5299f1335f9019a00907962386ce", + fee: 4560, + vsize: 215.25, + value: 763225, + rate: 21.18466898954704, + rbf: true + }, + time: 1703316270, + interval: 1, + fullRbf: false, + replaces: [] + } + ], + mined: true + } +]` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, + { + type: "endpoint", + category: "mempool", + httpRequestMethod: "GET", + fragment: "get-mempool-fullrbf", + title: "GET Mempool Full RBF Transactions", + description: { + default: "Returns the list of mempool transactions that are part of a Full-RBF chain." + }, + urlString: "/v1/fullrbf/replacements", + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/fullrbf/replacements`, + commonJS: ``, + esModule: ``, + }, + codeSampleMainnet: { + curl: [], + response: `[ + { + tx: { + txid: "25e2bfaf0e0821e5cb71f11e460b2f71e1d5a3755015de42544afa5fbad6d443", + fee: 24436, + vsize: 297.75, + value: 273418, + rate: 82.0688497061293, + rbf: false, + fullRbf: true + }, + time: 1703409882, + fullRbf: true, + replaces: [ + { + tx: { + txid: "07d501e8ad4a25f07f3ced0a6102741720f710765e6fdb2eb966ba0df657997a", + fee: 24138, + vsize: 297.75, + value: 273716, + rate: 81.06801007556675, + rbf: false + }, + time: 1703409853, + interval: 29, + fullRbf: true, + replaces: [] + } + ] + }, + ... +]` + }, + codeSampleTestnet: { + curl: [], + response: `[ + { + tx: { + txid: "25e2bfaf0e0821e5cb71f11e460b2f71e1d5a3755015de42544afa5fbad6d443", + fee: 24436, + vsize: 297.75, + value: 273418, + rate: 82.0688497061293, + rbf: false, + fullRbf: true + }, + time: 1703409882, + fullRbf: true, + replaces: [ + { + tx: { + txid: "07d501e8ad4a25f07f3ced0a6102741720f710765e6fdb2eb966ba0df657997a", + fee: 24138, + vsize: 297.75, + value: 273716, + rate: 81.06801007556675, + rbf: false + }, + time: 1703409853, + interval: 29, + fullRbf: true, + replaces: [] + } + ] + }, + ... +]` + }, + codeSampleSignet: { + curl: [], + response: `[ + { + tx: { + txid: "25e2bfaf0e0821e5cb71f11e460b2f71e1d5a3755015de42544afa5fbad6d443", + fee: 24436, + vsize: 297.75, + value: 273418, + rate: 82.0688497061293, + rbf: false, + fullRbf: true + }, + time: 1703409882, + fullRbf: true, + replaces: [ + { + tx: { + txid: "07d501e8ad4a25f07f3ced0a6102741720f710765e6fdb2eb966ba0df657997a", + fee: 24138, + vsize: 297.75, + value: 273716, + rate: 81.06801007556675, + rbf: false + }, + time: 1703409853, + interval: 29, + fullRbf: true, + replaces: [] + } + ] + }, + ... +]` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, { type: "category", category: "transactions", @@ -5143,7 +6122,7 @@ export const restApiDocsData = [ description: { default: "Returns the ancestors and the best descendant fees for a transaction." }, - urlString: "/v1/fees/cpfp", + urlString: "/v1/cpfp", showConditions: bitcoinNetworks.concat(liquidNetworks), showJsExamples: showJsExamplesDefault, codeExample: { @@ -6000,6 +6979,148 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "transactions", + httpRequestMethod: "GET", + fragment: "get-transaction-rbf-history", + title: "GET Transaction RBF History", + description: { + default: "Returns the RBF tree history of a transaction." + }, + urlString: "v1/tx/:txId/rbf", + showConditions: bitcoinNetworks, + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/tx/%{1}/rbf`, + commonJS: ``, + esModule: ``, + }, + codeSampleMainnet: { + curl: [`2e95ff9094df9f3650e3f2abc189250760162be89a88f9f2f23301c7cb14b8b4`], + response: `{ + replacements: { + tx: { + txid: "2e95ff9094df9f3650e3f2abc189250760162be89a88f9f2f23301c7cb14b8b4", + fee: 1668, + vsize: 276.75, + value: 14849, + rate: 4.824207492795389, + rbf: false, + fullRbf: true + }, + time: 1703240261, + fullRbf: true, + replaces: [ + { + tx: { + txid: "3f4670463daadffed07d7a1060071b07f7e81a2566eca21d78bb513cbf21c82a", + fee: 420, + vsize: 208.25, + value: 4856, + rate: 2.0168067226890756, + rbf: false + }, + time: 1702870898, + interval: 369363, + fullRbf: true, + replaces: [] + } + ... + ] + }, + replaces: [ + "3f4670463daadffed07d7a1060071b07f7e81a2566eca21d78bb513cbf21c82a", + "92f9b4f719d0ffc9035d3a9767d80c940cecbc656df2243bafd33f52b583ee92" + ] +}` + }, + codeSampleTestnet: { + curl: [`5faaa30530bee55de8cc896bdf48f803c2274a94bffc2842386bec2a8bf7a813`], + response: `{ + replacements: { + tx: { + txid: "5faaa30530bee55de8cc896bdf48f803c2274a94bffc2842386bec2a8bf7a813", + fee: 9101, + vsize: 318, + value: 148022607, + rate: 28.61949685534591, + rbf: true, + fullRbf: false, + mined: true + }, + time: 1703322610, + fullRbf: false, + replaces: [ + { + tx: { + txid: "06e69641fa889fe9148669ac2904929004e7140087bedaec8c8e4e05aabded52", + fee: 7000, + vsize: 318, + value: 148024708, + rate: 22.0125786163522, + rbf: true + }, + time: 1703322602, + interval: 8, + fullRbf: false, + replaces: [] + } + ], + mined: true + }, + replaces: [ + "06e69641fa889fe9148669ac2904929004e7140087bedaec8c8e4e05aabded52" + ] +}` + }, + codeSampleSignet: { + curl: [`13985a5717a1ea54ce720cd6b70421b1667061be491a6799acf6dea01c551248`], + response: `{ + replacements: { + tx: { + txid: "13985a5717a1ea54ce720cd6b70421b1667061be491a6799acf6dea01c551248", + fee: 5040, + vsize: 215.5, + value: 762745, + rate: 23.387470997679813, + rbf: true, + fullRbf: false, + mined: true + }, + time: 1703316272, + fullRbf: false, + replaces: [ + { + tx: { + txid: "eac5ec8487414c955f4a5d3b2e516c351aec5299f1335f9019a00907962386ce", + fee: 4560, + vsize: 215.25, + value: 763225, + rate: 21.18466898954704, + rbf: true + }, + time: 1703316270, + interval: 2, + fullRbf: false, + replaces: [] + } + ], + mined: true + }, + replaces: [ + "eac5ec8487414c955f4a5d3b2e516c351aec5299f1335f9019a00907962386ce" + ] +}` + }, + codeSampleLiquid: emptyCodeSample, + codeSampleLiquidTestnet: emptyCodeSample, + codeSampleBisq: emptyCodeSample, + } + } + }, { type: "endpoint", category: "transactions", @@ -6098,6 +7219,48 @@ export const restApiDocsData = [ } } }, + { + type: "endpoint", + category: "transactions", + httpRequestMethod: "GET", + fragment: "get-transaction-times", + title: "GET Transaction Times", + description: { + default: "Returns the timestamps when a list of unconfirmed transactions was initially observed in the mempool. If a transaction is not found in the mempool or has been mined, the timestamp will be 0." + }, + urlString: "/v1/transaction-times", + showConditions: bitcoinNetworks.concat(liquidNetworks), + showJsExamples: showJsExamplesDefaultFalse, + codeExample: { + default: { + codeTemplate: { + curl: `/api/v1/transaction-times?txId[]=%{1}&txId[]=%{2}`, + commonJS: ``, + esModule: ``, + }, + codeSampleMainnet: { + curl: ['51545ef0ec7f09196e60693b59369a134870985c8a90e5d42655b191de06285e', '6086089bd1c56a9c42a39d470cdfa7c12d4b52bf209608b390dfc4943f2d3851'], + response: `[1703082129,1702325558]` + }, + codeSampleTestnet: { + curl: ['25e7a95ebf10ed192ee91741653d8d970ac88f8e0cd6fb14cc6c7145116d3964', '1e158327e52acae35de94962e60e53fc70f6b175b0cfc3e2058bed4b895203b4'], + response: `[1703267563,1703267322]` + }, + codeSampleSignet: { + curl: ['8af0c5199acd89621244f2f61107fe5a9c7c7aad54928e8400651d03ca949aeb', '08f840f7b0c33c5b0fdadf1666e8a8c206836993d95fc1eeeef39b5ef9de03d0'], + response: `[1703267652,1703267696]` + }, + codeSampleLiquid: { + curl: ['6091498f06a3054f82a0c3e5be0a23030185c658dc3568684b0bccc4e759be11', '631212a073aa4ca392e3aeb469d1366ec2ee288988b106e4a6fc8dae8c4d7a9a'], + response: `[1703267652,1703267696]`, + }, + codeSampleLiquidTestnet: { + curl: ['fa8d43e47b2c4bbee12fd8bc1c7440028be2da6ac0f1df6ac77c983938c503fb', '26b12cd450f8fa8b6a527578db218bf212a60b2d5eb65c168f8eb3be6f5fd991'], + response: `[1703268185,1703268209]`, + }, + } + } + }, { type: "endpoint", category: "transactions", From d2a5adbd9d234aa5023cd43d7c73eb8b35902944 Mon Sep 17 00:00:00 2001 From: natsee Date: Thu, 28 Dec 2023 15:34:36 +0100 Subject: [PATCH 40/80] Fix duplicate address field in search results --- .../search-form/search-results/search-results.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/search-form/search-results/search-results.component.html b/frontend/src/app/components/search-form/search-results/search-results.component.html index d4f68edbd..6c096fc4e 100644 --- a/frontend/src/app/components/search-form/search-results/search-results.component.html +++ b/frontend/src/app/components/search-form/search-results/search-results.component.html @@ -35,7 +35,7 @@ - +
    Bitcoin Addresses
    + + + +
    TXIDAccelerated
    Accelerated
    diff --git a/frontend/src/app/components/block/block-preview.component.ts b/frontend/src/app/components/block/block-preview.component.ts index c4dfe40df..49417508f 100644 --- a/frontend/src/app/components/block/block-preview.component.ts +++ b/frontend/src/app/components/block/block-preview.component.ts @@ -2,7 +2,7 @@ import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/co import { ActivatedRoute, ParamMap } from '@angular/router'; import { ElectrsApiService } from '../../services/electrs-api.service'; import { switchMap, tap, throttleTime, catchError, shareReplay, startWith, pairwise, filter } from 'rxjs/operators'; -import { of, Subscription, asyncScheduler } from 'rxjs'; +import { of, Subscription, asyncScheduler, forkJoin } from 'rxjs'; import { StateService } from '../../services/state.service'; import { SeoService } from '../../services/seo.service'; import { OpenGraphService } from '../../services/opengraph.service'; @@ -121,21 +121,37 @@ export class BlockPreviewComponent implements OnInit, OnDestroy { this.overviewSubscription = block$.pipe( startWith(null), pairwise(), - switchMap(([prevBlock, block]) => this.apiService.getStrippedBlockTransactions$(block.id) - .pipe( - catchError((err) => { - this.overviewError = err; - this.openGraphService.fail('block-viz-' + this.rawId); - return of([]); - }), - switchMap((transactions) => { - return of({ transactions, direction: 'down' }); - }) - ) + switchMap(([prevBlock, block]) => { + return forkJoin([ + this.apiService.getStrippedBlockTransactions$(block.id) + .pipe( + catchError((err) => { + this.overviewError = err; + this.openGraphService.fail('block-viz-' + this.rawId); + return of([]); + }), + switchMap((transactions) => { + return of(transactions); + }) + ), + block.height > 819500 ? this.apiService.getAccelerationHistory$({ blockHash: block.id }) : of([]) + ]); + } ), ) - .subscribe(({transactions, direction}: {transactions: TransactionStripped[], direction: string}) => { + .subscribe(([transactions, accelerations]) => { this.strippedTransactions = transactions; + + const acceleratedInBlock = {}; + for (const acc of accelerations) { + acceleratedInBlock[acc.txid] = acc; + } + for (const tx of transactions) { + if (acceleratedInBlock[tx.txid]) { + tx.acc = true; + } + } + this.isLoadingOverview = false; if (this.blockGraph) { this.blockGraph.destroy(); diff --git a/frontend/src/app/components/block/block.component.ts b/frontend/src/app/components/block/block.component.ts index bb83494c5..d3fef00a6 100644 --- a/frontend/src/app/components/block/block.component.ts +++ b/frontend/src/app/components/block/block.component.ts @@ -328,17 +328,28 @@ export class BlockComponent implements OnInit, OnDestroy { this.overviewError = err; return of(null); }) - ) + ), + block.height > 819500 ? this.apiService.getAccelerationHistory$({ blockHash: block.id }) : of([]) ]); }) ) - .subscribe(([transactions, blockAudit]) => { + .subscribe(([transactions, blockAudit, accelerations]) => { if (transactions) { this.strippedTransactions = transactions; } else { this.strippedTransactions = []; } + const acceleratedInBlock = {}; + for (const acc of accelerations) { + acceleratedInBlock[acc.txid] = acc; + } + for (const tx of transactions) { + if (acceleratedInBlock[tx.txid]) { + tx.acc = true; + } + } + this.blockAudit = null; if (transactions && blockAudit) { const inTemplate = {}; From fab82551cfa6e6a16c3d5d24e9fc753385d47ce3 Mon Sep 17 00:00:00 2001 From: wiz Date: Sun, 31 Dec 2023 03:22:14 +0900 Subject: [PATCH 42/80] Remove old GPLv3 license file, rename AGPLv3 license to COPYING --- LICENSE.AGPL-3.md => COPYING.md | 0 LICENSE.GPL-3.md | 675 -------------------------------- 2 files changed, 675 deletions(-) rename LICENSE.AGPL-3.md => COPYING.md (100%) delete mode 100644 LICENSE.GPL-3.md diff --git a/LICENSE.AGPL-3.md b/COPYING.md similarity index 100% rename from LICENSE.AGPL-3.md rename to COPYING.md diff --git a/LICENSE.GPL-3.md b/LICENSE.GPL-3.md deleted file mode 100644 index 2fb2e74d8..000000000 --- a/LICENSE.GPL-3.md +++ /dev/null @@ -1,675 +0,0 @@ -### GNU GENERAL PUBLIC LICENSE - -Version 3, 29 June 2007 - -Copyright (C) 2007 Free Software Foundation, Inc. - - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - -### Preamble - -The GNU General Public License is a free, copyleft license for -software and other kinds of works. - -The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom -to share and change all versions of a program--to make sure it remains -free software for all its users. We, the Free Software Foundation, use -the GNU General Public License for most of our software; it applies -also to any other work released this way by its authors. You can apply -it to your programs, too. - -When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - -To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you -have certain responsibilities if you distribute copies of the -software, or if you modify it: responsibilities to respect the freedom -of others. - -For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - -Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - -Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the -manufacturer can do so. This is fundamentally incompatible with the -aim of protecting users' freedom to change the software. The -systematic pattern of such abuse occurs in the area of products for -individuals to use, which is precisely where it is most unacceptable. -Therefore, we have designed this version of the GPL to prohibit the -practice for those products. If such problems arise substantially in -other domains, we stand ready to extend this provision to those -domains in future versions of the GPL, as needed to protect the -freedom of users. - -Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish -to avoid the special danger that patents applied to a free program -could make it effectively proprietary. To prevent this, the GPL -assures that patents cannot be used to render the program non-free. - -The precise terms and conditions for copying, distribution and -modification follow. - -### TERMS AND CONDITIONS - -#### 0. Definitions. - -"This License" refers to version 3 of the GNU General Public License. - -"Copyright" also means copyright-like laws that apply to other kinds -of works, such as semiconductor masks. - -"The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - -To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of -an exact copy. The resulting work is called a "modified version" of -the earlier work or a work "based on" the earlier work. - -A "covered work" means either the unmodified Program or a work based -on the Program. - -To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - -To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user -through a computer network, with no transfer of a copy, is not -conveying. - -An interactive user interface displays "Appropriate Legal Notices" to -the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - -#### 1. Source Code. - -The "source code" for a work means the preferred form of the work for -making modifications to it. "Object code" means any non-source form of -a work. - -A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - -The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - -The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - -The Corresponding Source need not include anything that users can -regenerate automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same -work. - -#### 2. Basic Permissions. - -All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - -You may make, run and propagate covered works that you do not convey, -without conditions so long as your license otherwise remains in force. -You may convey covered works to others for the sole purpose of having -them make modifications exclusively for you, or provide you with -facilities for running those works, provided that you comply with the -terms of this License in conveying all material for which you do not -control copyright. Those thus making or running the covered works for -you must do so exclusively on your behalf, under your direction and -control, on terms that prohibit them from making any copies of your -copyrighted material outside their relationship with you. - -Conveying under any other circumstances is permitted solely under the -conditions stated below. Sublicensing is not allowed; section 10 makes -it unnecessary. - -#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - -No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - -When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such -circumvention is effected by exercising rights under this License with -respect to the covered work, and you disclaim any intention to limit -operation or modification of the work as a means of enforcing, against -the work's users, your or third parties' legal rights to forbid -circumvention of technological measures. - -#### 4. Conveying Verbatim Copies. - -You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - -You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - -#### 5. Conveying Modified Source Versions. - -You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these -conditions: - -- a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. -- b) The work must carry prominent notices stating that it is - released under this License and any conditions added under - section 7. This requirement modifies the requirement in section 4 - to "keep intact all notices". -- c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. -- d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - -A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - -#### 6. Conveying Non-Source Forms. - -You may convey a covered work in object code form under the terms of -sections 4 and 5, provided that you also convey the machine-readable -Corresponding Source under the terms of this License, in one of these -ways: - -- a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. -- b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the Corresponding - Source from a network server at no charge. -- c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. -- d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. -- e) Convey the object code using peer-to-peer transmission, - provided you inform other peers where the object code and - Corresponding Source of the work are being offered to the general - public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - -A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, -family, or household purposes, or (2) anything designed or sold for -incorporation into a dwelling. In determining whether a product is a -consumer product, doubtful cases shall be resolved in favor of -coverage. For a particular product received by a particular user, -"normally used" refers to a typical or common use of that class of -product, regardless of the status of the particular user or of the way -in which the particular user actually uses, or expects or is expected -to use, the product. A product is a consumer product regardless of -whether the product has substantial commercial, industrial or -non-consumer uses, unless such uses represent the only significant -mode of use of the product. - -"Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to -install and execute modified versions of a covered work in that User -Product from a modified version of its Corresponding Source. The -information must suffice to ensure that the continued functioning of -the modified object code is in no case prevented or interfered with -solely because modification has been made. - -If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - -The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or -updates for a work that has been modified or installed by the -recipient, or for the User Product in which it has been modified or -installed. Access to a network may be denied when the modification -itself materially and adversely affects the operation of the network -or violates the rules and protocols for communication across the -network. - -Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - -#### 7. Additional Terms. - -"Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - -Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders -of that material) supplement the terms of this License with terms: - -- a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or -- b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or -- c) Prohibiting misrepresentation of the origin of that material, - or requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or -- d) Limiting the use for publicity purposes of names of licensors - or authors of the material; or -- e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or -- f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions - of it) with contractual assumptions of liability to the recipient, - for any liability that these contractual assumptions directly - impose on those licensors and authors. - -All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - -If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; the -above requirements apply either way. - -#### 8. Termination. - -You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - -However, if you cease all violation of this License, then your license -from a particular copyright holder is reinstated (a) provisionally, -unless and until the copyright holder explicitly and finally -terminates your license, and (b) permanently, if the copyright holder -fails to notify you of the violation by some reasonable means prior to -60 days after the cessation. - -Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - -Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - -#### 9. Acceptance Not Required for Having Copies. - -You are not required to accept this License in order to receive or run -a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - -#### 10. Automatic Licensing of Downstream Recipients. - -Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - -An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - -You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - -#### 11. Patents. - -A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - -A contributor's "essential patent claims" are all patent claims owned -or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - -In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - -If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - -A patent license is "discriminatory" if it does not include within the -scope of its coverage, prohibits the exercise of, or is conditioned on -the non-exercise of one or more of the rights that are specifically -granted under this License. You may not convey a covered work if you -are a party to an arrangement with a third party that is in the -business of distributing software, under which you make payment to the -third party based on the extent of your activity of conveying the -work, and under which the third party grants, to any of the parties -who would receive the covered work from you, a discriminatory patent -license (a) in connection with copies of the covered work conveyed by -you (or copies made from those copies), or (b) primarily for and in -connection with specific products or compilations that contain the -covered work, unless you entered into that arrangement, or that patent -license was granted, prior to 28 March 2007. - -Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - -#### 12. No Surrender of Others' Freedom. - -If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under -this License and any other pertinent obligations, then as a -consequence you may not convey it at all. For example, if you agree to -terms that obligate you to collect a royalty for further conveying -from those to whom you convey the Program, the only way you could -satisfy both those terms and this License would be to refrain entirely -from conveying the Program. - -#### 13. Use with the GNU Affero General Public License. - -Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - -#### 14. Revised Versions of this License. - -The Free Software Foundation may publish revised and/or new versions -of the GNU General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in -detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies that a certain numbered version of the GNU General Public -License "or any later version" applies to it, you have the option of -following the terms and conditions either of that numbered version or -of any later version published by the Free Software Foundation. If the -Program does not specify a version number of the GNU General Public -License, you may choose any version ever published by the Free -Software Foundation. - -If the Program specifies that a proxy can decide which future versions -of the GNU General Public License can be used, that proxy's public -statement of acceptance of a version permanently authorizes you to -choose that version for the Program. - -Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - -#### 15. Disclaimer of Warranty. - -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND -PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - -#### 16. Limitation of Liability. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR -CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT -NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM -TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER -PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -#### 17. Interpretation of Sections 15 and 16. - -If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -### How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these -terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively state -the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper -mail. - -If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands \`show w' and \`show c' should show the -appropriate parts of the General Public License. Of course, your -program's commands might be different; for a GUI interface, you would -use an "about box". - -You should also get your employer (if you work as a programmer) or -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. For more information on this, and how to apply and follow -the GNU GPL, see . - -The GNU General Public License does not permit incorporating your -program into proprietary programs. If your program is a subroutine -library, you may consider it more useful to permit linking proprietary -applications with the library. If this is what you want to do, use the -GNU Lesser General Public License instead of this License. But first, -please read . From 681f9a1c694cf70900da60bbedc62e2224445fb3 Mon Sep 17 00:00:00 2001 From: wiz Date: Sun, 31 Dec 2023 03:39:23 +0900 Subject: [PATCH 43/80] ops: Enable redis for production mainnet --- production/mempool-config.mainnet.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/production/mempool-config.mainnet.json b/production/mempool-config.mainnet.json index 0aa90aa9c..36310e59d 100644 --- a/production/mempool-config.mainnet.json +++ b/production/mempool-config.mainnet.json @@ -106,7 +106,12 @@ "node206.tk7.mempool.space" ] }, - "MEMPOOL_SERVICES": { + "REDIS": { + "ENABLED": true, + "UNIX_SOCKET_PATH": "/tmp/redis.sock", + "BATCH_QUERY_BASE_SIZE": 5000 + }, + "MEMPOOL_SERVICES": { "API": "https://mempool.space/api/v1/services", "ACCELERATIONS": true } From 23ececca956beec76540d49fca782150b0933739 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sun, 31 Dec 2023 18:05:25 +0000 Subject: [PATCH 44/80] Optimize websocket updates on new block --- backend/src/api/websocket-handler.ts | 54 ++++++++++++++----- .../mempool-block-overview.component.ts | 38 ++++++++++++- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index b082573f1..34d4682d2 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -282,8 +282,7 @@ class WebsocketHandler { } if (Object.keys(response).length) { - const serializedResponse = this.serializeResponse(response); - client.send(serializedResponse); + client.send(this.serializeResponse(response)); } } catch (e) { logger.debug(`Error parsing websocket message from ${client['remoteAddress']}: ` + (e instanceof Error ? e.message : e)); @@ -392,8 +391,7 @@ class WebsocketHandler { } if (Object.keys(response).length) { - const serializedResponse = this.serializeResponse(response); - client.send(serializedResponse); + client.send(this.serializeResponse(response)); } }); } @@ -639,8 +637,7 @@ class WebsocketHandler { } if (Object.keys(response).length) { - const serializedResponse = this.serializeResponse(response); - client.send(serializedResponse); + client.send(this.serializeResponse(response)); } }); } @@ -738,10 +735,13 @@ class WebsocketHandler { } } + const confirmedTxids: { [txid: string]: boolean } = {}; + // Update mempool to remove transactions included in the new block for (const txId of txIds) { delete _memPool[txId]; rbfCache.mined(txId); + confirmedTxids[txId] = true; } if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) { @@ -773,6 +773,8 @@ class WebsocketHandler { 'fees': fees, }); + const mBlocksWithTransactions = mempoolBlocks.getMempoolBlocksWithTransactions(); + const responseCache = { ...this.socketData }; function getCachedResponse(key, data): string { if (!responseCache[key]) { @@ -808,7 +810,7 @@ class WebsocketHandler { if (client['track-tx']) { const trackTxid = client['track-tx']; - if (trackTxid && txIds.indexOf(trackTxid) > -1) { + if (trackTxid && confirmedTxids[trackTxid]) { response['txConfirmed'] = JSON.stringify(trackTxid); } else { const mempoolTx = _memPool[trackTxid]; @@ -880,17 +882,24 @@ class WebsocketHandler { if (client['track-mempool-block'] >= 0 && memPool.isInSync()) { const index = client['track-mempool-block']; - if (mBlockDeltas && mBlockDeltas[index]) { - response['projected-block-transactions'] = getCachedResponse(`projected-block-transactions-${index}`, { - index: index, - delta: mBlockDeltas[index], - }); + + if (mBlockDeltas && mBlockDeltas[index] && mBlocksWithTransactions[index]?.transactions?.length) { + if (mBlockDeltas[index].added.length > (mBlocksWithTransactions[index]?.transactions.length / 2)) { + response['projected-block-transactions'] = getCachedResponse(`projected-block-transactions-full-${index}`, { + index: index, + blockTransactions: mBlocksWithTransactions[index].transactions, + }); + } else { + response['projected-block-transactions'] = getCachedResponse(`projected-block-transactions-delta-${index}`, { + index: index, + delta: mBlockDeltas[index], + }); + } } } if (Object.keys(response).length) { - const serializedResponse = this.serializeResponse(response); - client.send(serializedResponse); + client.send(this.serializeResponse(response)); } }); } @@ -951,10 +960,27 @@ class WebsocketHandler { private printLogs(): void { if (this.wss) { + let numTxSubs = 0; + let numProjectedSubs = 0; + let numRbfSubs = 0; + + this.wss.clients.forEach((client) => { + if (client['track-tx']) { + numTxSubs++; + } + if (client['track-mempool-block'] >= 0) { + numProjectedSubs++; + } + if (client['track-rbf']) { + numRbfSubs++; + } + }) + const count = this.wss?.clients?.size || 0; const diff = count - this.numClients; this.numClients = count; logger.debug(`${count} websocket clients | ${this.numConnected} connected | ${this.numDisconnected} disconnected | (${diff >= 0 ? '+' : ''}${diff})`); + logger.debug(`websocket subscriptions: track-tx: ${numTxSubs}, track-mempool-block: ${numProjectedSubs} track-rbf: ${numRbfSubs}`); this.numConnected = 0; this.numDisconnected = 0; } diff --git a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts index 4beda043a..f09b8f5ea 100644 --- a/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts +++ b/frontend/src/app/components/mempool-block-overview/mempool-block-overview.component.ts @@ -35,6 +35,8 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang blockSub: Subscription; deltaSub: Subscription; + firstLoad: boolean = true; + constructor( public stateService: StateService, private websocketService: WebsocketService, @@ -58,7 +60,40 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang ) .pipe(switchMap(() => this.stateService.mempoolBlockTransactions$)) .subscribe((transactionsStripped) => { - this.replaceBlock(transactionsStripped); + if (this.firstLoad) { + this.replaceBlock(transactionsStripped); + } else { + const inOldBlock = {}; + const inNewBlock = {}; + const added: TransactionStripped[] = []; + const changed: { txid: string, rate: number | undefined, acc: boolean | undefined }[] = []; + const removed: string[] = []; + for (const tx of transactionsStripped) { + inNewBlock[tx.txid] = true; + } + for (const txid of Object.keys(this.blockGraph?.scene?.txs || {})) { + inOldBlock[txid] = true; + if (!inNewBlock[txid]) { + removed.push(txid); + } + } + for (const tx of transactionsStripped) { + if (!inOldBlock[tx.txid]) { + added.push(tx); + } else { + changed.push({ + txid: tx.txid, + rate: tx.rate, + acc: tx.acc + }); + } + } + this.updateBlock({ + removed, + changed, + added + }); + } }); this.deltaSub = this.stateService.mempoolBlockDelta$.subscribe((delta) => { this.updateBlock(delta); @@ -67,6 +102,7 @@ export class MempoolBlockOverviewComponent implements OnInit, OnDestroy, OnChang ngOnChanges(changes): void { if (changes.index) { + this.firstLoad = true; if (this.blockGraph) { this.blockGraph.clear(changes.index.currentValue > changes.index.previousValue ? this.chainDirection : this.poolDirection); } From bd34d71d8b82bc784da1f6be3da17d3c076c7cfa Mon Sep 17 00:00:00 2001 From: natsee Date: Sat, 30 Dec 2023 19:19:07 +0100 Subject: [PATCH 45/80] Update regexes in regex.utils.ts --- .../search-form/search-form.component.ts | 18 ++- .../pipes/relative-url/relative-url.pipe.ts | 1 + frontend/src/app/shared/regex.utils.ts | 121 +++++++++++++----- 3 files changed, 105 insertions(+), 35 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index cb64df7f4..4ed6b1d64 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -38,11 +38,11 @@ export class SearchFormComponent implements OnInit { } regexAddress = getRegex('address', 'mainnet'); // Default to mainnet - regexBlockhash = getRegex('blockhash'); + regexBlockhash = getRegex('blockhash', 'mainnet'); regexTransaction = getRegex('transaction'); regexBlockheight = getRegex('blockheight'); - regexDate = /^(?:\d{4}[-/]\d{1,2}[-/]\d{1,2}(?: \d{1,2}:\d{2})?)$/; - regexUnixTimestamp = /^\d{10}$/; + regexDate = getRegex('date'); + regexUnixTimestamp = getRegex('timestamp'); focus$ = new Subject(); click$ = new Subject(); @@ -72,6 +72,7 @@ export class SearchFormComponent implements OnInit { this.network = network; // TODO: Eventually change network type here from string to enum of consts this.regexAddress = getRegex('address', network as any || 'mainnet'); + this.regexBlockhash = getRegex('blockhash', network as any || 'mainnet'); }); this.router.events.subscribe((e: NavigationStart) => { // Reset search focus when changing page @@ -181,8 +182,8 @@ export class SearchFormComponent implements OnInit { const lightningResults = result[1]; const matchesBlockHeight = this.regexBlockheight.test(searchText) && parseInt(searchText) <= this.stateService.latestBlockHeight; - const matchesDateTime = this.regexDate.test(searchText) && new Date(searchText).toString() !== 'Invalid Date'; - const matchesUnixTimestamp = this.regexUnixTimestamp.test(searchText); + const matchesDateTime = this.regexDate.test(searchText) && new Date(searchText).toString() !== 'Invalid Date' && new Date(searchText).getTime() <= Date.now() && new Date(searchText).getTime() >= 1231006505000; + const matchesUnixTimestamp = this.regexUnixTimestamp.test(searchText) && parseInt(searchText) <= Math.floor(Date.now() / 1000) && parseInt(searchText) >= 1231006505; // 1231006505 is the timestamp of the genesis block const matchesTxId = this.regexTransaction.test(searchText) && !this.regexBlockhash.test(searchText); const matchesBlockHash = this.regexBlockhash.test(searchText); const matchesAddress = !matchesTxId && this.regexAddress.test(searchText); @@ -237,7 +238,7 @@ export class SearchFormComponent implements OnInit { if (searchText) { this.isSearching = true; - const otherNetworks = findOtherNetworks(searchText, this.network as any); + const otherNetworks = findOtherNetworks(searchText, this.network as any || 'mainnet'); if (!this.regexTransaction.test(searchText) && this.regexAddress.test(searchText)) { this.navigate('/address/', searchText); } else if (otherNetworks.length > 0) { @@ -269,6 +270,11 @@ export class SearchFormComponent implements OnInit { } else if (this.regexDate.test(searchText) || this.regexUnixTimestamp.test(searchText)) { let timestamp: number; this.regexDate.test(searchText) ? timestamp = Math.floor(new Date(searchText).getTime() / 1000) : timestamp = searchText; + // Check if timestamp is too far in the future or before the genesis block + if (timestamp > Math.floor(Date.now() / 1000) || timestamp < 1231006505) { + this.isSearching = false; + return; + } this.apiService.getBlockDataFromTimestamp$(timestamp).subscribe( (data) => { this.navigate('/block/', data.hash); }, (error) => { console.log(error); this.isSearching = false; } diff --git a/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts b/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts index 83f5f20df..4211765df 100644 --- a/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts +++ b/frontend/src/app/shared/pipes/relative-url/relative-url.pipe.ts @@ -12,6 +12,7 @@ export class RelativeUrlPipe implements PipeTransform { transform(value: string, swapNetwork?: string): string { let network = swapNetwork || this.stateService.network; + if (network === 'mainnet') network = ''; if (this.stateService.env.BASE_MODULE === 'liquid' && network === 'liquidtestnet') { network = 'testnet'; } else if (this.stateService.env.BASE_MODULE !== 'mempool') { diff --git a/frontend/src/app/shared/regex.utils.ts b/frontend/src/app/shared/regex.utils.ts index bac256c8d..d0cd08f24 100644 --- a/frontend/src/app/shared/regex.utils.ts +++ b/frontend/src/app/shared/regex.utils.ts @@ -9,13 +9,16 @@ const BECH32_CHARS_UP = `[AC-HJ-NP-Z02-9]`; const HEX_CHARS = `[a-fA-F0-9]`; // A regex to say "A single 0 OR any number with no leading zeroes" -// Capped at 13 digits so as to not be confused with lightning channel IDs (which are around 17 digits) +// Capped at 9 digits so as to not be confused with lightning channel IDs (which are around 17 digits) // (?: // Start a non-capturing group // 0 // A single 0 // | // OR -// [1-9][0-9]{0,12} // Any succession of numbers up to 13 digits starting with 1-9 +// [1-9][0-9]{0,8} // Any succession of numbers up to 9 digits starting with 1-9 // ) // End the non-capturing group. -const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9][0-9]{0,12})`; +const ZERO_INDEX_NUMBER_CHARS = `(?:0|[1-9][0-9]{0,8})`; + +// Simple digits only regex +const NUMBER_CHARS = `[0-9]`; // Formatting of the address regex is for readability, // We should ignore formatting it with automated formatting tools like prettier. @@ -48,7 +51,7 @@ const ADDRESS_CHARS: { + BASE58_CHARS + `{33,34}`, // m|n is 34 length, 2 is 35 length (We match the first letter separately) bech32: `(?:` - + `tb1` // Starts with bc1 + + `tb1` // Starts with tb1 + BECH32_CHARS_LW + `{6,100}` // As per bech32, 6 char checksum is minimum + `|` @@ -76,18 +79,18 @@ const ADDRESS_CHARS: { + BASE58_CHARS + `{33}`, // All min-max lengths are 34 bech32: `(?:` - + `(?:` // bech32 liquid starts with ex or lq - + `ex` + + `(?:` // bech32 liquid starts with ex1 or lq1 + + `ex1` + `|` - + `lq` + + `lq1` + `)` + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. + `{6,100}` + `|` + `(?:` // Same as above but all upper case - + `EX` + + `EX1` + `|` - + `LQ` + + `LQ1` + `)` + BECH32_CHARS_UP + `{6,100}` @@ -99,39 +102,39 @@ const ADDRESS_CHARS: { + `{33}`, // P2PKH is ???(TODO: find size), P2SH is 34 bech32: `(?:` + `(?:` // bech32 liquid testnet starts with tex or tlq - + `tex` // TODO: Why does mempool use this and not ert|el like in the elements source? + + `tex1` // TODO: Why does mempool use this and not ert|el like in the elements source? + `|` - + `tlq` // TODO: does this exist? + + `tlq1` // TODO: does this exist? + `)` + BECH32_CHARS_LW // blech32 and bech32 are the same alphabet and protocol, different checksums. + `{6,100}` + `|` + `(?:` // Same as above but all upper case - + `TEX` + + `TEX1` + `|` - + `TLQ` + + `TLQ1` + `)` + BECH32_CHARS_UP + `{6,100}` + `)`, }, bisq: { - base58: `B1` // bisq base58 addrs start with B1 + base58: `(?:[bB][13]` // b or B at the start, followed by a single 1 or 3 + BASE58_CHARS - + `{33}`, // always length 35 + + `{26,33})`, bech32: `(?:` - + `bbc1` // Starts with bbc1 + + `[bB]bc1` // b or B at the start, followed by bc1 + BECH32_CHARS_LW - + `{6,100}` + + `{6,100}` + `|` - + `BBC1` // All upper case version + + `[bB]BC1` // b or B at the start, followed by BC1 + BECH32_CHARS_UP + `{6,100}` + `)`, }, } -type RegexTypeNoAddr = `blockhash` | `transaction` | `blockheight`; -export type RegexType = `address` | RegexTypeNoAddr; +type RegexTypeNoAddrNoBlockHash = | `transaction` | `blockheight` | `date` | `timestamp`; +export type RegexType = `address` | `blockhash` | RegexTypeNoAddrNoBlockHash; export const NETWORKS = [`testnet`, `signet`, `liquid`, `liquidtestnet`, `bisq`, `mainnet`] as const; export type Network = typeof NETWORKS[number]; // Turn const array into union type @@ -139,15 +142,15 @@ export type Network = typeof NETWORKS[number]; // Turn const array into union ty export const ADDRESS_REGEXES: [RegExp, Network][] = NETWORKS .map(network => [getRegex('address', network), network]) -export function findOtherNetworks(address: string, skipNetwork: Network): Network[] { - return ADDRESS_REGEXES.filter(([regex, network]) => - network !== skipNetwork && - regex.test(address) - ).map(([, network]) => network); +export function findOtherNetworks(address: string, skipNetwork: Network): {network: Network, address: string}[] { + return ADDRESS_REGEXES + .filter(([regex, network]) => network !== skipNetwork && regex.test(address)) + .map(([, network]) => ({ network, address })); } -export function getRegex(type: RegexTypeNoAddr): RegExp; +export function getRegex(type: RegexTypeNoAddrNoBlockHash): RegExp; export function getRegex(type: 'address', network: Network): RegExp; +export function getRegex(type: 'blockhash', network: Network): RegExp; export function getRegex(type: RegexType, network?: Network): RegExp { let regex = `^`; // ^ = Start of string switch (type) { @@ -156,11 +159,37 @@ export function getRegex(type: RegexType, network?: Network): RegExp { case `blockheight`: regex += ZERO_INDEX_NUMBER_CHARS; // block height is a 0 indexed number break; - // Match a 32 byte block hash in hex. Assumes at least 32 bits of difficulty. + // Match a 32 byte block hash in hex. // [Testing Order]: Must always be tested before `transaction` case `blockhash`: - regex += `0{8}`; // Starts with exactly 8 zeroes in a row - regex += `${HEX_CHARS}{56}`; // Continues with exactly 56 hex letters/numbers + if (!network) { + throw new Error(`Must pass network when type is blockhash`); + } + let leadingZeroes: number; + switch (network) { + case `mainnet`: + leadingZeroes = 8; // Assumes at least 32 bits of difficulty + break; + case `testnet`: + leadingZeroes = 8; // Assumes at least 32 bits of difficulty + break; + case `signet`: + leadingZeroes = 5; + break; + case `liquid`: + leadingZeroes = 8; // We are not interested in Liquid block hashes + break; + case `liquidtestnet`: + leadingZeroes = 8; // We are not interested in Liquid block hashes + break; + case `bisq`: + leadingZeroes = 8; // Assumes at least 32 bits of difficulty + break; + default: + throw new Error(`Invalid Network ${network} (Unreachable error in TypeScript)`); + } + regex += `0{${leadingZeroes}}`; + regex += `${HEX_CHARS}{${64 - leadingZeroes}}`; // Exactly 64 hex letters/numbers break; // Match a 32 byte tx hash in hex. Contains optional output index specifier. // [Testing Order]: Must always be tested after `blockhash` @@ -185,16 +214,28 @@ export function getRegex(type: RegexType, network?: Network): RegExp { regex += ADDRESS_CHARS.mainnet.base58; regex += `|`; // OR regex += ADDRESS_CHARS.mainnet.bech32; + regex += `|`; // OR + regex += `04${HEX_CHARS}{128}`; // Uncompressed pubkey + regex += `|`; // OR + regex += `(?:02|03)${HEX_CHARS}{64}`; // Compressed pubkey break; case `testnet`: 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 regex += ADDRESS_CHARS.signet.bech32; + regex += `|`; // OR + regex += `04${HEX_CHARS}{128}`; // Uncompressed pubkey + regex += `|`; // OR + regex += `(?:02|03)${HEX_CHARS}{64}`; // Compressed pubkey break; case `liquid`: regex += ADDRESS_CHARS.liquid.base58; @@ -216,6 +257,28 @@ export function getRegex(type: RegexType, network?: Network): RegExp { } regex += `)`; // End the non-capturing group break; + // Match a date in the format YYYY-MM-DD (optional: HH:MM) + // [Testing Order]: any order is fine + case `date`: + regex += `(?:`; // Start a non-capturing group + regex += `${NUMBER_CHARS}{4}`; // Exactly 4 digits + regex += `[-/]`; // 1 instance of the symbol "-" or "/" + regex += `${NUMBER_CHARS}{1,2}`; // Exactly 4 digits + regex += `[-/]`; // 1 instance of the symbol "-" or "/" + regex += `${NUMBER_CHARS}{1,2}`; // Exactly 4 digits + regex += `(?:`; // Start a non-capturing group + regex += ` `; // 1 instance of the symbol " " + regex += `${NUMBER_CHARS}{1,2}`; // Exactly 4 digits + regex += `:`; // 1 instance of the symbol ":" + regex += `${NUMBER_CHARS}{1,2}`; // Exactly 4 digits + regex += `)?`; // End the non-capturing group. This group appears 0 or 1 times + regex += `)`; // End the non-capturing group + break; + // Match a unix timestamp + // [Testing Order]: any order is fine + case `timestamp`: + regex += `${NUMBER_CHARS}{10}`; // Exactly 10 digits + break; default: throw new Error(`Invalid RegexType ${type} (Unreachable error in TypeScript)`); } From 9b6e60bfbaccc489e44f01a5c661d6e380641a8e Mon Sep 17 00:00:00 2001 From: wiz Date: Mon, 1 Jan 2024 08:01:06 +0900 Subject: [PATCH 46/80] ops: Add production/redis.conf --- production/redis.conf | 79 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 production/redis.conf diff --git a/production/redis.conf b/production/redis.conf new file mode 100644 index 000000000..f1ed13a68 --- /dev/null +++ b/production/redis.conf @@ -0,0 +1,79 @@ +save 3600 1 300 100 60 10000 +unixsocket /tmp/redis.sock +unixsocketperm 666 + +bind 127.0.0.1 -::1 +protected-mode yes +port 6379 +tcp-backlog 511 +timeout 0 +tcp-keepalive 300 +daemonize yes +pidfile /var/run/redis/redis.pid +loglevel notice +logfile /var/log/redis/redis.log +databases 16 +always-show-logo no +set-proc-title yes +proc-title-template "{title} {listen-addr} {server-mode}" +locale-collate "" +stop-writes-on-bgsave-error yes +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +rdb-del-sync-files no +dir /var/db/redis/ +replica-serve-stale-data yes +replica-read-only yes +repl-diskless-sync yes +repl-diskless-sync-delay 5 +repl-diskless-sync-max-replicas 0 +repl-diskless-load disabled +repl-disable-tcp-nodelay no +replica-priority 100 +acllog-max-len 128 +lazyfree-lazy-eviction no +lazyfree-lazy-expire no +lazyfree-lazy-server-del no +replica-lazy-flush no +lazyfree-lazy-user-del no +lazyfree-lazy-user-flush no +oom-score-adj no +oom-score-adj-values 0 200 800 +disable-thp yes +appendonly no +appendfilename "appendonly.aof" +appenddirname "appendonlydir" +appendfsync everysec +no-appendfsync-on-rewrite no +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb +aof-load-truncated yes +aof-use-rdb-preamble yes +aof-timestamp-enabled no + +slowlog-log-slower-than 10000 +slowlog-max-len 128 +latency-monitor-threshold 0 +notify-keyspace-events "" +hash-max-listpack-entries 512 +hash-max-listpack-value 64 +list-max-listpack-size -2 +list-compress-depth 0 +set-max-intset-entries 512 +set-max-listpack-entries 128 +set-max-listpack-value 64 +zset-max-listpack-entries 128 +zset-max-listpack-value 64 +hll-sparse-max-bytes 3000 +stream-node-max-bytes 4096 +stream-node-max-entries 100 +activerehashing yes +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit replica 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 +hz 10 +dynamic-hz yes +aof-rewrite-incremental-fsync yes +rdb-save-incremental-fsync yes +jemalloc-bg-thread yes From 51bfffbf0ee60930efa7204d8e0276c887b6d440 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Mon, 1 Jan 2024 12:01:53 +0000 Subject: [PATCH 47/80] unsubscribe from mempool block tracking --- .../src/app/components/mempool-block/mempool-block.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/src/app/components/mempool-block/mempool-block.component.ts b/frontend/src/app/components/mempool-block/mempool-block.component.ts index 197b07247..89fb97dad 100644 --- a/frontend/src/app/components/mempool-block/mempool-block.component.ts +++ b/frontend/src/app/components/mempool-block/mempool-block.component.ts @@ -75,6 +75,7 @@ export class MempoolBlockComponent implements OnInit, OnDestroy { ngOnDestroy(): void { this.stateService.markBlock$.next({}); + this.websocketService.stopTrackMempoolBlock(); } getOrdinal(mempoolBlock: MempoolBlock): string { From 3e1b85e32ca7526f9772a495b14ef8bd6cfb3546 Mon Sep 17 00:00:00 2001 From: natsee Date: Sun, 31 Dec 2023 23:23:53 +0100 Subject: [PATCH 48/80] Add search addresses from cross networks feature --- .../search-form/search-form.component.ts | 48 ++++++++++--------- .../search-results.component.html | 16 +++++-- .../search-results.component.scss | 4 ++ .../search-results.component.ts | 2 +- frontend/src/app/shared/regex.utils.ts | 37 ++++++++++++++ 5 files changed, 79 insertions(+), 28 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index 4ed6b1d64..ed46f1e88 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -2,14 +2,14 @@ import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ViewC import { UntypedFormBuilder, UntypedFormGroup, Validators } from '@angular/forms'; import { EventType, NavigationStart, Router } from '@angular/router'; import { AssetsService } from '../../services/assets.service'; -import { StateService } from '../../services/state.service'; +import { Env, StateService } from '../../services/state.service'; import { Observable, of, Subject, zip, BehaviorSubject, combineLatest } from 'rxjs'; import { debounceTime, distinctUntilChanged, switchMap, catchError, map, startWith, tap } from 'rxjs/operators'; import { ElectrsApiService } from '../../services/electrs-api.service'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { ApiService } from '../../services/api.service'; import { SearchResultsComponent } from './search-results/search-results.component'; -import { findOtherNetworks, getRegex } from '../../shared/regex.utils'; +import { Network, findOtherNetworks, getRegex, getTargetUrl, needBaseModuleChange } from '../../shared/regex.utils'; @Component({ selector: 'app-search-form', @@ -19,7 +19,7 @@ import { findOtherNetworks, getRegex } from '../../shared/regex.utils'; }) export class SearchFormComponent implements OnInit { @Input() hamburgerOpen = false; - + env: Env; network = ''; assets: object = {}; isSearching = false; @@ -68,6 +68,7 @@ export class SearchFormComponent implements OnInit { } ngOnInit(): void { + this.env = this.stateService.env; this.stateService.networkChanged$.subscribe((network) => { this.network = network; // TODO: Eventually change network type here from string to enum of consts @@ -103,9 +104,6 @@ export class SearchFormComponent implements OnInit { const searchText$ = this.searchForm.get('searchText').valueChanges .pipe( map((text) => { - if (this.network === 'bisq' && text.match(/^(b)[^c]/i)) { - return text.substr(1); - } return text.trim(); }), tap((text) => { @@ -139,9 +137,6 @@ export class SearchFormComponent implements OnInit { ); }), map((result: any[]) => { - if (this.network === 'bisq') { - result[0] = result[0].map((address: string) => 'B' + address); - } return result; }), tap(() => { @@ -171,6 +166,7 @@ export class SearchFormComponent implements OnInit { blockHeight: false, txId: false, address: false, + otherNetworks: [], addresses: [], nodes: [], channels: [], @@ -186,10 +182,13 @@ export class SearchFormComponent implements OnInit { const matchesUnixTimestamp = this.regexUnixTimestamp.test(searchText) && parseInt(searchText) <= Math.floor(Date.now() / 1000) && parseInt(searchText) >= 1231006505; // 1231006505 is the timestamp of the genesis block const matchesTxId = this.regexTransaction.test(searchText) && !this.regexBlockhash.test(searchText); const matchesBlockHash = this.regexBlockhash.test(searchText); - const matchesAddress = !matchesTxId && this.regexAddress.test(searchText); + let matchesAddress = !matchesTxId && this.regexAddress.test(searchText); + const otherNetworks = findOtherNetworks(searchText, this.network as any || 'mainnet'); - if (matchesAddress && this.network === 'bisq') { - searchText = 'B' + searchText; + // Add B prefix to addresses in Bisq network + if (!matchesAddress && this.network === 'bisq' && getRegex('address', 'mainnet').test(searchText)) { + searchText = 'B' + searchText; + matchesAddress = !matchesTxId && this.regexAddress.test(searchText); } if (matchesDateTime && searchText.indexOf('/') !== -1) { @@ -205,7 +204,8 @@ export class SearchFormComponent implements OnInit { txId: matchesTxId, blockHash: matchesBlockHash, address: matchesAddress, - addresses: addressPrefixSearchResults, + addresses: matchesAddress && addressPrefixSearchResults.length === 1 && searchText === addressPrefixSearchResults[0] ? [] : addressPrefixSearchResults, // If there is only one address and it matches the search text, don't show it in the dropdown + otherNetworks: otherNetworks, nodes: lightningResults.nodes, channels: lightningResults.channels, }; @@ -230,6 +230,8 @@ export class SearchFormComponent implements OnInit { this.navigate('/lightning/node/', result.public_key); } else if (result.short_id) { this.navigate('/lightning/channel/', result.id); + } else if (result.network) { + this.navigate('/address/', result.address, undefined, result.network); } } @@ -238,12 +240,8 @@ export class SearchFormComponent implements OnInit { if (searchText) { this.isSearching = true; - const otherNetworks = findOtherNetworks(searchText, this.network as any || 'mainnet'); if (!this.regexTransaction.test(searchText) && this.regexAddress.test(searchText)) { this.navigate('/address/', searchText); - } else if (otherNetworks.length > 0) { - // Change the network to the first match - this.navigate('/address/', searchText, undefined, otherNetworks[0]); } else if (this.regexBlockhash.test(searchText)) { this.navigate('/block/', searchText); } else if (this.regexBlockheight.test(searchText)) { @@ -288,11 +286,15 @@ export class SearchFormComponent implements OnInit { navigate(url: string, searchText: string, extras?: any, swapNetwork?: string) { - this.router.navigate([this.relativeUrlPipe.transform(url, swapNetwork), searchText], extras); - this.searchTriggered.emit(); - this.searchForm.setValue({ - searchText: '', - }); - this.isSearching = false; + if (needBaseModuleChange(this.env.BASE_MODULE as 'liquid' | 'bisq' | 'mempool', swapNetwork as Network)) { + window.location.href = getTargetUrl(swapNetwork as Network, searchText, this.env); + } else { + this.router.navigate([this.relativeUrlPipe.transform(url, swapNetwork), searchText], extras); + this.searchTriggered.emit(); + this.searchForm.setValue({ + searchText: '', + }); + this.isSearching = false; + } } } diff --git a/frontend/src/app/components/search-form/search-results/search-results.component.html b/frontend/src/app/components/search-form/search-results/search-results.component.html index d4f68edbd..adc92b0bf 100644 --- a/frontend/src/app/components/search-form/search-results/search-results.component.html +++ b/frontend/src/app/components/search-form/search-results/search-results.component.html @@ -1,4 +1,4 @@ -
    @@ -245,7 +247,9 @@
    - + + +
    @@ -452,5 +456,24 @@ + + + + + + + + + + + + + + + + +
    Total fees
    Weight
    Transactions
    +
    +

    diff --git a/frontend/src/app/dashboard/dashboard.component.html b/frontend/src/app/dashboard/dashboard.component.html index 4025a45d0..12ce14512 100644 --- a/frontend/src/app/dashboard/dashboard.component.html +++ b/frontend/src/app/dashboard/dashboard.component.html @@ -87,8 +87,8 @@ New fee Status - - + + @@ -158,8 +158,8 @@ {{ currency }} Fee - - + + @@ -199,6 +199,28 @@ + + + +
    +
    +
    +
    + + +
    + + + + +
    +
    +
    +
    + + +
    +
    From 0ec40eafb401629095573342fb2989f594620365 Mon Sep 17 00:00:00 2001 From: natsee Date: Fri, 12 Jan 2024 17:21:07 +0100 Subject: [PATCH 71/80] Remove hard-coded timestamp for regexes --- .../src/app/components/search-form/search-form.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index c00537f5a..745efce21 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -272,7 +272,7 @@ export class SearchFormComponent implements OnInit { let timestamp: number; this.regexDate.test(searchText) ? timestamp = Math.floor(new Date(searchText).getTime() / 1000) : timestamp = searchText; // Check if timestamp is too far in the future or before the genesis block - if (timestamp > Math.floor(Date.now() / 1000) || timestamp < 1231006505) { + if (timestamp > Math.floor(Date.now() / 1000)) { this.isSearching = false; return; } From 3b8de5057cc0eea4fdef84ede0a9d13ff10ec007 Mon Sep 17 00:00:00 2001 From: natsee Date: Fri, 12 Jan 2024 18:04:14 +0100 Subject: [PATCH 72/80] Check env flags before cross network address search --- .../search-form/search-form.component.ts | 11 +++++++-- .../search-results.component.html | 2 +- frontend/src/app/shared/regex.utils.ts | 23 +++++++++++++++++-- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/frontend/src/app/components/search-form/search-form.component.ts b/frontend/src/app/components/search-form/search-form.component.ts index 745efce21..2a9983a24 100644 --- a/frontend/src/app/components/search-form/search-form.component.ts +++ b/frontend/src/app/components/search-form/search-form.component.ts @@ -186,7 +186,7 @@ export class SearchFormComponent implements OnInit { const matchesTxId = this.regexTransaction.test(searchText) && !this.regexBlockhash.test(searchText); const matchesBlockHash = this.regexBlockhash.test(searchText); let matchesAddress = !matchesTxId && this.regexAddress.test(searchText); - const otherNetworks = findOtherNetworks(searchText, this.network as any || 'mainnet'); + const otherNetworks = findOtherNetworks(searchText, this.network as any || 'mainnet', this.env); // Add B prefix to addresses in Bisq network if (!matchesAddress && this.network === 'bisq' && getRegex('address', 'mainnet').test(searchText)) { @@ -234,7 +234,14 @@ export class SearchFormComponent implements OnInit { } else if (result.short_id) { this.navigate('/lightning/channel/', result.id); } else if (result.network) { - this.navigate('/address/', result.address, undefined, result.network); + if (result.isNetworkAvailable) { + this.navigate('/address/', result.address, undefined, result.network); + } else { + this.searchForm.setValue({ + searchText: '', + }); + this.isSearching = false; + } } } diff --git a/frontend/src/app/components/search-form/search-results/search-results.component.html b/frontend/src/app/components/search-form/search-results/search-results.component.html index adc92b0bf..f83df6b93 100644 --- a/frontend/src/app/components/search-form/search-results/search-results.component.html +++ b/frontend/src/app/components/search-form/search-results/search-results.component.html @@ -38,7 +38,7 @@
    Other Networks Address
    - diff --git a/frontend/src/app/shared/regex.utils.ts b/frontend/src/app/shared/regex.utils.ts index 607bd704a..128f7566e 100644 --- a/frontend/src/app/shared/regex.utils.ts +++ b/frontend/src/app/shared/regex.utils.ts @@ -144,10 +144,29 @@ export type Network = typeof NETWORKS[number]; // Turn const array into union ty export const ADDRESS_REGEXES: [RegExp, Network][] = NETWORKS .map(network => [getRegex('address', network), network]) -export function findOtherNetworks(address: string, skipNetwork: Network): {network: Network, address: string}[] { +export function findOtherNetworks(address: string, skipNetwork: Network, env: Env): { network: Network, address: string, isNetworkAvailable: boolean }[] { return ADDRESS_REGEXES .filter(([regex, network]) => network !== skipNetwork && regex.test(address)) - .map(([, network]) => ({ network, address })); + .map(([, network]) => ({ network, address, isNetworkAvailable: isNetworkAvailable(network, env) })); +} + +function isNetworkAvailable(network: Network, env: Env): boolean { + switch (network) { + case 'testnet': + return env.TESTNET_ENABLED === true; + case 'signet': + return env.SIGNET_ENABLED === true; + case 'liquid': + return env.LIQUID_ENABLED === true; + case 'liquidtestnet': + return env.LIQUID_TESTNET_ENABLED === true; + case 'bisq': + return env.BISQ_ENABLED === true; + case 'mainnet': + return true; // There is no "MAINNET_ENABLED" flag + default: + return false; + } } export function needBaseModuleChange(fromBaseModule: 'mempool' | 'liquid' | 'bisq', toNetwork: Network): boolean { From a06bf86b95c43118b13bceba2caa556e9a9db1a8 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Fri, 12 Jan 2024 13:06:11 -0800 Subject: [PATCH 73/80] Update Cypress to v13.6.2 --- frontend/package-lock.json | 14 +++++++------- frontend/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 59bdac54a..f49fd614a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -58,7 +58,7 @@ "optionalDependencies": { "@cypress/schematic": "^2.5.0", "@types/cypress": "^1.1.3", - "cypress": "^13.6.0", + "cypress": "^13.6.2", "cypress-fail-on-console-error": "~5.1.0", "cypress-wait-until": "^2.0.1", "mock-socket": "~9.3.1", @@ -7083,9 +7083,9 @@ "peer": true }, "node_modules/cypress": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.0.tgz", - "integrity": "sha512-quIsnFmtj4dBUEJYU4OH0H12bABJpSujvWexC24Ju1gTlKMJbeT6tTO0vh7WNfiBPPjoIXLN+OUqVtiKFs6SGw==", + "version": "13.6.2", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.2.tgz", + "integrity": "sha512-TW3bGdPU4BrfvMQYv1z3oMqj71YI4AlgJgnrycicmPZAXtvywVFZW9DAToshO65D97rCWfG/kqMFsYB6Kp91gQ==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -22272,9 +22272,9 @@ "peer": true }, "cypress": { - "version": "13.6.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.0.tgz", - "integrity": "sha512-quIsnFmtj4dBUEJYU4OH0H12bABJpSujvWexC24Ju1gTlKMJbeT6tTO0vh7WNfiBPPjoIXLN+OUqVtiKFs6SGw==", + "version": "13.6.2", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.6.2.tgz", + "integrity": "sha512-TW3bGdPU4BrfvMQYv1z3oMqj71YI4AlgJgnrycicmPZAXtvywVFZW9DAToshO65D97rCWfG/kqMFsYB6Kp91gQ==", "optional": true, "requires": { "@cypress/request": "^3.0.0", diff --git a/frontend/package.json b/frontend/package.json index 8dbcbcf3e..330250871 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -110,7 +110,7 @@ "optionalDependencies": { "@cypress/schematic": "^2.5.0", "@types/cypress": "^1.1.3", - "cypress": "^13.6.0", + "cypress": "^13.6.2", "cypress-fail-on-console-error": "~5.1.0", "cypress-wait-until": "^2.0.1", "mock-socket": "~9.3.1", From fdd14fd6dcb4440b600062e725692a7532c248c4 Mon Sep 17 00:00:00 2001 From: wiz Date: Sat, 13 Jan 2024 12:22:23 +0900 Subject: [PATCH 74/80] ops: Disable disk cache for production mainnet --- production/mempool-config.mainnet.json | 1 + 1 file changed, 1 insertion(+) diff --git a/production/mempool-config.mainnet.json b/production/mempool-config.mainnet.json index 36310e59d..e3ce58ceb 100644 --- a/production/mempool-config.mainnet.json +++ b/production/mempool-config.mainnet.json @@ -3,6 +3,7 @@ "NETWORK": "mainnet", "BACKEND": "esplora", "HTTP_PORT": 8999, + "CACHE_ENABLED": false, "MINED_BLOCKS_CACHE": 144, "SPAWN_CLUSTER_PROCS": 0, "API_URL_PREFIX": "/api/v1/", From 2ca6dc51da5c50e24753660a8d478b921b6b25af Mon Sep 17 00:00:00 2001 From: wiz Date: Sat, 13 Jan 2024 12:22:38 +0900 Subject: [PATCH 75/80] ops: Increase nginx proxy_read_timeout to 2m --- production/nginx/http-basic.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/production/nginx/http-basic.conf b/production/nginx/http-basic.conf index dc880cad5..fd5cc4b94 100644 --- a/production/nginx/http-basic.conf +++ b/production/nginx/http-basic.conf @@ -19,6 +19,8 @@ client_header_timeout 10s; keepalive_timeout 69s; # maximum time between packets nginx is allowed to pause when sending the client data send_timeout 69s; +# maximum time to wait for response from upstream backends +proxy_read_timeout 120s; # number of requests per connection, does not affect SPDY keepalive_requests 1337; From e4d7034d81b52ffc39e7ea25327d5241f9682c5d Mon Sep 17 00:00:00 2001 From: "transifex-integration[bot]" <43880903+transifex-integration[bot]@users.noreply.github.com> Date: Sat, 13 Jan 2024 16:57:03 +0000 Subject: [PATCH 76/80] Translate frontend/src/locale/messages.xlf in nb 100% reviewed source file: 'frontend/src/locale/messages.xlf' on 'nb'. --- frontend/src/locale/messages.nb.xlf | 158 ++++++++++++++++++++++++++-- 1 file changed, 148 insertions(+), 10 deletions(-) diff --git a/frontend/src/locale/messages.nb.xlf b/frontend/src/locale/messages.nb.xlf index a035d3765..7870acc32 100644 --- a/frontend/src/locale/messages.nb.xlf +++ b/frontend/src/locale/messages.nb.xlf @@ -59,6 +59,7 @@ + node_modules/src/ngb-config.ts 13 @@ -66,6 +67,7 @@ Slide of + Lysbilde av node_modules/src/ngb-config.ts 13 @@ -404,6 +406,7 @@ See current balance, pending transactions, and history of confirmed transactions for BSQ address . + Se gjeldende saldo, ventende transaksjoner og historikk for bekreftede transaksjoner for BSQ-adresse . src/app/bisq/bisq-address/bisq-address.component.ts 44 @@ -500,6 +503,7 @@ See all BSQ transactions in Bitcoin block (block hash ). + Se alle BSQ-transaksjoner i Bitcoin-blokk (blokkhash ). src/app/bisq/bisq-block/bisq-block.component.ts 92 @@ -627,6 +631,7 @@ See a list of recent Bitcoin blocks with BSQ transactions, total BSQ sent per block, and more. + Se en liste over nylige Bitcoin-blokker med BSQ-transaksjoner, totalt BSQ sendt per blokk og mer. src/app/bisq/bisq-blocks/bisq-blocks.component.ts 39 @@ -756,6 +761,7 @@ Markets + Markeder src/app/bisq/bisq-dashboard/bisq-dashboard.component.ts 32 @@ -763,6 +769,7 @@ Explore the full Bitcoin ecosystem with The Mempool Open Source Project™. See Bisq market prices, trading activity, and more. + Utforsk hele Bitcoin-økosystemet med The Mempool Open Source Project™. Se Bisq markedspriser, handelsaktivitet og mer. src/app/bisq/bisq-dashboard/bisq-dashboard.component.ts 33 @@ -848,6 +855,7 @@ Bisq market: + Bisq-markedet: src/app/bisq/bisq-market/bisq-market.component.ts 51 @@ -855,6 +863,7 @@ See price history, current buy/sell offers, and latest trades for the market on Bisq. + Se prishistorikk, gjeldende kjøps-/salgstilbud og siste handler for -markedet på Bisq. src/app/bisq/bisq-market/bisq-market.component.ts 52 @@ -990,6 +999,7 @@ See high-level stats on the BSQ economy: supply metrics, number of addresses, BSQ price, market cap, and more. + Se statistikk om BSQ-økonomien: forsyningsstatistikk, antall adresser, BSQ-pris, markedsverdi og mer. src/app/bisq/bisq-stats/bisq-stats.component.ts 29 @@ -1169,6 +1179,7 @@ Fee per weight unit + Avgift per vektenhet src/app/bisq/bisq-transaction/bisq-transaction.component.html 68 @@ -1237,6 +1248,7 @@ See inputs, outputs, transaction type, burnt amount, and more for transaction with txid . + Se innganger, utganger, transaksjonstype, brent beløp og mer for transaksjon med txid . src/app/bisq/bisq-transaction/bisq-transaction.component.ts 51 @@ -1426,6 +1438,7 @@ See recent BSQ transactions: amount, txid, associated Bitcoin block, transaction type, and more. + Se nylige BSQ-transaksjoner: beløp, txid, tilhørende Bitcoin-blokk, transaksjonstype og mer. src/app/bisq/bisq-transactions/bisq-transactions.component.ts 82 @@ -1466,6 +1479,7 @@ Become a Community Sponsor + Bli en samfunnssponsor src/app/components/about/about.component.html 39 @@ -1474,6 +1488,7 @@ Become an Enterprise Sponsor + Bli en bedriftssponsor src/app/components/about/about.component.html 46 @@ -1491,6 +1506,7 @@ Whale Sponsors + Hvalsponsorer src/app/components/about/about.component.html 202 @@ -1499,6 +1515,7 @@ Chad Sponsors + Chadsponsorer src/app/components/about/about.component.html 215 @@ -1507,6 +1524,7 @@ OG Sponsors ❤️ + OG Sponsorer ❤️ src/app/components/about/about.component.html 228 @@ -1589,6 +1607,7 @@ Learn more about The Mempool Open Source Project®: enterprise sponsors, individual sponsors, integrations, who contributes, FOSS licensing, and more. + Lær mer om The Mempool Open Source Project®: bedriftssponsorer, individuelle sponsorer, integrasjoner, hvem som bidrar, FOSS-lisensiering og mer. src/app/components/about/about.component.ts 46 @@ -1818,7 +1837,8 @@ - See mempool transactions, confirmed transactions, balance, and more for address . + See mempool transactions, confirmed transactions, balance, and more for address . + Se mempool-transaksjoner, bekreftede transaksjoner, saldo og mer for adresse . src/app/components/address/address-preview.component.ts 72 @@ -2114,6 +2134,7 @@ Explore all the assets issued on the Liquid network like L-BTC, L-CAD, USDT, and more. + Utforsk alle eiendelene utstedt på Liquid-nettverket som L-BTC, L-CAD, USDT og mer. src/app/components/assets/assets-nav/assets-nav.component.ts 43 @@ -2276,6 +2297,7 @@ See Bitcoin feerates visualized over time, including minimum and maximum feerates per block along with feerates at various percentiles. + Se Bitcoin-gebyrer visualisert over tid, inkludert minimums- og maksimumsgebyrer per blokk sammen med gebyrer på forskjellige persentiler. src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.ts 67 @@ -2332,6 +2354,7 @@ See the average mining fees earned per Bitcoin block visualized in BTC and USD over time. + Se gjennomsnittlig utvinningsavgift tjent per Bitcoin-blokk visualisert i BTC og USD over tid. src/app/components/block-fees-graph/block-fees-graph.component.ts 68 @@ -2375,6 +2398,7 @@ Block Health + Blokkhelse src/app/components/block-health-graph/block-health-graph.component.html 6 @@ -2387,6 +2411,7 @@ Block Health + Blokkhelse src/app/components/block-health-graph/block-health-graph.component.ts 63 @@ -2394,6 +2419,7 @@ See Bitcoin block health visualized over time. Block health is a measure of how many expected transactions were included in an actual mined block. Expected transactions are determined using Mempool's re-implementation of Bitcoin Core's transaction selection algorithm. + Se Bitcoin-blokkhelse visualisert over tid. Blokkhelse er et mål på hvor mange forventede transaksjoner som ble inkludert i en faktisk utvunnet blokk. Forventede transaksjoner bestemmes ved hjelp av Mempools re-implementering av Bitcoin Cores transaksjonsvalgalgoritme. src/app/components/block-health-graph/block-health-graph.component.ts 64 @@ -2416,7 +2442,7 @@ src/app/lightning/nodes-channels-map/nodes-channels-map.component.ts - 215 + 216 src/app/lightning/nodes-map/nodes-map.component.ts @@ -2425,6 +2451,7 @@ Health + Helse src/app/components/block-health-graph/block-health-graph.component.ts 190 @@ -2515,6 +2542,7 @@ Accelerated fee rate + Akselerert gebyrsats src/app/components/block-overview-tooltip/block-overview-tooltip.component.html 33 @@ -2546,6 +2574,7 @@ Weight + Vekt src/app/components/block-overview-tooltip/block-overview-tooltip.component.html 43 @@ -2603,6 +2632,7 @@ High sigop count + Høyt antall sigops src/app/components/block-overview-tooltip/block-overview-tooltip.component.html 52 @@ -2620,6 +2650,7 @@ Recently CPFP'd + Nylig CPFPet src/app/components/block-overview-tooltip/block-overview-tooltip.component.html 54 @@ -2637,6 +2668,7 @@ Conflicting + Motstridende src/app/components/block-overview-tooltip/block-overview-tooltip.component.html 57 @@ -2645,6 +2677,7 @@ Accelerated + Akselerert src/app/components/block-overview-tooltip/block-overview-tooltip.component.html 58 @@ -2670,6 +2703,7 @@ See Bitcoin block rewards in BTC and USD visualized over time. Block rewards are the total funds miners earn from the block subsidy and fees. + Se Bitcoin-blokkbelønninger i BTC og USD visualisert over tid. Blokkbelønninger er de totale midlene utvinnerene tjener fra blokksubsidier og gebyr. src/app/components/block-rewards-graph/block-rewards-graph.component.ts 66 @@ -2694,6 +2728,7 @@ See Bitcoin block sizes (MB) and block weights (weight units) visualized over time. + Se Bitcoin-blokkstørrelser (MB) og blokkvekter (vektenheter) visualisert over tid. src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.ts 63 @@ -2809,6 +2844,7 @@ See size, weight, fee range, included transactions, and more for Liquid block (). + Se størrelse, vekt, gebyrområde, inkluderte transaksjoner og mer for Liquid blokk (). src/app/components/block-view/block-view.component.ts 112 @@ -2824,6 +2860,7 @@ See size, weight, fee range, included transactions, audit (expected v actual), and more for Bitcoin block (). + Se størrelse, vekt, gebyrområde, inkluderte transaksjoner, revisjon (forventet v faktisk) og mer for Bitcoin blokk ( ). src/app/components/block-view/block-view.component.ts 114 @@ -2912,6 +2949,7 @@ This block does not belong to the main chain, it has been replaced by: + Denne blokken tilhører ikke hovedkjeden, den er erstattet av: src/app/components/block/block.component.html 5 @@ -2947,6 +2985,7 @@ Stale + Foreldet src/app/components/block/block.component.html 30 @@ -3412,6 +3451,7 @@ Blocks + Blokker src/app/components/blocks-list/blocks-list.component.ts 59 @@ -3419,6 +3459,7 @@ See the most recent Liquid blocks along with basic stats such as block height, block size, and more. + Se de nyeste Liquid-blokkene sammen med grunnleggende statistikk som blokkhøyde, blokkstørrelse og mer. src/app/components/blocks-list/blocks-list.component.ts 62 @@ -3426,6 +3467,7 @@ See the most recent Bitcoin blocks along with basic stats such as block height, block reward, block size, and more. + Se de nyeste Bitcoin-blokkene sammen med grunnleggende statistikk som blokkhøyde, blokkbelønning, blokkstørrelse og mer. src/app/components/blocks-list/blocks-list.component.ts 64 @@ -3433,6 +3475,7 @@ Calculator + Kalkulator src/app/components/calculator/calculator.component.html 3 @@ -3470,6 +3513,7 @@ Memory Usage + Minnebruk src/app/components/clock/clock.component.html 65 @@ -3549,6 +3593,7 @@ blocks + blokker src/app/components/difficulty-mining/difficulty-mining.component.html 10,11 @@ -3852,6 +3897,7 @@ WU/s + WU/s src/app/components/footer/footer.component.html 14 @@ -4024,7 +4070,7 @@ src/app/lightning/nodes-channels-map/nodes-channels-map.component.html - 6 + 19 lightning.nodes-channels-world-map @@ -4072,6 +4118,7 @@ See hashrate and difficulty for the Bitcoin network visualized over time. + Se hashrate og vanskelighetsgrad for Bitcoin-nettverket visualisert over tid. src/app/components/hashrate-chart/hashrate-chart.component.ts 75 @@ -4179,6 +4226,7 @@ See stats for transactions in the mempool: fee range, aggregate size, and more. Mempool blocks are updated in real-time as the network receives new transactions. + Se statistikk for transaksjoner i mempoolen: gebyrområde, samlet størrelse og mer. Mempool-blokker oppdateres i sanntid etter hvert som nettverket mottar nye transaksjoner. src/app/components/mempool-block/mempool-block.component.ts 58 @@ -4202,6 +4250,7 @@ Count + Antall src/app/components/mempool-graph/mempool-graph.component.ts 325 @@ -4229,6 +4278,7 @@ Sign in + Logg inn src/app/components/menu/menu.component.html 10 @@ -4255,6 +4305,7 @@ Recent Blocks + Nylige blokker src/app/components/mining-dashboard/mining-dashboard.component.html 52 @@ -4280,6 +4331,7 @@ Get real-time Bitcoin mining stats like hashrate, difficulty adjustment, block rewards, pool dominance, and more. + Få sanntids Bitcoin-utvinningsstatistikk som hashrate, vanskeliggradsjustering, blokkbelønninger, gruppedominans og mer. src/app/components/mining-dashboard/mining-dashboard.component.ts 21 @@ -4296,6 +4348,7 @@ Pools Luck + Gruppeflaks src/app/components/pool-ranking/pool-ranking.component.html 9 @@ -4326,6 +4379,7 @@ Pools Count + Antall grupper src/app/components/pool-ranking/pool-ranking.component.html 17 @@ -4440,6 +4494,7 @@ Empty Blocks + Tomme blokker src/app/components/pool-ranking/pool-ranking.component.html 98 @@ -4465,6 +4520,7 @@ See the top Bitcoin mining pools ranked by number of blocks mined, over your desired timeframe. + Se de beste utvinningsgruppene rangert etter antall blokker utvunnet, over ønsket tidsramme. src/app/components/pool-ranking/pool-ranking.component.ts 59 @@ -4554,6 +4610,7 @@ See mining pool stats for : most recent mined blocks, hashrate over time, total block reward to date, known coinbase addresses, and more. + Se utvinningsgruppe-statistikk for : siste utvunnede blokker, hashrate over tid, total blokkbelønning hittil, kjente coinbaseadresser og mer. src/app/components/pool/pool-preview.component.ts 86 @@ -4620,6 +4677,7 @@ Blocks (24h) + Blokker (24 timer) src/app/components/pool/pool.component.html 146 @@ -4734,6 +4792,7 @@ Broadcast Transaction + Kringkast transaksjon src/app/components/push-transaction/push-transaction.component.ts 31 @@ -4741,6 +4800,7 @@ Broadcast a transaction to the network using the transaction's hash. + Kringkast en transaksjon til -nettverket ved å bruke transaksjonens hash. src/app/components/push-transaction/push-transaction.component.ts 32 @@ -4748,6 +4808,7 @@ RBF Replacements + RBF-erstatninger src/app/components/rbf-list/rbf-list.component.html 2 @@ -4760,6 +4821,7 @@ Full RBF + Full RBF src/app/components/rbf-list/rbf-list.component.html 24 @@ -4776,6 +4838,7 @@ There are no replacements in the mempool yet! + Det er ingen erstatninger i mempoolen ennå! src/app/components/rbf-list/rbf-list.component.html 34 @@ -4784,6 +4847,7 @@ See the most recent RBF replacements on the Bitcoin network, updated in real-time. + Se de siste RBF-erstatningene på Bitcoin-nettverket, oppdatert i sanntid. src/app/components/rbf-list/rbf-list.component.ts 59 @@ -4829,6 +4893,7 @@ Status + Status src/app/components/rbf-timeline/rbf-timeline-tooltip.component.html 33 @@ -4846,6 +4911,7 @@ RBF + RBF src/app/components/rbf-timeline/rbf-timeline-tooltip.component.html 36 @@ -5065,6 +5131,7 @@ Clock (Mempool) + Klokke (Mempool) src/app/components/statistics/statistics.component.html 17 @@ -5117,6 +5184,7 @@ Cap outliers + Fjern avvikere src/app/components/statistics/statistics.component.html 122 @@ -5125,6 +5193,7 @@ See mempool size (in MvB) and transactions per second (in vB/s) visualized over time. + Se mempoolstørrelse (i MvB) og transaksjoner per sekund (i vB/s) visualisert over tid. src/app/components/statistics/statistics.component.ts 67 @@ -5132,6 +5201,7 @@ See Bitcoin blocks and mempool congestion in real-time in a simplified format perfect for a TV. + Se Bitcoin-blokker og mempool i sanntid i et forenklet format perfekt for en TV. src/app/components/television/television.component.ts 40 @@ -5343,7 +5413,8 @@ transactions-list.coinbase - Get real-time status, addresses, fees, script info, and more for transaction with txid {txid}. + Get real-time status, addresses, fees, script info, and more for transaction with txid . + Få sanntidsstatus, adresser, gebyrer, skriptinformasjon og mer for transaksjon med txid . src/app/components/transaction/transaction-preview.component.ts 91 @@ -5385,6 +5456,7 @@ Accelerate + Akselerer src/app/components/transaction/transaction.component.html 123 @@ -5422,6 +5494,7 @@ RBF History + RBF historie src/app/components/transaction/transaction.component.html 218 @@ -5493,6 +5566,7 @@ Adjusted vsize + Justert vsize src/app/components/transaction/transaction.component.html 298 @@ -5511,6 +5585,7 @@ Sigops + Sigops src/app/components/transaction/transaction.component.html 320 @@ -5538,6 +5613,7 @@ Accelerated fee rate + Akselerert gebyrsats src/app/components/transaction/transaction.component.html 516 @@ -5893,6 +5969,7 @@ Recent Replacements + Nylige erstatninger src/app/dashboard/dashboard.component.html 79 @@ -5901,6 +5978,7 @@ Previous fee + Tidligere avgift src/app/dashboard/dashboard.component.html 86 @@ -5909,6 +5987,7 @@ New fee + Ny avgift src/app/dashboard/dashboard.component.html 87 @@ -5917,6 +5996,7 @@ Recent Transactions + Nylige transaksjoner src/app/dashboard/dashboard.component.html 153 @@ -5954,6 +6034,7 @@ Incoming Transactions + Innkommende transaksjoner src/app/dashboard/dashboard.component.html 259 @@ -5962,6 +6043,7 @@ mempool.space merely provides data about the Bitcoin network. It cannot help you with retrieving funds, wallet issues, etc.For any such requests, you need to get in touch with the entity that helped make the transaction (wallet software, exchange company, etc). + mempool.space gir bare data om Bitcoin-nettverket. Det kan ikke hjelpe deg med å hente midler, lommebokproblemer osv.For slike forespørsler må du ta kontakt med enheten som bidro til transaksjonen (lommebokprogramvare, børsselskap osv.). src/app/docs/api-docs/api-docs.component.html 15,16 @@ -6056,6 +6138,7 @@ FAQ + FAQ src/app/docs/docs/docs.component.ts 45 @@ -6063,6 +6146,7 @@ Get answers to common questions like: What is a mempool? Why isn't my transaction confirming? How can I run my own instance of The Mempool Open Source Project? And more. + Få svar på vanlige spørsmål som: Hva er en mempool? Hvorfor bekreftes ikke transaksjonen min? Hvordan kan jeg kjøre min egen instans av Mempool Open Source Project? Og mer. src/app/docs/docs/docs.component.ts 46 @@ -6070,6 +6154,7 @@ REST API + REST API src/app/docs/docs/docs.component.ts 49 @@ -6077,6 +6162,7 @@ Documentation for the liquid.network REST API service: get info on addresses, transactions, assets, blocks, and more. + Dokumentasjon for liquid.network REST API-tjenesten: få informasjon om adresser, transaksjoner, eiendeler, blokker og mer. src/app/docs/docs/docs.component.ts 51 @@ -6084,6 +6170,7 @@ Documentation for the bisq.markets REST API service: get info on recent trades, current offers, transactions, network state, and more. + Dokumentasjon for bisq.markets REST API-tjenesten: få informasjon om nylige handler, nåværende tilbud, transaksjoner, nettverkstilstand og mer. src/app/docs/docs/docs.component.ts 53 @@ -6091,6 +6178,7 @@ Documentation for the mempool.space REST API service: get info on addresses, transactions, blocks, fees, mining, the Lightning network, and more. + Dokumentasjon for mempool.space REST API-tjenesten: få informasjon om adresser, transaksjoner, blokker, avgifter, utvinning, Lightning-nettverket og mer. src/app/docs/docs/docs.component.ts 55 @@ -6098,6 +6186,7 @@ WebSocket API + WebSocket API src/app/docs/docs/docs.component.ts 59 @@ -6105,6 +6194,7 @@ Documentation for the liquid.network WebSocket API service: get real-time info on blocks, mempools, transactions, addresses, and more. + Dokumentasjon for liquid.network WebSocket API-tjenesten: få sanntidsinformasjon om blokker, mempooler, transaksjoner, adresser og mer. src/app/docs/docs/docs.component.ts 61 @@ -6112,6 +6202,7 @@ Documentation for the mempool.space WebSocket API service: get real-time info on blocks, mempools, transactions, addresses, and more. + Dokumentasjon for mempool.space WebSocket API-tjenesten: få sanntidsinformasjon om blokker, mempooler, transaksjoner, adresser og mer. src/app/docs/docs/docs.component.ts 63 @@ -6119,6 +6210,7 @@ Electrum RPC + Electrum RPC src/app/docs/docs/docs.component.ts 67 @@ -6126,6 +6218,7 @@ Documentation for our Electrum RPC interface: get instant, convenient, and reliable access to an Esplora instance. + Dokumentasjon for vårt Electrum RPC-grensesnitt: få umiddelbar, praktisk og pålitelig tilgang til en Esplora-instans. src/app/docs/docs/docs.component.ts 68 @@ -6438,6 +6531,7 @@ Overview for Lightning channel . See channel capacity, the Lightning nodes involved, related on-chain transactions, and more. + Oversikt for Lightning-kanalen . Se kanalkapasitet, Lightning-nodene som er involvert, relaterte transaksjoner i kjeden og mer. src/app/lightning/channel/channel-preview.component.ts 37 @@ -6936,6 +7030,7 @@ Connect + Koble til src/app/lightning/group/group.component.html 73 @@ -6986,6 +7081,7 @@ Penalties + Straffer src/app/lightning/justice-list/justice-list.component.html 4 @@ -7062,7 +7158,8 @@ lightning.connectivity-ranking - Get stats on the Lightning network (aggregate capacity, connectivity, etc) and Lightning nodes (channels, liquidity, etc) and Lightning channels (status, fees, etc). + Get stats on the Lightning network (aggregate capacity, connectivity, etc), Lightning nodes (channels, liquidity, etc) and Lightning channels (status, fees, etc). + Få statistikk om Lightning-nettverket (samlet kapasitet, tilkobling osv.), Lightning-noder (kanaler, likviditet osv.) og Lightning-kanaler (status, avgifter osv.). src/app/lightning/lightning-dashboard/lightning-dashboard.component.ts 28 @@ -7172,6 +7269,7 @@ Overview for the Lightning network node named . See channels, capacity, location, fee stats, and more. + Oversikt for Lightning-nettverksnoden . Se kanaler, kapasitet, plassering, gebyrstatistikk og mer. src/app/lightning/node/node-preview.component.ts 52 @@ -7232,6 +7330,7 @@ Decoded + Dekodet src/app/lightning/node/node.component.html 136 @@ -7344,7 +7443,7 @@ (Tor-noder ekskludert) src/app/lightning/nodes-channels-map/nodes-channels-map.component.html - 8 + 21 src/app/lightning/nodes-map/nodes-map.component.html @@ -7365,14 +7464,15 @@ Lightning-kanaler verdenskart src/app/lightning/nodes-channels-map/nodes-channels-map.component.ts - 68 + 69 See the channels of non-Tor Lightning network nodes visualized on a world map. Hover/tap on points on the map for node names and details. + Se kanalene til ikke-Tor Lightning-nettverksnoder visualisert på et verdenskart. Hold musepekeren/trykk på punkter på kartet for nodenavn og detaljer. src/app/lightning/nodes-channels-map/nodes-channels-map.component.ts - 69 + 70 @@ -7380,7 +7480,7 @@ Ingen geolokaliseringsdata tilgjengelig src/app/lightning/nodes-channels-map/nodes-channels-map.component.ts - 227 + 228 @@ -7394,6 +7494,7 @@ See the locations of non-Tor Lightning network nodes visualized on a world map. Hover/tap on points on the map for node names and details. + Se plasseringen til ikke-Tor Lightning-nettverksnoder visualisert på et verdenskart. Hold musepekeren/trykk på punkter på kartet for nodenavn og detaljer. src/app/lightning/nodes-map/nodes-map.component.ts 51 @@ -7401,6 +7502,7 @@ See the number of Lightning network nodes visualized over time by network: clearnet only (IPv4, IPv6), darknet (Tor, I2p, cjdns), and both. + Se antall Lightning-nettverksnoder visualisert over tid etter nettverk: bare clearnet (IPv4, IPv6), darknet (Tor, I2p, cjdns) og begge deler. src/app/lightning/nodes-networks-chart/nodes-networks-chart.component.ts 68 @@ -7469,6 +7571,7 @@ See a geographical breakdown of the Lightning network: how many Lightning nodes are hosted in countries around the world, aggregate BTC capacity for each country, and more. + Se en geografisk inndeling av Lightning-nettverket: hvor mange Lightning-noder er det i land rundt om i verden, samlet BTC-kapasitet for hvert land, og mer. src/app/lightning/nodes-per-country-chart/nodes-per-country-chart.component.ts 47 @@ -7539,6 +7642,7 @@ Explore all the Lightning nodes hosted in and see an overview of each node's capacity, number of open channels, and more. + Utforsk alle Lightning-nodene som er i og se en oversikt over hver nodes kapasitet, antall åpne kanaler og mer. src/app/lightning/nodes-per-country/nodes-per-country.component.ts 36 @@ -7689,6 +7793,7 @@ Browse all Bitcoin Lightning nodes using the [AS] ISP and see aggregate stats like total number of nodes, total capacity, and more for the ISP. + Bla gjennom alle Bitcoin Lightning-noder ved å bruke [AS] ISP og se samlet statistikk som totalt antall noder, total kapasitet, og mer for Internett-leverandøren. src/app/lightning/nodes-per-isp/nodes-per-isp-preview.component.ts 45 @@ -7744,6 +7849,7 @@ See the oldest nodes on the Lightning network along with their capacity, number of channels, location, etc. + Se de eldste nodene på Lightning-nettverket sammen med deres kapasitet, antall kanaler, plassering osv. src/app/lightning/nodes-ranking/oldest-nodes/oldest-nodes.component.ts 28 @@ -7751,6 +7857,7 @@ See Lightning nodes with the most BTC liquidity deployed along with high-level stats like number of open channels, location, node age, and more. + Se Lightning-noder med mest BTC-likviditet utplassert sammen med statistikk som antall åpne kanaler, plassering, nodens alder og mer. src/app/lightning/nodes-ranking/top-nodes-per-capacity/top-nodes-per-capacity.component.ts 34 @@ -7758,6 +7865,7 @@ See Lightning nodes with the most channels open along with high-level stats like total node capacity, node age, and more. + Se Lightning-noder med flest åpne kanaler sammen med statistikk som total nodekapasitet, nodealder og mer. src/app/lightning/nodes-ranking/top-nodes-per-channels/top-nodes-per-channels.component.ts 38 @@ -7781,7 +7889,8 @@ - See top the Lightning network nodes ranked by liquidity, connectivity, and age. + See the top Lightning network nodes ranked by liquidity, connectivity, and age. + Se de beste Lightning-nettverksnodene rangert etter likviditet, tilkobling og alder. src/app/lightning/nodes-rankings-dashboard/nodes-rankings-dashboard.component.ts 23 @@ -7789,6 +7898,7 @@ See the capacity of the Lightning network visualized over time in terms of the number of open channels and total bitcoin capacity. + Se kapasiteten til Lightning-nettverket visualisert over tid i form av antall åpne kanaler og total bitcoin-kapasitet. src/app/lightning/statistics-chart/lightning-statistics-chart.component.ts 67 @@ -7796,6 +7906,7 @@ confirmation + bekreftelse src/app/shared/components/confirmations/confirmations.component.html 4 @@ -7805,6 +7916,7 @@ confirmations + bekreftelser src/app/shared/components/confirmations/confirmations.component.html 5 @@ -7814,6 +7926,7 @@ Replaced + Erstattet src/app/shared/components/confirmations/confirmations.component.html 12 @@ -7823,6 +7936,7 @@ Removed + Fjernet src/app/shared/components/confirmations/confirmations.component.html 15 @@ -7842,6 +7956,7 @@ sat/WU + sat/WU src/app/shared/components/fee-rate/fee-rate.component.html 3 @@ -7851,6 +7966,7 @@ My Account + Min konto src/app/shared/components/global-footer/global-footer.component.html 25 @@ -7863,6 +7979,7 @@ Sign In + Logg inn src/app/shared/components/global-footer/global-footer.component.html 26 @@ -7875,6 +7992,7 @@ Explore + Utforsk src/app/shared/components/global-footer/global-footer.component.html 41 @@ -7883,6 +8001,7 @@ Connect to our Nodes + Koble til nodene våre src/app/shared/components/global-footer/global-footer.component.html 46 @@ -7891,6 +8010,7 @@ API Documentation + API-dokumentasjon src/app/shared/components/global-footer/global-footer.component.html 47 @@ -7899,6 +8019,7 @@ Learn + Lær src/app/shared/components/global-footer/global-footer.component.html 50 @@ -7907,6 +8028,7 @@ What is a mempool? + Hva er en mempool? src/app/shared/components/global-footer/global-footer.component.html 51 @@ -7915,6 +8037,7 @@ What is a block explorer? + Hva er en blokkutforsker? src/app/shared/components/global-footer/global-footer.component.html 52 @@ -7923,6 +8046,7 @@ What is a mempool explorer? + Hva er en mempool utforsker? src/app/shared/components/global-footer/global-footer.component.html 53 @@ -7931,6 +8055,7 @@ Why isn't my transaction confirming? + Hvorfor bekreftes ikke transaksjonen min? src/app/shared/components/global-footer/global-footer.component.html 54 @@ -7939,6 +8064,7 @@ More FAQs » + Flere vanlige spørsmål » src/app/shared/components/global-footer/global-footer.component.html 55 @@ -7947,6 +8073,7 @@ Networks + Nettverk src/app/shared/components/global-footer/global-footer.component.html 59 @@ -7955,6 +8082,7 @@ Mainnet Explorer + Mainnet utforsker src/app/shared/components/global-footer/global-footer.component.html 60 @@ -7963,6 +8091,7 @@ Testnet Explorer + Testnet utforsker src/app/shared/components/global-footer/global-footer.component.html 61 @@ -7971,6 +8100,7 @@ Signet Explorer + Signet utforsker src/app/shared/components/global-footer/global-footer.component.html 62 @@ -7979,6 +8109,7 @@ Liquid Testnet Explorer + Liquid testnet utforsker src/app/shared/components/global-footer/global-footer.component.html 63 @@ -7987,6 +8118,7 @@ Liquid Explorer + Liquid utforsker src/app/shared/components/global-footer/global-footer.component.html 64 @@ -7995,6 +8127,7 @@ Bisq Explorer + Bisq utforsker src/app/shared/components/global-footer/global-footer.component.html 65 @@ -8003,6 +8136,7 @@ Tools + Verktøy src/app/shared/components/global-footer/global-footer.component.html 69 @@ -8011,6 +8145,7 @@ Clock (Mined) + Klokke (utvunnet) src/app/shared/components/global-footer/global-footer.component.html 71 @@ -8019,6 +8154,7 @@ Legal + Lovlig src/app/shared/components/global-footer/global-footer.component.html 76 @@ -8047,6 +8183,7 @@ Trademark Policy + Varemerkepolitikk src/app/shared/components/global-footer/global-footer.component.html 79 @@ -8056,6 +8193,7 @@ This is a test network. Coins have no value. + Dette er et testnettverk. Mynter har ingen verdi. src/app/shared/components/testnet-alert/testnet-alert.component.html 3 From 65236c7b08c63498f849a695767fccdecdf4a074 Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Sat, 13 Jan 2024 13:55:12 -0800 Subject: [PATCH 77/80] Add seconds to the block view timestamp --- frontend/src/app/components/block/block.component.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/app/components/block/block.component.html b/frontend/src/app/components/block/block.component.html index b34b39c8c..885f8e1ac 100644 --- a/frontend/src/app/components/block/block.component.html +++ b/frontend/src/app/components/block/block.component.html @@ -47,7 +47,7 @@ Timestamp - + From a8442a3467d808d63406a38a90680db9f8e1d70b Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Sat, 13 Jan 2024 18:11:13 -0800 Subject: [PATCH 78/80] Add seconds to block timestamp in the mining pool view and blocks list --- .../src/app/components/blocks-list/blocks-list.component.html | 2 +- frontend/src/app/components/pool/pool.component.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/blocks-list/blocks-list.component.html b/frontend/src/app/components/blocks-list/blocks-list.component.html index 85e2ea17f..838c7cb4e 100644 --- a/frontend/src/app/components/blocks-list/blocks-list.component.html +++ b/frontend/src/app/components/blocks-list/blocks-list.component.html @@ -46,7 +46,7 @@
    - ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }} + ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm:ss' }} {{ block.height }} - ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }} + ‎{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm:ss' }} From 0722c221c78729f3954e5d2e2f620c7fa52e4200 Mon Sep 17 00:00:00 2001 From: softsimon Date: Sun, 14 Jan 2024 11:24:56 +0700 Subject: [PATCH 79/80] Minor adjustments --- .../search-form/search-results/search-results.component.html | 4 ++-- .../search-form/search-results/search-results.component.ts | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/app/components/search-form/search-results/search-results.component.html b/frontend/src/app/components/search-form/search-results/search-results.component.html index f83df6b93..5d64b7495 100644 --- a/frontend/src/app/components/search-form/search-results/search-results.component.html +++ b/frontend/src/app/components/search-form/search-results/search-results.component.html @@ -36,10 +36,10 @@ -
    Other Networks Address
    +
    Other Network Address
    diff --git a/frontend/src/app/components/search-form/search-results/search-results.component.ts b/frontend/src/app/components/search-form/search-results/search-results.component.ts index 84c541a70..ade01bf89 100644 --- a/frontend/src/app/components/search-form/search-results/search-results.component.ts +++ b/frontend/src/app/components/search-form/search-results/search-results.component.ts @@ -45,6 +45,9 @@ export class SearchResultsComponent implements OnChanges { break; case 'Enter': event.preventDefault(); + if (this.resultsFlattened[this.activeIdx]?.isNetworkAvailable === false) { + return; + } if (this.resultsFlattened[this.activeIdx]) { this.selectedResult.emit(this.resultsFlattened[this.activeIdx]); } else { From 00b8f001b0d9f37458f6979fb209c7e39b7cb5ca Mon Sep 17 00:00:00 2001 From: Mononaut Date: Mon, 15 Jan 2024 02:47:29 +0000 Subject: [PATCH 80/80] Fix goggles inscription detection bug --- backend/src/api/common.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/backend/src/api/common.ts b/backend/src/api/common.ts index 358a98c98..af93b9622 100644 --- a/backend/src/api/common.ts +++ b/backend/src/api/common.ts @@ -263,8 +263,13 @@ export class Common { case 'v0_p2wsh': flags |= TransactionFlags.p2wsh; break; case 'v1_p2tr': { flags |= TransactionFlags.p2tr; - if (vin.witness.length > 2) { - const asm = vin.inner_witnessscript_asm || transactionUtils.convertScriptSigAsm(vin.witness[vin.witness.length - 2]); + // in taproot, if the last witness item begins with 0x50, it's an annex + const hasAnnex = vin.witness?.[vin.witness.length - 1].startsWith('50'); + // script spends have more than one witness item, not counting the annex (if present) + if (vin.witness.length > (hasAnnex ? 2 : 1)) { + // the script itself is the second-to-last witness item, not counting the annex + const asm = vin.inner_witnessscript_asm || transactionUtils.convertScriptSigAsm(vin.witness[vin.witness.length - (hasAnnex ? 3 : 2)]); + // inscriptions smuggle data within an 'OP_0 OP_IF ... OP_ENDIF' envelope if (asm?.includes('OP_0 OP_IF')) { flags |= TransactionFlags.inscription; }

    Ovtf*nL@gSdACc7IN#w*q(qasboeh(OrTrAK3) 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 From 4f3852bbba88265b88ae0175febe5ce484e83bde Mon Sep 17 00:00:00 2001 From: Matt Hill Date: Tue, 19 Dec 2023 21:49:52 -0700 Subject: [PATCH 33/80] One more --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e272c6b39..7e426f155 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Mempool can be conveniently installed on the following full-node distros: - [RaspiBlitz](https://github.com/rootzoll/raspiblitz) - [RoninDojo](https://code.samourai.io/ronindojo/RoninDojo) - [myNode](https://github.com/mynodebtc/mynode) -- [Start9](https://github.com/Start9Labs/start-os) +- [StartOS](https://github.com/Start9Labs/start-os) - [nix-bitcoin](https://github.com/fort-nix/nix-bitcoin/blob/a1eacce6768ca4894f365af8f79be5bbd594e1c3/examples/configuration.nix#L129) **We highly recommend you deploy your own Mempool instance this way.** No matter which option you pick, you'll be able to get your own fully-sovereign instance of Mempool up quickly without needing to fiddle with any settings. From f4715419073e98792b78e2735c4f72c2bed665e8 Mon Sep 17 00:00:00 2001 From: natsee Date: Wed, 20 Dec 2023 16:21:40 +0100 Subject: [PATCH 34/80] Fix fade out on RBF history --- .../rbf-timeline/rbf-timeline.component.html | 21 +++++------ .../rbf-timeline/rbf-timeline.component.scss | 35 ++++++++++--------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html index 9ff35d669..6f19537e1 100644 --- a/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html +++ b/frontend/src/app/components/rbf-timeline/rbf-timeline.component.html @@ -1,6 +1,6 @@