Merge branch 'master' into natsoni/more-fiat-currencies
This commit is contained in:
		
						commit
						23076172e4
					
				
							
								
								
									
										12
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										12
									
								
								backend/package-lock.json
									
									
									
										generated
									
									
									
								
							@ -4027,9 +4027,9 @@
 | 
				
			|||||||
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
					      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/ip": {
 | 
					    "node_modules/ip": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
 | 
					      "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/ipaddr.js": {
 | 
					    "node_modules/ipaddr.js": {
 | 
				
			||||||
      "version": "1.9.1",
 | 
					      "version": "1.9.1",
 | 
				
			||||||
@ -10683,9 +10683,9 @@
 | 
				
			|||||||
      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
					      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ip": {
 | 
					    "ip": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
 | 
					      "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ipaddr.js": {
 | 
					    "ipaddr.js": {
 | 
				
			||||||
      "version": "1.9.1",
 | 
					      "version": "1.9.1",
 | 
				
			||||||
 | 
				
			|||||||
@ -56,6 +56,9 @@ class AccelerationRepository {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async $getAccelerationInfo(poolSlug: string | null = null, height: number | null = null, interval: string | null = null): Promise<PublicAcceleration[]> {
 | 
					  public async $getAccelerationInfo(poolSlug: string | null = null, height: number | null = null, interval: string | null = null): Promise<PublicAcceleration[]> {
 | 
				
			||||||
 | 
					    if (!interval || !['24h', '3d', '1w', '1m'].includes(interval)) {
 | 
				
			||||||
 | 
					      interval = '1m';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    interval = Common.getSqlInterval(interval);
 | 
					    interval = Common.getSqlInterval(interval);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!config.MEMPOOL_SERVICES.ACCELERATIONS || (interval == null && poolSlug == null && height == null)) {
 | 
					    if (!config.MEMPOOL_SERVICES.ACCELERATIONS || (interval == null && poolSlug == null && height == null)) {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										91
									
								
								frontend/package-lock.json
									
									
									
										generated
									
									
									
								
							@ -8070,13 +8070,18 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/es5-ext": {
 | 
					    "node_modules/es5-ext": {
 | 
				
			||||||
      "version": "0.10.53",
 | 
					      "version": "0.10.64",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
 | 
				
			||||||
      "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
 | 
					      "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
 | 
				
			||||||
 | 
					      "hasInstallScript": true,
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "es6-iterator": "~2.0.3",
 | 
					        "es6-iterator": "^2.0.3",
 | 
				
			||||||
        "es6-symbol": "~3.1.3",
 | 
					        "es6-symbol": "^3.1.3",
 | 
				
			||||||
        "next-tick": "~1.0.0"
 | 
					        "esniff": "^2.0.1",
 | 
				
			||||||
 | 
					        "next-tick": "^1.1.0"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/es6-iterator": {
 | 
					    "node_modules/es6-iterator": {
 | 
				
			||||||
@ -8624,6 +8629,25 @@
 | 
				
			|||||||
        "url": "https://github.com/sponsors/sindresorhus"
 | 
					        "url": "https://github.com/sponsors/sindresorhus"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/esniff": {
 | 
				
			||||||
 | 
					      "version": "2.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "d": "^1.0.1",
 | 
				
			||||||
 | 
					        "es5-ext": "^0.10.62",
 | 
				
			||||||
 | 
					        "event-emitter": "^0.3.5",
 | 
				
			||||||
 | 
					        "type": "^2.7.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "engines": {
 | 
				
			||||||
 | 
					        "node": ">=0.10"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "node_modules/esniff/node_modules/type": {
 | 
				
			||||||
 | 
					      "version": "2.7.2",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "node_modules/espree": {
 | 
					    "node_modules/espree": {
 | 
				
			||||||
      "version": "9.4.1",
 | 
					      "version": "9.4.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
 | 
				
			||||||
@ -10397,9 +10421,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/ip": {
 | 
					    "node_modules/ip": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
 | 
					      "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/ipaddr.js": {
 | 
					    "node_modules/ipaddr.js": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
@ -12508,9 +12532,9 @@
 | 
				
			|||||||
      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
 | 
					      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/next-tick": {
 | 
					    "node_modules/next-tick": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
 | 
					      "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "node_modules/ngx-echarts": {
 | 
					    "node_modules/ngx-echarts": {
 | 
				
			||||||
      "version": "16.2.0",
 | 
					      "version": "16.2.0",
 | 
				
			||||||
@ -23055,13 +23079,14 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "es5-ext": {
 | 
					    "es5-ext": {
 | 
				
			||||||
      "version": "0.10.53",
 | 
					      "version": "0.10.64",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
 | 
				
			||||||
      "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
 | 
					      "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "es6-iterator": "~2.0.3",
 | 
					        "es6-iterator": "^2.0.3",
 | 
				
			||||||
        "es6-symbol": "~3.1.3",
 | 
					        "es6-symbol": "^3.1.3",
 | 
				
			||||||
        "next-tick": "~1.0.0"
 | 
					        "esniff": "^2.0.1",
 | 
				
			||||||
 | 
					        "next-tick": "^1.1.0"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "es6-iterator": {
 | 
					    "es6-iterator": {
 | 
				
			||||||
@ -23472,6 +23497,24 @@
 | 
				
			|||||||
      "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
 | 
					      "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "esniff": {
 | 
				
			||||||
 | 
					      "version": "2.0.1",
 | 
				
			||||||
 | 
					      "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
 | 
				
			||||||
 | 
					      "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
 | 
				
			||||||
 | 
					      "requires": {
 | 
				
			||||||
 | 
					        "d": "^1.0.1",
 | 
				
			||||||
 | 
					        "es5-ext": "^0.10.62",
 | 
				
			||||||
 | 
					        "event-emitter": "^0.3.5",
 | 
				
			||||||
 | 
					        "type": "^2.7.2"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "dependencies": {
 | 
				
			||||||
 | 
					        "type": {
 | 
				
			||||||
 | 
					          "version": "2.7.2",
 | 
				
			||||||
 | 
					          "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz",
 | 
				
			||||||
 | 
					          "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw=="
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "espree": {
 | 
					    "espree": {
 | 
				
			||||||
      "version": "9.4.1",
 | 
					      "version": "9.4.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz",
 | 
				
			||||||
@ -24802,9 +24845,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ip": {
 | 
					    "ip": {
 | 
				
			||||||
      "version": "2.0.0",
 | 
					      "version": "2.0.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ=="
 | 
					      "integrity": "sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ipaddr.js": {
 | 
					    "ipaddr.js": {
 | 
				
			||||||
      "version": "2.1.0",
 | 
					      "version": "2.1.0",
 | 
				
			||||||
@ -26374,9 +26417,9 @@
 | 
				
			|||||||
      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
 | 
					      "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "next-tick": {
 | 
					    "next-tick": {
 | 
				
			||||||
      "version": "1.0.0",
 | 
					      "version": "1.1.0",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
 | 
				
			||||||
      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
 | 
					      "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "ngx-echarts": {
 | 
					    "ngx-echarts": {
 | 
				
			||||||
      "version": "16.2.0",
 | 
					      "version": "16.2.0",
 | 
				
			||||||
 | 
				
			|||||||
@ -9,23 +9,38 @@
 | 
				
			|||||||
      </button>
 | 
					      </button>
 | 
				
			||||||
    </div>  
 | 
					    </div>  
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
 | 
					    <form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="daysAvailable">
 | 
				
			||||||
      <div class="btn-group btn-group-toggle" name="radioBasic" [class]="{'disabled': isLoading}">
 | 
					      <div class="btn-group btn-group-toggle" name="radioBasic" [class]="{'disabled': isLoading}">
 | 
				
			||||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
 | 
					        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
 | 
				
			||||||
          <input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 24H
 | 
					          <input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 24H
 | 
				
			||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 1" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
 | 
				
			||||||
          <input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3D
 | 
					          <input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3D
 | 
				
			||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 3" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
 | 
				
			||||||
          <input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1W
 | 
					          <input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1W
 | 
				
			||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 7" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
 | 
				
			||||||
          <input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1M
 | 
					          <input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1M
 | 
				
			||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 30" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
 | 
				
			||||||
          <input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3M
 | 
					          <input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3M
 | 
				
			||||||
        </label>
 | 
					        </label>
 | 
				
			||||||
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 90" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
 | 
				
			||||||
 | 
					          <input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 6M
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 180" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
 | 
				
			||||||
 | 
					          <input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 1Y
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 360" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
 | 
				
			||||||
 | 
					          <input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 2Y
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
 | 
					        <label class="btn btn-primary btn-sm" *ngIf="daysAvailable >= 720" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
 | 
				
			||||||
 | 
					          <input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> 3Y
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
 | 
					        <label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === 'all'">
 | 
				
			||||||
 | 
					          <input type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan"> ALL
 | 
				
			||||||
 | 
					        </label>
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    </form>
 | 
					    </form>
 | 
				
			||||||
  </div>
 | 
					  </div>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnDestroy, OnInit } from '@angular/core';
 | 
					import { ChangeDetectionStrategy, ChangeDetectorRef, Component, Inject, Input, LOCALE_ID, OnDestroy, OnInit } from '@angular/core';
 | 
				
			||||||
import { EChartsOption } from 'echarts';
 | 
					import { EChartsOption } from 'echarts';
 | 
				
			||||||
import { Observable, Subscription, combineLatest, fromEvent } from 'rxjs';
 | 
					import { Observable, Subscription, combineLatest, fromEvent, share } from 'rxjs';
 | 
				
			||||||
import { startWith, switchMap, tap } from 'rxjs/operators';
 | 
					import { startWith, switchMap, tap } from 'rxjs/operators';
 | 
				
			||||||
import { SeoService } from '../../../services/seo.service';
 | 
					import { SeoService } from '../../../services/seo.service';
 | 
				
			||||||
import { formatNumber } from '@angular/common';
 | 
					import { formatNumber } from '@angular/common';
 | 
				
			||||||
@ -41,8 +41,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    renderer: 'svg',
 | 
					    renderer: 'svg',
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  hrStatsObservable$: Observable<any>;
 | 
					  aggregatedHistory$: Observable<any>;
 | 
				
			||||||
  statsObservable$: Observable<any>;
 | 
					 | 
				
			||||||
  statsSubscription: Subscription;
 | 
					  statsSubscription: Subscription;
 | 
				
			||||||
  isLoading = true;
 | 
					  isLoading = true;
 | 
				
			||||||
  formatNumber = formatNumber;
 | 
					  formatNumber = formatNumber;
 | 
				
			||||||
@ -50,6 +49,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
  chartInstance: any = undefined;
 | 
					  chartInstance: any = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  currency: string;
 | 
					  currency: string;
 | 
				
			||||||
 | 
					  daysAvailable: number = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    @Inject(LOCALE_ID) public locale: string,
 | 
					    @Inject(LOCALE_ID) public locale: string,
 | 
				
			||||||
@ -81,7 +81,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
        this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
 | 
					        this.radioGroupForm.controls.dateSpan.setValue(fragment, { emitEvent: false });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    this.statsObservable$ = combineLatest([
 | 
					    this.aggregatedHistory$ = combineLatest([
 | 
				
			||||||
      this.radioGroupForm.get('dateSpan').valueChanges.pipe(
 | 
					      this.radioGroupForm.get('dateSpan').valueChanges.pipe(
 | 
				
			||||||
        startWith(this.radioGroupForm.controls.dateSpan.value),
 | 
					        startWith(this.radioGroupForm.controls.dateSpan.value),
 | 
				
			||||||
        switchMap((timespan) => {
 | 
					        switchMap((timespan) => {
 | 
				
			||||||
@ -95,14 +95,17 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
      ),
 | 
					      ),
 | 
				
			||||||
      fromEvent(window, 'resize').pipe(startWith(null)),
 | 
					      fromEvent(window, 'resize').pipe(startWith(null)),
 | 
				
			||||||
    ]).pipe(
 | 
					    ]).pipe(
 | 
				
			||||||
      tap(([history]) => {
 | 
					      tap(([response]) => {
 | 
				
			||||||
 | 
					        const history: Acceleration[] = response.body;
 | 
				
			||||||
 | 
					        this.daysAvailable = (new Date().getTime() / 1000 - response.headers.get('x-oldest-accel')) / (24 * 3600);
 | 
				
			||||||
        this.isLoading = false;
 | 
					        this.isLoading = false;
 | 
				
			||||||
        this.prepareChartOptions(history);
 | 
					        this.prepareChartOptions(history);
 | 
				
			||||||
        this.cd.markForCheck();
 | 
					        this.cd.markForCheck();
 | 
				
			||||||
      })
 | 
					      }),
 | 
				
			||||||
 | 
					      share(),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.statsObservable$.subscribe();
 | 
					    this.aggregatedHistory$.subscribe();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  prepareChartOptions(data) {
 | 
					  prepareChartOptions(data) {
 | 
				
			||||||
@ -247,6 +250,7 @@ export class AccelerationFeesGraphComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
          type: 'bar',
 | 
					          type: 'bar',
 | 
				
			||||||
          barWidth: '90%',
 | 
					          barWidth: '90%',
 | 
				
			||||||
          large: true,
 | 
					          large: true,
 | 
				
			||||||
 | 
					          barMinHeight: 1,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      ],
 | 
					      ],
 | 
				
			||||||
      dataZoom: (this.widget || data.length === 0 )? undefined : [{
 | 
					      dataZoom: (this.widget || data.length === 0 )? undefined : [{
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ export class AccelerationsListComponent implements OnInit {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    this.accelerationList$ = this.pageSubject.pipe(
 | 
					    this.accelerationList$ = this.pageSubject.pipe(
 | 
				
			||||||
      switchMap((page) => {
 | 
					      switchMap((page) => {
 | 
				
			||||||
        const accelerationObservable$ = this.accelerations$ || (this.pending ? this.servicesApiService.getAccelerations$() : this.servicesApiService.getAccelerationHistoryObserveResponse$({ timeframe: '1y', page: page }));
 | 
					        const accelerationObservable$ = this.accelerations$ || (this.pending ? this.servicesApiService.getAccelerations$() : this.servicesApiService.getAccelerationHistoryObserveResponse$({ page: page }));
 | 
				
			||||||
        return accelerationObservable$.pipe(
 | 
					        return accelerationObservable$.pipe(
 | 
				
			||||||
          switchMap(response => {
 | 
					          switchMap(response => {
 | 
				
			||||||
            let accelerations = response;
 | 
					            let accelerations = response;
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ export class AcceleratorDashboardComponent implements OnInit {
 | 
				
			|||||||
    this.accelerations$ = this.stateService.chainTip$.pipe(
 | 
					    this.accelerations$ = this.stateService.chainTip$.pipe(
 | 
				
			||||||
      distinctUntilChanged(),
 | 
					      distinctUntilChanged(),
 | 
				
			||||||
      switchMap(() => {
 | 
					      switchMap(() => {
 | 
				
			||||||
        return this.serviceApiServices.getAccelerationHistory$({ timeframe: '3m', page: 1, pageLength: 100}).pipe(
 | 
					        return this.serviceApiServices.getAccelerationHistory$({}).pipe(
 | 
				
			||||||
          catchError(() => {
 | 
					          catchError(() => {
 | 
				
			||||||
            return of([]);
 | 
					            return of([]);
 | 
				
			||||||
          }),
 | 
					          }),
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
  <div class="block-overview-graph">
 | 
					  <div class="block-overview-graph">
 | 
				
			||||||
    <canvas class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas>
 | 
					    <canvas class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas>
 | 
				
			||||||
    <div class="loader-wrapper" [class.hidden]="(!isLoading || disableSpinner) && !unavailable">
 | 
					    <div class="loader-wrapper" [class.hidden]="(!isLoading || disableSpinner) && !unavailable">
 | 
				
			||||||
      <div *ngIf="isLoading" class="spinner-border ml-3 loading" role="status"></div>
 | 
					      <div *ngIf="!unavailable" class="spinner-border ml-3 loading" role="status"></div>
 | 
				
			||||||
      <div *ngIf="!isLoading && unavailable" class="ml-3" i18n="block.not-available">not available</div>
 | 
					      <div *ngIf="!isLoading && unavailable" class="ml-3" i18n="block.not-available">not available</div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <app-block-overview-tooltip
 | 
					    <app-block-overview-tooltip
 | 
				
			||||||
 | 
				
			|||||||
@ -60,6 +60,5 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  &.hidden {
 | 
					  &.hidden {
 | 
				
			||||||
    opacity: 0;
 | 
					    opacity: 0;
 | 
				
			||||||
    transition: opacity 500ms;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -433,6 +433,9 @@
 | 
				
			|||||||
        <td i18n="block.total-fees|Total fees in a block">Total fees</td>
 | 
					        <td i18n="block.total-fees|Total fees in a block">Total fees</td>
 | 
				
			||||||
        <td>
 | 
					        <td>
 | 
				
			||||||
          <app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
 | 
					          <app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-3" [noFiat]="true"></app-amount>
 | 
				
			||||||
 | 
					          <span *ngIf="oobFees" class="oobFees" i18n-ngbTooltip="Acceleration Fees" ngbTooltip="Acceleration fees paid out-of-band">
 | 
				
			||||||
 | 
					             +<app-amount [satoshis]="oobFees" digitsInfo="1.2-4" [noFiat]="true"></app-amount>
 | 
				
			||||||
 | 
					          </span>
 | 
				
			||||||
          <span *ngIf="blockAudit.feeDelta" class="difference" [class.positive]="blockAudit.feeDelta <= 0" [class.negative]="blockAudit.feeDelta > 0">
 | 
					          <span *ngIf="blockAudit.feeDelta" class="difference" [class.positive]="blockAudit.feeDelta <= 0" [class.negative]="blockAudit.feeDelta > 0">
 | 
				
			||||||
            {{ blockAudit.feeDelta < 0 ? '+' : '' }}{{ (-blockAudit.feeDelta * 100) | amountShortener: 2 }}%
 | 
					            {{ blockAudit.feeDelta < 0 ? '+' : '' }}{{ (-blockAudit.feeDelta * 100) | amountShortener: 2 }}%
 | 
				
			||||||
          </span>
 | 
					          </span>
 | 
				
			||||||
 | 
				
			|||||||
@ -288,6 +288,10 @@ h1 {
 | 
				
			|||||||
  @media (max-width: 767.98px) {
 | 
					  @media (max-width: 767.98px) {
 | 
				
			||||||
    margin-top: 0.75rem;
 | 
					    margin-top: 0.75rem;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  .oobFees {
 | 
				
			||||||
 | 
					    color: #653b9c;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.graph-col {
 | 
					.graph-col {
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ import { StateService } from '../../services/state.service';
 | 
				
			|||||||
import { SeoService } from '../../services/seo.service';
 | 
					import { SeoService } from '../../services/seo.service';
 | 
				
			||||||
import { WebsocketService } from '../../services/websocket.service';
 | 
					import { WebsocketService } from '../../services/websocket.service';
 | 
				
			||||||
import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
 | 
					import { RelativeUrlPipe } from '../../shared/pipes/relative-url/relative-url.pipe';
 | 
				
			||||||
import { BlockAudit, BlockExtended, TransactionStripped } from '../../interfaces/node-api.interface';
 | 
					import { AccelerationInfo, BlockAudit, BlockExtended, TransactionStripped } from '../../interfaces/node-api.interface';
 | 
				
			||||||
import { ApiService } from '../../services/api.service';
 | 
					import { ApiService } from '../../services/api.service';
 | 
				
			||||||
import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
 | 
					import { BlockOverviewGraphComponent } from '../../components/block-overview-graph/block-overview-graph.component';
 | 
				
			||||||
import { detectWebGL } from '../../shared/graphs.utils';
 | 
					import { detectWebGL } from '../../shared/graphs.utils';
 | 
				
			||||||
@ -43,6 +43,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
  latestBlock: BlockExtended;
 | 
					  latestBlock: BlockExtended;
 | 
				
			||||||
  latestBlocks: BlockExtended[] = [];
 | 
					  latestBlocks: BlockExtended[] = [];
 | 
				
			||||||
  transactions: Transaction[];
 | 
					  transactions: Transaction[];
 | 
				
			||||||
 | 
					  oobFees: number = 0;
 | 
				
			||||||
  isLoadingTransactions = true;
 | 
					  isLoadingTransactions = true;
 | 
				
			||||||
  strippedTransactions: TransactionStripped[];
 | 
					  strippedTransactions: TransactionStripped[];
 | 
				
			||||||
  overviewTransitionDirection: string;
 | 
					  overviewTransitionDirection: string;
 | 
				
			||||||
@ -85,6 +86,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
  timeLtr: boolean;
 | 
					  timeLtr: boolean;
 | 
				
			||||||
  childChangeSubscription: Subscription;
 | 
					  childChangeSubscription: Subscription;
 | 
				
			||||||
  auditPrefSubscription: Subscription;
 | 
					  auditPrefSubscription: Subscription;
 | 
				
			||||||
 | 
					  oobSubscription: Subscription;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  priceSubscription: Subscription;
 | 
					  priceSubscription: Subscription;
 | 
				
			||||||
  blockConversion: Price;
 | 
					  blockConversion: Price;
 | 
				
			||||||
@ -168,6 +170,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
        this.page = 1;
 | 
					        this.page = 1;
 | 
				
			||||||
        this.error = undefined;
 | 
					        this.error = undefined;
 | 
				
			||||||
        this.fees = undefined;
 | 
					        this.fees = undefined;
 | 
				
			||||||
 | 
					        this.oobFees = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (history.state.data && history.state.data.blockHeight) {
 | 
					        if (history.state.data && history.state.data.blockHeight) {
 | 
				
			||||||
          this.blockHeight = history.state.data.blockHeight;
 | 
					          this.blockHeight = history.state.data.blockHeight;
 | 
				
			||||||
@ -446,7 +449,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
            inBlock[tx.txid] = true;
 | 
					            inBlock[tx.txid] = true;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          blockAudit.feeDelta = blockAudit.expectedFees > 0 ? (blockAudit.expectedFees - this.block.extras.totalFees) / blockAudit.expectedFees : 0;
 | 
					          blockAudit.feeDelta = blockAudit.expectedFees > 0 ? (blockAudit.expectedFees - (this.block.extras.totalFees + this.oobFees)) / blockAudit.expectedFees : 0;
 | 
				
			||||||
          blockAudit.weightDelta = blockAudit.expectedWeight > 0 ? (blockAudit.expectedWeight - this.block.weight) / blockAudit.expectedWeight : 0;
 | 
					          blockAudit.weightDelta = blockAudit.expectedWeight > 0 ? (blockAudit.expectedWeight - this.block.weight) / blockAudit.expectedWeight : 0;
 | 
				
			||||||
          blockAudit.txDelta = blockAudit.template.length > 0 ? (blockAudit.template.length - this.block.tx_count) / blockAudit.template.length : 0;
 | 
					          blockAudit.txDelta = blockAudit.template.length > 0 ? (blockAudit.template.length - this.block.tx_count) / blockAudit.template.length : 0;
 | 
				
			||||||
          this.blockAudit = blockAudit;
 | 
					          this.blockAudit = blockAudit;
 | 
				
			||||||
@ -462,6 +465,32 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
      this.setupBlockGraphs();
 | 
					      this.setupBlockGraphs();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.oobSubscription = block$.pipe(
 | 
				
			||||||
 | 
					      switchMap((block) => this.apiService.getAccelerationsByHeight$(block.height)
 | 
				
			||||||
 | 
					        .pipe(
 | 
				
			||||||
 | 
					          map(accelerations => {
 | 
				
			||||||
 | 
					            return { block, accelerations };
 | 
				
			||||||
 | 
					          }),
 | 
				
			||||||
 | 
					          catchError((err) => {
 | 
				
			||||||
 | 
					            return of({ block, accelerations: [] });
 | 
				
			||||||
 | 
					        }))
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    ).subscribe(({ block, accelerations}) => {
 | 
				
			||||||
 | 
					      let totalFees = 0;
 | 
				
			||||||
 | 
					      for (const acc of accelerations) {
 | 
				
			||||||
 | 
					        totalFees += acc.boost_cost;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      this.oobFees = totalFees;
 | 
				
			||||||
 | 
					      if (block && this.block && this.blockAudit && block?.height === this.block?.height) {
 | 
				
			||||||
 | 
					        this.blockAudit.feeDelta = this.blockAudit.expectedFees > 0 ? (this.blockAudit.expectedFees - (this.block.extras.totalFees + this.oobFees)) / this.blockAudit.expectedFees : 0;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    (error) => {
 | 
				
			||||||
 | 
					      this.error = error;
 | 
				
			||||||
 | 
					      this.isLoadingBlock = false;
 | 
				
			||||||
 | 
					      this.isLoadingOverview = false;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.networkChangedSubscription = this.stateService.networkChanged$
 | 
					    this.networkChangedSubscription = this.stateService.networkChanged$
 | 
				
			||||||
      .subscribe((network) => this.network = network);
 | 
					      .subscribe((network) => this.network = network);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -529,6 +558,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
				
			|||||||
    this.unsubscribeNextBlockSubscriptions();
 | 
					    this.unsubscribeNextBlockSubscriptions();
 | 
				
			||||||
    this.childChangeSubscription?.unsubscribe();
 | 
					    this.childChangeSubscription?.unsubscribe();
 | 
				
			||||||
    this.priceSubscription?.unsubscribe();
 | 
					    this.priceSubscription?.unsubscribe();
 | 
				
			||||||
 | 
					    this.oobSubscription?.unsubscribe();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  unsubscribeNextBlockSubscriptions() {
 | 
					  unsubscribeNextBlockSubscriptions() {
 | 
				
			||||||
 | 
				
			|||||||
@ -56,7 +56,7 @@
 | 
				
			|||||||
              <app-time kind="since" [time]="block.timestamp" [fastRender]="true" [precision]="1" minUnit="minute"></app-time></div>
 | 
					              <app-time kind="since" [time]="block.timestamp" [fastRender]="true" [precision]="1" minUnit="minute"></app-time></div>
 | 
				
			||||||
          </ng-container>
 | 
					          </ng-container>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div class="animated" [class]="markHeight === block.height ? 'hide' : 'show'" *ngIf="block.extras?.pool != undefined">
 | 
					        <div class="animated" [class]="markHeight === block.height ? 'hide' : 'show'" *ngIf="block.extras?.pool != undefined && showPools">
 | 
				
			||||||
          <a [attr.data-cy]="'bitcoin-block-' + offset + '-index-' + i + '-pool'" class="badge badge-primary"
 | 
					          <a [attr.data-cy]="'bitcoin-block-' + offset + '-index-' + i + '-pool'" class="badge badge-primary"
 | 
				
			||||||
            [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]">
 | 
					            [routerLink]="[('/mining/pool/' + block.extras.pool.slug) | relativeUrl]">
 | 
				
			||||||
            {{ block.extras.pool.name}}</a>
 | 
					            {{ block.extras.pool.name}}</a>
 | 
				
			||||||
 | 
				
			|||||||
@ -27,6 +27,7 @@ export class BlockchainBlocksComponent implements OnInit, OnChanges, OnDestroy {
 | 
				
			|||||||
  @Input() minimal: boolean = false;
 | 
					  @Input() minimal: boolean = false;
 | 
				
			||||||
  @Input() blockWidth: number = 125;
 | 
					  @Input() blockWidth: number = 125;
 | 
				
			||||||
  @Input() spotlight: number = 0;
 | 
					  @Input() spotlight: number = 0;
 | 
				
			||||||
 | 
					  @Input() showPools: boolean = true;
 | 
				
			||||||
  @Input() getHref?: (index, block) => string = (index, block) => `/block/${block.id}`;
 | 
					  @Input() getHref?: (index, block) => string = (index, block) => `/block/${block.id}`;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  specialBlocks = specialBlocks;
 | 
					  specialBlocks = specialBlocks;
 | 
				
			||||||
 | 
				
			|||||||
@ -16,6 +16,7 @@
 | 
				
			|||||||
          [minimal]="true"
 | 
					          [minimal]="true"
 | 
				
			||||||
          [count]="blockchainBlocks"
 | 
					          [count]="blockchainBlocks"
 | 
				
			||||||
          [blockWidth]="blockWidth"
 | 
					          [blockWidth]="blockWidth"
 | 
				
			||||||
 | 
					          [showPools]="false"
 | 
				
			||||||
          [spotlight]="mode === 'mined' ? -index - 1 : 0"
 | 
					          [spotlight]="mode === 'mined' ? -index - 1 : 0"
 | 
				
			||||||
          [getHref]="getMinedUrl"
 | 
					          [getHref]="getMinedUrl"
 | 
				
			||||||
        ></app-blockchain-blocks>
 | 
					        ></app-blockchain-blocks>
 | 
				
			||||||
 | 
				
			|||||||
@ -16,9 +16,9 @@
 | 
				
			|||||||
  </ng-container>
 | 
					  </ng-container>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <a class="navbar-brand" [ngClass]="{'dual-logos': subdomain}" [routerLink]="['/' | relativeUrl]" (click)="brandClick($event)">
 | 
					  <a class="navbar-brand" [ngClass]="{'dual-logos': subdomain}" [routerLink]="['/' | relativeUrl]" (click)="brandClick($event)">
 | 
				
			||||||
  <ng-template [ngIf]="subdomain">
 | 
					  <ng-template [ngIf]="subdomain && enterpriseInfo">
 | 
				
			||||||
    <div class="subdomain_container">
 | 
					    <div class="subdomain_container">
 | 
				
			||||||
      <img [src]="'/api/v1/services/enterprise/images/' + subdomain + '/logo'" class="subdomain_logo">
 | 
					      <img [src]="'/api/v1/services/enterprise/images/' + subdomain + '/logo?imageMd5=' + enterpriseInfo.imageMd5" class="subdomain_logo">
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
  </ng-template>
 | 
					  </ng-template>
 | 
				
			||||||
    <ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
 | 
					    <ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Component, OnInit, Input, ViewChild } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, Input, ViewChild } from '@angular/core';
 | 
				
			||||||
import { Router } from '@angular/router';
 | 
					import { Router } from '@angular/router';
 | 
				
			||||||
import { Env, StateService } from '../../services/state.service';
 | 
					import { Env, StateService } from '../../services/state.service';
 | 
				
			||||||
import { Observable, merge, of } from 'rxjs';
 | 
					import { Observable, merge, of, Subscription } from 'rxjs';
 | 
				
			||||||
import { LanguageService } from '../../services/language.service';
 | 
					import { LanguageService } from '../../services/language.service';
 | 
				
			||||||
import { EnterpriseService } from '../../services/enterprise.service';
 | 
					import { EnterpriseService } from '../../services/enterprise.service';
 | 
				
			||||||
import { NavigationService } from '../../services/navigation.service';
 | 
					import { NavigationService } from '../../services/navigation.service';
 | 
				
			||||||
@ -14,7 +14,7 @@ import { ApiService } from '../../services/api.service';
 | 
				
			|||||||
  templateUrl: './master-page.component.html',
 | 
					  templateUrl: './master-page.component.html',
 | 
				
			||||||
  styleUrls: ['./master-page.component.scss'],
 | 
					  styleUrls: ['./master-page.component.scss'],
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
export class MasterPageComponent implements OnInit {
 | 
					export class MasterPageComponent implements OnInit, OnDestroy {
 | 
				
			||||||
  @Input() headerVisible = true;
 | 
					  @Input() headerVisible = true;
 | 
				
			||||||
  @Input() footerVisibleOverride: boolean | null = null;
 | 
					  @Input() footerVisibleOverride: boolean | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -33,6 +33,9 @@ export class MasterPageComponent implements OnInit {
 | 
				
			|||||||
  servicesEnabled = false;
 | 
					  servicesEnabled = false;
 | 
				
			||||||
  menuOpen = false;
 | 
					  menuOpen = false;
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  enterpriseInfo: any;
 | 
				
			||||||
 | 
					  enterpriseInfo$: Subscription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @ViewChild(MenuComponent)
 | 
					  @ViewChild(MenuComponent)
 | 
				
			||||||
  public menuComponent!: MenuComponent;
 | 
					  public menuComponent!: MenuComponent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -64,6 +67,9 @@ export class MasterPageComponent implements OnInit {
 | 
				
			|||||||
        this.footerVisible = this.footerVisibleOverride;
 | 
					        this.footerVisible = this.footerVisibleOverride;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					    this.enterpriseInfo$ = this.enterpriseService.info$.subscribe(info => {
 | 
				
			||||||
 | 
					      this.enterpriseInfo = info;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    this.servicesEnabled = this.officialMempoolSpace && this.stateService.env.ACCELERATOR === true && this.stateService.network === '';
 | 
					    this.servicesEnabled = this.officialMempoolSpace && this.stateService.env.ACCELERATOR === true && this.stateService.network === '';
 | 
				
			||||||
    this.refreshAuth();
 | 
					    this.refreshAuth();
 | 
				
			||||||
@ -72,6 +78,12 @@ export class MasterPageComponent implements OnInit {
 | 
				
			|||||||
    this.menuOpen = isServicesPage && !this.isSmallScreen();
 | 
					    this.menuOpen = isServicesPage && !this.isSmallScreen();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ngOnDestroy() {
 | 
				
			||||||
 | 
					    if (this.enterpriseInfo$) {
 | 
				
			||||||
 | 
					      this.enterpriseInfo$.unsubscribe();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  collapse(): void {
 | 
					  collapse(): void {
 | 
				
			||||||
    this.navCollapsed = !this.navCollapsed;
 | 
					    this.navCollapsed = !this.navCollapsed;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -70,6 +70,26 @@
 | 
				
			|||||||
                    <app-tx-features [tx]="tx"></app-tx-features>
 | 
					                    <app-tx-features [tx]="tx"></app-tx-features>
 | 
				
			||||||
                  </td>
 | 
					                  </td>
 | 
				
			||||||
                </tr>
 | 
					                </tr>
 | 
				
			||||||
 | 
					                <tr *ngIf="network === ''">
 | 
				
			||||||
 | 
					                  <td class="td-width" i18n="transaction.mining">Mining</td>
 | 
				
			||||||
 | 
					                  <td *ngIf="pool" class="wrap-cell">
 | 
				
			||||||
 | 
					                    <a placement="bottom" [routerLink]="['/mining/pool' | relativeUrl, pool.slug]" class="badge mr-1"
 | 
				
			||||||
 | 
					                      [class]="pool.name === 'Unknown' ? 'badge-secondary' : 'badge-primary'">
 | 
				
			||||||
 | 
					                      {{ pool.name }}
 | 
				
			||||||
 | 
					                    </a>
 | 
				
			||||||
 | 
					                    <ng-container *ngIf="auditStatus">
 | 
				
			||||||
 | 
					                      <span *ngIf="auditStatus.coinbase; else expected" class="badge badge-primary mr-1" i18n="tx-features.tag.coinbase|Coinbase">Coinbase</span>
 | 
				
			||||||
 | 
					                      <ng-template #expected><span *ngIf="auditStatus.expected; else seen" class="badge badge-success mr-1" i18n-ngbTooltip="Expected in block tooltip" ngbTooltip="This transaction was projected to be included in the block" placement="bottom" i18n="tx-features.tag.expected|Expected in Block">Expected in Block</span></ng-template>
 | 
				
			||||||
 | 
					                      <ng-template #seen><span *ngIf="auditStatus.seen; else notSeen" class="badge badge-success mr-1" i18n-ngbTooltip="Seen in mempool tooltip" ngbTooltip="This transaction was seen in the mempool prior to mining" placement="bottom" i18n="tx-features.tag.seen|Seen in Mempool">Seen in Mempool</span></ng-template>
 | 
				
			||||||
 | 
					                      <ng-template #notSeen><span class="badge badge-warning mr-1" i18n-ngbTooltip="Not seen in mempool tooltip" ngbTooltip="This transaction was missing from our mempool prior to mining" placement="bottom" i18n="tx-features.tag.not-seen|Not seen in Mempool">Not seen in Mempool</span></ng-template>
 | 
				
			||||||
 | 
					                      <span *ngIf="auditStatus.added" class="badge badge-primary mr-1" i18n-ngbTooltip="Added transaction tooltip" ngbTooltip="This transaction may have been added or prioritized out-of-band" placement="bottom" i18n="tx-features.tag.added|Added">Added</span>
 | 
				
			||||||
 | 
					                      <span *ngIf="auditStatus.conflict" class="badge badge-warning mr-1" i18n-ngbTooltip="Conflict in mempool tooltip" ngbTooltip="This transaction conflicted with another version in our mempool" placement="bottom" i18n="tx-features.tag.conflict|Conflict">Conflict</span>
 | 
				
			||||||
 | 
					                    </ng-container>
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                  <td *ngIf="!pool">
 | 
				
			||||||
 | 
					                    <span class="skeleton-loader"></span>
 | 
				
			||||||
 | 
					                  </td>
 | 
				
			||||||
 | 
					                </tr>
 | 
				
			||||||
              </tbody>
 | 
					              </tbody>
 | 
				
			||||||
            </table>
 | 
					            </table>
 | 
				
			||||||
          </div>
 | 
					          </div>
 | 
				
			||||||
@ -509,7 +529,7 @@
 | 
				
			|||||||
<ng-template #feeTable>
 | 
					<ng-template #feeTable>
 | 
				
			||||||
  <table class="table table-borderless table-striped">
 | 
					  <table class="table table-borderless table-striped">
 | 
				
			||||||
    <tbody>
 | 
					    <tbody>
 | 
				
			||||||
      <tr *ngIf="isMobile && (network === 'liquid' || network === 'liquidtestnet' || !featuresEnabled)"></tr>
 | 
					      <tr *ngIf="isMobile && (network === 'liquid' || network === 'liquidtestnet' || !featuresEnabled || network === '')"></tr>
 | 
				
			||||||
      <tr>
 | 
					      <tr>
 | 
				
			||||||
        <td class="td-width" i18n="transaction.fee|Transaction fee">Fee</td>
 | 
					        <td class="td-width" i18n="transaction.fee|Transaction fee">Fee</td>
 | 
				
			||||||
        <td>{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [blockConversion]="blockConversion" [value]="tx.fee"></app-fiat></span></td>
 | 
					        <td>{{ tx.fee | number }} <span class="symbol" i18n="shared.sat|sat">sat</span> <span class="fiat"><app-fiat [blockConversion]="blockConversion" [value]="tx.fee"></app-fiat></span></td>
 | 
				
			||||||
 | 
				
			|||||||
@ -149,6 +149,10 @@
 | 
				
			|||||||
		.btn {
 | 
							.btn {
 | 
				
			||||||
			display: block;
 | 
								display: block;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    &.wrap-cell {
 | 
				
			||||||
 | 
					      white-space: normal;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -8,10 +8,11 @@ import {
 | 
				
			|||||||
  retryWhen,
 | 
					  retryWhen,
 | 
				
			||||||
  delay,
 | 
					  delay,
 | 
				
			||||||
  mergeMap,
 | 
					  mergeMap,
 | 
				
			||||||
  tap
 | 
					  tap,
 | 
				
			||||||
 | 
					  map
 | 
				
			||||||
} from 'rxjs/operators';
 | 
					} from 'rxjs/operators';
 | 
				
			||||||
import { Transaction } from '../../interfaces/electrs.interface';
 | 
					import { Transaction } from '../../interfaces/electrs.interface';
 | 
				
			||||||
import { of, merge, Subscription, Observable, Subject, from, throwError } from 'rxjs';
 | 
					import { of, merge, Subscription, Observable, Subject, from, throwError, combineLatest } from 'rxjs';
 | 
				
			||||||
import { StateService } from '../../services/state.service';
 | 
					import { StateService } from '../../services/state.service';
 | 
				
			||||||
import { CacheService } from '../../services/cache.service';
 | 
					import { CacheService } from '../../services/cache.service';
 | 
				
			||||||
import { WebsocketService } from '../../services/websocket.service';
 | 
					import { WebsocketService } from '../../services/websocket.service';
 | 
				
			||||||
@ -28,6 +29,22 @@ import { isFeatureActive } from '../../bitcoin.utils';
 | 
				
			|||||||
import { ServicesApiServices } from '../../services/services-api.service';
 | 
					import { ServicesApiServices } from '../../services/services-api.service';
 | 
				
			||||||
import { EnterpriseService } from '../../services/enterprise.service';
 | 
					import { EnterpriseService } from '../../services/enterprise.service';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface Pool {
 | 
				
			||||||
 | 
					  id: number;
 | 
				
			||||||
 | 
					  name: string;
 | 
				
			||||||
 | 
					  slug: string;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface AuditStatus {
 | 
				
			||||||
 | 
					  seen?: boolean;
 | 
				
			||||||
 | 
					  expected?: boolean;
 | 
				
			||||||
 | 
					  added?: boolean;
 | 
				
			||||||
 | 
					  delayed?: number;
 | 
				
			||||||
 | 
					  accelerated?: boolean;
 | 
				
			||||||
 | 
					  conflict?: boolean;
 | 
				
			||||||
 | 
					  coinbase?: boolean;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Component({
 | 
					@Component({
 | 
				
			||||||
  selector: 'app-transaction',
 | 
					  selector: 'app-transaction',
 | 
				
			||||||
  templateUrl: './transaction.component.html',
 | 
					  templateUrl: './transaction.component.html',
 | 
				
			||||||
@ -58,6 +75,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
  urlFragmentSubscription: Subscription;
 | 
					  urlFragmentSubscription: Subscription;
 | 
				
			||||||
  mempoolBlocksSubscription: Subscription;
 | 
					  mempoolBlocksSubscription: Subscription;
 | 
				
			||||||
  blocksSubscription: Subscription;
 | 
					  blocksSubscription: Subscription;
 | 
				
			||||||
 | 
					  miningSubscription: Subscription;
 | 
				
			||||||
  fragmentParams: URLSearchParams;
 | 
					  fragmentParams: URLSearchParams;
 | 
				
			||||||
  rbfTransaction: undefined | Transaction;
 | 
					  rbfTransaction: undefined | Transaction;
 | 
				
			||||||
  replaced: boolean = false;
 | 
					  replaced: boolean = false;
 | 
				
			||||||
@ -67,11 +85,14 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
  accelerationInfo: Acceleration | null = null;
 | 
					  accelerationInfo: Acceleration | null = null;
 | 
				
			||||||
  sigops: number | null;
 | 
					  sigops: number | null;
 | 
				
			||||||
  adjustedVsize: number | null;
 | 
					  adjustedVsize: number | null;
 | 
				
			||||||
 | 
					  pool: Pool | null;
 | 
				
			||||||
 | 
					  auditStatus: AuditStatus | null;
 | 
				
			||||||
  showCpfpDetails = false;
 | 
					  showCpfpDetails = false;
 | 
				
			||||||
  fetchCpfp$ = new Subject<string>();
 | 
					  fetchCpfp$ = new Subject<string>();
 | 
				
			||||||
  fetchRbfHistory$ = new Subject<string>();
 | 
					  fetchRbfHistory$ = new Subject<string>();
 | 
				
			||||||
  fetchCachedTx$ = new Subject<string>();
 | 
					  fetchCachedTx$ = new Subject<string>();
 | 
				
			||||||
  fetchAcceleration$ = new Subject<string>();
 | 
					  fetchAcceleration$ = new Subject<string>();
 | 
				
			||||||
 | 
					  fetchMiningInfo$ = new Subject<{ hash: string, height: number, txid: string }>();
 | 
				
			||||||
  isCached: boolean = false;
 | 
					  isCached: boolean = false;
 | 
				
			||||||
  now = Date.now();
 | 
					  now = Date.now();
 | 
				
			||||||
  da$: Observable<DifficultyAdjustment>;
 | 
					  da$: Observable<DifficultyAdjustment>;
 | 
				
			||||||
@ -100,6 +121,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
  acceleratorAvailable: boolean = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === '';
 | 
					  acceleratorAvailable: boolean = this.stateService.env.OFFICIAL_MEMPOOL_SPACE && this.stateService.env.ACCELERATOR && this.stateService.network === '';
 | 
				
			||||||
  showAccelerationSummary = false;
 | 
					  showAccelerationSummary = false;
 | 
				
			||||||
  scrollIntoAccelPreview = false;
 | 
					  scrollIntoAccelPreview = false;
 | 
				
			||||||
 | 
					  auditEnabled: boolean = this.stateService.env.AUDIT && this.stateService.env.BASE_MODULE === 'mempool' && this.stateService.env.MINING_DASHBOARD === true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @ViewChild('graphContainer')
 | 
					  @ViewChild('graphContainer')
 | 
				
			||||||
  graphContainer: ElementRef;
 | 
					  graphContainer: ElementRef;
 | 
				
			||||||
@ -266,6 +288,54 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.miningSubscription = this.fetchMiningInfo$.pipe(
 | 
				
			||||||
 | 
					      filter((target) => target.txid === this.txId),
 | 
				
			||||||
 | 
					      tap(() => {
 | 
				
			||||||
 | 
					        this.pool = null;
 | 
				
			||||||
 | 
					        this.auditStatus = null;
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					      switchMap(({ hash, height, txid }) => {
 | 
				
			||||||
 | 
					        const foundBlock = this.cacheService.getCachedBlock(height) || null;
 | 
				
			||||||
 | 
					        const auditAvailable = this.isAuditAvailable(height);
 | 
				
			||||||
 | 
					        const isCoinbase = this.tx.vin.some(v => v.is_coinbase);
 | 
				
			||||||
 | 
					        const fetchAudit = auditAvailable && !isCoinbase;
 | 
				
			||||||
 | 
					        return combineLatest([
 | 
				
			||||||
 | 
					          foundBlock ? of(foundBlock.extras.pool) : this.apiService.getBlock$(hash).pipe(
 | 
				
			||||||
 | 
					            map(block => {
 | 
				
			||||||
 | 
					              return block.extras.pool;
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            catchError(() => {
 | 
				
			||||||
 | 
					              return of(null);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          fetchAudit ? this.apiService.getBlockAudit$(hash).pipe(
 | 
				
			||||||
 | 
					            map(audit => {
 | 
				
			||||||
 | 
					              const isAdded = audit.addedTxs.includes(txid);
 | 
				
			||||||
 | 
					              const isAccelerated = audit.acceleratedTxs.includes(txid);
 | 
				
			||||||
 | 
					              const isConflict = audit.fullrbfTxs.includes(txid);
 | 
				
			||||||
 | 
					              const isExpected = audit.template.some(tx => tx.txid === txid);
 | 
				
			||||||
 | 
					              return {
 | 
				
			||||||
 | 
					                seen: isExpected || !(isAdded || isConflict),
 | 
				
			||||||
 | 
					                expected: isExpected,
 | 
				
			||||||
 | 
					                added: isAdded,
 | 
				
			||||||
 | 
					                conflict: isConflict,
 | 
				
			||||||
 | 
					                accelerated: isAccelerated,
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            catchError(() => {
 | 
				
			||||||
 | 
					              return of(null);
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					          ) : of(isCoinbase ? { coinbase: true } : null)
 | 
				
			||||||
 | 
					        ]);
 | 
				
			||||||
 | 
					      }),
 | 
				
			||||||
 | 
					      catchError(() => {
 | 
				
			||||||
 | 
					        return of(null);
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    ).subscribe(([pool, auditStatus]) => {
 | 
				
			||||||
 | 
					      this.pool = pool;
 | 
				
			||||||
 | 
					      this.auditStatus = auditStatus;
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.mempoolPositionSubscription = this.stateService.mempoolTxPosition$.subscribe(txPosition => {
 | 
					    this.mempoolPositionSubscription = this.stateService.mempoolTxPosition$.subscribe(txPosition => {
 | 
				
			||||||
      this.now = Date.now();
 | 
					      this.now = Date.now();
 | 
				
			||||||
      if (txPosition && txPosition.txid === this.txId && txPosition.position) {
 | 
					      if (txPosition && txPosition.txid === this.txId && txPosition.position) {
 | 
				
			||||||
@ -396,6 +466,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            this.fetchAcceleration$.next(tx.status.block_hash);
 | 
					            this.fetchAcceleration$.next(tx.status.block_hash);
 | 
				
			||||||
 | 
					            this.fetchMiningInfo$.next({ hash: tx.status.block_hash, height: tx.status.block_height, txid: tx.txid });
 | 
				
			||||||
            this.transactionTime = 0;
 | 
					            this.transactionTime = 0;
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -453,6 +524,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
          this.audioService.playSound('magic');
 | 
					          this.audioService.playSound('magic');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        this.fetchAcceleration$.next(block.id);
 | 
					        this.fetchAcceleration$.next(block.id);
 | 
				
			||||||
 | 
					        this.fetchMiningInfo$.next({ hash: block.id, height: block.height, txid: this.tx.txid });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -606,6 +678,29 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
    this.featuresEnabled = this.segwitEnabled || this.taprootEnabled || this.rbfEnabled;
 | 
					    this.featuresEnabled = this.segwitEnabled || this.taprootEnabled || this.rbfEnabled;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  isAuditAvailable(blockHeight: number): boolean {
 | 
				
			||||||
 | 
					    if (!this.auditEnabled) {
 | 
				
			||||||
 | 
					      return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    switch (this.stateService.network) {
 | 
				
			||||||
 | 
					      case 'testnet':
 | 
				
			||||||
 | 
					        if (blockHeight < this.stateService.env.TESTNET_BLOCK_AUDIT_START_HEIGHT) {
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      case 'signet':
 | 
				
			||||||
 | 
					        if (blockHeight < this.stateService.env.SIGNET_BLOCK_AUDIT_START_HEIGHT) {
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
 | 
					      default:
 | 
				
			||||||
 | 
					        if (blockHeight < this.stateService.env.MAINNET_BLOCK_AUDIT_START_HEIGHT) {
 | 
				
			||||||
 | 
					          return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  resetTransaction() {
 | 
					  resetTransaction() {
 | 
				
			||||||
    this.error = undefined;
 | 
					    this.error = undefined;
 | 
				
			||||||
    this.tx = null;
 | 
					    this.tx = null;
 | 
				
			||||||
@ -625,6 +720,8 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
    this.accelerationInfo = null;
 | 
					    this.accelerationInfo = null;
 | 
				
			||||||
    this.txInBlockIndex = null;
 | 
					    this.txInBlockIndex = null;
 | 
				
			||||||
    this.mempoolPosition = null;
 | 
					    this.mempoolPosition = null;
 | 
				
			||||||
 | 
					    this.pool = null;
 | 
				
			||||||
 | 
					    this.auditStatus = null;
 | 
				
			||||||
    document.body.scrollTo(0, 0);
 | 
					    document.body.scrollTo(0, 0);
 | 
				
			||||||
    this.leaveTransaction();
 | 
					    this.leaveTransaction();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -712,6 +809,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
 | 
				
			|||||||
    this.mempoolPositionSubscription.unsubscribe();
 | 
					    this.mempoolPositionSubscription.unsubscribe();
 | 
				
			||||||
    this.mempoolBlocksSubscription.unsubscribe();
 | 
					    this.mempoolBlocksSubscription.unsubscribe();
 | 
				
			||||||
    this.blocksSubscription.unsubscribe();
 | 
					    this.blocksSubscription.unsubscribe();
 | 
				
			||||||
 | 
					    this.miningSubscription?.unsubscribe();
 | 
				
			||||||
    this.leaveTransaction();
 | 
					    this.leaveTransaction();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -236,7 +236,7 @@ export class DashboardComponent implements OnInit, OnDestroy, AfterViewInit {
 | 
				
			|||||||
                  acc.unshift(stats);
 | 
					                  acc.unshift(stats);
 | 
				
			||||||
                  acc = acc.slice(0, 120);
 | 
					                  acc = acc.slice(0, 120);
 | 
				
			||||||
                  return acc;
 | 
					                  return acc;
 | 
				
			||||||
                }, mempoolStats)
 | 
					                }, (mempoolStats || []))
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
            of(mempoolStats)
 | 
					            of(mempoolStats)
 | 
				
			||||||
          );
 | 
					          );
 | 
				
			||||||
 | 
				
			|||||||
@ -9878,16 +9878,179 @@ export const restApiDocsData = [
 | 
				
			|||||||
  },
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    type: "category",
 | 
					    type: "category",
 | 
				
			||||||
    category: "accelerator",
 | 
					    category: "accelerator-public",
 | 
				
			||||||
    fragment: "accelerator",
 | 
					    fragment: "accelerator-public",
 | 
				
			||||||
    title: "Accelerator",
 | 
					    title: "Accelerator (Public)",
 | 
				
			||||||
    showConditions: [""],
 | 
					    showConditions: [""],
 | 
				
			||||||
    options: { officialOnly: true },
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    options: { officialOnly: true },
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
    type: "endpoint",
 | 
					    type: "endpoint",
 | 
				
			||||||
    category: "accelerator",
 | 
					    category: "accelerator-public",
 | 
				
			||||||
 | 
					    httpRequestMethod: "POST",
 | 
				
			||||||
 | 
					    fragment: "accelerator-estimate",
 | 
				
			||||||
 | 
					    title: "POST Calculate Estimated Costs",
 | 
				
			||||||
 | 
					    description: {
 | 
				
			||||||
 | 
					      default: "<p>Returns estimated costs to accelerate a transaction. Optionally set the <code>api_key</code> header to get customized estimation.</p>"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    urlString: "/v1/services/accelerator/estimate",
 | 
				
			||||||
 | 
					    showConditions: [""],
 | 
				
			||||||
 | 
					    showJsExamples: showJsExamplesDefaultFalse,
 | 
				
			||||||
 | 
					    codeExample: {
 | 
				
			||||||
 | 
					      default: {
 | 
				
			||||||
 | 
					        codeTemplate: {
 | 
				
			||||||
 | 
					          curl: `%{1}" "[[hostname]][[baseNetworkUrl]]/api/v1/services/accelerator/estimate`, //custom interpolation technique handled in replaceCurlPlaceholder()
 | 
				
			||||||
 | 
					          commonJS: ``,
 | 
				
			||||||
 | 
					          esModule: ``
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        codeSampleMainnet: {
 | 
				
			||||||
 | 
					          esModule: [],
 | 
				
			||||||
 | 
					          commonJS: [],
 | 
				
			||||||
 | 
					          curl: ["txInput=ee13ebb99632377c15c94980357f674d285ac413452050031ea6dcd3e9b2dc29"],
 | 
				
			||||||
 | 
					          headers: "api_key: stacksats",
 | 
				
			||||||
 | 
					          response: `{
 | 
				
			||||||
 | 
					  "txSummary": {
 | 
				
			||||||
 | 
					    "txid": "ee13ebb99632377c15c94980357f674d285ac413452050031ea6dcd3e9b2dc29",
 | 
				
			||||||
 | 
					    "effectiveVsize": 154,
 | 
				
			||||||
 | 
					    "effectiveFee": 154,
 | 
				
			||||||
 | 
					    "ancestorCount": 1
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "cost": 3850,
 | 
				
			||||||
 | 
					  "targetFeeRate": 26,
 | 
				
			||||||
 | 
					  "nextBlockFee": 4004,
 | 
				
			||||||
 | 
					  "userBalance": 99900000,
 | 
				
			||||||
 | 
					  "mempoolBaseFee": 40000,
 | 
				
			||||||
 | 
					  "vsizeFee": 50000,
 | 
				
			||||||
 | 
					  "hasAccess": true
 | 
				
			||||||
 | 
					}`,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
 | 
					    type: "endpoint",
 | 
				
			||||||
 | 
					    category: "accelerator-public",
 | 
				
			||||||
 | 
					    httpRequestMethod: "GET",
 | 
				
			||||||
 | 
					    fragment: "accelerator-pending",
 | 
				
			||||||
 | 
					    title: "GET Pending Accelerations",
 | 
				
			||||||
 | 
					    description: {
 | 
				
			||||||
 | 
					      default: "<p>Returns all transactions currently being accelerated.</p>"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    urlString: "/v1/services/accelerator/accelerations",
 | 
				
			||||||
 | 
					    showConditions: [""],
 | 
				
			||||||
 | 
					    showJsExamples: showJsExamplesDefaultFalse,
 | 
				
			||||||
 | 
					    codeExample: {
 | 
				
			||||||
 | 
					      default: {
 | 
				
			||||||
 | 
					        codeTemplate: {
 | 
				
			||||||
 | 
					          curl: `/api/v1/services/accelerator/accelerations`,
 | 
				
			||||||
 | 
					          commonJS: ``,
 | 
				
			||||||
 | 
					          esModule: ``
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        codeSampleMainnet: {
 | 
				
			||||||
 | 
					          esModule: [],
 | 
				
			||||||
 | 
					          commonJS: [],
 | 
				
			||||||
 | 
					          curl: [],
 | 
				
			||||||
 | 
					          headers: '',
 | 
				
			||||||
 | 
					          response: `[
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "txid": "8a183c8ae929a2afb857e7f2acd440aaefdf2797f8f7eab1c5f95ff8602abc81",
 | 
				
			||||||
 | 
					    "added": 1707558316,
 | 
				
			||||||
 | 
					    "feeDelta": 3500,
 | 
				
			||||||
 | 
					    "effectiveVsize": 111,
 | 
				
			||||||
 | 
					    "effectiveFee": 1671,
 | 
				
			||||||
 | 
					    "pools": [
 | 
				
			||||||
 | 
					      111
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "txid": "6097f295e21bdd8d725bd8d9ad4dd72b05bd795dc648bfef52150a9b2b7f7a45",
 | 
				
			||||||
 | 
					    "added": 1707560464,
 | 
				
			||||||
 | 
					    "feeDelta": 60000,
 | 
				
			||||||
 | 
					    "effectiveVsize": 812,
 | 
				
			||||||
 | 
					    "effectiveFee": 7790,
 | 
				
			||||||
 | 
					    "pools": [
 | 
				
			||||||
 | 
					      111
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]`,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
 | 
					    type: "endpoint",
 | 
				
			||||||
 | 
					    category: "accelerator-public",
 | 
				
			||||||
 | 
					    httpRequestMethod: "GET",
 | 
				
			||||||
 | 
					    fragment: "accelerator-public-history",
 | 
				
			||||||
 | 
					    title: "GET Acceleration History",
 | 
				
			||||||
 | 
					    description: {
 | 
				
			||||||
 | 
					      default: `<p>Returns all past accelerated transactions.
 | 
				
			||||||
 | 
					      Filters can be applied:<ul>
 | 
				
			||||||
 | 
					      <li><code>status</code>: <code>all</code>, <code>requested</code>, <code>accelerating</code>, <code>mined</code>, <code>completed</code>, <code>failed</code></li>
 | 
				
			||||||
 | 
					      <li><code>timeframe</code>: <code>24h</code>, <code>3d</code>, <code>1w</code>, <code>1m</code>, <code>3m</code>, <code>6m</code>, <code>1y</code>, <code>2y</code>, <code>3y</code>, <code>4y</code>, <code>all</code></li>
 | 
				
			||||||
 | 
					      <li><code>poolUniqueId</code>: any id from <a target="_blank" href="https://github.com/mempool/mining-pools/blob/master/pools-v2.json">https://github.com/mempool/mining-pools/blob/master/pools-v2.json</a>. <i>Note: This will return all acceleration requests accepted by the pool but the the listed transactions may have been mined by another pool.</i>
 | 
				
			||||||
 | 
					      <li><code>blockHash</code>: a block hash</a>
 | 
				
			||||||
 | 
					      <li><code>blockHeight</code>: a block height</a>
 | 
				
			||||||
 | 
					      <li><code>page</code>: the requested page number if using pagination <i>(min: 1)</i></a>
 | 
				
			||||||
 | 
					      <li><code>pageLength</code>: the page lenght if using pagination <i>(min: 1, max: 50)</i></a>
 | 
				
			||||||
 | 
					      </ul></p>`
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    urlString: "/v1/services/accelerator/accelerations/history",
 | 
				
			||||||
 | 
					    showConditions: [""],
 | 
				
			||||||
 | 
					    showJsExamples: showJsExamplesDefaultFalse,
 | 
				
			||||||
 | 
					    codeExample: {
 | 
				
			||||||
 | 
					      default: {
 | 
				
			||||||
 | 
					        codeTemplate: {
 | 
				
			||||||
 | 
					          curl: `/api/v1/services/accelerator/accelerations/history?blockHash=00000000000000000000482f0746d62141694b9210a813b97eb8445780a32003`,
 | 
				
			||||||
 | 
					          commonJS: ``,
 | 
				
			||||||
 | 
					          esModule: ``
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        codeSampleMainnet: {
 | 
				
			||||||
 | 
					          esModule: [],
 | 
				
			||||||
 | 
					          commonJS: [],
 | 
				
			||||||
 | 
					          curl: [],
 | 
				
			||||||
 | 
					          headers: '',
 | 
				
			||||||
 | 
					          response: `[
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "txid": "d7e1796d8eb4a09d4e6c174e36cfd852f1e6e6c9f7df4496339933cd32cbdd1d",
 | 
				
			||||||
 | 
					    "status": "completed",
 | 
				
			||||||
 | 
					    "feePaid": 53239,
 | 
				
			||||||
 | 
					    "added": 1707421053,
 | 
				
			||||||
 | 
					    "lastUpdated": 1707422952,
 | 
				
			||||||
 | 
					    "baseFee": 50000,
 | 
				
			||||||
 | 
					    "vsizeFee": 0,
 | 
				
			||||||
 | 
					    "effectiveFee": 146,
 | 
				
			||||||
 | 
					    "effectiveVsize": 141,
 | 
				
			||||||
 | 
					    "feeDelta": 14000,
 | 
				
			||||||
 | 
					    "blockHash": "00000000000000000000482f0746d62141694b9210a813b97eb8445780a32003",
 | 
				
			||||||
 | 
					    "blockHeight": 829559,
 | 
				
			||||||
 | 
					    "pools": [
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        "pool_unique_id": 111,
 | 
				
			||||||
 | 
					        "username": "foundryusa"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]`,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    type: "category",
 | 
				
			||||||
 | 
					    category: "accelerator-private",
 | 
				
			||||||
 | 
					    fragment: "accelerator-private",
 | 
				
			||||||
 | 
					    title: "Accelerator (Authenticated)",
 | 
				
			||||||
 | 
					    showConditions: [""],
 | 
				
			||||||
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
 | 
					    type: "endpoint",
 | 
				
			||||||
 | 
					    category: "accelerator-private",
 | 
				
			||||||
    httpRequestMethod: "GET",
 | 
					    httpRequestMethod: "GET",
 | 
				
			||||||
    fragment: "accelerator-deposit-history",
 | 
					    fragment: "accelerator-deposit-history",
 | 
				
			||||||
    title: "GET Deposit History",
 | 
					    title: "GET Deposit History",
 | 
				
			||||||
@ -9935,7 +10098,7 @@ export const restApiDocsData = [
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    options: { officialOnly: true },
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
    type: "endpoint",
 | 
					    type: "endpoint",
 | 
				
			||||||
    category: "accelerator",
 | 
					    category: "accelerator-private",
 | 
				
			||||||
    httpRequestMethod: "GET",
 | 
					    httpRequestMethod: "GET",
 | 
				
			||||||
    fragment: "accelerator-balance",
 | 
					    fragment: "accelerator-balance",
 | 
				
			||||||
    title: "GET Available Balance",
 | 
					    title: "GET Available Balance",
 | 
				
			||||||
@ -9969,51 +10132,7 @@ export const restApiDocsData = [
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    options: { officialOnly: true },
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
    type: "endpoint",
 | 
					    type: "endpoint",
 | 
				
			||||||
    category: "accelerator",
 | 
					    category: "accelerator-private",
 | 
				
			||||||
    httpRequestMethod: "POST",
 | 
					 | 
				
			||||||
    fragment: "accelerator-estimate",
 | 
					 | 
				
			||||||
    title: "POST Calculate Estimated Costs",
 | 
					 | 
				
			||||||
    description: {
 | 
					 | 
				
			||||||
      default: "<p>Returns estimated costs to accelerate a transaction.</p>"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    urlString: "/v1/services/accelerator/estimate",
 | 
					 | 
				
			||||||
    showConditions: [""],
 | 
					 | 
				
			||||||
    showJsExamples: showJsExamplesDefaultFalse,
 | 
					 | 
				
			||||||
    codeExample: {
 | 
					 | 
				
			||||||
      default: {
 | 
					 | 
				
			||||||
        codeTemplate: {
 | 
					 | 
				
			||||||
          curl: `%{1}" "[[hostname]][[baseNetworkUrl]]/api/v1/services/accelerator/estimate`, //custom interpolation technique handled in replaceCurlPlaceholder()
 | 
					 | 
				
			||||||
          commonJS: ``,
 | 
					 | 
				
			||||||
          esModule: ``
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        codeSampleMainnet: {
 | 
					 | 
				
			||||||
          esModule: [],
 | 
					 | 
				
			||||||
          commonJS: [],
 | 
					 | 
				
			||||||
          curl: ["txInput=ee13ebb99632377c15c94980357f674d285ac413452050031ea6dcd3e9b2dc29"],
 | 
					 | 
				
			||||||
          headers: "api_key: stacksats",
 | 
					 | 
				
			||||||
          response: `{
 | 
					 | 
				
			||||||
  "txSummary": {
 | 
					 | 
				
			||||||
    "txid": "ee13ebb99632377c15c94980357f674d285ac413452050031ea6dcd3e9b2dc29",
 | 
					 | 
				
			||||||
    "effectiveVsize": 154,
 | 
					 | 
				
			||||||
    "effectiveFee": 154,
 | 
					 | 
				
			||||||
    "ancestorCount": 1
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "cost": 3850,
 | 
					 | 
				
			||||||
  "targetFeeRate": 26,
 | 
					 | 
				
			||||||
  "nextBlockFee": 4004,
 | 
					 | 
				
			||||||
  "userBalance": 99900000,
 | 
					 | 
				
			||||||
  "mempoolBaseFee": 40000,
 | 
					 | 
				
			||||||
  "vsizeFee": 50000,
 | 
					 | 
				
			||||||
  "hasAccess": true
 | 
					 | 
				
			||||||
}`,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    options: { officialOnly: true },
 | 
					 | 
				
			||||||
    type: "endpoint",
 | 
					 | 
				
			||||||
    category: "accelerator",
 | 
					 | 
				
			||||||
    httpRequestMethod: "POST",
 | 
					    httpRequestMethod: "POST",
 | 
				
			||||||
    fragment: "accelerator-accelerate",
 | 
					    fragment: "accelerator-accelerate",
 | 
				
			||||||
    title: "POST Accelerate A Transaction",
 | 
					    title: "POST Accelerate A Transaction",
 | 
				
			||||||
@ -10043,10 +10162,10 @@ export const restApiDocsData = [
 | 
				
			|||||||
  {
 | 
					  {
 | 
				
			||||||
    options: { officialOnly: true },
 | 
					    options: { officialOnly: true },
 | 
				
			||||||
    type: "endpoint",
 | 
					    type: "endpoint",
 | 
				
			||||||
    category: "accelerator",
 | 
					    category: "accelerator-private",
 | 
				
			||||||
    httpRequestMethod: "GET",
 | 
					    httpRequestMethod: "GET",
 | 
				
			||||||
    fragment: "accelerator-history",
 | 
					    fragment: "accelerator-history",
 | 
				
			||||||
    title: "GET Private Acceleration History",
 | 
					    title: "GET Acceleration History",
 | 
				
			||||||
    description: {
 | 
					    description: {
 | 
				
			||||||
      default: "<p>Returns the user's past acceleration requests.</p><p>Pass one of the following for <code>:status</code>: <code>all</code>, <code>requested</code>, <code>accelerating</code>, <code>mined</code>, <code>completed</code>, <code>failed</code>. Pass <code>true</code> in <code>:details</code> to get a detailed <code>history</code> of the acceleration request.</p>"
 | 
					      default: "<p>Returns the user's past acceleration requests.</p><p>Pass one of the following for <code>:status</code>: <code>all</code>, <code>requested</code>, <code>accelerating</code>, <code>mined</code>, <code>completed</code>, <code>failed</code>. Pass <code>true</code> in <code>:details</code> to get a detailed <code>history</code> of the acceleration request.</p>"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@ -10153,117 +10272,6 @@ export const restApiDocsData = [
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
]`,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    options: { officialOnly: true },
 | 
					 | 
				
			||||||
    type: "endpoint",
 | 
					 | 
				
			||||||
    category: "accelerator",
 | 
					 | 
				
			||||||
    httpRequestMethod: "GET",
 | 
					 | 
				
			||||||
    fragment: "accelerator-pending",
 | 
					 | 
				
			||||||
    title: "GET Pending Accelerations",
 | 
					 | 
				
			||||||
    description: {
 | 
					 | 
				
			||||||
      default: "<p>Returns all transactions currently being accelerated.</p>"
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    urlString: "/v1/services/accelerator/accelerations",
 | 
					 | 
				
			||||||
    showConditions: [""],
 | 
					 | 
				
			||||||
    showJsExamples: showJsExamplesDefaultFalse,
 | 
					 | 
				
			||||||
    codeExample: {
 | 
					 | 
				
			||||||
      default: {
 | 
					 | 
				
			||||||
        codeTemplate: {
 | 
					 | 
				
			||||||
          curl: `/api/v1/services/accelerator/accelerations`,
 | 
					 | 
				
			||||||
          commonJS: ``,
 | 
					 | 
				
			||||||
          esModule: ``
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        codeSampleMainnet: {
 | 
					 | 
				
			||||||
          esModule: [],
 | 
					 | 
				
			||||||
          commonJS: [],
 | 
					 | 
				
			||||||
          curl: [],
 | 
					 | 
				
			||||||
          headers: '',
 | 
					 | 
				
			||||||
          response: `[
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    "txid": "8a183c8ae929a2afb857e7f2acd440aaefdf2797f8f7eab1c5f95ff8602abc81",
 | 
					 | 
				
			||||||
    "added": 1707558316,
 | 
					 | 
				
			||||||
    "feeDelta": 3500,
 | 
					 | 
				
			||||||
    "effectiveVsize": 111,
 | 
					 | 
				
			||||||
    "effectiveFee": 1671,
 | 
					 | 
				
			||||||
    "pools": [
 | 
					 | 
				
			||||||
      111
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    "txid": "6097f295e21bdd8d725bd8d9ad4dd72b05bd795dc648bfef52150a9b2b7f7a45",
 | 
					 | 
				
			||||||
    "added": 1707560464,
 | 
					 | 
				
			||||||
    "feeDelta": 60000,
 | 
					 | 
				
			||||||
    "effectiveVsize": 812,
 | 
					 | 
				
			||||||
    "effectiveFee": 7790,
 | 
					 | 
				
			||||||
    "pools": [
 | 
					 | 
				
			||||||
      111
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
]`,
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    options: { officialOnly: true },
 | 
					 | 
				
			||||||
    type: "endpoint",
 | 
					 | 
				
			||||||
    category: "accelerator",
 | 
					 | 
				
			||||||
    httpRequestMethod: "GET",
 | 
					 | 
				
			||||||
    fragment: "accelerator-public-history",
 | 
					 | 
				
			||||||
    title: "GET Public Acceleration History",
 | 
					 | 
				
			||||||
    description: {
 | 
					 | 
				
			||||||
      default: `<p>Returns all past accelerated transactions.
 | 
					 | 
				
			||||||
      Filters can be applied:<ul>
 | 
					 | 
				
			||||||
      <li><code>status</code>: <code>all</code>, <code>requested</code>, <code>accelerating</code>, <code>mined</code>, <code>completed</code>, <code>failed</code></li>
 | 
					 | 
				
			||||||
      <li><code>timeframe</code>: <code>24h</code>, <code>3d</code>, <code>1w</code>, <code>1m</code>, <code>3m</code>, <code>6m</code>, <code>1y</code>, <code>2y</code>, <code>3y</code>, <code>all</code></li>
 | 
					 | 
				
			||||||
      <li><code>poolUniqueId</code>: any id from <a target="_blank" href="https://github.com/mempool/mining-pools/blob/master/pools-v2.json">https://github.com/mempool/mining-pools/blob/master/pools-v2.json</a>
 | 
					 | 
				
			||||||
      <li><code>blockHash</code>: a block hash</a>
 | 
					 | 
				
			||||||
      <li><code>blockHeight</code>: a block height</a>
 | 
					 | 
				
			||||||
      <li><code>page</code>: the requested page number if using pagination</a>
 | 
					 | 
				
			||||||
      <li><code>pageLength</code>: the page lenght if using pagination</a>
 | 
					 | 
				
			||||||
      </ul></p>`
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    urlString: "/v1/services/accelerator/accelerations/history",
 | 
					 | 
				
			||||||
    showConditions: [""],
 | 
					 | 
				
			||||||
    showJsExamples: showJsExamplesDefaultFalse,
 | 
					 | 
				
			||||||
    codeExample: {
 | 
					 | 
				
			||||||
      default: {
 | 
					 | 
				
			||||||
        codeTemplate: {
 | 
					 | 
				
			||||||
          curl: `/api/v1/services/accelerator/accelerations/history?blockHash=00000000000000000000482f0746d62141694b9210a813b97eb8445780a32003`,
 | 
					 | 
				
			||||||
          commonJS: ``,
 | 
					 | 
				
			||||||
          esModule: ``
 | 
					 | 
				
			||||||
        },
 | 
					 | 
				
			||||||
        codeSampleMainnet: {
 | 
					 | 
				
			||||||
          esModule: [],
 | 
					 | 
				
			||||||
          commonJS: [],
 | 
					 | 
				
			||||||
          curl: [],
 | 
					 | 
				
			||||||
          headers: '',
 | 
					 | 
				
			||||||
          response: `[
 | 
					 | 
				
			||||||
  {
 | 
					 | 
				
			||||||
    "txid": "d7e1796d8eb4a09d4e6c174e36cfd852f1e6e6c9f7df4496339933cd32cbdd1d",
 | 
					 | 
				
			||||||
    "status": "completed",
 | 
					 | 
				
			||||||
    "feePaid": 53239,
 | 
					 | 
				
			||||||
    "added": 1707421053,
 | 
					 | 
				
			||||||
    "lastUpdated": 1707422952,
 | 
					 | 
				
			||||||
    "baseFee": 50000,
 | 
					 | 
				
			||||||
    "vsizeFee": 0,
 | 
					 | 
				
			||||||
    "effectiveFee": 146,
 | 
					 | 
				
			||||||
    "effectiveVsize": 141,
 | 
					 | 
				
			||||||
    "feeDelta": 14000,
 | 
					 | 
				
			||||||
    "blockHash": "00000000000000000000482f0746d62141694b9210a813b97eb8445780a32003",
 | 
					 | 
				
			||||||
    "blockHeight": 829559,
 | 
					 | 
				
			||||||
    "pools": [
 | 
					 | 
				
			||||||
      {
 | 
					 | 
				
			||||||
        "pool_unique_id": 111,
 | 
					 | 
				
			||||||
        "username": "foundryusa"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
]`,
 | 
					]`,
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
<div id="enterprise-cta-desktop">
 | 
					<div id="enterprise-cta-desktop" *ngIf="officialMempoolInstance">
 | 
				
			||||||
  <p>Get higher API limits with Mempool Enterprise®</p>
 | 
					  <p>Get higher API limits with Mempool Enterprise®</p>
 | 
				
			||||||
  <a class="btn btn-small btn-purple" href="/enterprise">More Info <fa-icon [icon]="['fas', 'angle-right']" [styles]="{'font-size': '12px'}"></fa-icon></a>
 | 
					  <a class="btn btn-small btn-purple" href="/enterprise">More Info <fa-icon [icon]="['fas', 'angle-right']" [styles]="{'font-size': '12px'}"></fa-icon></a>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      <div class="doc-content">
 | 
					      <div class="doc-content">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div id="enterprise-cta-mobile" *ngIf="showMobileEnterpriseUpsell">
 | 
					        <div id="enterprise-cta-mobile" *ngIf="officialMempoolInstance && showMobileEnterpriseUpsell">
 | 
				
			||||||
          <p>Get higher API limits with <span class="no-line-break">Mempool Enterprise®</span></p>
 | 
					          <p>Get higher API limits with <span class="no-line-break">Mempool Enterprise®</span></p>
 | 
				
			||||||
          <div class="button-group">
 | 
					          <div class="button-group">
 | 
				
			||||||
            <a class="btn btn-small btn-secondary" (click)="showMobileEnterpriseUpsell = false">No Thanks</a>
 | 
					            <a class="btn btn-small btn-secondary" (click)="showMobileEnterpriseUpsell = false">No Thanks</a>
 | 
				
			||||||
 | 
				
			|||||||
@ -404,3 +404,17 @@ export interface AccelerationHistoryParams {
 | 
				
			|||||||
  page?: number;
 | 
					  page?: number;
 | 
				
			||||||
  pageLength?: number;
 | 
					  pageLength?: number;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface AccelerationInfo {
 | 
				
			||||||
 | 
					  txid: string,
 | 
				
			||||||
 | 
					  height: number,
 | 
				
			||||||
 | 
					  pool: {
 | 
				
			||||||
 | 
					    id: number,
 | 
				
			||||||
 | 
					    slug: string,
 | 
				
			||||||
 | 
					    name: string,
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  effective_vsize: number,
 | 
				
			||||||
 | 
					  effective_fee: number,
 | 
				
			||||||
 | 
					  boost_rate: number,
 | 
				
			||||||
 | 
					  boost_cost: number,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { Injectable } from '@angular/core';
 | 
					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, Acceleration, AccelerationHistoryParams, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume } from '../interfaces/node-api.interface';
 | 
					  PoolStat, BlockExtended, TransactionStripped, RewardStats, AuditScore, BlockSizesAndWeights, RbfTree, BlockAudit, Acceleration, AccelerationHistoryParams, CurrentPegs, AuditStatus, FederationAddress, FederationUtxo, RecentPeg, PegsVolume, AccelerationInfo } from '../interfaces/node-api.interface';
 | 
				
			||||||
import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs';
 | 
					import { BehaviorSubject, Observable, catchError, filter, of, shareReplay, take, tap } from 'rxjs';
 | 
				
			||||||
import { StateService } from './state.service';
 | 
					import { StateService } from './state.service';
 | 
				
			||||||
import { Transaction } from '../interfaces/electrs.interface';
 | 
					import { Transaction } from '../interfaces/electrs.interface';
 | 
				
			||||||
@ -459,4 +459,22 @@ export class ApiService {
 | 
				
			|||||||
        (queryParams.length > 0 ? `?${queryParams.join('&')}` : '')
 | 
					        (queryParams.length > 0 ? `?${queryParams.join('&')}` : '')
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getAccelerationsByPool$(slug: string): Observable<AccelerationInfo[]> {
 | 
				
			||||||
 | 
					    return this.httpClient.get<AccelerationInfo[]>(
 | 
				
			||||||
 | 
					      this.apiBaseUrl + this.apiBasePath + `/api/v1/accelerations/pool/${slug}`
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getAccelerationsByHeight$(height: number): Observable<AccelerationInfo[]> {
 | 
				
			||||||
 | 
					    return this.httpClient.get<AccelerationInfo[]>(
 | 
				
			||||||
 | 
					      this.apiBaseUrl + this.apiBasePath + `/api/v1/accelerations/block/${height}`
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  getRecentAccelerations$(interval: string | undefined): Observable<AccelerationInfo[]> {
 | 
				
			||||||
 | 
					    return this.httpClient.get<AccelerationInfo[]>(
 | 
				
			||||||
 | 
					      this.apiBaseUrl + this.apiBasePath + '/api/v1/accelerations/interval' + (interval !== undefined ? `/${interval}` : '')
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ import { ApiService } from './api.service';
 | 
				
			|||||||
import { SeoService } from './seo.service';
 | 
					import { SeoService } from './seo.service';
 | 
				
			||||||
import { StateService } from './state.service';
 | 
					import { StateService } from './state.service';
 | 
				
			||||||
import { ActivatedRoute } from '@angular/router';
 | 
					import { ActivatedRoute } from '@angular/router';
 | 
				
			||||||
 | 
					import { BehaviorSubject } from 'rxjs';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Injectable({
 | 
					@Injectable({
 | 
				
			||||||
  providedIn: 'root'
 | 
					  providedIn: 'root'
 | 
				
			||||||
@ -11,9 +12,9 @@ import { ActivatedRoute } from '@angular/router';
 | 
				
			|||||||
export class EnterpriseService {
 | 
					export class EnterpriseService {
 | 
				
			||||||
  exclusiveHostName = '.mempool.space';
 | 
					  exclusiveHostName = '.mempool.space';
 | 
				
			||||||
  subdomain: string | null = null;
 | 
					  subdomain: string | null = null;
 | 
				
			||||||
  info: object = {};
 | 
					 | 
				
			||||||
  statsUrl: string;
 | 
					  statsUrl: string;
 | 
				
			||||||
  siteId: number;
 | 
					  siteId: number;
 | 
				
			||||||
 | 
					  info$: BehaviorSubject<object> = new BehaviorSubject(null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  constructor(
 | 
					  constructor(
 | 
				
			||||||
    @Inject(DOCUMENT) private document: Document,
 | 
					    @Inject(DOCUMENT) private document: Document,
 | 
				
			||||||
@ -47,9 +48,9 @@ export class EnterpriseService {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  fetchSubdomainInfo(): void {
 | 
					  fetchSubdomainInfo(): void {
 | 
				
			||||||
    this.apiService.getEnterpriseInfo$(this.subdomain).subscribe((info) => {
 | 
					    this.apiService.getEnterpriseInfo$(this.subdomain).subscribe((info) => {
 | 
				
			||||||
      this.info = info;
 | 
					 | 
				
			||||||
      this.insertMatomo(info.site_id);
 | 
					      this.insertMatomo(info.site_id);
 | 
				
			||||||
      this.seoService.setEnterpriseTitle(info.title);
 | 
					      this.seoService.setEnterpriseTitle(info.title);
 | 
				
			||||||
 | 
					      this.info$.next(info);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    (error) => {
 | 
					    (error) => {
 | 
				
			||||||
      if (error.status === 404) {
 | 
					      if (error.status === 404) {
 | 
				
			||||||
 | 
				
			|||||||
@ -145,8 +145,8 @@ export class ServicesApiServices {
 | 
				
			|||||||
    return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations`);
 | 
					    return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations`);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getAggregatedAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
 | 
					  getAggregatedAccelerationHistory$(params: AccelerationHistoryParams): Observable<any> {
 | 
				
			||||||
    return this.httpClient.get<Acceleration[]>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history/aggregated`, { params: { ...params } });
 | 
					    return this.httpClient.get<any>(`${SERVICES_API_PREFIX}/accelerator/accelerations/history/aggregated`, { params: { ...params }, observe: 'response' });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  getAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
 | 
					  getAccelerationHistory$(params: AccelerationHistoryParams): Observable<Acceleration[]> {
 | 
				
			||||||
 | 
				
			|||||||
@ -116,7 +116,7 @@ export class WebsocketService {
 | 
				
			|||||||
            this.startMultiTrackTransaction(this.trackingTxId);
 | 
					            this.startMultiTrackTransaction(this.trackingTxId);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          if (this.isTrackingMempoolBlock) {
 | 
					          if (this.isTrackingMempoolBlock) {
 | 
				
			||||||
            this.startTrackMempoolBlock(this.trackingMempoolBlock);
 | 
					            this.startTrackMempoolBlock(this.trackingMempoolBlock, true);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
          if (this.isTrackingRbf) {
 | 
					          if (this.isTrackingRbf) {
 | 
				
			||||||
            this.startTrackRbf(this.isTrackingRbf);
 | 
					            this.startTrackRbf(this.isTrackingRbf);
 | 
				
			||||||
@ -197,9 +197,9 @@ export class WebsocketService {
 | 
				
			|||||||
    this.websocketSubject.next({ 'track-asset': 'stop' });
 | 
					    this.websocketSubject.next({ 'track-asset': 'stop' });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  startTrackMempoolBlock(block: number) {
 | 
					  startTrackMempoolBlock(block: number, force: boolean = false) {
 | 
				
			||||||
    // skip duplicate tracking requests
 | 
					    // skip duplicate tracking requests
 | 
				
			||||||
    if (this.trackingMempoolBlock !== block) {
 | 
					    if (force || this.trackingMempoolBlock !== block) {
 | 
				
			||||||
      this.websocketSubject.next({ 'track-mempool-block': block });
 | 
					      this.websocketSubject.next({ 'track-mempool-block': block });
 | 
				
			||||||
      this.isTrackingMempoolBlock = true;
 | 
					      this.isTrackingMempoolBlock = true;
 | 
				
			||||||
      this.trackingMempoolBlock = block;
 | 
					      this.trackingMempoolBlock = block;
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user