diff --git a/backend/src/api/blocks.ts b/backend/src/api/blocks.ts index 16ae94f66..42e15bf82 100644 --- a/backend/src/api/blocks.ts +++ b/backend/src/api/blocks.ts @@ -839,8 +839,11 @@ class Blocks { } else { this.currentBlockHeight++; logger.debug(`New block found (#${this.currentBlockHeight})!`); - this.updateTimerProgress(timer, `getting orphaned blocks for ${this.currentBlockHeight}`); - await chainTips.updateOrphanedBlocks(); + // skip updating the orphan block cache if we've fallen behind the chain tip + if (this.currentBlockHeight >= blockHeightTip - 2) { + this.updateTimerProgress(timer, `getting orphaned blocks for ${this.currentBlockHeight}`); + await chainTips.updateOrphanedBlocks(); + } } this.updateTimerProgress(timer, `getting block data for ${this.currentBlockHeight}`); diff --git a/backend/src/api/chain-tips.ts b/backend/src/api/chain-tips.ts index b68b0b281..b7fd05ad8 100644 --- a/backend/src/api/chain-tips.ts +++ b/backend/src/api/chain-tips.ts @@ -12,32 +12,68 @@ export interface OrphanedBlock { height: number; hash: string; status: 'valid-fork' | 'valid-headers' | 'headers-only'; + prevhash: string; } class ChainTips { private chainTips: ChainTip[] = []; - private orphanedBlocks: OrphanedBlock[] = []; + private orphanedBlocks: { [hash: string]: OrphanedBlock } = {}; + private blockCache: { [hash: string]: OrphanedBlock } = {}; + private orphansByHeight: { [height: number]: OrphanedBlock[] } = {}; public async updateOrphanedBlocks(): Promise { try { this.chainTips = await bitcoinClient.getChainTips(); - this.orphanedBlocks = []; + + const start = Date.now(); + const breakAt = start + 10000; + let newOrphans = 0; + this.orphanedBlocks = {}; for (const chain of this.chainTips) { if (chain.status === 'valid-fork' || chain.status === 'valid-headers') { - let block = await bitcoinClient.getBlock(chain.hash); - while (block && block.confirmations === -1) { - this.orphanedBlocks.push({ - height: block.height, - hash: block.hash, - status: chain.status - }); - block = await bitcoinClient.getBlock(block.previousblockhash); + const orphans: OrphanedBlock[] = []; + let hash = chain.hash; + do { + let orphan = this.blockCache[hash]; + if (!orphan) { + const block = await bitcoinClient.getBlock(hash); + if (block && block.confirmations === -1) { + newOrphans++; + orphan = { + height: block.height, + hash: block.hash, + status: chain.status, + prevhash: block.previousblockhash, + }; + this.blockCache[hash] = orphan; + } + } + if (orphan) { + orphans.push(orphan); + } + hash = orphan?.prevhash; + } while (hash && (Date.now() < breakAt)); + for (const orphan of orphans) { + this.orphanedBlocks[orphan.hash] = orphan; } } + if (Date.now() >= breakAt) { + logger.debug(`Breaking orphaned blocks updater after 10s, will continue next block`); + break; + } } - logger.debug(`Updated orphaned blocks cache. Found ${this.orphanedBlocks.length} orphaned blocks`); + this.orphansByHeight = {}; + const allOrphans = Object.values(this.orphanedBlocks); + for (const orphan of allOrphans) { + if (!this.orphansByHeight[orphan.height]) { + this.orphansByHeight[orphan.height] = []; + } + this.orphansByHeight[orphan.height].push(orphan); + } + + logger.debug(`Updated orphaned blocks cache. Fetched ${newOrphans} new orphaned blocks. Total ${allOrphans.length}`); } catch (e) { logger.err(`Cannot get fetch orphaned blocks. Reason: ${e instanceof Error ? e.message : e}`); } @@ -48,13 +84,7 @@ class ChainTips { return []; } - const orphans: OrphanedBlock[] = []; - for (const block of this.orphanedBlocks) { - if (block.height === height) { - orphans.push(block); - } - } - return orphans; + return this.orphansByHeight[height] || []; } } diff --git a/frontend/angular.json b/frontend/angular.json index 46cc3f667..190982225 100644 --- a/frontend/angular.json +++ b/frontend/angular.json @@ -181,6 +181,11 @@ "bundleName": "wiz", "inject": false }, + { + "input": "src/theme-bukele.scss", + "bundleName": "bukele", + "inject": false + }, "node_modules/@fortawesome/fontawesome-svg-core/styles.css" ], "vendorChunk": true, diff --git a/frontend/custom-sv-config.json b/frontend/custom-sv-config.json index f64f41be8..dee3dab18 100644 --- a/frontend/custom-sv-config.json +++ b/frontend/custom-sv-config.json @@ -1,30 +1,37 @@ { - "theme": "contrast", + "theme": "bukele", "enterprise": "onbtc", "branding": { "name": "onbtc", - "title": "Oficina Nacional del Bitcoin", + "title": "Bitcoin Office", "site_id": 19, - "header_img": "/resources/onbtc.svg", - "img": "/resources/elsalvador.svg", + "header_img": "/resources/onbtclogo.svg", + "footer_img": "/resources/onbtclogo.svg", "rounded_corner": true }, "dashboard": { "widgets": [ { - "component": "fees" + "component": "fees", + "mobileOrder": 4 }, { "component": "balance", + "mobileOrder": 1, "props": { "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo" } }, { - "component": "goggles" + "component": "twitter", + "mobileOrder": 5, + "props": { + "handle": "nayibbukele" + } }, { "component": "address", + "mobileOrder": 2, "props": { "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo", "period": "1m" @@ -35,6 +42,7 @@ }, { "component": "addressTransactions", + "mobileOrder": 3, "props": { "address": "32ixEdVJWo3kmvJGMTZq5jAQVZZeuwnqzo" } diff --git a/frontend/generate-config.js b/frontend/generate-config.js index 8f911dfe6..91a9a2abb 100644 --- a/frontend/generate-config.js +++ b/frontend/generate-config.js @@ -10,6 +10,7 @@ let settings = []; let configContent = {}; let gitCommitHash = ''; let packetJsonVersion = ''; +let customConfig; try { const rawConfig = fs.readFileSync(CONFIG_FILE_NAME); @@ -23,7 +24,13 @@ try { } } -const indexFilePath = configContent.BASE_MODULE ? 'src/index.' + configContent.BASE_MODULE + '.html' : 'src/index.mempool.html'; +if (configContent && configContent.CUSTOMIZATION) { + customConfig = readConfig(configContent.CUSTOMIZATION); +} + +const baseModuleName = configContent.BASE_MODULE || 'mempool'; +const customBuildName = (customConfig && configContent.enterprise) ? ('.' + configContent.enterprise) : ''; +const indexFilePath = 'src/index.' + baseModuleName + customBuildName + '.html'; try { fs.copyFileSync(indexFilePath, 'src/index.html'); @@ -111,20 +118,14 @@ writeConfigTemplate(GENERATED_TEMPLATE_CONFIG_FILE_NAME, newConfigTemplate); const currentConfig = readConfig(GENERATED_CONFIG_FILE_NAME); let customConfigJs = ''; -if (configContent && configContent.CUSTOMIZATION) { - const customConfig = readConfig(configContent.CUSTOMIZATION); - if (customConfig) { - console.log(`Customizing frontend using ${configContent.CUSTOMIZATION}`); - customConfigJs = `(function (window) { - window.__env = window.__env || {}; - window.__env.customize = ${customConfig}; - }((typeof global !== 'undefined') ? global : this)); - `; - } else { - throw new Error('Failed to load customization file'); - } +if (customConfig) { + console.log(`Customizing frontend using ${configContent.CUSTOMIZATION}`); + customConfigJs = `(function (window) { + window.__env = window.__env || {}; + window.__env.customize = ${customConfig}; + }((typeof global !== 'undefined') ? global : this)); + `; } - writeConfig(GENERATED_CUSTOMIZATION_FILE_NAME, customConfigJs); if (currentConfig && currentConfig === newConfig) { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5e0702a01..83f9234cb 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -32,10 +32,10 @@ "bootstrap": "~4.6.2", "browserify": "^17.0.0", "clipboard": "^2.0.11", - "cypress": "^13.8.0", + "cypress": "^13.9.0", "domino": "^2.1.6", "echarts": "~5.5.0", - "esbuild": "^0.20.2", + "esbuild": "^0.21.1", "lightweight-charts": "~3.8.0", "ngx-echarts": "~17.1.0", "ngx-infinite-scroll": "^17.0.0", @@ -63,7 +63,7 @@ "optionalDependencies": { "@cypress/schematic": "^2.5.0", "@types/cypress": "^1.1.3", - "cypress": "^13.8.0", + "cypress": "^13.9.0", "cypress-fail-on-console-error": "~5.1.0", "cypress-wait-until": "^2.0.1", "mock-socket": "~9.3.1", @@ -3197,9 +3197,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.1.tgz", + "integrity": "sha512-O7yppwipkXvnEPjzkSXJRk2g4bS8sUx9p9oXHq9MU/U7lxUzZVsnFZMDTmeeX9bfQxrFcvOacl/ENgOh0WP9pA==", "cpu": [ "ppc64" ], @@ -3212,9 +3212,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.1.tgz", + "integrity": "sha512-hh3jKWikdnTtHCglDAeVO3Oyh8MaH8xZUaWMiCCvJ9/c3NtPqZq+CACOlGTxhddypXhl+8B45SeceYBfB/e8Ow==", "cpu": [ "arm" ], @@ -3227,9 +3227,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.1.tgz", + "integrity": "sha512-jXhccq6es+onw7x8MxoFnm820mz7sGa9J14kLADclmiEUH4fyj+FjR6t0M93RgtlI/awHWhtF0Wgfhqgf9gDZA==", "cpu": [ "arm64" ], @@ -3242,9 +3242,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.1.tgz", + "integrity": "sha512-NPObtlBh4jQHE01gJeucqEhdoD/4ya2owSIS8lZYS58aR0x7oZo9lB2lVFxgTANSa5MGCBeoQtr+yA9oKCGPvA==", "cpu": [ "x64" ], @@ -3257,9 +3257,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.1.tgz", + "integrity": "sha512-BLT7TDzqsVlQRmJfO/FirzKlzmDpBWwmCUlyggfzUwg1cAxVxeA4O6b1XkMInlxISdfPAOunV9zXjvh5x99Heg==", "cpu": [ "arm64" ], @@ -3272,9 +3272,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.1.tgz", + "integrity": "sha512-D3h3wBQmeS/vp93O4B+SWsXB8HvRDwMyhTNhBd8yMbh5wN/2pPWRW5o/hM3EKgk9bdKd9594lMGoTCTiglQGRQ==", "cpu": [ "x64" ], @@ -3287,9 +3287,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.1.tgz", + "integrity": "sha512-/uVdqqpNKXIxT6TyS/oSK4XE4xWOqp6fh4B5tgAwozkyWdylcX+W4YF2v6SKsL4wCQ5h1bnaSNjWPXG/2hp8AQ==", "cpu": [ "arm64" ], @@ -3302,9 +3302,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.1.tgz", + "integrity": "sha512-paAkKN1n1jJitw+dAoR27TdCzxRl1FOEITx3h201R6NoXUojpMzgMLdkXVgCvaCSCqwYkeGLoe9UVNRDKSvQgw==", "cpu": [ "x64" ], @@ -3317,9 +3317,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.1.tgz", + "integrity": "sha512-tRHnxWJnvNnDpNVnsyDhr1DIQZUfCXlHSCDohbXFqmg9W4kKR7g8LmA3kzcwbuxbRMKeit8ladnCabU5f2traA==", "cpu": [ "arm" ], @@ -3332,9 +3332,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.1.tgz", + "integrity": "sha512-G65d08YoH00TL7Xg4LaL3gLV21bpoAhQ+r31NUu013YB7KK0fyXIt05VbsJtpqh/6wWxoLJZOvQHYnodRrnbUQ==", "cpu": [ "arm64" ], @@ -3347,9 +3347,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.1.tgz", + "integrity": "sha512-tt/54LqNNAqCz++QhxoqB9+XqdsaZOtFD/srEhHYwBd3ZUOepmR1Eeot8bS+Q7BiEvy9vvKbtpHf+r6q8hF5UA==", "cpu": [ "ia32" ], @@ -3362,9 +3362,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.1.tgz", + "integrity": "sha512-MhNalK6r0nZD0q8VzUBPwheHzXPr9wronqmZrewLfP7ui9Fv1tdPmg6e7A8lmg0ziQCziSDHxh3cyRt4YMhGnQ==", "cpu": [ "loong64" ], @@ -3377,9 +3377,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.1.tgz", + "integrity": "sha512-YCKVY7Zen5rwZV+nZczOhFmHaeIxR4Zn3jcmNH53LbgF6IKRwmrMywqDrg4SiSNApEefkAbPSIzN39FC8VsxPg==", "cpu": [ "mips64el" ], @@ -3392,9 +3392,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.1.tgz", + "integrity": "sha512-bw7bcQ+270IOzDV4mcsKAnDtAFqKO0jVv3IgRSd8iM0ac3L8amvCrujRVt1ajBTJcpDaFhIX+lCNRKteoDSLig==", "cpu": [ "ppc64" ], @@ -3407,9 +3407,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.1.tgz", + "integrity": "sha512-ARmDRNkcOGOm1AqUBSwRVDfDeD9hGYRfkudP2QdoonBz1ucWVnfBPfy7H4JPI14eYtZruRSczJxyu7SRYDVOcg==", "cpu": [ "riscv64" ], @@ -3422,9 +3422,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.1.tgz", + "integrity": "sha512-o73TcUNMuoTZlhwFdsgr8SfQtmMV58sbgq6gQq9G1xUiYnHMTmJbwq65RzMx89l0iya69lR4bxBgtWiiOyDQZA==", "cpu": [ "s390x" ], @@ -3437,9 +3437,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.1.tgz", + "integrity": "sha512-da4/1mBJwwgJkbj4fMH7SOXq2zapgTo0LKXX1VUZ0Dxr+e8N0WbS80nSZ5+zf3lvpf8qxrkZdqkOqFfm57gXwA==", "cpu": [ "x64" ], @@ -3452,9 +3452,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.1.tgz", + "integrity": "sha512-CPWs0HTFe5woTJN5eKPvgraUoRHrCtzlYIAv9wBC+FAyagBSaf+UdZrjwYyTGnwPGkThV4OCI7XibZOnPvONVw==", "cpu": [ "x64" ], @@ -3467,9 +3467,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.1.tgz", + "integrity": "sha512-xxhTm5QtzNLc24R0hEkcH+zCx/o49AsdFZ0Cy5zSd/5tOj4X2g3/2AJB625NoadUuc4A8B3TenLJoYdWYOYCew==", "cpu": [ "x64" ], @@ -3482,9 +3482,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.1.tgz", + "integrity": "sha512-CWibXszpWys1pYmbr9UiKAkX6x+Sxw8HWtw1dRESK1dLW5fFJ6rMDVw0o8MbadusvVQx1a8xuOxnHXT941Hp1A==", "cpu": [ "x64" ], @@ -3497,9 +3497,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.1.tgz", + "integrity": "sha512-jb5B4k+xkytGbGUS4T+Z89cQJ9DJ4lozGRSV+hhfmCPpfJ3880O31Q1srPCimm+V6UCbnigqD10EgDNgjvjerQ==", "cpu": [ "arm64" ], @@ -3512,9 +3512,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.1.tgz", + "integrity": "sha512-PgyFvjJhXqHn1uxPhyN1wZ6dIomKjiLUQh1LjFvjiV1JmnkZ/oMPrfeEAZg5R/1ftz4LZWZr02kefNIQ5SKREQ==", "cpu": [ "ia32" ], @@ -3527,9 +3527,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.1.tgz", + "integrity": "sha512-W9NttRZQR5ehAiqHGDnvfDaGmQOm6Fi4vSlce8mjM75x//XKuVAByohlEX6N17yZnVXxQFuh4fDRunP8ca6bfA==", "cpu": [ "x64" ], @@ -8029,9 +8029,9 @@ "peer": true }, "node_modules/cypress": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.8.0.tgz", - "integrity": "sha512-Qau//mtrwEGOU9cn2YjavECKyDUwBh8J2tit+y9s1wsv6C3BX+rlv6I9afmQnL8PmEEzJ6be7nppMHacFzZkTw==", + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.9.0.tgz", + "integrity": "sha512-atNjmYfHsvTuCaxTxLZr9xGoHz53LLui3266WWxXJHY7+N6OdwJdg/feEa3T+buez9dmUXHT1izCOklqG82uCQ==", "hasInstallScript": true, "optional": true, "dependencies": { @@ -9197,9 +9197,9 @@ } }, "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.1.tgz", + "integrity": "sha512-GPqx+FX7mdqulCeQ4TsGZQ3djBJkx5k7zBGtqt9ycVlWNg8llJ4RO9n2vciu8BN2zAEs6lPbPl0asZsAh7oWzg==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -9208,29 +9208,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "@esbuild/aix-ppc64": "0.21.1", + "@esbuild/android-arm": "0.21.1", + "@esbuild/android-arm64": "0.21.1", + "@esbuild/android-x64": "0.21.1", + "@esbuild/darwin-arm64": "0.21.1", + "@esbuild/darwin-x64": "0.21.1", + "@esbuild/freebsd-arm64": "0.21.1", + "@esbuild/freebsd-x64": "0.21.1", + "@esbuild/linux-arm": "0.21.1", + "@esbuild/linux-arm64": "0.21.1", + "@esbuild/linux-ia32": "0.21.1", + "@esbuild/linux-loong64": "0.21.1", + "@esbuild/linux-mips64el": "0.21.1", + "@esbuild/linux-ppc64": "0.21.1", + "@esbuild/linux-riscv64": "0.21.1", + "@esbuild/linux-s390x": "0.21.1", + "@esbuild/linux-x64": "0.21.1", + "@esbuild/netbsd-x64": "0.21.1", + "@esbuild/openbsd-x64": "0.21.1", + "@esbuild/sunos-x64": "0.21.1", + "@esbuild/win32-arm64": "0.21.1", + "@esbuild/win32-ia32": "0.21.1", + "@esbuild/win32-x64": "0.21.1" } }, "node_modules/esbuild-wasm": { @@ -20563,141 +20563,141 @@ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==" }, "@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.1.tgz", + "integrity": "sha512-O7yppwipkXvnEPjzkSXJRk2g4bS8sUx9p9oXHq9MU/U7lxUzZVsnFZMDTmeeX9bfQxrFcvOacl/ENgOh0WP9pA==", "optional": true }, "@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.1.tgz", + "integrity": "sha512-hh3jKWikdnTtHCglDAeVO3Oyh8MaH8xZUaWMiCCvJ9/c3NtPqZq+CACOlGTxhddypXhl+8B45SeceYBfB/e8Ow==", "optional": true }, "@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.1.tgz", + "integrity": "sha512-jXhccq6es+onw7x8MxoFnm820mz7sGa9J14kLADclmiEUH4fyj+FjR6t0M93RgtlI/awHWhtF0Wgfhqgf9gDZA==", "optional": true }, "@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.1.tgz", + "integrity": "sha512-NPObtlBh4jQHE01gJeucqEhdoD/4ya2owSIS8lZYS58aR0x7oZo9lB2lVFxgTANSa5MGCBeoQtr+yA9oKCGPvA==", "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.1.tgz", + "integrity": "sha512-BLT7TDzqsVlQRmJfO/FirzKlzmDpBWwmCUlyggfzUwg1cAxVxeA4O6b1XkMInlxISdfPAOunV9zXjvh5x99Heg==", "optional": true }, "@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.1.tgz", + "integrity": "sha512-D3h3wBQmeS/vp93O4B+SWsXB8HvRDwMyhTNhBd8yMbh5wN/2pPWRW5o/hM3EKgk9bdKd9594lMGoTCTiglQGRQ==", "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.1.tgz", + "integrity": "sha512-/uVdqqpNKXIxT6TyS/oSK4XE4xWOqp6fh4B5tgAwozkyWdylcX+W4YF2v6SKsL4wCQ5h1bnaSNjWPXG/2hp8AQ==", "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.1.tgz", + "integrity": "sha512-paAkKN1n1jJitw+dAoR27TdCzxRl1FOEITx3h201R6NoXUojpMzgMLdkXVgCvaCSCqwYkeGLoe9UVNRDKSvQgw==", "optional": true }, "@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.1.tgz", + "integrity": "sha512-tRHnxWJnvNnDpNVnsyDhr1DIQZUfCXlHSCDohbXFqmg9W4kKR7g8LmA3kzcwbuxbRMKeit8ladnCabU5f2traA==", "optional": true }, "@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.1.tgz", + "integrity": "sha512-G65d08YoH00TL7Xg4LaL3gLV21bpoAhQ+r31NUu013YB7KK0fyXIt05VbsJtpqh/6wWxoLJZOvQHYnodRrnbUQ==", "optional": true }, "@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.1.tgz", + "integrity": "sha512-tt/54LqNNAqCz++QhxoqB9+XqdsaZOtFD/srEhHYwBd3ZUOepmR1Eeot8bS+Q7BiEvy9vvKbtpHf+r6q8hF5UA==", "optional": true }, "@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.1.tgz", + "integrity": "sha512-MhNalK6r0nZD0q8VzUBPwheHzXPr9wronqmZrewLfP7ui9Fv1tdPmg6e7A8lmg0ziQCziSDHxh3cyRt4YMhGnQ==", "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.1.tgz", + "integrity": "sha512-YCKVY7Zen5rwZV+nZczOhFmHaeIxR4Zn3jcmNH53LbgF6IKRwmrMywqDrg4SiSNApEefkAbPSIzN39FC8VsxPg==", "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.1.tgz", + "integrity": "sha512-bw7bcQ+270IOzDV4mcsKAnDtAFqKO0jVv3IgRSd8iM0ac3L8amvCrujRVt1ajBTJcpDaFhIX+lCNRKteoDSLig==", "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.1.tgz", + "integrity": "sha512-ARmDRNkcOGOm1AqUBSwRVDfDeD9hGYRfkudP2QdoonBz1ucWVnfBPfy7H4JPI14eYtZruRSczJxyu7SRYDVOcg==", "optional": true }, "@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.1.tgz", + "integrity": "sha512-o73TcUNMuoTZlhwFdsgr8SfQtmMV58sbgq6gQq9G1xUiYnHMTmJbwq65RzMx89l0iya69lR4bxBgtWiiOyDQZA==", "optional": true }, "@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.1.tgz", + "integrity": "sha512-da4/1mBJwwgJkbj4fMH7SOXq2zapgTo0LKXX1VUZ0Dxr+e8N0WbS80nSZ5+zf3lvpf8qxrkZdqkOqFfm57gXwA==", "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.1.tgz", + "integrity": "sha512-CPWs0HTFe5woTJN5eKPvgraUoRHrCtzlYIAv9wBC+FAyagBSaf+UdZrjwYyTGnwPGkThV4OCI7XibZOnPvONVw==", "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.1.tgz", + "integrity": "sha512-xxhTm5QtzNLc24R0hEkcH+zCx/o49AsdFZ0Cy5zSd/5tOj4X2g3/2AJB625NoadUuc4A8B3TenLJoYdWYOYCew==", "optional": true }, "@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.1.tgz", + "integrity": "sha512-CWibXszpWys1pYmbr9UiKAkX6x+Sxw8HWtw1dRESK1dLW5fFJ6rMDVw0o8MbadusvVQx1a8xuOxnHXT941Hp1A==", "optional": true }, "@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.1.tgz", + "integrity": "sha512-jb5B4k+xkytGbGUS4T+Z89cQJ9DJ4lozGRSV+hhfmCPpfJ3880O31Q1srPCimm+V6UCbnigqD10EgDNgjvjerQ==", "optional": true }, "@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.1.tgz", + "integrity": "sha512-PgyFvjJhXqHn1uxPhyN1wZ6dIomKjiLUQh1LjFvjiV1JmnkZ/oMPrfeEAZg5R/1ftz4LZWZr02kefNIQ5SKREQ==", "optional": true }, "@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.1.tgz", + "integrity": "sha512-W9NttRZQR5ehAiqHGDnvfDaGmQOm6Fi4vSlce8mjM75x//XKuVAByohlEX6N17yZnVXxQFuh4fDRunP8ca6bfA==", "optional": true }, "@eslint-community/eslint-utils": { @@ -24112,9 +24112,9 @@ "peer": true }, "cypress": { - "version": "13.8.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.8.0.tgz", - "integrity": "sha512-Qau//mtrwEGOU9cn2YjavECKyDUwBh8J2tit+y9s1wsv6C3BX+rlv6I9afmQnL8PmEEzJ6be7nppMHacFzZkTw==", + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.9.0.tgz", + "integrity": "sha512-atNjmYfHsvTuCaxTxLZr9xGoHz53LLui3266WWxXJHY7+N6OdwJdg/feEa3T+buez9dmUXHT1izCOklqG82uCQ==", "optional": true, "requires": { "@cypress/request": "^3.0.0", @@ -25032,33 +25032,33 @@ } }, "esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.1.tgz", + "integrity": "sha512-GPqx+FX7mdqulCeQ4TsGZQ3djBJkx5k7zBGtqt9ycVlWNg8llJ4RO9n2vciu8BN2zAEs6lPbPl0asZsAh7oWzg==", "requires": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" + "@esbuild/aix-ppc64": "0.21.1", + "@esbuild/android-arm": "0.21.1", + "@esbuild/android-arm64": "0.21.1", + "@esbuild/android-x64": "0.21.1", + "@esbuild/darwin-arm64": "0.21.1", + "@esbuild/darwin-x64": "0.21.1", + "@esbuild/freebsd-arm64": "0.21.1", + "@esbuild/freebsd-x64": "0.21.1", + "@esbuild/linux-arm": "0.21.1", + "@esbuild/linux-arm64": "0.21.1", + "@esbuild/linux-ia32": "0.21.1", + "@esbuild/linux-loong64": "0.21.1", + "@esbuild/linux-mips64el": "0.21.1", + "@esbuild/linux-ppc64": "0.21.1", + "@esbuild/linux-riscv64": "0.21.1", + "@esbuild/linux-s390x": "0.21.1", + "@esbuild/linux-x64": "0.21.1", + "@esbuild/netbsd-x64": "0.21.1", + "@esbuild/openbsd-x64": "0.21.1", + "@esbuild/sunos-x64": "0.21.1", + "@esbuild/win32-arm64": "0.21.1", + "@esbuild/win32-ia32": "0.21.1", + "@esbuild/win32-x64": "0.21.1" } }, "esbuild-wasm": { diff --git a/frontend/package.json b/frontend/package.json index adc33cb00..49e2be379 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -92,7 +92,7 @@ "ngx-infinite-scroll": "^17.0.0", "qrcode": "1.5.1", "rxjs": "~7.8.1", - "esbuild": "^0.20.2", + "esbuild": "^0.21.1", "tinyify": "^4.0.0", "tlite": "^0.1.9", "tslib": "~2.6.0", @@ -115,7 +115,7 @@ "optionalDependencies": { "@cypress/schematic": "^2.5.0", "@types/cypress": "^1.1.3", - "cypress": "^13.8.0", + "cypress": "^13.9.0", "cypress-fail-on-console-error": "~5.1.0", "cypress-wait-until": "^2.0.1", "mock-socket": "~9.3.1", diff --git a/frontend/src/app/app-routing.module.ts b/frontend/src/app/app-routing.module.ts index 5262a431a..4fd1d2013 100644 --- a/frontend/src/app/app-routing.module.ts +++ b/frontend/src/app/app-routing.module.ts @@ -168,6 +168,10 @@ let routes: Routes = [ path: 'testnet', loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) }, + { + path: 'testnet4', + loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) + }, { path: 'signet', loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) diff --git a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.scss b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.scss index 96273dead..984bc2b4c 100644 --- a/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.scss +++ b/frontend/src/app/components/acceleration/acceleration-fees-graph/acceleration-fees-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; 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 563e189cf..e6763f60a 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 @@ -60,7 +60,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts index 282927b4a..5f9017bbd 100644 --- a/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts +++ b/frontend/src/app/components/acceleration/accelerator-dashboard/accelerator-dashboard.component.ts @@ -148,7 +148,7 @@ export class AcceleratorDashboardComponent implements OnInit, OnDestroy { } else { const rate = tx.fee / tx.vsize; // color by simple single-tx fee rate const feeLevelIndex = feeLevels.findIndex((feeLvl) => Math.max(1, rate) < feeLvl) - 1; - return this.theme.theme === 'contrast' ? contrastColors[feeLevelIndex] || contrastColors[contrastColors.length - 1] : normalColors[feeLevelIndex] || normalColors[normalColors.length - 1]; + return this.theme.theme === 'contrast' || this.theme.theme === 'bukele' ? contrastColors[feeLevelIndex] || contrastColors[contrastColors.length - 1] : normalColors[feeLevelIndex] || normalColors[normalColors.length - 1]; } } diff --git a/frontend/src/app/components/address-graph/address-graph.component.scss b/frontend/src/app/components/address-graph/address-graph.component.scss index 3752203c1..62393644b 100644 --- a/frontend/src/app/components/address-graph/address-graph.component.scss +++ b/frontend/src/app/components/address-graph/address-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/address-graph/address-graph.component.ts b/frontend/src/app/components/address-graph/address-graph.component.ts index a5db9602d..842e96cdd 100644 --- a/frontend/src/app/components/address-graph/address-graph.component.ts +++ b/frontend/src/app/components/address-graph/address-graph.component.ts @@ -73,7 +73,7 @@ export class AddressGraphComponent implements OnChanges, OnDestroy { if (!this.address || !this.stats) { return; } - if (changes.address || changes.isPubkey || changes.addressSummary$) { + if (changes.address || changes.isPubkey || changes.addressSummary$ || changes.stats) { if (this.subscription) { this.subscription.unsubscribe(); } @@ -248,7 +248,9 @@ export class AddressGraphComponent implements OnChanges, OnDestroy { } ngOnDestroy(): void { - this.subscription.unsubscribe(); + if (this.subscription) { + this.subscription.unsubscribe(); + } } isMobile() { diff --git a/frontend/src/app/components/address/address-preview.component.scss b/frontend/src/app/components/address/address-preview.component.scss index 623d72db2..f03e13541 100644 --- a/frontend/src/app/components/address/address-preview.component.scss +++ b/frontend/src/app/components/address/address-preview.component.scss @@ -3,7 +3,7 @@ } .qr-wrapper { - background-color: var(--fg); + background-color: #fff; padding: 10px; padding-bottom: 5px; display: inline-block; diff --git a/frontend/src/app/components/address/address.component.scss b/frontend/src/app/components/address/address.component.scss index 78ca0e80d..da615376c 100644 --- a/frontend/src/app/components/address/address.component.scss +++ b/frontend/src/app/components/address/address.component.scss @@ -1,5 +1,5 @@ .qr-wrapper { - background-color: var(--fg); + background-color: #fff; padding: 10px; padding-bottom: 5px; display: inline-block; diff --git a/frontend/src/app/components/asset/asset.component.scss b/frontend/src/app/components/asset/asset.component.scss index 6f8bc0915..56b1d6258 100644 --- a/frontend/src/app/components/asset/asset.component.scss +++ b/frontend/src/app/components/asset/asset.component.scss @@ -1,5 +1,5 @@ .qr-wrapper { - background-color: var(--fg); + background-color: #fff; padding: 10px; padding-bottom: 5px; display: inline-block; diff --git a/frontend/src/app/components/balance-widget/balance-widget.component.ts b/frontend/src/app/components/balance-widget/balance-widget.component.ts index c48cbc869..8e1d3f442 100644 --- a/frontend/src/app/components/balance-widget/balance-widget.component.ts +++ b/frontend/src/app/components/balance-widget/balance-widget.component.ts @@ -57,8 +57,9 @@ export class BalanceWidgetComponent implements OnInit, OnChanges { calculateStats(summary: AddressTxSummary[]): void { let weekTotal = 0; let monthTotal = 0; - const weekAgo = (Date.now() / 1000) - (60 * 60 * 24 * 7); - const monthAgo = (Date.now() / 1000) - (60 * 60 * 24 * 30); + + const weekAgo = (new Date(new Date().setHours(0, 0, 0, 0) - (7 * 24 * 60 * 60 * 1000)).getTime()) / 1000; + const monthAgo = (new Date(new Date().setHours(0, 0, 0, 0) - (30 * 24 * 60 * 60 * 1000)).getTime()) / 1000; for (let i = 0; i < summary.length && summary[i].time >= monthAgo; i++) { monthTotal += summary[i].value; if (summary[i].time >= weekAgo) { diff --git a/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.scss b/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.scss index ed531e63d..5d8c286d3 100644 --- a/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.scss +++ b/frontend/src/app/components/block-fee-rates-graph/block-fee-rates-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/block-fees-graph/block-fees-graph.component.scss b/frontend/src/app/components/block-fees-graph/block-fees-graph.component.scss index b73d55685..ec3aeadc8 100644 --- a/frontend/src/app/components/block-fees-graph/block-fees-graph.component.scss +++ b/frontend/src/app/components/block-fees-graph/block-fees-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/block-health-graph/block-health-graph.component.scss b/frontend/src/app/components/block-health-graph/block-health-graph.component.scss index 7b8154bae..992906e5c 100644 --- a/frontend/src/app/components/block-health-graph/block-health-graph.component.scss +++ b/frontend/src/app/components/block-health-graph/block-health-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; 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 ceb12738d..6231ba70d 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 @@ -651,13 +651,13 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy, On getFilterColorFunction(flags: bigint, gradient: 'fee' | 'age'): ((tx: TxView) => Color) { return (tx: TxView) => { if ((this.filterMode === 'and' && (tx.bigintFlags & flags) === flags) || (this.filterMode === 'or' && (flags === 0n || (tx.bigintFlags & flags) > 0n))) { - if (this.themeService.theme !== 'contrast') { + if (this.themeService.theme !== 'contrast' && this.themeService.theme !== 'bukele') { return (gradient === 'age') ? ageColorFunction(tx, defaultColors.fee, defaultAuditColors, this.relativeTime || (Date.now() / 1000)) : defaultColorFunction(tx, defaultColors.fee, defaultAuditColors, this.relativeTime || (Date.now() / 1000)); } else { return (gradient === 'age') ? ageColorFunction(tx, contrastColors.fee, contrastAuditColors, this.relativeTime || (Date.now() / 1000)) : contrastColorFunction(tx, contrastColors.fee, contrastAuditColors, this.relativeTime || (Date.now() / 1000)); } } else { - if (this.themeService.theme !== 'contrast') { + if (this.themeService.theme !== 'contrast' && this.themeService.theme !== 'bukele') { return (gradient === 'age') ? { r: 1, g: 1, b: 1, a: 0.05 } : defaultColorFunction( tx, defaultColors.unmatchedfee, diff --git a/frontend/src/app/components/block-overview-graph/block-scene.ts b/frontend/src/app/components/block-overview-graph/block-scene.ts index 9dd76dec9..c59fcb7d4 100644 --- a/frontend/src/app/components/block-overview-graph/block-scene.ts +++ b/frontend/src/app/components/block-overview-graph/block-scene.ts @@ -69,7 +69,7 @@ export default class BlockScene { } setColorFunction(colorFunction: ((tx: TxView) => Color) | null): void { - this.theme.theme === 'contrast' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction; + this.theme.theme === 'contrast' || this.theme.theme === 'bukele' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction; this.updateAllColors(); } @@ -246,7 +246,7 @@ export default class BlockScene { this.flip = flip; this.vertexArray = vertexArray; this.highlightingEnabled = highlighting; - theme.theme === 'contrast' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction; + theme.theme === 'contrast' || theme.theme === 'bukele' ? this.getColor = colorFunction || contrastColorFunction : this.getColor = colorFunction || defaultColorFunction; this.theme = theme; this.scene = { diff --git a/frontend/src/app/components/block-overview-graph/utils.ts b/frontend/src/app/components/block-overview-graph/utils.ts index ec6181853..9a6d9da43 100644 --- a/frontend/src/app/components/block-overview-graph/utils.ts +++ b/frontend/src/app/components/block-overview-graph/utils.ts @@ -177,7 +177,7 @@ export function ageColorFunction( return auditColors.accelerated; } - const color = theme !== 'contrast' ? defaultColorFunction(tx, colors, auditColors, relativeTime) : contrastColorFunction(tx, colors, auditColors, relativeTime); + const color = theme !== 'contrast' && theme !== 'bukele' ? defaultColorFunction(tx, colors, auditColors, relativeTime) : contrastColorFunction(tx, colors, auditColors, relativeTime); const ageLevel = (!tx.time ? 0 : (0.8 * Math.tanh((1 / 15) * Math.log2((Math.max(1, 0.6 * ((relativeTime - tx.time) - 60))))))); return { diff --git a/frontend/src/app/components/block-overview-tooltip/block-overview-tooltip.component.scss b/frontend/src/app/components/block-overview-tooltip/block-overview-tooltip.component.scss index 507d4c18d..28708506b 100644 --- a/frontend/src/app/components/block-overview-tooltip/block-overview-tooltip.component.scss +++ b/frontend/src/app/components/block-overview-tooltip/block-overview-tooltip.component.scss @@ -1,6 +1,6 @@ .block-overview-tooltip { position: absolute; - background: rgba(#11131f, 0.95); + background: color-mix(in srgb, var(--active-bg) 95%, transparent); border-radius: 4px; box-shadow: 1px 1px 10px rgba(0,0,0,0.5); color: var(--tooltip-grey); @@ -30,7 +30,7 @@ th, td { } .badge.badge-accelerated { - background-color: var(--tertiary); + background-color: #653b9c; box-shadow: #ad7de57f 0px 0px 12px -2px; color: white; animation: acceleratePulse 1s infinite; @@ -71,7 +71,7 @@ th, td { } @keyframes acceleratePulse { - 0% { background-color: var(--tertiary); box-shadow: #ad7de57f 0px 0px 12px -2px; } + 0% { background-color: #653b9c; box-shadow: #ad7de57f 0px 0px 12px -2px; } 50% { background-color: #8457bb; box-shadow: #ad7de5 0px 0px 18px -2px;} - 100% { background-color: var(--tertiary); box-shadow: #ad7de57f 0px 0px 12px -2px; } + 100% { background-color: #653b9c; box-shadow: #ad7de57f 0px 0px 12px -2px; } } \ No newline at end of file diff --git a/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.scss b/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.scss index 7b8154bae..992906e5c 100644 --- a/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.scss +++ b/frontend/src/app/components/block-rewards-graph/block-rewards-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.scss b/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.scss index 7b8154bae..992906e5c 100644 --- a/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.scss +++ b/frontend/src/app/components/block-sizes-weights-graph/block-sizes-weights-graph.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss index 269fdab42..b11a35513 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.scss @@ -63,7 +63,7 @@ .fee-span { font-size: 11px; margin-bottom: 5px; - color: #fff000; + color: var(--yellow); } .transaction-count { @@ -130,7 +130,7 @@ height: 0; border-left: calc(var(--block-size) * 0.3) solid transparent; border-right: calc(var(--block-size) * 0.3) solid transparent; - border-bottom: calc(var(--block-size) * 0.3) solid #FFF; + border-bottom: calc(var(--block-size) * 0.3) solid var(--fg); } .flashing { diff --git a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts index 1d0e284f8..1a7598079 100644 --- a/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts +++ b/frontend/src/app/components/blockchain-blocks/blockchain-blocks.component.ts @@ -350,7 +350,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy { return { left: addLeft + this.blockOffset * index + 'px', background: `repeating-linear-gradient( - #2d3348, + var(--secondary), var(--secondary) ${greenBackgroundHeight}%, ${this.gradientColors[this.network][0]} ${Math.max(greenBackgroundHeight, 0)}%, ${this.gradientColors[this.network][1]} 100% @@ -362,7 +362,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy { convertStyleForLoadingBlock(style) { return { ...style, - background: "#2d3348", + background: "var(--secondary)", }; } @@ -371,7 +371,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy { return { left: addLeft + (this.blockOffset * index) + 'px', - background: "#2d3348", + background: "var(--secondary)", }; } diff --git a/frontend/src/app/components/blockchain/blockchain.component.scss b/frontend/src/app/components/blockchain/blockchain.component.scss index b0a589a04..700f57a27 100644 --- a/frontend/src/app/components/blockchain/blockchain.component.scss +++ b/frontend/src/app/components/blockchain/blockchain.component.scss @@ -54,7 +54,7 @@ } .time-toggle { - color: white; + color: var(--fg); font-size: 0.8rem; position: absolute; bottom: -1.8em; @@ -68,7 +68,7 @@ } .block-display-toggle { - color: white; + color: var(--fg); font-size: 0.8rem; position: absolute; bottom: 15.8em; diff --git a/frontend/src/app/components/clock/clock.component.ts b/frontend/src/app/components/clock/clock.component.ts index 90f24a753..4a9b19e78 100644 --- a/frontend/src/app/components/clock/clock.component.ts +++ b/frontend/src/app/components/clock/clock.component.ts @@ -32,12 +32,12 @@ export class ClockComponent implements OnInit { limitHeight: number; gradientColors = { - '': ['#9339f4', '#105fb0'], - liquid: ['#116761', '#183550'], - 'liquidtestnet': ['#494a4a', '#272e46'], - testnet: ['#1d486f', '#183550'], - testnet4: ['#1d486f', '#183550'], - signet: ['#6f1d5d', '#471850'], + '': ['var(--mainnet-alt)', 'var(--primary)'], + liquid: ['var(--liquid)', 'var(--testnet-alt)'], + 'liquidtestnet': ['var(--liquidtestnet)', 'var(--liquidtestnet-alt)'], + testnet: ['var(--testnet)', 'var(--testnet-alt)'], + testnet4: ['var(--testnet)', 'var(--testnet-alt)'], + signet: ['var(--signet)', 'var(--signet-alt)'], }; constructor( @@ -100,8 +100,8 @@ export class ClockComponent implements OnInit { return { background: `repeating-linear-gradient( - #2d3348, - #2d3348 ${greenBackgroundHeight}%, + var(--secondary), + var(--secondary) ${greenBackgroundHeight}%, ${this.gradientColors[''][0]} ${Math.max(greenBackgroundHeight, 0)}%, ${this.gradientColors[''][1]} 100% )`, diff --git a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html index 9180571a0..6e2db2165 100644 --- a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html +++ b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.html @@ -4,7 +4,7 @@ @for (widget of widgets; track widget.component) { @switch (widget.component) { @case ('fees') { -
+
Transaction Fees
@@ -14,12 +14,12 @@
} @case ('difficulty') { -
+
} @case ('goggles') { -
+
} @case ('incoming') { -
+
@@ -93,7 +93,7 @@ } @case ('replacements') { -
+
@@ -140,7 +140,7 @@ } @case ('blocks') { -
+
@@ -184,7 +184,7 @@ } @case ('transactions') { -
+
Recent Transactions
@@ -224,13 +224,13 @@ } @case ('balance') { -
+
Treasury
} @case ('address') { -
+ } @case ('addressTransactions') { -
+ diff --git a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.ts b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.ts index 2847b6586..fbaf7be74 100644 --- a/frontend/src/app/components/custom-dashboard/custom-dashboard.component.ts +++ b/frontend/src/app/components/custom-dashboard/custom-dashboard.component.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, ChangeDetectionStrategy, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, HostListener, Inject, OnDestroy, OnInit, PLATFORM_ID } from '@angular/core'; import { combineLatest, merge, Observable, of, Subject, Subscription } from 'rxjs'; import { catchError, filter, map, scan, share, shareReplay, startWith, switchMap, tap } from 'rxjs/operators'; import { BlockExtended, OptimizedMempoolStats, TransactionStripped } from '../../interfaces/node-api.interface'; @@ -57,6 +57,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni incomingGraphHeight: number = 300; graphHeight: number = 300; webGlEnabled = true; + isMobile: boolean = window.innerWidth <= 767.98; widgets; @@ -85,6 +86,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni private electrsApiService: ElectrsApiService, private websocketService: WebsocketService, private seoService: SeoService, + private cd: ChangeDetectorRef, @Inject(PLATFORM_ID) private platformId: Object, ) { this.webGlEnabled = this.stateService.isBrowser && detectWebGL(); @@ -230,8 +232,10 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni this.stateService.live2Chart$ .pipe( scan((acc, stats) => { + const now = Date.now() / 1000; + const start = now - (2 * 60 * 60); acc.unshift(stats); - acc = acc.slice(0, 120); + acc = acc.filter(p => p.added >= start); return acc; }, (mempoolStats || [])) ), @@ -283,8 +287,8 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni startAddressSubscription(): void { if (this.stateService.env.customize && this.stateService.env.customize.dashboard.widgets.some(w => w.props?.address)) { - const address = this.stateService.env.customize.dashboard.widgets.find(w => w.props?.address).props.address; - const addressString = (/^[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100}|04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}$/.test(address)) ? address.toLowerCase() : address; + let addressString = this.stateService.env.customize.dashboard.widgets.find(w => w.props?.address).props.address; + addressString = (/^[A-Z]{2,5}1[AC-HJ-NP-Z02-9]{8,100}|04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}$/.test(addressString)) ? addressString.toLowerCase() : addressString; this.addressSubscription = ( addressString.match(/04[a-fA-F0-9]{128}|(02|03)[a-fA-F0-9]{64}/) @@ -299,6 +303,7 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni ).subscribe((address: Address) => { this.websocketService.startTrackAddress(address.address); this.address = address; + this.cd.markForCheck(); }); this.addressSummary$ = ( @@ -368,5 +373,6 @@ export class CustomDashboardComponent implements OnInit, OnDestroy, AfterViewIni this.goggleResolution = 86; this.graphHeight = 310; } + this.isMobile = window.innerWidth <= 767.98; } } diff --git a/frontend/src/app/components/difficulty-mining/difficulty-mining.component.scss b/frontend/src/app/components/difficulty-mining/difficulty-mining.component.scss index 77f54f267..bd396928f 100644 --- a/frontend/src/app/components/difficulty-mining/difficulty-mining.component.scss +++ b/frontend/src/app/components/difficulty-mining/difficulty-mining.component.scss @@ -119,7 +119,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/difficulty/difficulty-tooltip.component.scss b/frontend/src/app/components/difficulty/difficulty-tooltip.component.scss index 5b4a8a02f..e4fd989af 100644 --- a/frontend/src/app/components/difficulty/difficulty-tooltip.component.scss +++ b/frontend/src/app/components/difficulty/difficulty-tooltip.component.scss @@ -1,9 +1,9 @@ .difficulty-tooltip { position: fixed; - background: rgba(#11131f, 0.95); + background: color-mix(in srgb, var(--active-bg) 95%, transparent); border-radius: 4px; box-shadow: 1px 1px 10px rgba(0,0,0,0.5); - color: #b1b1b1; + color: var(--tooltip-grey); padding: 10px 15px; text-align: left; pointer-events: none; diff --git a/frontend/src/app/components/difficulty/difficulty.component.html b/frontend/src/app/components/difficulty/difficulty.component.html index c9b3d183b..e9bf36515 100644 --- a/frontend/src/app/components/difficulty/difficulty.component.html +++ b/frontend/src/app/components/difficulty/difficulty.component.html @@ -15,8 +15,8 @@ - - + + diff --git a/frontend/src/app/components/difficulty/difficulty.component.scss b/frontend/src/app/components/difficulty/difficulty.component.scss index d10b800a8..8de7fae2c 100644 --- a/frontend/src/app/components/difficulty/difficulty.component.scss +++ b/frontend/src/app/components/difficulty/difficulty.component.scss @@ -128,7 +128,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; @@ -223,7 +224,7 @@ height: 100%; } .background { - background: linear-gradient(to right, var(--primary), #9339f4); + background: linear-gradient(to right, var(--primary), var(--mainnet-alt)); left: 0; right: 0; } diff --git a/frontend/src/app/components/fees-box/fees-box.component.scss b/frontend/src/app/components/fees-box/fees-box.component.scss index 0272936ee..c5843f58b 100644 --- a/frontend/src/app/components/fees-box/fees-box.component.scss +++ b/frontend/src/app/components/fees-box/fees-box.component.scss @@ -79,7 +79,7 @@ display: flex; flex-direction: row; transition: background-color 1s; - color: var(--color-fg); + color: #fff; &.priority { @media (767px < width < 992px), (width < 576px) { width: 100%; diff --git a/frontend/src/app/components/fees-box/fees-box.component.ts b/frontend/src/app/components/fees-box/fees-box.component.ts index e923b26e9..78fd102ca 100644 --- a/frontend/src/app/components/fees-box/fees-box.component.ts +++ b/frontend/src/app/components/fees-box/fees-box.component.ts @@ -16,8 +16,8 @@ export class FeesBoxComponent implements OnInit, OnDestroy { isLoading$: Observable; recommendedFees$: Observable; themeSubscription: Subscription; - gradient = 'linear-gradient(to right, #2e324e, #2e324e)'; - noPriority = '#2e324e'; + gradient = 'linear-gradient(to right, var(--skeleton-bg), var(--skeleton-bg))'; + noPriority = 'var(--skeleton-bg)'; fees: Recommendedfees; constructor( diff --git a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss index dc19dc9d1..b6b49eed2 100644 --- a/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss +++ b/frontend/src/app/components/hashrate-chart/hashrate-chart.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.scss b/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.scss index 64a4dcb3d..a2e3b8866 100644 --- a/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.scss +++ b/frontend/src/app/components/hashrates-chart-pools/hashrate-chart-pools.component.scss @@ -11,7 +11,8 @@ .main-title { position: relative; - color: #ffffff91; + color: var(--fg); + opacity: var(--opacity); margin-top: -13px; font-size: 10px; text-transform: uppercase; diff --git a/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts b/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts index c456053ea..a63c166d9 100644 --- a/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts +++ b/frontend/src/app/components/incoming-transactions-graph/incoming-transactions-graph.component.ts @@ -66,7 +66,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On if (!this.data) { return; } - this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference'); + this.windowPreference = (this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference')) || '2h'; const windowSize = Math.max(10, Math.floor(this.data.series[0].length / 8)); this.MA = this.calculateMA(this.data.series[0], windowSize); if (this.outlierCappingEnabled === true) { @@ -216,22 +216,19 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On type: 'line', }, formatter: (params: any) => { - const axisValueLabel: string = formatterXAxis(this.locale, this.windowPreference, params[0].axisValue); + const bestItem = params.reduce((best, item) => { + return (item.seriesName === 'data' && (!best || best.value[1] < item.value[1])) ? item : best; + }, null); + const axisValueLabel: string = formatterXAxis(this.locale, this.windowPreference, bestItem.axisValue); const colorSpan = (color: string) => ``; let itemFormatted = '
' + axisValueLabel + '
'; - params.map((item: any, index: number) => { - - //Do no include MA in tooltip legend! - if (item.seriesName !== 'MA') { - if (index < 26) { - itemFormatted += `
-
${colorSpan(item.color)}
+ if (bestItem) { + itemFormatted += `
+
${colorSpan(bestItem.color)}
-
${formatNumber(item.value[1], this.locale, '1.0-0')}vB/s
+
${formatNumber(bestItem.value[1], this.locale, '1.0-0')}vB/s
`; - } - } - }); + } return `
${itemFormatted}
`; } diff --git a/frontend/src/app/components/liquid-master-page/liquid-master-page.component.scss b/frontend/src/app/components/liquid-master-page/liquid-master-page.component.scss index b0f3ce9c6..17bc8aeb5 100644 --- a/frontend/src/app/components/liquid-master-page/liquid-master-page.component.scss +++ b/frontend/src/app/components/liquid-master-page/liquid-master-page.component.scss @@ -4,6 +4,7 @@ top: 0; width: 100%; z-index: 100; + background-color: var(--bg); } li.nav-item.active { @@ -17,7 +18,7 @@ fa-icon { .navbar { z-index: 100; min-height: 64px; - background-color: var(--bg); + background-color: var(--nav-bg); } li.nav-item { @@ -48,7 +49,7 @@ li.nav-item { } .navbar-nav { - background: var(--navbar-bg); + background: var(--nav-bg); bottom: 0; box-shadow: 0px 0px 15px 0px #000; flex-direction: row; diff --git a/frontend/src/app/components/master-page-preview/master-page-preview.component.html b/frontend/src/app/components/master-page-preview/master-page-preview.component.html index 49efce400..8f3204ec4 100644 --- a/frontend/src/app/components/master-page-preview/master-page-preview.component.html +++ b/frontend/src/app/components/master-page-preview/master-page-preview.component.html @@ -6,7 +6,7 @@ } @if (enterpriseInfo?.header_img) { - enterpriseInfo.title + enterpriseInfo.title } @else { diff --git a/frontend/src/app/components/master-page-preview/master-page-preview.component.scss b/frontend/src/app/components/master-page-preview/master-page-preview.component.scss index fb0fd5c24..bb2e5b706 100644 --- a/frontend/src/app/components/master-page-preview/master-page-preview.component.scss +++ b/frontend/src/app/components/master-page-preview/master-page-preview.component.scss @@ -5,6 +5,7 @@ max-width: 1200px; max-height: 600px; padding-top: 80px; + background: var(--nav-bg); header { position: absolute; @@ -18,7 +19,7 @@ flex-direction: row; justify-content: space-between; align-items: center; - background: var(--stat-box-bg); + background: var(--nav-bg); text-align: start; font-size: 1.8em; } diff --git a/frontend/src/app/components/master-page/master-page.component.html b/frontend/src/app/components/master-page/master-page.component.html index 18fbeac68..169dd24a3 100644 --- a/frontend/src/app/components/master-page/master-page.component.html +++ b/frontend/src/app/components/master-page/master-page.component.html @@ -17,16 +17,16 @@ - -
- -
-
-
@if (enterpriseInfo?.header_img) { - enterpriseInfo.title + enterpriseInfo.title } @else { + +
+ +
+
+
} @@ -38,24 +38,28 @@
- -
- -
-
-
- - @if (enterpriseInfo?.header_img) { - enterpriseInfo.title - } @else { - - - } -
-
Offline
-
Reconnecting...
-
-
+ @if (enterpriseInfo?.header_img) { + enterpriseInfo.title + } @else { + +
+ +
+
+
+ + @if (enterpriseInfo?.header_img) { + enterpriseInfo.title + } @else { + + + } +
+
Offline
+
Reconnecting...
+
+
+ }