Merge branch 'master' into mononaut/standalone-visualizations

This commit is contained in:
wiz 2023-11-09 19:52:32 +09:00 committed by GitHub
commit 80ecf77270
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 1085 additions and 800 deletions

View file

@ -9,7 +9,7 @@ jobs:
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')" if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
strategy: strategy:
matrix: matrix:
node: ["16", "17", "18", "20"] node: ["18", "20"]
flavor: ["dev", "prod"] flavor: ["dev", "prod"]
fail-fast: false fail-fast: false
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"
@ -67,7 +67,7 @@ jobs:
if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')" if: "!contains(github.event.pull_request.labels.*.name, 'ops') && !contains(github.head_ref, 'ops/')"
strategy: strategy:
matrix: matrix:
node: ["16", "17", "18", "20"] node: ["18", "20"]
flavor: ["dev", "prod"] flavor: ["dev", "prod"]
fail-fast: false fail-fast: false
runs-on: "ubuntu-latest" runs-on: "ubuntu-latest"

View file

@ -38,7 +38,7 @@ jobs:
- name: Setup node - name: Setup node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 18 node-version: 20
cache: "npm" cache: "npm"
cache-dependency-path: ${{ matrix.module }}/frontend/package-lock.json cache-dependency-path: ${{ matrix.module }}/frontend/package-lock.json

19
.github/workflows/get_backend_hash.yml vendored Normal file
View file

@ -0,0 +1,19 @@
name: 'Print backend hashes'
on: [workflow_dispatch]
jobs:
print-backend-sha:
runs-on: 'ubuntu-latest'
name: Print backend hashes
steps:
- name: Checkout
uses: actions/checkout@v3
with:
path: repo
- name: Run script
working-directory: repo
run: |
chmod +x ./scripts/get_backend_hash.sh
sh ./scripts/get_backend_hash.sh

View file

@ -68,17 +68,17 @@ jobs:
run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
- name: Checkout project - name: Checkout project
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Init repo for Dockerization - name: Init repo for Dockerization
run: docker/init.sh "$TAG" run: docker/init.sh "$TAG"
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v3
id: qemu id: qemu
- name: Setup Docker buildx action - name: Setup Docker buildx action
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v3
id: buildx id: buildx
- name: Available platforms - name: Available platforms
@ -98,7 +98,7 @@ jobs:
docker buildx build \ docker buildx build \
--cache-from "type=local,src=/tmp/.buildx-cache" \ --cache-from "type=local,src=/tmp/.buildx-cache" \
--cache-to "type=local,dest=/tmp/.buildx-cache" \ --cache-to "type=local,dest=/tmp/.buildx-cache" \
--platform linux/amd64,linux/arm64,linux/arm/v7 \ --platform linux/amd64,linux/arm64 \
--tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:$TAG \ --tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:$TAG \
--tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:latest \ --tag ${{ secrets.DOCKER_HUB_USER }}/${{ matrix.service }}:latest \
--output "type=registry" ./${{ matrix.service }}/ \ --output "type=registry" ./${{ matrix.service }}/ \

2
.nvmrc
View file

@ -1 +1 @@
v16.16.0 v20.8.0

View file

@ -1,47 +0,0 @@
# If you see pwd_unknown showing up check permissions
PWD ?= pwd_unknown
# DATABASE DEPLOY FOLDER CONFIG - default ./data
ifeq ($(data),)
DATA := data
export DATA
else
DATA := $(data)
export DATA
endif
.PHONY: help
help:
@echo ''
@echo ''
@echo ' Usage: make [COMMAND]'
@echo ''
@echo ' make all # build init mempool and electrs'
@echo ' make init # setup some useful configs'
@echo ' make mempool # build q dockerized mempool.space'
@echo ' make electrs # build a docker electrs image'
@echo ''
.PHONY: init
init:
@echo ''
mkdir -p $(DATA) $(DATA)/mysql $(DATA)/mysql/data
#REF: https://github.com/mempool/mempool/blob/master/docker/README.md
cat docker/docker-compose.yml > docker-compose.yml
cat backend/mempool-config.sample.json > backend/mempool-config.json
.PHONY: mempool
mempool: init
@echo ''
docker-compose up --force-recreate --always-recreate-deps
@echo ''
.PHONY: electrs
electrum:
#REF: https://hub.docker.com/r/beli/electrum
@echo ''
docker build -f docker/electrum/Dockerfile .
@echo ''
.PHONY: all
all: init
make mempool
#######################
-include Makefile

View file

@ -1 +0,0 @@
# For additional configs/scripting

View file

@ -23,6 +23,7 @@ Mempool can be conveniently installed on the following full-node distros:
- [RoninDojo](https://code.samourai.io/ronindojo/RoninDojo) - [RoninDojo](https://code.samourai.io/ronindojo/RoninDojo)
- [myNode](https://github.com/mynodebtc/mynode) - [myNode](https://github.com/mynodebtc/mynode)
- [Start9](https://github.com/Start9Labs/embassy-os) - [Start9](https://github.com/Start9Labs/embassy-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. **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.

View file

@ -68,7 +68,8 @@
"DATABASE": "mempool", "DATABASE": "mempool",
"USERNAME": "mempool", "USERNAME": "mempool",
"PASSWORD": "mempool", "PASSWORD": "mempool",
"TIMEOUT": 180000 "TIMEOUT": 180000,
"PID_DIR": ""
}, },
"SYSLOG": { "SYSLOG": {
"ENABLED": true, "ENABLED": true,

View file

@ -9,12 +9,12 @@
"version": "3.0.0-dev", "version": "3.0.0-dev",
"license": "GNU Affero General Public License v3.0", "license": "GNU Affero General Public License v3.0",
"dependencies": { "dependencies": {
"@babel/core": "^7.21.3", "@babel/core": "^7.23.2",
"@mempool/electrum-client": "1.1.9", "@mempool/electrum-client": "1.1.9",
"@types/node": "^18.15.3", "@types/node": "^18.15.3",
"axios": "~1.4.0", "axios": "~1.5.0",
"bitcoinjs-lib": "~6.1.3", "bitcoinjs-lib": "~6.1.3",
"crypto-js": "~4.1.1", "crypto-js": "~4.2.0",
"express": "~4.18.2", "express": "~4.18.2",
"maxmind": "~4.3.11", "maxmind": "~4.3.11",
"mysql2": "~3.6.0", "mysql2": "~3.6.0",
@ -26,7 +26,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/code-frame": "^7.18.6", "@babel/code-frame": "^7.18.6",
"@babel/core": "^7.21.3", "@babel/core": "^7.23.2",
"@types/compression": "^1.7.2", "@types/compression": "^1.7.2",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",
@ -65,47 +65,48 @@
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.21.4", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/highlight": "^7.18.6" "@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/compat-data": { "node_modules/@babel/compat-data": {
"version": "7.21.4", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz",
"integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/core": { "node_modules/@babel/core": {
"version": "7.21.4", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz",
"integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.21.4", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.21.4", "@babel/generator": "^7.23.0",
"@babel/helper-compilation-targets": "^7.21.4", "@babel/helper-compilation-targets": "^7.22.15",
"@babel/helper-module-transforms": "^7.21.2", "@babel/helper-module-transforms": "^7.23.0",
"@babel/helpers": "^7.21.0", "@babel/helpers": "^7.23.2",
"@babel/parser": "^7.21.4", "@babel/parser": "^7.23.0",
"@babel/template": "^7.20.7", "@babel/template": "^7.22.15",
"@babel/traverse": "^7.21.4", "@babel/traverse": "^7.23.2",
"@babel/types": "^7.21.4", "@babel/types": "^7.23.0",
"convert-source-map": "^1.7.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"gensync": "^1.0.0-beta.2", "gensync": "^1.0.0-beta.2",
"json5": "^2.2.2", "json5": "^2.2.3",
"semver": "^6.3.0" "semver": "^6.3.1"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -115,13 +116,19 @@
"url": "https://opencollective.com/babel" "url": "https://opencollective.com/babel"
} }
}, },
"node_modules/@babel/core/node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true
},
"node_modules/@babel/generator": { "node_modules/@babel/generator": {
"version": "7.21.4", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.21.4", "@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17", "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1" "jsesc": "^2.5.1"
@ -145,87 +152,84 @@
} }
}, },
"node_modules/@babel/helper-compilation-targets": { "node_modules/@babel/helper-compilation-targets": {
"version": "7.21.4", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
"integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/compat-data": "^7.21.4", "@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.21.0", "@babel/helper-validator-option": "^7.22.15",
"browserslist": "^4.21.3", "browserslist": "^4.21.9",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
"semver": "^6.3.0" "semver": "^6.3.1"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
} }
}, },
"node_modules/@babel/helper-environment-visitor": { "node_modules/@babel/helper-environment-visitor": {
"version": "7.18.9", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-function-name": { "node_modules/@babel/helper-function-name": {
"version": "7.21.0", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/template": "^7.20.7", "@babel/template": "^7.22.15",
"@babel/types": "^7.21.0" "@babel/types": "^7.23.0"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-hoist-variables": { "node_modules/@babel/helper-hoist-variables": {
"version": "7.18.6", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.18.6" "@babel/types": "^7.22.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-module-imports": { "node_modules/@babel/helper-module-imports": {
"version": "7.21.4", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
"integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.21.4" "@babel/types": "^7.22.15"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-module-transforms": { "node_modules/@babel/helper-module-transforms": {
"version": "7.21.2", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz",
"integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.18.6", "@babel/helper-module-imports": "^7.22.15",
"@babel/helper-simple-access": "^7.20.2", "@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-validator-identifier": "^7.19.1", "@babel/helper-validator-identifier": "^7.22.20"
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.21.2",
"@babel/types": "^7.21.2"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
} }
}, },
"node_modules/@babel/helper-plugin-utils": { "node_modules/@babel/helper-plugin-utils": {
@ -238,78 +242,78 @@
} }
}, },
"node_modules/@babel/helper-simple-access": { "node_modules/@babel/helper-simple-access": {
"version": "7.20.2", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
"integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.20.2" "@babel/types": "^7.22.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-split-export-declaration": { "node_modules/@babel/helper-split-export-declaration": {
"version": "7.18.6", "version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/types": "^7.18.6" "@babel/types": "^7.22.5"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.19.4", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.19.1", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-validator-option": { "node_modules/@babel/helper-validator-option": {
"version": "7.21.0", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
"integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helpers": { "node_modules/@babel/helpers": {
"version": "7.21.0", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
"integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/template": "^7.20.7", "@babel/template": "^7.22.15",
"@babel/traverse": "^7.21.0", "@babel/traverse": "^7.23.2",
"@babel/types": "^7.21.0" "@babel/types": "^7.23.0"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/highlight": { "node_modules/@babel/highlight": {
"version": "7.18.6", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.18.6", "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.0.0", "chalk": "^2.4.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
}, },
"engines": { "engines": {
@ -317,9 +321,9 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.21.4", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true, "dev": true,
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@ -506,33 +510,33 @@
} }
}, },
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.20.7", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.18.6", "@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.20.7", "@babel/parser": "^7.22.15",
"@babel/types": "^7.20.7" "@babel/types": "^7.22.15"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.21.4", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.21.4", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.21.4", "@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.21.0", "@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.21.4", "@babel/parser": "^7.23.0",
"@babel/types": "^7.21.4", "@babel/types": "^7.23.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@ -541,13 +545,13 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.21.4", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.19.4", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.19.1", "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
}, },
"engines": { "engines": {
@ -2321,9 +2325,9 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.4.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@ -2590,9 +2594,9 @@
} }
}, },
"node_modules/browserslist": { "node_modules/browserslist": {
"version": "4.21.5", "version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
"integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2602,13 +2606,17 @@
{ {
"type": "tidelift", "type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist" "url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
} }
], ],
"dependencies": { "dependencies": {
"caniuse-lite": "^1.0.30001449", "caniuse-lite": "^1.0.30001541",
"electron-to-chromium": "^1.4.284", "electron-to-chromium": "^1.4.535",
"node-releases": "^2.0.8", "node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.10" "update-browserslist-db": "^1.0.13"
}, },
"bin": { "bin": {
"browserslist": "cli.js" "browserslist": "cli.js"
@ -2700,9 +2708,9 @@
} }
}, },
"node_modules/caniuse-lite": { "node_modules/caniuse-lite": {
"version": "1.0.30001473", "version": "1.0.30001547",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001547.tgz",
"integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==", "integrity": "sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -2892,9 +2900,9 @@
} }
}, },
"node_modules/crypto-js": { "node_modules/crypto-js": {
"version": "4.1.1", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.4", "version": "4.3.4",
@ -3023,9 +3031,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
}, },
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.348", "version": "1.4.551",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.348.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.551.tgz",
"integrity": "sha512-gM7TdwuG3amns/1rlgxMbeeyNoBFPa+4Uu0c7FeROWh4qWmvSOnvcslKmWy51ggLKZ2n/F/4i2HJ+PVNxH9uCQ==", "integrity": "sha512-/Ng/W/kFv7wdEHYzxdK7Cv0BHEGSkSB3M0Ssl8Ndr1eMiYeas/+Mv4cNaDqamqWx6nd2uQZfPz6g25z25M/sdw==",
"dev": true "dev": true
}, },
"node_modules/emittery": { "node_modules/emittery": {
@ -6184,9 +6192,9 @@
"dev": true "dev": true
}, },
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.10", "version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true "dev": true
}, },
"node_modules/normalize-path": { "node_modules/normalize-path": {
@ -7399,9 +7407,9 @@
} }
}, },
"node_modules/update-browserslist-db": { "node_modules/update-browserslist-db": {
"version": "1.0.10", "version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
"dev": true, "dev": true,
"funding": [ "funding": [
{ {
@ -7411,6 +7419,10 @@
{ {
"type": "tidelift", "type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist" "url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
} }
], ],
"dependencies": { "dependencies": {
@ -7418,7 +7430,7 @@
"picocolors": "^1.0.0" "picocolors": "^1.0.0"
}, },
"bin": { "bin": {
"browserslist-lint": "cli.js" "update-browserslist-db": "cli.js"
}, },
"peerDependencies": { "peerDependencies": {
"browserslist": ">= 4.21.0" "browserslist": ">= 4.21.0"
@ -7683,50 +7695,59 @@
} }
}, },
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.21.4", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/highlight": "^7.18.6" "@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
} }
}, },
"@babel/compat-data": { "@babel/compat-data": {
"version": "7.21.4", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz",
"integrity": "sha512-/DYyDpeCfaVinT40FPGdkkb+lYSKvsVuMjDAG7jPOWWiM1ibOaB9CXJAlc4d1QpP/U2q2P9jbrSlClKSErd55g==", "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==",
"dev": true "dev": true
}, },
"@babel/core": { "@babel/core": {
"version": "7.21.4", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz",
"integrity": "sha512-qt/YV149Jman/6AfmlxJ04LMIu8bMoyl3RB91yTFrxQmgbrSvQMy7cI8Q62FHx1t8wJ8B5fu0UDoLwHAhUo1QA==", "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@ampproject/remapping": "^2.2.0", "@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.21.4", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.21.4", "@babel/generator": "^7.23.0",
"@babel/helper-compilation-targets": "^7.21.4", "@babel/helper-compilation-targets": "^7.22.15",
"@babel/helper-module-transforms": "^7.21.2", "@babel/helper-module-transforms": "^7.23.0",
"@babel/helpers": "^7.21.0", "@babel/helpers": "^7.23.2",
"@babel/parser": "^7.21.4", "@babel/parser": "^7.23.0",
"@babel/template": "^7.20.7", "@babel/template": "^7.22.15",
"@babel/traverse": "^7.21.4", "@babel/traverse": "^7.23.2",
"@babel/types": "^7.21.4", "@babel/types": "^7.23.0",
"convert-source-map": "^1.7.0", "convert-source-map": "^2.0.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"gensync": "^1.0.0-beta.2", "gensync": "^1.0.0-beta.2",
"json5": "^2.2.2", "json5": "^2.2.3",
"semver": "^6.3.0" "semver": "^6.3.1"
},
"dependencies": {
"convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true
}
} }
}, },
"@babel/generator": { "@babel/generator": {
"version": "7.21.4", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-NieM3pVIYW2SwGzKoqfPrQsf4xGs9M9AIG3ThppsSRmO+m7eQhmI6amajKMUeIO37wFfsvnvcxQFx6x6iqxDnA==", "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.21.4", "@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17", "@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1" "jsesc": "^2.5.1"
@ -7746,66 +7767,63 @@
} }
}, },
"@babel/helper-compilation-targets": { "@babel/helper-compilation-targets": {
"version": "7.21.4", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
"integrity": "sha512-Fa0tTuOXZ1iL8IeDFUWCzjZcn+sJGd9RZdH9esYVjEejGmzf+FFYQpMi/kZUk2kPy/q1H3/GPw7np8qar/stfg==", "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/compat-data": "^7.21.4", "@babel/compat-data": "^7.22.9",
"@babel/helper-validator-option": "^7.21.0", "@babel/helper-validator-option": "^7.22.15",
"browserslist": "^4.21.3", "browserslist": "^4.21.9",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
"semver": "^6.3.0" "semver": "^6.3.1"
} }
}, },
"@babel/helper-environment-visitor": { "@babel/helper-environment-visitor": {
"version": "7.18.9", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"dev": true "dev": true
}, },
"@babel/helper-function-name": { "@babel/helper-function-name": {
"version": "7.21.0", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/template": "^7.20.7", "@babel/template": "^7.22.15",
"@babel/types": "^7.21.0" "@babel/types": "^7.23.0"
} }
}, },
"@babel/helper-hoist-variables": { "@babel/helper-hoist-variables": {
"version": "7.18.6", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.18.6" "@babel/types": "^7.22.5"
} }
}, },
"@babel/helper-module-imports": { "@babel/helper-module-imports": {
"version": "7.21.4", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
"integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.21.4" "@babel/types": "^7.22.15"
} }
}, },
"@babel/helper-module-transforms": { "@babel/helper-module-transforms": {
"version": "7.21.2", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz",
"integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.18.6", "@babel/helper-module-imports": "^7.22.15",
"@babel/helper-simple-access": "^7.20.2", "@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-validator-identifier": "^7.19.1", "@babel/helper-validator-identifier": "^7.22.20"
"@babel/template": "^7.20.7",
"@babel/traverse": "^7.21.2",
"@babel/types": "^7.21.2"
} }
}, },
"@babel/helper-plugin-utils": { "@babel/helper-plugin-utils": {
@ -7815,67 +7833,67 @@
"dev": true "dev": true
}, },
"@babel/helper-simple-access": { "@babel/helper-simple-access": {
"version": "7.20.2", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
"integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.20.2" "@babel/types": "^7.22.5"
} }
}, },
"@babel/helper-split-export-declaration": { "@babel/helper-split-export-declaration": {
"version": "7.18.6", "version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/types": "^7.18.6" "@babel/types": "^7.22.5"
} }
}, },
"@babel/helper-string-parser": { "@babel/helper-string-parser": {
"version": "7.19.4", "version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
"dev": true "dev": true
}, },
"@babel/helper-validator-identifier": { "@babel/helper-validator-identifier": {
"version": "7.19.1", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true "dev": true
}, },
"@babel/helper-validator-option": { "@babel/helper-validator-option": {
"version": "7.21.0", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
"integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
"dev": true "dev": true
}, },
"@babel/helpers": { "@babel/helpers": {
"version": "7.21.0", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
"integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/template": "^7.20.7", "@babel/template": "^7.22.15",
"@babel/traverse": "^7.21.0", "@babel/traverse": "^7.23.2",
"@babel/types": "^7.21.0" "@babel/types": "^7.23.0"
} }
}, },
"@babel/highlight": { "@babel/highlight": {
"version": "7.18.6", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.18.6", "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.0.0", "chalk": "^2.4.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.21.4", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"dev": true "dev": true
}, },
"@babel/plugin-syntax-async-generators": { "@babel/plugin-syntax-async-generators": {
@ -8005,42 +8023,42 @@
} }
}, },
"@babel/template": { "@babel/template": {
"version": "7.20.7", "version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.18.6", "@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.20.7", "@babel/parser": "^7.22.15",
"@babel/types": "^7.20.7" "@babel/types": "^7.22.15"
} }
}, },
"@babel/traverse": { "@babel/traverse": {
"version": "7.21.4", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-eyKrRHKdyZxqDm+fV1iqL9UAHMoIg0nDaGqfIOd8rKH17m5snv7Gn4qgjBoFfLz9APvjFU/ICT00NVCv1Epp8Q==", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/code-frame": "^7.21.4", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.21.4", "@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.18.9", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.21.0", "@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.21.4", "@babel/parser": "^7.23.0",
"@babel/types": "^7.21.4", "@babel/types": "^7.23.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.21.4", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.4.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-rU2oY501qDxE8Pyo7i/Orqma4ziCOrby0/9mvbDUGEfvZjb279Nk9k19e2fiCxHbRRpY2ZyrgW1eq22mvmOIzA==", "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@babel/helper-string-parser": "^7.19.4", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.19.1", "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
@ -9397,9 +9415,9 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
}, },
"axios": { "axios": {
"version": "1.4.0", "version": "1.5.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
"integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
"requires": { "requires": {
"follow-redirects": "^1.15.0", "follow-redirects": "^1.15.0",
"form-data": "^4.0.0", "form-data": "^4.0.0",
@ -9615,15 +9633,15 @@
} }
}, },
"browserslist": { "browserslist": {
"version": "4.21.5", "version": "4.22.1",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz",
"integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"caniuse-lite": "^1.0.30001449", "caniuse-lite": "^1.0.30001541",
"electron-to-chromium": "^1.4.284", "electron-to-chromium": "^1.4.535",
"node-releases": "^2.0.8", "node-releases": "^2.0.13",
"update-browserslist-db": "^1.0.10" "update-browserslist-db": "^1.0.13"
} }
}, },
"bs-logger": { "bs-logger": {
@ -9694,9 +9712,9 @@
"dev": true "dev": true
}, },
"caniuse-lite": { "caniuse-lite": {
"version": "1.0.30001473", "version": "1.0.30001547",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001473.tgz", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001547.tgz",
"integrity": "sha512-ewDad7+D2vlyy+E4UJuVfiBsU69IL+8oVmTuZnH5Q6CIUbxNfI50uVpRHbUPDD6SUaN2o0Lh4DhTrvLG/Tn1yg==", "integrity": "sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA==",
"dev": true "dev": true
}, },
"chalk": { "chalk": {
@ -9832,9 +9850,9 @@
} }
}, },
"crypto-js": { "crypto-js": {
"version": "4.1.1", "version": "4.2.0",
"resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz",
"integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==" "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q=="
}, },
"debug": { "debug": {
"version": "4.3.4", "version": "4.3.4",
@ -9924,9 +9942,9 @@
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
}, },
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.348", "version": "1.4.551",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.348.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.551.tgz",
"integrity": "sha512-gM7TdwuG3amns/1rlgxMbeeyNoBFPa+4Uu0c7FeROWh4qWmvSOnvcslKmWy51ggLKZ2n/F/4i2HJ+PVNxH9uCQ==", "integrity": "sha512-/Ng/W/kFv7wdEHYzxdK7Cv0BHEGSkSB3M0Ssl8Ndr1eMiYeas/+Mv4cNaDqamqWx6nd2uQZfPz6g25z25M/sdw==",
"dev": true "dev": true
}, },
"emittery": { "emittery": {
@ -12280,9 +12298,9 @@
"dev": true "dev": true
}, },
"node-releases": { "node-releases": {
"version": "2.0.10", "version": "2.0.13",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
"integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
"dev": true "dev": true
}, },
"normalize-path": { "normalize-path": {
@ -13118,9 +13136,9 @@
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
}, },
"update-browserslist-db": { "update-browserslist-db": {
"version": "1.0.10", "version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
"dev": true, "dev": true,
"requires": { "requires": {
"escalade": "^3.1.1", "escalade": "^3.1.1",

View file

@ -38,12 +38,12 @@
"rust-build": "cd rust-gbt && npm run build-release" "rust-build": "cd rust-gbt && npm run build-release"
}, },
"dependencies": { "dependencies": {
"@babel/core": "^7.21.3", "@babel/core": "^7.23.2",
"@mempool/electrum-client": "1.1.9", "@mempool/electrum-client": "1.1.9",
"@types/node": "^18.15.3", "@types/node": "^18.15.3",
"axios": "~1.4.0", "axios": "~1.5.0",
"bitcoinjs-lib": "~6.1.3", "bitcoinjs-lib": "~6.1.3",
"crypto-js": "~4.1.1", "crypto-js": "~4.2.0",
"express": "~4.18.2", "express": "~4.18.2",
"maxmind": "~4.3.11", "maxmind": "~4.3.11",
"mysql2": "~3.6.0", "mysql2": "~3.6.0",
@ -55,7 +55,7 @@
}, },
"devDependencies": { "devDependencies": {
"@babel/code-frame": "^7.18.6", "@babel/code-frame": "^7.18.6",
"@babel/core": "^7.21.3", "@babel/core": "^7.23.2",
"@types/compression": "^1.7.2", "@types/compression": "^1.7.2",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"@types/express": "^4.17.17", "@types/express": "^4.17.17",

View file

@ -69,6 +69,7 @@
"DATABASE": "__DATABASE_DATABASE__", "DATABASE": "__DATABASE_DATABASE__",
"USERNAME": "__DATABASE_USERNAME__", "USERNAME": "__DATABASE_USERNAME__",
"PASSWORD": "__DATABASE_PASSWORD__", "PASSWORD": "__DATABASE_PASSWORD__",
"PID_DIR": "__DATABASE_PID_FILE__",
"TIMEOUT": 3000 "TIMEOUT": 3000
}, },
"SYSLOG": { "SYSLOG": {

View file

@ -84,6 +84,7 @@ describe('Mempool Backend Config', () => {
USERNAME: 'mempool', USERNAME: 'mempool',
PASSWORD: 'mempool', PASSWORD: 'mempool',
TIMEOUT: 180000, TIMEOUT: 180000,
PID_DIR: ''
}); });
expect(config.SYSLOG).toStrictEqual({ expect(config.SYSLOG).toStrictEqual({

View file

@ -478,7 +478,7 @@ class BitcoinRoutes {
} }
let nextHash = startFromHash; let nextHash = startFromHash;
for (let i = 0; i < 10 && nextHash; i++) { for (let i = 0; i < 15 && nextHash; i++) {
const localBlock = blocks.getBlocks().find((b) => b.id === nextHash); const localBlock = blocks.getBlocks().find((b) => b.id === nextHash);
if (localBlock) { if (localBlock) {
returnBlocks.push(localBlock); returnBlocks.push(localBlock);

View file

@ -7,7 +7,7 @@ import cpfpRepository from '../repositories/CpfpRepository';
import { RowDataPacket } from 'mysql2'; import { RowDataPacket } from 'mysql2';
class DatabaseMigration { class DatabaseMigration {
private static currentVersion = 65; private static currentVersion = 66;
private queryTimeout = 3600_000; private queryTimeout = 3600_000;
private statisticsAddedIndexed = false; private statisticsAddedIndexed = false;
private uniqueLogs: string[] = []; private uniqueLogs: string[] = [];
@ -553,6 +553,11 @@ class DatabaseMigration {
await this.$executeQuery('ALTER TABLE `blocks_audits` ADD accelerated_txs JSON DEFAULT "[]"'); await this.$executeQuery('ALTER TABLE `blocks_audits` ADD accelerated_txs JSON DEFAULT "[]"');
await this.updateToSchemaVersion(65); await this.updateToSchemaVersion(65);
} }
if (databaseSchemaVersion < 66) {
await this.$executeQuery('ALTER TABLE `statistics` ADD min_fee FLOAT UNSIGNED DEFAULT NULL');
await this.updateToSchemaVersion(66);
}
} }
/** /**

View file

@ -3,21 +3,30 @@ import { Common } from './common';
import mempool from './mempool'; import mempool from './mempool';
import projectedBlocks from './mempool-blocks'; import projectedBlocks from './mempool-blocks';
interface RecommendedFees {
fastestFee: number,
halfHourFee: number,
hourFee: number,
economyFee: number,
minimumFee: number,
}
class FeeApi { class FeeApi {
constructor() { } constructor() { }
defaultFee = Common.isLiquid() ? 0.1 : 1; defaultFee = Common.isLiquid() ? 0.1 : 1;
public getRecommendedFee() { public getRecommendedFee(): RecommendedFees {
const pBlocks = projectedBlocks.getMempoolBlocks(); const pBlocks = projectedBlocks.getMempoolBlocks();
const mPool = mempool.getMempoolInfo(); const mPool = mempool.getMempoolInfo();
const minimumFee = Math.ceil(mPool.mempoolminfee * 100000); const minimumFee = Math.ceil(mPool.mempoolminfee * 100000);
const defaultMinFee = Math.max(minimumFee, this.defaultFee);
if (!pBlocks.length) { if (!pBlocks.length) {
return { return {
'fastestFee': this.defaultFee, 'fastestFee': defaultMinFee,
'halfHourFee': this.defaultFee, 'halfHourFee': defaultMinFee,
'hourFee': this.defaultFee, 'hourFee': defaultMinFee,
'economyFee': minimumFee, 'economyFee': minimumFee,
'minimumFee': minimumFee, 'minimumFee': minimumFee,
}; };
@ -27,11 +36,15 @@ class FeeApi {
const secondMedianFee = pBlocks[1] ? this.optimizeMedianFee(pBlocks[1], pBlocks[2], firstMedianFee) : this.defaultFee; const secondMedianFee = pBlocks[1] ? this.optimizeMedianFee(pBlocks[1], pBlocks[2], firstMedianFee) : this.defaultFee;
const thirdMedianFee = pBlocks[2] ? this.optimizeMedianFee(pBlocks[2], pBlocks[3], secondMedianFee) : this.defaultFee; const thirdMedianFee = pBlocks[2] ? this.optimizeMedianFee(pBlocks[2], pBlocks[3], secondMedianFee) : this.defaultFee;
// explicitly enforce a minimum of ceil(mempoolminfee) on all recommendations.
// simply rounding up recommended rates is insufficient, as the purging rate
// can exceed the median rate of projected blocks in some extreme scenarios
// (see https://bitcoin.stackexchange.com/a/120024)
return { return {
'fastestFee': firstMedianFee, 'fastestFee': Math.max(minimumFee, firstMedianFee),
'halfHourFee': secondMedianFee, 'halfHourFee': Math.max(minimumFee, secondMedianFee),
'hourFee': thirdMedianFee, 'hourFee': Math.max(minimumFee, thirdMedianFee),
'economyFee': Math.min(2 * minimumFee, thirdMedianFee), 'economyFee': Math.max(minimumFee, Math.min(2 * minimumFee, thirdMedianFee)),
'minimumFee': minimumFee, 'minimumFee': minimumFee,
}; };
} }

View file

@ -31,7 +31,7 @@ class MemoryCache {
} }
private cleanup() { private cleanup() {
this.cache = this.cache.filter((cache) => cache.expires < (new Date())); this.cache = this.cache.filter((cache) => cache.expires > (new Date()));
} }
} }

View file

@ -15,6 +15,7 @@ class StatisticsApi {
mempool_byte_weight, mempool_byte_weight,
fee_data, fee_data,
total_fee, total_fee,
min_fee,
vsize_1, vsize_1,
vsize_2, vsize_2,
vsize_3, vsize_3,
@ -54,7 +55,7 @@ class StatisticsApi {
vsize_1800, vsize_1800,
vsize_2000 vsize_2000
) )
VALUES (NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, VALUES (NOW(), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)`; 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)`;
const [result]: any = await DB.query(query); const [result]: any = await DB.query(query);
return result.insertId; return result.insertId;
@ -73,6 +74,7 @@ class StatisticsApi {
mempool_byte_weight, mempool_byte_weight,
fee_data, fee_data,
total_fee, total_fee,
min_fee,
vsize_1, vsize_1,
vsize_2, vsize_2,
vsize_3, vsize_3,
@ -112,7 +114,7 @@ class StatisticsApi {
vsize_1800, vsize_1800,
vsize_2000 vsize_2000
) )
VALUES (${statistics.added}, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, VALUES (${statistics.added}, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`; ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
const params: (string | number)[] = [ const params: (string | number)[] = [
@ -122,6 +124,7 @@ class StatisticsApi {
statistics.mempool_byte_weight, statistics.mempool_byte_weight,
statistics.fee_data, statistics.fee_data,
statistics.total_fee, statistics.total_fee,
statistics.min_fee,
statistics.vsize_1, statistics.vsize_1,
statistics.vsize_2, statistics.vsize_2,
statistics.vsize_3, statistics.vsize_3,
@ -173,6 +176,7 @@ class StatisticsApi {
UNIX_TIMESTAMP(added) as added, UNIX_TIMESTAMP(added) as added,
CAST(avg(unconfirmed_transactions) as DOUBLE) as unconfirmed_transactions, CAST(avg(unconfirmed_transactions) as DOUBLE) as unconfirmed_transactions,
CAST(avg(vbytes_per_second) as DOUBLE) as vbytes_per_second, CAST(avg(vbytes_per_second) as DOUBLE) as vbytes_per_second,
CAST(avg(min_fee) as DOUBLE) as min_fee,
CAST(avg(vsize_1) as DOUBLE) as vsize_1, CAST(avg(vsize_1) as DOUBLE) as vsize_1,
CAST(avg(vsize_2) as DOUBLE) as vsize_2, CAST(avg(vsize_2) as DOUBLE) as vsize_2,
CAST(avg(vsize_3) as DOUBLE) as vsize_3, CAST(avg(vsize_3) as DOUBLE) as vsize_3,
@ -222,6 +226,7 @@ class StatisticsApi {
UNIX_TIMESTAMP(added) as added, UNIX_TIMESTAMP(added) as added,
CAST(avg(unconfirmed_transactions) as DOUBLE) as unconfirmed_transactions, CAST(avg(unconfirmed_transactions) as DOUBLE) as unconfirmed_transactions,
CAST(avg(vbytes_per_second) as DOUBLE) as vbytes_per_second, CAST(avg(vbytes_per_second) as DOUBLE) as vbytes_per_second,
CAST(avg(min_fee) as DOUBLE) as min_fee,
vsize_1, vsize_1,
vsize_2, vsize_2,
vsize_3, vsize_3,
@ -407,6 +412,7 @@ class StatisticsApi {
vbytes_per_second: s.vbytes_per_second, vbytes_per_second: s.vbytes_per_second,
mempool_byte_weight: s.mempool_byte_weight, mempool_byte_weight: s.mempool_byte_weight,
total_fee: s.total_fee, total_fee: s.total_fee,
min_fee: s.min_fee,
vsizes: [ vsizes: [
s.vsize_1, s.vsize_1,
s.vsize_2, s.vsize_2,

View file

@ -89,6 +89,9 @@ class Statistics {
} }
}); });
// get minFee and convert to sats/vb
const minFee = memPool.getMempoolInfo().mempoolminfee * 100000;
try { try {
const insertId = await statisticsApi.$create({ const insertId = await statisticsApi.$create({
added: 'NOW()', added: 'NOW()',
@ -98,6 +101,7 @@ class Statistics {
mempool_byte_weight: totalWeight, mempool_byte_weight: totalWeight,
total_fee: totalFee, total_fee: totalFee,
fee_data: '', fee_data: '',
min_fee: minFee,
vsize_1: weightVsizeFees['1'] || 0, vsize_1: weightVsizeFees['1'] || 0,
vsize_2: weightVsizeFees['2'] || 0, vsize_2: weightVsizeFees['2'] || 0,
vsize_3: weightVsizeFees['3'] || 0, vsize_3: weightVsizeFees['3'] || 0,

View file

@ -93,6 +93,7 @@ interface IConfig {
USERNAME: string; USERNAME: string;
PASSWORD: string; PASSWORD: string;
TIMEOUT: number; TIMEOUT: number;
PID_DIR: string;
}; };
SYSLOG: { SYSLOG: {
ENABLED: boolean; ENABLED: boolean;
@ -219,6 +220,7 @@ const defaults: IConfig = {
'USERNAME': 'mempool', 'USERNAME': 'mempool',
'PASSWORD': 'mempool', 'PASSWORD': 'mempool',
'TIMEOUT': 180000, 'TIMEOUT': 180000,
'PID_DIR': '',
}, },
'SYSLOG': { 'SYSLOG': {
'ENABLED': true, 'ENABLED': true,

View file

@ -1,3 +1,5 @@
import * as fs from 'fs';
import path from 'path';
import config from './config'; import config from './config';
import { createPool, Pool, PoolConnection } from 'mysql2/promise'; import { createPool, Pool, PoolConnection } from 'mysql2/promise';
import logger from './logger'; import logger from './logger';
@ -101,6 +103,33 @@ import { FieldPacket, OkPacket, PoolOptions, ResultSetHeader, RowDataPacket } fr
} }
} }
public getPidLock(): boolean {
const filePath = path.join(config.DATABASE.PID_DIR || __dirname, `/mempool-${config.DATABASE.DATABASE}.pid`);
if (fs.existsSync(filePath)) {
const pid = fs.readFileSync(filePath).toString();
if (pid !== `${process.pid}`) {
const msg = `Already running on PID ${pid} (or pid file '${filePath}' is stale)`;
logger.err(msg);
throw new Error(msg);
} else {
return true;
}
} else {
fs.writeFileSync(filePath, `${process.pid}`);
return true;
}
}
public releasePidLock(): void {
const filePath = path.join(config.DATABASE.PID_DIR || __dirname, `/mempool-${config.DATABASE.DATABASE}.pid`);
if (fs.existsSync(filePath)) {
const pid = fs.readFileSync(filePath).toString();
if (pid === `${process.pid}`) {
fs.unlinkSync(filePath);
}
}
}
private async getPool(): Promise<Pool> { private async getPool(): Promise<Pool> {
if (this.pool === null) { if (this.pool === null) {
this.pool = createPool(this.poolConfig); this.pool = createPool(this.poolConfig);

View file

@ -91,11 +91,18 @@ class Server {
async startServer(worker = false): Promise<void> { async startServer(worker = false): Promise<void> {
logger.notice(`Starting Mempool Server${worker ? ' (worker)' : ''}... (${backendInfo.getShortCommitHash()})`); logger.notice(`Starting Mempool Server${worker ? ' (worker)' : ''}... (${backendInfo.getShortCommitHash()})`);
// Register cleanup listeners for exit events
['exit', 'SIGINT', 'SIGTERM', 'SIGUSR1', 'SIGUSR2', 'uncaughtException', 'unhandledRejection'].forEach(event => {
process.on(event, () => { this.onExit(event); });
});
if (config.MEMPOOL.BACKEND === 'esplora') { if (config.MEMPOOL.BACKEND === 'esplora') {
bitcoinApi.startHealthChecks(); bitcoinApi.startHealthChecks();
} }
if (config.DATABASE.ENABLED) { if (config.DATABASE.ENABLED) {
DB.getPidLock();
await DB.checkDbConnection(); await DB.checkDbConnection();
try { try {
if (process.env.npm_config_reindex_blocks === 'true') { // Re-index requests if (process.env.npm_config_reindex_blocks === 'true') { // Re-index requests
@ -306,6 +313,15 @@ class Server {
this.lastHeapLogTime = now; this.lastHeapLogTime = now;
} }
} }
onExit(exitEvent): void {
if (config.DATABASE.ENABLED) {
DB.releasePidLock();
}
process.exit(0);
}
} }
((): Server => new Server())(); ((): Server => new Server())();

View file

@ -300,6 +300,7 @@ export interface Statistic {
total_fee: number; total_fee: number;
mempool_byte_weight: number; mempool_byte_weight: number;
fee_data: string; fee_data: string;
min_fee: number;
vsize_1: number; vsize_1: number;
vsize_2: number; vsize_2: number;
@ -346,6 +347,7 @@ export interface OptimizedStatistic {
vbytes_per_second: number; vbytes_per_second: number;
total_fee: number; total_fee: number;
mempool_byte_weight: number; mempool_byte_weight: number;
min_fee: number;
vsizes: number[]; vsizes: number[];
} }

3
contributors/TKone7.txt Normal file
View file

@ -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 October 23, 2023.
Signed: TKone7

View file

@ -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 October 23, 2023.
Signed: fanquake

3
contributors/fubz.txt Normal file
View file

@ -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 January 25, 2022.
Signed: fubz

View file

@ -1,4 +1,4 @@
FROM node:16.16.0-buster-slim AS builder FROM node:20.8.0-buster-slim AS builder
ARG commitHash ARG commitHash
ENV MEMPOOL_COMMIT_HASH=${commitHash} ENV MEMPOOL_COMMIT_HASH=${commitHash}
@ -17,7 +17,7 @@ ENV PATH="/root/.cargo/bin:$PATH"
RUN npm install --omit=dev --omit=optional RUN npm install --omit=dev --omit=optional
RUN npm run package RUN npm run package
FROM node:16.16.0-buster-slim FROM node:20.8.0-buster-slim
WORKDIR /backend WORKDIR /backend

View file

@ -69,7 +69,8 @@
"DATABASE": "__DATABASE_DATABASE__", "DATABASE": "__DATABASE_DATABASE__",
"USERNAME": "__DATABASE_USERNAME__", "USERNAME": "__DATABASE_USERNAME__",
"PASSWORD": "__DATABASE_PASSWORD__", "PASSWORD": "__DATABASE_PASSWORD__",
"TIMEOUT": __DATABASE_TIMEOUT__ "TIMEOUT": __DATABASE_TIMEOUT__,
"PID_DIR": "__DATABASE_PID_DIR__"
}, },
"SYSLOG": { "SYSLOG": {
"ENABLED": __SYSLOG_ENABLED__, "ENABLED": __SYSLOG_ENABLED__,

View file

@ -71,6 +71,7 @@ __DATABASE_DATABASE__=${DATABASE_DATABASE:=mempool}
__DATABASE_USERNAME__=${DATABASE_USERNAME:=mempool} __DATABASE_USERNAME__=${DATABASE_USERNAME:=mempool}
__DATABASE_PASSWORD__=${DATABASE_PASSWORD:=mempool} __DATABASE_PASSWORD__=${DATABASE_PASSWORD:=mempool}
__DATABASE_TIMEOUT__=${DATABASE_TIMEOUT:=180000} __DATABASE_TIMEOUT__=${DATABASE_TIMEOUT:=180000}
__DATABASE_PID_DIR__=${DATABASE_PID_DIR:=""}
# SYSLOG # SYSLOG
__SYSLOG_ENABLED__=${SYSLOG_ENABLED:=false} __SYSLOG_ENABLED__=${SYSLOG_ENABLED:=false}
@ -139,7 +140,7 @@ __MEMPOOL_SERVICES_API__=${MEMPOOL_SERVICES_API:=""}
__MEMPOOL_SERVICES_ACCELERATIONS__=${MEMPOOL_SERVICES_ACCELERATIONS:=false} __MEMPOOL_SERVICES_ACCELERATIONS__=${MEMPOOL_SERVICES_ACCELERATIONS:=false}
# REDIS # REDIS
__REDIS_ENABLED__=${REDIS_ENABLED:=true} __REDIS_ENABLED__=${REDIS_ENABLED:=false}
__REDIS_UNIX_SOCKET_PATH__=${REDIS_UNIX_SOCKET_PATH:=true} __REDIS_UNIX_SOCKET_PATH__=${REDIS_UNIX_SOCKET_PATH:=true}
mkdir -p "${__MEMPOOL_CACHE_DIR__}" mkdir -p "${__MEMPOOL_CACHE_DIR__}"
@ -209,6 +210,7 @@ sed -i "s!__DATABASE_DATABASE__!${__DATABASE_DATABASE__}!g" mempool-config.json
sed -i "s!__DATABASE_USERNAME__!${__DATABASE_USERNAME__}!g" mempool-config.json sed -i "s!__DATABASE_USERNAME__!${__DATABASE_USERNAME__}!g" mempool-config.json
sed -i "s!__DATABASE_PASSWORD__!${__DATABASE_PASSWORD__}!g" mempool-config.json sed -i "s!__DATABASE_PASSWORD__!${__DATABASE_PASSWORD__}!g" mempool-config.json
sed -i "s!__DATABASE_TIMEOUT__!${__DATABASE_TIMEOUT__}!g" mempool-config.json sed -i "s!__DATABASE_TIMEOUT__!${__DATABASE_TIMEOUT__}!g" mempool-config.json
sed -i "s!__DATABASE_PID_DIR__!${__DATABASE_PID_DIR__}!g" mempool-config.json
sed -i "s!__SYSLOG_ENABLED__!${__SYSLOG_ENABLED__}!g" mempool-config.json sed -i "s!__SYSLOG_ENABLED__!${__SYSLOG_ENABLED__}!g" mempool-config.json
sed -i "s!__SYSLOG_HOST__!${__SYSLOG_HOST__}!g" mempool-config.json sed -i "s!__SYSLOG_HOST__!${__SYSLOG_HOST__}!g" mempool-config.json

View file

@ -38,7 +38,7 @@ services:
MYSQL_USER: "mempool" MYSQL_USER: "mempool"
MYSQL_PASSWORD: "mempool" MYSQL_PASSWORD: "mempool"
MYSQL_ROOT_PASSWORD: "admin" MYSQL_ROOT_PASSWORD: "admin"
image: mariadb:10.5.8 image: mariadb:10.5.21
user: "1000:1000" user: "1000:1000"
restart: on-failure restart: on-failure
stop_grace_period: 1m stop_grace_period: 1m

View file

@ -1,32 +0,0 @@
FROM ubuntu:18.04
MAINTAINER mempool.space developers
EXPOSE 50002
# runs as UID 1000 GID 1000 inside the container
ENV VERSION 4.0.9
RUN set -x \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends gpg gpg-agent dirmngr \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends wget xpra python3-pyqt5 python3-wheel python3-pip python3-setuptools libsecp256k1-0 libsecp256k1-dev python3-numpy python3-dev build-essential \
&& wget -O /tmp/Electrum-${VERSION}.tar.gz https://download.electrum.org/${VERSION}/Electrum-${VERSION}.tar.gz \
&& wget -O /tmp/Electrum-${VERSION}.tar.gz.asc https://download.electrum.org/${VERSION}/Electrum-${VERSION}.tar.gz.asc \
&& gpg --keyserver keys.gnupg.net --recv-keys 6694D8DE7BE8EE5631BED9502BD5824B7F9470E6 \
&& gpg --verify /tmp/Electrum-${VERSION}.tar.gz.asc /tmp/Electrum-${VERSION}.tar.gz \
&& pip3 install /tmp/Electrum-${VERSION}.tar.gz \
&& test -f /usr/local/bin/electrum \
&& rm -vrf /tmp/Electrum-${VERSION}.tar.gz /tmp/Electrum-${VERSION}.tar.gz.asc ${HOME}/.gnupg \
&& apt-get purge --autoremove -y python3-wheel python3-pip python3-setuptools python3-dev build-essential libsecp256k1-dev curl gpg gpg-agent dirmngr \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& useradd -d /home/mempool -m mempool \
&& mkdir /electrum \
&& ln -s /electrum /home/mempool/.electrum \
&& chown mempool:mempool /electrum
USER mempool
ENV HOME /home/mempool
WORKDIR /home/mempool
VOLUME /electrum
CMD ["/usr/bin/xpra", "start", ":100", "--start-child=/usr/local/bin/electrum", "--bind-tcp=0.0.0.0:50002","--daemon=yes", "--notifications=no", "--mdns=no", "--pulseaudio=no", "--html=off", "--speaker=disabled", "--microphone=disabled", "--webcam=no", "--printing=no", "--dbus-launch=", "--exit-with-children"]
ENTRYPOINT ["electrum"]

View file

@ -1,4 +1,4 @@
FROM node:16.16.0-buster-slim AS builder FROM node:20.8.0-buster-slim AS builder
ARG commitHash ARG commitHash
ENV DOCKER_COMMIT_HASH=${commitHash} ENV DOCKER_COMMIT_HASH=${commitHash}
@ -13,7 +13,7 @@ RUN npm install --omit=dev --omit=optional
RUN npm run build RUN npm run build
FROM nginx:1.17.8-alpine FROM nginx:1.24.0-alpine
WORKDIR /patch WORKDIR /patch

View file

@ -39,6 +39,7 @@ __AUDIT__=${AUDIT:=false}
__MAINNET_BLOCK_AUDIT_START_HEIGHT__=${MAINNET_BLOCK_AUDIT_START_HEIGHT:=0} __MAINNET_BLOCK_AUDIT_START_HEIGHT__=${MAINNET_BLOCK_AUDIT_START_HEIGHT:=0}
__TESTNET_BLOCK_AUDIT_START_HEIGHT__=${TESTNET_BLOCK_AUDIT_START_HEIGHT:=0} __TESTNET_BLOCK_AUDIT_START_HEIGHT__=${TESTNET_BLOCK_AUDIT_START_HEIGHT:=0}
__SIGNET_BLOCK_AUDIT_START_HEIGHT__=${SIGNET_BLOCK_AUDIT_START_HEIGHT:=0} __SIGNET_BLOCK_AUDIT_START_HEIGHT__=${SIGNET_BLOCK_AUDIT_START_HEIGHT:=0}
__ACCELERATOR__=${ACCELERATOR:=false}
__HISTORICAL_PRICE__=${HISTORICAL_PRICE:=true} __HISTORICAL_PRICE__=${HISTORICAL_PRICE:=true}
# Export as environment variables to be used by envsubst # Export as environment variables to be used by envsubst
@ -65,6 +66,7 @@ export __AUDIT__
export __MAINNET_BLOCK_AUDIT_START_HEIGHT__ export __MAINNET_BLOCK_AUDIT_START_HEIGHT__
export __TESTNET_BLOCK_AUDIT_START_HEIGHT__ export __TESTNET_BLOCK_AUDIT_START_HEIGHT__
export __SIGNET_BLOCK_AUDIT_START_HEIGHT__ export __SIGNET_BLOCK_AUDIT_START_HEIGHT__
export __ACCELERATOR__
export __HISTORICAL_PRICE__ export __HISTORICAL_PRICE__
folder=$(find /var/www/mempool -name "config.js" | xargs dirname) folder=$(find /var/www/mempool -name "config.js" | xargs dirname)

View file

@ -59,9 +59,9 @@
"optionalDependencies": { "optionalDependencies": {
"@cypress/schematic": "^2.5.0", "@cypress/schematic": "^2.5.0",
"@types/cypress": "^1.1.3", "@types/cypress": "^1.1.3",
"cypress": "^12.17.2", "cypress": "^13.3.0",
"cypress-fail-on-console-error": "~4.0.3", "cypress-fail-on-console-error": "~5.0.0",
"cypress-wait-until": "^2.0.0", "cypress-wait-until": "^2.0.1",
"mock-socket": "~9.2.1", "mock-socket": "~9.2.1",
"start-server-and-test": "~2.0.0" "start-server-and-test": "~2.0.0"
} }
@ -1250,11 +1250,12 @@
"integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==" "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg=="
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
"version": "7.22.5", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"dependencies": { "dependencies": {
"@babel/highlight": "^7.22.5" "@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -1464,20 +1465,33 @@
} }
}, },
"node_modules/@babel/helper-environment-visitor": { "node_modules/@babel/helper-environment-visitor": {
"version": "7.22.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-function-name": { "node_modules/@babel/helper-function-name": {
"version": "7.22.5", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"dependencies": { "dependencies": {
"@babel/template": "^7.22.5", "@babel/template": "^7.22.15",
"@babel/types": "^7.22.5" "@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-function-name/node_modules/@babel/template": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"dependencies": {
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@ -1627,9 +1641,9 @@
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.22.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@ -1669,12 +1683,12 @@
} }
}, },
"node_modules/@babel/highlight": { "node_modules/@babel/highlight": {
"version": "7.22.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.0.0", "chalk": "^2.4.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
}, },
"engines": { "engines": {
@ -1682,9 +1696,9 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.22.7", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
}, },
@ -2879,18 +2893,18 @@
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.22.8", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.22.5", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.22.7", "@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.22.5", "@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.22.7", "@babel/parser": "^7.23.0",
"@babel/types": "^7.22.5", "@babel/types": "^7.23.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@ -2898,13 +2912,36 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/traverse/node_modules/@babel/generator": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"dependencies": {
"@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.20",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.22.10", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.22.5", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
}, },
"engines": { "engines": {
@ -3016,9 +3053,9 @@
} }
}, },
"node_modules/@cypress/request": { "node_modules/@cypress/request": {
"version": "2.88.11", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz",
"integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"aws-sign2": "~0.7.0", "aws-sign2": "~0.7.0",
@ -3034,9 +3071,9 @@
"json-stringify-safe": "~5.0.1", "json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19", "mime-types": "~2.1.19",
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"qs": "~6.10.3", "qs": "6.10.4",
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0", "tough-cookie": "^4.1.3",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0",
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },
@ -4333,9 +4370,9 @@
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "18.11.9", "version": "18.17.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.18.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" "integrity": "sha512-/4QOuy3ZpV7Ya1GTRz5CYSz3DgkKpyUptXuQ5PPce7uuyJAOR7r9FhkmxJfvcNUXyklbC63a+YvB3jxy7s9ngw=="
}, },
"node_modules/@types/qrcode": { "node_modules/@types/qrcode": {
"version": "1.5.0", "version": "1.5.0",
@ -5574,9 +5611,9 @@
"optional": true "optional": true
}, },
"node_modules/bn.js": { "node_modules/bn.js": {
"version": "5.2.0", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
}, },
"node_modules/body-parser": { "node_modules/body-parser": {
"version": "1.20.1", "version": "1.20.1",
@ -5871,25 +5908,28 @@
} }
}, },
"node_modules/browserify-sign": { "node_modules/browserify-sign": {
"version": "4.2.1", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz",
"integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==",
"dependencies": { "dependencies": {
"bn.js": "^5.1.1", "bn.js": "^5.2.1",
"browserify-rsa": "^4.0.1", "browserify-rsa": "^4.1.0",
"create-hash": "^1.2.0", "create-hash": "^1.2.0",
"create-hmac": "^1.1.7", "create-hmac": "^1.1.7",
"elliptic": "^6.5.3", "elliptic": "^6.5.4",
"inherits": "^2.0.4", "inherits": "^2.0.4",
"parse-asn1": "^5.1.5", "parse-asn1": "^5.1.6",
"readable-stream": "^3.6.0", "readable-stream": "^3.6.2",
"safe-buffer": "^5.2.0" "safe-buffer": "^5.2.1"
},
"engines": {
"node": ">= 4"
} }
}, },
"node_modules/browserify-sign/node_modules/readable-stream": { "node_modules/browserify-sign/node_modules/readable-stream": {
"version": "3.6.0", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": { "dependencies": {
"inherits": "^2.0.3", "inherits": "^2.0.3",
"string_decoder": "^1.1.1", "string_decoder": "^1.1.1",
@ -7113,15 +7153,15 @@
"peer": true "peer": true
}, },
"node_modules/cypress": { "node_modules/cypress": {
"version": "12.17.2", "version": "13.3.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.2.tgz", "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.3.0.tgz",
"integrity": "sha512-hxWAaWbqQBzzMuadSGSuQg5PDvIGOovm6xm0hIfpCVcORsCAj/gF2p0EvfnJ4f+jK2PCiDgP6D2eeE9/FK4Mjg==", "integrity": "sha512-mpI8qcTwLGiA4zEQvTC/U1xGUezVV4V8HQCOYjlEOrVmU1etVvxOjkCXHGwrlYdZU/EPmUiWfsO3yt1o+Q2bgw==",
"hasInstallScript": true, "hasInstallScript": true,
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"@cypress/request": "^2.88.11", "@cypress/request": "^3.0.0",
"@cypress/xvfb": "^1.2.4", "@cypress/xvfb": "^1.2.4",
"@types/node": "^14.14.31", "@types/node": "^18.17.5",
"@types/sinonjs__fake-timers": "8.1.1", "@types/sinonjs__fake-timers": "8.1.1",
"@types/sizzle": "^2.3.2", "@types/sizzle": "^2.3.2",
"arch": "^2.2.0", "arch": "^2.2.0",
@ -7154,6 +7194,7 @@
"minimist": "^1.2.8", "minimist": "^1.2.8",
"ospath": "^1.2.2", "ospath": "^1.2.2",
"pretty-bytes": "^5.6.0", "pretty-bytes": "^5.6.0",
"process": "^0.11.10",
"proxy-from-env": "1.0.0", "proxy-from-env": "1.0.0",
"request-progress": "^3.0.0", "request-progress": "^3.0.0",
"semver": "^7.5.3", "semver": "^7.5.3",
@ -7166,13 +7207,13 @@
"cypress": "bin/cypress" "cypress": "bin/cypress"
}, },
"engines": { "engines": {
"node": "^14.0.0 || ^16.0.0 || >=18.0.0" "node": "^16.0.0 || ^18.0.0 || >=20.0.0"
} }
}, },
"node_modules/cypress-fail-on-console-error": { "node_modules/cypress-fail-on-console-error": {
"version": "4.0.3", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-4.0.3.tgz", "resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-5.0.0.tgz",
"integrity": "sha512-v2nPupd2brtxKLkDQX58SbEPWRF/2nDbqPTnYyhPIYHqG7U3P2dGUZ3zraETKKoLhU3+C0otjgB6Vg/bHhocQw==", "integrity": "sha512-xui/aSu8rmExZjZNgId3iX0MsGZih6ZoFH+54vNHrK3HaqIZZX5hUuNhAcmfSoM1rIDc2DeITeVaMn/hiQ9IWQ==",
"optional": true, "optional": true,
"dependencies": { "dependencies": {
"chai": "^4.3.4", "chai": "^4.3.4",
@ -7182,19 +7223,9 @@
} }
}, },
"node_modules/cypress-wait-until": { "node_modules/cypress-wait-until": {
"version": "2.0.0", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-2.0.0.tgz", "resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-2.0.1.tgz",
"integrity": "sha512-ulUZyrWBn+OuC8oiQuGKAScDYfpaWnE3dEE/raUo64w4RHQxZrQ/iMIWT4ZjGMMPr3P+BFEALCRnjQeRqzZj6g==", "integrity": "sha512-+IyVnYNiaX1+C+V/LazrJWAi/CqiwfNoRSrFviECQEyolW1gDRy765PZosL2alSSGK8V10Y7BGfOQyZUDgmnjQ==",
"optional": true,
"engines": {
"node": ">=18.16.0",
"npm": ">=9.5.1"
}
},
"node_modules/cypress/node_modules/@types/node": {
"version": "14.18.53",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.53.tgz",
"integrity": "sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A==",
"optional": true "optional": true
}, },
"node_modules/cypress/node_modules/ansi-styles": { "node_modules/cypress/node_modules/ansi-styles": {
@ -10976,28 +11007,6 @@
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
}, },
"node_modules/jsdom/node_modules/tough-cookie": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"dependencies": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.2.0",
"url-parse": "^1.5.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/jsdom/node_modules/universalify": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/jsesc": { "node_modules/jsesc": {
"version": "2.5.2", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
@ -15682,16 +15691,25 @@
} }
}, },
"node_modules/tough-cookie": { "node_modules/tough-cookie": {
"version": "2.5.0", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"optional": true,
"dependencies": { "dependencies": {
"psl": "^1.1.28", "psl": "^1.1.33",
"punycode": "^2.1.1" "punycode": "^2.1.1",
"universalify": "^0.2.0",
"url-parse": "^1.5.3"
}, },
"engines": { "engines": {
"node": ">=0.8" "node": ">=6"
}
},
"node_modules/tough-cookie/node_modules/universalify": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==",
"engines": {
"node": ">= 4.0.0"
} }
}, },
"node_modules/tr46": { "node_modules/tr46": {
@ -17790,11 +17808,12 @@
"integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg==" "integrity": "sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg=="
}, },
"@babel/code-frame": { "@babel/code-frame": {
"version": "7.22.5", "version": "7.22.13",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
"integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
"requires": { "requires": {
"@babel/highlight": "^7.22.5" "@babel/highlight": "^7.22.13",
"chalk": "^2.4.2"
} }
}, },
"@babel/compat-data": { "@babel/compat-data": {
@ -17959,17 +17978,29 @@
} }
}, },
"@babel/helper-environment-visitor": { "@babel/helper-environment-visitor": {
"version": "7.22.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==" "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA=="
}, },
"@babel/helper-function-name": { "@babel/helper-function-name": {
"version": "7.22.5", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
"requires": { "requires": {
"@babel/template": "^7.22.5", "@babel/template": "^7.22.15",
"@babel/types": "^7.22.5" "@babel/types": "^7.23.0"
},
"dependencies": {
"@babel/template": {
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
"requires": {
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
"@babel/types": "^7.22.15"
}
}
} }
}, },
"@babel/helper-hoist-variables": { "@babel/helper-hoist-variables": {
@ -18071,9 +18102,9 @@
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==" "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
}, },
"@babel/helper-validator-identifier": { "@babel/helper-validator-identifier": {
"version": "7.22.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==" "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
}, },
"@babel/helper-validator-option": { "@babel/helper-validator-option": {
"version": "7.22.5", "version": "7.22.5",
@ -18101,19 +18132,19 @@
} }
}, },
"@babel/highlight": { "@babel/highlight": {
"version": "7.22.5", "version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
"integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
"requires": { "requires": {
"@babel/helper-validator-identifier": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20",
"chalk": "^2.0.0", "chalk": "^2.4.2",
"js-tokens": "^4.0.0" "js-tokens": "^4.0.0"
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.22.7", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==" "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
}, },
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.22.5", "version": "7.22.5",
@ -18890,29 +18921,51 @@
} }
}, },
"@babel/traverse": { "@babel/traverse": {
"version": "7.22.8", "version": "7.23.2",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz",
"integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==",
"requires": { "requires": {
"@babel/code-frame": "^7.22.5", "@babel/code-frame": "^7.22.13",
"@babel/generator": "^7.22.7", "@babel/generator": "^7.23.0",
"@babel/helper-environment-visitor": "^7.22.5", "@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.22.5", "@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5", "@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6", "@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.22.7", "@babel/parser": "^7.23.0",
"@babel/types": "^7.22.5", "@babel/types": "^7.23.0",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
},
"dependencies": {
"@babel/generator": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz",
"integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==",
"requires": {
"@babel/types": "^7.23.0",
"@jridgewell/gen-mapping": "^0.3.2",
"@jridgewell/trace-mapping": "^0.3.17",
"jsesc": "^2.5.1"
}
},
"@jridgewell/trace-mapping": {
"version": "0.3.20",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.20.tgz",
"integrity": "sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==",
"requires": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
}
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.22.10", "version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==", "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
"requires": { "requires": {
"@babel/helper-string-parser": "^7.22.5", "@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.5", "@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
@ -19010,9 +19063,9 @@
} }
}, },
"@cypress/request": { "@cypress/request": {
"version": "2.88.11", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/@cypress/request/-/request-2.88.11.tgz", "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.1.tgz",
"integrity": "sha512-M83/wfQ1EkspjkE2lNWNV5ui2Cv7UCv1swW1DqljahbzLVWltcsexQh8jYtuS/vzFXP+HySntGM83ZXA9fn17w==", "integrity": "sha512-TWivJlJi8ZDx2wGOw1dbLuHJKUYX7bWySw377nlnGOW3hP9/MUKIsEdXT/YngWxVdgNCHRBmFlBipE+5/2ZZlQ==",
"optional": true, "optional": true,
"requires": { "requires": {
"aws-sign2": "~0.7.0", "aws-sign2": "~0.7.0",
@ -19028,9 +19081,9 @@
"json-stringify-safe": "~5.0.1", "json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19", "mime-types": "~2.1.19",
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"qs": "~6.10.3", "qs": "6.10.4",
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0", "tough-cookie": "^4.1.3",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0",
"uuid": "^8.3.2" "uuid": "^8.3.2"
} }
@ -19927,9 +19980,9 @@
"integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==" "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q=="
}, },
"@types/node": { "@types/node": {
"version": "18.11.9", "version": "18.17.18",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.9.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.18.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==" "integrity": "sha512-/4QOuy3ZpV7Ya1GTRz5CYSz3DgkKpyUptXuQ5PPce7uuyJAOR7r9FhkmxJfvcNUXyklbC63a+YvB3jxy7s9ngw=="
}, },
"@types/qrcode": { "@types/qrcode": {
"version": "1.5.0", "version": "1.5.0",
@ -20868,9 +20921,9 @@
"optional": true "optional": true
}, },
"bn.js": { "bn.js": {
"version": "5.2.0", "version": "5.2.1",
"resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
"integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==" "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ=="
}, },
"body-parser": { "body-parser": {
"version": "1.20.1", "version": "1.20.1",
@ -21214,25 +21267,25 @@
} }
}, },
"browserify-sign": { "browserify-sign": {
"version": "4.2.1", "version": "4.2.2",
"resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.2.tgz",
"integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", "integrity": "sha512-1rudGyeYY42Dk6texmv7c4VcQ0EsvVbLwZkA+AQB7SxvXxmcD93jcHie8bzecJ+ChDlmAm2Qyu0+Ccg5uhZXCg==",
"requires": { "requires": {
"bn.js": "^5.1.1", "bn.js": "^5.2.1",
"browserify-rsa": "^4.0.1", "browserify-rsa": "^4.1.0",
"create-hash": "^1.2.0", "create-hash": "^1.2.0",
"create-hmac": "^1.1.7", "create-hmac": "^1.1.7",
"elliptic": "^6.5.3", "elliptic": "^6.5.4",
"inherits": "^2.0.4", "inherits": "^2.0.4",
"parse-asn1": "^5.1.5", "parse-asn1": "^5.1.6",
"readable-stream": "^3.6.0", "readable-stream": "^3.6.2",
"safe-buffer": "^5.2.0" "safe-buffer": "^5.2.1"
}, },
"dependencies": { "dependencies": {
"readable-stream": { "readable-stream": {
"version": "3.6.0", "version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"requires": { "requires": {
"inherits": "^2.0.3", "inherits": "^2.0.3",
"string_decoder": "^1.1.1", "string_decoder": "^1.1.1",
@ -22065,14 +22118,14 @@
"peer": true "peer": true
}, },
"cypress": { "cypress": {
"version": "12.17.2", "version": "13.3.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-12.17.2.tgz", "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.3.0.tgz",
"integrity": "sha512-hxWAaWbqQBzzMuadSGSuQg5PDvIGOovm6xm0hIfpCVcORsCAj/gF2p0EvfnJ4f+jK2PCiDgP6D2eeE9/FK4Mjg==", "integrity": "sha512-mpI8qcTwLGiA4zEQvTC/U1xGUezVV4V8HQCOYjlEOrVmU1etVvxOjkCXHGwrlYdZU/EPmUiWfsO3yt1o+Q2bgw==",
"optional": true, "optional": true,
"requires": { "requires": {
"@cypress/request": "^2.88.11", "@cypress/request": "^3.0.0",
"@cypress/xvfb": "^1.2.4", "@cypress/xvfb": "^1.2.4",
"@types/node": "^14.14.31", "@types/node": "^18.17.5",
"@types/sinonjs__fake-timers": "8.1.1", "@types/sinonjs__fake-timers": "8.1.1",
"@types/sizzle": "^2.3.2", "@types/sizzle": "^2.3.2",
"arch": "^2.2.0", "arch": "^2.2.0",
@ -22105,6 +22158,7 @@
"minimist": "^1.2.8", "minimist": "^1.2.8",
"ospath": "^1.2.2", "ospath": "^1.2.2",
"pretty-bytes": "^5.6.0", "pretty-bytes": "^5.6.0",
"process": "^0.11.10",
"proxy-from-env": "1.0.0", "proxy-from-env": "1.0.0",
"request-progress": "^3.0.0", "request-progress": "^3.0.0",
"semver": "^7.5.3", "semver": "^7.5.3",
@ -22114,12 +22168,6 @@
"yauzl": "^2.10.0" "yauzl": "^2.10.0"
}, },
"dependencies": { "dependencies": {
"@types/node": {
"version": "14.18.53",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.53.tgz",
"integrity": "sha512-soGmOpVBUq+gaBMwom1M+krC/NNbWlosh4AtGA03SyWNDiqSKtwp7OulO1M6+mg8YkHMvJ/y0AkCeO8d1hNb7A==",
"optional": true
},
"ansi-styles": { "ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -22236,9 +22284,9 @@
} }
}, },
"cypress-fail-on-console-error": { "cypress-fail-on-console-error": {
"version": "4.0.3", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-4.0.3.tgz", "resolved": "https://registry.npmjs.org/cypress-fail-on-console-error/-/cypress-fail-on-console-error-5.0.0.tgz",
"integrity": "sha512-v2nPupd2brtxKLkDQX58SbEPWRF/2nDbqPTnYyhPIYHqG7U3P2dGUZ3zraETKKoLhU3+C0otjgB6Vg/bHhocQw==", "integrity": "sha512-xui/aSu8rmExZjZNgId3iX0MsGZih6ZoFH+54vNHrK3HaqIZZX5hUuNhAcmfSoM1rIDc2DeITeVaMn/hiQ9IWQ==",
"optional": true, "optional": true,
"requires": { "requires": {
"chai": "^4.3.4", "chai": "^4.3.4",
@ -22248,9 +22296,9 @@
} }
}, },
"cypress-wait-until": { "cypress-wait-until": {
"version": "2.0.0", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-2.0.0.tgz", "resolved": "https://registry.npmjs.org/cypress-wait-until/-/cypress-wait-until-2.0.1.tgz",
"integrity": "sha512-ulUZyrWBn+OuC8oiQuGKAScDYfpaWnE3dEE/raUo64w4RHQxZrQ/iMIWT4ZjGMMPr3P+BFEALCRnjQeRqzZj6g==", "integrity": "sha512-+IyVnYNiaX1+C+V/LazrJWAi/CqiwfNoRSrFviECQEyolW1gDRy765PZosL2alSSGK8V10Y7BGfOQyZUDgmnjQ==",
"optional": true "optional": true
}, },
"d": { "d": {
@ -24967,22 +25015,6 @@
"version": "6.0.1", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
},
"tough-cookie": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"requires": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
"universalify": "^0.2.0",
"url-parse": "^1.5.3"
}
},
"universalify": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="
} }
} }
}, },
@ -28497,13 +28529,21 @@
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
}, },
"tough-cookie": { "tough-cookie": {
"version": "2.5.0", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"optional": true,
"requires": { "requires": {
"psl": "^1.1.28", "psl": "^1.1.33",
"punycode": "^2.1.1" "punycode": "^2.1.1",
"universalify": "^0.2.0",
"url-parse": "^1.5.3"
},
"dependencies": {
"universalify": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz",
"integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg=="
}
} }
}, },
"tr46": { "tr46": {

View file

@ -35,7 +35,7 @@
"start:local-staging": "npm run generate-config && npm run sync-assets-dev && npm run ng -- serve -c local-staging", "start:local-staging": "npm run generate-config && npm run sync-assets-dev && npm run ng -- serve -c local-staging",
"start:mixed": "npm run generate-config && npm run sync-assets-dev && npm run ng -- serve -c mixed", "start:mixed": "npm run generate-config && npm run sync-assets-dev && npm run ng -- serve -c mixed",
"build": "npm run generate-config && npm run ng -- build --configuration production --localize && npm run sync-assets && npm run build-mempool.js", "build": "npm run generate-config && npm run ng -- build --configuration production --localize && npm run sync-assets && npm run build-mempool.js",
"sync-assets": "rsync -av ./src/resources ./dist/mempool/browser && node sync-assets.js 'dist/mempool/browser/resources'", "sync-assets": "rsync -av ./src/resources ./dist/mempool/browser && node sync-assets.js 'dist/mempool/browser/resources/'",
"sync-assets-dev": "node sync-assets.js 'src/resources/'", "sync-assets-dev": "node sync-assets.js 'src/resources/'",
"generate-config": "node generate-config.js", "generate-config": "node generate-config.js",
"build-mempool.js": "npm run build-mempool-js && npm run build-mempool-liquid-js && npm run build-mempool-bisq-js", "build-mempool.js": "npm run build-mempool-js && npm run build-mempool-liquid-js && npm run build-mempool-bisq-js",
@ -85,7 +85,6 @@
"clipboard": "^2.0.11", "clipboard": "^2.0.11",
"domino": "^2.1.6", "domino": "^2.1.6",
"echarts": "~5.4.3", "echarts": "~5.4.3",
"echarts-gl": "^2.0.9",
"lightweight-charts": "~3.8.0", "lightweight-charts": "~3.8.0",
"ngx-echarts": "~16.0.0", "ngx-echarts": "~16.0.0",
"ngx-infinite-scroll": "^16.0.0", "ngx-infinite-scroll": "^16.0.0",
@ -111,9 +110,9 @@
"optionalDependencies": { "optionalDependencies": {
"@cypress/schematic": "^2.5.0", "@cypress/schematic": "^2.5.0",
"@types/cypress": "^1.1.3", "@types/cypress": "^1.1.3",
"cypress": "^12.17.2", "cypress": "^13.3.0",
"cypress-fail-on-console-error": "~4.0.3", "cypress-fail-on-console-error": "~5.0.0",
"cypress-wait-until": "^2.0.0", "cypress-wait-until": "^2.0.1",
"mock-socket": "~9.2.1", "mock-socket": "~9.2.1",
"start-server-and-test": "~2.0.0" "start-server-and-test": "~2.0.0"
}, },

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnInit } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { Observable, Subscription, combineLatest } from 'rxjs'; import { Observable, Subscription, combineLatest } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core';
import { EChartsOption, graphic } from 'echarts'; import { echarts, EChartsOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';
@ -123,11 +123,11 @@ export class BlockFeesGraphComponent implements OnInit {
this.chartOptions = { this.chartOptions = {
title: title, title: title,
color: [ color: [
new graphic.LinearGradient(0, 0, 0, 1, [ new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FDD835' }, { offset: 0, color: '#FDD835' },
{ offset: 1, color: '#FB8C00' }, { offset: 1, color: '#FB8C00' },
]), ]),
new graphic.LinearGradient(0, 0, 0, 1, [ new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#C0CA33' }, { offset: 0, color: '#C0CA33' },
{ offset: 1, color: '#1B5E20' }, { offset: 1, color: '#1B5E20' },
]), ]),

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnInit } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core';
import { EChartsOption, graphic } from 'echarts'; import { echarts, EChartsOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';
@ -123,11 +123,11 @@ export class BlockRewardsGraphComponent implements OnInit {
title: title, title: title,
animation: false, animation: false,
color: [ color: [
new graphic.LinearGradient(0, 0, 0, 1, [ new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#FDD835' }, { offset: 0, color: '#FDD835' },
{ offset: 1, color: '#FB8C00' }, { offset: 1, color: '#FB8C00' },
]), ]),
new graphic.LinearGradient(0, 0, 0, 1, [ new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: '#C0CA33' }, { offset: 0, color: '#C0CA33' },
{ offset: 1, color: '#1B5E20' }, { offset: 1, color: '#1B5E20' },
]), ]),

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption} from 'echarts'; import { EChartsOption} from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';

View file

@ -1,6 +1,6 @@
<app-indexing-progress *ngIf="!widget"></app-indexing-progress> <app-indexing-progress *ngIf="!widget"></app-indexing-progress>
<div class="container-xl" style="min-height: 335px" [ngClass]="{'widget': widget, 'full-height': !widget, 'legacy': !indexingAvailable}"> <div class="container-xl" style="min-height: 335px" [ngClass]="{'widget': widget, 'full-height': !widget, 'legacy': !isMempoolModule}">
<h1 *ngIf="!widget" class="float-left" i18n="master-page.blocks">Blocks</h1> <h1 *ngIf="!widget" class="float-left" i18n="master-page.blocks">Blocks</h1>
<div *ngIf="!widget && isLoading" class="spinner-border ml-3" role="status"></div> <div *ngIf="!widget && isLoading" class="spinner-border ml-3" role="status"></div>
@ -9,28 +9,28 @@
<div style="min-height: 295px"> <div style="min-height: 295px">
<table class="table table-borderless"> <table class="table table-borderless">
<thead> <thead>
<th class="height text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" i18n="latest-blocks.height">Height</th> <th class="height text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}" i18n="latest-blocks.height">Height</th>
<th *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" i18n="mining.pool-name" <th *ngIf="isMempoolModule" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}" i18n="mining.pool-name"
i18n-ngbTooltip="mining.pool-name" ngbTooltip="Pool" placement="bottom" #miningpool [disableTooltip]="!isEllipsisActive(miningpool)">Pool</th> i18n-ngbTooltip="mining.pool-name" ngbTooltip="Pool" placement="bottom" #miningpool [disableTooltip]="!isEllipsisActive(miningpool)">Pool</th>
<th class="timestamp" i18n="latest-blocks.timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Timestamp</th> <th class="timestamp" i18n="latest-blocks.timestamp" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">Timestamp</th>
<th *ngIf="auditAvailable" class="health text-right" i18n="latest-blocks.health" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" <th *ngIf="auditAvailable" class="health text-right" i18n="latest-blocks.health" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
i18n-ngbTooltip="latest-blocks.health" ngbTooltip="Health" placement="bottom" #health [disableTooltip]="!isEllipsisActive(health)">Health</th> i18n-ngbTooltip="latest-blocks.health" ngbTooltip="Health" placement="bottom" #health [disableTooltip]="!isEllipsisActive(health)">Health</th>
<th *ngIf="indexingAvailable" class="reward text-right" i18n="latest-blocks.reward" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" <th *ngIf="isMempoolModule" class="reward text-right" i18n="latest-blocks.reward" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
i18n-ngbTooltip="latest-blocks.reward" ngbTooltip="Reward" placement="bottom" #reward [disableTooltip]="!isEllipsisActive(reward)">Reward</th> i18n-ngbTooltip="latest-blocks.reward" ngbTooltip="Reward" placement="bottom" #reward [disableTooltip]="!isEllipsisActive(reward)">Reward</th>
<th *ngIf="indexingAvailable && !widget" class="fees text-right" i18n="latest-blocks.fees" [class]="indexingAvailable ? '' : 'legacy'">Fees</th> <th *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-right" i18n="latest-blocks.fees" [class]="isMempoolModule ? '' : 'legacy'">Fees</th>
<th *ngIf="auditAvailable && !widget" class="fee-delta" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"></th> <th *ngIf="auditAvailable && !widget" class="fee-delta" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"></th>
<th *ngIf="indexingAvailable" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" <th *ngIf="isMempoolModule" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
i18n-ngbTooltip="dashboard.txs" ngbTooltip="TXs" placement="bottom" #txs [disableTooltip]="!isEllipsisActive(txs)">TXs</th> i18n-ngbTooltip="dashboard.txs" ngbTooltip="TXs" placement="bottom" #txs [disableTooltip]="!isEllipsisActive(txs)">TXs</th>
<th *ngIf="!indexingAvailable" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">Transactions</th> <th *ngIf="!isMempoolModule" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">Transactions</th>
<th class="size" i18n="latest-blocks.size" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Size</th> <th class="size" i18n="latest-blocks.size" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">Size</th>
</thead> </thead>
<tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''"> <tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock"> <tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
<td class="height text-left" [class]="widget ? 'widget' : ''"> <td class="height text-left" [class]="widget ? 'widget' : ''">
<a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a> <a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a>
</td> </td>
<td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="isMempoolModule" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<div class="tooltip-custom"> <div *ngIf="indexingAvailable" class="tooltip-custom">
<a class="clear-link" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]"> <a class="clear-link" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]">
<img width="22" height="22" src="{{ block.extras.pool['logo'] }}" <img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
onError="this.src = '/resources/mining-pools/default.svg'" [alt]="'Logo of ' + block.extras.pool.name + ' mining pool'"> onError="this.src = '/resources/mining-pools/default.svg'" [alt]="'Logo of ' + block.extras.pool.name + ' mining pool'">
@ -38,11 +38,17 @@
</a> </a>
<span *ngIf="!widget" class="tooltiptext badge badge-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span> <span *ngIf="!widget" class="tooltiptext badge badge-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span>
</div> </div>
<div *ngIf="!indexingAvailable" class="tooltip-custom">
<img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
onError="this.src = '/resources/mining-pools/default.svg'" [alt]="'Logo of ' + block.extras.pool.name + ' mining pool'">
<span class="pool-name">{{ block.extras.pool.name }}</span>
<span *ngIf="!widget" class="tooltiptext badge badge-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span>
</div>
</td> </td>
<td class="timestamp" *ngIf="!widget" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td class="timestamp" *ngIf="!widget" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
&lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }} &lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}
</td> </td>
<td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<a <a
*ngIf="block?.extras?.matchRate != null; else nullHealth" *ngIf="block?.extras?.matchRate != null; else nullHealth"
class="health-badge badge" class="health-badge badge"
@ -56,21 +62,21 @@
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span> <span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
</ng-template> </ng-template>
</td> </td>
<td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="isMempoolModule" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<app-amount [satoshis]="block.extras.reward" [noFiat]="true" digitsInfo="1.2-2"></app-amount> <app-amount [satoshis]="block.extras.reward" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
</td> </td>
<td *ngIf="indexingAvailable && !widget" class="fees text-right" [class]="indexingAvailable ? '' : 'legacy'"> <td *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-right" [class]="isMempoolModule ? '' : 'legacy'">
<app-amount [satoshis]="block.extras.totalFees" [noFiat]="true" digitsInfo="1.2-2"></app-amount> <app-amount [satoshis]="block.extras.totalFees" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
</td> </td>
<td *ngIf="auditAvailable" class="fee-delta" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="auditAvailable" class="fee-delta" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span *ngIf="block.extras.feeDelta" class="difference" [class.positive]="block.extras.feeDelta >= 0" [class.negative]="block.extras.feeDelta < 0"> <span *ngIf="block.extras.feeDelta" class="difference" [class.positive]="block.extras.feeDelta >= 0" [class.negative]="block.extras.feeDelta < 0">
{{ block.extras.feeDelta > 0 ? '+' : '' }}{{ (block.extras.feeDelta * 100) | amountShortener: 2 }}% {{ block.extras.feeDelta > 0 ? '+' : '' }}{{ (block.extras.feeDelta * 100) | amountShortener: 2 }}%
</span> </span>
</td> </td>
<td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
{{ block.tx_count | number }} {{ block.tx_count | number }}
</td> </td>
<td class="size" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'"> <td class="size" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
<div class="progress"> <div class="progress">
<div class="progress-bar progress-mempool" role="progressbar" <div class="progress-bar progress-mempool" role="progressbar"
[ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"></div> [ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"></div>
@ -82,34 +88,34 @@
<ng-template #skeleton> <ng-template #skeleton>
<tbody> <tbody>
<tr *ngFor="let item of skeletonLines"> <tr *ngFor="let item of skeletonLines">
<td class="height text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td class="height text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="isMempoolModule" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 125px"></span> <span class="skeleton-loader" style="max-width: 125px"></span>
</td> </td>
<td class="timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'"> <td class="timestamp" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 150px"></span> <span class="skeleton-loader" style="max-width: 150px"></span>
</td> </td>
<td class="mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'"> <td class="mined" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 125px"></span> <span class="skeleton-loader" style="max-width: 125px"></span>
</td> </td>
<td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td *ngIf="isMempoolModule" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td *ngIf="indexingAvailable && !widget" class="fees text-right" [class]="indexingAvailable ? '' : 'legacy'"> <td *ngIf="isMempoolModule && !widget" class="fees text-right" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td *ngIf="auditAvailable && !widget" class="fee-delta" [class]="indexingAvailable ? '' : 'legacy'"> <td *ngIf="auditAvailable && !widget" class="fee-delta" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}"> <td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span> <span class="skeleton-loader" style="max-width: 75px"></span>
</td> </td>
<td class="size" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'"> <td class="size" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader"></span> <span class="skeleton-loader"></span>
</td> </td>
</tr> </tr>

View file

@ -19,6 +19,7 @@ export class BlocksList implements OnInit {
blocks$: Observable<BlockExtended[]> = undefined; blocks$: Observable<BlockExtended[]> = undefined;
isMempoolModule = false;
indexingAvailable = false; indexingAvailable = false;
auditAvailable = false; auditAvailable = false;
isLoading = true; isLoading = true;
@ -39,6 +40,7 @@ export class BlocksList implements OnInit {
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
private seoService: SeoService, private seoService: SeoService,
) { ) {
this.isMempoolModule = this.stateService.env.BASE_MODULE === 'mempool';
} }
ngOnInit(): void { ngOnInit(): void {
@ -75,11 +77,10 @@ export class BlocksList implements OnInit {
this.lastBlockHeight = Math.max(...blocks.map(o => o.height)); this.lastBlockHeight = Math.max(...blocks.map(o => o.height));
}), }),
map(blocks => { map(blocks => {
if (this.indexingAvailable) { if (this.stateService.env.BASE_MODULE === 'mempool') {
for (const block of blocks) { for (const block of blocks) {
// @ts-ignore: Need to add an extra field for the template // @ts-ignore: Need to add an extra field for the template
block.extras.pool.logo = `/resources/mining-pools/` + block.extras.pool.logo = `/resources/mining-pools/` + block.extras.pool.slug + '.svg';
block.extras.pool.slug + '.svg';
} }
} }
if (this.widget) { if (this.widget) {
@ -110,7 +111,7 @@ export class BlocksList implements OnInit {
} }
if (blocks[1]) { if (blocks[1]) {
this.blocksCount = Math.max(this.blocksCount, blocks[1][0].height) + 1; this.blocksCount = Math.max(this.blocksCount, blocks[1][0].height) + 1;
if (this.stateService.env.MINING_DASHBOARD) { if (this.isMempoolModule) {
// @ts-ignore: Need to add an extra field for the template // @ts-ignore: Need to add an extra field for the template
blocks[1][0].extras.pool.logo = `/resources/mining-pools/` + blocks[1][0].extras.pool.logo = `/resources/mining-pools/` +
blocks[1][0].extras.pool.slug + '.svg'; blocks[1][0].extras.pool.slug + '.svg';
@ -121,9 +122,11 @@ export class BlocksList implements OnInit {
return acc; return acc;
}, []), }, []),
switchMap((blocks) => { switchMap((blocks) => {
if (this.isMempoolModule && this.auditAvailable) {
blocks.forEach(block => { blocks.forEach(block => {
block.extras.feeDelta = block.extras.expectedFees ? (block.extras.totalFees - block.extras.expectedFees) / block.extras.expectedFees : 0; block.extras.feeDelta = block.extras.expectedFees ? (block.extras.totalFees - block.extras.expectedFees) / block.extras.expectedFees : 0;
}); });
}
return of(blocks); return of(blocks);
}) })
); );

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption, graphic } from 'echarts'; import { echarts, EChartsOption } from '../../graphs/echarts';
import { merge, Observable, of } from 'rxjs'; import { merge, Observable, of } from 'rxjs';
import { map, mergeMap, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, mergeMap, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';
@ -204,7 +204,7 @@ export class HashrateChartComponent implements OnInit {
title: title, title: title,
animation: false, animation: false,
color: [ color: [
new graphic.LinearGradient(0, 0, 0, 0.65, [ new echarts.graphic.LinearGradient(0, 0, 0, 0.65, [
{ offset: 0, color: '#F4511E99' }, { offset: 0, color: '#F4511E99' },
{ offset: 0.25, color: '#FB8C0099' }, { offset: 0.25, color: '#FB8C0099' },
{ offset: 0.5, color: '#FFB30099' }, { offset: 0.5, color: '#FFB30099' },
@ -212,7 +212,7 @@ export class HashrateChartComponent implements OnInit {
{ offset: 1, color: '#7CB34299' } { offset: 1, color: '#7CB34299' }
]), ]),
'#D81B60', '#D81B60',
new graphic.LinearGradient(0, 0, 0, 0.65, [ new echarts.graphic.LinearGradient(0, 0, 0, 0.65, [
{ offset: 0, color: '#F4511E' }, { offset: 0, color: '#F4511E' },
{ offset: 0.25, color: '#FB8C00' }, { offset: 0.25, color: '#FB8C00' },
{ offset: 0.5, color: '#FFB300' }, { offset: 0.5, color: '#FFB300' },
@ -342,7 +342,7 @@ export class HashrateChartComponent implements OnInit {
type: 'value', type: 'value',
axisLabel: { axisLabel: {
color: 'rgb(110, 112, 121)', color: 'rgb(110, 112, 121)',
formatter: (val) => { formatter: (val): string => {
const selectedPowerOfTen: any = selectPowerOfTen(val); const selectedPowerOfTen: any = selectPowerOfTen(val);
const newVal = Math.round(val / selectedPowerOfTen.divider); const newVal = Math.round(val / selectedPowerOfTen.divider);
return `${newVal} ${selectedPowerOfTen.unit}H/s`; return `${newVal} ${selectedPowerOfTen.unit}H/s`;
@ -364,9 +364,9 @@ export class HashrateChartComponent implements OnInit {
position: 'right', position: 'right',
axisLabel: { axisLabel: {
color: 'rgb(110, 112, 121)', color: 'rgb(110, 112, 121)',
formatter: (val) => { formatter: (val): string => {
if (this.stateService.network === 'signet') { if (this.stateService.network === 'signet') {
return val; return `${val}`;
} }
const selectedPowerOfTen: any = selectPowerOfTen(val); const selectedPowerOfTen: any = selectPowerOfTen(val);
const newVal = Math.round(val / selectedPowerOfTen.divider); const newVal = Math.round(val / selectedPowerOfTen.divider);

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { delay, map, retryWhen, share, startWith, switchMap, tap } from 'rxjs/operators'; import { delay, map, retryWhen, share, startWith, switchMap, tap } from 'rxjs/operators';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';

View file

@ -1,5 +1,5 @@
import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core'; import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnInit, OnDestroy } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { OnChanges } from '@angular/core'; import { OnChanges } from '@angular/core';
import { StorageService } from '../../services/storage.service'; import { StorageService } from '../../services/storage.service';
import { download, formatterXAxis, formatterXAxisLabel } from '../../shared/graphs.utils'; import { download, formatterXAxis, formatterXAxisLabel } from '../../shared/graphs.utils';
@ -37,6 +37,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
}; };
windowPreference: string; windowPreference: string;
chartInstance: any = undefined; chartInstance: any = undefined;
MA: number[][] = [];
weightMode: boolean = false; weightMode: boolean = false;
rateUnitSub: Subscription; rateUnitSub: Subscription;
@ -62,6 +63,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
return; return;
} }
this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference'); this.windowPreference = this.windowPreferenceOverride ? this.windowPreferenceOverride : this.storageService.getValue('graphWindowPreference');
this.MA = this.calculateMA(this.data.series[0]);
this.mountChart(); this.mountChart();
} }
@ -72,7 +74,101 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
this.isLoading = false; this.isLoading = false;
} }
/// calculate the moving average of maData
calculateMA(maData): number[][] {
//update const variables that are not changed
const ma: number[][] = [];
let sum = 0;
let i = 0;
const len = maData.length;
//Adjust window length based on the length of the data
//5% appeared as a good amount from tests
//TODO: make this a text box in the UI
const maWindowLen = Math.ceil(len * 0.05);
//calculate the center of the moving average window
const center = Math.floor(maWindowLen / 2);
//calculate the centered moving average
for (i = center; i < len - center; i++) {
sum = 0;
//build out ma as we loop through the data
ma[i] = [];
ma[i].push(maData[i][0]);
for (let j = i - center; j <= i + center; j++) {
sum += maData[j][1];
}
ma[i].push(sum / maWindowLen);
}
//return the moving average array
return ma;
}
mountChart(): void { mountChart(): void {
//create an array for the echart series
//similar to how it is done in mempool-graph.component.ts
const seriesGraph = [];
seriesGraph.push({
zlevel: 0,
name: 'data',
data: this.data.series[0],
type: 'line',
smooth: false,
showSymbol: false,
symbol: 'none',
lineStyle: {
width: 3,
},
markLine: {
silent: true,
symbol: 'none',
lineStyle: {
color: '#fff',
opacity: 1,
width: 2,
},
data: [{
yAxis: 1667,
label: {
show: false,
color: '#ffffff',
}
}],
}
},
{
zlevel: 0,
name: 'MA',
data: this.MA,
type: 'line',
smooth: false,
showSymbol: false,
symbol: 'none',
lineStyle: {
width: 1,
color: "white",
},
markLine: {
silent: true,
symbol: 'none',
lineStyle: {
color: '#fff',
opacity: 1,
width: 2,
},
data: [{
yAxis: 1667,
label: {
show: false,
color: '#ffffff',
}
}],
}
});
this.mempoolStatsChartOption = { this.mempoolStatsChartOption = {
grid: { grid: {
height: this.height, height: this.height,
@ -126,13 +222,17 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
const colorSpan = (color: string) => `<span class="indicator" style="background-color: ` + color + `"></span>`; const colorSpan = (color: string) => `<span class="indicator" style="background-color: ` + color + `"></span>`;
let itemFormatted = '<div class="title">' + axisValueLabel + '</div>'; let itemFormatted = '<div class="title">' + axisValueLabel + '</div>';
params.map((item: any, index: number) => { params.map((item: any, index: number) => {
//Do no include MA in tooltip legend!
if (item.seriesName !== 'MA') {
if (index < 26) { if (index < 26) {
itemFormatted += `<div class="item"> itemFormatted += `<div class="item">
<div class="indicator-container">${colorSpan(item.color)}</div> <div class="indicator-container">${colorSpan(item.color)}</div>
<div class="grow"></div> <div class="grow"></div>
<div class="value">${formatNumber(this.weightMode ? item.value[1] * 4 : item.value[1], this.locale, '1.0-0')} <span class="symbol">${this.weightMode ? 'WU' : 'vB'}/s</span></div> <div class="value">${formatNumber(item.value[1], this.locale, '1.0-0')}<span class="symbol">vB/s</span></div>
</div>`; </div>`;
} }
}
}); });
return `<div class="tx-wrapper-tooltip-chart ${(this.template === 'advanced') ? 'tx-wrapper-tooltip-chart-advanced' : ''}">${itemFormatted}</div>`; return `<div class="tx-wrapper-tooltip-chart ${(this.template === 'advanced') ? 'tx-wrapper-tooltip-chart-advanced' : ''}">${itemFormatted}</div>`;
} }
@ -171,35 +271,7 @@ export class IncomingTransactionsGraphComponent implements OnInit, OnChanges, On
} }
} }
}, },
series: [ series: seriesGraph,
{
zlevel: 0,
data: this.data.series[0],
type: 'line',
smooth: false,
showSymbol: false,
symbol: 'none',
lineStyle: {
width: 3,
},
markLine: {
silent: true,
symbol: 'none',
lineStyle: {
color: '#fff',
opacity: 1,
width: 2,
},
data: [{
yAxis: 1667,
label: {
show: false,
color: '#ffffff',
}
}],
}
},
],
visualMap: { visualMap: {
show: false, show: false,
top: 50, top: 50,

View file

@ -1,6 +1,6 @@
import { Component, Inject, LOCALE_ID, ChangeDetectionStrategy, Input, OnChanges, OnInit } from '@angular/core'; import { Component, Inject, LOCALE_ID, ChangeDetectionStrategy, Input, OnChanges, OnInit } from '@angular/core';
import { formatDate, formatNumber } from '@angular/common'; import { formatDate, formatNumber } from '@angular/common';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
@Component({ @Component({
selector: 'app-lbtc-pegs-graph', selector: 'app-lbtc-pegs-graph',

View file

@ -6,7 +6,7 @@ import { formatNumber } from '@angular/common';
import { OptimizedMempoolStats } from '../../interfaces/node-api.interface'; import { OptimizedMempoolStats } from '../../interfaces/node-api.interface';
import { StateService } from '../../services/state.service'; import { StateService } from '../../services/state.service';
import { StorageService } from '../../services/storage.service'; import { StorageService } from '../../services/storage.service';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { feeLevels, chartColors } from '../../app.constants'; import { feeLevels, chartColors } from '../../app.constants';
import { download, formatterXAxis, formatterXAxisLabel } from '../../shared/graphs.utils'; import { download, formatterXAxis, formatterXAxisLabel } from '../../shared/graphs.utils';
@ -27,7 +27,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
@Input() data: any[]; @Input() data: any[];
@Input() filterSize = 100000; @Input() filterSize = 100000;
@Input() limitFilterFee = 1; @Input() limitFilterFee = 1;
@Input() hideCount: boolean = false; @Input() hideCount: boolean = true;
@Input() height: number | string = 200; @Input() height: number | string = 200;
@Input() top: number | string = 20; @Input() top: number | string = 20;
@Input() right: number | string = 10; @Input() right: number | string = 10;
@ -53,7 +53,7 @@ export class MempoolGraphComponent implements OnInit, OnChanges {
chartInstance: any = undefined; chartInstance: any = undefined;
weightMode: boolean = false; weightMode: boolean = false;
isWidget: boolean = false; isWidget: boolean = false;
showCount: boolean = true; showCount: boolean = false;
constructor( constructor(
private vbytesPipe: VbytesPipe, private vbytesPipe: VbytesPipe,

View file

@ -1,7 +1,7 @@
import { ChangeDetectionStrategy, Component, Input, NgZone, OnInit, HostBinding } from '@angular/core'; import { ChangeDetectionStrategy, Component, Input, NgZone, OnInit, HostBinding } from '@angular/core';
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { EChartsOption, PieSeriesOption } from 'echarts'; import { EChartsOption, PieSeriesOption } from '../../graphs/echarts';
import { merge, Observable } from 'rxjs'; import { merge, Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { SeoService } from '../../services/seo.service'; import { SeoService } from '../../services/seo.service';

View file

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { EChartsOption, graphic } from 'echarts'; import { echarts, EChartsOption } from '../../graphs/echarts';
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { map, switchMap, catchError } from 'rxjs/operators'; import { map, switchMap, catchError } from 'rxjs/operators';
import { PoolStat } from '../../interfaces/node-api.interface'; import { PoolStat } from '../../interfaces/node-api.interface';
@ -127,7 +127,7 @@ export class PoolPreviewComponent implements OnInit {
title: title, title: title,
animation: false, animation: false,
color: [ color: [
new graphic.LinearGradient(0, 0, 0, 0.65, [ new echarts.graphic.LinearGradient(0, 0, 0, 0.65, [
{ offset: 0, color: '#F4511E' }, { offset: 0, color: '#F4511E' },
{ offset: 0.25, color: '#FB8C00' }, { offset: 0.25, color: '#FB8C00' },
{ offset: 0.5, color: '#FFB300' }, { offset: 0.5, color: '#FFB300' },

View file

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { EChartsOption, graphic } from 'echarts'; import { echarts, EChartsOption } from '../../graphs/echarts';
import { BehaviorSubject, Observable, of, timer } from 'rxjs'; import { BehaviorSubject, Observable, of, timer } from 'rxjs';
import { catchError, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; import { catchError, distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators';
import { BlockExtended, PoolStat } from '../../interfaces/node-api.interface'; import { BlockExtended, PoolStat } from '../../interfaces/node-api.interface';
@ -131,7 +131,7 @@ export class PoolComponent implements OnInit {
title: title, title: title,
animation: false, animation: false,
color: [ color: [
new graphic.LinearGradient(0, 0, 0, 0.65, [ new echarts.graphic.LinearGradient(0, 0, 0, 0.65, [
{ offset: 0, color: '#F4511E' }, { offset: 0, color: '#F4511E' },
{ offset: 0.25, color: '#FB8C00' }, { offset: 0.25, color: '#FB8C00' },
{ offset: 0.5, color: '#FFB300' }, { offset: 0.5, color: '#FFB300' },

View file

@ -14,6 +14,7 @@
<div id="blockchain-container" [dir]="timeLtr ? 'rtl' : 'ltr'" #blockchainContainer <div id="blockchain-container" [dir]="timeLtr ? 'rtl' : 'ltr'" #blockchainContainer
[class.menu-open]="menuOpen" [class.menu-open]="menuOpen"
[class.menu-closing]="menuSliding && !menuOpen" [class.menu-closing]="menuSliding && !menuOpen"
[class.with-menu]="hasMenu"
(mousedown)="onMouseDown($event)" (mousedown)="onMouseDown($event)"
(pointerdown)="onPointerDown($event)" (pointerdown)="onPointerDown($event)"
(touchmove)="onTouchMove($event)" (touchmove)="onTouchMove($event)"

View file

@ -6,7 +6,7 @@
overflow-y: hidden; overflow-y: hidden;
scrollbar-width: none; scrollbar-width: none;
-ms-overflow-style: none; -ms-overflow-style: none;
width: calc(100% + 120px); width: 100%;
transform: translateX(0px); transform: translateX(0px);
transition: transform 0; transition: transform 0;
@ -20,6 +20,10 @@
transform: translateX(0px); transform: translateX(0px);
transition: transform 0.25s; transition: transform 0.25s;
} }
&.with-menu {
width: calc(100% + 120px);
}
} }
#blockchain-container::-webkit-scrollbar { #blockchain-container::-webkit-scrollbar {

View file

@ -60,11 +60,16 @@ export class StartComponent implements OnInit, AfterViewChecked, OnDestroy {
menuSliding: boolean = false; menuSliding: boolean = false;
menuTimeout: number; menuTimeout: number;
hasMenu = false;
constructor( constructor(
private stateService: StateService, private stateService: StateService,
private cd: ChangeDetectorRef, private cd: ChangeDetectorRef,
) { ) {
this.isiOS = ['iPhone','iPod','iPad'].includes((navigator as any)?.userAgentData?.platform || navigator.platform); this.isiOS = ['iPhone','iPod','iPad'].includes((navigator as any)?.userAgentData?.platform || navigator.platform);
if (this.stateService.network === '') {
this.hasMenu = true;
}
} }
ngOnInit() { ngOnInit() {

View file

@ -32,7 +32,7 @@ export class StatisticsComponent implements OnInit {
chartColors = chartColors; chartColors = chartColors;
filterSize = 100000; filterSize = 100000;
filterFeeIndex = 1; filterFeeIndex = 1;
showCount = true; showCount = false;
maxFeeIndex: number; maxFeeIndex: number;
dropDownOpen = false; dropDownOpen = false;

View file

@ -0,0 +1,17 @@
// Import tree-shakeable echarts
import * as echarts from 'echarts/core';
import { LineChart, LinesChart, BarChart, TreemapChart, PieChart, ScatterChart } from 'echarts/charts';
import { TitleComponent, TooltipComponent, GridComponent, LegendComponent, GeoComponent, DataZoomComponent, VisualMapComponent } from 'echarts/components';
import { SVGRenderer, CanvasRenderer } from 'echarts/renderers';
// Typescript interfaces
import { EChartsOption, TreemapSeriesOption, LineSeriesOption, PieSeriesOption } from 'echarts';
echarts.use([
SVGRenderer, CanvasRenderer,
TitleComponent, TooltipComponent, GridComponent,
LegendComponent, GeoComponent, DataZoomComponent,
VisualMapComponent,
LineChart, LinesChart, BarChart, TreemapChart, PieChart, ScatterChart
]);
export { echarts, EChartsOption, TreemapSeriesOption, LineSeriesOption, PieSeriesOption };

View file

@ -53,7 +53,7 @@ import { CommonModule } from '@angular/common';
SharedModule, SharedModule,
GraphsRoutingModule, GraphsRoutingModule,
NgxEchartsModule.forRoot({ NgxEchartsModule.forRoot({
echarts: () => import('echarts') echarts: () => import('./echarts').then(m => m.echarts),
}) })
], ],
exports: [ exports: [

View file

@ -57,7 +57,7 @@ export class GroupPreviewComponent implements OnInit {
return of(null); return of(null);
} }
return this.lightningApiService.getNodGroupNodes$(this.groupId); return this.lightningApiService.getNodeGroup$(this.groupId);
}), }),
map((nodes) => { map((nodes) => {
for (const node of nodes) { for (const node of nodes) {

View file

@ -41,7 +41,7 @@ export class GroupComponent implements OnInit {
this.seoService.setTitle(`Mempool.space Lightning Nodes`); this.seoService.setTitle(`Mempool.space Lightning Nodes`);
this.seoService.setDescription(`See all Lightning nodes run by mempool.space -- these are the nodes that provide the data on the mempool.space Lightning dashboard.`); this.seoService.setDescription(`See all Lightning nodes run by mempool.space -- these are the nodes that provide the data on the mempool.space Lightning dashboard.`);
this.nodes$ = this.lightningApiService.getNodGroupNodes$('mempool.space') this.nodes$ = this.lightningApiService.getNodeGroup$('mempool.space')
.pipe( .pipe(
map((nodes) => { map((nodes) => {
for (const node of nodes) { for (const node of nodes) {

View file

@ -27,7 +27,7 @@ export class LightningApiService {
return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey); return this.httpClient.get<any>(this.apiBasePath + '/api/v1/lightning/nodes/' + publicKey);
} }
getNodGroupNodes$(name: string): Observable<any[]> { getNodeGroup$(name: string): Observable<any[]> {
return this.httpClient.get<any[]>(this.apiBasePath + '/api/v1/lightning/nodes/group/' + name); return this.httpClient.get<any[]>(this.apiBasePath + '/api/v1/lightning/nodes/group/' + name);
} }

View file

@ -1,5 +1,5 @@
import { Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { switchMap } from 'rxjs/operators'; import { switchMap } from 'rxjs/operators';
import { download } from '../../shared/graphs.utils'; import { download } from '../../shared/graphs.utils';
import { LightningApiService } from '../lightning-api.service'; import { LightningApiService } from '../lightning-api.service';

View file

@ -1,5 +1,5 @@
import { Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption } from 'echarts'; import { EChartsOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators'; import { switchMap, tap } from 'rxjs/operators';
import { formatNumber } from '@angular/common'; import { formatNumber } from '@angular/common';

View file

@ -6,8 +6,7 @@ import { AssetsService } from '../../services/assets.service';
import { ActivatedRoute, ParamMap, Router } from '@angular/router'; import { ActivatedRoute, ParamMap, Router } from '@angular/router';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
import { StateService } from '../../services/state.service'; import { StateService } from '../../services/state.service';
import { EChartsOption, registerMap } from 'echarts'; import { EChartsOption, echarts } from '../../graphs/echarts';
import 'echarts-gl';
import { isMobile } from '../../shared/common.utils'; import { isMobile } from '../../shared/common.utils';
@Component({ @Component({
@ -88,7 +87,7 @@ export class NodesChannelsMap implements OnInit {
this.style !== 'channelpage' ? this.apiService.getChannelsGeo$(params.get('public_key') ?? undefined, this.style) : [''], this.style !== 'channelpage' ? this.apiService.getChannelsGeo$(params.get('public_key') ?? undefined, this.style) : [''],
[params.get('public_key') ?? undefined] [params.get('public_key') ?? undefined]
).pipe(tap((data) => { ).pipe(tap((data) => {
registerMap('world', data[0]); echarts.registerMap('world', data[0]);
const channelsLoc = []; const channelsLoc = [];
const nodes = []; const nodes = [];

View file

@ -1,7 +1,7 @@
import { formatNumber } from '@angular/common'; import { formatNumber } from '@angular/common';
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnChanges } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, OnChanges } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { ECharts, EChartsOption, TreemapSeriesOption } from 'echarts'; import { EChartsOption, TreemapSeriesOption } from '../../graphs/echarts';
import { Observable, share, switchMap, tap } from 'rxjs'; import { Observable, share, switchMap, tap } from 'rxjs';
import { lerpColor } from '../../shared/graphs.utils'; import { lerpColor } from '../../shared/graphs.utils';
import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe'; import { AmountShortenerPipe } from '../../shared/pipes/amount-shortener.pipe';
@ -18,7 +18,7 @@ import { StateService } from '../../services/state.service';
export class NodeChannels implements OnChanges { export class NodeChannels implements OnChanges {
@Input() publicKey: string; @Input() publicKey: string;
chartInstance: ECharts; chartInstance: any;
chartOptions: EChartsOption = {}; chartOptions: EChartsOption = {};
chartInitOptions = { chartInitOptions = {
renderer: 'svg', renderer: 'svg',
@ -129,7 +129,7 @@ export class NodeChannels implements OnChanges {
}; };
} }
onChartInit(ec: ECharts): void { onChartInit(ec: any): void {
this.chartInstance = ec; this.chartInstance = ec;
this.chartInstance.on('click', (e) => { this.chartInstance.on('click', (e) => {

View file

@ -3,7 +3,7 @@ import { SeoService } from '../../services/seo.service';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';
import { Observable, BehaviorSubject, switchMap, tap, combineLatest } from 'rxjs'; import { Observable, BehaviorSubject, switchMap, tap, combineLatest } from 'rxjs';
import { AssetsService } from '../../services/assets.service'; import { AssetsService } from '../../services/assets.service';
import { EChartsOption, registerMap } from 'echarts'; import { EChartsOption, echarts } from '../../graphs/echarts';
import { lerpColor } from '../../shared/graphs.utils'; import { lerpColor } from '../../shared/graphs.utils';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
@ -63,7 +63,7 @@ export class NodesMap implements OnInit, OnChanges {
this.assetsService.getWorldMapJson$, this.assetsService.getWorldMapJson$,
this.nodes$ this.nodes$
).pipe(tap((data) => { ).pipe(tap((data) => {
registerMap('world', data[0]); echarts.registerMap('world', data[0]);
let maxLiquidity = data[1].maxLiquidity; let maxLiquidity = data[1].maxLiquidity;
let inputNodes: any[] = data[1].nodes; let inputNodes: any[] = data[1].nodes;
@ -88,7 +88,7 @@ export class NodesMap implements OnInit, OnChanges {
node.public_key, node.public_key,
node.alias, node.alias,
node.capacity, node.capacity,
node.channels, node.active_channel_count,
node.country, node.country,
node.iso_code, node.iso_code,
]); ]);

View file

@ -1,5 +1,5 @@
import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption, graphic, LineSeriesOption} from 'echarts'; import { echarts, EChartsOption, LineSeriesOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { formatNumber } from '@angular/common'; import { formatNumber } from '@angular/common';
@ -152,7 +152,7 @@ export class NodesNetworksChartComponent implements OnInit {
opacity: 0.5, opacity: 0.5,
}, },
stack: 'Total', stack: 'Total',
color: new graphic.LinearGradient(0, 0.75, 0, 1, [ color: new echarts.graphic.LinearGradient(0, 0.75, 0, 1, [
{ offset: 0, color: '#D81B60' }, { offset: 0, color: '#D81B60' },
{ offset: 1, color: '#D81B60AA' }, { offset: 1, color: '#D81B60AA' },
]), ]),
@ -174,7 +174,7 @@ export class NodesNetworksChartComponent implements OnInit {
opacity: 0.5, opacity: 0.5,
}, },
stack: 'Total', stack: 'Total',
color: new graphic.LinearGradient(0, 0.75, 0, 1, [ color: new echarts.graphic.LinearGradient(0, 0.75, 0, 1, [
{ offset: 0, color: '#be7d4c' }, { offset: 0, color: '#be7d4c' },
{ offset: 1, color: '#be7d4cAA' }, { offset: 1, color: '#be7d4cAA' },
]), ]),
@ -195,7 +195,7 @@ export class NodesNetworksChartComponent implements OnInit {
opacity: 0.5, opacity: 0.5,
}, },
stack: 'Total', stack: 'Total',
color: new graphic.LinearGradient(0, 0.75, 0, 1, [ color: new echarts.graphic.LinearGradient(0, 0.75, 0, 1, [
{ offset: 0, color: '#FFB300' }, { offset: 0, color: '#FFB300' },
{ offset: 1, color: '#FFB300AA' }, { offset: 1, color: '#FFB300AA' },
]), ]),
@ -216,7 +216,7 @@ export class NodesNetworksChartComponent implements OnInit {
opacity: 0.5, opacity: 0.5,
}, },
stack: 'Total', stack: 'Total',
color: new graphic.LinearGradient(0, 0.75, 0, 1, [ color: new echarts.graphic.LinearGradient(0, 0.75, 0, 1, [
{ offset: 0, color: '#7D4698' }, { offset: 0, color: '#7D4698' },
{ offset: 1, color: '#7D4698AA' }, { offset: 1, color: '#7D4698AA' },
]), ]),

View file

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, OnInit, HostBinding, NgZone } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit, HostBinding, NgZone } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { EChartsOption, PieSeriesOption } from 'echarts'; import { EChartsOption, PieSeriesOption } from '../../graphs/echarts';
import { map, Observable, share, tap } from 'rxjs'; import { map, Observable, share, tap } from 'rxjs';
import { chartColors } from '../../app.constants'; import { chartColors } from '../../app.constants';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';

View file

@ -1,6 +1,6 @@
import { ChangeDetectionStrategy, Component, OnInit, HostBinding, NgZone, Input } from '@angular/core'; import { ChangeDetectionStrategy, Component, OnInit, HostBinding, NgZone, Input } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { EChartsOption, PieSeriesOption } from 'echarts'; import { EChartsOption, PieSeriesOption } from '../../graphs/echarts';
import { combineLatest, map, Observable, share, startWith, Subject, switchMap, tap } from 'rxjs'; import { combineLatest, map, Observable, share, startWith, Subject, switchMap, tap } from 'rxjs';
import { chartColors } from '../../app.constants'; import { chartColors } from '../../app.constants';
import { ApiService } from '../../services/api.service'; import { ApiService } from '../../services/api.service';

View file

@ -1,5 +1,5 @@
import { Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core'; import { Component, Inject, Input, LOCALE_ID, OnInit, HostBinding } from '@angular/core';
import { EChartsOption, graphic } from 'echarts'; import { echarts, EChartsOption } from '../../graphs/echarts';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; import { map, share, startWith, switchMap, tap } from 'rxjs/operators';
import { SeoService } from '../../services/seo.service'; import { SeoService } from '../../services/seo.service';
@ -132,7 +132,7 @@ export class LightningStatisticsChartComponent implements OnInit {
animation: false, animation: false,
color: [ color: [
'#FFB300', '#FFB300',
new graphic.LinearGradient(0, 0.75, 0, 1, [ new echarts.graphic.LinearGradient(0, 0.75, 0, 1, [
{ offset: 0, color: '#D81B60' }, { offset: 0, color: '#D81B60' },
{ offset: 1, color: '#D81B60AA' }, { offset: 1, color: '#D81B60AA' },
]), ]),

View file

@ -84,6 +84,7 @@
<a href="https://github.com/mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a> <a href="https://github.com/mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>GitHub</title><path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/></svg></a>
<a href="https://twitter.com/mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a> <a href="https://twitter.com/mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Twitter</title><path d="M23.953 4.57a10 10 0 01-2.825.775 4.958 4.958 0 002.163-2.723c-.951.555-2.005.959-3.127 1.184a4.92 4.92 0 00-8.384 4.482C7.69 8.095 4.067 6.13 1.64 3.162a4.822 4.822 0 00-.666 2.475c0 1.71.87 3.213 2.188 4.096a4.904 4.904 0 01-2.228-.616v.06a4.923 4.923 0 003.946 4.827 4.996 4.996 0 01-2.212.085 4.936 4.936 0 004.604 3.417 9.867 9.867 0 01-6.102 2.105c-.39 0-.779-.023-1.17-.067a13.995 13.995 0 007.557 2.209c9.053 0 13.998-7.496 13.998-13.985 0-.21 0-.42-.015-.63A9.935 9.935 0 0024 4.59z"/></svg></a>
<a href="nostr:npub18d4r6wanxkyrdfjdrjqzj2ukua5cas669ew2g5w7lf4a8te7awzqey6lt3" target="_blank"><svg fill="#fff" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 875 875"><path d="M684.72 485.57c.22 12.59-11.93 51.47-38.67 81.3-26.74 29.83-56.02 20.85-58.42 20.16s-3.09-4.46-7.89-3.77-9.6 6.17-18.86 7.2-17.49 1.71-26.06-1.37c-4.46.69-5.14.71-7.2 2.24s-17.83 10.79-21.6 11.47c0 7.2-1.37 44.57 0 55.89s3.77 25.71 7.54 36 2.74 10.63 7.54 9.94 13.37.34 15.77 4.11c2.4 3.77 1.37 6.51 5.49 8.23s60.69 17.14 99.43 19.2c26.74.69 42.86 2.74 52.12 19.54 1.37 7.89 7.54 13.03 11.31 14.06s8.23 2.06 12 5.83 1.03 8.23 5.49 11.66c4.46 3.43 14.74 8.57 25.37 13.71 10.63 5.14 15.09 13.37 15.77 16.11s1.71 10.97 1.71 10.97-8.91 0-10.97-2.06-2.74-5.83-2.74-5.83-6.17 1.03-7.54 3.43.69 2.74-7.89.69-11.66-3.77-18.17-8.57c-6.51-4.8-16.46-17.14-25.03-16.8 4.11 8.23 5.83 8.23 10.63 10.97s8.23 5.83 8.23 5.83l-7.2 4.46s-4.46 2.06-14.74-.69-11.66-4.46-12.69-10.63 0-9.26-2.74-14.4-4.11-15.77-22.29-21.26c-18.17-5.49-66.52-21.26-100.12-24.69s-22.63-2.74-28.11-1.37-15.77 4.46-26.4-1.37c-10.63-5.83-16.8-13.71-17.49-20.23s-1.71-10.97 0-19.2 3.43-19.89 1.71-26.74-14.06-55.89-19.89-64.12c-13.03 1.03-50.74-.69-50.74-.69s-2.4-.69-17.49 5.83-36.48 13.76-46.77 19.93-14.4 9.7-16.12 13.13c.12 3-1.23 7.72-2.79 9.06s-12.48 2.42-12.48 2.42-5.85 5.86-8.25 9.97c-6.86 9.6-55.2 125.14-66.52 149.83-13.54 32.57-9.77 27.43-37.71 27.43s-8.06.3-8.06.3-12.34 5.88-16.8 5.88-18.86-2.4-26.4 0-16.46 9.26-23.31 10.29-4.95-1.34-8.38-3.74c-4-.21-14.27-.12-14.27-.12s1.74-6.51 7.91-10.88c8.23-5.83 25.37-16.11 34.63-21.26s17.49-7.89 23.31-9.26 18.51-6.17 30.51-9.94 19.54-8.23 29.83-31.54 50.4-111.43 51.43-116.23c.63-2.96 3.73-6.48 4.8-15.09.66-5.35-2.49-13.04 1.71-22.63 10.97-25.03 21.6-20.23 26.4-20.23s17.14.34 26.4-1.37 15.43-2.74 24.69-7.89 11.31-8.91 11.31-8.91l-19.89-3.43s-18.51.69-25.03-4.46-15.43-15.77-15.43-15.77l-7.54-7.2 1.03 8.57s-5.14-8.91-6.51-10.29-8.57-6.51-11.31-11.31-7.54-25.03-7.54-25.03l-6.17 13.03-1.71-18.86-5.14 7.2-2.74-16.11-4.8 8.23-3.43-14.4-5.83 4.46-2.4-10.29-5.83-3.43s-14.06-9.26-16.46-9.6-4.46 3.43-4.46 3.43l1.37 12-12.2-6.27-7-11.9s2.36 4.01-9.62 7.53c-20.55 0-21.89-2.28-24.93-3.94-1.31-6.56-5.57-10.11-5.57-10.11h-20.57l-.34-6.86-7.89 3.09.69-10.29h-14.06l1.03-11.31h-8.91s3.09-9.26 25.71-22.97 25.03-16.46 46.29-17.14c21.26-.69 32.91 2.74 46.29 8.23s38.74 13.71 43.89 17.49c11.31-9.94 28.46-19.89 34.29-19.89 1.03-2.4 6.19-12.33 17.96-17.6 35.31-15.81 108.13-34 131.53-35.54 31.2-2.06 7.89-1.37 39.09 2.06 31.2 3.43 54.17 7.54 69.6 12.69 12.58 4.19 25.03 9.6 34.29 2.06 4.33-1.81 11.81-1.34 17.83-5.14 30.69-25.09 34.72-32.35 43.63-41.95s20.14-24.91 22.54-45.14 4.46-58.29-10.63-88.12-28.8-45.26-34.63-69.26c-5.83-24-8.23-61.03-6.17-73.03 2.06-12 5.14-22.29 6.86-30.51s9.94-14.74 19.89-16.46c9.94-1.71 17.83 1.37 22.29 4.8 4.46 3.43 11.65 6.28 13.37 10.29.34 1.71-1.37 6.51 8.23 8.23 9.6 1.71 16.05 4.16 16.05 4.16s15.64 4.29 3.11 7.73c-12.69 2.06-20.52-.71-24.29 1.69s-7.21 10.08-9.61 11.1-7.2.34-12 4.11-9.6 6.86-12.69 14.4-5.49 15.77-3.43 26.74 8.57 31.54 14.4 43.2c5.83 11.66 20.23 40.8 24.34 47.66s15.77 29.49 16.8 53.83 1.03 44.23 0 54.86-10.84 51.65-35.53 85.94c-8.16 14.14-23.21 31.9-24.67 35.03-1.45 3.13-3.02 4.88-1.61 7.65 4.62 9.05 12.87 22.13 14.71 29.22 2.29 6.64 6.99 16.13 7.22 28.72Z" style="stroke:#000;stroke-miterlimit:10;stroke-width:6px"/></svg></a> <a href="nostr:npub18d4r6wanxkyrdfjdrjqzj2ukua5cas669ew2g5w7lf4a8te7awzqey6lt3" target="_blank"><svg fill="#fff" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 875 875"><path d="M684.72 485.57c.22 12.59-11.93 51.47-38.67 81.3-26.74 29.83-56.02 20.85-58.42 20.16s-3.09-4.46-7.89-3.77-9.6 6.17-18.86 7.2-17.49 1.71-26.06-1.37c-4.46.69-5.14.71-7.2 2.24s-17.83 10.79-21.6 11.47c0 7.2-1.37 44.57 0 55.89s3.77 25.71 7.54 36 2.74 10.63 7.54 9.94 13.37.34 15.77 4.11c2.4 3.77 1.37 6.51 5.49 8.23s60.69 17.14 99.43 19.2c26.74.69 42.86 2.74 52.12 19.54 1.37 7.89 7.54 13.03 11.31 14.06s8.23 2.06 12 5.83 1.03 8.23 5.49 11.66c4.46 3.43 14.74 8.57 25.37 13.71 10.63 5.14 15.09 13.37 15.77 16.11s1.71 10.97 1.71 10.97-8.91 0-10.97-2.06-2.74-5.83-2.74-5.83-6.17 1.03-7.54 3.43.69 2.74-7.89.69-11.66-3.77-18.17-8.57c-6.51-4.8-16.46-17.14-25.03-16.8 4.11 8.23 5.83 8.23 10.63 10.97s8.23 5.83 8.23 5.83l-7.2 4.46s-4.46 2.06-14.74-.69-11.66-4.46-12.69-10.63 0-9.26-2.74-14.4-4.11-15.77-22.29-21.26c-18.17-5.49-66.52-21.26-100.12-24.69s-22.63-2.74-28.11-1.37-15.77 4.46-26.4-1.37c-10.63-5.83-16.8-13.71-17.49-20.23s-1.71-10.97 0-19.2 3.43-19.89 1.71-26.74-14.06-55.89-19.89-64.12c-13.03 1.03-50.74-.69-50.74-.69s-2.4-.69-17.49 5.83-36.48 13.76-46.77 19.93-14.4 9.7-16.12 13.13c.12 3-1.23 7.72-2.79 9.06s-12.48 2.42-12.48 2.42-5.85 5.86-8.25 9.97c-6.86 9.6-55.2 125.14-66.52 149.83-13.54 32.57-9.77 27.43-37.71 27.43s-8.06.3-8.06.3-12.34 5.88-16.8 5.88-18.86-2.4-26.4 0-16.46 9.26-23.31 10.29-4.95-1.34-8.38-3.74c-4-.21-14.27-.12-14.27-.12s1.74-6.51 7.91-10.88c8.23-5.83 25.37-16.11 34.63-21.26s17.49-7.89 23.31-9.26 18.51-6.17 30.51-9.94 19.54-8.23 29.83-31.54 50.4-111.43 51.43-116.23c.63-2.96 3.73-6.48 4.8-15.09.66-5.35-2.49-13.04 1.71-22.63 10.97-25.03 21.6-20.23 26.4-20.23s17.14.34 26.4-1.37 15.43-2.74 24.69-7.89 11.31-8.91 11.31-8.91l-19.89-3.43s-18.51.69-25.03-4.46-15.43-15.77-15.43-15.77l-7.54-7.2 1.03 8.57s-5.14-8.91-6.51-10.29-8.57-6.51-11.31-11.31-7.54-25.03-7.54-25.03l-6.17 13.03-1.71-18.86-5.14 7.2-2.74-16.11-4.8 8.23-3.43-14.4-5.83 4.46-2.4-10.29-5.83-3.43s-14.06-9.26-16.46-9.6-4.46 3.43-4.46 3.43l1.37 12-12.2-6.27-7-11.9s2.36 4.01-9.62 7.53c-20.55 0-21.89-2.28-24.93-3.94-1.31-6.56-5.57-10.11-5.57-10.11h-20.57l-.34-6.86-7.89 3.09.69-10.29h-14.06l1.03-11.31h-8.91s3.09-9.26 25.71-22.97 25.03-16.46 46.29-17.14c21.26-.69 32.91 2.74 46.29 8.23s38.74 13.71 43.89 17.49c11.31-9.94 28.46-19.89 34.29-19.89 1.03-2.4 6.19-12.33 17.96-17.6 35.31-15.81 108.13-34 131.53-35.54 31.2-2.06 7.89-1.37 39.09 2.06 31.2 3.43 54.17 7.54 69.6 12.69 12.58 4.19 25.03 9.6 34.29 2.06 4.33-1.81 11.81-1.34 17.83-5.14 30.69-25.09 34.72-32.35 43.63-41.95s20.14-24.91 22.54-45.14 4.46-58.29-10.63-88.12-28.8-45.26-34.63-69.26c-5.83-24-8.23-61.03-6.17-73.03 2.06-12 5.14-22.29 6.86-30.51s9.94-14.74 19.89-16.46c9.94-1.71 17.83 1.37 22.29 4.8 4.46 3.43 11.65 6.28 13.37 10.29.34 1.71-1.37 6.51 8.23 8.23 9.6 1.71 16.05 4.16 16.05 4.16s15.64 4.29 3.11 7.73c-12.69 2.06-20.52-.71-24.29 1.69s-7.21 10.08-9.61 11.1-7.2.34-12 4.11-9.6 6.86-12.69 14.4-5.49 15.77-3.43 26.74 8.57 31.54 14.4 43.2c5.83 11.66 20.23 40.8 24.34 47.66s15.77 29.49 16.8 53.83 1.03 44.23 0 54.86-10.84 51.65-35.53 85.94c-8.16 14.14-23.21 31.9-24.67 35.03-1.45 3.13-3.02 4.88-1.61 7.65 4.62 9.05 12.87 22.13 14.71 29.22 2.29 6.64 6.99 16.13 7.22 28.72Z" style="stroke:#000;stroke-miterlimit:10;stroke-width:6px"/></svg></a>
<a href="https://primal.net/mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg" ><path d="m155.5 253c-8.9 2-18.1 3-27.5 3-25.9 0-50-7.7-70.2-20.9-5-7.2-7.2-11.1-8.9-14-0.8-1.4-1.5-2.6-2.2-3.8-7.7-12.2-11.7-28-12.5-46.6-2.7-57.4 32.2-94 67.8-100.1 22.6-3.8 40.6 0.1 54.3 7.5-12.1-3.4-26.6-3.6-43.2 1.1-40.1 12.9-53.5 52.3-47.8 95.8 10 54.6 63.5 74.1 90.2 78zm-114.3-30.9c-7.4-13.2-14.2-33-15-51-2.9-60.9 34.4-101.6 74.5-108.3 54.7-9.3 85.1 23.1 95.6 47.1 0.4-0.3 0.6-0.9 0.3-1.4-17.2-37.4-52.8-63.2-94-63.2-46.8 0-88.5 33.6-102.6 83.4 0.2 36.9 16 70.2 41.2 93.4zm158.8 11.7c-9.2 6.3-19.3 11.5-30.1 15.2-5.1-0.9-10.9-2-14.9-2.8-1.9-0.4-3.4-0.7-4.3-0.9-24.4-4.4-67.9-20.1-77.5-71.6-2.6-20.6-0.7-39.7 6.1-54.8 6.7-14.9 18.4-26.3 36.1-32 20.6-5.6 37.7-2.9 50.3 3.9q-4.7-0.9-9.6-1c-27.4 0-49.7 23.9-49.7 53.3 0 11.7 3.6 22.5 9.6 31.3 0 0 17.2 32.5 64 29.6 41.7-2.6 63.4-40 66-53.8 1.3-7.2 2-14.6 2-22.2 0-66.3-53.7-120-120-120-50.1 0-93.1 30.8-111.1 74.4-6 7.9-11.2 16.7-15.4 26.2 9.3-61.5 62.4-108.6 126.5-108.6 70.7 0 128 57.3 128 128 0 44-22.2 82.8-56 105.8z" style="fill:#ffffff"/></svg></a>
<a href="https://youtube.com/@mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>YouTube</title><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg></a> <a href="https://youtube.com/@mempool" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>YouTube</title><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg></a>
<a href="https://bitcointv.com/c/mempool/videos" target="_blank"><svg _ngcontent-serverApp-c90="" xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 440 440"><path _ngcontent-serverApp-c90="" d="M225.57,2.08l-.69-.45a4.22,4.22,0,0,0-5.72,1.23L182.33,46.09a4,4,0,0,0,.88,5.81l9.38,6.38L173.48,97.49a4.22,4.22,0,0,0,2.45,4.19s3.55.7,4.53-1l41.92-40.56a3.62,3.62,0,0,0-1.51-5.1l-10.55-6.12L227.44,6.79A4.26,4.26,0,0,0,225.57,2.08Z" fill="#fff"></path><path _ngcontent-serverApp-c90="" d="M118.52,401.83c-62.51,0-113.37-51-113.37-113.67V214.68C5.15,152,56,101,118.52,101H342.08a24.82,24.82,0,0,1,24.76,24.83V377a24.81,24.81,0,0,1-24.76,24.82Z"></path><path _ngcontent-serverApp-c90="" d="M342.08,105.18a20.65,20.65,0,0,1,20.61,20.66V377a20.66,20.66,0,0,1-20.61,20.66H118.52C58.3,397.67,9.31,348.55,9.31,288.16V214.68c0-60.38,49-109.5,109.21-109.5H342.08m0-8.34H118.52C53.62,96.84,1,149.6,1,214.68v73.48C1,353.24,53.62,406,118.52,406H342.08A29,29,0,0,0,371,377V125.84a29,29,0,0,0-28.92-29Z" fill="#fff"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M344.69,346.23A25.84,25.84,0,1,0,335,369.87l-10.22-10.2a11.69,11.69,0,1,1,4.77-5.12l10.31,10.28A25.84,25.84,0,0,0,344.69,346.23Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M315.82,257.61a25.67,25.67,0,0,0-12.53,5.22L315,274.49a9.58,9.58,0,0,1,2.11-.73A9.72,9.72,0,1,1,309.4,283a9.4,9.4,0,0,1,.75-3.41L298.4,267.84a25.77,25.77,0,1,0,17.42-10.23Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M313,214a7.76,7.76,0,1,1,1.41,10.91,7.62,7.62,0,0,1-2.19-2.69l-18.67-.14a25.94,25.94,0,1,0,.05-7l18.64.14A7.4,7.4,0,0,1,313,214Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M341.2,144.08h-6.32c-1.67,0-3.61,1.87-3.61,4.29s1.94,4.29,3.61,4.29h6.32c1.67,0,3.61-1.87,3.61-4.29S342.87,144.08,341.2,144.08Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M301.75,144.08h-6.44c-1.67,0-3.61,1.87-3.61,4.29s1.94,4.29,3.61,4.29h6.44c1.67,0,3.61-1.87,3.61-4.29S303.42,144.08,301.75,144.08Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M321.77,144.08h-7c-1.67,0-3.62,1.87-3.62,4.29s1.95,4.29,3.62,4.29h7c1.67,0,3.62-1.87,3.62-4.29S323.44,144.08,321.77,144.08Z"></path><ellipse _ngcontent-serverApp-c90="" fill="#fff" cx="295.97" cy="127.61" rx="4.27" ry="4.29"></ellipse><path _ngcontent-serverApp-c90="" fill="#fff" d="M340.54,131.9a4.29,4.29,0,1,0-4.27-4.29A4.28,4.28,0,0,0,340.54,131.9Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M318.26,131.9a4.29,4.29,0,1,0-4.27-4.29A4.29,4.29,0,0,0,318.26,131.9Z"></path><ellipse _ngcontent-serverApp-c90="" fill="#fff" cx="295.97" cy="169.13" rx="4.27" ry="4.29"></ellipse><path _ngcontent-serverApp-c90="" fill="#fff" d="M340.54,164.84a4.3,4.3,0,1,0,4.27,4.29A4.29,4.29,0,0,0,340.54,164.84Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M318.26,164.84a4.3,4.3,0,1,0,4.28,4.29A4.29,4.29,0,0,0,318.26,164.84Z"></path><path _ngcontent-serverApp-c90="" d="M108.62,256.87c8.36-1,7.68-7.76,3.14-17-3.64-7.4-9.74-16.39-15.75-25.36-14.23-21.23-27.69-42.23-5.35-41.07,19.55,1,42.9,18.63,68.22,36.74,31.1,22.24,65.16,45.21,98.81,39.11a151.19,151.19,0,0,1,20-2.37V221a92,92,0,0,0-91.91-92.16H124.33A92,92,0,0,0,32.42,221v17.59c17.71,3.81,31,9.94,43.8,14.15C86.6,256.16,96.69,258.31,108.62,256.87Z"></path><path _ngcontent-serverApp-c90="" d="M273.37,310.79c-35-15.26-76.67-32.1-104-23.59-3.15,1-5,2.3-6,3.85-3.35,5.31,4.67,13.57,14.89,22.17,7.17,6,15.36,12.21,21.44,17.64,11.47,10.26,15.35,17.84-9.89,16.62-29.75-1.44-49.18-13.75-71.18-24l-.29-.14a165.84,165.84,0,0,0-22.93-8.91c-15.74-4.67-34.22-6.79-58.51-3.28A91.93,91.93,0,0,0,124.33,375h61.45A92,92,0,0,0,273.37,310.79Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M257.69,249.31C224,255.41,190,232.44,158.88,210.2c-25.32-18.11-48.67-35.72-68.22-36.74C68.32,172.3,81.78,193.3,96,214.53c6,9,12.11,18,15.75,25.36,4.54,9.22,5.22,16-3.14,17-11.93,1.44-22-.71-32.4-4.13-12.8-4.21-26.09-10.34-43.8-14.15v44.26c0,1.26.14,2.48.19,3.72a91.8,91.8,0,0,0,2.9,19.62c.43,1.67.84,3.34,1.37,5,24.29-3.51,42.77-1.39,58.51,3.28a165.84,165.84,0,0,1,22.93,8.91c.39-.12.76-.26,1.14-.39l-.85.53c22,10.25,41.43,22.56,71.18,24,25.24,1.22,21.36-6.36,9.89-16.62-6.08-5.43-14.27-11.61-21.44-17.64-10.22-8.6-18.24-16.86-14.89-22.17,1-1.55,2.87-2.87,6-3.85,27.33-8.51,69,8.33,104,23.59.32-1,.56-2.05.84-3.07a92.33,92.33,0,0,0,3.48-24.87V246.94A151.19,151.19,0,0,0,257.69,249.31Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M192,137a78,78,0,0,1,77.78,78v73.91a78,78,0,0,1-77.78,78H118.51a78,78,0,0,1-77.78-78V215a78,78,0,0,1,77.78-78H192m0-8.33H118.51A86.21,86.21,0,0,0,32.42,215v73.91a86.21,86.21,0,0,0,86.09,86.33H192a86.21,86.21,0,0,0,86.09-86.33V215A86.21,86.21,0,0,0,192,128.64Z"></path></svg></a> <a href="https://bitcointv.com/c/mempool/videos" target="_blank"><svg _ngcontent-serverApp-c90="" xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 440 440"><path _ngcontent-serverApp-c90="" d="M225.57,2.08l-.69-.45a4.22,4.22,0,0,0-5.72,1.23L182.33,46.09a4,4,0,0,0,.88,5.81l9.38,6.38L173.48,97.49a4.22,4.22,0,0,0,2.45,4.19s3.55.7,4.53-1l41.92-40.56a3.62,3.62,0,0,0-1.51-5.1l-10.55-6.12L227.44,6.79A4.26,4.26,0,0,0,225.57,2.08Z" fill="#fff"></path><path _ngcontent-serverApp-c90="" d="M118.52,401.83c-62.51,0-113.37-51-113.37-113.67V214.68C5.15,152,56,101,118.52,101H342.08a24.82,24.82,0,0,1,24.76,24.83V377a24.81,24.81,0,0,1-24.76,24.82Z"></path><path _ngcontent-serverApp-c90="" d="M342.08,105.18a20.65,20.65,0,0,1,20.61,20.66V377a20.66,20.66,0,0,1-20.61,20.66H118.52C58.3,397.67,9.31,348.55,9.31,288.16V214.68c0-60.38,49-109.5,109.21-109.5H342.08m0-8.34H118.52C53.62,96.84,1,149.6,1,214.68v73.48C1,353.24,53.62,406,118.52,406H342.08A29,29,0,0,0,371,377V125.84a29,29,0,0,0-28.92-29Z" fill="#fff"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M344.69,346.23A25.84,25.84,0,1,0,335,369.87l-10.22-10.2a11.69,11.69,0,1,1,4.77-5.12l10.31,10.28A25.84,25.84,0,0,0,344.69,346.23Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M315.82,257.61a25.67,25.67,0,0,0-12.53,5.22L315,274.49a9.58,9.58,0,0,1,2.11-.73A9.72,9.72,0,1,1,309.4,283a9.4,9.4,0,0,1,.75-3.41L298.4,267.84a25.77,25.77,0,1,0,17.42-10.23Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M313,214a7.76,7.76,0,1,1,1.41,10.91,7.62,7.62,0,0,1-2.19-2.69l-18.67-.14a25.94,25.94,0,1,0,.05-7l18.64.14A7.4,7.4,0,0,1,313,214Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M341.2,144.08h-6.32c-1.67,0-3.61,1.87-3.61,4.29s1.94,4.29,3.61,4.29h6.32c1.67,0,3.61-1.87,3.61-4.29S342.87,144.08,341.2,144.08Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M301.75,144.08h-6.44c-1.67,0-3.61,1.87-3.61,4.29s1.94,4.29,3.61,4.29h6.44c1.67,0,3.61-1.87,3.61-4.29S303.42,144.08,301.75,144.08Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M321.77,144.08h-7c-1.67,0-3.62,1.87-3.62,4.29s1.95,4.29,3.62,4.29h7c1.67,0,3.62-1.87,3.62-4.29S323.44,144.08,321.77,144.08Z"></path><ellipse _ngcontent-serverApp-c90="" fill="#fff" cx="295.97" cy="127.61" rx="4.27" ry="4.29"></ellipse><path _ngcontent-serverApp-c90="" fill="#fff" d="M340.54,131.9a4.29,4.29,0,1,0-4.27-4.29A4.28,4.28,0,0,0,340.54,131.9Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M318.26,131.9a4.29,4.29,0,1,0-4.27-4.29A4.29,4.29,0,0,0,318.26,131.9Z"></path><ellipse _ngcontent-serverApp-c90="" fill="#fff" cx="295.97" cy="169.13" rx="4.27" ry="4.29"></ellipse><path _ngcontent-serverApp-c90="" fill="#fff" d="M340.54,164.84a4.3,4.3,0,1,0,4.27,4.29A4.29,4.29,0,0,0,340.54,164.84Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M318.26,164.84a4.3,4.3,0,1,0,4.28,4.29A4.29,4.29,0,0,0,318.26,164.84Z"></path><path _ngcontent-serverApp-c90="" d="M108.62,256.87c8.36-1,7.68-7.76,3.14-17-3.64-7.4-9.74-16.39-15.75-25.36-14.23-21.23-27.69-42.23-5.35-41.07,19.55,1,42.9,18.63,68.22,36.74,31.1,22.24,65.16,45.21,98.81,39.11a151.19,151.19,0,0,1,20-2.37V221a92,92,0,0,0-91.91-92.16H124.33A92,92,0,0,0,32.42,221v17.59c17.71,3.81,31,9.94,43.8,14.15C86.6,256.16,96.69,258.31,108.62,256.87Z"></path><path _ngcontent-serverApp-c90="" d="M273.37,310.79c-35-15.26-76.67-32.1-104-23.59-3.15,1-5,2.3-6,3.85-3.35,5.31,4.67,13.57,14.89,22.17,7.17,6,15.36,12.21,21.44,17.64,11.47,10.26,15.35,17.84-9.89,16.62-29.75-1.44-49.18-13.75-71.18-24l-.29-.14a165.84,165.84,0,0,0-22.93-8.91c-15.74-4.67-34.22-6.79-58.51-3.28A91.93,91.93,0,0,0,124.33,375h61.45A92,92,0,0,0,273.37,310.79Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M257.69,249.31C224,255.41,190,232.44,158.88,210.2c-25.32-18.11-48.67-35.72-68.22-36.74C68.32,172.3,81.78,193.3,96,214.53c6,9,12.11,18,15.75,25.36,4.54,9.22,5.22,16-3.14,17-11.93,1.44-22-.71-32.4-4.13-12.8-4.21-26.09-10.34-43.8-14.15v44.26c0,1.26.14,2.48.19,3.72a91.8,91.8,0,0,0,2.9,19.62c.43,1.67.84,3.34,1.37,5,24.29-3.51,42.77-1.39,58.51,3.28a165.84,165.84,0,0,1,22.93,8.91c.39-.12.76-.26,1.14-.39l-.85.53c22,10.25,41.43,22.56,71.18,24,25.24,1.22,21.36-6.36,9.89-16.62-6.08-5.43-14.27-11.61-21.44-17.64-10.22-8.6-18.24-16.86-14.89-22.17,1-1.55,2.87-2.87,6-3.85,27.33-8.51,69,8.33,104,23.59.32-1,.56-2.05.84-3.07a92.33,92.33,0,0,0,3.48-24.87V246.94A151.19,151.19,0,0,0,257.69,249.31Z"></path><path _ngcontent-serverApp-c90="" fill="#fff" d="M192,137a78,78,0,0,1,77.78,78v73.91a78,78,0,0,1-77.78,78H118.51a78,78,0,0,1-77.78-78V215a78,78,0,0,1,77.78-78H192m0-8.33H118.51A86.21,86.21,0,0,0,32.42,215v73.91a86.21,86.21,0,0,0,86.09,86.33H192a86.21,86.21,0,0,0,86.09-86.33V215A86.21,86.21,0,0,0,192,128.64Z"></path></svg></a>
<a href="https://mempool.chat" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Matrix</title><path d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z"/></svg></a> <a href="https://mempool.chat" target="_blank"><svg fill="#fff" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Matrix</title><path d="M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.314.448.208.785.582 1.02 1.108.254-.374.6-.706 1.034-.992.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.245.489.559.646.951.152.392.23.863.23 1.417v5.728h-2.349V11.52c0-.286-.01-.559-.032-.812a1.755 1.755 0 0 0-.18-.66 1.106 1.106 0 0 0-.438-.448c-.194-.11-.457-.166-.785-.166-.332 0-.6.064-.803.189a1.38 1.38 0 0 0-.48.499 1.946 1.946 0 0 0-.231.696 5.56 5.56 0 0 0-.06.785v4.768h-2.35v-4.8c0-.254-.004-.503-.018-.752a2.074 2.074 0 0 0-.143-.688 1.052 1.052 0 0 0-.415-.503c-.194-.125-.476-.19-.854-.19-.111 0-.259.024-.439.074-.18.051-.36.143-.53.282-.171.138-.319.337-.439.595-.12.259-.18.6-.18 1.02v4.966H5.46V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z"/></svg></a>

View file

@ -88,7 +88,14 @@ footer .row.link-tree {
footer .row.social-links { footer .row.social-links {
text-align: center; text-align: center;
margin: 24px 0; display: flex;
flex-wrap: wrap;
width: fit-content;
margin: 0 auto;
@media (max-width: 450px){
width: 250px;
}
} }
footer .row.social-links a { footer .row.social-links a {
@ -97,6 +104,7 @@ footer .row.social-links a {
footer .row.social-links svg { footer .row.social-links svg {
width: 20px; width: 20px;
margin: 10px 0 10px 0;
} }
footer .row.version { footer .row.version {
@ -189,10 +197,6 @@ footer .sponsor {
margin-top: 15px; margin-top: 15px;
} }
footer .row.social-links {
margin: 48px 0 24px 0;
}
footer .selector:not(:last-child) { footer .selector:not(:last-child) {
margin-right: 10px; margin-right: 10px;
} }
@ -236,10 +240,6 @@ footer .sponsor {
margin-top: 15px; margin-top: 15px;
} }
footer .services.row.social-links {
margin: 48px 0 24px 0;
}
footer .services.selector:not(:last-child) { footer .services.selector:not(:last-child) {
margin-right: 10px; margin-right: 10px;
} }

View file

@ -1,6 +1,19 @@
var https = require('https'); var https = require('https');
var fs = require('fs'); var fs = require('fs');
var crypto = require('crypto'); var crypto = require('crypto');
var path = require('node:path');
const LOG_TAG = '[sync-assets]';
let verbose = false;
if (parseInt(process.env.SKIP_SYNC) === 1) {
console.log(`${LOG_TAG} SKIP_SYNC is set, not checking any assets`);
process.exit(0);
}
if (parseInt(process.env.VERBOSE) === 1) {
console.log(`${LOG_TAG} VERBOSE is set, logs will be more verbose`);
verbose = true;
}
const CONFIG_FILE_NAME = 'mempool-frontend-config.json'; const CONFIG_FILE_NAME = 'mempool-frontend-config.json';
let configContent = {}; let configContent = {};
@ -8,6 +21,13 @@ let configContent = {};
var PATH; var PATH;
if (process.argv[2]) { if (process.argv[2]) {
PATH = process.argv[2]; PATH = process.argv[2];
PATH += PATH.endsWith("/") ? "" : "/"
PATH = path.normalize(PATH);
console.log(`[sync-assets] using PATH ${PATH}`);
if (!fs.existsSync(PATH)){
console.log(`${LOG_TAG} ${PATH} does not exist, creating`);
fs.mkdirSync(PATH, { recursive: true });
}
} }
if (!PATH) { if (!PATH) {
@ -17,12 +37,12 @@ if (!PATH) {
try { try {
const rawConfig = fs.readFileSync(CONFIG_FILE_NAME); const rawConfig = fs.readFileSync(CONFIG_FILE_NAME);
configContent = JSON.parse(rawConfig); configContent = JSON.parse(rawConfig);
console.log(`${CONFIG_FILE_NAME} file found, using provided config`); console.log(`${LOG_TAG} ${CONFIG_FILE_NAME} file found, using provided config`);
} catch (e) { } catch (e) {
if (e.code !== 'ENOENT') { if (e.code !== 'ENOENT') {
throw new Error(e); throw new Error(e);
} else { } else {
console.log(`${CONFIG_FILE_NAME} file not found, using default config`); console.log(`${LOG_TAG} ${CONFIG_FILE_NAME} file not found, using default config`);
} }
} }
@ -37,6 +57,11 @@ function download(filename, url) {
}) })
.on('error', function(e) { .on('error', function(e) {
throw new Error(e); throw new Error(e);
})
.on('finish', () => {
if (verbose) {
console.log(`${LOG_TAG} Finished downloading ${url} to ${filename}`);
}
}); });
} }
@ -44,12 +69,18 @@ function getLocalHash(filePath) {
const size = fs.statSync(filePath); const size = fs.statSync(filePath);
const buffer = fs.readFileSync(filePath); const buffer = fs.readFileSync(filePath);
const bufferWithHeader = Buffer.concat([Buffer.from('blob '), Buffer.from(`${size.size}`), Buffer.from('\0'), buffer]); const bufferWithHeader = Buffer.concat([Buffer.from('blob '), Buffer.from(`${size.size}`), Buffer.from('\0'), buffer]);
return crypto.createHash('sha1').update(bufferWithHeader).digest('hex'); const hash = crypto.createHash('sha1').update(bufferWithHeader).digest('hex');
if (verbose) {
console.log(`${LOG_TAG} \tgetLocalHash ${filePath} ${hash}`);
}
return hash;
} }
function downloadMiningPoolLogos$() { function downloadMiningPoolLogos$() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log('Checking if mining pool logos needs downloading or updating...'); console.log(`${LOG_TAG} Checking if mining pool logos needs downloading or updating...`);
const options = { const options = {
host: 'api.github.com', host: 'api.github.com',
path: '/repos/mempool/mining-pool-logos/contents/', path: '/repos/mempool/mining-pool-logos/contents/',
@ -58,7 +89,7 @@ function downloadMiningPoolLogos$() {
}; };
if (githubSecret) { if (githubSecret) {
console.log('Downloading the mining pool logos with authentication'); console.log(`${LOG_TAG} Downloading the mining pool logos with authentication`);
options.headers['authorization'] = `Bearer ${githubSecret}`; options.headers['authorization'] = `Bearer ${githubSecret}`;
options.headers['X-GitHub-Api-Version'] = '2022-11-28'; options.headers['X-GitHub-Api-Version'] = '2022-11-28';
} }
@ -79,21 +110,29 @@ function downloadMiningPoolLogos$() {
} }
let downloadedCount = 0; let downloadedCount = 0;
for (const poolLogo of poolLogos) { for (const poolLogo of poolLogos) {
const filePath = `${PATH}/mining-pools/${poolLogo.name}`; const filePath = PATH + `mining-pools/${poolLogo.name}`;
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
const localHash = getLocalHash(filePath); const localHash = getLocalHash(filePath);
if (verbose) {
console.log(`${LOG_TAG} Remote ${poolLogo.name} logo hash ${poolLogo.sha}`);
console.log(`${LOG_TAG} \tchecking if ${filePath} exists: ${fs.existsSync(filePath)}`);
}
if (localHash !== poolLogo.sha) { if (localHash !== poolLogo.sha) {
console.log(`${poolLogo.name} is different on the remote, downloading...`); console.log(`${LOG_TAG} \t\t${poolLogo.name} is different on the remote, downloading...`);
download(filePath, poolLogo.download_url); download(filePath, poolLogo.download_url);
downloadedCount++; downloadedCount++;
} }
} else { } else {
console.log(`${poolLogo.name} is missing, downloading...`); console.log(`${LOG_TAG} ${poolLogo.name} is missing, downloading...`);
const miningPoolsDir = PATH + `mining-pools/`;
if (!fs.existsSync(miningPoolsDir)){
fs.mkdirSync(miningPoolsDir, { recursive: true });
}
download(filePath, poolLogo.download_url); download(filePath, poolLogo.download_url);
downloadedCount++; downloadedCount++;
} }
} }
console.log(`Downloaded ${downloadedCount} and skipped ${poolLogos.length - downloadedCount} existing mining pool logos`); console.log(`${LOG_TAG} Downloaded ${downloadedCount} and skipped ${poolLogos.length - downloadedCount} existing mining pool logos`);
resolve(); resolve();
} catch (e) { } catch (e) {
reject(`Unable to download mining pool logos. Trying again at next restart. Reason: ${e instanceof Error ? e.message : e}`); reject(`Unable to download mining pool logos. Trying again at next restart. Reason: ${e instanceof Error ? e.message : e}`);
@ -109,7 +148,7 @@ function downloadMiningPoolLogos$() {
function downloadPromoVideoSubtiles$() { function downloadPromoVideoSubtiles$() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log('Checking if promo video subtitles needs downloading or updating...'); console.log(`${LOG_TAG} Checking if promo video subtitles needs downloading or updating...`);
const options = { const options = {
host: 'api.github.com', host: 'api.github.com',
path: '/repos/mempool/mempool-promo/contents/subtitles', path: '/repos/mempool/mempool-promo/contents/subtitles',
@ -118,7 +157,7 @@ function downloadPromoVideoSubtiles$() {
}; };
if (githubSecret) { if (githubSecret) {
console.log('Downloading the promo video subtitles with authentication'); console.log(`${LOG_TAG} Downloading the promo video subtitles with authentication`);
options.headers['authorization'] = `Bearer ${githubSecret}`; options.headers['authorization'] = `Bearer ${githubSecret}`;
options.headers['X-GitHub-Api-Version'] = '2022-11-28'; options.headers['X-GitHub-Api-Version'] = '2022-11-28';
} }
@ -140,21 +179,30 @@ function downloadPromoVideoSubtiles$() {
} }
let downloadedCount = 0; let downloadedCount = 0;
for (const language of videoLanguages) { for (const language of videoLanguages) {
const filePath = `${PATH}/promo-video/${language.name}`; const filePath = PATH + `promo-video/${language.name}`;
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
if (verbose) {
console.log(`${LOG_TAG} ${language.name} remote promo video hash ${language.sha}`);
}
const localHash = getLocalHash(filePath); const localHash = getLocalHash(filePath);
if (localHash !== language.sha) { if (localHash !== language.sha) {
console.log(`${language.name} is different on the remote, updating`); console.log(`${LOG_TAG} ${language.name} is different on the remote, updating`);
download(filePath, language.download_url); download(filePath, language.download_url);
downloadedCount++; downloadedCount++;
} }
} else { } else {
console.log(`${language.name} is missing, downloading`); console.log(`${LOG_TAG} ${language.name} is missing, downloading`);
const promoVideosDir = PATH + `promo-video/`;
if (!fs.existsSync(promoVideosDir)){
fs.mkdirSync(promoVideosDir, { recursive: true });
}
download(filePath, language.download_url); download(filePath, language.download_url);
downloadedCount++; downloadedCount++;
} }
} }
console.log(`Downloaded ${downloadedCount} and skipped ${videoLanguages.length - downloadedCount} existing video subtitles`); console.log(`${LOG_TAG} Downloaded ${downloadedCount} and skipped ${videoLanguages.length - downloadedCount} existing video subtitles`);
resolve(); resolve();
} catch (e) { } catch (e) {
reject(`Unable to download video subtitles. Trying again at next restart. Reason: ${e instanceof Error ? e.message : e}`); reject(`Unable to download video subtitles. Trying again at next restart. Reason: ${e instanceof Error ? e.message : e}`);
@ -170,7 +218,7 @@ function downloadPromoVideoSubtiles$() {
function downloadPromoVideo$() { function downloadPromoVideo$() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
console.log('Checking if promo video needs downloading or updating...'); console.log(`${LOG_TAG} Checking if promo video needs downloading or updating...`);
const options = { const options = {
host: 'api.github.com', host: 'api.github.com',
path: '/repos/mempool/mempool-promo/contents', path: '/repos/mempool/mempool-promo/contents',
@ -179,7 +227,7 @@ function downloadPromoVideo$() {
}; };
if (githubSecret) { if (githubSecret) {
console.log('Downloading the promo videos with authentication'); console.log(`${LOG_TAG} Downloading the promo video with authentication`);
options.headers['authorization'] = `Bearer ${githubSecret}`; options.headers['authorization'] = `Bearer ${githubSecret}`;
options.headers['X-GitHub-Api-Version'] = '2022-11-28'; options.headers['X-GitHub-Api-Version'] = '2022-11-28';
} }
@ -202,18 +250,19 @@ function downloadPromoVideo$() {
if (item.name !== 'promo.mp4') { if (item.name !== 'promo.mp4') {
continue; continue;
} }
const filePath = `${PATH}/promo-video/mempool-promo.mp4`; const filePath = PATH + `promo-video/mempool-promo.mp4`;
if (fs.existsSync(filePath)) { if (fs.existsSync(filePath)) {
const localHash = getLocalHash(filePath); const localHash = getLocalHash(filePath);
if (localHash !== item.sha) { if (localHash !== item.sha) {
console.log(`mempool-promo.mp4 is different on the remote, updating`); console.log(`${LOG_TAG} \tmempool-promo.mp4 is different on the remote, updating`);
download(filePath, item.download_url); download(filePath, item.download_url);
console.log('mempool-promo.mp4 downloaded.'); console.log(`${LOG_TAG} \tmempool-promo.mp4 downloaded.`);
} else { } else {
console.log(`mempool-promo.mp4 is already up to date. Skipping.`); console.log(`${LOG_TAG} \tmempool-promo.mp4 is already up to date. Skipping.`);
} }
} else { } else {
console.log(`mempool-promo.mp4 is missing, downloading`); console.log(`${LOG_TAG} \tmempool-promo.mp4 is missing, downloading`);
download(filePath, item.download_url); download(filePath, item.download_url);
} }
} }
@ -232,30 +281,47 @@ function downloadPromoVideo$() {
} }
let assetsJsonUrl = 'https://raw.githubusercontent.com/mempool/asset_registry_db/master/index.json';
let assetsMinimalJsonUrl = 'https://raw.githubusercontent.com/mempool/asset_registry_db/master/index.minimal.json';
if (configContent.BASE_MODULE && configContent.BASE_MODULE === 'liquid') { if (configContent.BASE_MODULE && configContent.BASE_MODULE === 'liquid') {
assetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.json'; const assetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.json';
assetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.minimal.json'; const assetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_db/master/index.minimal.json';
const testnetAssetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.json';
const testnetAssetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.minimal.json';
console.log(`${LOG_TAG} Downloading assets`);
download(PATH + 'assets.json', assetsJsonUrl);
console.log(`${LOG_TAG} Downloading assets minimal`);
download(PATH + 'assets.minimal.json', assetsMinimalJsonUrl);
console.log(`${LOG_TAG} Downloading testnet assets`);
download(PATH + 'assets-testnet.json', testnetAssetsJsonUrl);
console.log(`${LOG_TAG} Downloading testnet assets minimal`);
download(PATH + 'assets-testnet.minimal.json', testnetAssetsMinimalJsonUrl);
} else {
if (verbose) {
console.log(`${LOG_TAG} BASE_MODULE is not set to Liquid (${configContent.BASE_MODULE}), skipping downloading assets`);
}
} }
const testnetAssetsJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.json'; (() => {
const testnetAssetsMinimalJsonUrl = 'https://raw.githubusercontent.com/Blockstream/asset_registry_testnet_db/master/index.minimal.json'; if (verbose) {
console.log(`${LOG_TAG} Downloading mining pool logos`);
console.log('Downloading assets'); }
download(PATH + 'assets.json', assetsJsonUrl); downloadMiningPoolLogos$()
console.log('Downloading assets minimal'); .then(() => {
download(PATH + 'assets.minimal.json', assetsMinimalJsonUrl); if (verbose) {
console.log('Downloading testnet assets'); console.log(`${LOG_TAG} Downloading promo video subtitles`);
download(PATH + 'assets-testnet.json', testnetAssetsJsonUrl); }
console.log('Downloading testnet assets minimal'); downloadPromoVideoSubtiles$();
download(PATH + 'assets-testnet.minimal.json', testnetAssetsMinimalJsonUrl); })
.then(() => {
downloadMiningPoolLogos$() if (verbose) {
.then(() => downloadPromoVideoSubtiles$()) console.log(`${LOG_TAG} Downloading promo video`);
.then(() => downloadPromoVideo$()) }
downloadPromoVideo$();
})
.catch((error) => { .catch((error) => {
throw new Error(error); throw new Error(error);
}); });
})();

View file

@ -332,7 +332,7 @@ BITCOIN_REPO_URL=https://github.com/bitcoin/bitcoin
BITCOIN_REPO_NAME=bitcoin BITCOIN_REPO_NAME=bitcoin
BITCOIN_REPO_BRANCH=master BITCOIN_REPO_BRANCH=master
#BITCOIN_LATEST_RELEASE=$(curl -s https://api.github.com/repos/bitcoin/bitcoin/releases/latest|grep tag_name|head -1|cut -d '"' -f4) #BITCOIN_LATEST_RELEASE=$(curl -s https://api.github.com/repos/bitcoin/bitcoin/releases/latest|grep tag_name|head -1|cut -d '"' -f4)
BITCOIN_LATEST_RELEASE=v25.0 BITCOIN_LATEST_RELEASE=v25.1
echo -n '.' echo -n '.'
BISQ_REPO_URL=https://github.com/bisq-network/bisq BISQ_REPO_URL=https://github.com/bisq-network/bisq
@ -1046,8 +1046,8 @@ echo "[*] Installing nvm.sh from GitHub"
osSudo "${MEMPOOL_USER}" sh -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | zsh' osSudo "${MEMPOOL_USER}" sh -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | zsh'
echo "[*] Building NodeJS v20.5.1 via nvm.sh" echo "[*] Building NodeJS v20.5.1 via nvm.sh"
osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; nvm install v20.5.1 --shared-zlib' osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; nvm install v20.7.0 --shared-zlib'
osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; nvm alias default 20.5.1' osSudo "${MEMPOOL_USER}" zsh -c 'source ~/.zshrc ; nvm alias default 20.7.0'
#################### ####################
# Tor installation # # Tor installation #
@ -1489,7 +1489,7 @@ EOF
osSudo "${UNFURL_USER}" sh -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | zsh' osSudo "${UNFURL_USER}" sh -c 'curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | zsh'
echo "[*] Building NodeJS via nvm.sh" echo "[*] Building NodeJS via nvm.sh"
osSudo "${UNFURL_USER}" zsh -c 'source ~/.zshrc ; nvm install v16.16.0 --shared-zlib' osSudo "${UNFURL_USER}" zsh -c 'source ~/.zshrc ; nvm install v20.7.0 --shared-zlib'
;; ;;
esac esac
@ -1660,15 +1660,15 @@ case $OS in
crontab_bitcoin=() crontab_bitcoin=()
if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then if [ "${BITCOIN_MAINNET_ENABLE}" = ON ];then
echo "[*] Installing Electrs Mainnet Cronjob" echo "[*] Installing Electrs Mainnet Cronjob"
crontab_bitcoin+="@reboot sleep 30 ; screen -dmS mainnet /bitcoin/electrs/electrs-start-mainnet\n" crontab_bitcoin+="@reboot sleep 30 ; screen -dmS mainnet /bitcoin/electrs/start mainnet\n"
fi fi
if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then if [ "${BITCOIN_TESTNET_ENABLE}" = ON ];then
echo "[*] Installing Electrs Testnet Cronjob" echo "[*] Installing Electrs Testnet Cronjob"
crontab_bitcoin+="@reboot sleep 70 ; screen -dmS testnet /bitcoin/electrs/electrs-start-testnet\n" crontab_bitcoin+="@reboot sleep 70 ; screen -dmS testnet /bitcoin/electrs/start testnet\n"
fi fi
if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then if [ "${BITCOIN_SIGNET_ENABLE}" = ON ];then
echo "[*] Installing Electrs Signet Cronjob" echo "[*] Installing Electrs Signet Cronjob"
crontab_bitcoin+="@reboot sleep 90 ; screen -dmS signet /bitcoin/electrs/electrs-start-signet\n" crontab_bitcoin+="@reboot sleep 90 ; screen -dmS signet /bitcoin/electrs/start signet\n"
fi fi
if [ "${BITCOIN_MAINNET_ENABLE}" = ON -o "${BITCOIN_TESTNET_ENABLE}" = ON -o "${BITCOIN_SIGNET_ENABLE}" = ON ];then if [ "${BITCOIN_MAINNET_ENABLE}" = ON -o "${BITCOIN_TESTNET_ENABLE}" = ON -o "${BITCOIN_SIGNET_ENABLE}" = ON ];then
echo "${crontab_bitcoin}" | crontab -u "${BITCOIN_USER}" - echo "${crontab_bitcoin}" | crontab -u "${BITCOIN_USER}" -

View file

@ -1,7 +1,7 @@
#!/usr/bin/env zsh #!/usr/bin/env zsh
export NVM_DIR="$HOME/.nvm" export NVM_DIR="$HOME/.nvm"
source "$NVM_DIR/nvm.sh" source "$NVM_DIR/nvm.sh"
nvm use v20.5.1 nvm use v20.7.0
# start all mempool backends that exist # start all mempool backends that exist
for site in mainnet mainnet-lightning testnet testnet-lightning signet signet-lightning bisq liquid liquidtestnet;do for site in mainnet mainnet-lightning testnet testnet-lightning signet signet-lightning bisq liquid liquidtestnet;do

View file

@ -5,3 +5,4 @@ proxy_cache_path /var/cache/nginx/slurper keys_zone=slurper:20m levels=1:2 inact
proxy_cache_path /var/cache/nginx/services keys_zone=services:20m levels=1:2 inactive=365d max_size=100m; proxy_cache_path /var/cache/nginx/services keys_zone=services:20m levels=1:2 inactive=365d max_size=100m;
proxy_cache_path /var/cache/nginx/markets keys_zone=markets:20m levels=1:2 inactive=365d max_size=100m; proxy_cache_path /var/cache/nginx/markets keys_zone=markets:20m levels=1:2 inactive=365d max_size=100m;
types_hash_max_size 4096; types_hash_max_size 4096;
proxy_buffer_size 8k;

View file

@ -0,0 +1,7 @@
for LOCATION in fmt va1 fra tk7
do
for NODE in 201 202 203 204 205 206
do
echo $(curl -sk https://node$NODE.$LOCATION.mempool.space/api/v1/backend-info)
done
done

View file

@ -1,4 +1,16 @@
const configFile = require('../config.json'); const fs = require('fs');
const path = require('path');
const configPath = process.env.UNFURLER_CONFIG || './config.json';
const absolutePath = path.resolve(configPath);
let config;
try {
config = JSON.parse(fs.readFileSync(absolutePath, 'utf8'));
} catch (e) {
console.error(`Could not read config file ${absolutePath}: ${e}`);
process.exit(-1);
}
interface IConfig { interface IConfig {
SERVER: { SERVER: {
@ -57,7 +69,7 @@ class Config implements IConfig {
SYSLOG: IConfig['SYSLOG']; SYSLOG: IConfig['SYSLOG'];
constructor() { constructor() {
const configs = this.merge(configFile, defaults); const configs = this.merge(config, defaults);
this.SERVER = configs.SERVER; this.SERVER = configs.SERVER;
this.MEMPOOL = configs.MEMPOOL; this.MEMPOOL = configs.MEMPOOL;
this.PUPPETEER = configs.PUPPETEER; this.PUPPETEER = configs.PUPPETEER;