Merge branch 'master' into nymkappa/feature/block-list-loading

This commit is contained in:
wiz
2022-05-27 18:38:36 +09:00
committed by GitHub
43 changed files with 763 additions and 988 deletions

View File

@@ -1,8 +1,30 @@
# mempool-frontend
# Mempool Frontend
## Contributing
You can build and run the Mempool frontend and proxy to the production Mempool backend (for easier frontend development), or you can connect it to your own backend for a full Mempool development instance, custom deployment, etc.
This package is used for the https://mempool.space, https://liquid.network and https://bisq.markets websites - there are npm scripts to setup all three, which effectively change how BASE_MODULE is configured:
Jump to a section in this doc:
- [Quick Setup for Frontend Development](#quick-setup-for-frontend-development)
- [Manual Frontend Setup](#manual-setup)
- [Translations](#translations-transifex-project)
## Quick Setup for Frontend Development
If you want to quickly improve the UI, fix typos, or make other updates that don't require any backend changes, you don't need to set up an entire backend—you can simply run the Mempool frontend locally and proxy to the mempool.space backend.
### 1. Clone Mempool Repository
Get the latest Mempool code:
```
git clone https://github.com/mempool/mempool
cd mempool
```
### 2. Specify Website
The same frontend codebase is used for https://mempool.space, https://liquid.network and https://bisq.markets.
Configure the frontend for the site you want by running the corresponding command:
```
$ npm run config:defaults:mempool
@@ -10,18 +32,22 @@ $ npm run config:defaults:liquid
$ npm run config:defaults:bisq
```
Changes that affect the frontend codebase only can be done using the production backend so you don't need to spin up the entire Mempool infrastructure. This is very convenient in case you want to quickly improve the UI, fix typos or implement new features that don't require any backend changes.
### 3. Run the Frontend
Make your changes, install the project dependencies and run the frontend server as follows:
_Node.js 16 and npm 7 are recommended._
Install project dependencies and run the frontend server:
```
$ npm install
$ npm run serve:local-prod
```
The frontend will be available at http://localhost:4200/ and all API requests will be proxied to the production server at https://mempool.space
The frontend will be available at http://localhost:4200/ and all API requests will be proxied to the production server at https://mempool.space.
After making your changes, you can run our end-to-end automation suite and check for possible regressions:
### 4. Test
After making your changes, you can run our end-to-end automation suite and check for possible regressions.
Headless:
@@ -37,11 +63,43 @@ $ npm run config:defaults:mempool && npm run cypress:open
This will open the Cypress test runner, where you can select any of the test files to run.
If all tests are green, submit your PR and it will be reviewed by someone on the team as soon as possible.
If all tests are green, submit your PR, and it will be reviewed by someone on the team as soon as possible.
## Manual Setup
Set up the [Mempool backend](../backend/) first, if you haven't already.
### 1. Build the Frontend
_Node.js 16 and npm 7 are recommended._
Build the frontend:
```
cd frontend
npm install # add --prod for production
npm run build
```
### 2. Run the Frontend
#### Development
To run your local Mempool frontend with your local Mempool backend:
```
npm run serve
```
#### Production
The `npm run build` command from step 1 above should have generated a `dist` directory. Put the contents of `dist/` onto your web server.
You will probably want to set up a reverse proxy, TLS, etc. There are sample nginx configuration files in the top level of the repository for reference, but note that support for such tasks is outside the scope of this project.
## Translations: Transifex Project
The mempool frontend strings are localized into 20+ locales:
The Mempool frontend strings are localized into 20+ locales:
https://www.transifex.com/mempool/mempool/dashboard/
### Translators

View File

@@ -3900,9 +3900,9 @@
}
},
"node_modules/@socket.io/component-emitter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz",
"integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
"dev": true
},
"node_modules/@tootallnate/once": {
@@ -4755,15 +4755,17 @@
}
},
"node_modules/async": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
"dev": true
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dependencies": {
"lodash": "^4.17.14"
}
},
"node_modules/async-each-series": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz",
"integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=",
"integrity": "sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==",
"dev": true,
"engines": {
"node": ">=0.8.0"
@@ -4996,12 +4998,6 @@
"@babel/core": "^7.0.0-0"
}
},
"node_modules/backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
"dev": true
},
"node_modules/balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -5254,13 +5250,13 @@
}
},
"node_modules/browser-sync": {
"version": "2.27.9",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.9.tgz",
"integrity": "sha512-3zBtggcaZIeU9so4ja9yxk7/CZu9B3DOL6zkxFpzHCHsQmkGBPVXg61jItbeoa+WXgNLnr1sYES/2yQwyEZ2+w==",
"version": "2.27.10",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.10.tgz",
"integrity": "sha512-xKm+6KJmJu6RuMWWbFkKwOCSqQOxYe3nOrFkKI5Tr/ZzjPxyU3pFShKK3tWnazBo/3lYQzN7fzjixG8fwJh1Xw==",
"dev": true,
"dependencies": {
"browser-sync-client": "^2.27.9",
"browser-sync-ui": "^2.27.9",
"browser-sync-client": "^2.27.10",
"browser-sync-ui": "^2.27.10",
"bs-recipes": "1.3.4",
"bs-snippet-injector": "^2.0.1",
"chokidar": "^3.5.1",
@@ -5277,7 +5273,7 @@
"localtunnel": "^2.0.1",
"micromatch": "^4.0.2",
"opn": "5.3.0",
"portscanner": "2.1.1",
"portscanner": "2.2.0",
"qs": "6.2.3",
"raw-body": "^2.3.2",
"resp-modifier": "6.0.2",
@@ -5298,15 +5294,16 @@
}
},
"node_modules/browser-sync-client": {
"version": "2.27.9",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.9.tgz",
"integrity": "sha512-FHW8kydp7FXo6jnX3gXJCpHAHtWNLK0nx839nnK+boMfMI1n4KZd0+DmTxHBsHsF3OHud4V4jwoN8U5HExMIdQ==",
"version": "2.27.10",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.10.tgz",
"integrity": "sha512-KCFKA1YDj6cNul0VsA28apohtBsdk5Wv8T82ClOZPZMZWxPj4Ny5AUbrj9UlAb/k6pdxE5HABrWDhP9+cjt4HQ==",
"dev": true,
"dependencies": {
"etag": "1.8.1",
"fresh": "0.5.2",
"mitt": "^1.1.3",
"rxjs": "^5.5.6"
"rxjs": "^5.5.6",
"typescript": "^4.6.2"
},
"engines": {
"node": ">=8.0.0"
@@ -5333,10 +5330,23 @@
"node": ">=0.10.0"
}
},
"node_modules/browser-sync-client/node_modules/typescript": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/browser-sync-ui": {
"version": "2.27.9",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.9.tgz",
"integrity": "sha512-rsduR2bRIwFvM8CX6iY/Nu5aWub0WB9zfSYg9Le/RV5N5DEyxJYey0VxdfWCnzDOoelassTDzYQo+r0iJno3qw==",
"version": "2.27.10",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.10.tgz",
"integrity": "sha512-elbJILq4Uo6OQv6gsvS3Y9vRAJlWu+h8j0JDkF0X/ua+3S6SVbbiWnZc8sNOFlG7yvVGIwBED3eaYQ0iBo1Dtw==",
"dev": true,
"dependencies": {
"async-each-series": "0.1.1",
@@ -7891,20 +7901,16 @@
}
},
"node_modules/engine.io-client": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.1.1.tgz",
"integrity": "sha512-V05mmDo4gjimYW+FGujoGmmmxRaDsrVr7AXA3ZIfa04MWM1jOfZfUwou0oNqhNwy/votUDvGDt4JA4QF4e0b4g==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz",
"integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.0.0",
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.0",
"has-cors": "1.1.0",
"parseqs": "0.0.6",
"parseuri": "0.0.6",
"engine.io-parser": "~5.0.3",
"ws": "~8.2.3",
"xmlhttprequest-ssl": "~2.0.0",
"yeast": "0.1.2"
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-client/node_modules/ws": {
@@ -9571,12 +9577,6 @@
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
},
"node_modules/has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
"dev": true
},
"node_modules/has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -13181,18 +13181,6 @@
"parse5": "^6.0.1"
}
},
"node_modules/parseqs": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==",
"dev": true
},
"node_modules/parseuri": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==",
"dev": true
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -13366,14 +13354,6 @@
"node": ">= 0.12.0"
}
},
"node_modules/portfinder/node_modules/async": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"dependencies": {
"lodash": "^4.17.14"
}
},
"node_modules/portfinder/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
@@ -13383,12 +13363,12 @@
}
},
"node_modules/portscanner": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz",
"integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz",
"integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==",
"dev": true,
"dependencies": {
"async": "1.5.2",
"async": "^2.6.0",
"is-number-like": "^1.0.3"
},
"engines": {
@@ -15098,29 +15078,27 @@
"devOptional": true
},
"node_modules/socket.io-client": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.4.1.tgz",
"integrity": "sha512-N5C/L5fLNha5Ojd7Yeb/puKcPWWcoB/A09fEjjNsg91EDVr5twk/OEyO6VT9dlLSUNY85NpW6KBhVMvaLKQ3vQ==",
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.0.0",
"backo2": "~1.0.2",
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.1.1",
"parseuri": "0.0.6",
"socket.io-parser": "~4.1.1"
"engine.io-client": "~6.2.1",
"socket.io-parser": "~4.2.0"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-client/node_modules/socket.io-parser": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.2.tgz",
"integrity": "sha512-j3kk71QLJuyQ/hh5F/L2t1goqzdTL0gvDzuhTuNSwihfuFUrcSji0qFZmJJPtG6Rmug153eOPsUizeirf1IIog==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz",
"integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==",
"dev": true,
"dependencies": {
"@socket.io/component-emitter": "~3.0.0",
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
@@ -17264,12 +17242,6 @@
"fd-slicer": "~1.1.0"
}
},
"node_modules/yeast": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
"dev": true
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
@@ -20020,9 +19992,9 @@
"devOptional": true
},
"@socket.io/component-emitter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.0.0.tgz",
"integrity": "sha512-2pTGuibAXJswAPJjaKisthqS/NOK5ypG4LYT6tEAV0S/mxW0zOIvYvGK0V8w8+SHxAm6vRMSjqSalFXeBAqs+Q==",
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz",
"integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==",
"dev": true
},
"@tootallnate/once": {
@@ -20794,15 +20766,17 @@
"optional": true
},
"async": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=",
"dev": true
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"requires": {
"lodash": "^4.17.14"
}
},
"async-each-series": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-0.1.1.tgz",
"integrity": "sha1-dhfBkXQB/Yykooqtzj266Yr+tDI=",
"integrity": "sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==",
"dev": true
},
"asynckit": {
@@ -20976,12 +20950,6 @@
"@babel/helper-define-polyfill-provider": "^0.3.1"
}
},
"backo2": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
"integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=",
"dev": true
},
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
@@ -21210,13 +21178,13 @@
}
},
"browser-sync": {
"version": "2.27.9",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.9.tgz",
"integrity": "sha512-3zBtggcaZIeU9so4ja9yxk7/CZu9B3DOL6zkxFpzHCHsQmkGBPVXg61jItbeoa+WXgNLnr1sYES/2yQwyEZ2+w==",
"version": "2.27.10",
"resolved": "https://registry.npmjs.org/browser-sync/-/browser-sync-2.27.10.tgz",
"integrity": "sha512-xKm+6KJmJu6RuMWWbFkKwOCSqQOxYe3nOrFkKI5Tr/ZzjPxyU3pFShKK3tWnazBo/3lYQzN7fzjixG8fwJh1Xw==",
"dev": true,
"requires": {
"browser-sync-client": "^2.27.9",
"browser-sync-ui": "^2.27.9",
"browser-sync-client": "^2.27.10",
"browser-sync-ui": "^2.27.10",
"bs-recipes": "1.3.4",
"bs-snippet-injector": "^2.0.1",
"chokidar": "^3.5.1",
@@ -21233,7 +21201,7 @@
"localtunnel": "^2.0.1",
"micromatch": "^4.0.2",
"opn": "5.3.0",
"portscanner": "2.1.1",
"portscanner": "2.2.0",
"qs": "6.2.3",
"raw-body": "^2.3.2",
"resp-modifier": "6.0.2",
@@ -21343,15 +21311,16 @@
}
},
"browser-sync-client": {
"version": "2.27.9",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.9.tgz",
"integrity": "sha512-FHW8kydp7FXo6jnX3gXJCpHAHtWNLK0nx839nnK+boMfMI1n4KZd0+DmTxHBsHsF3OHud4V4jwoN8U5HExMIdQ==",
"version": "2.27.10",
"resolved": "https://registry.npmjs.org/browser-sync-client/-/browser-sync-client-2.27.10.tgz",
"integrity": "sha512-KCFKA1YDj6cNul0VsA28apohtBsdk5Wv8T82ClOZPZMZWxPj4Ny5AUbrj9UlAb/k6pdxE5HABrWDhP9+cjt4HQ==",
"dev": true,
"requires": {
"etag": "1.8.1",
"fresh": "0.5.2",
"mitt": "^1.1.3",
"rxjs": "^5.5.6"
"rxjs": "^5.5.6",
"typescript": "^4.6.2"
},
"dependencies": {
"rxjs": {
@@ -21368,13 +21337,19 @@
"resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.0.1.tgz",
"integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=",
"dev": true
},
"typescript": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
"integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
"dev": true
}
}
},
"browser-sync-ui": {
"version": "2.27.9",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.9.tgz",
"integrity": "sha512-rsduR2bRIwFvM8CX6iY/Nu5aWub0WB9zfSYg9Le/RV5N5DEyxJYey0VxdfWCnzDOoelassTDzYQo+r0iJno3qw==",
"version": "2.27.10",
"resolved": "https://registry.npmjs.org/browser-sync-ui/-/browser-sync-ui-2.27.10.tgz",
"integrity": "sha512-elbJILq4Uo6OQv6gsvS3Y9vRAJlWu+h8j0JDkF0X/ua+3S6SVbbiWnZc8sNOFlG7yvVGIwBED3eaYQ0iBo1Dtw==",
"dev": true,
"requires": {
"async-each-series": "0.1.1",
@@ -23395,20 +23370,16 @@
}
},
"engine.io-client": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.1.1.tgz",
"integrity": "sha512-V05mmDo4gjimYW+FGujoGmmmxRaDsrVr7AXA3ZIfa04MWM1jOfZfUwou0oNqhNwy/votUDvGDt4JA4QF4e0b4g==",
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.2.2.tgz",
"integrity": "sha512-8ZQmx0LQGRTYkHuogVZuGSpDqYZtCM/nv8zQ68VZ+JkOpazJ7ICdsSpaO6iXwvaU30oFg5QJOJWj8zWqhbKjkQ==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.0.0",
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.0.0",
"has-cors": "1.1.0",
"parseqs": "0.0.6",
"parseuri": "0.0.6",
"engine.io-parser": "~5.0.3",
"ws": "~8.2.3",
"xmlhttprequest-ssl": "~2.0.0",
"yeast": "0.1.2"
"xmlhttprequest-ssl": "~2.0.0"
},
"dependencies": {
"ws": {
@@ -24622,12 +24593,6 @@
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
},
"has-cors": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz",
"integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=",
"dev": true
},
"has-flag": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
@@ -27435,18 +27400,6 @@
"parse5": "^6.0.1"
}
},
"parseqs": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz",
"integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==",
"dev": true
},
"parseuri": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz",
"integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==",
"dev": true
},
"parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
@@ -27576,14 +27529,6 @@
"mkdirp": "^0.5.5"
},
"dependencies": {
"async": {
"version": "2.6.4",
"resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
"integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
"requires": {
"lodash": "^4.17.14"
}
},
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
@@ -27595,12 +27540,12 @@
}
},
"portscanner": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.1.1.tgz",
"integrity": "sha1-6rtAnk3iSVD1oqUW01rnaTQ/u5Y=",
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz",
"integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==",
"dev": true,
"requires": {
"async": "1.5.2",
"async": "^2.6.0",
"is-number-like": "^1.0.3"
}
},
@@ -28879,26 +28824,24 @@
"devOptional": true
},
"socket.io-client": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.4.1.tgz",
"integrity": "sha512-N5C/L5fLNha5Ojd7Yeb/puKcPWWcoB/A09fEjjNsg91EDVr5twk/OEyO6VT9dlLSUNY85NpW6KBhVMvaLKQ3vQ==",
"version": "4.5.1",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.5.1.tgz",
"integrity": "sha512-e6nLVgiRYatS+AHXnOnGi4ocOpubvOUCGhyWw8v+/FxW8saHkinG6Dfhi9TU0Kt/8mwJIAASxvw6eujQmjdZVA==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.0.0",
"backo2": "~1.0.2",
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.1.1",
"parseuri": "0.0.6",
"socket.io-parser": "~4.1.1"
"engine.io-client": "~6.2.1",
"socket.io-parser": "~4.2.0"
},
"dependencies": {
"socket.io-parser": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.1.2.tgz",
"integrity": "sha512-j3kk71QLJuyQ/hh5F/L2t1goqzdTL0gvDzuhTuNSwihfuFUrcSji0qFZmJJPtG6Rmug153eOPsUizeirf1IIog==",
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.0.tgz",
"integrity": "sha512-tLfmEwcEwnlQTxFB7jibL/q2+q8dlVQzj4JdRLJ/W/G1+Fu9VSxCx1Lo+n1HvXxKnM//dUuD0xgiA7tQf57Vng==",
"dev": true,
"requires": {
"@socket.io/component-emitter": "~3.0.0",
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
}
}
@@ -30543,12 +30486,6 @@
"fd-slicer": "~1.1.0"
}
},
"yeast": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz",
"integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=",
"dev": true
},
"yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",

View File

@@ -7,7 +7,6 @@ import { AddressComponent } from './components/address/address.component';
import { MasterPageComponent } from './components/master-page/master-page.component';
import { AboutComponent } from './components/about/about.component';
import { StatusViewComponent } from './components/status-view/status-view.component';
import { LatestBlocksComponent } from './components/latest-blocks/latest-blocks.component';
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-policy.component';
import { TrademarkPolicyComponent } from './components/trademark-policy/trademark-policy.component';
@@ -36,19 +35,20 @@ let routes: Routes = [
component: MasterPageComponent,
children: [
{
path: 'tx/push',
component: PushTransactionComponent,
path: 'mining/blocks',
redirectTo: 'blocks',
pathMatch: 'full'
},
{
path: 'blocks',
component: LatestBlocksComponent,
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'mining/blocks',
path: 'blocks',
component: BlocksList,
},
{
@@ -115,6 +115,11 @@ let routes: Routes = [
{
path: 'signet',
children: [
{
path: 'mining/blocks',
redirectTo: 'blocks',
pathMatch: 'full'
},
{
path: '',
pathMatch: 'full',
@@ -128,16 +133,12 @@ let routes: Routes = [
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'blocks',
component: LatestBlocksComponent,
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'mining/blocks',
path: 'blocks',
component: BlocksList,
},
{
@@ -211,19 +212,20 @@ let routes: Routes = [
component: MasterPageComponent,
children: [
{
path: 'tx/push',
component: PushTransactionComponent,
path: 'mining/blocks',
redirectTo: 'blocks',
pathMatch: 'full'
},
{
path: 'blocks',
component: LatestBlocksComponent,
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'mining/blocks',
path: 'blocks',
component: BlocksList,
},
{
@@ -321,16 +323,12 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'blocks',
component: LatestBlocksComponent,
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'mining/blocks',
path: 'blocks',
component: BlocksList,
},
{
@@ -429,16 +427,12 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
path: 'tx/push',
component: PushTransactionComponent,
},
{
path: 'blocks',
component: LatestBlocksComponent,
},
{
path: 'about',
component: AboutComponent,
},
{
path: 'mining/blocks',
path: 'blocks',
component: BlocksList,
},
{

View File

@@ -7,7 +7,6 @@ import { LightweightChartsComponent } from './lightweight-charts/lightweight-cha
import { LightweightChartsAreaComponent } from './lightweight-charts-area/lightweight-charts-area.component';
import { BisqMarketComponent } from './bisq-market/bisq-market.component';
import { BisqTransactionsComponent } from './bisq-transactions/bisq-transactions.component';
import { NgbPaginationModule } from '@ng-bootstrap/ng-bootstrap';
import { BisqTransactionComponent } from './bisq-transaction/bisq-transaction.component';
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
@@ -50,7 +49,6 @@ import { CommonModule } from '@angular/common';
CommonModule,
BisqRoutingModule,
SharedModule,
NgbPaginationModule,
FontAwesomeModule,
NgxBootstrapMultiselectModule,
],

View File

@@ -250,6 +250,10 @@
<img class="image" src="/resources/profile/marina.svg" />
<span>Marina</span>
</a>
<a href="https://github.com/bitcoin-wallet/bitcoin-wallet/" target="_blank" title="Bitcoin Wallet (Schildbach)">
<img class="image" src="/resources/profile/schildbach.svg" />
<span>Schildbach</span>
</a>
</div>
</div>

View File

@@ -8,34 +8,34 @@
</button>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" ngbRadioGroup name="radioBasic" formControlName="dateSpan">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 1">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 144">
<input ngbButton type="radio" [value]="'24h'" fragment="24h"> 24h
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 3">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 432">
<input ngbButton type="radio" [value]="'3d'" fragment="3d"> 3D
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 7">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 1008">
<input ngbButton type="radio" [value]="'1w'" fragment="1w"> 1W
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 30">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 4320">
<input ngbButton type="radio" [value]="'1m'" fragment="1m"> 1M
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 90">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 12960">
<input ngbButton type="radio" [value]="'3m'" fragment="3m"> 3M
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 180">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 25920">
<input ngbButton type="radio" [value]="'6m'" fragment="6m"> 6M
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 365">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 52560">
<input ngbButton type="radio" [value]="'1y'" fragment="1y"> 1Y
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 730">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 105120">
<input ngbButton type="radio" [value]="'2y'" fragment="2y"> 2Y
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay >= 1095">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount >= 157680">
<input ngbButton type="radio" [value]="'3y'" fragment="3y"> 3Y
</label>
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.availableTimespanDay > 1095">
<label ngbButtonLabel class="btn-primary btn-sm" *ngIf="stats.blockCount > 157680">
<input ngbButton type="radio" [value]="'all'" fragment="all"> ALL
</label>
</div>

View File

@@ -76,7 +76,7 @@ export class BlockFeeRatesGraphComponent implements OnInit {
this.isLoading = true;
return this.apiService.getHistoricalBlockFeeRates$(timespan)
.pipe(
tap((data: any) => {
tap((response) => {
// Group by percentile
const seriesData = {
'Min': [],
@@ -87,15 +87,15 @@ export class BlockFeeRatesGraphComponent implements OnInit {
'90th': [],
'Max': []
};
for (const rate of data.blockFeeRates) {
for (const rate of response.body) {
const timestamp = rate.timestamp * 1000;
seriesData['Min'].push([timestamp, rate.avg_fee_0, rate.avg_height]);
seriesData['10th'].push([timestamp, rate.avg_fee_10, rate.avg_height]);
seriesData['25th'].push([timestamp, rate.avg_fee_25, rate.avg_height]);
seriesData['Median'].push([timestamp, rate.avg_fee_50, rate.avg_height]);
seriesData['75th'].push([timestamp, rate.avg_fee_75, rate.avg_height]);
seriesData['90th'].push([timestamp, rate.avg_fee_90, rate.avg_height]);
seriesData['Max'].push([timestamp, rate.avg_fee_100, rate.avg_height]);
seriesData['Min'].push([timestamp, rate.avgFee_0, rate.avgHeight]);
seriesData['10th'].push([timestamp, rate.avgFee_10, rate.avgHeight]);
seriesData['25th'].push([timestamp, rate.avgFee_25, rate.avgHeight]);
seriesData['Median'].push([timestamp, rate.avgFee_50, rate.avgHeight]);
seriesData['75th'].push([timestamp, rate.avgFee_75, rate.avgHeight]);
seriesData['90th'].push([timestamp, rate.avgFee_90, rate.avgHeight]);
seriesData['Max'].push([timestamp, rate.avgFee_100, rate.avgHeight]);
}
// Prepare chart
@@ -130,13 +130,9 @@ export class BlockFeeRatesGraphComponent implements OnInit {
});
this.isLoading = false;
}),
map((data: any) => {
const availableTimespanDay = (
(new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp)
) / 3600 / 24;
map((response) => {
return {
availableTimespanDay: availableTimespanDay,
blockCount: parseInt(response.headers.get('x-total-count'), 10),
};
}),
);

View File

@@ -71,7 +71,7 @@ export class BlockFeesGraphComponent implements OnInit {
.pipe(
tap((response) => {
this.prepareChartOptions({
blockFees: response.body.map(val => [val.timestamp * 1000, val.avg_fees / 100000000]),
blockFees: response.body.map(val => [val.timestamp * 1000, val.avgFees / 100000000]),
});
this.isLoading = false;
}),

View File

@@ -69,7 +69,7 @@ export class BlockRewardsGraphComponent implements OnInit {
.pipe(
tap((response) => {
this.prepareChartOptions({
blockRewards: response.body.map(val => [val.timestamp * 1000, val.avg_rewards / 100000000]),
blockRewards: response.body.map(val => [val.timestamp * 1000, val.avgRewards / 100000000]),
});
this.isLoading = false;
}),

View File

@@ -83,8 +83,8 @@ export class BlockSizesWeightsGraphComponent implements OnInit {
tap((response) => {
const data = response.body;
this.prepareChartOptions({
sizes: data.sizes.map(val => [val.timestamp * 1000, val.avg_size / 1000000, val.avg_height]),
weights: data.weights.map(val => [val.timestamp * 1000, val.avg_weight / 1000000, val.avg_height]),
sizes: data.sizes.map(val => [val.timestamp * 1000, val.avgSize / 1000000, val.avgHeight]),
weights: data.weights.map(val => [val.timestamp * 1000, val.avgWeight / 1000000, val.avgHeight]),
});
this.isLoading = false;
}),

View File

@@ -114,7 +114,7 @@
<td><span class="skeleton-loader"></span></td>
</tr>
</ng-template>
<tr>
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td i18n="block.miner">Miner</td>
<td *ngIf="stateService.env.MINING_DASHBOARD">
<a placement="bottom" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]" class="badge"
@@ -197,7 +197,18 @@
<app-transactions-list [transactions]="transactions" [paginated]="true"></app-transactions-list>
<ng-template [ngIf]="isLoadingTransactions">
<ng-template [ngIf]="transactionsError">
<div class="text-center">
<br>
<span i18n="error.general-loading-data">Error loading data.</span>
<br><br>
<i>{{ transactionsError.status }}: {{ transactionsError.error }}</i>
<br>
<br>
</div>
</ng-template>
<ng-template [ngIf]="isLoadingTransactions && !transactionsError">
<div class="text-center mb-4" class="tx-skeleton">
<ng-container *ngIf="(txsLoadingStatus$ | async) as txsLoadingStatus; else headerLoader">
@@ -271,9 +282,9 @@
<ng-template [ngIf]="error">
<div class="text-center">
<span i18n="block.error.loading-block-data">Error loading block data.</span>
<span i18n="error.general-loading-data">Error loading data.</span>
<br><br>
<i>{{ error.error }}</i>
<i>{{ error.code }}: {{ error.error }}</i>
</div>
</ng-template>

View File

@@ -38,6 +38,7 @@ export class BlockComponent implements OnInit, OnDestroy {
showDetails = false;
showPreviousBlocklink = true;
showNextBlocklink = true;
transactionsError: any = null;
subscription: Subscription;
keyNavigationSubscription: Subscription;
@@ -152,12 +153,13 @@ export class BlockComponent implements OnInit, OnDestroy {
this.stateService.markBlock$.next({ blockHeight: this.blockHeight });
this.isLoadingTransactions = true;
this.transactions = null;
this.transactionsError = null;
}),
debounceTime(300),
switchMap((block) => this.electrsApiService.getBlockTransactions$(block.id)
.pipe(
catchError((err) => {
console.log(err);
this.transactionsError = err;
return of([]);
}))
),
@@ -218,9 +220,16 @@ export class BlockComponent implements OnInit, OnDestroy {
const start = (page - 1) * this.itemsPerPage;
this.isLoadingTransactions = true;
this.transactions = null;
this.transactionsError = null;
target.scrollIntoView(); // works for chrome
this.electrsApiService.getBlockTransactions$(this.block.id, start)
.pipe(
catchError((err) => {
this.transactionsError = err;
return of([]);
})
)
.subscribe((transactions) => {
this.transactions = transactions;
this.isLoadingTransactions = false;

View File

@@ -1,6 +1,6 @@
<app-indexing-progress *ngIf="!widget"></app-indexing-progress>
<div class="container-xl" [class]="widget ? 'widget' : 'full-height'">
<div class="container-xl" style="min-height: 335px" [ngClass]="{'widget': widget, 'full-height': !widget, 'legacy': !indexingAvailable}">
<h1 *ngIf="!widget" class="float-left" i18n="master-page.blocks">Blocks</h1>
<div *ngIf="!widget && isLoading" class="spinner-border ml-3" role="status"></div>
@@ -9,22 +9,22 @@
<div style="min-height: 295px">
<table class="table table-borderless">
<thead>
<th class="height text-left" [class]="widget ? 'widget' : ''" i18n="latest-blocks.height">Height</th>
<th class="pool text-left" [class]="widget ? 'widget' : ''" i18n="mining.pool-name">Pool</th>
<th class="timestamp" i18n="latest-blocks.timestamp" *ngIf="!widget">Timestamp</th>
<th class="mined" i18n="latest-blocks.mined" *ngIf="!widget">Mined</th>
<th class="reward text-right" i18n="latest-blocks.reward" [class]="widget ? 'widget' : ''">Reward</th>
<th class="fees text-right" i18n="latest-blocks.fees" *ngIf="!widget">Fees</th>
<th class="txs text-right" i18n="dashboard.txs" [class]="widget ? 'widget' : ''">TXs</th>
<th class="size" i18n="latest-blocks.size" *ngIf="!widget">Size</th>
<th class="height text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" i18n="latest-blocks.height">Height</th>
<th *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}" i18n="mining.pool-name">Pool</th>
<th class="timestamp" i18n="latest-blocks.timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Timestamp</th>
<th class="mined" i18n="latest-blocks.mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Mined</th>
<th *ngIf="indexingAvailable" class="reward text-right" i18n="latest-blocks.reward" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">Reward</th>
<th *ngIf="indexingAvailable && !widget" class="fees text-right" i18n="latest-blocks.fees" [class]="indexingAvailable ? '' : 'legacy'">Fees</th>
<th *ngIf="indexingAvailable" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">TXs</th>
<th *ngIf="!indexingAvailable" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">Transactions</th>
<th class="size" i18n="latest-blocks.size" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">Size</th>
</thead>
<tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
<td class="text-left" [class]="widget ? 'widget' : ''">
<a [routerLink]="['/block' | relativeUrl, block.height]">{{ block.height
}}</a>
<a [routerLink]="['/block' | relativeUrl, block.height]">{{ block.height }}</a>
</td>
<td class="pool text-left" [class]="widget ? 'widget' : ''">
<td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<div class="tooltip-custom">
<a class="clear-link" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]">
<img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
@@ -37,19 +37,19 @@
<td class="timestamp" *ngIf="!widget">
&lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}
</td>
<td class="mined" *ngIf="!widget">
<td class="mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
<app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since>
</td>
<td class="reward text-right" [class]="widget ? 'widget' : ''">
<td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<app-amount [satoshis]="block.extras.reward" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
</td>
<td class="fees text-right" *ngIf="!widget">
<td *ngIf="indexingAvailable && !widget" class="fees text-right" [class]="indexingAvailable ? '' : 'legacy'">
<app-amount [satoshis]="block.extras.totalFees" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
</td>
<td class="txs text-right" [class]="widget ? 'widget' : ''">
<td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
{{ block.tx_count | number }}
</td>
<td class="size" *ngIf="!widget">
<td class="size" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
<div class="progress">
<div class="progress-bar progress-mempool" role="progressbar"
[ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"></div>
@@ -61,29 +61,29 @@
<ng-template #skeleton>
<tbody>
<tr *ngFor="let item of skeletonLines">
<td class="height text-left" [class]="widget ? 'widget' : ''">
<td class="height text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="pool text-left" [class]="widget ? 'widget' : ''">
<td *ngIf="indexingAvailable" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<img width="1" height="25" style="opacity: 0">
<span class="skeleton-loader" style="max-width: 125px"></span>
</td>
<td class="timestamp" *ngIf="!widget">
<td class="timestamp" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 150px"></span>
</td>
<td class="mined" *ngIf="!widget">
<td class="mined" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 125px"></span>
</td>
<td class="reward text-right" [class]="widget ? 'widget' : ''">
<td *ngIf="indexingAvailable" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="fees text-right" *ngIf="!widget">
<td *ngIf="indexingAvailable && !widget" class="fees text-right" [class]="indexingAvailable ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="txs text-right" [class]="widget ? 'widget' : ''">
<td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="size" *ngIf="!widget">
<td class="size" *ngIf="!widget" [class]="indexingAvailable ? '' : 'legacy'">
<span class="skeleton-loader"></span>
</td>
</tr>

View File

@@ -12,6 +12,9 @@
padding-left: 0px;
padding-bottom: 0px;
}
.container-xl.legacy {
max-width: 1140px;
}
.container {
max-width: 100%;
@@ -64,6 +67,9 @@ tr, td, th {
width: 10%;
}
}
.height.legacy {
width: 15%;
}
.timestamp {
width: 18%;
@@ -71,6 +77,9 @@ tr, td, th {
display: none;
}
}
.timestamp.legacy {
width: 20%;
}
.mined {
width: 13%;
@@ -78,6 +87,12 @@ tr, td, th {
display: none;
}
}
.mined.legacy {
width: 15%;
@media (max-width: 576px) {
display: table-cell;
}
}
.txs {
padding-right: 40px;
@@ -94,6 +109,10 @@ tr, td, th {
display: none;
}
}
.txs.legacy {
padding-right: 80px;
width: 10%;
}
.fees {
width: 10%;
@@ -132,6 +151,12 @@ tr, td, th {
display: none;
}
}
.size.legacy {
width: 20%;
@media (max-width: 576px) {
display: table-cell;
}
}
/* Tooltip text */
.tooltip-custom {

View File

@@ -17,6 +17,7 @@ export class BlocksList implements OnInit {
blocks$: Observable<any[]> = undefined;
indexingAvailable = false;
isLoading = true;
fromBlockHeight = undefined;
paginationMaxSize: number;
@@ -35,6 +36,9 @@ export class BlocksList implements OnInit {
}
ngOnInit(): void {
this.indexingAvailable = (this.stateService.env.BASE_MODULE === 'mempool' &&
this.stateService.env.MINING_DASHBOARD === true);
if (!this.widget) {
this.websocketService.want(['blocks']);
}
@@ -55,17 +59,19 @@ export class BlocksList implements OnInit {
this.isLoading = false;
}),
map(blocks => {
for (const block of blocks) {
// @ts-ignore: Need to add an extra field for the template
block.extras.pool.logo = `./resources/mining-pools/` +
block.extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg';
if (this.indexingAvailable) {
for (const block of blocks) {
// @ts-ignore: Need to add an extra field for the template
block.extras.pool.logo = `./resources/mining-pools/` +
block.extras.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg';
}
}
if (this.widget) {
return blocks.slice(0, 6);
}
return blocks;
}),
retryWhen(errors => errors.pipe(delayWhen(() => timer(1000))))
retryWhen(errors => errors.pipe(delayWhen(() => timer(10000))))
)
})
),
@@ -81,9 +87,11 @@ export class BlocksList implements OnInit {
return blocks[0];
}
this.blocksCount = Math.max(this.blocksCount, blocks[1][0].height) + 1;
// @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.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg';
if (this.stateService.env.MINING_DASHBOARD) {
// @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.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg';
}
acc.unshift(blocks[1][0]);
acc = acc.slice(0, this.widget ? 6 : 15);
return acc;

View File

@@ -1,4 +1,4 @@
<div style="min-height: 295px">
<div style="min-height: 335px">
<table class="table latest-adjustments">
<thead>
<tr>

View File

@@ -34,10 +34,6 @@ export class DifficultyAdjustmentsTable implements OnInit {
.pipe(
map((response) => {
const data = response.body;
const availableTimespanDay = (
(new Date().getTime() / 1000) - (data.oldestIndexedBlockTimestamp)
) / 3600 / 24;
const tableData = [];
for (let i = data.difficulty.length - 1; i > 0; --i) {
const selectedPowerOfTen: any = selectPowerOfTen(data.difficulty[i].difficulty);
@@ -53,7 +49,6 @@ export class DifficultyAdjustmentsTable implements OnInit {
this.isLoading = false;
return {
availableTimespanDay: availableTimespanDay,
difficulty: tableData.slice(0, 6),
};
}),

View File

@@ -1,7 +1,7 @@
<div class="mb-3 d-flex menu" style="padding: 0px 35px;">
<div *ngIf="stateService.env.MINING_DASHBOARD" class="mb-3 d-flex menu" style="padding: 0px 35px;">
<a routerLinkActive="active" class="btn btn-primary w-50 mr-1"
[routerLink]="['/graphs/mempool' | relativeUrl]">Mempool</a>
<div ngbDropdown *ngIf="stateService.env.MINING_DASHBOARD" class="w-50">
<div ngbDropdown class="w-50">
<button class="btn btn-primary w-100" id="dropdownBasic1" ngbDropdownToggle i18n="mining">Mining</button>
<div ngbDropdownMenu aria-labelledby="dropdownBasic1">
<a class="dropdown-item" routerLinkActive="active" [routerLink]="['/graphs/mining/pools' | relativeUrl]"

View File

@@ -1,57 +0,0 @@
<div class="container-xl">
<h1 class="float-left" i18n="master-page.blocks">Blocks</h1>
<br>
<div class="clearfix"></div>
<table class="table table-borderless" [alwaysCallback]="true" infiniteScroll [infiniteScrollDistance]="1.5" [infiniteScrollUpDistance]="1.5" [infiniteScrollThrottle]="50" (scrolled)="loadMore()">
<thead>
<th style="width: 15%;" i18n="latest-blocks.height">Height</th>
<th class="d-none d-md-block" style="width: 20%;" i18n="latest-blocks.timestamp">Timestamp</th>
<th style="width: 20%;" i18n="latest-blocks.mined">Mined</th>
<th class="d-none d-lg-block" style="width: 15%;" i18n="latest-blocks.transactions">Transactions</th>
<th style="width: 20%;" i18n="latest-blocks.size">Size</th>
</thead>
<tbody>
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
<td><a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
<td class="d-none d-md-block">&lrm;{{ block.timestamp * 1000 | date:'yyyy-MM-dd HH:mm' }}</td>
<td><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since></td>
<td class="d-none d-lg-block">{{ block.tx_count | number }}</td>
<td>
<div class="progress">
<div class="progress-bar progress-mempool {{ network$ | async }}" role="progressbar" [ngStyle]="{'width': (block.weight / stateService.env.BLOCK_WEIGHT_UNITS)*100 + '%' }"></div>
<div class="progress-text" [innerHTML]="block.size | bytes: 2"></div>
</div>
</td>
</tr>
<ng-template [ngIf]="isLoading">
<tr *ngFor="let item of [1,2,3,4,5,6,7,8,9,10]">
<td><span class="skeleton-loader"></span></td>
<td class="d-none d-md-block"><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
<td class="d-none d-lg-block"><span class="skeleton-loader"></span></td>
<td><span class="skeleton-loader"></span></td>
</tr>
<ng-container *ngIf="(blocksLoadingStatus$ | async) as blocksLoadingStatus">
<tr>
<td colspan="5">
<div class="progress progress-dark">
<div class="progress-bar progress-darklight" role="progressbar" [ngStyle]="{'width': blocksLoadingStatus + '%' }"></div>
</div>
</td>
</tr>
</ng-container>
</ng-template>
</tbody>
</table>
<ng-template [ngIf]="error">
<div class="text-center">
<span>Error loading blocks</span>
<br>
<i>{{ error.error }}</i>
</div>
</ng-template>
</div>

View File

@@ -1,14 +0,0 @@
.progress {
background-color: #2d3348;
}
@media (min-width: 768px) {
.d-md-block {
display: table-cell !important;
}
}
@media (min-width: 992px) {
.d-lg-block {
display: table-cell !important;
}
}

View File

@@ -1,140 +0,0 @@
import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { ElectrsApiService } from '../../services/electrs-api.service';
import { StateService } from '../../services/state.service';
import { Block } from '../../interfaces/electrs.interface';
import { Subscription, Observable, merge, of } from 'rxjs';
import { SeoService } from '../../services/seo.service';
import { WebsocketService } from 'src/app/services/websocket.service';
import { map } from 'rxjs/operators';
@Component({
selector: 'app-latest-blocks',
templateUrl: './latest-blocks.component.html',
styleUrls: ['./latest-blocks.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class LatestBlocksComponent implements OnInit, OnDestroy {
network$: Observable<string>;
error: any;
blocks: any[] = [];
blockSubscription: Subscription;
isLoading = true;
interval: any;
blocksLoadingStatus$: Observable<number>;
latestBlockHeight: number;
heightOfPageUntilBlocks = 150;
heightOfBlocksTableChunk = 470;
constructor(
private electrsApiService: ElectrsApiService,
public stateService: StateService,
private seoService: SeoService,
private websocketService: WebsocketService,
private cd: ChangeDetectorRef,
) { }
ngOnInit() {
this.seoService.setTitle($localize`:@@8a7b4bd44c0ac71b2e72de0398b303257f7d2f54:Blocks`);
this.websocketService.want(['blocks']);
this.network$ = merge(of(''), this.stateService.networkChanged$);
this.blocksLoadingStatus$ = this.stateService.loadingIndicators$
.pipe(
map((indicators) => indicators['blocks'] !== undefined ? indicators['blocks'] : 0)
);
this.blockSubscription = this.stateService.blocks$
.subscribe(([block]) => {
if (block === null || !this.blocks.length) {
return;
}
this.latestBlockHeight = block.height;
if (block.height === this.blocks[0].height) {
return;
}
// If we are out of sync, reload the blocks instead
if (block.height > this.blocks[0].height + 1) {
this.loadInitialBlocks();
return;
}
if (block.height <= this.blocks[0].height) {
return;
}
this.blocks.pop();
this.blocks.unshift(block);
this.cd.markForCheck();
});
this.loadInitialBlocks();
}
ngOnDestroy() {
clearInterval(this.interval);
this.blockSubscription.unsubscribe();
}
loadInitialBlocks() {
this.electrsApiService.listBlocks$()
.subscribe((blocks) => {
this.blocks = blocks;
this.isLoading = false;
this.error = undefined;
this.latestBlockHeight = blocks[0].height;
const spaceForBlocks = window.innerHeight - this.heightOfPageUntilBlocks;
const chunks = Math.ceil(spaceForBlocks / this.heightOfBlocksTableChunk) - 1;
if (chunks > 0) {
this.loadMore(chunks);
}
this.cd.markForCheck();
},
(error) => {
console.log(error);
this.error = error;
this.isLoading = false;
this.cd.markForCheck();
});
}
loadMore(chunks = 0) {
if (this.isLoading) {
return;
}
const height = this.blocks[this.blocks.length - 1].height - 1;
if (height < 0) {
return;
}
this.isLoading = true;
this.electrsApiService.listBlocks$(height)
.subscribe((blocks) => {
this.blocks = this.blocks.concat(blocks);
this.isLoading = false;
this.error = undefined;
const chunksLeft = chunks - 1;
if (chunksLeft > 0) {
this.loadMore(chunksLeft);
}
this.cd.markForCheck();
},
(error) => {
console.log(error);
this.error = error;
this.isLoading = false;
this.cd.markForCheck();
});
}
trackByBlock(index: number, block: Block) {
return block.height;
}
}

View File

@@ -51,7 +51,7 @@
<div class="card-body">
<h5 class="card-title" i18n="dashboard.latest-blocks">Latest blocks</h5>
<app-blocks-list [widget]=true></app-blocks-list>
<div><a [routerLink]="['/mining/blocks' | relativeUrl]" i18n="dashboard.view-more">View more &raquo;</a></div>
<div><a [routerLink]="['/blocks' | relativeUrl]" i18n="dashboard.view-more">View more &raquo;</a></div>
</div>
</div>
</div>

View File

@@ -136,7 +136,7 @@
</tr>
</tbody>
</table>
<div class=""><a href="" [routerLink]="[(stateService.env.MINING_DASHBOARD ? '/mining/blocks' : '/blocks') | relativeUrl]" i18n="dashboard.view-more">View more &raquo;</a></div>
<div class=""><a href="" [routerLink]="['/blocks' | relativeUrl]" i18n="dashboard.view-more">View more &raquo;</a></div>
</div>
</div>
</div>

View File

@@ -198,9 +198,7 @@
display: none;
text-align: right;
width: 20%;
@media (min-width: 376px) {
display: table-cell;
}
display: table-cell;
}
.table-cell-size {
display: none;

View File

@@ -3049,7 +3049,6 @@ export const restApiDocsData = [
"slug": "antpool"
},
...
"oldestIndexedBlockTimestamp": 1231006505,
"blockCount": 1005,
"lastEstimatedHashrate": 230086716765559200000
}`
@@ -3080,7 +3079,6 @@ export const restApiDocsData = [
},
...
],
"oldestIndexedBlockTimestamp": 1296688602,
"blockCount": 2226180,
"lastEstimatedHashrate": 602244182177430.8
}`
@@ -3834,34 +3832,34 @@ export const restApiDocsData = [
curl: [`1w`],
response: `[
{
"avg_height": 735644,
"avgHeight": 735644,
"timestamp": 1652119111,
"avg_fees": 24212890
"avgFees": 24212890
},
{
"avg_height": 735646,
"avgHeight": 735646,
"timestamp": 1652120252,
"avg_fees": 21655996
"avgFees": 21655996
},
{
"avg_height": 735648,
"avgHeight": 735648,
"timestamp": 1652121214,
"avg_fees": 20678859
"avgFees": 20678859
},
{
"avg_height": 735649,
"avgHeight": 735649,
"timestamp": 1652121757,
"avg_fees": 21020140
"avgFees": 21020140
},
{
"avg_height": 735650,
"avgHeight": 735650,
"timestamp": 1652122367,
"avg_fees": 23064200
"avgFees": 23064200
},
{
"avg_height": 735652,
"avgHeight": 735652,
"timestamp": 1652122893,
"avg_fees": 17620723
"avgFees": 17620723
},
...
]`
@@ -3872,14 +3870,14 @@ export const restApiDocsData = [
curl: [`1w`],
response: `[
{
"avg_height": 2224253,
"avgHeight": 2224253,
"timestamp": 1652346420,
"avg_fees": 211686
"avgFees": 211686
},
{
"avg_height": 2224254,
"avgHeight": 2224254,
"timestamp": 1652346850,
"avg_fees": 2565952
"avgFees": 2565952
},
...
]`
@@ -3890,14 +3888,14 @@ export const restApiDocsData = [
curl: [`1w`],
response: `[
{
"avg_height": 89978,
"avgHeight": 89978,
"timestamp": 1652346573,
"avg_fees": 1071
"avgFees": 1071
},
{
"avg_height": 89979,
"avgHeight": 89979,
"timestamp": 1652346970,
"avg_fees": 1224
"avgFees": 1224
},
...
]`
@@ -3933,29 +3931,29 @@ export const restApiDocsData = [
curl: [`1d`],
response: `[
{
"avg_height": 599992,
"avgHeight": 599992,
"timestamp": 1571438412,
"avg_rewards": 1260530933
"avgRewards": 1260530933
},
{
"avg_height": 600000,
"avgHeight": 600000,
"timestamp": 1571443398,
"avg_rewards": 1264314538
"avgRewards": 1264314538
},
{
"avg_height": 725441,
"avgHeight": 725441,
"timestamp": 1646139035,
"avg_rewards": 637067563
"avgRewards": 637067563
},
{
"avg_height": 725585,
"avgHeight": 725585,
"timestamp": 1646222444,
"avg_rewards": 646519104
"avgRewards": 646519104
},
{
"avg_height": 725727,
"avgHeight": 725727,
"timestamp": 1646308374,
"avg_rewards": 638709605
"avgRewards": 638709605
},
...
]`
@@ -3966,14 +3964,14 @@ export const restApiDocsData = [
curl: [`1d`],
response: `[
{
"avg_height": 12,
"avgHeight": 12,
"timestamp": 1296689648,
"avg_rewards": 5000000000
"avgRewards": 5000000000
},
{
"avg_height": 269,
"avgHeight": 269,
"timestamp": 1296717674,
"avg_rewards": 5000091820
"avgRewards": 5000091820
},
...
]`
@@ -3984,14 +3982,14 @@ export const restApiDocsData = [
curl: [`1d`],
response: `[
{
"avg_height": 183,
"avgHeight": 183,
"timestamp": 1598962247,
"avg_rewards": 5000000000
"avgRewards": 5000000000
},
{
"avg_height": 576,
"avgHeight": 576,
"timestamp": 1599047892,
"avg_rewards": 5000000000
"avgRewards": 5000000000
},
...
]`
@@ -4025,111 +4023,103 @@ export const restApiDocsData = [
esModule: [],
commonJS: [],
curl: [`1m`],
response: `{
"oldestIndexedBlockTimestamp": 1571434851,
"blockFeeRates": [
{
"avg_height": 732152,
"timestamp": 1650132959,
"avg_fee_0": 1,
"avg_fee_10": 2,
"avg_fee_25": 2,
"avg_fee_50": 3,
"avg_fee_75": 4,
"avg_fee_90": 8,
"avg_fee_100": 393
},
{
"avg_height": 732158,
"timestamp": 1650134432,
"avg_fee_0": 1,
"avg_fee_10": 1,
"avg_fee_25": 2,
"avg_fee_50": 4,
"avg_fee_75": 6,
"avg_fee_90": 10,
"avg_fee_100": 240
},
{
"avg_height": 732161,
"timestamp": 1650135818,
"avg_fee_0": 1,
"avg_fee_10": 1,
"avg_fee_25": 1,
"avg_fee_50": 2,
"avg_fee_75": 5,
"avg_fee_90": 8,
"avg_fee_100": 251
},
...
]
}`
response: `[
{
"avgHeight": 732152,
"timestamp": 1650132959,
"avgFee_0": 1,
"avgFee_10": 2,
"avgFee_25": 2,
"avgFee_50": 3,
"avgFee_75": 4,
"avgFee_90": 8,
"avgFee_100": 393
},
{
"avgHeight": 732158,
"timestamp": 1650134432,
"avgFee_0": 1,
"avgFee_10": 1,
"avgFee_25": 2,
"avgFee_50": 4,
"avgFee_75": 6,
"avgFee_90": 10,
"avgFee_100": 240
},
{
"avgHeight": 732161,
"timestamp": 1650135818,
"avgFee_0": 1,
"avgFee_10": 1,
"avgFee_25": 1,
"avgFee_50": 2,
"avgFee_75": 5,
"avgFee_90": 8,
"avgFee_100": 251
},
...
]`
},
codeSampleTestnet: {
esModule: [],
commonJS: [],
curl: [`1m`],
response: `{
"oldestIndexedBlockTimestamp": 1296688602,
"blockFeeRates": [
{
"avg_height": 2196306,
"timestamp": 1650360168,
"avg_fee_0": 1,
"avg_fee_10": 1,
"avg_fee_25": 1,
"avg_fee_50": 1,
"avg_fee_75": 2,
"avg_fee_90": 28,
"avg_fee_100": 2644
},
{
"avg_height": 2196308,
"timestamp": 1650361209,
"avg_fee_0": 1,
"avg_fee_10": 1,
"avg_fee_25": 1,
"avg_fee_50": 4,
"avg_fee_75": 12,
"avg_fee_90": 65,
"avg_fee_100": 102
},
...
]
}`
response: `[
{
"avgHeight": 2196306,
"timestamp": 1650360168,
"avgFee_0": 1,
"avgFee_10": 1,
"avgFee_25": 1,
"avgFee_50": 1,
"avgFee_75": 2,
"avgFee_90": 28,
"avgFee_100": 2644
},
{
"avgHeight": 2196308,
"timestamp": 1650361209,
"avgFee_0": 1,
"avgFee_10": 1,
"avgFee_25": 1,
"avgFee_50": 4,
"avgFee_75": 12,
"avgFee_90": 65,
"avgFee_100": 102
},
...
]`
},
codeSampleSignet: {
esModule: [],
commonJS: [],
curl: [`1m`],
response: `{
"oldestIndexedBlockTimestamp": 1598918400,
"blockFeeRates": [
{
"avg_height": 86620,
"timestamp": 1650360010,
"avg_fee_0": 1,
"avg_fee_10": 1,
"avg_fee_25": 1,
"avg_fee_50": 1,
"avg_fee_75": 1,
"avg_fee_90": 1,
"avg_fee_100": 1
},
{
"avg_height": 86623,
"timestamp": 1650361330,
"avg_fee_0": 1,
"avg_fee_10": 1,
"avg_fee_25": 1,
"avg_fee_50": 1,
"avg_fee_75": 1,
"avg_fee_90": 1,
"avg_fee_100": 1
},
...
]
}`
"blockFeeRates": [
{
"avgHeight": 86620,
"timestamp": 1650360010,
"avgFee_0": 1,
"avgFee_10": 1,
"avgFee_25": 1,
"avgFee_50": 1,
"avgFee_75": 1,
"avgFee_90": 1,
"avgFee_100": 1
},
{
"avgHeight": 86623,
"timestamp": 1650361330,
"avgFee_0": 1,
"avgFee_10": 1,
"avgFee_25": 1,
"avgFee_50": 1,
"avgFee_75": 1,
"avgFee_90": 1,
"avgFee_100": 1
},
...
]`
},
codeSampleLiquid: emptyCodeSample,
codeSampleLiquidTestnet: emptyCodeSample,
@@ -4163,47 +4153,47 @@ export const restApiDocsData = [
response: `{
"sizes": [
{
"avg_height": 576650,
"avgHeight": 576650,
"timestamp": 1558212081,
"avg_size": 1271404
"avgSize": 1271404
},
{
"avg_height": 576715,
"avgHeight": 576715,
"timestamp": 1558246272,
"avg_size": 1105893
"avgSize": 1105893
},
{
"avg_height": 576797,
"avgHeight": 576797,
"timestamp": 1558289379,
"avg_size": 1141071
"avgSize": 1141071
},
{
"avg_height": 576885,
"avgHeight": 576885,
"timestamp": 1558330184,
"avg_size": 1108166
"avgSize": 1108166
},
...
],
"weights": [
{
"avg_height": 576650,
"avgHeight": 576650,
"timestamp": 1558212081,
"avg_weight": 3994002
"avgWeight": 3994002
},
{
"avg_height": 576715,
"avgHeight": 576715,
"timestamp": 1558246272,
"avg_weight": 3756312
"avgWeight": 3756312
},
{
"avg_height": 576797,
"avgHeight": 576797,
"timestamp": 1558289379,
"avg_weight": 3719625
"avgWeight": 3719625
},
{
"avg_height": 576885,
"avgHeight": 576885,
"timestamp": 1558330184,
"avg_weight": 3631381
"avgWeight": 3631381
},
...
]
@@ -4216,27 +4206,27 @@ export const restApiDocsData = [
response: `{
"sizes": [
{
"avg_height": 1517188,
"avgHeight": 1517188,
"timestamp": 1558262730,
"avg_size": 25089
"avgSize": 25089
},
{
"avg_height": 1517275,
"avgHeight": 1517275,
"timestamp": 1558290933,
"avg_size": 21679
"avgSize": 21679
},
...
],
"weights": [
{
"avg_height": 1517188,
"avgHeight": 1517188,
"timestamp": 1558262730,
"avg_weight": 74921
"avgWeight": 74921
},
{
"avg_height": 1517275,
"avgHeight": 1517275,
"timestamp": 1558290933,
"avg_weight": 65164
"avgWeight": 65164
},
...
]
@@ -4249,27 +4239,27 @@ export const restApiDocsData = [
response: `{
"sizes": [
{
"avg_height": 83,
"avgHeight": 83,
"timestamp": 1598937527,
"avg_size": 329
"avgSize": 329
},
{
"avg_height": 266,
"avgHeight": 266,
"timestamp": 1598982991,
"avg_size": 330
"avgSize": 330
},
...
],
"weights": [
{
"avg_height": 83,
"avgHeight": 83,
"timestamp": 1598937527,
"avg_weight": 1209
"avgWeight": 1209
},
{
"avg_height": 266,
"avgHeight": 266,
"timestamp": 1598982991,
"avg_weight": 1212
"avgWeight": 1212
},
...
]

View File

@@ -1,14 +1,14 @@
<div class="code">
<ul ngbNav #navCodeTemplate="ngbNav" class="nav-tabs code-tab">
<li ngbNavItem *ngIf="code.codeTemplate.curl && method !== 'websocket'">
<a ngbNavLink (click)="adjustContainerHeight( $event )">cURL</a>
<ul ngbNav #navCodeTemplate="ngbNav" class="nav-tabs code-tab" role="tablist">
<li ngbNavItem *ngIf="code.codeTemplate.curl && method !== 'websocket'" role="presentation">
<a ngbNavLink (click)="adjustContainerHeight( $event )" role="tab">cURL</a>
<ng-template ngbNavContent>
<div class="subtitle"><ng-container i18n="API Docs code example">Code Example</ng-container> <app-clipboard [text]="wrapCurlTemplate(code)"></app-clipboard></div>
<pre><code [innerText]="wrapCurlTemplate(code)"></code></pre>
</ng-template>
</li>
<li ngbNavItem *ngIf="showCodeExample[network]">
<a ngbNavLink (click)="adjustContainerHeight( $event )" >CommonJS</a>
<li ngbNavItem *ngIf="showCodeExample[network]" role="presentation">
<a ngbNavLink (click)="adjustContainerHeight( $event )" role="tab">CommonJS</a>
<ng-template ngbNavContent>
<div class="subtitle"><ng-container i18n="API Docs code example">Code Example</ng-container> <app-clipboard [text]="wrapCommonJS(code)"></app-clipboard></div>
<div class="links">
@@ -17,8 +17,8 @@
<pre><code [innerText]="wrapCommonJS(code)"></code></pre>
</ng-template>
</li>
<li ngbNavItem *ngIf="showCodeExample[network]">
<a ngbNavLink (click)="adjustContainerHeight( $event )">ES Module</a>
<li ngbNavItem *ngIf="showCodeExample[network]" role="presentation">
<a ngbNavLink (click)="adjustContainerHeight( $event )" role="tab">ES Module</a>
<ng-template ngbNavContent>
<div class="subtitle"><ng-container i18n="API Docs install lib">Install Package</ng-container> <app-clipboard [text]="wrapImportTemplate()"></app-clipboard></div>
<div class="links">

View File

@@ -3,10 +3,10 @@
<h2 i18n="documentation.title">Documentation</h2>
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTab" class="nav-tabs">
<ul ngbNav #nav="ngbNav" [(activeId)]="activeTab" class="nav-tabs" role="tablist">
<li [ngbNavItem]="0" *ngIf="showFaqTab">
<a ngbNavLink [routerLink]="['/docs/faq' | relativeUrl]">FAQ</a>
<li [ngbNavItem]="0" *ngIf="showFaqTab" role="presentation">
<a ngbNavLink [routerLink]="['/docs/faq' | relativeUrl]" role="tab">FAQ</a>
<ng-template ngbNavContent>
<app-api-docs [whichTab]="'faq'"></app-api-docs>
@@ -14,8 +14,8 @@
</ng-template>
</li>
<li [ngbNavItem]="1">
<a ngbNavLink [routerLink]="['/docs/api/rest' | relativeUrl]">API - REST</a>
<li [ngbNavItem]="1" role="presentation">
<a ngbNavLink [routerLink]="['/docs/api/rest' | relativeUrl]" role="tab">API - REST</a>
<ng-template ngbNavContent>
<app-api-docs [whichTab]="'rest'"></app-api-docs>
@@ -23,8 +23,8 @@
</ng-template>
</li>
<li [ngbNavItem]="2" *ngIf="showWebSocketTab">
<a ngbNavLink [routerLink]="['/docs/api/websocket' | relativeUrl]">API - WebSocket</a>
<li [ngbNavItem]="2" *ngIf="showWebSocketTab" role="presentation">
<a ngbNavLink [routerLink]="['/docs/api/websocket' | relativeUrl]" role="tab">API - WebSocket</a>
<ng-template ngbNavContent>
<app-api-docs [whichTab]="'websocket'"></app-api-docs>

View File

@@ -76,7 +76,6 @@ export interface SinglePoolStats {
export interface PoolsStats {
blockCount: number;
lastEstimatedHashrate: number;
oldestIndexedBlockTimestamp: number;
pools: SinglePoolStats[];
}

View File

@@ -149,7 +149,7 @@ export class ApiService {
getBlocks$(from: number): Observable<BlockExtended[]> {
return this.httpClient.get<BlockExtended[]>(
this.apiBaseUrl + this.apiBasePath + `/api/v1/blocks-extras` +
this.apiBaseUrl + this.apiBasePath + `/api/v1/blocks` +
(from !== undefined ? `/${from}` : ``)
);
}
@@ -189,7 +189,7 @@ export class ApiService {
getHistoricalBlockFeeRates$(interval: string | undefined) : Observable<any> {
return this.httpClient.get<any[]>(
this.apiBaseUrl + this.apiBasePath + `/api/v1/mining/blocks/fee-rates` +
(interval !== undefined ? `/${interval}` : '')
(interval !== undefined ? `/${interval}` : ''), { observe: 'response' }
);
}

View File

@@ -1,7 +1,6 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
import { NgbCollapse, NgbCollapseModule, NgbRadioGroup, NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, faChartArea, faCogs, faCubes, faHammer, faDatabase, faExchangeAlt, faInfoCircle,
faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown,
@@ -48,7 +47,6 @@ import { TransactionsListComponent } from '../components/transactions-list/trans
import { BlockComponent } from '../components/block/block.component';
import { AddressComponent } from '../components/address/address.component';
import { SearchFormComponent } from '../components/search-form/search-form.component';
import { LatestBlocksComponent } from '../components/latest-blocks/latest-blocks.component';
import { AddressLabelsComponent } from '../components/address-labels/address-labels.component';
import { FooterComponent } from '../components/footer/footer.component';
import { TimeSpanComponent } from '../components/time-span/time-span.component';
@@ -113,7 +111,6 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index
BlockComponent,
TransactionsListComponent,
AddressComponent,
LatestBlocksComponent,
SearchFormComponent,
TimeSpanComponent,
AddressLabelsComponent,
@@ -148,11 +145,10 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index
NgbTooltipModule,
NgbButtonsModule,
NgbPaginationModule,
NgbDropdownModule,
NgbAccordionModule,
InfiniteScrollModule,
NgbTypeaheadModule,
NgbModule,
NgbDropdownModule,
NgbCollapseModule,
InfiniteScrollModule,
FontAwesomeModule,
],
providers: [
@@ -164,17 +160,16 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index
],
exports: [
RouterModule,
InfiniteScrollModule,
NgbTypeaheadModule,
NgbModule,
FontAwesomeModule,
NgbAccordionModule,
NgbNavModule,
ReactiveFormsModule,
NgbNavModule,
NgbTooltipModule,
NgbButtonsModule,
NgbPaginationModule,
NgbTypeaheadModule,
NgbDropdownModule,
NgbCollapseModule,
InfiniteScrollModule,
FontAwesomeModule,
TimeSinceComponent,
TimeUntilComponent,
ClipboardComponent,
@@ -208,7 +203,6 @@ import { IndexingProgressComponent } from '../components/indexing-progress/index
BlockComponent,
TransactionsListComponent,
AddressComponent,
LatestBlocksComponent,
SearchFormComponent,
TimeSpanComponent,
AddressLabelsComponent,

View File

@@ -398,11 +398,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">13,15</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.html</context>
<context context-type="linenumber">10,12</context>
<context context-type="linenumber">13,14</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool/pool.component.html</context>
@@ -464,10 +460,6 @@
<context context-type="sourcefile">src/app/components/difficulty-adjustments-table/difficulty-adjustments-table.component.html</context>
<context context-type="linenumber">5,7</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.html</context>
<context context-type="linenumber">9,10</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool/pool.component.html</context>
<context context-type="linenumber">212,214</context>
@@ -505,8 +497,8 @@
<context context-type="linenumber">34,36</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.html</context>
<context context-type="linenumber">12,16</context>
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">18,19</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/mempool-block/mempool-block.component.html</context>
@@ -528,14 +520,6 @@
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">4,9</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.html</context>
<context context-type="linenumber">2,7</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.ts</context>
<context context-type="linenumber">39</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/liquid-master-page/liquid-master-page.component.html</context>
<context context-type="linenumber">35,37</context>
@@ -715,7 +699,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
<context context-type="linenumber">357,361</context>
<context context-type="linenumber">361,365</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/dashboard/dashboard.component.html</context>
@@ -956,7 +940,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">245,247</context>
<context context-type="linenumber">249,251</context>
</context-group>
</trans-unit>
<trans-unit id="8fe73a4787b8068b2ba61f54ab7e0f9af2ea1fc9" datatype="html">
@@ -1008,7 +992,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">272,273</context>
<context context-type="linenumber">277,278</context>
</context-group>
<note priority="1" from="description">Transaction singular confirmation count</note>
<note priority="1" from="meaning">shared.confirmation-count.singular</note>
@@ -1036,7 +1020,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">273,274</context>
<context context-type="linenumber">278,279</context>
</context-group>
<note priority="1" from="description">Transaction plural confirmation count</note>
<note priority="1" from="meaning">shared.confirmation-count.plural</note>
@@ -1368,7 +1352,7 @@
<source>Community Alliances</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
<context context-type="linenumber">257,259</context>
<context context-type="linenumber">261,263</context>
</context-group>
<note priority="1" from="description">about.alliances</note>
</trans-unit>
@@ -1376,7 +1360,7 @@
<source>Project Translators</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
<context context-type="linenumber">273,275</context>
<context context-type="linenumber">277,279</context>
</context-group>
<note priority="1" from="description">about.translators</note>
</trans-unit>
@@ -1384,7 +1368,7 @@
<source>Project Contributors</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
<context context-type="linenumber">287,289</context>
<context context-type="linenumber">291,293</context>
</context-group>
<note priority="1" from="description">about.contributors</note>
</trans-unit>
@@ -1392,7 +1376,7 @@
<source>Project Members</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
<context context-type="linenumber">299,301</context>
<context context-type="linenumber">303,305</context>
</context-group>
<note priority="1" from="description">about.project_members</note>
</trans-unit>
@@ -1400,7 +1384,7 @@
<source>Project Maintainers</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/about/about.component.html</context>
<context context-type="linenumber">312,314</context>
<context context-type="linenumber">316,318</context>
</context-group>
<note priority="1" from="description">about.maintainers</note>
</trans-unit>
@@ -1490,7 +1474,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">280,282</context>
<context context-type="linenumber">285,287</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/dashboard/dashboard.component.html</context>
@@ -1920,7 +1904,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">15,17</context>
<context context-type="linenumber">15,16</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool/pool.component.html</context>
@@ -1963,11 +1947,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">18,20</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.html</context>
<context context-type="linenumber">13,16</context>
<context context-type="linenumber">19,21</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/mempool-block/mempool-block.component.html</context>
@@ -2109,7 +2089,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">265</context>
<context context-type="linenumber">269</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/dashboard/dashboard.component.html</context>
@@ -2257,19 +2237,23 @@
<note priority="1" from="description">Transaction Details</note>
<note priority="1" from="meaning">transaction.details</note>
</trans-unit>
<trans-unit id="56ad2f3895f350abdd3cee2d95498deb8819afac" datatype="html">
<source>Error loading block data.</source>
<trans-unit id="822972b5d47ee555d3be0c7ab9aae8090ecdf7bc" datatype="html">
<source>Error loading data.</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">274,280</context>
<context context-type="linenumber">203,205</context>
</context-group>
<note priority="1" from="description">block.error.loading-block-data</note>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.html</context>
<context context-type="linenumber">285,290</context>
</context-group>
<note priority="1" from="description">error.general-loading-data</note>
</trans-unit>
<trans-unit id="block.component.browser-title" datatype="html">
<source>Block <x id="BLOCK_HEIGHT" equiv-text="block.height"/>: <x id="BLOCK_ID" equiv-text="block.id"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/block/block.component.ts</context>
<context context-type="linenumber">146</context>
<context context-type="linenumber">147</context>
</context-group>
</trans-unit>
<trans-unit id="e70fcca5a99575cffef3ff8cbd5e69f06ffd0f1c" datatype="html">
@@ -2294,10 +2278,6 @@
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">14,15</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/latest-blocks/latest-blocks.component.html</context>
<context context-type="linenumber">11,12</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool/pool.component.html</context>
<context context-type="linenumber">214,215</context>
@@ -2316,7 +2296,7 @@
<source>TXs</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/blocks-list/blocks-list.component.html</context>
<context context-type="linenumber">18,19</context>
<context context-type="linenumber">18</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/pool/pool.component.html</context>
@@ -2890,11 +2870,11 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">144,147</context>
<context context-type="linenumber">148,151</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">255,257</context>
<context context-type="linenumber">259,261</context>
</context-group>
<note priority="1" from="description">show-all</note>
</trans-unit>
@@ -3445,7 +3425,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">276,279</context>
<context context-type="linenumber">281,284</context>
</context-group>
<note priority="1" from="description">Transaction unconfirmed state</note>
<note priority="1" from="meaning">transaction.unconfirmed</note>
@@ -3562,7 +3542,7 @@
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">265,266</context>
<context context-type="linenumber">269,270</context>
</context-group>
<note priority="1" from="description">sat</note>
<note priority="1" from="meaning">shared.sat</note>
@@ -3604,7 +3584,7 @@
<source>ScriptSig (ASM)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">100,102</context>
<context context-type="linenumber">104,106</context>
</context-group>
<note priority="1" from="description">ScriptSig (ASM)</note>
<note priority="1" from="meaning">transactions-list.scriptsig.asm</note>
@@ -3613,7 +3593,7 @@
<source>ScriptSig (HEX)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">104,107</context>
<context context-type="linenumber">108,111</context>
</context-group>
<note priority="1" from="description">ScriptSig (HEX)</note>
<note priority="1" from="meaning">transactions-list.scriptsig.hex</note>
@@ -3622,7 +3602,7 @@
<source>Witness</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">109,111</context>
<context context-type="linenumber">113,115</context>
</context-group>
<note priority="1" from="description">transactions-list.witness</note>
</trans-unit>
@@ -3630,7 +3610,7 @@
<source>P2SH redeem script</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">113,114</context>
<context context-type="linenumber">117,118</context>
</context-group>
<note priority="1" from="description">transactions-list.p2sh-redeem-script</note>
</trans-unit>
@@ -3638,7 +3618,7 @@
<source>P2TR tapscript</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">117,119</context>
<context context-type="linenumber">121,123</context>
</context-group>
<note priority="1" from="description">transactions-list.p2tr-tapscript</note>
</trans-unit>
@@ -3646,7 +3626,7 @@
<source>P2WSH witness script</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">119,121</context>
<context context-type="linenumber">123,125</context>
</context-group>
<note priority="1" from="description">transactions-list.p2wsh-witness-script</note>
</trans-unit>
@@ -3654,7 +3634,7 @@
<source>nSequence</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">124,126</context>
<context context-type="linenumber">128,130</context>
</context-group>
<note priority="1" from="description">transactions-list.nsequence</note>
</trans-unit>
@@ -3662,7 +3642,7 @@
<source>Previous output script</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">129,130</context>
<context context-type="linenumber">133,134</context>
</context-group>
<note priority="1" from="description">transactions-list.previous-output-script</note>
</trans-unit>
@@ -3670,7 +3650,7 @@
<source>Previous output type</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">133,134</context>
<context context-type="linenumber">137,138</context>
</context-group>
<note priority="1" from="description">transactions-list.previous-output-type</note>
</trans-unit>
@@ -3678,7 +3658,7 @@
<source>Peg-out to <x id="START_TAG_NG_CONTAINER" ctype="x-ng_container" equiv-text="&lt;ng-container *ngTemplateOutlet=&quot;pegOutLink&quot;&gt;"/><x id="CLOSE_TAG_NG_CONTAINER" ctype="x-ng_container" equiv-text="&lt;/ng-contain"/></source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">172,173</context>
<context context-type="linenumber">176,177</context>
</context-group>
<note priority="1" from="description">transactions-list.peg-out-to</note>
</trans-unit>
@@ -3686,7 +3666,7 @@
<source>ScriptPubKey (ASM)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">233,235</context>
<context context-type="linenumber">237,239</context>
</context-group>
<note priority="1" from="description">ScriptPubKey (ASM)</note>
<note priority="1" from="meaning">transactions-list.scriptpubkey.asm</note>
@@ -3695,11 +3675,19 @@
<source>ScriptPubKey (HEX)</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">237,240</context>
<context context-type="linenumber">241,244</context>
</context-group>
<note priority="1" from="description">ScriptPubKey (HEX)</note>
<note priority="1" from="meaning">transactions-list.scriptpubkey.hex</note>
</trans-unit>
<trans-unit id="ed46038430735e21c9b6165380ec1892e2f87791" datatype="html">
<source>Show all inputs to reveal fee data</source>
<context-group purpose="location">
<context context-type="sourcefile">src/app/components/transactions-list/transactions-list.component.html</context>
<context context-type="linenumber">271,274</context>
</context-group>
<note priority="1" from="description">transactions-list.load-to-reveal-fee-info</note>
</trans-unit>
<trans-unit id="f85c05147b720576e50336cf26f63d3b05601699" datatype="html">
<source>This transaction saved <x id="INTERPOLATION" equiv-text="{{ segwitGains.realizedGains * 100 | number: &apos;1.0-0&apos; }}"/>% on fees by using native SegWit-Bech32</source>
<context-group purpose="location">

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="-0.015 -0.015 1.03 1.03" preserveAspectRatio="xMidYMid"><defs><filter id="b"><feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation=".5"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge></filter><filter id="c"><feGaussianBlur in="SourceAlpha" result="blur-out" stdDeviation="1.3"/><feMerge><feMergeNode/><feMergeNode in="SourceGraphic"/></feMerge></filter><linearGradient id="a" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" style="stop-color:#f9b949"/><stop offset="100%" style="stop-color:#f7931a"/></linearGradient></defs><path d="M63.036 39.741c-4.274 17.143-21.637 27.576-38.782 23.301C7.116 58.768-3.317 41.404.959 24.262 5.23 7.117 22.594-3.317 39.734.957c17.144 4.274 27.576 21.64 23.302 38.784z" style="fill:url(#a)" filter="url(#b)" transform="scale(.01563)"/><path d="M46.1 27.441c.638-4.258-2.604-6.547-7.037-8.074l1.438-5.768-3.511-.875-1.4 5.616c-.923-.23-1.871-.447-2.813-.662l1.41-5.653-3.51-.875-1.438 5.766c-.764-.174-1.514-.346-2.242-.527l.004-.018-4.842-1.209-.934 3.75s2.605.597 2.55.634c1.422.355 1.679 1.296 1.636 2.042l-1.638 6.571c.098.025.225.061.365.117l-.371-.092-2.296 9.205c-.174.432-.615 1.08-1.61.834.036.051-2.551-.637-2.551-.637l-1.743 4.019 4.569 1.139c.85.213 1.683.436 2.503.646l-1.453 5.834 3.507.875 1.439-5.772c.958.26 1.888.5 2.798.726l-1.434 5.745 3.51.875 1.454-5.823c5.987 1.133 10.489.676 12.384-4.739 1.527-4.36-.076-6.875-3.226-8.515 2.294-.529 4.022-2.038 4.483-5.155zM38.08 38.69c-1.085 4.36-8.426 2.003-10.806 1.412l1.928-7.729c2.38.594 10.012 1.77 8.878 6.317zm1.086-11.312c-.99 3.966-7.1 1.951-9.082 1.457l1.748-7.01c1.982.494 8.365 1.416 7.334 5.553z" style="fill:#fff" filter="url(#c)" transform="scale(.01563)"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB