Merge branch 'master' into nymkappa/feature/zero-base-fee-tag
This commit is contained in:
		
						commit
						2c370ffccd
					
				| @ -31,6 +31,7 @@ | |||||||
|     "prefer-const": 1, |     "prefer-const": 1, | ||||||
|     "prefer-rest-params": 1, |     "prefer-rest-params": 1, | ||||||
|     "quotes": [1, "single", { "allowTemplateLiterals": true }], |     "quotes": [1, "single", { "allowTemplateLiterals": true }], | ||||||
|     "semi": 1 |     "semi": 1, | ||||||
|  |     "eqeqeq": 1 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -434,12 +434,14 @@ class NodesApi { | |||||||
|         SELECT nodes.public_key, CAST(COALESCE(nodes.capacity, 0) as INT) as capacity, CAST(COALESCE(nodes.channels, 0) as INT) as channels, |         SELECT nodes.public_key, CAST(COALESCE(nodes.capacity, 0) as INT) as capacity, CAST(COALESCE(nodes.channels, 0) as INT) as channels, | ||||||
|           nodes.alias, UNIX_TIMESTAMP(nodes.first_seen) as first_seen, UNIX_TIMESTAMP(nodes.updated_at) as updated_at, |           nodes.alias, UNIX_TIMESTAMP(nodes.first_seen) as first_seen, UNIX_TIMESTAMP(nodes.updated_at) as updated_at, | ||||||
|           geo_names_city.names as city, geo_names_country.names as country, |           geo_names_city.names as city, geo_names_country.names as country, | ||||||
|           geo_names_iso.names as iso_code, geo_names_subdivision.names as subdivision |           geo_names_iso.names as iso_code, geo_names_subdivision.names as subdivision, | ||||||
|  |           nodes.longitude, nodes.latitude, nodes.as_number, geo_names_isp.names as isp | ||||||
|         FROM nodes |         FROM nodes | ||||||
|         LEFT JOIN geo_names geo_names_country ON geo_names_country.id = nodes.country_id AND geo_names_country.type = 'country' |         LEFT JOIN geo_names geo_names_country ON geo_names_country.id = nodes.country_id AND geo_names_country.type = 'country' | ||||||
|         LEFT JOIN geo_names geo_names_city ON geo_names_city.id = nodes.city_id AND geo_names_city.type = 'city' |         LEFT JOIN geo_names geo_names_city ON geo_names_city.id = nodes.city_id AND geo_names_city.type = 'city' | ||||||
|         LEFT JOIN geo_names geo_names_iso ON geo_names_iso.id = nodes.country_id AND geo_names_iso.type = 'country_iso_code' |         LEFT JOIN geo_names geo_names_iso ON geo_names_iso.id = nodes.country_id AND geo_names_iso.type = 'country_iso_code' | ||||||
|         LEFT JOIN geo_names geo_names_subdivision on geo_names_subdivision.id = nodes.subdivision_id AND geo_names_subdivision.type = 'division' |         LEFT JOIN geo_names geo_names_subdivision on geo_names_subdivision.id = nodes.subdivision_id AND geo_names_subdivision.type = 'division' | ||||||
|  |         LEFT JOIN geo_names geo_names_isp on geo_names_isp.id = nodes.as_number AND geo_names_isp.type = 'as_organization' | ||||||
|         WHERE geo_names_country.id = ? |         WHERE geo_names_country.id = ? | ||||||
|         ORDER BY capacity DESC |         ORDER BY capacity DESC | ||||||
|       `;
 |       `;
 | ||||||
| @ -449,6 +451,7 @@ class NodesApi { | |||||||
|         rows[i].country = JSON.parse(rows[i].country); |         rows[i].country = JSON.parse(rows[i].country); | ||||||
|         rows[i].city = JSON.parse(rows[i].city); |         rows[i].city = JSON.parse(rows[i].city); | ||||||
|         rows[i].subdivision = JSON.parse(rows[i].subdivision); |         rows[i].subdivision = JSON.parse(rows[i].subdivision); | ||||||
|  |         rows[i].isp = JSON.parse(rows[i].isp); | ||||||
|       } |       } | ||||||
|       return rows; |       return rows; | ||||||
|     } catch (e) { |     } catch (e) { | ||||||
| @ -463,7 +466,8 @@ class NodesApi { | |||||||
|         SELECT nodes.public_key, CAST(COALESCE(nodes.capacity, 0) as INT) as capacity, CAST(COALESCE(nodes.channels, 0) as INT) as channels, |         SELECT nodes.public_key, CAST(COALESCE(nodes.capacity, 0) as INT) as capacity, CAST(COALESCE(nodes.channels, 0) as INT) as channels, | ||||||
|           nodes.alias, UNIX_TIMESTAMP(nodes.first_seen) as first_seen, UNIX_TIMESTAMP(nodes.updated_at) as updated_at, |           nodes.alias, UNIX_TIMESTAMP(nodes.first_seen) as first_seen, UNIX_TIMESTAMP(nodes.updated_at) as updated_at, | ||||||
|           geo_names_city.names as city, geo_names_country.names as country, |           geo_names_city.names as city, geo_names_country.names as country, | ||||||
|           geo_names_iso.names as iso_code, geo_names_subdivision.names as subdivision |           geo_names_iso.names as iso_code, geo_names_subdivision.names as subdivision, | ||||||
|  |           nodes.longitude, nodes.latitude | ||||||
|         FROM nodes |         FROM nodes | ||||||
|         LEFT JOIN geo_names geo_names_country ON geo_names_country.id = nodes.country_id AND geo_names_country.type = 'country' |         LEFT JOIN geo_names geo_names_country ON geo_names_country.id = nodes.country_id AND geo_names_country.type = 'country' | ||||||
|         LEFT JOIN geo_names geo_names_city ON geo_names_city.id = nodes.city_id AND geo_names_city.type = 'city' |         LEFT JOIN geo_names geo_names_city ON geo_names_city.id = nodes.city_id AND geo_names_city.type = 'city' | ||||||
|  | |||||||
| @ -21,6 +21,7 @@ class NodesRoutes { | |||||||
|       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/rankings/age', this.$getOldestNodes) |       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/rankings/age', this.$getOldestNodes) | ||||||
|       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/:public_key/statistics', this.$getHistoricalNodeStats) |       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/:public_key/statistics', this.$getHistoricalNodeStats) | ||||||
|       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/:public_key', this.$getNode) |       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/:public_key', this.$getNode) | ||||||
|  |       .get(config.MEMPOOL.API_URL_PREFIX + 'lightning/nodes/group/:name', this.$getNodeGroup) | ||||||
|     ; |     ; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -33,6 +34,39 @@ class NodesRoutes { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   private async $getNodeGroup(req: Request, res: Response) { | ||||||
|  |     try { | ||||||
|  |       let nodesList; | ||||||
|  |       let nodes: any[] = []; | ||||||
|  |       switch (config.MEMPOOL.NETWORK) { | ||||||
|  |         case 'testnet': | ||||||
|  |           nodesList = ['032c7c7819276c4f706a04df1a0f1e10a5495994a7be4c1d3d28ca766e5a2b957b', '025a7e38c2834dd843591a4d23d5f09cdeb77ddca85f673c2d944a14220ff14cf7', '0395e2731a1673ef21d7a16a727c4fc4d4c35a861c428ce2c819c53d2b81c8bd55', '032ab2028c0b614c6d87824e2373529652fd7e4221b4c70cc4da7c7005c49afcf0', '029001b22fe70b48bee12d014df91982eb85ff1bd404ec772d5c83c4ee3e88d2c3', '0212e2848d79f928411da5f2ff0a8c95ec6ccb5a09d2031b6f71e91309dcde63af', '03e871a2229523d34f76e6311ff197cfe7f26c2fbec13554b93a46f4e710c47dab', '032202ec98d976b0e928bd1d91924e8bd3eab07231fc39feb3737b010071073df8', '02fa7c5a948d03d563a9f36940c2205a814e594d17c0042ced242c71a857d72605', '039c14fdec2d958e3d14cebf657451bbd9e039196615785e82c917f274e3fb2205', '033589bbcb233ffc416cefd5437c7f37e9d7cb7942d405e39e72c4c846d9b37f18', '029293110441c6e2eacb57e1255bf6ef05c41a6a676fe474922d33c19f98a7d584']; | ||||||
|  |           break; | ||||||
|  |         case 'signet': | ||||||
|  |           nodesList = ['03ddab321b760433cbf561b615ef62ac7d318630c5f51d523aaf5395b90b751956', '033d92c7bfd213ef1b34c90e985fb5dc77f9ec2409d391492484e57a44c4aca1de', '02ad010dda54253c1eb9efe38b0760657a3b43ecad62198c359c051c9d99d45781', '025196512905b8a3f1597428b867bec63ec9a95e5089eb7dc7e63e2d2691669029', '027c625aa1fbe3768db68ebcb05b53b6dc0ce68b7b54b8900d326d167363e684fe', '03f1629af3101fcc56b7aac2667016be84e3defbf3d0c8719f836c9b41c9a57a43', '02dfb81e2f7a3c4c9e8a51b70ef82b4a24549cc2fab1f5b2fd636501774a918991', '02d01ccf832944c68f10d39006093769c5b8bda886d561b128534e313d729fdb34', '02499ed23027d4698a6904ff4ec1b6085a61f10b9a6937f90438f9947e38e8ea86', '038310e3a786340f2bd7770704c7ccfe560fd163d9a1c99d67894597419d12cbf7', '03e5e9d879b72c7d67ecd483bae023bd33e695bb32b981a4021260f7b9d62bc761', '028d16e1a0ace4c0c0a421536d8d32ce484dfe6e2f726b7b0e7c30f12a195f8cc7']; | ||||||
|  |           break; | ||||||
|  |         default: | ||||||
|  |           nodesList = ['03fbc17549ec667bccf397ababbcb4cdc0e3394345e4773079ab2774612ec9be61', '03da9a8623241ccf95f19cd645c6cecd4019ac91570e976eb0a128bebbc4d8a437', '03ca5340cf85cb2e7cf076e489f785410838de174e40be62723e8a60972ad75144', '0238bd27f02d67d6c51e269692bc8c9a32357a00e7777cba7f4f1f18a2a700b108', '03f983dcabed6baa1eab5b56c8b2e8fdc846ab3fd931155377897335e85a9fa57c', '03e399589533581e48796e29a825839a010036a61b20744fda929d6709fcbffcc5', '021f5288b5f72c42cd0d8801086af7ce09a816d8ee9a4c47a4b436399b26cb601a', '032b01b7585f781420cd4148841a82831ba37fa952342052cec16750852d4f2dd9', '02848036488d4b8fb1f1c4064261ec36151f43b085f0b51bd239ade3ddfc940c34', '02b6b1640fe029e304c216951af9fbefdb23b0bdc9baaf327540d31b6107841fdf', '03694289827203a5b3156d753071ddd5bf92e371f5a462943f9555eef6d2d6606c', '0283d850db7c3e8ea7cc9c4abc7afaab12bbdf72b677dcba1d608350d2537d7d43']; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       for (let pubKey of nodesList) { | ||||||
|  |         try { | ||||||
|  |           const node = await nodesApi.$getNode(pubKey); | ||||||
|  |           if (node) { | ||||||
|  |             nodes.push(node); | ||||||
|  |           } | ||||||
|  |         } catch (e) {} | ||||||
|  |       } | ||||||
|  |        | ||||||
|  |       res.header('Pragma', 'public'); | ||||||
|  |       res.header('Cache-control', 'public'); | ||||||
|  |       res.setHeader('Expires', new Date(Date.now() + 1000 * 60).toUTCString()); | ||||||
|  |       res.json(nodes); | ||||||
|  |     } catch (e) { | ||||||
|  |       res.status(500).send(e instanceof Error ? e.message : e); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|   private async $getNode(req: Request, res: Response) { |   private async $getNode(req: Request, res: Response) { | ||||||
|     try { |     try { | ||||||
|       const node = await nodesApi.$getNode(req.params.public_key); |       const node = await nodesApi.$getNode(req.params.public_key); | ||||||
|  | |||||||
| @ -124,7 +124,7 @@ async function buildIncompleteChannel(clChannel: any): Promise<ILightningApi.Cha | |||||||
|  */ |  */ | ||||||
| function convertPolicy(clChannel: any): ILightningApi.RoutingPolicy { | function convertPolicy(clChannel: any): ILightningApi.RoutingPolicy { | ||||||
|   return { |   return { | ||||||
|     time_lock_delta: 0, // TODO
 |     time_lock_delta: clChannel.delay, | ||||||
|     min_htlc: clChannel.htlc_minimum_msat.slice(0, -4), |     min_htlc: clChannel.htlc_minimum_msat.slice(0, -4), | ||||||
|     max_htlc_msat: clChannel.htlc_maximum_msat.slice(0, -4), |     max_htlc_msat: clChannel.htlc_maximum_msat.slice(0, -4), | ||||||
|     fee_base_msat: clChannel.base_fee_millisatoshi, |     fee_base_msat: clChannel.base_fee_millisatoshi, | ||||||
|  | |||||||
							
								
								
									
										3
									
								
								contributors/WesVleuten.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								contributors/WesVleuten.txt
									
									
									
									
									
										Normal 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 September 1, 2022. | ||||||
|  | 
 | ||||||
|  | Signed: WesVleuten | ||||||
| @ -403,7 +403,7 @@ Corresponding `docker-compose.yml` overrides: | |||||||
| 
 | 
 | ||||||
| `mempool-config.json`: | `mempool-config.json`: | ||||||
| ``` | ``` | ||||||
|   "CLN": { |   "CLIGHTNING": { | ||||||
|     "SOCKET": "" |     "SOCKET": "" | ||||||
|   } |   } | ||||||
| ``` | ``` | ||||||
| @ -412,6 +412,6 @@ Corresponding `docker-compose.yml` overrides: | |||||||
| ``` | ``` | ||||||
|   api: |   api: | ||||||
|     environment: |     environment: | ||||||
|       CLN_SOCKET: "" |       CLIGHTNING_SOCKET: "" | ||||||
|       ... |       ... | ||||||
| ``` | ``` | ||||||
|  | |||||||
| @ -67,6 +67,22 @@ | |||||||
|     "ENABLED": __BISQ_ENABLED__, |     "ENABLED": __BISQ_ENABLED__, | ||||||
|     "DATA_PATH": "__BISQ_DATA_PATH__" |     "DATA_PATH": "__BISQ_DATA_PATH__" | ||||||
|   }, |   }, | ||||||
|  |   "LIGHTNING": { | ||||||
|  |     "ENABLED": __LIGHTNING_ENABLED__, | ||||||
|  |     "BACKEND": "__LIGHTNING_BACKEND__", | ||||||
|  |     "STATS_REFRESH_INTERVAL": __LIGHTNING_STATS_REFRESH_INTERVAL__, | ||||||
|  |     "GRAPH_REFRESH_INTERVAL": __LIGHTNING_GRAPH_REFRESH_INTERVAL__, | ||||||
|  |     "LOGGER_UPDATE_INTERVAL": __LIGHTNING_LOGGER_UPDATE_INTERVAL__, | ||||||
|  |     "TOPOLOGY_FOLDER": "__LIGHTNING_TOPOLOGY_FOLDER__" | ||||||
|  |   }, | ||||||
|  |   "LND": { | ||||||
|  |     "TLS_CERT_PATH": "__LND_TLS_CERT_PATH__", | ||||||
|  |     "MACAROON_PATH": "__LND_MACAROON_PATH__", | ||||||
|  |     "REST_API_URL": "__LND_REST_API_URL__" | ||||||
|  |   }, | ||||||
|  |   "CLIGHTNING": { | ||||||
|  |     "SOCKET": "__CLIGHTNING_SOCKET__" | ||||||
|  |   }, | ||||||
|   "SOCKS5PROXY": { |   "SOCKS5PROXY": { | ||||||
|     "ENABLED": __SOCKS5PROXY_ENABLED__, |     "ENABLED": __SOCKS5PROXY_ENABLED__, | ||||||
|     "USE_ONION": __SOCKS5PROXY_USE_ONION__, |     "USE_ONION": __SOCKS5PROXY_USE_ONION__, | ||||||
|  | |||||||
| @ -105,7 +105,7 @@ __LND_MACAROON_PATH__=${LND_MACAROON_PATH:=""} | |||||||
| __LND_REST_API_URL__=${LND_REST_API_URL:="https://localhost:8080"} | __LND_REST_API_URL__=${LND_REST_API_URL:="https://localhost:8080"} | ||||||
| 
 | 
 | ||||||
| # CLN | # CLN | ||||||
| __CLN_SOCKET__=${CLN_SOCKET:=""} | __CLIGHTNING_SOCKET__=${CLIGHTNING_SOCKET:=""} | ||||||
| 
 | 
 | ||||||
| mkdir -p "${__MEMPOOL_CACHE_DIR__}" | mkdir -p "${__MEMPOOL_CACHE_DIR__}" | ||||||
| 
 | 
 | ||||||
| @ -132,8 +132,8 @@ sed -i "s!__MEMPOOL_USER_AGENT__!${__MEMPOOL_USER_AGENT__}!g" mempool-config.jso | |||||||
| sed -i "s/__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__/${__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__}/g" mempool-config.json | sed -i "s/__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__/${__MEMPOOL_STDOUT_LOG_MIN_PRIORITY__}/g" mempool-config.json | ||||||
| sed -i "s/__MEMPOOL_INDEXING_BLOCKS_AMOUNT__/${__MEMPOOL_INDEXING_BLOCKS_AMOUNT__}/g" mempool-config.json | sed -i "s/__MEMPOOL_INDEXING_BLOCKS_AMOUNT__/${__MEMPOOL_INDEXING_BLOCKS_AMOUNT__}/g" mempool-config.json | ||||||
| sed -i "s/__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__/${__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__}/g" mempool-config.json | sed -i "s/__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__/${__MEMPOOL_AUTOMATIC_BLOCK_REINDEXING__}/g" mempool-config.json | ||||||
| sed -i "s!__MEMPOOL_POOLS_JSON_URL__!${__MEMPOOL_POOLS_JSON_URL__}/g" mempool-config.json | sed -i "s!__MEMPOOL_POOLS_JSON_URL__!${__MEMPOOL_POOLS_JSON_URL__}!g" mempool-config.json | ||||||
| sed -i "s!__MEMPOOL_POOLS_JSON_TREE_URL__!${__MEMPOOL_POOLS_JSON_TREE_URL__}/g" mempool-config.json | sed -i "s!__MEMPOOL_POOLS_JSON_TREE_URL__!${__MEMPOOL_POOLS_JSON_TREE_URL__}!g" mempool-config.json | ||||||
| 
 | 
 | ||||||
| sed -i "s/__CORE_RPC_HOST__/${__CORE_RPC_HOST__}/g" mempool-config.json | sed -i "s/__CORE_RPC_HOST__/${__CORE_RPC_HOST__}/g" mempool-config.json | ||||||
| sed -i "s/__CORE_RPC_PORT__/${__CORE_RPC_PORT__}/g" mempool-config.json | sed -i "s/__CORE_RPC_PORT__/${__CORE_RPC_PORT__}/g" mempool-config.json | ||||||
| @ -203,6 +203,6 @@ sed -i "s!__LND_MACAROON_PATH__!${__LND_MACAROON_PATH__}!g" mempool-config.json | |||||||
| sed -i "s!__LND_REST_API_URL__!${__LND_REST_API_URL__}!g" mempool-config.json | sed -i "s!__LND_REST_API_URL__!${__LND_REST_API_URL__}!g" mempool-config.json | ||||||
| 
 | 
 | ||||||
| # CLN | # CLN | ||||||
| sed -i "s!__CLN_SOCKET__!${__CLN_SOCKET__}!g" mempool-config.json | sed -i "s!__CLIGHTNING_SOCKET__!${__CLIGHTNING_SOCKET__}!g" mempool-config.json | ||||||
| 
 | 
 | ||||||
| node /backend/package/index.js | node /backend/package/index.js | ||||||
|  | |||||||
| @ -32,6 +32,7 @@ | |||||||
|     "prefer-const": 1, |     "prefer-const": 1, | ||||||
|     "prefer-rest-params": 1, |     "prefer-rest-params": 1, | ||||||
|     "quotes": [1, "single", { "allowTemplateLiterals": true }], |     "quotes": [1, "single", { "allowTemplateLiterals": true }], | ||||||
|     "semi": 1 |     "semi": 1, | ||||||
|  |     "eqeqeq": 1 | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  | |||||||
| @ -170,6 +170,10 @@ | |||||||
|           }, |           }, | ||||||
|           "configurations": { |           "configurations": { | ||||||
|             "production": { |             "production": { | ||||||
|  |               "assets": [ | ||||||
|  |                 "src/favicon.ico", | ||||||
|  |                 "src/robots.txt" | ||||||
|  |               ], | ||||||
|               "fileReplacements": [ |               "fileReplacements": [ | ||||||
|                 { |                 { | ||||||
|                   "replace": "src/environments/environment.ts", |                   "replace": "src/environments/environment.ts", | ||||||
|  | |||||||
| @ -34,7 +34,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": "node sync-assets.js && rsync -av ./dist/mempool/browser/en-US/resources ./dist/mempool/browser/resources", |     "sync-assets": "rsync -av ./src/resources ./dist/mempool/browser && node sync-assets.js", | ||||||
|     "sync-assets-dev": "node sync-assets.js dev", |     "sync-assets-dev": "node sync-assets.js dev", | ||||||
|     "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", | ||||||
|  | |||||||
| @ -3,14 +3,10 @@ import { Routes, RouterModule } from '@angular/router'; | |||||||
| import { AppPreloadingStrategy } from './app.preloading-strategy' | import { AppPreloadingStrategy } from './app.preloading-strategy' | ||||||
| import { StartComponent } from './components/start/start.component'; | import { StartComponent } from './components/start/start.component'; | ||||||
| import { TransactionComponent } from './components/transaction/transaction.component'; | import { TransactionComponent } from './components/transaction/transaction.component'; | ||||||
| import { TransactionPreviewComponent } from './components/transaction/transaction-preview.component'; |  | ||||||
| import { BlockComponent } from './components/block/block.component'; | import { BlockComponent } from './components/block/block.component'; | ||||||
| import { BlockAuditComponent } from './components/block-audit/block-audit.component'; | import { BlockAuditComponent } from './components/block-audit/block-audit.component'; | ||||||
| import { BlockPreviewComponent } from './components/block/block-preview.component'; |  | ||||||
| import { AddressComponent } from './components/address/address.component'; | import { AddressComponent } from './components/address/address.component'; | ||||||
| import { AddressPreviewComponent } from './components/address/address-preview.component'; |  | ||||||
| import { MasterPageComponent } from './components/master-page/master-page.component'; | import { MasterPageComponent } from './components/master-page/master-page.component'; | ||||||
| import { MasterPagePreviewComponent } from './components/master-page-preview/master-page-preview.component'; |  | ||||||
| import { AboutComponent } from './components/about/about.component'; | import { AboutComponent } from './components/about/about.component'; | ||||||
| import { StatusViewComponent } from './components/status-view/status-view.component'; | import { StatusViewComponent } from './components/status-view/status-view.component'; | ||||||
| import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component'; | import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component'; | ||||||
| @ -346,61 +342,18 @@ let routes: Routes = [ | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     path: 'preview', |     path: 'preview', | ||||||
|     component: MasterPagePreviewComponent, |  | ||||||
|     children: [ |     children: [ | ||||||
|       { |       { | ||||||
|         path: 'block/:id', |         path: '', | ||||||
|         component: BlockPreviewComponent |         loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         path: 'testnet/block/:id', |         path: 'testnet', | ||||||
|         component: BlockPreviewComponent |         loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) | ||||||
|       }, |       }, | ||||||
|       { |       { | ||||||
|         path: 'signet/block/:id', |         path: 'signet', | ||||||
|         component: BlockPreviewComponent |         loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'address/:id', |  | ||||||
|         children: [], |  | ||||||
|         component: AddressPreviewComponent |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'testnet/address/:id', |  | ||||||
|         children: [], |  | ||||||
|         component: AddressPreviewComponent |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'signet/address/:id', |  | ||||||
|         children: [], |  | ||||||
|         component: AddressPreviewComponent |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'tx/:id', |  | ||||||
|         children: [], |  | ||||||
|         component: TransactionPreviewComponent |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'testnet/tx/:id', |  | ||||||
|         children: [], |  | ||||||
|         component: TransactionPreviewComponent |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'signet/tx/:id', |  | ||||||
|         children: [], |  | ||||||
|         component: TransactionPreviewComponent |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'lightning', |  | ||||||
|         loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule) |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'testnet/lightning', |  | ||||||
|         loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule) |  | ||||||
|       }, |  | ||||||
|       { |  | ||||||
|         path: 'signet/lightning', |  | ||||||
|         loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule) |  | ||||||
|       }, |       }, | ||||||
|     ], |     ], | ||||||
|   }, |   }, | ||||||
| @ -643,35 +596,14 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') { | |||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       path: 'preview', |       path: 'preview', | ||||||
|       component: MasterPagePreviewComponent, |  | ||||||
|       children: [ |       children: [ | ||||||
|         { |         { | ||||||
|           path: 'block/:id', |           path: '', | ||||||
|           component: BlockPreviewComponent |           loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) | ||||||
|         }, |         }, | ||||||
|         { |         { | ||||||
|           path: 'testnet/block/:id', |           path: 'testnet', | ||||||
|           component: BlockPreviewComponent |           loadChildren: () => import('./previews.module').then(m => m.PreviewsModule) | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           path: 'address/:id', |  | ||||||
|           children: [], |  | ||||||
|           component: AddressPreviewComponent |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           path: 'testnet/address/:id', |  | ||||||
|           children: [], |  | ||||||
|           component: AddressPreviewComponent |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           path: 'tx/:id', |  | ||||||
|           children: [], |  | ||||||
|           component: TransactionPreviewComponent |  | ||||||
|         }, |  | ||||||
|         { |  | ||||||
|           path: 'testnet/tx/:id', |  | ||||||
|           children: [], |  | ||||||
|           component: TransactionPreviewComponent |  | ||||||
|         }, |         }, | ||||||
|       ], |       ], | ||||||
|     }, |     }, | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser'; | import { BrowserModule, BrowserTransferStateModule } from '@angular/platform-browser'; | ||||||
| import { NgModule } from '@angular/core'; | import { ModuleWithProviders, NgModule } from '@angular/core'; | ||||||
| import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; | import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; | ||||||
| import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; | ||||||
| import { AppRoutingModule } from './app-routing.module'; | import { AppRoutingModule } from './app-routing.module'; | ||||||
| @ -20,6 +20,23 @@ import { ShortenStringPipe } from './shared/pipes/shorten-string-pipe/shorten-st | |||||||
| import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe'; | import { CapAddressPipe } from './shared/pipes/cap-address-pipe/cap-address-pipe'; | ||||||
| import { AppPreloadingStrategy } from './app.preloading-strategy'; | import { AppPreloadingStrategy } from './app.preloading-strategy'; | ||||||
| 
 | 
 | ||||||
|  | const providers = [ | ||||||
|  |   ElectrsApiService, | ||||||
|  |   StateService, | ||||||
|  |   WebsocketService, | ||||||
|  |   AudioService, | ||||||
|  |   SeoService, | ||||||
|  |   OpenGraphService, | ||||||
|  |   StorageService, | ||||||
|  |   EnterpriseService, | ||||||
|  |   LanguageService, | ||||||
|  |   ShortenStringPipe, | ||||||
|  |   FiatShortenerPipe, | ||||||
|  |   CapAddressPipe, | ||||||
|  |   AppPreloadingStrategy, | ||||||
|  |   { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true } | ||||||
|  | ]; | ||||||
|  | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|   declarations: [ |   declarations: [ | ||||||
|     AppComponent, |     AppComponent, | ||||||
| @ -32,22 +49,17 @@ import { AppPreloadingStrategy } from './app.preloading-strategy'; | |||||||
|     BrowserAnimationsModule, |     BrowserAnimationsModule, | ||||||
|     SharedModule, |     SharedModule, | ||||||
|   ], |   ], | ||||||
|   providers: [ |   providers: providers, | ||||||
|     ElectrsApiService, |  | ||||||
|     StateService, |  | ||||||
|     WebsocketService, |  | ||||||
|     AudioService, |  | ||||||
|     SeoService, |  | ||||||
|     OpenGraphService, |  | ||||||
|     StorageService, |  | ||||||
|     EnterpriseService, |  | ||||||
|     LanguageService, |  | ||||||
|     ShortenStringPipe, |  | ||||||
|     FiatShortenerPipe, |  | ||||||
|     CapAddressPipe, |  | ||||||
|     AppPreloadingStrategy, |  | ||||||
|     { provide: HTTP_INTERCEPTORS, useClass: HttpCacheInterceptor, multi: true } |  | ||||||
|   ], |  | ||||||
|   bootstrap: [AppComponent] |   bootstrap: [AppComponent] | ||||||
| }) | }) | ||||||
| export class AppModule { } | export class AppModule { } | ||||||
|  | 
 | ||||||
|  | @NgModule({}) | ||||||
|  | export class MempoolSharedModule{ | ||||||
|  |   static forRoot(): ModuleWithProviders<MempoolSharedModule> { | ||||||
|  |     return { | ||||||
|  |       ngModule: AppModule, | ||||||
|  |       providers: providers | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| import { Component, OnInit, OnDestroy } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { switchMap, filter, catchError } from 'rxjs/operators'; | import { switchMap, filter, catchError } from 'rxjs/operators'; | ||||||
| import { ParamMap, ActivatedRoute } from '@angular/router'; | import { ParamMap, ActivatedRoute } from '@angular/router'; | ||||||
| import { Subscription, of } from 'rxjs'; | import { Subscription, of } from 'rxjs'; | ||||||
| import { BisqTransaction } from '../bisq.interfaces'; | import { BisqTransaction } from '../bisq.interfaces'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-address', |   selector: 'app-bisq-address', | ||||||
|  | |||||||
| @ -1,14 +1,14 @@ | |||||||
| import { Component, OnInit, OnDestroy } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { BisqBlock } from 'src/app/bisq/bisq.interfaces'; | import { BisqBlock } from '../../bisq/bisq.interfaces'; | ||||||
| import { Location } from '@angular/common'; | import { Location } from '@angular/common'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { ActivatedRoute, ParamMap, Router } from '@angular/router'; | import { ActivatedRoute, ParamMap, Router } from '@angular/router'; | ||||||
| import { Subscription, of } from 'rxjs'; | import { Subscription, of } from 'rxjs'; | ||||||
| import { switchMap, catchError } from 'rxjs/operators'; | import { switchMap, catchError } from 'rxjs/operators'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { ElectrsApiService } from 'src/app/services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { HttpErrorResponse } from '@angular/common/http'; | import { HttpErrorResponse } from '@angular/common/http'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-block', |   selector: 'app-bisq-block', | ||||||
|  | |||||||
| @ -3,9 +3,9 @@ import { BisqApiService } from '../bisq-api.service'; | |||||||
| import { switchMap, map, take, mergeMap, tap } from 'rxjs/operators'; | import { switchMap, map, take, mergeMap, tap } from 'rxjs/operators'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { BisqBlock, BisqOutput, BisqTransaction } from '../bisq.interfaces'; | import { BisqBlock, BisqOutput, BisqTransaction } from '../bisq.interfaces'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { ActivatedRoute, Router } from '@angular/router'; | import { ActivatedRoute, Router } from '@angular/router'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-blocks', |   selector: 'app-bisq-blocks', | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | ||||||
| import { Observable, combineLatest, BehaviorSubject, of } from 'rxjs'; | import { Observable, combineLatest, BehaviorSubject, of } from 'rxjs'; | ||||||
| import { map, share, switchMap } from 'rxjs/operators'; | import { map, share, switchMap } from 'rxjs/operators'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { Trade } from '../bisq.interfaces'; | import { Trade } from '../bisq.interfaces'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | ||||||
| import { Observable, combineLatest, BehaviorSubject, of } from 'rxjs'; | import { Observable, combineLatest, BehaviorSubject, of } from 'rxjs'; | ||||||
| import { map, share, switchMap } from 'rxjs/operators'; | import { map, share, switchMap } from 'rxjs/operators'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { Trade } from '../bisq.interfaces'; | import { Trade } from '../bisq.interfaces'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,8 +3,8 @@ import { FormBuilder, FormGroup } from '@angular/forms'; | |||||||
| import { ActivatedRoute, Router } from '@angular/router'; | import { ActivatedRoute, Router } from '@angular/router'; | ||||||
| import { combineLatest, merge, Observable, of } from 'rxjs'; | import { combineLatest, merge, Observable, of } from 'rxjs'; | ||||||
| import { map, switchMap } from 'rxjs/operators'; | import { map, switchMap } from 'rxjs/operators'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { OffersMarket, Trade } from '../bisq.interfaces'; | import { OffersMarket, Trade } from '../bisq.interfaces'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { BisqStats } from '../bisq.interfaces'; | import { BisqStats } from '../bisq.interfaces'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-stats', |   selector: 'app-bisq-stats', | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { Component, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; | import { Component, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; | ||||||
| import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; | import { BisqTransaction } from '../../bisq/bisq.interfaces'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-transaction-details', |   selector: 'app-bisq-transaction-details', | ||||||
|  | |||||||
| @ -1,15 +1,15 @@ | |||||||
| import { Component, OnInit, OnDestroy } from '@angular/core'; | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||||||
| import { ActivatedRoute, ParamMap, Router } from '@angular/router'; | import { ActivatedRoute, ParamMap, Router } from '@angular/router'; | ||||||
| import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; | import { BisqTransaction } from '../../bisq/bisq.interfaces'; | ||||||
| import { switchMap, map, catchError } from 'rxjs/operators'; | import { switchMap, map, catchError } from 'rxjs/operators'; | ||||||
| import { of, Observable, Subscription } from 'rxjs'; | import { of, Observable, Subscription } from 'rxjs'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Block, Transaction } from 'src/app/interfaces/electrs.interface'; | import { Block, Transaction } from '../../interfaces/electrs.interface'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { ElectrsApiService } from 'src/app/services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { HttpErrorResponse } from '@angular/common/http'; | import { HttpErrorResponse } from '@angular/common/http'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-transaction', |   selector: 'app-bisq-transaction', | ||||||
|  | |||||||
| @ -4,11 +4,11 @@ import { BisqTransaction, BisqOutput } from '../bisq.interfaces'; | |||||||
| import { Observable, Subscription } from 'rxjs'; | import { Observable, Subscription } from 'rxjs'; | ||||||
| import { switchMap, map, tap } from 'rxjs/operators'; | import { switchMap, map, tap } from 'rxjs/operators'; | ||||||
| import { BisqApiService } from '../bisq-api.service'; | import { BisqApiService } from '../bisq-api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { FormGroup, FormBuilder } from '@angular/forms'; | import { FormGroup, FormBuilder } from '@angular/forms'; | ||||||
| import { Router, ActivatedRoute } from '@angular/router'; | import { Router, ActivatedRoute } from '@angular/router'; | ||||||
| import { IMultiSelectOption, IMultiSelectSettings, IMultiSelectTexts } from 'src/app/components/ngx-bootstrap-multiselect/types' | import { IMultiSelectOption, IMultiSelectSettings, IMultiSelectTexts } from '../../components/ngx-bootstrap-multiselect/types' | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-transactions', |   selector: 'app-bisq-transactions', | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; | ||||||
| import { BisqTransaction } from 'src/app/bisq/bisq.interfaces'; | import { BisqTransaction } from '../../bisq/bisq.interfaces'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { Block } from 'src/app/interfaces/electrs.interface'; | import { Block } from '../../interfaces/electrs.interface'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-transfers', |   selector: 'app-bisq-transfers', | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -187,8 +187,8 @@ | |||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| 
 | 
 | ||||||
|   <div class="selfhosted-integrations-sponsor"> |   <div class="community-integrations-sponsor"> | ||||||
|     <h3 i18n="about.self-hosted-integrations">Self-Hosted Integrations</h3> |     <h3 i18n="about.community-integrations">Community Integrations</h3> | ||||||
|     <div class="wrapper"> |     <div class="wrapper"> | ||||||
|       <a href="https://github.com/getumbrel/umbrel" target="_blank" title="Umbrel"> |       <a href="https://github.com/getumbrel/umbrel" target="_blank" title="Umbrel"> | ||||||
|         <img class="image" src="/resources/profile/umbrel.png" /> |         <img class="image" src="/resources/profile/umbrel.png" /> | ||||||
| @ -218,18 +218,24 @@ | |||||||
|         <img class="image" src="/resources/profile/start9.png" /> |         <img class="image" src="/resources/profile/start9.png" /> | ||||||
|         <span>EmbassyOS</span> |         <span>EmbassyOS</span> | ||||||
|       </a> |       </a> | ||||||
|     </div> |       <a href="https://github.com/btcpayserver/btcpayserver" target="_blank" title="BTCPay Server"> | ||||||
|   </div> |         <img class="image" src="/resources/profile/btcpayserver.svg" /> | ||||||
| 
 |         <span>BTCPay</span> | ||||||
|   <div class="community-integrations-sponsor"> |       </a> | ||||||
|     <h3 i18n="about.wallet-integrations">Wallet Integrations</h3> |  | ||||||
|     <div class="wrapper"> |  | ||||||
|       <a href="https://github.com/bisq-network/bisq" target="_blank" title="Bisq"> |       <a href="https://github.com/bisq-network/bisq" target="_blank" title="Bisq"> | ||||||
|         <img class="image" src="/resources/profile/bisq_network.png" /> |         <img class="image" src="/resources/profile/bisq_network.png" /> | ||||||
|         <span>Bisq</span> |         <span>Bisq</span> | ||||||
|       </a> |       </a> | ||||||
|  |       <a href="https://github.com/BlueWallet/BlueWallet" target="_blank" title="BlueWallet"> | ||||||
|  |         <img class="image" src="/resources/profile/bluewallet.png" /> | ||||||
|  |         <span>BlueWallet</span> | ||||||
|  |       </a> | ||||||
|  |       <a href="https://github.com/muun/apollo" target="_blank" title="Muun Wallet"> | ||||||
|  |         <img class="image" src="/resources/profile/muun.png" /> | ||||||
|  |         <span>Muun</span> | ||||||
|  |       </a> | ||||||
|       <a href="https://github.com/spesmilo/electrum" target="_blank" title="Electrum Wallet"> |       <a href="https://github.com/spesmilo/electrum" target="_blank" title="Electrum Wallet"> | ||||||
|         <img class="image" src="/resources/profile/electrum.jpg" /> |         <img class="image" src="/resources/profile/electrum.png" /> | ||||||
|         <span>Electrum</span> |         <span>Electrum</span> | ||||||
|       </a> |       </a> | ||||||
|       <a href="https://github.com/cryptoadvance/specter-desktop" target="_blank" title="Specter Wallet"> |       <a href="https://github.com/cryptoadvance/specter-desktop" target="_blank" title="Specter Wallet"> | ||||||
| @ -244,18 +250,14 @@ | |||||||
|         <img class="image" src="/resources/profile/phoenix.jpg" /> |         <img class="image" src="/resources/profile/phoenix.jpg" /> | ||||||
|         <span>Phoenix</span> |         <span>Phoenix</span> | ||||||
|       </a> |       </a> | ||||||
|  |       <a href="https://github.com/lnbits/lnbits-legend" target="_blank" title="LNbits"> | ||||||
|  |         <img class="image" src="/resources/profile/lnbits.svg" /> | ||||||
|  |         <span>LNBits</span> | ||||||
|  |       </a> | ||||||
|       <a href="https://github.com/layer2tech/mercury-wallet" target="_blank" title="Mercury Wallet"> |       <a href="https://github.com/layer2tech/mercury-wallet" target="_blank" title="Mercury Wallet"> | ||||||
|         <img class="image" src="/resources/profile/mercury.svg" /> |         <img class="image" src="/resources/profile/mercury.svg" /> | ||||||
|         <span>Mercury</span> |         <span>Mercury</span> | ||||||
|       </a> |       </a> | ||||||
|       <a href="https://github.com/muun/apollo" target="_blank" title="Muun Wallet"> |  | ||||||
|         <img class="image" src="/resources/profile/muun.png" /> |  | ||||||
|         <span>Muun</span> |  | ||||||
|       </a> |  | ||||||
|       <a href="https://github.com/BlueWallet/BlueWallet" target="_blank" title="BlueWallet"> |  | ||||||
|         <img class="image" src="/resources/profile/bluewallet.png" /> |  | ||||||
|         <span>BlueWallet</span> |  | ||||||
|       </a> |  | ||||||
|       <a href="https://github.com/hsjoberg/blixt-wallet" target="_blank" title="Blixt Wallet"> |       <a href="https://github.com/hsjoberg/blixt-wallet" target="_blank" title="Blixt Wallet"> | ||||||
|         <img class="image" src="/resources/profile/blixt.png" /> |         <img class="image" src="/resources/profile/blixt.png" /> | ||||||
|         <span>Blixt</span> |         <span>Blixt</span> | ||||||
|  | |||||||
| @ -43,7 +43,6 @@ | |||||||
|   .alliances, |   .alliances, | ||||||
|   .enterprise-sponsor, |   .enterprise-sponsor, | ||||||
|   .community-integrations-sponsor, |   .community-integrations-sponsor, | ||||||
|   .selfhosted-integrations-sponsor, |  | ||||||
|   .maintainers { |   .maintainers { | ||||||
|     margin-top: 68px; |     margin-top: 68px; | ||||||
|     margin-bottom: 68px; |     margin-bottom: 68px; | ||||||
| @ -117,7 +116,6 @@ | |||||||
|   .community-sponsor, |   .community-sponsor, | ||||||
|   .project-translators, |   .project-translators, | ||||||
|   .community-integrations-sponsor, |   .community-integrations-sponsor, | ||||||
|   .selfhosted-integrations-sponsor, |  | ||||||
|   .maintainers { |   .maintainers { | ||||||
|     .wrapper { |     .wrapper { | ||||||
|       display: inline-block; |       display: inline-block; | ||||||
| @ -193,6 +191,6 @@ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .community-integrations-sponsor { | .community-integrations-sponsor { | ||||||
|   max-width: 830px; |   max-width: 970px; | ||||||
|   margin: auto; |   margin: auto; | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; | ||||||
| import { WebsocketService } from '../../services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { IBackendInfo } from 'src/app/interfaces/websocket.interface'; | import { IBackendInfo } from '../../interfaces/websocket.interface'; | ||||||
| import { Router } from '@angular/router'; | import { Router } from '@angular/router'; | ||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { ITranslators } from 'src/app/interfaces/node-api.interface'; | import { ITranslators } from '../../interfaces/node-api.interface'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-about', |   selector: 'app-about', | ||||||
|  | |||||||
| @ -1,9 +1,16 @@ | |||||||
| <a *ngIf="channel; else default" [routerLink]="['/lightning/channel' | relativeUrl, channel.id]"> | <ng-template [ngIf]="channel" [ngIfElse]="default"> | ||||||
|   <span |   <div> | ||||||
|     *ngIf="label" |     <div class="badge-positioner"> | ||||||
|     class="badge badge-pill badge-warning" |       <a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]"> | ||||||
|   >{{ label }}</span> |         <span  | ||||||
| </a> |           *ngIf="label" | ||||||
|  |           class="badge badge-pill badge-warning" | ||||||
|  |         >{{ label }}</span> | ||||||
|  |       </a> | ||||||
|  |     </div> | ||||||
|  |       | ||||||
|  |   </div> | ||||||
|  | </ng-template> | ||||||
| 
 | 
 | ||||||
| <ng-template #default> | <ng-template #default> | ||||||
|   <span |   <span | ||||||
|  | |||||||
| @ -1,3 +1,7 @@ | |||||||
| .badge { | .badge { | ||||||
|   margin-right: 2px; |   margin-right: 2px; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | .badge-positioner { | ||||||
|  |   position: absolute; | ||||||
|  | } | ||||||
| @ -1,7 +1,7 @@ | |||||||
| import { Component, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; | import { Component, ChangeDetectionStrategy, Input, OnChanges } from '@angular/core'; | ||||||
| import { Vin, Vout } from '../../interfaces/electrs.interface'; | import { Vin, Vout } from '../../interfaces/electrs.interface'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { parseMultisigScript } from 'src/app/bitcoin.utils'; | import { parseMultisigScript } from '../../bitcoin.utils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-address-labels', |   selector: 'app-address-labels', | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| <div class="box preview-box" *ngIf="address && !error"> | <div class="box preview-box" *ngIf="address && !error"> | ||||||
|   <h2 class="preview-header" i18n="shared.address">Address</h2> |   <app-preview-title> | ||||||
|  |     <span i18n="shared.address">Address</span> | ||||||
|  |   </app-preview-title> | ||||||
|   <div class="row"> |   <div class="row"> | ||||||
|     <div class="col-md"> |     <div class="col-md"> | ||||||
|       <div class="row d-flex justify-content-between"> |       <div class="row d-flex justify-content-between"> | ||||||
|  | |||||||
| @ -3,13 +3,13 @@ import { ActivatedRoute, ParamMap } from '@angular/router'; | |||||||
| import { ElectrsApiService } from '../../services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { switchMap, filter, catchError, map, tap } from 'rxjs/operators'; | import { switchMap, filter, catchError, map, tap } from 'rxjs/operators'; | ||||||
| import { Address, Transaction } from '../../interfaces/electrs.interface'; | import { Address, Transaction } from '../../interfaces/electrs.interface'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { OpenGraphService } from 'src/app/services/opengraph.service'; | import { OpenGraphService } from '../../services/opengraph.service'; | ||||||
| import { AudioService } from 'src/app/services/audio.service'; | import { AudioService } from '../../services/audio.service'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { of, merge, Subscription, Observable } from 'rxjs'; | import { of, merge, Subscription, Observable } from 'rxjs'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { AddressInformation } from 'src/app/interfaces/node-api.interface'; | import { AddressInformation } from '../../interfaces/node-api.interface'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-address-preview', |   selector: 'app-address-preview', | ||||||
|  | |||||||
| @ -3,13 +3,13 @@ import { ActivatedRoute, ParamMap } from '@angular/router'; | |||||||
| import { ElectrsApiService } from '../../services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { switchMap, filter, catchError, map, tap } from 'rxjs/operators'; | import { switchMap, filter, catchError, map, tap } from 'rxjs/operators'; | ||||||
| import { Address, Transaction } from '../../interfaces/electrs.interface'; | import { Address, Transaction } from '../../interfaces/electrs.interface'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { AudioService } from 'src/app/services/audio.service'; | import { AudioService } from '../../services/audio.service'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { of, merge, Subscription, Observable } from 'rxjs'; | import { of, merge, Subscription, Observable } from 'rxjs'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { AddressInformation } from 'src/app/interfaces/node-api.interface'; | import { AddressInformation } from '../../interfaces/node-api.interface'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-address', |   selector: 'app-address', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Location } from '@angular/common'; | import { Location } from '@angular/common'; | ||||||
| import { Component, HostListener, OnInit, Inject, LOCALE_ID, HostBinding } from '@angular/core'; | import { Component, HostListener, OnInit, Inject, LOCALE_ID, HostBinding } from '@angular/core'; | ||||||
| import { Router, NavigationEnd } from '@angular/router'; | import { Router, NavigationEnd } from '@angular/router'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { OpenGraphService } from 'src/app/services/opengraph.service'; | import { OpenGraphService } from '../../services/opengraph.service'; | ||||||
| import { NgbTooltipConfig } from '@ng-bootstrap/ng-bootstrap'; | import { NgbTooltipConfig } from '@ng-bootstrap/ng-bootstrap'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } from '@angular/core'; | ||||||
| import { combineLatest, Observable } from 'rxjs'; | import { combineLatest, Observable } from 'rxjs'; | ||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { moveDec } from 'src/app/bitcoin.utils'; | import { moveDec } from '../../bitcoin.utils'; | ||||||
| import { AssetsService } from 'src/app/services/assets.service'; | import { AssetsService } from '../../services/assets.service'; | ||||||
| import { ElectrsApiService } from 'src/app/services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { environment } from 'src/environments/environment'; | import { environment } from 'src/environments/environment'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -3,15 +3,15 @@ import { ActivatedRoute, ParamMap } from '@angular/router'; | |||||||
| import { ElectrsApiService } from '../../services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { switchMap, filter, catchError, take } from 'rxjs/operators'; | import { switchMap, filter, catchError, take } from 'rxjs/operators'; | ||||||
| import { Asset, Transaction } from '../../interfaces/electrs.interface'; | import { Asset, Transaction } from '../../interfaces/electrs.interface'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { AudioService } from 'src/app/services/audio.service'; | import { AudioService } from '../../services/audio.service'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { of, merge, Subscription, combineLatest } from 'rxjs'; | import { of, merge, Subscription, combineLatest } from 'rxjs'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { environment } from 'src/environments/environment'; | import { environment } from 'src/environments/environment'; | ||||||
| import { AssetsService } from 'src/app/services/assets.service'; | import { AssetsService } from '../../services/assets.service'; | ||||||
| import { moveDec } from 'src/app/bitcoin.utils'; | import { moveDec } from '../../bitcoin.utils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-asset', |   selector: 'app-asset', | ||||||
|  | |||||||
| @ -2,8 +2,8 @@ import { Component, OnInit } from '@angular/core'; | |||||||
| import { ActivatedRoute, ParamMap } from '@angular/router'; | import { ActivatedRoute, ParamMap } from '@angular/router'; | ||||||
| import { combineLatest, Observable } from 'rxjs'; | import { combineLatest, Observable } from 'rxjs'; | ||||||
| import { map, switchMap } from 'rxjs/operators'; | import { map, switchMap } from 'rxjs/operators'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../../services/api.service'; | ||||||
| import { AssetsService } from 'src/app/services/assets.service'; | import { AssetsService } from '../../../services/assets.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-asset-group', |   selector: 'app-asset-group', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../../services/api.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-assets-featured', |   selector: 'app-assets-featured', | ||||||
|  | |||||||
| @ -4,11 +4,11 @@ import { Router } from '@angular/router'; | |||||||
| import { NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; | import { NgbTypeahead } from '@ng-bootstrap/ng-bootstrap'; | ||||||
| import { merge, Observable, of, Subject } from 'rxjs'; | import { merge, Observable, of, Subject } from 'rxjs'; | ||||||
| import { distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; | import { distinctUntilChanged, filter, map, switchMap } from 'rxjs/operators'; | ||||||
| import { AssetExtended } from 'src/app/interfaces/electrs.interface'; | import { AssetExtended } from '../../../interfaces/electrs.interface'; | ||||||
| import { AssetsService } from 'src/app/services/assets.service'; | import { AssetsService } from '../../../services/assets.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../../services/seo.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../../services/state.service'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { environment } from 'src/environments/environment'; | import { environment } from 'src/environments/environment'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { AssetsService } from 'src/app/services/assets.service'; | import { AssetsService } from '../../services/assets.service'; | ||||||
| import { environment } from 'src/environments/environment'; | import { environment } from 'src/environments/environment'; | ||||||
| import { FormGroup } from '@angular/forms'; | import { FormGroup } from '@angular/forms'; | ||||||
| import { filter, map, switchMap, take } from 'rxjs/operators'; | import { filter, map, switchMap, take } from 'rxjs/operators'; | ||||||
| import { ActivatedRoute, Router } from '@angular/router'; | import { ActivatedRoute, Router } from '@angular/router'; | ||||||
| import { combineLatest, Observable } from 'rxjs'; | import { combineLatest, Observable } from 'rxjs'; | ||||||
| import { AssetExtended } from 'src/app/interfaces/electrs.interface'; | import { AssetExtended } from '../../interfaces/electrs.interface'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-assets', |   selector: 'app-assets', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { Env, StateService } from '../../services/state.service'; | import { Env, StateService } from '../../services/state.service'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { LanguageService } from 'src/app/services/language.service'; | import { LanguageService } from '../../services/language.service'; | ||||||
| import { EnterpriseService } from 'src/app/services/enterprise.service'; | import { EnterpriseService } from '../../services/enterprise.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-bisq-master-page', |   selector: 'app-bisq-master-page', | ||||||
|  | |||||||
| @ -2,11 +2,11 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; | |||||||
| import { ActivatedRoute, ParamMap, Router } from '@angular/router'; | import { ActivatedRoute, ParamMap, Router } from '@angular/router'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { map, share, switchMap, tap } from 'rxjs/operators'; | import { map, share, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { BlockAudit, TransactionStripped } from 'src/app/interfaces/node-api.interface'; | import { BlockAudit, TransactionStripped } from '../../interfaces/node-api.interface'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { detectWebGL } from 'src/app/shared/graphs.utils'; | import { detectWebGL } from '../../shared/graphs.utils'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { BlockOverviewGraphComponent } from '../block-overview-graph/block-overview-graph.component'; | import { BlockOverviewGraphComponent } from '../block-overview-graph/block-overview-graph.component'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -2,16 +2,16 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, O | |||||||
| import { EChartsOption } from 'echarts'; | import { EChartsOption } from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../shared/graphs.utils'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { MiningService } from 'src/app/services/mining.service'; | import { MiningService } from '../../services/mining.service'; | ||||||
| import { selectPowerOfTen } from 'src/app/bitcoin.utils'; | import { selectPowerOfTen } from '../../bitcoin.utils'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { ActivatedRoute, Router } from '@angular/router'; | import { ActivatedRoute, Router } from '@angular/router'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -2,15 +2,15 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } | |||||||
| import { EChartsOption, graphic } from 'echarts'; | import { EChartsOption, graphic } from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { formatCurrency, formatNumber, getCurrencySymbol } from '@angular/common'; | import { formatCurrency, formatNumber, getCurrencySymbol } from '@angular/common'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../shared/graphs.utils'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { MiningService } from 'src/app/services/mining.service'; | import { MiningService } from '../../services/mining.service'; | ||||||
| import { ActivatedRoute } from '@angular/router'; | import { ActivatedRoute } from '@angular/router'; | ||||||
| import { FiatShortenerPipe } from 'src/app/shared/pipes/fiat-shortener.pipe'; | import { FiatShortenerPipe } from '../../shared/pipes/fiat-shortener.pipe'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block-fees-graph', |   selector: 'app-block-fees-graph', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| <div class="block-overview-graph"> | <div class="block-overview-graph"> | ||||||
|   <canvas class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas> |   <canvas class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas> | ||||||
|   <div class="loader-wrapper" [class.hidden]="!isLoading"> |   <div class="loader-wrapper" [class.hidden]="!isLoading || disableSpinner"> | ||||||
|     <div class="spinner-border ml-3 loading" role="status"></div> |     <div class="spinner-border ml-3 loading" role="status"></div> | ||||||
|   </div> |   </div> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, NgZone, AfterViewInit, OnDestroy } from '@angular/core'; | import { Component, ElementRef, ViewChild, HostListener, Input, Output, EventEmitter, NgZone, AfterViewInit, OnDestroy } from '@angular/core'; | ||||||
| import { TransactionStripped } from 'src/app/interfaces/websocket.interface'; | import { TransactionStripped } from '../../interfaces/websocket.interface'; | ||||||
| import { FastVertexArray } from './fast-vertex-array'; | import { FastVertexArray } from './fast-vertex-array'; | ||||||
| import BlockScene from './block-scene'; | import BlockScene from './block-scene'; | ||||||
| import TxSprite from './tx-sprite'; | import TxSprite from './tx-sprite'; | ||||||
| @ -17,6 +17,7 @@ export class BlockOverviewGraphComponent implements AfterViewInit, OnDestroy { | |||||||
|   @Input() blockLimit: number; |   @Input() blockLimit: number; | ||||||
|   @Input() orientation = 'left'; |   @Input() orientation = 'left'; | ||||||
|   @Input() flip = true; |   @Input() flip = true; | ||||||
|  |   @Input() disableSpinner = false; | ||||||
|   @Output() txClickEvent = new EventEmitter<TransactionStripped>(); |   @Output() txClickEvent = new EventEmitter<TransactionStripped>(); | ||||||
|   @Output() readyEvent = new EventEmitter(); |   @Output() readyEvent = new EventEmitter(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { FastVertexArray } from './fast-vertex-array'; | import { FastVertexArray } from './fast-vertex-array'; | ||||||
| import TxView from './tx-view'; | import TxView from './tx-view'; | ||||||
| import { TransactionStripped } from 'src/app/interfaces/websocket.interface'; | import { TransactionStripped } from '../../interfaces/websocket.interface'; | ||||||
| import { Position, Square, ViewUpdateParams } from './sprite-types'; | import { Position, Square, ViewUpdateParams } from './sprite-types'; | ||||||
| 
 | 
 | ||||||
| export default class BlockScene { | export default class BlockScene { | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import TxSprite from './tx-sprite'; | import TxSprite from './tx-sprite'; | ||||||
| import { FastVertexArray } from './fast-vertex-array'; | import { FastVertexArray } from './fast-vertex-array'; | ||||||
| import { TransactionStripped } from 'src/app/interfaces/websocket.interface'; | import { TransactionStripped } from '../../interfaces/websocket.interface'; | ||||||
| import { SpriteUpdateParams, Square, Color, ViewUpdateParams } from './sprite-types'; | import { SpriteUpdateParams, Square, Color, ViewUpdateParams } from './sprite-types'; | ||||||
| import { feeLevels, mempoolFeeColors } from 'src/app/app.constants'; | import { feeLevels, mempoolFeeColors } from '../../app.constants'; | ||||||
| 
 | 
 | ||||||
| const hoverTransitionTime = 300; | const hoverTransitionTime = 300; | ||||||
| const defaultHoverColor = hexToColor('1bd8f4'); | const defaultHoverColor = hexToColor('1bd8f4'); | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, ElementRef, ViewChild, Input, OnChanges, ChangeDetectionStrategy } from '@angular/core'; | import { Component, ElementRef, ViewChild, Input, OnChanges, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { TransactionStripped } from 'src/app/interfaces/websocket.interface'; | import { TransactionStripped } from '../../interfaces/websocket.interface'; | ||||||
| import { Position } from 'src/app/components/block-overview-graph/sprite-types.js'; | import { Position } from '../../components/block-overview-graph/sprite-types.js'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block-overview-tooltip', |   selector: 'app-block-overview-tooltip', | ||||||
|  | |||||||
| @ -2,15 +2,15 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, NgZone, O | |||||||
| import { EChartsOption } from 'echarts'; | import { EChartsOption } from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../shared/graphs.utils'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { ActivatedRoute, Router } from '@angular/router'; | import { ActivatedRoute, Router } from '@angular/router'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block-prediction-graph', |   selector: 'app-block-prediction-graph', | ||||||
|  | |||||||
| @ -2,15 +2,15 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit } | |||||||
| import { EChartsOption, graphic } from 'echarts'; | import { EChartsOption, graphic } from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { formatCurrency, formatNumber, getCurrencySymbol } from '@angular/common'; | import { formatCurrency, formatNumber, getCurrencySymbol } from '@angular/common'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis, formatterXAxisLabel, formatterXAxisTimeCategory } from '../../shared/graphs.utils'; | ||||||
| import { MiningService } from 'src/app/services/mining.service'; | import { MiningService } from '../../services/mining.service'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { ActivatedRoute } from '@angular/router'; | import { ActivatedRoute } from '@angular/router'; | ||||||
| import { FiatShortenerPipe } from 'src/app/shared/pipes/fiat-shortener.pipe'; | import { FiatShortenerPipe } from '../../shared/pipes/fiat-shortener.pipe'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block-rewards-graph', |   selector: 'app-block-rewards-graph', | ||||||
|  | |||||||
| @ -2,14 +2,14 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, H | |||||||
| import { EChartsOption} from 'echarts'; | import { EChartsOption} from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { MiningService } from 'src/app/services/mining.service'; | import { MiningService } from '../../services/mining.service'; | ||||||
| import { ActivatedRoute } from '@angular/router'; | import { ActivatedRoute } from '@angular/router'; | ||||||
| import { download, formatterXAxis } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis } from '../../shared/graphs.utils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block-sizes-weights-graph', |   selector: 'app-block-sizes-weights-graph', | ||||||
|  | |||||||
| @ -1,16 +1,21 @@ | |||||||
| <div class="box preview-box" *ngIf="!error"> | <div class="box preview-box" *ngIf="!error"> | ||||||
|   <h2 class="preview-header" i18n="shared.block-title">Block</h2> |   <app-preview-title> | ||||||
|  |     <span i18n="shared.block-title">Block</span> | ||||||
|  |   </app-preview-title> | ||||||
|   <div class="row"> |   <div class="row"> | ||||||
|     <div class="col-sm"> |     <div class="col-sm"> | ||||||
|       <div class="row d-flex justify-content-between"> |       <div class="row"> | ||||||
|         <div class="title-wrapper"> |         <div class="block-titles"> | ||||||
|           <h1 class="title"> |           <h1 class="title"> | ||||||
|             <ng-template [ngIf]="blockHeight === 0"><ng-container i18n="@@2303359202781425764">Genesis</ng-container></ng-template> |             <ng-template [ngIf]="blockHeight === 0"><ng-container i18n="@@2303359202781425764">Genesis</ng-container></ng-template> | ||||||
|             <ng-template [ngIf]="blockHeight" i18n="shared.block-title">{{ blockHeight }}</ng-template> |             <ng-template [ngIf]="blockHeight" i18n="shared.block-title">{{ blockHeight }}</ng-template> | ||||||
|           </h1> |           </h1> | ||||||
|  |           <div class="blockhash" *ngIf="blockHash"> | ||||||
|  |             <h2 class="truncate right">{{ blockHash.slice(0,32) }}</h2> | ||||||
|  |             <h2 class="truncate left">{{ blockHash.slice(32) }}</h2> | ||||||
|  |           </div> | ||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|       <a class="subtitle truncated" [routerLink]="['/block/' | relativeUrl, blockHash]"><span class="first">{{blockHash.slice(0,-4)}}</span><span class="last-four">{{blockHash.slice(-4)}}</span></a> |  | ||||||
|       <table class="table table-borderless table-striped"> |       <table class="table table-borderless table-striped"> | ||||||
|         <tbody> |         <tbody> | ||||||
|           <!-- <tr> |           <!-- <tr> | ||||||
| @ -70,6 +75,7 @@ | |||||||
|         [blockLimit]="stateService.blockVSize" |         [blockLimit]="stateService.blockVSize" | ||||||
|         [orientation]="'top'" |         [orientation]="'top'" | ||||||
|         [flip]="false" |         [flip]="false" | ||||||
|  |         [disableSpinner]="true" | ||||||
|         (readyEvent)="onGraphReady()" |         (readyEvent)="onGraphReady()" | ||||||
|       ></app-block-overview-graph> |       ></app-block-overview-graph> | ||||||
|     </div> |     </div> | ||||||
|  | |||||||
| @ -1,10 +1,47 @@ | |||||||
| .table { | .table { | ||||||
|   font-size: 32px; |   font-size: 32px; | ||||||
|   margin-top: 6px; |   margin-top: 36px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .title-wrapper { | .block-titles { | ||||||
|  |   margin: 0; | ||||||
|   padding-left: 15px; |   padding-left: 15px; | ||||||
|  |   padding-right: 15px; | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: row; | ||||||
|  |   flex-wrap: nowrap; | ||||||
|  |   align-items: center; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   width: 100%; | ||||||
|  |   flex-grow: 1; | ||||||
|  | 
 | ||||||
|  |   .title { | ||||||
|  |     flex-shrink: 0; | ||||||
|  |     flex-grow:  0; | ||||||
|  |     margin-right: 30px; | ||||||
|  |     font-size: 64px; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   .blockhash { | ||||||
|  |     width: 0; | ||||||
|  |     flex-grow: 1; | ||||||
|  |     flex-shrink: 1; | ||||||
|  |     font-family: Consolas,Liberation Mono,Courier New,monospace; | ||||||
|  |     font-size: 32px; | ||||||
|  |     text-align: right; | ||||||
|  | 
 | ||||||
|  |     .truncate { | ||||||
|  |       max-width: 100%; | ||||||
|  |       overflow: hidden; | ||||||
|  |       white-space: nowrap; | ||||||
|  |       text-overflow: ellipsis; | ||||||
|  |       margin: 0; | ||||||
|  | 
 | ||||||
|  |       &.left { | ||||||
|  |         direction: rtl; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| .chart-container { | .chart-container { | ||||||
|  | |||||||
| @ -4,11 +4,11 @@ import { ElectrsApiService } from '../../services/electrs-api.service'; | |||||||
| import { switchMap, tap, throttleTime, catchError, shareReplay, startWith, pairwise, filter } from 'rxjs/operators'; | import { switchMap, tap, throttleTime, catchError, shareReplay, startWith, pairwise, filter } from 'rxjs/operators'; | ||||||
| import { of, Subscription, asyncScheduler } from 'rxjs'; | import { of, Subscription, asyncScheduler } from 'rxjs'; | ||||||
| import { StateService } from '../../services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { OpenGraphService } from 'src/app/services/opengraph.service'; | import { OpenGraphService } from '../../services/opengraph.service'; | ||||||
| import { BlockExtended, TransactionStripped } from 'src/app/interfaces/node-api.interface'; | import { BlockExtended, TransactionStripped } from '../../interfaces/node-api.interface'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { BlockOverviewGraphComponent } from 'src/app/components/block-overview-graph/block-overview-graph.component'; | import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block-preview', |   selector: 'app-block-preview', | ||||||
|  | |||||||
| @ -6,13 +6,13 @@ import { switchMap, tap, throttleTime, catchError, map, shareReplay, startWith, | |||||||
| import { Transaction, Vout } from '../../interfaces/electrs.interface'; | import { Transaction, Vout } from '../../interfaces/electrs.interface'; | ||||||
| import { Observable, of, Subscription, asyncScheduler, EMPTY } from 'rxjs'; | import { Observable, of, Subscription, asyncScheduler, EMPTY } from 'rxjs'; | ||||||
| import { StateService } from '../../services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { BlockExtended, TransactionStripped } from 'src/app/interfaces/node-api.interface'; | import { BlockExtended, TransactionStripped } from '../../interfaces/node-api.interface'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { BlockOverviewGraphComponent } from 'src/app/components/block-overview-graph/block-overview-graph.component'; | import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component'; | ||||||
| import { detectWebGL } from 'src/app/shared/graphs.utils'; | import { detectWebGL } from '../../shared/graphs.utils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-block', |   selector: 'app-block', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; | ||||||
| import { Observable, Subscription } from 'rxjs'; | import { Observable, Subscription } from 'rxjs'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { specialBlocks } from 'src/app/app.constants'; | import { specialBlocks } from '../../app.constants'; | ||||||
| import { BlockExtended } from 'src/app/interfaces/node-api.interface'; | import { BlockExtended } from '../../interfaces/node-api.interface'; | ||||||
| import { Location } from '@angular/common'; | import { Location } from '@angular/common'; | ||||||
| import { config } from 'process'; | import { config } from 'process'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-blockchain', |   selector: 'app-blockchain', | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core'; | ||||||
| import { BehaviorSubject, combineLatest, concat, Observable, timer } from 'rxjs'; | import { BehaviorSubject, combineLatest, concat, Observable, timer } from 'rxjs'; | ||||||
| import { delayWhen, map, retryWhen, scan, skip, switchMap, tap } from 'rxjs/operators'; | import { delayWhen, map, retryWhen, scan, skip, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { BlockExtended } from 'src/app/interfaces/node-api.interface'; | import { BlockExtended } from '../../interfaces/node-api.interface'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-blocks-list', |   selector: 'app-blocks-list', | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| import { Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; | import { Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { selectPowerOfTen } from 'src/app/bitcoin.utils'; | import { selectPowerOfTen } from '../../bitcoin.utils'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-difficulty-adjustments-table', |   selector: 'app-difficulty-adjustments-table', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { Recommendedfees } from 'src/app/interfaces/websocket.interface'; | import { Recommendedfees } from '../../interfaces/websocket.interface'; | ||||||
| import { feeLevels, mempoolFeeColors } from 'src/app/app.constants'; | import { feeLevels, mempoolFeeColors } from '../../app.constants'; | ||||||
| import { tap } from 'rxjs/operators'; | import { tap } from 'rxjs/operators'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Observable, combineLatest } from 'rxjs'; | import { Observable, combineLatest } from 'rxjs'; | ||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { MempoolInfo } from 'src/app/interfaces/websocket.interface'; | import { MempoolInfo } from '../../interfaces/websocket.interface'; | ||||||
| 
 | 
 | ||||||
| interface MempoolBlocksData { | interface MempoolBlocksData { | ||||||
|   blocks: number; |   blocks: number; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, OnInit } from "@angular/core"; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { StateService } from "src/app/services/state.service"; | import { StateService } from '../../services/state.service'; | ||||||
| import { WebsocketService } from "src/app/services/websocket.service"; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-graphs', |   selector: 'app-graphs', | ||||||
|  | |||||||
| @ -2,16 +2,16 @@ import { ChangeDetectionStrategy, Component, Inject, Input, LOCALE_ID, OnInit, H | |||||||
| import { EChartsOption, graphic } from 'echarts'; | import { EChartsOption, graphic } from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { selectPowerOfTen } from 'src/app/bitcoin.utils'; | import { selectPowerOfTen } from '../../bitcoin.utils'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { MiningService } from 'src/app/services/mining.service'; | import { MiningService } from '../../services/mining.service'; | ||||||
| import { download } from 'src/app/shared/graphs.utils'; | import { download } from '../../shared/graphs.utils'; | ||||||
| import { ActivatedRoute } from '@angular/router'; | import { ActivatedRoute } from '@angular/router'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-hashrate-chart', |   selector: 'app-hashrate-chart', | ||||||
|  | |||||||
| @ -2,13 +2,13 @@ import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, L | |||||||
| import { EChartsOption } from 'echarts'; | import { EChartsOption } from '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 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { poolsColor } from 'src/app/app.constants'; | import { poolsColor } from '../../app.constants'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { MiningService } from 'src/app/services/mining.service'; | import { MiningService } from '../../services/mining.service'; | ||||||
| import { download } from 'src/app/shared/graphs.utils'; | import { download } from '../../shared/graphs.utils'; | ||||||
| import { ActivatedRoute } from '@angular/router'; | import { ActivatedRoute } from '@angular/router'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnInit } from '@angular/core'; | import { Component, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnInit } from '@angular/core'; | ||||||
| import { EChartsOption } from 'echarts'; | import { EChartsOption } from 'echarts'; | ||||||
| import { OnChanges } from '@angular/core'; | import { OnChanges } from '@angular/core'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { download, formatterXAxis, formatterXAxisLabel } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis, formatterXAxisLabel } from '../../shared/graphs.utils'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { DOCUMENT } from '@angular/common'; | import { DOCUMENT } from '@angular/common'; | ||||||
| import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, Inject, OnInit } from '@angular/core'; | ||||||
| import { FormBuilder, FormGroup } from '@angular/forms'; | import { FormBuilder, FormGroup } from '@angular/forms'; | ||||||
| import { languages } from 'src/app/app.constants'; | import { languages } from '../../app.constants'; | ||||||
| import { LanguageService } from 'src/app/services/language.service'; | import { LanguageService } from '../../services/language.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-language-selector', |   selector: 'app-language-selector', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { Env, StateService } from '../../services/state.service'; | import { Env, StateService } from '../../services/state.service'; | ||||||
| import { merge, Observable, of} from 'rxjs'; | import { merge, Observable, of} from 'rxjs'; | ||||||
| import { LanguageService } from 'src/app/services/language.service'; | import { LanguageService } from '../../services/language.service'; | ||||||
| import { EnterpriseService } from 'src/app/services/enterprise.service'; | import { EnterpriseService } from '../../services/enterprise.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-liquid-master-page', |   selector: 'app-liquid-master-page', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core'; | ||||||
| import { Observable } from 'rxjs'; | import { Observable } from 'rxjs'; | ||||||
| import { map } from 'rxjs/operators'; | import { map } from 'rxjs/operators'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-loading-indicator', |   selector: 'app-loading-indicator', | ||||||
|  | |||||||
| @ -10,8 +10,8 @@ | |||||||
|       <span *ngSwitchCase="'signet'" class="network signet"><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Signet</span> |       <span *ngSwitchCase="'signet'" class="network signet"><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Signet</span> | ||||||
|       <span *ngSwitchCase="'testnet'" class="network testnet"><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span> |       <span *ngSwitchCase="'testnet'" class="network testnet"><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span> | ||||||
|       <span *ngSwitchCase="'bisq'" class="network bisq"><app-svg-images name="bisq" width="35" height="35" viewBox="0 0 75 75" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Bisq</span> |       <span *ngSwitchCase="'bisq'" class="network bisq"><app-svg-images name="bisq" width="35" height="35" viewBox="0 0 75 75" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Bisq</span> | ||||||
|       <span *ngSwitchCase="'liquid'" class="network liquid"><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Liquid</span> |       <span *ngSwitchCase="'liquid'" class="network liquid"><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span> | ||||||
|       <span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Liquid Testnet</span> |       <span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span> | ||||||
|       <span *ngSwitchDefault class="network mainnet"><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span> |       <span *ngSwitchDefault class="network mainnet"><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span> | ||||||
|     </div> |     </div> | ||||||
|   </header> |   </header> | ||||||
|  | |||||||
| @ -47,6 +47,7 @@ | |||||||
|     z-index: 101; |     z-index: 101; | ||||||
|     line-height: 80px; |     line-height: 80px; | ||||||
|     text-transform: capitalize; |     text-transform: capitalize; | ||||||
|  |     font-size: 2.4rem; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   ::ng-deep .title { |   ::ng-deep .title { | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { StateService } from '../../services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Observable, merge, of } from 'rxjs'; | import { Observable, merge, of } from 'rxjs'; | ||||||
| import { LanguageService } from 'src/app/services/language.service'; | import { LanguageService } from '../../services/language.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-master-page-preview', |   selector: 'app-master-page-preview', | ||||||
|  | |||||||
| @ -0,0 +1,11 @@ | |||||||
|  | <h2 class="preview-header"> | ||||||
|  |   <ng-container *ngIf="{ val: network$ | async } as network"> | ||||||
|  |     <ng-container [ngSwitch]="network.val"> | ||||||
|  |       <span *ngSwitchCase="'bisq'">Bisq </span> | ||||||
|  |       <span *ngSwitchCase="'liquid'">Liquid </span> | ||||||
|  |       <span *ngSwitchCase="'liquidtestnet'">Liquid </span> | ||||||
|  |       <span *ngSwitchDefault>Bitcoin </span> | ||||||
|  |     </ng-container> | ||||||
|  |   </ng-container> | ||||||
|  |   <ng-content></ng-content> | ||||||
|  | </h2> | ||||||
| @ -0,0 +1,20 @@ | |||||||
|  | import { Component, OnInit } from '@angular/core'; | ||||||
|  | import { StateService } from '../../services/state.service'; | ||||||
|  | import { Observable, merge, of } from 'rxjs'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'app-preview-title', | ||||||
|  |   templateUrl: './preview-title.component.html', | ||||||
|  |   styleUrls: [], | ||||||
|  | }) | ||||||
|  | export class PreviewTitleComponent implements OnInit { | ||||||
|  |   network$: Observable<string>; | ||||||
|  | 
 | ||||||
|  |   constructor( | ||||||
|  |     public stateService: StateService, | ||||||
|  |   ) { } | ||||||
|  | 
 | ||||||
|  |   ngOnInit() { | ||||||
|  |     this.network$ = merge(of(''), this.stateService.networkChanged$); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -1,8 +1,8 @@ | |||||||
| import { Component, Inject, OnInit } from '@angular/core'; | import { Component, Inject, OnInit } from '@angular/core'; | ||||||
| import { Env, StateService } from '../../services/state.service'; | import { Env, StateService } from '../../services/state.service'; | ||||||
| import { Observable, merge, of } from 'rxjs'; | import { Observable, merge, of } from 'rxjs'; | ||||||
| import { LanguageService } from 'src/app/services/language.service'; | import { LanguageService } from '../../services/language.service'; | ||||||
| import { EnterpriseService } from 'src/app/services/enterprise.service'; | import { EnterpriseService } from '../../services/enterprise.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-master-page', |   selector: 'app-master-page', | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| import { Component, ComponentRef, ViewChild, HostListener, Input, Output, EventEmitter, | import { Component, ComponentRef, ViewChild, HostListener, Input, Output, EventEmitter, | ||||||
|   OnDestroy, OnChanges, ChangeDetectionStrategy, AfterViewInit } from '@angular/core'; |   OnDestroy, OnChanges, ChangeDetectionStrategy, AfterViewInit } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { MempoolBlockDelta, TransactionStripped } from 'src/app/interfaces/websocket.interface'; | import { MempoolBlockDelta, TransactionStripped } from '../../interfaces/websocket.interface'; | ||||||
| import { BlockOverviewGraphComponent } from 'src/app/components/block-overview-graph/block-overview-graph.component'; | import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component'; | ||||||
| import { Subscription, BehaviorSubject, merge, of } from 'rxjs'; | import { Subscription, BehaviorSubject, merge, of } from 'rxjs'; | ||||||
| import { switchMap, filter } from 'rxjs/operators'; | import { switchMap, filter } from 'rxjs/operators'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { Router } from '@angular/router'; | import { Router } from '@angular/router'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|  | |||||||
| @ -1,11 +1,11 @@ | |||||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { ActivatedRoute, ParamMap } from '@angular/router'; | import { ActivatedRoute, ParamMap } from '@angular/router'; | ||||||
| import { switchMap, map, tap, filter } from 'rxjs/operators'; | import { switchMap, map, tap, filter } from 'rxjs/operators'; | ||||||
| import { MempoolBlock, TransactionStripped } from 'src/app/interfaces/websocket.interface'; | import { MempoolBlock, TransactionStripped } from '../../interfaces/websocket.interface'; | ||||||
| import { Observable, BehaviorSubject } from 'rxjs'; | import { Observable, BehaviorSubject } from 'rxjs'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-mempool-block', |   selector: 'app-mempool-block', | ||||||
|  | |||||||
| @ -1,14 +1,14 @@ | |||||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, Input } from '@angular/core'; | ||||||
| import { Subscription, Observable, fromEvent, merge, of, combineLatest, timer } from 'rxjs'; | import { Subscription, Observable, fromEvent, merge, of, combineLatest, timer } from 'rxjs'; | ||||||
| import { MempoolBlock } from 'src/app/interfaces/websocket.interface'; | import { MempoolBlock } from '../../interfaces/websocket.interface'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Router } from '@angular/router'; | import { Router } from '@angular/router'; | ||||||
| import { take, map, switchMap } from 'rxjs/operators'; | import { take, map, switchMap } from 'rxjs/operators'; | ||||||
| import { feeLevels, mempoolFeeColors } from 'src/app/app.constants'; | import { feeLevels, mempoolFeeColors } from '../../app.constants'; | ||||||
| import { specialBlocks } from 'src/app/app.constants'; | import { specialBlocks } from '../../app.constants'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { Location } from '@angular/common'; | import { Location } from '@angular/common'; | ||||||
| import { DifficultyAdjustment } from 'src/app/interfaces/node-api.interface'; | import { DifficultyAdjustment } from '../../interfaces/node-api.interface'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-mempool-blocks', |   selector: 'app-mempool-blocks', | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| import { Component, OnInit, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnChanges } from '@angular/core'; | import { Component, OnInit, Input, Inject, LOCALE_ID, ChangeDetectionStrategy, OnChanges } from '@angular/core'; | ||||||
| import { VbytesPipe } from 'src/app/shared/pipes/bytes-pipe/vbytes.pipe'; | import { VbytesPipe } from '../../shared/pipes/bytes-pipe/vbytes.pipe'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { OptimizedMempoolStats } from 'src/app/interfaces/node-api.interface'; | import { OptimizedMempoolStats } from '../../interfaces/node-api.interface'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { EChartsOption } from 'echarts'; | import { EChartsOption } from 'echarts'; | ||||||
| import { feeLevels, chartColors } from 'src/app/app.constants'; | import { feeLevels, chartColors } from '../../app.constants'; | ||||||
| import { download, formatterXAxis, formatterXAxisLabel } from 'src/app/shared/graphs.utils'; | import { download, formatterXAxis, formatterXAxisLabel } from '../../shared/graphs.utils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-mempool-graph', |   selector: 'app-mempool-graph', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-mining-dashboard', |   selector: 'app-mining-dashboard', | ||||||
|  | |||||||
| @ -4,15 +4,15 @@ import { ActivatedRoute, Router } from '@angular/router'; | |||||||
| import { EChartsOption, PieSeriesOption } from 'echarts'; | import { EChartsOption, PieSeriesOption } from 'echarts'; | ||||||
| import { concat, Observable } from 'rxjs'; | import { concat, Observable } from 'rxjs'; | ||||||
| import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; | import { map, share, startWith, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { SinglePoolStats } from 'src/app/interfaces/node-api.interface'; | import { SinglePoolStats } from '../../interfaces/node-api.interface'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StorageService } from '../..//services/storage.service'; | import { StorageService } from '../..//services/storage.service'; | ||||||
| import { MiningService, MiningStats } from '../../services/mining.service'; | import { MiningService, MiningStats } from '../../services/mining.service'; | ||||||
| import { StateService } from '../../services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { chartColors, poolsColor } from 'src/app/app.constants'; | import { chartColors, poolsColor } from '../../app.constants'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { download } from 'src/app/shared/graphs.utils'; | import { download } from '../../shared/graphs.utils'; | ||||||
| import { isMobile } from 'src/app/shared/common.utils'; | import { isMobile } from '../../shared/common.utils'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-pool-ranking', |   selector: 'app-pool-ranking', | ||||||
|  | |||||||
							
								
								
									
										34
									
								
								frontend/src/app/components/pool/pool-preview.component.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								frontend/src/app/components/pool/pool-preview.component.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,34 @@ | |||||||
|  | <div class="box preview-box" *ngIf="poolStats$ | async as poolStats"> | ||||||
|  |   <app-preview-title> | ||||||
|  |     <span i18n="mining.pools">mining pool</span> | ||||||
|  |   </app-preview-title> | ||||||
|  |   <div class="row d-flex justify-content-between full-width-row"> | ||||||
|  |     <div class="title-wrapper"> | ||||||
|  |       <h1 class="title">{{ poolStats.pool.name }}</h1> | ||||||
|  |     </div> | ||||||
|  |     <div class="logo-wrapper"> | ||||||
|  |       <img width="62" height="62" src="/resources/mining-pools/default.svg"> | ||||||
|  |       <img [class.noimg]="!imageLoaded" width="62" height="62" src="{{ poolStats['logo'] }}" | ||||||
|  |         (load)="onImageLoad()" (error)="onImageFail()"> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  |   <div class="row full-width-row"> | ||||||
|  |       <div class="stats"> | ||||||
|  |         <div class="stat-box"> | ||||||
|  |           <div class="label" i18n="mining.tags">Tags</div> | ||||||
|  |           <div *ngIf="poolStats.pool.regexes.length else nodata" class="data">{{ poolStats.pool.regexes }}</div> | ||||||
|  |         </div> | ||||||
|  |         <div class="stat-box"> | ||||||
|  |           <div class="label" i18n="mining.hashrate">Hashrate</div> | ||||||
|  |           <div class="data">{{ poolStats.estimatedHashrate | amountShortener : 1 : 'H/s' }}</div> | ||||||
|  |         </div> | ||||||
|  |       </div> | ||||||
|  |   </div> | ||||||
|  |   <div class="row hash-chart full-width-row"> | ||||||
|  |     <div class="chart" echarts [initOpts]="chartInitOptions" [options]="chartOptions" (chartFinished)="onChartReady()"></div> | ||||||
|  |   </div> | ||||||
|  | </div> | ||||||
|  | 
 | ||||||
|  | <ng-template #nodata> | ||||||
|  |   <div>~</div> | ||||||
|  | </ng-template> | ||||||
							
								
								
									
										78
									
								
								frontend/src/app/components/pool/pool-preview.component.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								frontend/src/app/components/pool/pool-preview.component.scss
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,78 @@ | |||||||
|  | .stats { | ||||||
|  |   display: flex; | ||||||
|  |   flex-direction: row; | ||||||
|  |   justify-content: center; | ||||||
|  |   align-items: flex-start; | ||||||
|  |   width: 100%; | ||||||
|  |   max-width: 100%; | ||||||
|  |   margin: 15px 0; | ||||||
|  |   font-size: 32px; | ||||||
|  |   overflow: hidden; | ||||||
|  | 
 | ||||||
|  |   .stat-box { | ||||||
|  |     display: flex; | ||||||
|  |     flex-direction: row; | ||||||
|  |     flex-wrap: nowrap; | ||||||
|  |     align-items: baseline; | ||||||
|  |     justify-content: space-between; | ||||||
|  |     width: 100%; | ||||||
|  |     margin-left: 15px; | ||||||
|  |     background: #181b2d; | ||||||
|  |     padding: 0.75rem; | ||||||
|  |     width: 0; | ||||||
|  |     flex-grow: 1; | ||||||
|  | 
 | ||||||
|  |     &:first-child { | ||||||
|  |       margin-left: 0; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     .label { | ||||||
|  |       flex-shrink: 0; | ||||||
|  |       flex-grow: 0; | ||||||
|  |       margin-right: 1em; | ||||||
|  |     } | ||||||
|  |     .data { | ||||||
|  |       flex-shrink: 1; | ||||||
|  |       overflow: hidden; | ||||||
|  |       text-overflow: ellipsis; | ||||||
|  |       white-space: nowrap; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .chart { | ||||||
|  |   width: 100%; | ||||||
|  |   height: 315px; | ||||||
|  |   background: #181b2d; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .row { | ||||||
|  |   margin-right: 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .full-width-row { | ||||||
|  |   padding-left: 15px; | ||||||
|  |   flex-wrap: nowrap; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | .logo-wrapper { | ||||||
|  |   position: relative; | ||||||
|  |   width: 62px; | ||||||
|  |   height: 62px; | ||||||
|  |   margin-left: 1em; | ||||||
|  | 
 | ||||||
|  |   img { | ||||||
|  |     position: absolute; | ||||||
|  |     right: 0; | ||||||
|  |     top: 0; | ||||||
|  |     background: #24273e; | ||||||
|  | 
 | ||||||
|  |     &.noimg { | ||||||
|  |       opacity: 0; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | ::ng-deep .symbol { | ||||||
|  |   font-size: 24px; | ||||||
|  | } | ||||||
							
								
								
									
										187
									
								
								frontend/src/app/components/pool/pool-preview.component.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								frontend/src/app/components/pool/pool-preview.component.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,187 @@ | |||||||
|  | import { ChangeDetectionStrategy, Component, Inject, LOCALE_ID, OnInit } from '@angular/core'; | ||||||
|  | import { ActivatedRoute } from '@angular/router'; | ||||||
|  | import { EChartsOption, graphic } from 'echarts'; | ||||||
|  | import { Observable, of } from 'rxjs'; | ||||||
|  | import { map, switchMap, catchError } from 'rxjs/operators'; | ||||||
|  | import { PoolStat } from '../../interfaces/node-api.interface'; | ||||||
|  | import { ApiService } from '../../services/api.service'; | ||||||
|  | import { StateService } from '../../services/state.service'; | ||||||
|  | import { formatNumber } from '@angular/common'; | ||||||
|  | import { SeoService } from '../../services/seo.service'; | ||||||
|  | import { OpenGraphService } from '../../services/opengraph.service'; | ||||||
|  | 
 | ||||||
|  | @Component({ | ||||||
|  |   selector: 'app-pool-preview', | ||||||
|  |   templateUrl: './pool-preview.component.html', | ||||||
|  |   styleUrls: ['./pool-preview.component.scss'], | ||||||
|  |   changeDetection: ChangeDetectionStrategy.OnPush | ||||||
|  | }) | ||||||
|  | export class PoolPreviewComponent implements OnInit { | ||||||
|  |   formatNumber = formatNumber; | ||||||
|  |   poolStats$: Observable<PoolStat>; | ||||||
|  |   isLoading = true; | ||||||
|  |   imageLoaded = false; | ||||||
|  |   lastImgSrc: string = ''; | ||||||
|  | 
 | ||||||
|  |   chartOptions: EChartsOption = {}; | ||||||
|  |   chartInitOptions = { | ||||||
|  |     renderer: 'svg', | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   slug: string = undefined; | ||||||
|  | 
 | ||||||
|  |   constructor( | ||||||
|  |     @Inject(LOCALE_ID) public locale: string, | ||||||
|  |     private apiService: ApiService, | ||||||
|  |     private route: ActivatedRoute, | ||||||
|  |     public stateService: StateService, | ||||||
|  |     private seoService: SeoService, | ||||||
|  |     private openGraphService: OpenGraphService, | ||||||
|  |   ) { | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   ngOnInit(): void { | ||||||
|  |     this.poolStats$ = this.route.params.pipe(map((params) => params.slug)) | ||||||
|  |       .pipe( | ||||||
|  |         switchMap((slug: any) => { | ||||||
|  |           this.isLoading = true; | ||||||
|  |           this.imageLoaded = false; | ||||||
|  |           this.slug = slug; | ||||||
|  |           this.openGraphService.waitFor('pool-hash-' + this.slug); | ||||||
|  |           this.openGraphService.waitFor('pool-stats-' + this.slug); | ||||||
|  |           this.openGraphService.waitFor('pool-chart-' + this.slug); | ||||||
|  |           this.openGraphService.waitFor('pool-img-' + this.slug); | ||||||
|  |           return this.apiService.getPoolHashrate$(this.slug) | ||||||
|  |             .pipe( | ||||||
|  |               switchMap((data) => { | ||||||
|  |                 this.isLoading = false; | ||||||
|  |                 this.prepareChartOptions(data.map(val => [val.timestamp * 1000, val.avgHashrate])); | ||||||
|  |                 this.openGraphService.waitOver('pool-hash-' + this.slug); | ||||||
|  |                 return [slug]; | ||||||
|  |               }), | ||||||
|  |               catchError(() => { | ||||||
|  |                 this.isLoading = false; | ||||||
|  |                 this.openGraphService.fail('pool-hash-' + this.slug); | ||||||
|  |                 return of([slug]); | ||||||
|  |               }) | ||||||
|  |             ); | ||||||
|  |         }), | ||||||
|  |         switchMap((slug) => { | ||||||
|  |           return this.apiService.getPoolStats$(slug).pipe( | ||||||
|  |             catchError(() => { | ||||||
|  |               this.isLoading = false; | ||||||
|  |               this.openGraphService.fail('pool-stats-' + this.slug); | ||||||
|  |               return of(null); | ||||||
|  |             }) | ||||||
|  |           ); | ||||||
|  |         }), | ||||||
|  |         map((poolStats) => { | ||||||
|  |           if (poolStats == null) { | ||||||
|  |             return null; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           this.seoService.setTitle(poolStats.pool.name); | ||||||
|  |           let regexes = '"'; | ||||||
|  |           for (const regex of poolStats.pool.regexes) { | ||||||
|  |             regexes += regex + '", "'; | ||||||
|  |           } | ||||||
|  |           poolStats.pool.regexes = regexes.slice(0, -3); | ||||||
|  |           poolStats.pool.addresses = poolStats.pool.addresses; | ||||||
|  | 
 | ||||||
|  |           if (poolStats.reportedHashrate) { | ||||||
|  |             poolStats.luck = poolStats.estimatedHashrate / poolStats.reportedHashrate * 100; | ||||||
|  |           } | ||||||
|  | 
 | ||||||
|  |           this.openGraphService.waitOver('pool-stats-' + this.slug); | ||||||
|  | 
 | ||||||
|  |           const logoSrc = `/resources/mining-pools/` + poolStats.pool.name.toLowerCase().replace(' ', '').replace('.', '') + '.svg'; | ||||||
|  |           if (logoSrc === this.lastImgSrc) { | ||||||
|  |             this.openGraphService.waitOver('pool-img-' + this.slug); | ||||||
|  |           } | ||||||
|  |           this.lastImgSrc = logoSrc; | ||||||
|  |           return Object.assign({ | ||||||
|  |             logo: logoSrc | ||||||
|  |           }, poolStats); | ||||||
|  |         }), | ||||||
|  |         catchError(() => { | ||||||
|  |           this.isLoading = false; | ||||||
|  |           this.openGraphService.fail('pool-stats-' + this.slug); | ||||||
|  |           return of(null); | ||||||
|  |         }) | ||||||
|  |       ); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   prepareChartOptions(data) { | ||||||
|  |     let title: object; | ||||||
|  |     if (data.length === 0) { | ||||||
|  |       title = { | ||||||
|  |         textStyle: { | ||||||
|  |           color: 'grey', | ||||||
|  |           fontSize: 15 | ||||||
|  |         }, | ||||||
|  |         text: $localize`:@@23555386d8af1ff73f297e89dd4af3f4689fb9dd:Indexing blocks`, | ||||||
|  |         left: 'center', | ||||||
|  |         top: 'center' | ||||||
|  |       }; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     this.chartOptions = { | ||||||
|  |       title: title, | ||||||
|  |       animation: false, | ||||||
|  |       color: [ | ||||||
|  |         new graphic.LinearGradient(0, 0, 0, 0.65, [ | ||||||
|  |           { offset: 0, color: '#F4511E' }, | ||||||
|  |           { offset: 0.25, color: '#FB8C00' }, | ||||||
|  |           { offset: 0.5, color: '#FFB300' }, | ||||||
|  |           { offset: 0.75, color: '#FDD835' }, | ||||||
|  |           { offset: 1, color: '#7CB342' } | ||||||
|  |         ]), | ||||||
|  |         '#D81B60', | ||||||
|  |       ], | ||||||
|  |       grid: { | ||||||
|  |         left: 15, | ||||||
|  |         right: 15, | ||||||
|  |         bottom: 15, | ||||||
|  |         top: 15, | ||||||
|  |         show: false, | ||||||
|  |       }, | ||||||
|  |       xAxis: data.length === 0 ? undefined : { | ||||||
|  |         type: 'time', | ||||||
|  |         show: false, | ||||||
|  |       }, | ||||||
|  |       yAxis: data.length === 0 ? undefined : [ | ||||||
|  |         { | ||||||
|  |           type: 'value', | ||||||
|  |           show: false, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |       series: data.length === 0 ? undefined : [ | ||||||
|  |         { | ||||||
|  |           zlevel: 0, | ||||||
|  |           name: 'Hashrate', | ||||||
|  |           showSymbol: false, | ||||||
|  |           symbol: 'none', | ||||||
|  |           data: data, | ||||||
|  |           type: 'line', | ||||||
|  |           lineStyle: { | ||||||
|  |             width: 4, | ||||||
|  |           }, | ||||||
|  |         }, | ||||||
|  |       ], | ||||||
|  |     }; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   onChartReady(): void { | ||||||
|  |     this.openGraphService.waitOver('pool-chart-' + this.slug); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   onImageLoad(): void { | ||||||
|  |     this.imageLoaded = true; | ||||||
|  |     this.openGraphService.waitOver('pool-img-' + this.slug); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   onImageFail(): void { | ||||||
|  |     this.imageLoaded = false; | ||||||
|  |     this.openGraphService.waitOver('pool-img-' + this.slug); | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -3,12 +3,12 @@ import { ActivatedRoute } from '@angular/router'; | |||||||
| import { EChartsOption, graphic } from 'echarts'; | import { EChartsOption, graphic } from 'echarts'; | ||||||
| import { BehaviorSubject, Observable, timer } from 'rxjs'; | import { BehaviorSubject, Observable, timer } from 'rxjs'; | ||||||
| import { distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | import { distinctUntilChanged, map, share, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { BlockExtended, PoolStat } from 'src/app/interfaces/node-api.interface'; | import { BlockExtended, PoolStat } from '../../interfaces/node-api.interface'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { selectPowerOfTen } from 'src/app/bitcoin.utils'; | import { selectPowerOfTen } from '../../bitcoin.utils'; | ||||||
| import { formatNumber } from '@angular/common'; | import { formatNumber } from '@angular/common'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-pool', |   selector: 'app-pool', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-push-transaction', |   selector: 'app-push-transaction', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, Input, AfterViewInit, ViewChild, ElementRef, ChangeDetectionStrategy } from '@angular/core'; | import { Component, Input, AfterViewInit, ViewChild, ElementRef, ChangeDetectionStrategy } from '@angular/core'; | ||||||
| import * as QRCode from 'qrcode'; | import * as QRCode from 'qrcode'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-qrcode', |   selector: 'app-qrcode', | ||||||
|  | |||||||
| @ -1,8 +1,8 @@ | |||||||
| import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core'; | ||||||
| import { concat, Observable } from 'rxjs'; | import { concat, Observable } from 'rxjs'; | ||||||
| import { map, switchMap, tap } from 'rxjs/operators'; | import { map, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-reward-stats', |   selector: 'app-reward-stats', | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ | |||||||
|     <div class="search-box-container mr-2"> |     <div class="search-box-container mr-2"> | ||||||
|       <input (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="Search the full Bitcoin ecosystem"> |       <input (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="Search the full Bitcoin ecosystem"> | ||||||
|        |        | ||||||
|       <app-search-results #searchResults [results]="typeAhead$ | async" [searchTerm]="searchForm.get('searchText').value" (selectedResult)="selectedResult($event)"></app-search-results> |       <app-search-results #searchResults [results]="typeAhead$ | async" (selectedResult)="selectedResult($event)"></app-search-results> | ||||||
|      |      | ||||||
|     </div> |     </div> | ||||||
|     <div> |     <div> | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ViewChild, HostListener } from '@angular/core'; | import { Component, OnInit, ChangeDetectionStrategy, EventEmitter, Output, ViewChild, HostListener } from '@angular/core'; | ||||||
| import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; | ||||||
| import { Router } from '@angular/router'; | import { Router } from '@angular/router'; | ||||||
| import { AssetsService } from 'src/app/services/assets.service'; | import { AssetsService } from '../../services/assets.service'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { Observable, of, Subject, zip, BehaviorSubject } from 'rxjs'; | import { Observable, of, Subject, zip, BehaviorSubject } from 'rxjs'; | ||||||
| import { debounceTime, distinctUntilChanged, switchMap, catchError, map } from 'rxjs/operators'; | import { debounceTime, distinctUntilChanged, switchMap, catchError, map } from 'rxjs/operators'; | ||||||
| import { ElectrsApiService } from 'src/app/services/electrs-api.service'; | import { ElectrsApiService } from '../../services/electrs-api.service'; | ||||||
| import { RelativeUrlPipe } from 'src/app/shared/pipes/relative-url/relative-url.pipe'; | import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SearchResultsComponent } from './search-results/search-results.component'; | import { SearchResultsComponent } from './search-results/search-results.component'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
| @ -74,6 +74,7 @@ export class SearchFormComponent implements OnInit { | |||||||
|         switchMap((text) => { |         switchMap((text) => { | ||||||
|           if (!text.length) { |           if (!text.length) { | ||||||
|             return of([ |             return of([ | ||||||
|  |               '', | ||||||
|               [], |               [], | ||||||
|               { |               { | ||||||
|                 nodes: [], |                 nodes: [], | ||||||
| @ -84,11 +85,14 @@ export class SearchFormComponent implements OnInit { | |||||||
|           this.isTypeaheading$.next(true); |           this.isTypeaheading$.next(true); | ||||||
|           if (!this.stateService.env.LIGHTNING) { |           if (!this.stateService.env.LIGHTNING) { | ||||||
|             return zip( |             return zip( | ||||||
|  |               of(text), | ||||||
|               this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))), |               this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))), | ||||||
|               [{ nodes: [], channels: [] }] |               [{ nodes: [], channels: [] }], | ||||||
|  |               of(this.regexBlockheight.test(text)), | ||||||
|             ); |             ); | ||||||
|           } |           } | ||||||
|           return zip( |           return zip( | ||||||
|  |             of(text), | ||||||
|             this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))), |             this.electrsApiService.getAddressesByPrefix$(text).pipe(catchError(() => of([]))), | ||||||
|             this.apiService.lightningSearch$(text).pipe(catchError(() => of({ |             this.apiService.lightningSearch$(text).pipe(catchError(() => of({ | ||||||
|               nodes: [], |               nodes: [], | ||||||
| @ -102,10 +106,12 @@ export class SearchFormComponent implements OnInit { | |||||||
|             return result[0].map((address: string) => 'B' + address); |             return result[0].map((address: string) => 'B' + address); | ||||||
|           } |           } | ||||||
|           return { |           return { | ||||||
|             addresses: result[0], |             searchText: result[0], | ||||||
|             nodes: result[1].nodes, |             blockHeight: this.regexBlockheight.test(result[0]) ? [parseInt(result[0], 10)] : [], | ||||||
|             channels: result[1].channels, |             addresses: result[1], | ||||||
|             totalResults: result[0].length + result[1].nodes.length + result[1].channels.length, |             nodes: result[2].nodes, | ||||||
|  |             channels: result[2].channels, | ||||||
|  |             totalResults: result[1].length + result[2].nodes.length + result[2].channels.length, | ||||||
|           }; |           }; | ||||||
|         }) |         }) | ||||||
|       ); |       ); | ||||||
| @ -121,6 +127,8 @@ export class SearchFormComponent implements OnInit { | |||||||
|   selectedResult(result: any) { |   selectedResult(result: any) { | ||||||
|     if (typeof result === 'string') { |     if (typeof result === 'string') { | ||||||
|       this.search(result); |       this.search(result); | ||||||
|  |     } else if (typeof result === 'number') { | ||||||
|  |       this.navigate('/block/', result.toString()); | ||||||
|     } else if (result.alias) { |     } else if (result.alias) { | ||||||
|       this.navigate('/lightning/node/', result.public_key); |       this.navigate('/lightning/node/', result.public_key); | ||||||
|     } else if (result.short_id) { |     } else if (result.short_id) { | ||||||
|  | |||||||
| @ -1,25 +1,31 @@ | |||||||
| <div class="dropdown-menu show" *ngIf="results" [hidden]="!results.addresses.length && !results.nodes.length && !results.channels.length"> | <div class="dropdown-menu show" *ngIf="results" [hidden]="!results.blockHeight.length && !results.addresses.length && !results.nodes.length && !results.channels.length"> | ||||||
|  |   <ng-template [ngIf]="results.blockHeight.length"> | ||||||
|  |     <div class="card-title">Bitcoin Block Height</div> | ||||||
|  |     <button (click)="clickItem(0)" [class.active]="0 === activeIdx" type="button" role="option" class="dropdown-item"> | ||||||
|  |       Go to "{{ results.searchText }}" | ||||||
|  |     </button> | ||||||
|  |   </ng-template> | ||||||
|   <ng-template [ngIf]="results.addresses.length"> |   <ng-template [ngIf]="results.addresses.length"> | ||||||
|     <div class="card-title" *ngIf="stateService.env.LIGHTNING">Bitcoin Addresses</div> |     <div class="card-title" *ngIf="stateService.env.LIGHTNING">Bitcoin Addresses</div> | ||||||
|     <ng-template ngFor [ngForOf]="results.addresses" let-address let-i="index"> |     <ng-template ngFor [ngForOf]="results.addresses" let-address let-i="index"> | ||||||
|       <button (click)="clickItem(i)" [class.active]="i === activeIdx" type="button" role="option" class="dropdown-item"> |       <button (click)="clickItem(results.blockHeight.length + i)" [class.active]="(results.blockHeight.length + i) === activeIdx" type="button" role="option" class="dropdown-item"> | ||||||
|         <ngb-highlight [result]="address | shortenString : isMobile ? 25 : 36" [term]="searchTerm"></ngb-highlight> |         <ngb-highlight [result]="address | shortenString : isMobile ? 25 : 36" [term]="results.searchText"></ngb-highlight> | ||||||
|       </button> |       </button> | ||||||
|     </ng-template> |     </ng-template> | ||||||
|   </ng-template> |   </ng-template> | ||||||
|   <ng-template [ngIf]="results.nodes.length"> |   <ng-template [ngIf]="results.nodes.length"> | ||||||
|     <div class="card-title">Lightning Nodes</div> |     <div class="card-title">Lightning Nodes</div> | ||||||
|     <ng-template ngFor [ngForOf]="results.nodes" let-node let-i="index"> |     <ng-template ngFor [ngForOf]="results.nodes" let-node let-i="index"> | ||||||
|       <button (click)="clickItem(results.addresses.length + i)" [class.inactive]="node.status === 0" [class.active]="results.addresses.length + i === activeIdx" [routerLink]="['/lightning/node' | relativeUrl, node.public_key]" type="button" role="option" class="dropdown-item"> |       <button (click)="clickItem(results.blockHeight.length + results.addresses.length + i)" [class.inactive]="node.status === 0" [class.active]="results.blockHeight.length + results.addresses.length + i === activeIdx" [routerLink]="['/lightning/node' | relativeUrl, node.public_key]" type="button" role="option" class="dropdown-item"> | ||||||
|         <ngb-highlight [result]="node.alias" [term]="searchTerm"></ngb-highlight>  <span class="symbol">{{ node.public_key | shortenString : 10 }}</span> |         <ngb-highlight [result]="node.alias" [term]="results.searchText"></ngb-highlight>  <span class="symbol">{{ node.public_key | shortenString : 10 }}</span> | ||||||
|       </button> |       </button> | ||||||
|     </ng-template> |     </ng-template> | ||||||
|   </ng-template> |   </ng-template> | ||||||
|   <ng-template [ngIf]="results.channels.length"> |   <ng-template [ngIf]="results.channels.length"> | ||||||
|     <div class="card-title">Lightning Channels</div> |     <div class="card-title">Lightning Channels</div> | ||||||
|     <ng-template ngFor [ngForOf]="results.channels" let-channel let-i="index"> |     <ng-template ngFor [ngForOf]="results.channels" let-channel let-i="index"> | ||||||
|       <button (click)="clickItem(results.addresses.length + results.nodes.length + i)" [class.inactive]="channel.status === 2"  [class.active]="results.addresses.length + results.nodes.length + i === activeIdx" type="button" role="option" class="dropdown-item"> |       <button (click)="clickItem(results.blockHeight.length + results.addresses.length + results.nodes.length + i)" [class.inactive]="channel.status === 2"  [class.active]="results.blockHeight.length + results.addresses.length + results.nodes.length + i === activeIdx" type="button" role="option" class="dropdown-item"> | ||||||
|         <ngb-highlight [result]="channel.short_id" [term]="searchTerm"></ngb-highlight>  <span class="symbol">{{ channel.id }}</span> |         <ngb-highlight [result]="channel.short_id" [term]="results.searchText"></ngb-highlight>  <span class="symbol">{{ channel.id }}</span> | ||||||
|       </button> |       </button> | ||||||
|     </ng-template> |     </ng-template> | ||||||
|   </ng-template> |   </ng-template> | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; | import { Component, EventEmitter, Input, OnChanges, Output } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../../services/state.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-search-results', |   selector: 'app-search-results', | ||||||
| @ -8,7 +8,6 @@ import { StateService } from 'src/app/services/state.service'; | |||||||
| }) | }) | ||||||
| export class SearchResultsComponent implements OnChanges { | export class SearchResultsComponent implements OnChanges { | ||||||
|   @Input() results: any = {}; |   @Input() results: any = {}; | ||||||
|   @Input() searchTerm = ''; |  | ||||||
|   @Output() selectedResult = new EventEmitter(); |   @Output() selectedResult = new EventEmitter(); | ||||||
| 
 | 
 | ||||||
|   isMobile = (window.innerWidth <= 767.98); |   isMobile = (window.innerWidth <= 767.98); | ||||||
| @ -16,12 +15,14 @@ export class SearchResultsComponent implements OnChanges { | |||||||
|   activeIdx = 0; |   activeIdx = 0; | ||||||
|   focusFirst = true; |   focusFirst = true; | ||||||
| 
 | 
 | ||||||
|   constructor(public stateService: StateService) { } |   constructor( | ||||||
|  |     public stateService: StateService, | ||||||
|  |     ) { } | ||||||
| 
 | 
 | ||||||
|   ngOnChanges() { |   ngOnChanges() { | ||||||
|     this.activeIdx = 0; |     this.activeIdx = 0; | ||||||
|     if (this.results) { |     if (this.results) { | ||||||
|       this.resultsFlattened = [...this.results.addresses, ...this.results.nodes, ...this.results.channels]; |       this.resultsFlattened = [...this.results.blockHeight, ...this.results.addresses, ...this.results.nodes, ...this.results.channels]; | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -47,7 +48,7 @@ export class SearchResultsComponent implements OnChanges { | |||||||
|         if (this.resultsFlattened[this.activeIdx]) { |         if (this.resultsFlattened[this.activeIdx]) { | ||||||
|           this.selectedResult.emit(this.resultsFlattened[this.activeIdx]); |           this.selectedResult.emit(this.resultsFlattened[this.activeIdx]); | ||||||
|         } else { |         } else { | ||||||
|           this.selectedResult.emit(this.searchTerm); |           this.selectedResult.emit(this.results.searchText); | ||||||
|         } |         } | ||||||
|         this.results = null; |         this.results = null; | ||||||
|         break; |         break; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core'; | import { Component, ElementRef, HostListener, OnInit, ViewChild } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { specialBlocks } from 'src/app/app.constants'; | import { specialBlocks } from '../../app.constants'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-start', |   selector: 'app-start', | ||||||
|  | |||||||
| @ -8,10 +8,10 @@ import { OptimizedMempoolStats } from '../../interfaces/node-api.interface'; | |||||||
| import { WebsocketService } from '../../services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { ApiService } from '../../services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| 
 | 
 | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { StorageService } from 'src/app/services/storage.service'; | import { StorageService } from '../../services/storage.service'; | ||||||
| import { feeLevels, chartColors } from 'src/app/app.constants'; | import { feeLevels, chartColors } from '../../app.constants'; | ||||||
| import { MempoolGraphComponent } from '../mempool-graph/mempool-graph.component'; | import { MempoolGraphComponent } from '../mempool-graph/mempool-graph.component'; | ||||||
| import { IncomingTransactionsGraphComponent } from '../incoming-transactions-graph/incoming-transactions-graph.component'; | import { IncomingTransactionsGraphComponent } from '../incoming-transactions-graph/incoming-transactions-graph.component'; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-status-view', |   selector: 'app-status-view', | ||||||
|  | |||||||
| @ -1,9 +1,9 @@ | |||||||
| import { Component, OnInit } from '@angular/core'; | import { Component, OnInit } from '@angular/core'; | ||||||
| import { WebsocketService } from 'src/app/services/websocket.service'; | import { WebsocketService } from '../../services/websocket.service'; | ||||||
| import { OptimizedMempoolStats } from '../../interfaces/node-api.interface'; | import { OptimizedMempoolStats } from '../../interfaces/node-api.interface'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { ApiService } from 'src/app/services/api.service'; | import { ApiService } from '../../services/api.service'; | ||||||
| import { SeoService } from 'src/app/services/seo.service'; | import { SeoService } from '../../services/seo.service'; | ||||||
| import { ActivatedRoute } from '@angular/router'; | import { ActivatedRoute } from '@angular/router'; | ||||||
| import { map, scan, startWith, switchMap, tap } from 'rxjs/operators'; | import { map, scan, startWith, switchMap, tap } from 'rxjs/operators'; | ||||||
| import { interval, merge, Observable } from 'rxjs'; | import { interval, merge, Observable } from 'rxjs'; | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { dates } from 'src/app/shared/i18n/dates'; | import { dates } from '../../shared/i18n/dates'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-time-since', |   selector: 'app-time-since', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { dates } from 'src/app/shared/i18n/dates'; | import { dates } from '../../shared/i18n/dates'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-time-span', |   selector: 'app-time-span', | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; | import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, Input, ChangeDetectorRef, OnChanges } from '@angular/core'; | ||||||
| import { StateService } from 'src/app/services/state.service'; | import { StateService } from '../../services/state.service'; | ||||||
| import { dates } from 'src/app/shared/i18n/dates'; | import { dates } from '../../shared/i18n/dates'; | ||||||
| 
 | 
 | ||||||
| @Component({ | @Component({ | ||||||
|   selector: 'app-time-until', |   selector: 'app-time-until', | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user