Merge branch 'master' into mononaut/confirmed-tx-status
This commit is contained in:
commit
90634c4343
@ -40,7 +40,9 @@
|
|||||||
"PORT": 8332,
|
"PORT": 8332,
|
||||||
"USERNAME": "mempool",
|
"USERNAME": "mempool",
|
||||||
"PASSWORD": "mempool",
|
"PASSWORD": "mempool",
|
||||||
"TIMEOUT": 60000
|
"TIMEOUT": 60000,
|
||||||
|
"COOKIE": false,
|
||||||
|
"COOKIE_PATH": "/path/to/bitcoin/.cookie"
|
||||||
},
|
},
|
||||||
"ELECTRUM": {
|
"ELECTRUM": {
|
||||||
"HOST": "127.0.0.1",
|
"HOST": "127.0.0.1",
|
||||||
@ -60,7 +62,9 @@
|
|||||||
"PORT": 8332,
|
"PORT": 8332,
|
||||||
"USERNAME": "mempool",
|
"USERNAME": "mempool",
|
||||||
"PASSWORD": "mempool",
|
"PASSWORD": "mempool",
|
||||||
"TIMEOUT": 60000
|
"TIMEOUT": 60000,
|
||||||
|
"COOKIE": false,
|
||||||
|
"COOKIE_PATH": "/path/to/bitcoin/.cookie"
|
||||||
},
|
},
|
||||||
"DATABASE": {
|
"DATABASE": {
|
||||||
"ENABLED": true,
|
"ENABLED": true,
|
||||||
|
14
backend/package-lock.json
generated
14
backend/package-lock.json
generated
@ -12,7 +12,7 @@
|
|||||||
"@babel/core": "^7.23.2",
|
"@babel/core": "^7.23.2",
|
||||||
"@mempool/electrum-client": "1.1.9",
|
"@mempool/electrum-client": "1.1.9",
|
||||||
"@types/node": "^18.15.3",
|
"@types/node": "^18.15.3",
|
||||||
"axios": "~1.5.0",
|
"axios": "~1.6.1",
|
||||||
"bitcoinjs-lib": "~6.1.3",
|
"bitcoinjs-lib": "~6.1.3",
|
||||||
"crypto-js": "~4.2.0",
|
"crypto-js": "~4.2.0",
|
||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
@ -2325,9 +2325,9 @@
|
|||||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
},
|
},
|
||||||
"node_modules/axios": {
|
"node_modules/axios": {
|
||||||
"version": "1.5.0",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
|
||||||
"integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
|
"integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.0",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
@ -9415,9 +9415,9 @@
|
|||||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||||
},
|
},
|
||||||
"axios": {
|
"axios": {
|
||||||
"version": "1.5.0",
|
"version": "1.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/axios/-/axios-1.6.1.tgz",
|
||||||
"integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==",
|
"integrity": "sha512-vfBmhDpKafglh0EldBEbVuoe7DyAavGSLWhuSm5ZSEKQnHhBf0xAAwybbNH1IkrJNGnS/VG4I5yxig1pCEXE4g==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"follow-redirects": "^1.15.0",
|
"follow-redirects": "^1.15.0",
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
"@babel/core": "^7.23.2",
|
"@babel/core": "^7.23.2",
|
||||||
"@mempool/electrum-client": "1.1.9",
|
"@mempool/electrum-client": "1.1.9",
|
||||||
"@types/node": "^18.15.3",
|
"@types/node": "^18.15.3",
|
||||||
"axios": "~1.5.0",
|
"axios": "~1.6.1",
|
||||||
"bitcoinjs-lib": "~6.1.3",
|
"bitcoinjs-lib": "~6.1.3",
|
||||||
"crypto-js": "~4.2.0",
|
"crypto-js": "~4.2.0",
|
||||||
"express": "~4.18.2",
|
"express": "~4.18.2",
|
||||||
|
@ -41,7 +41,9 @@
|
|||||||
"PORT": 15,
|
"PORT": 15,
|
||||||
"USERNAME": "__CORE_RPC_USERNAME__",
|
"USERNAME": "__CORE_RPC_USERNAME__",
|
||||||
"PASSWORD": "__CORE_RPC_PASSWORD__",
|
"PASSWORD": "__CORE_RPC_PASSWORD__",
|
||||||
"TIMEOUT": 1000
|
"TIMEOUT": 1000,
|
||||||
|
"COOKIE": false,
|
||||||
|
"COOKIE_PATH": "__CORE_RPC_COOKIE_PATH__"
|
||||||
},
|
},
|
||||||
"ELECTRUM": {
|
"ELECTRUM": {
|
||||||
"HOST": "__ELECTRUM_HOST__",
|
"HOST": "__ELECTRUM_HOST__",
|
||||||
@ -61,7 +63,9 @@
|
|||||||
"PORT": 17,
|
"PORT": 17,
|
||||||
"USERNAME": "__SECOND_CORE_RPC_USERNAME__",
|
"USERNAME": "__SECOND_CORE_RPC_USERNAME__",
|
||||||
"PASSWORD": "__SECOND_CORE_RPC_PASSWORD__",
|
"PASSWORD": "__SECOND_CORE_RPC_PASSWORD__",
|
||||||
"TIMEOUT": 2000
|
"TIMEOUT": 2000,
|
||||||
|
"COOKIE": false,
|
||||||
|
"COOKIE_PATH": "__SECOND_CORE_RPC_COOKIE_PATH__"
|
||||||
},
|
},
|
||||||
"DATABASE": {
|
"DATABASE": {
|
||||||
"ENABLED": false,
|
"ENABLED": false,
|
||||||
|
@ -66,7 +66,9 @@ describe('Mempool Backend Config', () => {
|
|||||||
PORT: 8332,
|
PORT: 8332,
|
||||||
USERNAME: 'mempool',
|
USERNAME: 'mempool',
|
||||||
PASSWORD: 'mempool',
|
PASSWORD: 'mempool',
|
||||||
TIMEOUT: 60000
|
TIMEOUT: 60000,
|
||||||
|
COOKIE: false,
|
||||||
|
COOKIE_PATH: '/bitcoin/.cookie'
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config.SECOND_CORE_RPC).toStrictEqual({
|
expect(config.SECOND_CORE_RPC).toStrictEqual({
|
||||||
@ -74,7 +76,9 @@ describe('Mempool Backend Config', () => {
|
|||||||
PORT: 8332,
|
PORT: 8332,
|
||||||
USERNAME: 'mempool',
|
USERNAME: 'mempool',
|
||||||
PASSWORD: 'mempool',
|
PASSWORD: 'mempool',
|
||||||
TIMEOUT: 60000
|
TIMEOUT: 60000,
|
||||||
|
COOKIE: false,
|
||||||
|
COOKIE_PATH: '/bitcoin/.cookie'
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(config.DATABASE).toStrictEqual({
|
expect(config.DATABASE).toStrictEqual({
|
||||||
|
@ -32,4 +32,5 @@ export interface BitcoinRpcCredentials {
|
|||||||
user: string;
|
user: string;
|
||||||
pass: string;
|
pass: string;
|
||||||
timeout: number;
|
timeout: number;
|
||||||
|
cookie?: string;
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ const nodeRpcCredentials: BitcoinRpcCredentials = {
|
|||||||
user: config.CORE_RPC.USERNAME,
|
user: config.CORE_RPC.USERNAME,
|
||||||
pass: config.CORE_RPC.PASSWORD,
|
pass: config.CORE_RPC.PASSWORD,
|
||||||
timeout: config.CORE_RPC.TIMEOUT,
|
timeout: config.CORE_RPC.TIMEOUT,
|
||||||
|
cookie: config.CORE_RPC.COOKIE ? config.CORE_RPC.COOKIE_PATH : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default new bitcoin.Client(nodeRpcCredentials);
|
export default new bitcoin.Client(nodeRpcCredentials);
|
||||||
|
@ -8,6 +8,7 @@ const nodeRpcCredentials: BitcoinRpcCredentials = {
|
|||||||
user: config.SECOND_CORE_RPC.USERNAME,
|
user: config.SECOND_CORE_RPC.USERNAME,
|
||||||
pass: config.SECOND_CORE_RPC.PASSWORD,
|
pass: config.SECOND_CORE_RPC.PASSWORD,
|
||||||
timeout: config.SECOND_CORE_RPC.TIMEOUT,
|
timeout: config.SECOND_CORE_RPC.TIMEOUT,
|
||||||
|
cookie: config.SECOND_CORE_RPC.COOKIE ? config.SECOND_CORE_RPC.COOKIE_PATH : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default new bitcoin.Client(nodeRpcCredentials);
|
export default new bitcoin.Client(nodeRpcCredentials);
|
||||||
|
@ -252,7 +252,11 @@ class DiskCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rbfData?.rbf) {
|
if (rbfData?.rbf) {
|
||||||
rbfCache.load(rbfData.rbf);
|
rbfCache.load({
|
||||||
|
txs: rbfData.rbf.txs.map(([txid, entry]) => ({ value: entry })),
|
||||||
|
trees: rbfData.rbf.trees,
|
||||||
|
expiring: rbfData.rbf.expiring.map(([txid, value]) => ({ key: txid, value })),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.warn('Failed to parse rbf cache. Skipping. Reason: ' + (e instanceof Error ? e.message : e));
|
logger.warn('Failed to parse rbf cache. Skipping. Reason: ' + (e instanceof Error ? e.message : e));
|
||||||
|
@ -53,6 +53,9 @@ class RbfCache {
|
|||||||
private expiring: Map<string, number> = new Map();
|
private expiring: Map<string, number> = new Map();
|
||||||
private cacheQueue: CacheEvent[] = [];
|
private cacheQueue: CacheEvent[] = [];
|
||||||
|
|
||||||
|
private evictionCount = 0;
|
||||||
|
private staleCount = 0;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
setInterval(this.cleanup.bind(this), 1000 * 60 * 10);
|
setInterval(this.cleanup.bind(this), 1000 * 60 * 10);
|
||||||
}
|
}
|
||||||
@ -245,6 +248,7 @@ class RbfCache {
|
|||||||
|
|
||||||
// flag a transaction as removed from the mempool
|
// flag a transaction as removed from the mempool
|
||||||
public evict(txid: string, fast: boolean = false): void {
|
public evict(txid: string, fast: boolean = false): void {
|
||||||
|
this.evictionCount++;
|
||||||
if (this.txs.has(txid) && (fast || !this.expiring.has(txid))) {
|
if (this.txs.has(txid) && (fast || !this.expiring.has(txid))) {
|
||||||
const expiryTime = fast ? Date.now() + (1000 * 60 * 10) : Date.now() + (1000 * 86400); // 24 hours
|
const expiryTime = fast ? Date.now() + (1000 * 60 * 10) : Date.now() + (1000 * 86400); // 24 hours
|
||||||
this.addExpiration(txid, expiryTime);
|
this.addExpiration(txid, expiryTime);
|
||||||
@ -272,18 +276,23 @@ class RbfCache {
|
|||||||
this.remove(txid);
|
this.remove(txid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
logger.debug(`rbf cache contains ${this.txs.size} txs, ${this.rbfTrees.size} trees, ${this.expiring.size} due to expire`);
|
logger.debug(`rbf cache contains ${this.txs.size} txs, ${this.rbfTrees.size} trees, ${this.expiring.size} due to expire (${this.evictionCount} newly expired)`);
|
||||||
|
this.evictionCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove a transaction & all previous versions from the cache
|
// remove a transaction & all previous versions from the cache
|
||||||
private remove(txid): void {
|
private remove(txid): void {
|
||||||
// don't remove a transaction if a newer version remains in the mempool
|
// don't remove a transaction if a newer version remains in the mempool
|
||||||
if (!this.replacedBy.has(txid)) {
|
if (!this.replacedBy.has(txid)) {
|
||||||
|
const root = this.treeMap.get(txid);
|
||||||
const replaces = this.replaces.get(txid);
|
const replaces = this.replaces.get(txid);
|
||||||
this.replaces.delete(txid);
|
this.replaces.delete(txid);
|
||||||
this.treeMap.delete(txid);
|
this.treeMap.delete(txid);
|
||||||
this.removeTx(txid);
|
this.removeTx(txid);
|
||||||
this.removeExpiration(txid);
|
this.removeExpiration(txid);
|
||||||
|
if (root === txid) {
|
||||||
|
this.removeTree(txid);
|
||||||
|
}
|
||||||
for (const tx of (replaces || [])) {
|
for (const tx of (replaces || [])) {
|
||||||
// recursively remove prior versions from the cache
|
// recursively remove prior versions from the cache
|
||||||
this.replacedBy.delete(tx);
|
this.replacedBy.delete(tx);
|
||||||
@ -359,9 +368,11 @@ class RbfCache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async load({ txs, trees, expiring }): Promise<void> {
|
public async load({ txs, trees, expiring }): Promise<void> {
|
||||||
|
try {
|
||||||
txs.forEach(txEntry => {
|
txs.forEach(txEntry => {
|
||||||
this.txs.set(txEntry.key, txEntry.value);
|
this.txs.set(txEntry.value.txid, txEntry.value);
|
||||||
});
|
});
|
||||||
|
this.staleCount = 0;
|
||||||
for (const deflatedTree of trees) {
|
for (const deflatedTree of trees) {
|
||||||
await this.importTree(deflatedTree.root, deflatedTree.root, deflatedTree, this.txs);
|
await this.importTree(deflatedTree.root, deflatedTree.root, deflatedTree, this.txs);
|
||||||
}
|
}
|
||||||
@ -370,7 +381,12 @@ class RbfCache {
|
|||||||
this.expiring.set(expiringEntry.key, new Date(expiringEntry.value).getTime());
|
this.expiring.set(expiringEntry.key, new Date(expiringEntry.value).getTime());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
logger.debug(`loaded ${txs.length} txs, ${trees.length} trees into rbf cache, ${expiring.length} due to expire, ${this.staleCount} were stale`);
|
||||||
|
this.staleCount = 0;
|
||||||
this.cleanup();
|
this.cleanup();
|
||||||
|
} catch (e) {
|
||||||
|
logger.err('failed to restore RBF cache: ' + (e instanceof Error ? e.message : e));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exportTree(tree: RbfTree, deflated: any = null) {
|
exportTree(tree: RbfTree, deflated: any = null) {
|
||||||
@ -398,6 +414,13 @@ class RbfCache {
|
|||||||
const treeInfo = deflated[txid];
|
const treeInfo = deflated[txid];
|
||||||
const replaces: RbfTree[] = [];
|
const replaces: RbfTree[] = [];
|
||||||
|
|
||||||
|
// if the root tx is unknown, remove this tree and return early
|
||||||
|
if (root === txid && !txs.has(txid)) {
|
||||||
|
this.staleCount++;
|
||||||
|
this.removeTree(deflated.key);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// check if any transactions in this tree have already been confirmed
|
// check if any transactions in this tree have already been confirmed
|
||||||
mined = mined || treeInfo.mined;
|
mined = mined || treeInfo.mined;
|
||||||
let exists = mined;
|
let exists = mined;
|
||||||
@ -413,7 +436,7 @@ class RbfCache {
|
|||||||
this.evict(txid, true);
|
this.evict(txid, true);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// most transactions do not exist
|
// most transactions only exist in our cache
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ class RedisCache {
|
|||||||
await memPool.$setMempool(loadedMempool);
|
await memPool.$setMempool(loadedMempool);
|
||||||
await rbfCache.load({
|
await rbfCache.load({
|
||||||
txs: rbfTxs,
|
txs: rbfTxs,
|
||||||
trees: rbfTrees.map(loadedTree => loadedTree.value),
|
trees: rbfTrees.map(loadedTree => { loadedTree.value.key = loadedTree.key; return loadedTree.value; }),
|
||||||
expiring: rbfExpirations,
|
expiring: rbfExpirations,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -577,7 +577,7 @@ class WebsocketHandler {
|
|||||||
response['utxoSpent'] = JSON.stringify(outspends);
|
response['utxoSpent'] = JSON.stringify(outspends);
|
||||||
}
|
}
|
||||||
|
|
||||||
const rbfReplacedBy = rbfCache.getReplacedBy(client['track-tx']);
|
const rbfReplacedBy = rbfChanges.map[client['track-tx']] ? rbfCache.getReplacedBy(client['track-tx']) : false;
|
||||||
if (rbfReplacedBy) {
|
if (rbfReplacedBy) {
|
||||||
response['rbfTransaction'] = JSON.stringify({
|
response['rbfTransaction'] = JSON.stringify({
|
||||||
txid: rbfReplacedBy,
|
txid: rbfReplacedBy,
|
||||||
|
@ -78,6 +78,8 @@ interface IConfig {
|
|||||||
USERNAME: string;
|
USERNAME: string;
|
||||||
PASSWORD: string;
|
PASSWORD: string;
|
||||||
TIMEOUT: number;
|
TIMEOUT: number;
|
||||||
|
COOKIE: boolean;
|
||||||
|
COOKIE_PATH: string;
|
||||||
};
|
};
|
||||||
SECOND_CORE_RPC: {
|
SECOND_CORE_RPC: {
|
||||||
HOST: string;
|
HOST: string;
|
||||||
@ -85,6 +87,8 @@ interface IConfig {
|
|||||||
USERNAME: string;
|
USERNAME: string;
|
||||||
PASSWORD: string;
|
PASSWORD: string;
|
||||||
TIMEOUT: number;
|
TIMEOUT: number;
|
||||||
|
COOKIE: boolean;
|
||||||
|
COOKIE_PATH: string;
|
||||||
};
|
};
|
||||||
DATABASE: {
|
DATABASE: {
|
||||||
ENABLED: boolean;
|
ENABLED: boolean;
|
||||||
@ -207,6 +211,8 @@ const defaults: IConfig = {
|
|||||||
'USERNAME': 'mempool',
|
'USERNAME': 'mempool',
|
||||||
'PASSWORD': 'mempool',
|
'PASSWORD': 'mempool',
|
||||||
'TIMEOUT': 60000,
|
'TIMEOUT': 60000,
|
||||||
|
'COOKIE': false,
|
||||||
|
'COOKIE_PATH': '/bitcoin/.cookie'
|
||||||
},
|
},
|
||||||
'SECOND_CORE_RPC': {
|
'SECOND_CORE_RPC': {
|
||||||
'HOST': '127.0.0.1',
|
'HOST': '127.0.0.1',
|
||||||
@ -214,6 +220,8 @@ const defaults: IConfig = {
|
|||||||
'USERNAME': 'mempool',
|
'USERNAME': 'mempool',
|
||||||
'PASSWORD': 'mempool',
|
'PASSWORD': 'mempool',
|
||||||
'TIMEOUT': 60000,
|
'TIMEOUT': 60000,
|
||||||
|
'COOKIE': false,
|
||||||
|
'COOKIE_PATH': '/bitcoin/.cookie'
|
||||||
},
|
},
|
||||||
'DATABASE': {
|
'DATABASE': {
|
||||||
'ENABLED': true,
|
'ENABLED': true,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
var http = require('http')
|
var http = require('http')
|
||||||
var https = require('https')
|
var https = require('https')
|
||||||
|
import { readFileSync } from 'fs';
|
||||||
|
|
||||||
var JsonRPC = function (opts) {
|
var JsonRPC = function (opts) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -55,7 +56,13 @@ JsonRPC.prototype.call = function (method, params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use HTTP auth if user and password set
|
// use HTTP auth if user and password set
|
||||||
if (this.opts.user && this.opts.pass) {
|
if (this.opts.cookie) {
|
||||||
|
if (!this.cachedCookie) {
|
||||||
|
this.cachedCookie = readFileSync(this.opts.cookie).toString();
|
||||||
|
}
|
||||||
|
// @ts-ignore
|
||||||
|
requestOptions.auth = this.cachedCookie;
|
||||||
|
} else if (this.opts.user && this.opts.pass) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
requestOptions.auth = this.opts.user + ':' + this.opts.pass
|
requestOptions.auth = this.opts.user + ':' + this.opts.pass
|
||||||
}
|
}
|
||||||
@ -93,7 +100,7 @@ JsonRPC.prototype.call = function (method, params) {
|
|||||||
reject(err)
|
reject(err)
|
||||||
})
|
})
|
||||||
|
|
||||||
request.on('response', function (response) {
|
request.on('response', (response) => {
|
||||||
clearTimeout(reqTimeout)
|
clearTimeout(reqTimeout)
|
||||||
|
|
||||||
// We need to buffer the response chunks in a nonblocking way.
|
// We need to buffer the response chunks in a nonblocking way.
|
||||||
@ -104,7 +111,7 @@ JsonRPC.prototype.call = function (method, params) {
|
|||||||
// When all the responses are finished, we decode the JSON and
|
// When all the responses are finished, we decode the JSON and
|
||||||
// depending on whether it's got a result or an error, we call
|
// depending on whether it's got a result or an error, we call
|
||||||
// emitSuccess or emitError on the promise.
|
// emitSuccess or emitError on the promise.
|
||||||
response.on('end', function () {
|
response.on('end', () => {
|
||||||
var err
|
var err
|
||||||
|
|
||||||
if (cbCalled) return
|
if (cbCalled) return
|
||||||
@ -113,6 +120,14 @@ JsonRPC.prototype.call = function (method, params) {
|
|||||||
try {
|
try {
|
||||||
var decoded = JSON.parse(buffer)
|
var decoded = JSON.parse(buffer)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
// if we authenticated using a cookie and it failed, read the cookie file again
|
||||||
|
if (
|
||||||
|
response.statusCode === 401 /* Unauthorized */ &&
|
||||||
|
this.opts.cookie
|
||||||
|
) {
|
||||||
|
this.cachedCookie = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
if (response.statusCode !== 200) {
|
if (response.statusCode !== 200) {
|
||||||
err = new Error('Invalid params, response status code: ' + response.statusCode)
|
err = new Error('Invalid params, response status code: ' + response.statusCode)
|
||||||
err.code = -32602
|
err.code = -32602
|
||||||
|
@ -164,7 +164,9 @@ Corresponding `docker-compose.yml` overrides:
|
|||||||
"PORT": 8332,
|
"PORT": 8332,
|
||||||
"USERNAME": "mempool",
|
"USERNAME": "mempool",
|
||||||
"PASSWORD": "mempool",
|
"PASSWORD": "mempool",
|
||||||
"TIMEOUT": 60000
|
"TIMEOUT": 60000,
|
||||||
|
"COOKIE": false,
|
||||||
|
"COOKIE_PATH": ""
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -177,6 +179,8 @@ Corresponding `docker-compose.yml` overrides:
|
|||||||
CORE_RPC_USERNAME: ""
|
CORE_RPC_USERNAME: ""
|
||||||
CORE_RPC_PASSWORD: ""
|
CORE_RPC_PASSWORD: ""
|
||||||
CORE_RPC_TIMEOUT: 60000
|
CORE_RPC_TIMEOUT: 60000
|
||||||
|
CORE_RPC_COOKIE: false
|
||||||
|
CORE_RPC_COOKIE_PATH: ""
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -231,7 +235,9 @@ Corresponding `docker-compose.yml` overrides:
|
|||||||
"PORT": 8332,
|
"PORT": 8332,
|
||||||
"USERNAME": "mempool",
|
"USERNAME": "mempool",
|
||||||
"PASSWORD": "mempool",
|
"PASSWORD": "mempool",
|
||||||
"TIMEOUT": 60000
|
"TIMEOUT": 60000,
|
||||||
|
"COOKIE": false,
|
||||||
|
"COOKIE_PATH": ""
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -244,6 +250,8 @@ Corresponding `docker-compose.yml` overrides:
|
|||||||
SECOND_CORE_RPC_USERNAME: ""
|
SECOND_CORE_RPC_USERNAME: ""
|
||||||
SECOND_CORE_RPC_PASSWORD: ""
|
SECOND_CORE_RPC_PASSWORD: ""
|
||||||
SECOND_CORE_RPC_TIMEOUT: ""
|
SECOND_CORE_RPC_TIMEOUT: ""
|
||||||
|
SECOND_CORE_RPC_COOKIE: false
|
||||||
|
SECOND_CORE_RPC_COOKIE_PATH: ""
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -41,7 +41,9 @@
|
|||||||
"PORT": __CORE_RPC_PORT__,
|
"PORT": __CORE_RPC_PORT__,
|
||||||
"USERNAME": "__CORE_RPC_USERNAME__",
|
"USERNAME": "__CORE_RPC_USERNAME__",
|
||||||
"PASSWORD": "__CORE_RPC_PASSWORD__",
|
"PASSWORD": "__CORE_RPC_PASSWORD__",
|
||||||
"TIMEOUT": __CORE_RPC_TIMEOUT__
|
"TIMEOUT": __CORE_RPC_TIMEOUT__,
|
||||||
|
"COOKIE": __CORE_RPC_COOKIE__,
|
||||||
|
"COOKIE_PATH": "__CORE_RPC_COOKIE_PATH__"
|
||||||
},
|
},
|
||||||
"ELECTRUM": {
|
"ELECTRUM": {
|
||||||
"HOST": "__ELECTRUM_HOST__",
|
"HOST": "__ELECTRUM_HOST__",
|
||||||
@ -61,7 +63,9 @@
|
|||||||
"PORT": __SECOND_CORE_RPC_PORT__,
|
"PORT": __SECOND_CORE_RPC_PORT__,
|
||||||
"USERNAME": "__SECOND_CORE_RPC_USERNAME__",
|
"USERNAME": "__SECOND_CORE_RPC_USERNAME__",
|
||||||
"PASSWORD": "__SECOND_CORE_RPC_PASSWORD__",
|
"PASSWORD": "__SECOND_CORE_RPC_PASSWORD__",
|
||||||
"TIMEOUT": __SECOND_CORE_RPC_TIMEOUT__
|
"TIMEOUT": __SECOND_CORE_RPC_TIMEOUT__,
|
||||||
|
"COOKIE": __SECOND_CORE_RPC_COOKIE__,
|
||||||
|
"COOKIE_PATH": "__SECOND_CORE_RPC_COOKIE_PATH__"
|
||||||
},
|
},
|
||||||
"DATABASE": {
|
"DATABASE": {
|
||||||
"ENABLED": __DATABASE_ENABLED__,
|
"ENABLED": __DATABASE_ENABLED__,
|
||||||
|
@ -43,6 +43,8 @@ __CORE_RPC_PORT__=${CORE_RPC_PORT:=8332}
|
|||||||
__CORE_RPC_USERNAME__=${CORE_RPC_USERNAME:=mempool}
|
__CORE_RPC_USERNAME__=${CORE_RPC_USERNAME:=mempool}
|
||||||
__CORE_RPC_PASSWORD__=${CORE_RPC_PASSWORD:=mempool}
|
__CORE_RPC_PASSWORD__=${CORE_RPC_PASSWORD:=mempool}
|
||||||
__CORE_RPC_TIMEOUT__=${CORE_RPC_TIMEOUT:=60000}
|
__CORE_RPC_TIMEOUT__=${CORE_RPC_TIMEOUT:=60000}
|
||||||
|
__CORE_RPC_COOKIE__=${CORE_RPC_COOKIE:=false}
|
||||||
|
__CORE_RPC_COOKIE_PATH__=${CORE_RPC_COOKIE_PATH:=""}
|
||||||
|
|
||||||
# ELECTRUM
|
# ELECTRUM
|
||||||
__ELECTRUM_HOST__=${ELECTRUM_HOST:=127.0.0.1}
|
__ELECTRUM_HOST__=${ELECTRUM_HOST:=127.0.0.1}
|
||||||
@ -63,6 +65,8 @@ __SECOND_CORE_RPC_PORT__=${SECOND_CORE_RPC_PORT:=8332}
|
|||||||
__SECOND_CORE_RPC_USERNAME__=${SECOND_CORE_RPC_USERNAME:=mempool}
|
__SECOND_CORE_RPC_USERNAME__=${SECOND_CORE_RPC_USERNAME:=mempool}
|
||||||
__SECOND_CORE_RPC_PASSWORD__=${SECOND_CORE_RPC_PASSWORD:=mempool}
|
__SECOND_CORE_RPC_PASSWORD__=${SECOND_CORE_RPC_PASSWORD:=mempool}
|
||||||
__SECOND_CORE_RPC_TIMEOUT__=${SECOND_CORE_RPC_TIMEOUT:=60000}
|
__SECOND_CORE_RPC_TIMEOUT__=${SECOND_CORE_RPC_TIMEOUT:=60000}
|
||||||
|
__SECOND_CORE_RPC_COOKIE__=${SECOND_CORE_RPC_COOKIE:=false}
|
||||||
|
__SECOND_CORE_RPC_COOKIE_PATH__=${SECOND_CORE_RPC_COOKIE_PATH:=""}
|
||||||
|
|
||||||
# DATABASE
|
# DATABASE
|
||||||
__DATABASE_ENABLED__=${DATABASE_ENABLED:=true}
|
__DATABASE_ENABLED__=${DATABASE_ENABLED:=true}
|
||||||
@ -188,6 +192,8 @@ sed -i "s!__CORE_RPC_PORT__!${__CORE_RPC_PORT__}!g" mempool-config.json
|
|||||||
sed -i "s!__CORE_RPC_USERNAME__!${__CORE_RPC_USERNAME__}!g" mempool-config.json
|
sed -i "s!__CORE_RPC_USERNAME__!${__CORE_RPC_USERNAME__}!g" mempool-config.json
|
||||||
sed -i "s!__CORE_RPC_PASSWORD__!${__CORE_RPC_PASSWORD__}!g" mempool-config.json
|
sed -i "s!__CORE_RPC_PASSWORD__!${__CORE_RPC_PASSWORD__}!g" mempool-config.json
|
||||||
sed -i "s!__CORE_RPC_TIMEOUT__!${__CORE_RPC_TIMEOUT__}!g" mempool-config.json
|
sed -i "s!__CORE_RPC_TIMEOUT__!${__CORE_RPC_TIMEOUT__}!g" mempool-config.json
|
||||||
|
sed -i "s!__CORE_RPC_COOKIE__!${__CORE_RPC_COOKIE__}!g" mempool-config.json
|
||||||
|
sed -i "s!__CORE_RPC_COOKIE_PATH__!${__CORE_RPC_COOKIE_PATH__}!g" mempool-config.json
|
||||||
|
|
||||||
sed -i "s!__ELECTRUM_HOST__!${__ELECTRUM_HOST__}!g" mempool-config.json
|
sed -i "s!__ELECTRUM_HOST__!${__ELECTRUM_HOST__}!g" mempool-config.json
|
||||||
sed -i "s!__ELECTRUM_PORT__!${__ELECTRUM_PORT__}!g" mempool-config.json
|
sed -i "s!__ELECTRUM_PORT__!${__ELECTRUM_PORT__}!g" mempool-config.json
|
||||||
@ -205,6 +211,8 @@ sed -i "s!__SECOND_CORE_RPC_PORT__!${__SECOND_CORE_RPC_PORT__}!g" mempool-config
|
|||||||
sed -i "s!__SECOND_CORE_RPC_USERNAME__!${__SECOND_CORE_RPC_USERNAME__}!g" mempool-config.json
|
sed -i "s!__SECOND_CORE_RPC_USERNAME__!${__SECOND_CORE_RPC_USERNAME__}!g" mempool-config.json
|
||||||
sed -i "s!__SECOND_CORE_RPC_PASSWORD__!${__SECOND_CORE_RPC_PASSWORD__}!g" mempool-config.json
|
sed -i "s!__SECOND_CORE_RPC_PASSWORD__!${__SECOND_CORE_RPC_PASSWORD__}!g" mempool-config.json
|
||||||
sed -i "s!__SECOND_CORE_RPC_TIMEOUT__!${__SECOND_CORE_RPC_TIMEOUT__}!g" mempool-config.json
|
sed -i "s!__SECOND_CORE_RPC_TIMEOUT__!${__SECOND_CORE_RPC_TIMEOUT__}!g" mempool-config.json
|
||||||
|
sed -i "s!__SECOND_CORE_RPC_COOKIE__!${__SECOND_CORE_RPC_COOKIE__}!g" mempool-config.json
|
||||||
|
sed -i "s!__SECOND_CORE_RPC_COOKIE_PATH__!${__SECOND_CORE_RPC_COOKIE_PATH__}!g" mempool-config.json
|
||||||
|
|
||||||
sed -i "s!__DATABASE_ENABLED__!${__DATABASE_ENABLED__}!g" mempool-config.json
|
sed -i "s!__DATABASE_ENABLED__!${__DATABASE_ENABLED__}!g" mempool-config.json
|
||||||
sed -i "s!__DATABASE_HOST__!${__DATABASE_HOST__}!g" mempool-config.json
|
sed -i "s!__DATABASE_HOST__!${__DATABASE_HOST__}!g" mempool-config.json
|
||||||
|
87
frontend/package-lock.json
generated
87
frontend/package-lock.json
generated
@ -33,9 +33,9 @@
|
|||||||
"clipboard": "^2.0.11",
|
"clipboard": "^2.0.11",
|
||||||
"domino": "^2.1.6",
|
"domino": "^2.1.6",
|
||||||
"echarts": "~5.4.3",
|
"echarts": "~5.4.3",
|
||||||
"echarts-gl": "^2.0.9",
|
|
||||||
"lightweight-charts": "~3.8.0",
|
"lightweight-charts": "~3.8.0",
|
||||||
"ngx-echarts": "~16.0.0",
|
"mock-socket": "~9.3.1",
|
||||||
|
"ngx-echarts": "~16.2.0",
|
||||||
"ngx-infinite-scroll": "^16.0.0",
|
"ngx-infinite-scroll": "^16.0.0",
|
||||||
"qrcode": "1.5.1",
|
"qrcode": "1.5.1",
|
||||||
"rxjs": "~7.8.1",
|
"rxjs": "~7.8.1",
|
||||||
@ -59,10 +59,10 @@
|
|||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@cypress/schematic": "^2.5.0",
|
"@cypress/schematic": "^2.5.0",
|
||||||
"@types/cypress": "^1.1.3",
|
"@types/cypress": "^1.1.3",
|
||||||
"cypress": "^13.3.0",
|
"cypress": "^13.5.0",
|
||||||
"cypress-fail-on-console-error": "~5.0.0",
|
"cypress-fail-on-console-error": "~5.0.0",
|
||||||
"cypress-wait-until": "^2.0.1",
|
"cypress-wait-until": "^2.0.1",
|
||||||
"mock-socket": "~9.2.1",
|
"mock-socket": "~9.3.1",
|
||||||
"start-server-and-test": "~2.0.0"
|
"start-server-and-test": "~2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -6429,11 +6429,6 @@
|
|||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/claygl": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ=="
|
|
||||||
},
|
|
||||||
"node_modules/clean-stack": {
|
"node_modules/clean-stack": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||||
@ -7153,9 +7148,9 @@
|
|||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"node_modules/cypress": {
|
"node_modules/cypress": {
|
||||||
"version": "13.3.0",
|
"version": "13.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.5.0.tgz",
|
||||||
"integrity": "sha512-mpI8qcTwLGiA4zEQvTC/U1xGUezVV4V8HQCOYjlEOrVmU1etVvxOjkCXHGwrlYdZU/EPmUiWfsO3yt1o+Q2bgw==",
|
"integrity": "sha512-oh6U7h9w8wwHfzNDJQ6wVcAeXu31DlIYlNOBvfd6U4CcB8oe4akawQmH+QJVOMZlM42eBoCne015+svVqdwdRQ==",
|
||||||
"hasInstallScript": true,
|
"hasInstallScript": true,
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@ -7825,18 +7820,6 @@
|
|||||||
"zrender": "5.4.4"
|
"zrender": "5.4.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/echarts-gl": {
|
|
||||||
"version": "2.0.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz",
|
|
||||||
"integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==",
|
|
||||||
"dependencies": {
|
|
||||||
"claygl": "^1.2.1",
|
|
||||||
"zrender": "^5.1.1"
|
|
||||||
},
|
|
||||||
"peerDependencies": {
|
|
||||||
"echarts": "^5.1.2"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/echarts/node_modules/tslib": {
|
"node_modules/echarts/node_modules/tslib": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
|
||||||
@ -9531,9 +9514,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/get-func-name": {
|
"node_modules/get-func-name": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
|
||||||
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
|
"integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
@ -12209,9 +12192,9 @@
|
|||||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||||
},
|
},
|
||||||
"node_modules/mock-socket": {
|
"node_modules/mock-socket": {
|
||||||
"version": "9.2.1",
|
"version": "9.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz",
|
||||||
"integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==",
|
"integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
@ -12460,9 +12443,9 @@
|
|||||||
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
|
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
|
||||||
},
|
},
|
||||||
"node_modules/ngx-echarts": {
|
"node_modules/ngx-echarts": {
|
||||||
"version": "16.0.0",
|
"version": "16.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-16.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-16.2.0.tgz",
|
||||||
"integrity": "sha512-hdM7/CL29bY3sF3V5ihb7H1NeUsQlhijp8tVxT23+vkNTf9SJrUHPjs9oHOMkbTlr2Q8HB+eVpckYAL/tuK0CQ==",
|
"integrity": "sha512-yhuDbp6qdkmR4kRVLS06Z0Iumod7xOj5n/Z++clRiKM24OQ4sM8WuOTicdfWy6eeYDNywdGSrri4Y5SUGRD8bg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
},
|
},
|
||||||
@ -21550,11 +21533,6 @@
|
|||||||
"safe-buffer": "^5.0.1"
|
"safe-buffer": "^5.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"claygl": {
|
|
||||||
"version": "1.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/claygl/-/claygl-1.3.0.tgz",
|
|
||||||
"integrity": "sha512-+gGtJjT6SSHD2l2yC3MCubW/sCV40tZuSs5opdtn79vFSGUgp/lH139RNEQ6Jy078/L0aV8odCw8RSrUcMfLaQ=="
|
|
||||||
},
|
|
||||||
"clean-stack": {
|
"clean-stack": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
|
||||||
@ -22118,9 +22096,9 @@
|
|||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"cypress": {
|
"cypress": {
|
||||||
"version": "13.3.0",
|
"version": "13.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/cypress/-/cypress-13.5.0.tgz",
|
||||||
"integrity": "sha512-mpI8qcTwLGiA4zEQvTC/U1xGUezVV4V8HQCOYjlEOrVmU1etVvxOjkCXHGwrlYdZU/EPmUiWfsO3yt1o+Q2bgw==",
|
"integrity": "sha512-oh6U7h9w8wwHfzNDJQ6wVcAeXu31DlIYlNOBvfd6U4CcB8oe4akawQmH+QJVOMZlM42eBoCne015+svVqdwdRQ==",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@cypress/request": "^3.0.0",
|
"@cypress/request": "^3.0.0",
|
||||||
@ -22659,15 +22637,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"echarts-gl": {
|
|
||||||
"version": "2.0.9",
|
|
||||||
"resolved": "https://registry.npmjs.org/echarts-gl/-/echarts-gl-2.0.9.tgz",
|
|
||||||
"integrity": "sha512-oKeMdkkkpJGWOzjgZUsF41DOh6cMsyrGGXimbjK2l6Xeq/dBQu4ShG2w2Dzrs/1bD27b2pLTGSaUzouY191gzA==",
|
|
||||||
"requires": {
|
|
||||||
"claygl": "^1.2.1",
|
|
||||||
"zrender": "^5.1.1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ee-first": {
|
"ee-first": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||||
@ -23971,9 +23940,9 @@
|
|||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
||||||
},
|
},
|
||||||
"get-func-name": {
|
"get-func-name": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
|
||||||
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=",
|
"integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"get-intrinsic": {
|
"get-intrinsic": {
|
||||||
@ -25945,9 +25914,9 @@
|
|||||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
|
||||||
},
|
},
|
||||||
"mock-socket": {
|
"mock-socket": {
|
||||||
"version": "9.2.1",
|
"version": "9.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz",
|
||||||
"integrity": "sha512-aw9F9T9G2zpGipLLhSNh6ZpgUyUl4frcVmRN08uE1NWPWg43Wx6+sGPDbQ7E5iFZZDJW5b5bypMeAEHqTbIFag==",
|
"integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"module-deps": {
|
"module-deps": {
|
||||||
@ -26141,9 +26110,9 @@
|
|||||||
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
|
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
|
||||||
},
|
},
|
||||||
"ngx-echarts": {
|
"ngx-echarts": {
|
||||||
"version": "16.0.0",
|
"version": "16.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-16.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/ngx-echarts/-/ngx-echarts-16.2.0.tgz",
|
||||||
"integrity": "sha512-hdM7/CL29bY3sF3V5ihb7H1NeUsQlhijp8tVxT23+vkNTf9SJrUHPjs9oHOMkbTlr2Q8HB+eVpckYAL/tuK0CQ==",
|
"integrity": "sha512-yhuDbp6qdkmR4kRVLS06Z0Iumod7xOj5n/Z++clRiKM24OQ4sM8WuOTicdfWy6eeYDNywdGSrri4Y5SUGRD8bg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
"domino": "^2.1.6",
|
"domino": "^2.1.6",
|
||||||
"echarts": "~5.4.3",
|
"echarts": "~5.4.3",
|
||||||
"lightweight-charts": "~3.8.0",
|
"lightweight-charts": "~3.8.0",
|
||||||
"ngx-echarts": "~16.0.0",
|
"ngx-echarts": "~16.2.0",
|
||||||
"ngx-infinite-scroll": "^16.0.0",
|
"ngx-infinite-scroll": "^16.0.0",
|
||||||
"qrcode": "1.5.1",
|
"qrcode": "1.5.1",
|
||||||
"rxjs": "~7.8.1",
|
"rxjs": "~7.8.1",
|
||||||
@ -110,10 +110,10 @@
|
|||||||
"optionalDependencies": {
|
"optionalDependencies": {
|
||||||
"@cypress/schematic": "^2.5.0",
|
"@cypress/schematic": "^2.5.0",
|
||||||
"@types/cypress": "^1.1.3",
|
"@types/cypress": "^1.1.3",
|
||||||
"cypress": "^13.3.0",
|
"cypress": "^13.5.0",
|
||||||
"cypress-fail-on-console-error": "~5.0.0",
|
"cypress-fail-on-console-error": "~5.0.0",
|
||||||
"cypress-wait-until": "^2.0.1",
|
"cypress-wait-until": "^2.0.1",
|
||||||
"mock-socket": "~9.2.1",
|
"mock-socket": "~9.3.1",
|
||||||
"start-server-and-test": "~2.0.0"
|
"start-server-and-test": "~2.0.0"
|
||||||
},
|
},
|
||||||
"scarfSettings": {
|
"scarfSettings": {
|
||||||
|
@ -1,30 +1,10 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
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 { TransactionComponent } from './components/transaction/transaction.component';
|
|
||||||
import { BlockComponent } from './components/block/block.component';
|
|
||||||
import { BlockViewComponent } from './components/block-view/block-view.component';
|
import { BlockViewComponent } from './components/block-view/block-view.component';
|
||||||
import { MempoolBlockViewComponent } from './components/mempool-block-view/mempool-block-view.component';
|
import { MempoolBlockViewComponent } from './components/mempool-block-view/mempool-block-view.component';
|
||||||
import { ClockComponent } from './components/clock/clock.component';
|
import { ClockComponent } from './components/clock/clock.component';
|
||||||
import { AddressComponent } from './components/address/address.component';
|
|
||||||
import { MasterPageComponent } from './components/master-page/master-page.component';
|
|
||||||
import { AboutComponent } from './components/about/about.component';
|
|
||||||
import { StatusViewComponent } from './components/status-view/status-view.component';
|
import { StatusViewComponent } from './components/status-view/status-view.component';
|
||||||
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
|
|
||||||
import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-policy.component';
|
|
||||||
import { TrademarkPolicyComponent } from './components/trademark-policy/trademark-policy.component';
|
|
||||||
import { BisqMasterPageComponent } from './components/bisq-master-page/bisq-master-page.component';
|
|
||||||
import { PushTransactionComponent } from './components/push-transaction/push-transaction.component';
|
|
||||||
import { BlocksList } from './components/blocks-list/blocks-list.component';
|
|
||||||
import { RbfList } from './components/rbf-list/rbf-list.component';
|
|
||||||
import { LiquidMasterPageComponent } from './components/liquid-master-page/liquid-master-page.component';
|
|
||||||
import { AssetGroupComponent } from './components/assets/asset-group/asset-group.component';
|
|
||||||
import { AssetsFeaturedComponent } from './components/assets/assets-featured/assets-featured.component';
|
|
||||||
import { AssetsComponent } from './components/assets/assets.component';
|
|
||||||
import { AssetComponent } from './components/asset/asset.component';
|
|
||||||
import { AssetsNavComponent } from './components/assets/assets-nav/assets-nav.component';
|
|
||||||
import { CalculatorComponent } from './components/calculator/calculator.component';
|
|
||||||
|
|
||||||
const browserWindow = window || {};
|
const browserWindow = window || {};
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@ -37,96 +17,14 @@ let routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule),
|
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
|
||||||
data: { preload: true },
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: MasterPageComponent,
|
loadChildren: () => import('./master-page.module').then(m => m.MasterPageModule),
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'mining/blocks',
|
|
||||||
redirectTo: 'blocks',
|
|
||||||
pathMatch: 'full'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx/push',
|
|
||||||
component: PushTransactionComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'about',
|
|
||||||
component: AboutComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'blocks',
|
|
||||||
component: BlocksList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'rbf',
|
|
||||||
component: RbfList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'terms-of-service',
|
|
||||||
component: TermsOfServiceComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'privacy-policy',
|
|
||||||
component: PrivacyPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'trademark-policy',
|
|
||||||
component: TrademarkPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true,
|
|
||||||
networkSpecific: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx',
|
|
||||||
component: StartComponent,
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: TransactionComponent
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'block',
|
|
||||||
component: StartComponent,
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: BlockComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'docs',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule),
|
|
||||||
data: { preload: true },
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'api',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning',
|
|
||||||
loadChildren: () => import('./lightning/lightning.module').then(m => m.LightningModule),
|
|
||||||
data: { preload: browserWindowEnv && browserWindowEnv.LIGHTNING === true, networks: ['bitcoin'] },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'status',
|
path: 'status',
|
||||||
data: { networks: ['bitcoin', 'liquid'] },
|
data: { networks: ['bitcoin', 'liquid'] },
|
||||||
@ -134,7 +32,8 @@ let routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
@ -153,88 +52,13 @@ let routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: MasterPageComponent,
|
loadChildren: () => import('./master-page.module').then(m => m.MasterPageModule),
|
||||||
children: [
|
data: { preload: true },
|
||||||
{
|
|
||||||
path: 'tx/push',
|
|
||||||
component: PushTransactionComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'about',
|
|
||||||
component: AboutComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'blocks',
|
|
||||||
component: BlocksList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'rbf',
|
|
||||||
component: RbfList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'terms-of-service',
|
|
||||||
component: TermsOfServiceComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'privacy-policy',
|
|
||||||
component: PrivacyPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'trademark-policy',
|
|
||||||
component: TrademarkPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true,
|
|
||||||
networkSpecific: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: TransactionComponent
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'block',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: BlockComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'docs',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'api',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
loadChildren: () => import('./lightning/lightning.module').then(m => m.LightningModule)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'status',
|
path: 'status',
|
||||||
@ -243,7 +67,8 @@ let routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
@ -254,97 +79,13 @@ let routes: Routes = [
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: MasterPageComponent,
|
loadChildren: () => import('./master-page.module').then(m => m.MasterPageModule),
|
||||||
children: [
|
data: { preload: true },
|
||||||
{
|
|
||||||
path: 'mining/blocks',
|
|
||||||
redirectTo: 'blocks',
|
|
||||||
pathMatch: 'full'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx/push',
|
|
||||||
component: PushTransactionComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'about',
|
|
||||||
component: AboutComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'blocks',
|
|
||||||
component: BlocksList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'rbf',
|
|
||||||
component: RbfList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tools/calculator',
|
|
||||||
component: CalculatorComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'terms-of-service',
|
|
||||||
component: TermsOfServiceComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'privacy-policy',
|
|
||||||
component: PrivacyPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'trademark-policy',
|
|
||||||
component: TrademarkPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true,
|
|
||||||
networkSpecific: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: TransactionComponent
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'block',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: BlockComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'docs',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'api',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
loadChildren: () => import('./lightning/lightning.module').then(m => m.LightningModule)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'preview',
|
path: 'preview',
|
||||||
@ -390,7 +131,8 @@ let routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./bitcoin-graphs.module').then(m => m.BitcoinGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
@ -401,7 +143,6 @@ let routes: Routes = [
|
|||||||
if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'bisq') {
|
if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'bisq') {
|
||||||
routes = [{
|
routes = [{
|
||||||
path: '',
|
path: '',
|
||||||
component: BisqMasterPageComponent,
|
|
||||||
loadChildren: () => import('./bisq/bisq.module').then(m => m.BisqModule)
|
loadChildren: () => import('./bisq/bisq.module').then(m => m.BisqModule)
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@ -414,105 +155,13 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./liquid/liquid-graphs.module').then(m => m.LiquidGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: LiquidMasterPageComponent,
|
loadChildren: () => import ('./liquid/liquid-master-page.module').then(m => m.LiquidMasterPageModule),
|
||||||
children: [
|
data: { preload: true },
|
||||||
{
|
|
||||||
path: 'tx/push',
|
|
||||||
component: PushTransactionComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'about',
|
|
||||||
component: AboutComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'blocks',
|
|
||||||
component: BlocksList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'terms-of-service',
|
|
||||||
component: TermsOfServiceComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'privacy-policy',
|
|
||||||
component: PrivacyPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'trademark-policy',
|
|
||||||
component: TrademarkPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true,
|
|
||||||
networkSpecific: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: TransactionComponent
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'block',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: BlockComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'assets',
|
|
||||||
data: { networks: ['liquid'] },
|
|
||||||
component: AssetsNavComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'all',
|
|
||||||
data: { networks: ['liquid'] },
|
|
||||||
component: AssetsComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'asset/:id',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: AssetComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'group/:id',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: AssetGroupComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '**',
|
|
||||||
redirectTo: 'all'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'docs',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'api',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'status',
|
path: 'status',
|
||||||
@ -521,7 +170,8 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./liquid/liquid-graphs.module').then(m => m.LiquidGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
@ -532,110 +182,13 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
|
|||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
pathMatch: 'full',
|
pathMatch: 'full',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./liquid/liquid-graphs.module').then(m => m.LiquidGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: LiquidMasterPageComponent,
|
loadChildren: () => import ('./liquid/liquid-master-page.module').then(m => m.LiquidMasterPageModule),
|
||||||
children: [
|
data: { preload: true },
|
||||||
{
|
|
||||||
path: 'tx/push',
|
|
||||||
component: PushTransactionComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'about',
|
|
||||||
component: AboutComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'blocks',
|
|
||||||
component: BlocksList,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'terms-of-service',
|
|
||||||
component: TermsOfServiceComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'privacy-policy',
|
|
||||||
component: PrivacyPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'trademark-policy',
|
|
||||||
component: TrademarkPolicyComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'address/:id',
|
|
||||||
children: [],
|
|
||||||
component: AddressComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true,
|
|
||||||
networkSpecific: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'tx',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: TransactionComponent
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'block',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: StartComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: ':id',
|
|
||||||
component: BlockComponent,
|
|
||||||
data: {
|
|
||||||
ogImage: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'assets',
|
|
||||||
data: { networks: ['liquid'] },
|
|
||||||
component: AssetsNavComponent,
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
path: 'featured',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: AssetsFeaturedComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'all',
|
|
||||||
data: { networks: ['liquid'] },
|
|
||||||
component: AssetsComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'asset/:id',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: AssetComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'group/:id',
|
|
||||||
data: { networkSpecific: true },
|
|
||||||
component: AssetGroupComponent
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '**',
|
|
||||||
redirectTo: 'featured'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'docs',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'api',
|
|
||||||
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'preview',
|
path: 'preview',
|
||||||
@ -657,7 +210,8 @@ if (browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid') {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule)
|
loadChildren: () => import('./liquid/liquid-graphs.module').then(m => m.LiquidGraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
|
@ -27,9 +27,11 @@ import { AutofocusDirective } from '../components/ngx-bootstrap-multiselect/auto
|
|||||||
import { MultiSelectSearchFilter } from '../components/ngx-bootstrap-multiselect/search-filter.pipe';
|
import { MultiSelectSearchFilter } from '../components/ngx-bootstrap-multiselect/search-filter.pipe';
|
||||||
import { OffClickDirective } from '../components/ngx-bootstrap-multiselect/off-click.directive';
|
import { OffClickDirective } from '../components/ngx-bootstrap-multiselect/off-click.directive';
|
||||||
import { NgxDropdownMultiselectComponent } from '../components/ngx-bootstrap-multiselect/ngx-bootstrap-multiselect.component';
|
import { NgxDropdownMultiselectComponent } from '../components/ngx-bootstrap-multiselect/ngx-bootstrap-multiselect.component';
|
||||||
|
import { BisqMasterPageComponent } from '../components/bisq-master-page/bisq-master-page.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
BisqMasterPageComponent,
|
||||||
BisqTransactionsComponent,
|
BisqTransactionsComponent,
|
||||||
BisqTransactionComponent,
|
BisqTransactionComponent,
|
||||||
BisqBlockComponent,
|
BisqBlockComponent,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { RouterModule, Routes } from '@angular/router';
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
import { AboutComponent } from '../components/about/about.component';
|
import { BisqMasterPageComponent } from '../components/bisq-master-page/bisq-master-page.component';
|
||||||
import { BisqTransactionsComponent } from './bisq-transactions/bisq-transactions.component';
|
import { BisqTransactionsComponent } from './bisq-transactions/bisq-transactions.component';
|
||||||
import { BisqTransactionComponent } from './bisq-transaction/bisq-transaction.component';
|
import { BisqTransactionComponent } from './bisq-transaction/bisq-transaction.component';
|
||||||
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
|
import { BisqBlockComponent } from './bisq-block/bisq-block.component';
|
||||||
@ -10,10 +10,13 @@ import { BisqStatsComponent } from './bisq-stats/bisq-stats.component';
|
|||||||
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
|
import { BisqDashboardComponent } from './bisq-dashboard/bisq-dashboard.component';
|
||||||
import { BisqMarketComponent } from './bisq-market/bisq-market.component';
|
import { BisqMarketComponent } from './bisq-market/bisq-market.component';
|
||||||
import { BisqMainDashboardComponent } from './bisq-main-dashboard/bisq-main-dashboard.component';
|
import { BisqMainDashboardComponent } from './bisq-main-dashboard/bisq-main-dashboard.component';
|
||||||
import { TermsOfServiceComponent } from '../components/terms-of-service/terms-of-service.component';
|
|
||||||
import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component';
|
import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: BisqMasterPageComponent,
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: BisqMainDashboardComponent,
|
component: BisqMainDashboardComponent,
|
||||||
@ -64,7 +67,7 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'about',
|
path: 'about',
|
||||||
component: AboutComponent,
|
loadChildren: () => import('../components/about/about.module').then(m => m.AboutModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'docs',
|
path: 'docs',
|
||||||
@ -76,12 +79,14 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'terms-of-service',
|
path: 'terms-of-service',
|
||||||
component: TermsOfServiceComponent
|
loadChildren: () => import('../components/terms-of-service/terms-of-service.module').then(m => m.TermsOfServiceModule),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '**',
|
path: '**',
|
||||||
redirectTo: ''
|
redirectTo: ''
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
37
frontend/src/app/bitcoin-graphs.module.ts
Normal file
37
frontend/src/app/bitcoin-graphs.module.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { MasterPageComponent } from './components/master-page/master-page.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: MasterPageComponent,
|
||||||
|
loadChildren: () => import('./graphs/graphs.module').then(m => m.GraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class BitcoinGraphsRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
BitcoinGraphsRoutingModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class BitcoinGraphsModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
40
frontend/src/app/components/about/about.module.ts
Normal file
40
frontend/src/app/components/about/about.module.ts
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { AboutComponent } from './about.component';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: AboutComponent,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AboutRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
AboutRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
AboutComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class AboutModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
43
frontend/src/app/components/block/block.module.ts
Normal file
43
frontend/src/app/components/block/block.module.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { BlockComponent } from './block.component';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: ':id',
|
||||||
|
component: BlockComponent,
|
||||||
|
data: {
|
||||||
|
ogImage: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class BlockRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
BlockRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
BlockComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class BlockModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,3 @@
|
|||||||
|
.fee-distribution-chart {
|
||||||
|
margin-top: 0.75rem;
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { OnChanges, OnDestroy } from '@angular/core';
|
import { HostListener, OnChanges, OnDestroy } from '@angular/core';
|
||||||
import { Component, Input, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
import { Component, Input, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
||||||
import { TransactionStripped } from '../../interfaces/websocket.interface';
|
import { TransactionStripped } from '../../interfaces/websocket.interface';
|
||||||
import { StateService } from '../../services/state.service';
|
import { StateService } from '../../services/state.service';
|
||||||
@ -9,6 +9,7 @@ import { Subscription } from 'rxjs';
|
|||||||
@Component({
|
@Component({
|
||||||
selector: 'app-fee-distribution-graph',
|
selector: 'app-fee-distribution-graph',
|
||||||
templateUrl: './fee-distribution-graph.component.html',
|
templateUrl: './fee-distribution-graph.component.html',
|
||||||
|
styleUrls: ['./fee-distribution-graph.component.scss'],
|
||||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
})
|
})
|
||||||
export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestroy {
|
export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
@ -25,6 +26,7 @@ export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestr
|
|||||||
simple: boolean = false;
|
simple: boolean = false;
|
||||||
data: number[][];
|
data: number[][];
|
||||||
labelInterval: number = 50;
|
labelInterval: number = 50;
|
||||||
|
smallScreen: boolean = window.innerWidth < 450;
|
||||||
|
|
||||||
rateUnitSub: Subscription;
|
rateUnitSub: Subscription;
|
||||||
weightMode: boolean = false;
|
weightMode: boolean = false;
|
||||||
@ -95,9 +97,9 @@ export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestr
|
|||||||
this.mempoolVsizeFeesOptions = {
|
this.mempoolVsizeFeesOptions = {
|
||||||
grid: {
|
grid: {
|
||||||
height: '210',
|
height: '210',
|
||||||
right: '20',
|
right: this.smallScreen ? '10' : '20',
|
||||||
top: '22',
|
top: '22',
|
||||||
left: '40',
|
left: this.smallScreen ? '10' : '40',
|
||||||
},
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
@ -131,16 +133,17 @@ export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestr
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
show: true,
|
show: !this.smallScreen,
|
||||||
formatter: (value: number): string => {
|
formatter: (value: number): string => {
|
||||||
const unitValue = this.weightMode ? value / 4 : value;
|
const unitValue = this.weightMode ? value / 4 : value;
|
||||||
const selectedPowerOfTen = selectPowerOfTen(unitValue);
|
const selectedPowerOfTen = selectPowerOfTen(unitValue);
|
||||||
const newVal = Math.round(unitValue / selectedPowerOfTen.divider);
|
const scaledValue = unitValue / selectedPowerOfTen.divider;
|
||||||
|
const newVal = scaledValue >= 100 ? Math.round(scaledValue) : scaledValue.toPrecision(3);
|
||||||
return `${newVal}${selectedPowerOfTen.unit}`;
|
return `${newVal}${selectedPowerOfTen.unit}`;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
axisTick: {
|
axisTick: {
|
||||||
show: true,
|
show: !this.smallScreen,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
series: [{
|
series: [{
|
||||||
@ -151,11 +154,13 @@ export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestr
|
|||||||
position: 'top',
|
position: 'top',
|
||||||
color: '#ffffff',
|
color: '#ffffff',
|
||||||
textShadowBlur: 0,
|
textShadowBlur: 0,
|
||||||
|
fontSize: this.smallScreen ? 10 : 12,
|
||||||
formatter: (label: { data: number[] }): string => {
|
formatter: (label: { data: number[] }): string => {
|
||||||
const value = label.data[1];
|
const value = label.data[1];
|
||||||
const unitValue = this.weightMode ? value / 4 : value;
|
const unitValue = this.weightMode ? value / 4 : value;
|
||||||
const selectedPowerOfTen = selectPowerOfTen(unitValue);
|
const selectedPowerOfTen = selectPowerOfTen(unitValue);
|
||||||
const newVal = Math.round(unitValue / selectedPowerOfTen.divider);
|
const scaledValue = unitValue / selectedPowerOfTen.divider;
|
||||||
|
const newVal = scaledValue >= 100 ? Math.round(scaledValue) : scaledValue.toPrecision(3);
|
||||||
return `${newVal}${selectedPowerOfTen.unit}`;
|
return `${newVal}${selectedPowerOfTen.unit}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -179,6 +184,16 @@ export class FeeDistributionGraphComponent implements OnInit, OnChanges, OnDestr
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
onResize(): void {
|
||||||
|
const isSmallScreen = window.innerWidth < 450;
|
||||||
|
if (this.smallScreen !== isSmallScreen) {
|
||||||
|
this.smallScreen = isSmallScreen;
|
||||||
|
this.prepareChart();
|
||||||
|
this.mountChart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.rateUnitSub.unsubscribe();
|
this.rateUnitSub.unsubscribe();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { PrivacyPolicyComponent } from './privacy-policy.component';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: PrivacyPolicyComponent,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class PrivacyPolicyRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
PrivacyPolicyRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
PrivacyPolicyComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class PrivacyPolicyModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { TermsOfServiceComponent } from './terms-of-service.component';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: TermsOfServiceComponent,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TermsModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TermsModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TermsOfServiceComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TermsOfServiceModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { TrademarkPolicyComponent } from './trademark-policy.component';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: TrademarkPolicyComponent,
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TrademarkRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TrademarkRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TrademarkPolicyComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TrademarkModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -422,6 +422,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
this.rbfTransaction = rbfTransaction;
|
this.rbfTransaction = rbfTransaction;
|
||||||
this.replaced = true;
|
this.replaced = true;
|
||||||
|
this.stateService.markBlock$.next({});
|
||||||
|
|
||||||
if (rbfTransaction && !this.tx) {
|
if (rbfTransaction && !this.tx) {
|
||||||
this.fetchCachedTx$.next(this.txId);
|
this.fetchCachedTx$.next(this.txId);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { TransactionComponent } from './transaction.component';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
import { TxBowtieModule } from '../tx-bowtie-graph/tx-bowtie.module';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: ':id',
|
||||||
|
component: TransactionComponent,
|
||||||
|
data: {
|
||||||
|
ogImage: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TransactionRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TransactionRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
TxBowtieModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TransactionComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TransactionModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -6,7 +6,7 @@ import { Outspend, Transaction, Vin, Vout } from '../../interfaces/electrs.inter
|
|||||||
import { ElectrsApiService } from '../../services/electrs-api.service';
|
import { ElectrsApiService } from '../../services/electrs-api.service';
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { AssetsService } from '../../services/assets.service';
|
import { AssetsService } from '../../services/assets.service';
|
||||||
import { filter, map, tap, switchMap, shareReplay } from 'rxjs/operators';
|
import { filter, map, tap, switchMap, shareReplay, catchError } from 'rxjs/operators';
|
||||||
import { BlockExtended } from '../../interfaces/node-api.interface';
|
import { BlockExtended } from '../../interfaces/node-api.interface';
|
||||||
import { ApiService } from '../../services/api.service';
|
import { ApiService } from '../../services/api.service';
|
||||||
import { PriceService } from '../../services/price.service';
|
import { PriceService } from '../../services/price.service';
|
||||||
@ -75,7 +75,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
for (let i = 0; i < txIds.length; i += 50) {
|
for (let i = 0; i < txIds.length; i += 50) {
|
||||||
batches.push(txIds.slice(i, i + 50));
|
batches.push(txIds.slice(i, i + 50));
|
||||||
}
|
}
|
||||||
return forkJoin(batches.map(batch => this.apiService.getOutspendsBatched$(batch)));
|
return forkJoin(batches.map(batch => { return this.apiService.cachedRequest(this.apiService.getOutspendsBatched$, 250, batch); }));
|
||||||
} else {
|
} else {
|
||||||
return of([]);
|
return of([]);
|
||||||
}
|
}
|
||||||
@ -90,6 +90,7 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
outspends.forEach((outspend, i) => {
|
outspends.forEach((outspend, i) => {
|
||||||
transactions[i]._outspends = outspend;
|
transactions[i]._outspends = outspend;
|
||||||
});
|
});
|
||||||
|
this.ref.markForCheck();
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
this.stateService.utxoSpent$
|
this.stateService.utxoSpent$
|
||||||
@ -108,6 +109,10 @@ export class TransactionsListComponent implements OnInit, OnChanges {
|
|||||||
.pipe(
|
.pipe(
|
||||||
filter(() => this.stateService.env.LIGHTNING),
|
filter(() => this.stateService.env.LIGHTNING),
|
||||||
switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
|
switchMap((txIds) => this.apiService.getChannelByTxIds$(txIds)),
|
||||||
|
catchError((error) => {
|
||||||
|
// handle 404
|
||||||
|
return of([]);
|
||||||
|
}),
|
||||||
tap((channels) => {
|
tap((channels) => {
|
||||||
if (!this.transactions) {
|
if (!this.transactions) {
|
||||||
return;
|
return;
|
||||||
|
@ -123,7 +123,7 @@ export class TxBowtieGraphComponent implements OnInit, OnChanges {
|
|||||||
.pipe(
|
.pipe(
|
||||||
switchMap((txid) => {
|
switchMap((txid) => {
|
||||||
if (!this.cached) {
|
if (!this.cached) {
|
||||||
return this.apiService.getOutspendsBatched$([txid]);
|
return this.apiService.cachedRequest(this.apiService.getOutspendsBatched$, 250, [txid]);
|
||||||
} else {
|
} else {
|
||||||
return of(null);
|
return of(null);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { SharedModule } from '../../shared/shared.module';
|
||||||
|
import { TxBowtieGraphComponent } from '../tx-bowtie-graph/tx-bowtie-graph.component';
|
||||||
|
import { TxBowtieGraphTooltipComponent } from '../tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
TxBowtieGraphComponent,
|
||||||
|
TxBowtieGraphTooltipComponent,
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
TxBowtieGraphComponent,
|
||||||
|
TxBowtieGraphTooltipComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class TxBowtieModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -8,8 +8,6 @@ import { BlockSizesWeightsGraphComponent } from '../components/block-sizes-weigh
|
|||||||
import { GraphsComponent } from '../components/graphs/graphs.component';
|
import { GraphsComponent } from '../components/graphs/graphs.component';
|
||||||
import { HashrateChartComponent } from '../components/hashrate-chart/hashrate-chart.component';
|
import { HashrateChartComponent } from '../components/hashrate-chart/hashrate-chart.component';
|
||||||
import { HashrateChartPoolsComponent } from '../components/hashrates-chart-pools/hashrate-chart-pools.component';
|
import { HashrateChartPoolsComponent } from '../components/hashrates-chart-pools/hashrate-chart-pools.component';
|
||||||
import { LiquidMasterPageComponent } from '../components/liquid-master-page/liquid-master-page.component';
|
|
||||||
import { MasterPageComponent } from '../components/master-page/master-page.component';
|
|
||||||
import { MempoolBlockComponent } from '../components/mempool-block/mempool-block.component';
|
import { MempoolBlockComponent } from '../components/mempool-block/mempool-block.component';
|
||||||
import { MiningDashboardComponent } from '../components/mining-dashboard/mining-dashboard.component';
|
import { MiningDashboardComponent } from '../components/mining-dashboard/mining-dashboard.component';
|
||||||
import { PoolRankingComponent } from '../components/pool-ranking/pool-ranking.component';
|
import { PoolRankingComponent } from '../components/pool-ranking/pool-ranking.component';
|
||||||
@ -18,22 +16,10 @@ import { StartComponent } from '../components/start/start.component';
|
|||||||
import { StatisticsComponent } from '../components/statistics/statistics.component';
|
import { StatisticsComponent } from '../components/statistics/statistics.component';
|
||||||
import { TelevisionComponent } from '../components/television/television.component';
|
import { TelevisionComponent } from '../components/television/television.component';
|
||||||
import { DashboardComponent } from '../dashboard/dashboard.component';
|
import { DashboardComponent } from '../dashboard/dashboard.component';
|
||||||
import { NodesNetworksChartComponent } from '../lightning/nodes-networks-chart/nodes-networks-chart.component';
|
|
||||||
import { LightningStatisticsChartComponent } from '../lightning/statistics-chart/lightning-statistics-chart.component';
|
|
||||||
import { NodesPerISPChartComponent } from '../lightning/nodes-per-isp-chart/nodes-per-isp-chart.component';
|
|
||||||
import { NodesPerCountryChartComponent } from '../lightning/nodes-per-country-chart/nodes-per-country-chart.component';
|
|
||||||
import { NodesMap } from '../lightning/nodes-map/nodes-map.component';
|
|
||||||
import { NodesChannelsMap } from '../lightning/nodes-channels-map/nodes-channels-map.component';
|
|
||||||
|
|
||||||
const browserWindow = window || {};
|
|
||||||
// @ts-ignore
|
|
||||||
const browserWindowEnv = browserWindow.__env || {};
|
|
||||||
const isLiquid = browserWindowEnv && browserWindowEnv.BASE_MODULE === 'liquid';
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
component: isLiquid ? LiquidMasterPageComponent : MasterPageComponent,
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: 'mining/pool/:slug',
|
path: 'mining/pool/:slug',
|
||||||
@ -108,34 +94,9 @@ const routes: Routes = [
|
|||||||
component: BlockSizesWeightsGraphComponent,
|
component: BlockSizesWeightsGraphComponent,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lightning/nodes-networks',
|
path: 'lightning',
|
||||||
data: { networks: ['bitcoin'] },
|
data: { preload: true, networks: ['bitcoin'] },
|
||||||
component: NodesNetworksChartComponent,
|
loadChildren: () => import ('./lightning-graphs.module').then(m => m.LightningGraphsModule),
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning/capacity',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
component: LightningStatisticsChartComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning/nodes-per-isp',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
component: NodesPerISPChartComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning/nodes-per-country',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
component: NodesPerCountryChartComponent,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning/nodes-map',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
component: NodesMap,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'lightning/nodes-channels-map',
|
|
||||||
data: { networks: ['bitcoin'] },
|
|
||||||
component: NodesChannelsMap,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '',
|
path: '',
|
||||||
|
58
frontend/src/app/graphs/lightning-graphs.module.ts
Normal file
58
frontend/src/app/graphs/lightning-graphs.module.ts
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { RouterModule, Routes } from '@angular/router';
|
||||||
|
import { NodesNetworksChartComponent } from '../lightning/nodes-networks-chart/nodes-networks-chart.component';
|
||||||
|
import { LightningStatisticsChartComponent } from '../lightning/statistics-chart/lightning-statistics-chart.component';
|
||||||
|
import { NodesPerISPChartComponent } from '../lightning/nodes-per-isp-chart/nodes-per-isp-chart.component';
|
||||||
|
import { NodesPerCountryChartComponent } from '../lightning/nodes-per-country-chart/nodes-per-country-chart.component';
|
||||||
|
import { NodesMap } from '../lightning/nodes-map/nodes-map.component';
|
||||||
|
import { NodesChannelsMap } from '../lightning/nodes-channels-map/nodes-channels-map.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: 'nodes-networks',
|
||||||
|
data: { networks: ['bitcoin'] },
|
||||||
|
component: NodesNetworksChartComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'capacity',
|
||||||
|
data: { networks: ['bitcoin'] },
|
||||||
|
component: LightningStatisticsChartComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'nodes-per-isp',
|
||||||
|
data: { networks: ['bitcoin'] },
|
||||||
|
component: NodesPerISPChartComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'nodes-per-country',
|
||||||
|
data: { networks: ['bitcoin'] },
|
||||||
|
component: NodesPerCountryChartComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'nodes-map',
|
||||||
|
data: { networks: ['bitcoin'] },
|
||||||
|
component: NodesMap,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'nodes-channels-map',
|
||||||
|
data: { networks: ['bitcoin'] },
|
||||||
|
component: NodesChannelsMap,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [RouterModule.forChild(routes)],
|
||||||
|
exports: [RouterModule],
|
||||||
|
})
|
||||||
|
export class LightningGraphsRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
SharedModule,
|
||||||
|
LightningGraphsRoutingModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class LightningGraphsModule { }
|
37
frontend/src/app/liquid/liquid-graphs.module.ts
Normal file
37
frontend/src/app/liquid/liquid-graphs.module.ts
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { LiquidMasterPageComponent } from '../components/liquid-master-page/liquid-master-page.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: LiquidMasterPageComponent,
|
||||||
|
loadChildren: () => import('../graphs/graphs.module').then(m => m.GraphsModule),
|
||||||
|
data: { preload: true },
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class LiquidGraphsRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
LiquidGraphsRoutingModule,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
export class LiquidGraphsModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
125
frontend/src/app/liquid/liquid-master-page.module.ts
Normal file
125
frontend/src/app/liquid/liquid-master-page.module.ts
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
import { LiquidMasterPageComponent } from '../components/liquid-master-page/liquid-master-page.component';
|
||||||
|
|
||||||
|
import { StartComponent } from '../components/start/start.component';
|
||||||
|
import { AddressComponent } from '../components/address/address.component';
|
||||||
|
import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component';
|
||||||
|
import { BlocksList } from '../components/blocks-list/blocks-list.component';
|
||||||
|
import { AssetGroupComponent } from '../components/assets/asset-group/asset-group.component';
|
||||||
|
import { AssetsComponent } from '../components/assets/assets.component';
|
||||||
|
import { AssetComponent } from '../components/asset/asset.component';
|
||||||
|
import { AssetsNavComponent } from '../components/assets/assets-nav/assets-nav.component';
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: LiquidMasterPageComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'tx/push',
|
||||||
|
component: PushTransactionComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'about',
|
||||||
|
loadChildren: () => import('../components/about/about.module').then(m => m.AboutModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'blocks',
|
||||||
|
component: BlocksList,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'terms-of-service',
|
||||||
|
loadChildren: () => import('../components/terms-of-service/terms-of-service.module').then(m => m.TermsOfServiceModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'privacy-policy',
|
||||||
|
loadChildren: () => import('../components/privacy-policy/privacy-policy.module').then(m => m.PrivacyPolicyModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'trademark-policy',
|
||||||
|
loadChildren: () => import('../components/trademark-policy/trademark-policy.module').then(m => m.TrademarkModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'address/:id',
|
||||||
|
children: [],
|
||||||
|
component: AddressComponent,
|
||||||
|
data: {
|
||||||
|
ogImage: true,
|
||||||
|
networkSpecific: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tx',
|
||||||
|
component: StartComponent,
|
||||||
|
data: { preload: true, networkSpecific: true },
|
||||||
|
loadChildren: () => import('../components/transaction/transaction.module').then(m => m.TransactionModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'block',
|
||||||
|
component: StartComponent,
|
||||||
|
data: { preload: true, networkSpecific: true },
|
||||||
|
loadChildren: () => import('../components/block/block.module').then(m => m.BlockModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'assets',
|
||||||
|
data: { networks: ['liquid'] },
|
||||||
|
component: AssetsNavComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'all',
|
||||||
|
data: { networks: ['liquid'] },
|
||||||
|
component: AssetsComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'asset/:id',
|
||||||
|
data: { networkSpecific: true },
|
||||||
|
component: AssetComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'group/:id',
|
||||||
|
data: { networkSpecific: true },
|
||||||
|
component: AssetGroupComponent
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '**',
|
||||||
|
redirectTo: 'all'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'docs',
|
||||||
|
loadChildren: () => import('../docs/docs.module').then(m => m.DocsModule),
|
||||||
|
data: { preload: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'api',
|
||||||
|
loadChildren: () => import('../docs/docs.module').then(m => m.DocsModule)
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class LiquidRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
LiquidRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
LiquidMasterPageComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class LiquidMasterPageModule { }
|
120
frontend/src/app/master-page.module.ts
Normal file
120
frontend/src/app/master-page.module.ts
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { Routes, RouterModule } from '@angular/router';
|
||||||
|
import { MasterPageComponent } from './components/master-page/master-page.component';
|
||||||
|
import { SharedModule } from './shared/shared.module';
|
||||||
|
|
||||||
|
import { StartComponent } from './components/start/start.component';
|
||||||
|
import { AddressComponent } from './components/address/address.component';
|
||||||
|
import { PushTransactionComponent } from './components/push-transaction/push-transaction.component';
|
||||||
|
import { BlocksList } from './components/blocks-list/blocks-list.component';
|
||||||
|
import { RbfList } from './components/rbf-list/rbf-list.component';
|
||||||
|
|
||||||
|
const browserWindow = window || {};
|
||||||
|
// @ts-ignore
|
||||||
|
const browserWindowEnv = browserWindow.__env || {};
|
||||||
|
|
||||||
|
const routes: Routes = [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: MasterPageComponent,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'mining/blocks',
|
||||||
|
redirectTo: 'blocks',
|
||||||
|
pathMatch: 'full'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tx/push',
|
||||||
|
component: PushTransactionComponent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'about',
|
||||||
|
loadChildren: () => import('./components/about/about.module').then(m => m.AboutModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'blocks',
|
||||||
|
component: BlocksList,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'rbf',
|
||||||
|
component: RbfList,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'terms-of-service',
|
||||||
|
loadChildren: () => import('./components/terms-of-service/terms-of-service.module').then(m => m.TermsOfServiceModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'privacy-policy',
|
||||||
|
loadChildren: () => import('./components/privacy-policy/privacy-policy.module').then(m => m.PrivacyPolicyModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'trademark-policy',
|
||||||
|
loadChildren: () => import('./components/trademark-policy/trademark-policy.module').then(m => m.TrademarkModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'address/:id',
|
||||||
|
children: [],
|
||||||
|
component: AddressComponent,
|
||||||
|
data: {
|
||||||
|
ogImage: true,
|
||||||
|
networkSpecific: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'tx',
|
||||||
|
component: StartComponent,
|
||||||
|
data: { preload: true, networkSpecific: true },
|
||||||
|
loadChildren: () => import('./components/transaction/transaction.module').then(m => m.TransactionModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'block',
|
||||||
|
component: StartComponent,
|
||||||
|
data: { preload: true, networkSpecific: true },
|
||||||
|
loadChildren: () => import('./components/block/block.module').then(m => m.BlockModule),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'docs',
|
||||||
|
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule),
|
||||||
|
data: { preload: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'api',
|
||||||
|
loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'lightning',
|
||||||
|
loadChildren: () => import('./lightning/lightning.module').then(m => m.LightningModule),
|
||||||
|
data: { preload: browserWindowEnv && browserWindowEnv.LIGHTNING === true, networks: ['bitcoin'] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
RouterModule.forChild(routes)
|
||||||
|
],
|
||||||
|
exports: [
|
||||||
|
RouterModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class MasterPageRoutingModule { }
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
MasterPageRoutingModule,
|
||||||
|
SharedModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
MasterPageComponent,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class MasterPageModule { }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { BlockPreviewComponent } from './components/block/block-preview.componen
|
|||||||
import { AddressPreviewComponent } from './components/address/address-preview.component';
|
import { AddressPreviewComponent } from './components/address/address-preview.component';
|
||||||
import { PoolPreviewComponent } from './components/pool/pool-preview.component';
|
import { PoolPreviewComponent } from './components/pool/pool-preview.component';
|
||||||
import { MasterPagePreviewComponent } from './components/master-page-preview/master-page-preview.component';
|
import { MasterPagePreviewComponent } from './components/master-page-preview/master-page-preview.component';
|
||||||
|
import { TxBowtieModule } from './components/tx-bowtie-graph/tx-bowtie.module';
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
TransactionPreviewComponent,
|
TransactionPreviewComponent,
|
||||||
@ -23,6 +24,7 @@ import { MasterPagePreviewComponent } from './components/master-page-preview/mas
|
|||||||
RouterModule,
|
RouterModule,
|
||||||
PreviewsRoutingModule,
|
PreviewsRoutingModule,
|
||||||
GraphsModule,
|
GraphsModule,
|
||||||
|
TxBowtieModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class PreviewsModule { }
|
export class PreviewsModule { }
|
||||||
|
@ -31,7 +31,8 @@ const routes: Routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'lightning',
|
path: 'lightning',
|
||||||
loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule)
|
loadChildren: () => import('./lightning/lightning-previews.module').then(m => m.LightningPreviewsModule),
|
||||||
|
data: { preload: true },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
|||||||
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
|
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
|
||||||
import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITranslators,
|
import { CpfpInfo, OptimizedMempoolStats, AddressInformation, LiquidPegs, ITranslators,
|
||||||
PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit } from '../interfaces/node-api.interface';
|
PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit } from '../interfaces/node-api.interface';
|
||||||
import { Observable, of } from 'rxjs';
|
import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs';
|
||||||
import { StateService } from './state.service';
|
import { StateService } from './state.service';
|
||||||
import { IBackendInfo, WebsocketResponse } from '../interfaces/websocket.interface';
|
import { IBackendInfo, WebsocketResponse } from '../interfaces/websocket.interface';
|
||||||
import { Outspend, Transaction } from '../interfaces/electrs.interface';
|
import { Outspend, Transaction } from '../interfaces/electrs.interface';
|
||||||
@ -20,6 +20,8 @@ export class ApiService {
|
|||||||
private apiBaseUrl: string; // base URL is protocol, hostname, and port
|
private apiBaseUrl: string; // base URL is protocol, hostname, and port
|
||||||
private apiBasePath: string; // network path is /testnet, etc. or '' for mainnet
|
private apiBasePath: string; // network path is /testnet, etc. or '' for mainnet
|
||||||
|
|
||||||
|
private requestCache = new Map<string, { subject: BehaviorSubject<any>, expiry: number }>;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private httpClient: HttpClient,
|
private httpClient: HttpClient,
|
||||||
private stateService: StateService,
|
private stateService: StateService,
|
||||||
@ -44,6 +46,46 @@ export class ApiService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private generateCacheKey(functionName: string, params: any[]): string {
|
||||||
|
return functionName + JSON.stringify(params);
|
||||||
|
}
|
||||||
|
|
||||||
|
// delete expired cache entries
|
||||||
|
private cleanExpiredCache(): void {
|
||||||
|
this.requestCache.forEach((value, key) => {
|
||||||
|
if (value.expiry < Date.now()) {
|
||||||
|
this.requestCache.delete(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
cachedRequest<T, F extends (...args: any[]) => Observable<T>>(
|
||||||
|
apiFunction: F,
|
||||||
|
expireAfter: number, // in ms
|
||||||
|
...params: Parameters<F>
|
||||||
|
): Observable<T> {
|
||||||
|
this.cleanExpiredCache();
|
||||||
|
|
||||||
|
const cacheKey = this.generateCacheKey(apiFunction.name, params);
|
||||||
|
if (!this.requestCache.has(cacheKey)) {
|
||||||
|
const subject = new BehaviorSubject<T | null>(null);
|
||||||
|
this.requestCache.set(cacheKey, { subject, expiry: Date.now() + expireAfter });
|
||||||
|
|
||||||
|
apiFunction.bind(this)(...params).pipe(
|
||||||
|
tap(data => {
|
||||||
|
subject.next(data as T);
|
||||||
|
}),
|
||||||
|
catchError((error) => {
|
||||||
|
subject.error(error);
|
||||||
|
return of(null);
|
||||||
|
}),
|
||||||
|
shareReplay(1),
|
||||||
|
).subscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.requestCache.get(cacheKey).subject.asObservable().pipe(filter(val => val !== null), take(1));
|
||||||
|
}
|
||||||
|
|
||||||
list2HStatistics$(): Observable<OptimizedMempoolStats[]> {
|
list2HStatistics$(): Observable<OptimizedMempoolStats[]> {
|
||||||
return this.httpClient.get<OptimizedMempoolStats[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/statistics/2h');
|
return this.httpClient.get<OptimizedMempoolStats[]>(this.apiBaseUrl + this.apiBasePath + '/api/v1/statistics/2h');
|
||||||
}
|
}
|
||||||
|
@ -6,12 +6,8 @@ import { faFilter, faAngleDown, faAngleUp, faAngleRight, faAngleLeft, faBolt, fa
|
|||||||
faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faClock, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown,
|
faLink, faList, faSearch, faCaretUp, faCaretDown, faTachometerAlt, faThList, faTint, faTv, faClock, faAngleDoubleDown, faSortUp, faAngleDoubleUp, faChevronDown,
|
||||||
faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft, faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck, faCircleCheck, faUserCircle } from '@fortawesome/free-solid-svg-icons';
|
faFileAlt, faRedoAlt, faArrowAltCircleRight, faExternalLinkAlt, faBook, faListUl, faDownload, faQrcode, faArrowRightArrowLeft, faArrowsRotate, faCircleLeft, faFastForward, faWallet, faUserClock, faWrench, faUserFriends, faQuestionCircle, faHistory, faSignOutAlt, faKey, faSuitcase, faIdCardAlt, faNetworkWired, faUserCheck, faCircleCheck, faUserCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
import { InfiniteScrollModule } from 'ngx-infinite-scroll';
|
||||||
import { MasterPageComponent } from '../components/master-page/master-page.component';
|
|
||||||
import { MenuComponent } from '../components/menu/menu.component';
|
import { MenuComponent } from '../components/menu/menu.component';
|
||||||
import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component';
|
import { PreviewTitleComponent } from '../components/master-page-preview/preview-title.component';
|
||||||
import { BisqMasterPageComponent } from '../components/bisq-master-page/bisq-master-page.component';
|
|
||||||
import { LiquidMasterPageComponent } from '../components/liquid-master-page/liquid-master-page.component';
|
|
||||||
import { AboutComponent } from '../components/about/about.component';
|
|
||||||
import { VbytesPipe } from './pipes/bytes-pipe/vbytes.pipe';
|
import { VbytesPipe } from './pipes/bytes-pipe/vbytes.pipe';
|
||||||
import { ShortenStringPipe } from './pipes/shorten-string-pipe/shorten-string.pipe';
|
import { ShortenStringPipe } from './pipes/shorten-string-pipe/shorten-string.pipe';
|
||||||
import { CeilPipe } from './pipes/math-ceil/math-ceil.pipe';
|
import { CeilPipe } from './pipes/math-ceil/math-ceil.pipe';
|
||||||
@ -45,9 +41,7 @@ import { AmountComponent } from '../components/amount/amount.component';
|
|||||||
import { RouterModule } from '@angular/router';
|
import { RouterModule } from '@angular/router';
|
||||||
import { CapAddressPipe } from './pipes/cap-address-pipe/cap-address-pipe';
|
import { CapAddressPipe } from './pipes/cap-address-pipe/cap-address-pipe';
|
||||||
import { StartComponent } from '../components/start/start.component';
|
import { StartComponent } from '../components/start/start.component';
|
||||||
import { TransactionComponent } from '../components/transaction/transaction.component';
|
|
||||||
import { TransactionsListComponent } from '../components/transactions-list/transactions-list.component';
|
import { TransactionsListComponent } from '../components/transactions-list/transactions-list.component';
|
||||||
import { BlockComponent } from '../components/block/block.component';
|
|
||||||
import { BlockOverviewGraphComponent } from '../components/block-overview-graph/block-overview-graph.component';
|
import { BlockOverviewGraphComponent } from '../components/block-overview-graph/block-overview-graph.component';
|
||||||
import { BlockOverviewTooltipComponent } from '../components/block-overview-tooltip/block-overview-tooltip.component';
|
import { BlockOverviewTooltipComponent } from '../components/block-overview-tooltip/block-overview-tooltip.component';
|
||||||
import { AddressComponent } from '../components/address/address.component';
|
import { AddressComponent } from '../components/address/address.component';
|
||||||
@ -62,13 +56,8 @@ import { FeesBoxComponent } from '../components/fees-box/fees-box.component';
|
|||||||
import { DifficultyComponent } from '../components/difficulty/difficulty.component';
|
import { DifficultyComponent } from '../components/difficulty/difficulty.component';
|
||||||
import { DifficultyTooltipComponent } from '../components/difficulty/difficulty-tooltip.component';
|
import { DifficultyTooltipComponent } from '../components/difficulty/difficulty-tooltip.component';
|
||||||
import { DifficultyMiningComponent } from '../components/difficulty-mining/difficulty-mining.component';
|
import { DifficultyMiningComponent } from '../components/difficulty-mining/difficulty-mining.component';
|
||||||
import { TermsOfServiceComponent } from '../components/terms-of-service/terms-of-service.component';
|
|
||||||
import { RbfTimelineComponent } from '../components/rbf-timeline/rbf-timeline.component';
|
import { RbfTimelineComponent } from '../components/rbf-timeline/rbf-timeline.component';
|
||||||
import { RbfTimelineTooltipComponent } from '../components/rbf-timeline/rbf-timeline-tooltip.component';
|
import { RbfTimelineTooltipComponent } from '../components/rbf-timeline/rbf-timeline-tooltip.component';
|
||||||
import { TxBowtieGraphComponent } from '../components/tx-bowtie-graph/tx-bowtie-graph.component';
|
|
||||||
import { TxBowtieGraphTooltipComponent } from '../components/tx-bowtie-graph-tooltip/tx-bowtie-graph-tooltip.component';
|
|
||||||
import { PrivacyPolicyComponent } from '../components/privacy-policy/privacy-policy.component';
|
|
||||||
import { TrademarkPolicyComponent } from '../components/trademark-policy/trademark-policy.component';
|
|
||||||
import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component';
|
import { PushTransactionComponent } from '../components/push-transaction/push-transaction.component';
|
||||||
import { AssetsFeaturedComponent } from '../components/assets/assets-featured/assets-featured.component';
|
import { AssetsFeaturedComponent } from '../components/assets/assets-featured/assets-featured.component';
|
||||||
import { AssetGroupComponent } from '../components/assets/asset-group/asset-group.component';
|
import { AssetGroupComponent } from '../components/assets/asset-group/asset-group.component';
|
||||||
@ -141,15 +130,9 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
MempoolBlocksComponent,
|
MempoolBlocksComponent,
|
||||||
BlockchainBlocksComponent,
|
BlockchainBlocksComponent,
|
||||||
AmountComponent,
|
AmountComponent,
|
||||||
AboutComponent,
|
|
||||||
MasterPageComponent,
|
|
||||||
MenuComponent,
|
MenuComponent,
|
||||||
PreviewTitleComponent,
|
PreviewTitleComponent,
|
||||||
BisqMasterPageComponent,
|
|
||||||
LiquidMasterPageComponent,
|
|
||||||
StartComponent,
|
StartComponent,
|
||||||
TransactionComponent,
|
|
||||||
BlockComponent,
|
|
||||||
BlockOverviewGraphComponent,
|
BlockOverviewGraphComponent,
|
||||||
BlockOverviewTooltipComponent,
|
BlockOverviewTooltipComponent,
|
||||||
TransactionsListComponent,
|
TransactionsListComponent,
|
||||||
@ -166,11 +149,6 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
DifficultyTooltipComponent,
|
DifficultyTooltipComponent,
|
||||||
RbfTimelineComponent,
|
RbfTimelineComponent,
|
||||||
RbfTimelineTooltipComponent,
|
RbfTimelineTooltipComponent,
|
||||||
TxBowtieGraphComponent,
|
|
||||||
TxBowtieGraphTooltipComponent,
|
|
||||||
TermsOfServiceComponent,
|
|
||||||
PrivacyPolicyComponent,
|
|
||||||
TrademarkPolicyComponent,
|
|
||||||
PushTransactionComponent,
|
PushTransactionComponent,
|
||||||
AssetsNavComponent,
|
AssetsNavComponent,
|
||||||
AssetsFeaturedComponent,
|
AssetsFeaturedComponent,
|
||||||
@ -233,7 +211,6 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
AmountShortenerPipe,
|
AmountShortenerPipe,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
MasterPageComponent,
|
|
||||||
MenuComponent,
|
MenuComponent,
|
||||||
RouterModule,
|
RouterModule,
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@ -275,8 +252,6 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
BlockchainBlocksComponent,
|
BlockchainBlocksComponent,
|
||||||
AmountComponent,
|
AmountComponent,
|
||||||
StartComponent,
|
StartComponent,
|
||||||
TransactionComponent,
|
|
||||||
BlockComponent,
|
|
||||||
BlockOverviewGraphComponent,
|
BlockOverviewGraphComponent,
|
||||||
BlockOverviewTooltipComponent,
|
BlockOverviewTooltipComponent,
|
||||||
TransactionsListComponent,
|
TransactionsListComponent,
|
||||||
@ -293,11 +268,6 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
DifficultyTooltipComponent,
|
DifficultyTooltipComponent,
|
||||||
RbfTimelineComponent,
|
RbfTimelineComponent,
|
||||||
RbfTimelineTooltipComponent,
|
RbfTimelineTooltipComponent,
|
||||||
TxBowtieGraphComponent,
|
|
||||||
TxBowtieGraphTooltipComponent,
|
|
||||||
TermsOfServiceComponent,
|
|
||||||
PrivacyPolicyComponent,
|
|
||||||
TrademarkPolicyComponent,
|
|
||||||
PushTransactionComponent,
|
PushTransactionComponent,
|
||||||
AssetsNavComponent,
|
AssetsNavComponent,
|
||||||
AssetsFeaturedComponent,
|
AssetsFeaturedComponent,
|
||||||
@ -320,6 +290,7 @@ import { OnlyVsizeDirective, OnlyWeightDirective } from './components/weight-dir
|
|||||||
ConfirmationsComponent,
|
ConfirmationsComponent,
|
||||||
ToggleComponent,
|
ToggleComponent,
|
||||||
GeolocationComponent,
|
GeolocationComponent,
|
||||||
|
TestnetAlertComponent,
|
||||||
PreviewTitleComponent,
|
PreviewTitleComponent,
|
||||||
GlobalFooterComponent,
|
GlobalFooterComponent,
|
||||||
AcceleratePreviewComponent,
|
AcceleratePreviewComponent,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user