Merge pull request #6022 from mempool/natsoni/bootstrap-5

Bump bootstrap to 5.3.8 and fix breaking changes
This commit is contained in:
mononaut 2026-03-31 11:16:01 +09:00 committed by GitHub
commit bcba5fb0c9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
129 changed files with 1458 additions and 1247 deletions

View file

@ -29,7 +29,7 @@
"@ng-bootstrap/ng-bootstrap": "^19.0.0",
"@noble/secp256k1": "^3.0.0",
"@types/qrcode": "~1.5.0",
"bootstrap": "~4.6.2",
"bootstrap": "~5.3.8",
"clipboard": "^2.0.11",
"cypress": "15.13.0",
"domino": "^2.1.6",
@ -8567,9 +8567,9 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"node_modules/bootstrap": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"funding": [
{
"type": "github",
@ -8580,9 +8580,9 @@
"url": "https://opencollective.com/bootstrap"
}
],
"license": "MIT",
"peerDependencies": {
"jquery": "1.9.1 - 3",
"popper.js": "^1.16.1"
"@popperjs/core": "^2.11.8"
}
},
"node_modules/brace-expansion": {
@ -12667,12 +12667,6 @@
"url": "https://github.com/sponsors/panva"
}
},
"node_modules/jquery": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==",
"peer": true
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -14720,17 +14714,6 @@
"node": ">=10.13.0"
}
},
"node_modules/popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
"deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/portscanner": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz",
@ -23115,9 +23098,9 @@
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
},
"bootstrap": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.6.2.tgz",
"integrity": "sha512-51Bbp/Uxr9aTuy6ca/8FbFloBUJZLHwnhTcnjIeRn2suQWsWzcuJhGjKDB5eppVte/8oCdOL3VuwxvZDUggwGQ==",
"version": "5.3.8",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.8.tgz",
"integrity": "sha512-HP1SZDqaLDPwsNiqRqi5NcP0SSXciX2s9E+RyqJIIqGo+vJeN5AJVM98CXmW/Wux0nQ5L7jeWUdplCEf0Ee+tg==",
"requires": {}
},
"brace-expansion": {
@ -25919,12 +25902,6 @@
"resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
"integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ=="
},
"jquery": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.0.tgz",
"integrity": "sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw==",
"peer": true
},
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@ -27377,12 +27354,6 @@
"resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz",
"integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="
},
"popper.js": {
"version": "1.16.1",
"resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz",
"integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==",
"peer": true
},
"portscanner": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz",

View file

@ -79,7 +79,7 @@
"@ng-bootstrap/ng-bootstrap": "^19.0.0",
"@types/qrcode": "~1.5.0",
"@noble/secp256k1": "^3.0.0",
"bootstrap": "~4.6.2",
"bootstrap": "~5.3.8",
"clipboard": "^2.0.11",
"domino": "^2.1.6",
"echarts": "~5.4.0",

View file

@ -90,7 +90,7 @@
</div>
<div class="row">
<div class="col">
<div class="form-group">
<div class="mb-3">
<div class="fee-card">
<div class="d-flex mb-0">
<ng-container *ngFor="let option of maxRateOptions">
@ -129,7 +129,7 @@
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1"><app-fiat [value]="math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee)"></app-fiat></span>
<span class="fiat ms-1"><app-fiat [value]="math.max(0, estimate.nextBlockFee - estimate.txSummary.effectiveFee)"></app-fiat></span>
</td>
</tr>
}
@ -151,7 +151,7 @@
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1"><app-fiat [value]="maxRateOptions[selectFeeRateIndex].fee"></app-fiat></span>
<span class="fiat ms-1"><app-fiat [value]="maxRateOptions[selectFeeRateIndex].fee"></app-fiat></span>
</td>
</tr>
}
@ -169,7 +169,7 @@
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1"><app-fiat [value]="estimate.mempoolBaseFee"></app-fiat></span>
<span class="fiat ms-1"><app-fiat [value]="estimate.mempoolBaseFee"></app-fiat></span>
</td>
</tr>
<tr class="info group-last dashed-bottom" *ngIf="estimate.vsizeFee">
@ -181,7 +181,7 @@
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1"><app-fiat [value]="estimate.vsizeFee"></app-fiat></span>
<span class="fiat ms-1"><app-fiat [value]="estimate.vsizeFee"></app-fiat></span>
</td>
</tr>
</ng-container>
@ -190,16 +190,16 @@
<ng-container *ngIf="hasAccessToBalanceMode">
<tr class="group-first">
<td class="item">
<b style="background-color: #5E35B1" class="p-1 pl-0" i18n="accelerator.estimated-cost">Estimated acceleration cost</b> ~{{ estimate.targetFeeRate | number : '1.0-0' }} sat/vB
<b style="background-color: #5E35B1" class="p-1" i18n="accelerator.estimated-cost">Estimated acceleration cost</b> ~{{ estimate.targetFeeRate | number : '1.0-0' }} sat/vB
</td>
<td class="amt">
<span style="background-color: #5E35B1" class="p-1 pl-0">
<span style="background-color: #5E35B1" class="p-1">
{{ estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee | number }}
</span>
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1"><app-fiat [value]="estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee"></app-fiat></span>
<span class="fiat ms-1"><app-fiat [value]="estimate.cost + estimate.mempoolBaseFee + estimate.vsizeFee"></app-fiat></span>
</td>
</tr>
</ng-container>
@ -209,19 +209,19 @@
<tr class="group-first group-last">
<td class="item">
@if (hasAccessToBalanceMode) {
<b style="background-color: var(--primary);" class="p-1 pl-0" i18n="accelerator.maximum-cost">Maximum acceleration cost</b>
<b style="background-color: var(--primary);" class="p-1" i18n="accelerator.maximum-cost">Maximum acceleration cost</b>
} @else {
<b style="background-color: var(--primary);" class="p-1 pl-0" i18n="accelerator.cost">Acceleration cost</b>
<b style="background-color: var(--primary);" class="p-1" i18n="accelerator.cost">Acceleration cost</b>
}
</td>
<td class="amt">
<span style="background-color: var(--primary)" class="p-1 pl-0">
<span style="background-color: var(--primary)" class="p-1">
{{ cost | number }}
</span>
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1">
<span class="fiat ms-1">
<app-fiat [value]="cost" [colorClass]="hasAccessToBalanceMode && estimate.userBalance < cost ? 'red-color' : 'green-color'"></app-fiat>
</span>
</td>
@ -237,7 +237,7 @@
</td>
<td class="units">
<span class="symbol" i18n="shared.sats">sats</span>
<span class="fiat ml-1">
<span class="fiat ms-1">
<app-fiat [value]="estimate.userBalance" [colorClass]="estimate.userBalance < cost ? 'red-color' : 'green-color'"></app-fiat>
</span>
</td>
@ -291,10 +291,10 @@
<form>
<div class="row">
<div class="col-md">
<div class="form-group form-check mb-2">
<div class="form-check mb-2">
<input type="radio" [checked]="selectedOption === 'wait'" class="form-check-input" id="wait" name="accel" (change)="selectedOptionChanged($event)">
<label class="form-check-label d-flex flex-column" for="wait">
<span class="font-weight-bold" i18n="accelerator.wait">Wait</span>
<span class="fw-bold" i18n="accelerator.wait">Wait</span>
@if (eta.blocks < 7) {
<span class="checkout-text"><ng-container i18n="accelerator.confirmation-expected">Confirmation expected</ng-container>&nbsp;<app-time kind="within" [time]="eta.time" [fastRender]="false" [fixedRender]="true"></app-time></span>
} @else {
@ -304,7 +304,7 @@
}
</label>
</div>
<div class="form-group form-check mb-2">
<div class="form-check mb-2">
<input type="radio" [checked]="selectedOption === 'accel'" class="form-check-input" id="accel" name="accel" (change)="selectedOptionChanged($event)">
<label class="form-check-label d-flex flex-column" for="accel">
<ng-container *ngTemplateOutlet="accelerateOption; context: {etaInfo}"></ng-container>
@ -328,7 +328,7 @@
</div>
<div class="pie d-none d-lg-flex">
<small class="form-text checkout-text mb-2"><ng-container *ngTemplateOutlet="prioritizedBy; context: {$implicit:etaInfo.hashratePercentage}"></ng-container></small>
<app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true" class="ml-2"></app-active-acceleration-box>
<app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true" class="ms-2"></app-active-acceleration-box>
</div>
<ng-container *ngTemplateOutlet="accelerateButton"></ng-container>
</div>
@ -364,7 +364,7 @@
</div>
<div class="col-md pie d-none d-md-flex" *ngIf="!forceMobile">
<small class="form-text checkout-text mb-2" *ngIf="(etaInfo$ | async) as etaInfo"><ng-container *ngTemplateOutlet="prioritizedBy; context: {$implicit:etaInfo.hashratePercentage}"></ng-container></small>
<app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true" class="ml-2"></app-active-acceleration-box>
<app-active-acceleration-box [miningStats]="miningStats" [pools]="estimate.pools" [chartOnly]="true" class="ms-2"></app-active-acceleration-box>
</div>
</div>
<div class="payment-area" style="font-size: 14px;">
@ -430,9 +430,9 @@
@if (canPayWithCashapp || canPayWithApplePay || canPayWithGooglePay) { <span class="mt-1 mb-1"></span> }
<div class="paymentMethod mx-2 d-flex justify-content-center align-items-center" style="width: 200px; height: 55px" (click)="moveToStep('cardonfile')">
@if (['VISA', 'MASTERCARD', 'JCB', 'DISCOVER', 'DISCOVER_DINERS', 'AMERICAN_EXPRESS'].includes(estimate?.availablePaymentMethods?.cardOnFile?.card?.brand)) {
<app-svg-images [name]="estimate?.availablePaymentMethods?.cardOnFile?.card?.brand" height="33" class="mr-2"></app-svg-images>
<app-svg-images [name]="estimate?.availablePaymentMethods?.cardOnFile?.card?.brand" height="33" class="me-2"></app-svg-images>
} @else {
<app-svg-images name="OTHER_BRAND" height="33" class="mr-2"></app-svg-images>
<app-svg-images name="OTHER_BRAND" height="33" class="me-2"></app-svg-images>
}
<span style="font-size: 22px; padding-bottom: 3px">{{ estimate?.availablePaymentMethods?.cardOnFile?.card?.last_4 }}</span>
</div>
@ -469,7 +469,7 @@
<div class="row text-center">
<div class="col-sm">
<div class="form-group w-100" style="font-size: 14px">
<div class="w-100 mb-3" style="font-size: 14px">
<ng-container i18n="accelerator.payment-to-mempool-space">Payment to mempool.space for acceleration of txid <a [routerLink]="'/tx/' + tx.txid" target="_blank">{{ tx.txid.substr(0, 10) }}..{{ tx.txid.substr(-10) }}</a></ng-container>
</div>
</div>
@ -478,7 +478,7 @@
@if (step === 'cashapp' && !loadingCashapp || step === 'applepay' && !loadingApplePay || step === 'googlepay' && !loadingGooglePay || step === 'cardonfile' && !loadingCardOnFile) {
<div class="row text-center mt-1">
<div class="col-sm">
<div class="form-group w-100">
<div class="w-100 mb-3">
<span><u><strong i18n="accelerator.total-additional-cost">Total additional cost</strong></u><br>
<span style="font-size: 16px" class="d-block mt-2">
<ng-container i18n="transaction.pay|Pay button label">Pay</ng-container>
@ -493,7 +493,7 @@
<div class="row text-center mt-1">
<div class="col-sm">
<div class="form-group w-100">
<div class="w-100 mb-3">
@if (step === 'applepay') {
<div id="apple-pay-button" class="apple-pay-button apple-pay-button-black" style="height: 50px" [style]="loadingApplePay ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
} @else if (step === 'cashapp') {
@ -501,11 +501,11 @@
} @else if (step === 'googlepay') {
<div id="google-pay-button" class="d-inline-block" style="height: 50px" [style]="loadingGooglePay ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''"></div>
} @else if (step === 'cardonfile') {
<div class="ml-auto mr-auto paymentMethod mx-2 d-flex justify-content-center align-items-center" style="width: 200px; height: 55px" (click)="requestCardOnFilePayment()" [style]="loadingCardOnFile ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''">
<div class="ms-auto me-auto paymentMethod mx-2 d-flex justify-content-center align-items-center" style="width: 200px; height: 55px" (click)="requestCardOnFilePayment()" [style]="loadingCardOnFile ? 'opacity: 0; width: 0px; height: 0px; pointer-events: none;' : ''">
@if (['VISA', 'MASTERCARD', 'JCB', 'DISCOVER', 'DISCOVER_DINERS', 'AMERICAN_EXPRESS'].includes(estimate?.availablePaymentMethods?.cardOnFile?.card?.brand)) {
<app-svg-images [name]="estimate?.availablePaymentMethods?.cardOnFile?.card?.brand" height="33" class="mr-2"></app-svg-images>
<app-svg-images [name]="estimate?.availablePaymentMethods?.cardOnFile?.card?.brand" height="33" class="me-2"></app-svg-images>
} @else {
<app-svg-images name="OTHER_BRAND" height="33" class="mr-2"></app-svg-images>
<app-svg-images name="OTHER_BRAND" height="33" class="me-2"></app-svg-images>
}
<span style="font-size: 22px; padding-bottom: 3px">{{ estimate?.availablePaymentMethods?.cardOnFile?.card?.last_4 }}</span>
</div>
@ -513,13 +513,13 @@
@if (loadingCashapp || loadingApplePay || loadingGooglePay || loadingCardOnFile) {
<div display="d-flex flex-row justify-content-center">
<span i18n="accelerator.loading-payment-method">Loading payment method...</span>
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
<div class="ms-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
}
</div>
@if (isTokenizing > 0) {
<div class="d-flex flex-row justify-content-center">
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
<div class="ms-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
}
</div>
@ -541,12 +541,12 @@
<div class="row text-center mt-1">
<div class="col-sm">
<div class="form-group w-100">
<div class="w-100 mb-3">
<!-- Processing payment -->
<div id="cash-app-pay" class="d-inline-block" [style]="'opacity: 0; width: 0px; height: 0px; pointer-events: none;'"></div>
<div display="d-flex flex-row justify-content-center">
<span i18n="accelerator.payment-processing">We are processing your payment...</span>
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
<div class="ms-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
</div>
</div>
@ -611,7 +611,7 @@
</ng-template>
<ng-template #customizeButton>
<button type="button" *ngIf="advancedEnabled" class="btn btn-sm btn-outline-info btn-small-height ml-2" (click)="moveToStep('quote')" i18n="accelerator.customize">customize</button>
<button type="button" *ngIf="advancedEnabled" class="btn btn-sm btn-outline-info btn-small-height ms-2" (click)="moveToStep('quote')" i18n="accelerator.customize">customize</button>
</ng-template>
<ng-template id="accelerate-to" #accelerateTo let-x i18n="accelerator.accelerate-to-x">Accelerate to ~{{ x | number : '1.0-0' }} sat/vB</ng-template>
@ -619,7 +619,7 @@
<ng-template #accelerateButton>
<div class="position-relative">
<button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center" [class.disabled]="!canPay || quoteError || cantPayReason || calculating || (!advancedEnabled && selectedOption !== 'accel')" style="width: 200px" (click)="moveToStep('checkout')">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="me-2" style="margin-left: -10px">
<span i18n="transaction.accelerate|Accelerate button label">Accelerate</span>
</button>
@if (quoteError || cantPayReason) {
@ -631,12 +631,12 @@
<ng-template #accountPayButton>
@if (hasAccessToBalanceMode) {
<button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center" [class.disabled]="!canPay || calculating" style="width: 200px" (click)="accelerateWithMempoolAccount()">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="me-2" style="margin-left: -10px">
<span i18n="transaction.pay|Pay button label">Pay</span>
</button>
} @else {
<button type="button" class="mt-1 btn btn-purple rounded-pill align-self-center d-flex flex-row justify-content-center align-items-center disabled" style="width: 200px">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="mr-2" style="margin-left: -10px">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="20" class="me-2" style="margin-left: -10px">
<span>Coming soon</span>
</button>
}
@ -645,7 +645,7 @@
<ng-template #prioritizedBy let-i i18n="accelerator.hashrate-percentage-description">Your transaction will be prioritized by up to <strong>{{ i | number : '1.1-1' }}%</strong> of miners.</ng-template>
<ng-template #partnerCodeDisplay let-partnerCode="partnerCode">
<div class="small font-italic">
<span i18n="accelerator.using-partner-code">Using partner code</span>&nbsp;<span class="badge badge-secondary">{{ partnerCode }}</span>
<div class="small fst-italic">
<span i18n="accelerator.using-partner-code">Using partner code</span>&nbsp;<span class="badge bg-secondary">{{ partnerCode }}</span>
</div>
</ng-template>

View file

@ -195,6 +195,12 @@
@media (max-width: 640px) {
flex-direction: column;
}
&.row>* {
width: unset;
padding-left: unset;
padding-right: unset;
}
}
.btn-error {
@ -237,4 +243,8 @@
flex-direction: row;
gap: 5px;
}
}
.form-text {
display: block;
}

View file

@ -11,11 +11,11 @@
<td class="label" i18n="transaction.status|Transaction Status">Status</td>
<td class="value">
@if (accelerationInfo.status === 'seen') {
<span class="badge badge-primary" i18n="transaction.first-seen|Transaction first seen">First seen</span>
<span class="badge bg-primary" i18n="transaction.first-seen|Transaction first seen">First seen</span>
} @else if (accelerationInfo.status === 'accelerated') {
<span class="badge badge-accelerated" i18n="transaction.audit.accelerated">Accelerated</span>
} @else if (accelerationInfo.status === 'mined') {
<span class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span class="badge bg-success" i18n="transaction.rbf.mined">Mined</span>
}
</td>
</tr>

View file

@ -29,7 +29,7 @@
<div class="shape"></div>
</div>
@if (canceled) {
<div class="status"><span class="badge badge-danger" i18n="accelerator.canceled">Canceled</span></div>
<div class="status"><span class="badge bg-danger" i18n="accelerator.canceled">Canceled</span></div>
} @else {
<div class="status"><span class="badge badge-waiting" i18n="transaction.rbf.mined">Mined</span></div>
}
@ -63,7 +63,7 @@
<div class="shape-border hovering" (pointerover)="onHover($event, 'seen');" (pointerout)="onBlur($event);">
<div class="shape"></div>
</div>
<div class="status"><span class="badge badge-primary" i18n="transaction.first-seen|Transaction first seen">First seen</span></div>
<div class="status"><span class="badge bg-primary" i18n="transaction.first-seen|Transaction first seen">First seen</span></div>
<div class="time">
@if (useAbsoluteTime) {
<span>{{ transactionTime * 1000 | date }}</span>
@ -122,7 +122,7 @@
<div class="shape"></div>
</div>
@if (tx.status.confirmed) {
<div class="status"><span class="badge badge-success" i18n="transaction.rbf.mined">Mined</span></div>
<div class="status"><span class="badge bg-success" i18n="transaction.rbf.mined">Mined</span></div>
<div class="time">
@if (useAbsoluteTime) {
<span>{{ tx.status.block_time * 1000 | date }}</span>

View file

@ -4,37 +4,43 @@
<div *ngIf="!widget" class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="accelerator.acceleration-fees">Acceleration Fees</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="daysAvailable">
<div class="btn-group btn-group-toggle" name="radioBasic">
<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
</label>
<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
</label>
<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
</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 class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="daysAvailable >= 3">
<input type="radio" class="btn-check" id="accelerationfees-1w" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-1w">1W</label>
</ng-container>
<ng-container *ngIf="daysAvailable >= 7">
<input type="radio" class="btn-check" id="accelerationfees-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-1m">1M</label>
</ng-container>
<ng-container *ngIf="daysAvailable >= 30">
<input type="radio" class="btn-check" id="accelerationfees-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-3m">3M</label>
</ng-container>
<ng-container *ngIf="daysAvailable >= 90">
<input type="radio" class="btn-check" id="accelerationfees-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-6m">6M</label>
</ng-container>
<ng-container *ngIf="daysAvailable >= 180">
<input type="radio" class="btn-check" id="accelerationfees-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-1y">1Y</label>
</ng-container>
<ng-container *ngIf="daysAvailable >= 360">
<input type="radio" class="btn-check" id="accelerationfees-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-2y">2Y</label>
</ng-container>
<ng-container *ngIf="daysAvailable >= 720">
<input type="radio" class="btn-check" id="accelerationfees-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="accelerationfees-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/acceleration/fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="accelerationfees-all">ALL</label>
</div>
</form>
</div>

View file

@ -1,56 +1,56 @@
<div class="container-lg widget-container p-0" [class.widget]="widget" [class.full-height]="!widget">
<h1 *ngIf="!widget" class="float-left" i18n="accelerator.accelerations">Accelerations</h1>
<div *ngIf="!widget && isLoading" class="spinner-border ml-3" role="status"></div>
<h1 *ngIf="!widget" class="float-start" i18n="accelerator.accelerations">Accelerations</h1>
<div *ngIf="!widget && isLoading" class="spinner-border ms-3" role="status"></div>
<div class="clearfix"></div>
<div class="acceleration-list" *ngIf="{ accelerations: accelerationList$ | async } as state">
<table *ngIf="nonEmptyAccelerations; else noData" class="table table-borderless table-fixed">
<thead>
<th class="txid text-left" i18n="dashboard.latest-transactions.txid">TXID</th>
<th class="txid text-start" i18n="dashboard.latest-transactions.txid">TXID</th>
<ng-container *ngIf="pending">
<th class="fee-rate text-right" i18n="transaction.fee-rate|Transaction fee rate">Fee rate</th>
<th class="bid text-right" i18n="accelerator.bid">Bid</th>
<th class="time text-right" i18n="accelerator.requested">Requested</th>
<th class="fee-rate text-end" i18n="transaction.fee-rate|Transaction fee rate">Fee rate</th>
<th class="bid text-end" i18n="accelerator.bid">Bid</th>
<th class="time text-end" i18n="accelerator.requested">Requested</th>
</ng-container>
<ng-container *ngIf="!pending">
<th class="fee text-right text-truncate" i18n="transaction.bid-boost|Bid Boost">Bid Boost</th>
<th class="block text-right" i18n="shared.block-title">Block</th>
<th class="pool text-right" i18n="mining.pool-name" *ngIf="!this.widget">Pool</th>
<th class="status text-right" i18n="transaction.status|Transaction Status">Status</th>
<th class="date text-right" i18n="accelerator.requested" *ngIf="!this.widget">Requested</th>
<th class="fee text-end text-truncate" i18n="transaction.bid-boost|Bid Boost">Bid Boost</th>
<th class="block text-end" i18n="shared.block-title">Block</th>
<th class="pool text-end" i18n="mining.pool-name" *ngIf="!this.widget">Pool</th>
<th class="status text-end" i18n="transaction.status|Transaction Status">Status</th>
<th class="date text-end" i18n="accelerator.requested" *ngIf="!this.widget">Requested</th>
</ng-container>
</thead>
<tbody *ngIf="state.accelerations && nonEmptyAccelerations; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngFor="let acceleration of state.accelerations; let i= index;">
<td class="txid text-left">
<td class="txid text-start">
<a [routerLink]="['/tx' | relativeUrl, acceleration.txid]">
<app-truncate [text]="acceleration.txid" [lastChars]="5"></app-truncate>
</a>
</td>
<ng-container *ngIf="pending">
<td class="fee-rate text-right">
<td class="fee-rate text-end">
<app-fee-rate [fee]="acceleration.effectiveFee" [weight]="acceleration.effectiveVsize * 4"></app-fee-rate>
</td>
<td class="bid text-right">
<td class="bid text-end">
{{ (acceleration.feeDelta) | number }} <span class="symbol" i18n="shared.sats">sats</span>
</td>
<td class="time text-right">
<td class="time text-end">
<app-time kind="since" [time]="acceleration.added" [fastRender]="true" [showTooltip]="true"></app-time>
</td>
</ng-container>
<ng-container *ngIf="!pending">
<td *ngIf="acceleration.boost != null" class="fee text-right">
<td *ngIf="acceleration.boost != null" class="fee text-end">
{{ acceleration.boost | number }} <span class="symbol" i18n="shared.sats">sats</span>
</td>
<td *ngIf="acceleration.boost == null" class="fee text-right">
<td *ngIf="acceleration.boost == null" class="fee text-end">
~
</td>
<td class="block text-right">
<td class="block text-end">
<a *ngIf="acceleration.blockHeight" [routerLink]="['/block' | relativeUrl, acceleration.blockHeight]">{{ acceleration.blockHeight }}</a>
<span *ngIf="!acceleration.blockHeight">~</span>
</td>
<td class="pool text-right" *ngIf="!this.widget">
<td class="pool text-end" *ngIf="!this.widget">
@if (acceleration.minedByPoolUniqueId && pools[acceleration.minedByPoolUniqueId]) {
<a placement="bottom" [routerLink]="['/mining/pool' | relativeUrl, pools[acceleration.minedByPoolUniqueId].slug]" class="badge" style="color: #FFF;padding:0;">
<img class="pool-logo" [src]="'/resources/mining-pools/' + pools[acceleration.minedByPoolUniqueId].slug + '.svg'" onError="this.src = '/resources/mining-pools/default.svg'" [alt]="'Logo of ' + pools[acceleration.minedByPoolUniqueId].name + ' mining pool'">
@ -60,14 +60,14 @@
~
}
</td>
<td class="status text-right">
<span *ngIf="acceleration.status === 'accelerating'" class="badge badge-warning" i18n="accelerator.pending">Pending</span>
<span *ngIf="acceleration.status.includes('completed') && acceleration.minedByPoolUniqueId && pools[acceleration.minedByPoolUniqueId]" class="badge badge-success"><ng-container i18n="accelerator.completed">Completed</ng-container><span *ngIf="acceleration.status === 'completed_provisional'">&nbsp;</span></span>
<span *ngIf="acceleration.status.includes('completed') && (!acceleration.minedByPoolUniqueId || !pools[acceleration.minedByPoolUniqueId])" class="badge badge-success"><ng-container i18n="transaction.rbf.mined">Mined</ng-container><span *ngIf="acceleration.status === 'completed_provisional'">&nbsp;</span></span>
<span *ngIf="acceleration.status.includes('failed') && acceleration.canceled" class="badge badge-danger"><ng-container i18n="accelerator.canceled">Canceled</ng-container><span *ngIf="acceleration.status === 'failed_provisional'">&nbsp;</span></span>
<span *ngIf="acceleration.status.includes('failed') && !acceleration.canceled" class="badge badge-danger"><ng-container i18n="accelerator.canceled">Failed</ng-container><span *ngIf="acceleration.status === 'failed_provisional'">&nbsp;</span></span>
<td class="status text-end">
<span *ngIf="acceleration.status === 'accelerating'" class="badge bg-warning" i18n="accelerator.pending">Pending</span>
<span *ngIf="acceleration.status.includes('completed') && acceleration.minedByPoolUniqueId && pools[acceleration.minedByPoolUniqueId]" class="badge bg-success"><ng-container i18n="accelerator.completed">Completed</ng-container><span *ngIf="acceleration.status === 'completed_provisional'">&nbsp;</span></span>
<span *ngIf="acceleration.status.includes('completed') && (!acceleration.minedByPoolUniqueId || !pools[acceleration.minedByPoolUniqueId])" class="badge bg-success"><ng-container i18n="transaction.rbf.mined">Mined</ng-container><span *ngIf="acceleration.status === 'completed_provisional'">&nbsp;</span></span>
<span *ngIf="acceleration.status.includes('failed') && acceleration.canceled" class="badge bg-danger"><ng-container i18n="accelerator.canceled">Canceled</ng-container><span *ngIf="acceleration.status === 'failed_provisional'">&nbsp;</span></span>
<span *ngIf="acceleration.status.includes('failed') && !acceleration.canceled" class="badge bg-danger"><ng-container i18n="accelerator.canceled">Failed</ng-container><span *ngIf="acceleration.status === 'failed_provisional'">&nbsp;</span></span>
</td>
<td class="date text-right" *ngIf="!this.widget">
<td class="date text-end" *ngIf="!this.widget">
<app-time kind="since" [time]="acceleration.added" [fastRender]="true" [showTooltip]="true"></app-time>
</td>
</ng-container>
@ -77,22 +77,22 @@
@if (!pending) {
<tbody>
<tr *ngFor="let item of skeletonLines">
<td class="txid text-left">
<td class="txid text-start">
<span class="skeleton-loader" style="max-width: 200px"></span>
</td>
<td class="fee text-right">
<td class="fee text-end">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="block text-right">
<td class="block text-end">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="pool text-right" *ngIf="!this.widget">
<td class="pool text-end" *ngIf="!this.widget">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="status text-right">
<td class="status text-end">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="date text-right" *ngIf="!this.widget">
<td class="date text-end" *ngIf="!this.widget">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
</tr>
@ -100,16 +100,16 @@
} @else {
<tbody>
<tr *ngFor="let item of skeletonLines">
<td class="txid text-left">
<td class="txid text-start">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="fee-rate text-right">
<td class="fee-rate text-end">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="bid text-right">
<td class="bid text-end">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
<td class="time text-right">
<td class="time text-end">
<span class="skeleton-loader" style="max-width: 100px"></span>
</td>
</tr>
@ -118,7 +118,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget" class="pagination-container float-end mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="this.accelerationCount" [rotate]="true" [maxSize]="maxSize" [pageSize]="15" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -62,7 +62,7 @@
<!-- Next block visualization -->
<div class="col" style="margin-bottom: 1.47rem">
<div class="card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
<div class="card-body ps-lg-3 pe-lg-3 ps-2 pe-2">
<a class="title-link" href="" [routerLink]="['/mempool-block/0' | relativeUrl]">
<h5 class="card-title d-inline">Mempool Goggles&reg; : <ng-container i18n="accelerator.accelerations">Accelerations</ng-container></h5>
<span>&nbsp;</span>
@ -78,7 +78,7 @@
<!-- acceleration fees graph -->
<div class="col" style="margin-bottom: 1.47rem">
<div class="card graph-card">
<div class="card-body pl-2 pr-2">
<div class="card-body ps-2 pe-2">
<h5 class="card-title" i18n="acceleration.historical-trend">Historical Trend</h5>
<div class="mempool-graph">
<app-acceleration-fees-graph

View file

@ -20,7 +20,7 @@
<td class="pie-chart" rowspan="2" *ngIf="!chartPositionLeft">
<div class="d-flex justify-content-between align-items-start">
@if (hasCpfp) {
<button type="button" class="btn btn-outline-info btn-sm btn-small-height float-right mt-0" (click)="onToggleCpfp()">CPFP</button>
<button type="button" class="btn btn-outline-info btn-sm btn-small-height float-end mt-0" (click)="onToggleCpfp()">CPFP</button>
}
<ng-container *ngTemplateOutlet="pieChart"></ng-container>
</div>
@ -36,7 +36,7 @@
<tr>
<td colspan="3" class="pt-0">
<div class="d-flex justify-content-end align-items-start">
<button type="button" class="btn btn-outline-info btn-sm btn-small-height float-right mt-0" (click)="onToggleCpfp()">CPFP</button>
<button type="button" class="btn btn-outline-info btn-sm btn-small-height float-end mt-0" (click)="onToggleCpfp()">CPFP</button>
</div>
</td>
</tr>

View file

@ -19,6 +19,6 @@
</tr>
</table>
<div *ngIf="addressStrings.length > itemsPerPage" class="pagination">
<ngb-pagination class="pagination-container float-right" [collectionSize]="addressStrings.length" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="pageIndex" (pageChange)="pageChange(pageIndex)" [boundaryLinks]="false" [ellipses]="false"></ngb-pagination>
<ngb-pagination class="pagination-container float-end" [collectionSize]="addressStrings.length" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="pageIndex" (pageChange)="pageChange(pageIndex)" [boundaryLinks]="false" [ellipses]="false"></ngb-pagination>
</div>
</div>

View file

@ -4,7 +4,7 @@
<a [routerLink]="['/lightning/channel' | relativeUrl, channel.id]">
<span
*ngIf="label"
class="badge badge-pill badge-warning {{ class }}"
class="badge rounded-pill bg-warning {{ class }}"
>{{ label }}</span>
</a>
</div>
@ -15,6 +15,6 @@
<ng-template #default>
<span
*ngIf="label"
class="badge badge-pill badge-warning {{ class }}"
class="badge rounded-pill bg-warning {{ class }}"
>{{ label }}</span>
</ng-template>

View file

@ -76,20 +76,20 @@
<ng-container *ngIf="(addressTypeInfo?.tapscript && addressTypeInfo?.scripts?.size > 0) || taprootPsbtExpanded">
<br>
<div class="title-tx">
<h2 class="text-left" i18n="address.taproot-tree">Taproot Tree</h2>
<h2 class="text-start" i18n="address.taproot-tree">Taproot Tree</h2>
</div>
<div class="box">
<div class="row">
<div class="col-md">
<div *ngIf="taprootPsbtExpanded" class="mb-3">
<form *ngIf="psbtForm" [formGroup]="psbtForm" novalidate>
<label for="psbtInput" class="form-label mb-1 font-weight-bold">PSBT</label>
<label for="psbtInput" class="form-label mb-1 fw-bold">PSBT</label>
<textarea id="psbtInput" class="form-control font-monospace" rows="1" formControlName="psbt" placeholder="Hex or base64 encoded PSBT involving this address" autocomplete="off" spellcheck="false" (input)="submitPsbt()"></textarea>
<label for="tapleavesInput" class="form-label mt-2 mb-1 font-weight-bold">Tapleaves</label>
<label for="tapleavesInput" class="form-label mt-2 mb-1 fw-bold">Tapleaves</label>
<textarea id="tapleavesInput" class="form-control font-monospace" rows="1" formControlName="tapleaf" placeholder="Hex or base64 encoded, comma separated PSBT_IN_TAP_LEAF_SCRIPT (<control block>:<script><leaf version>)" autocomplete="off" spellcheck="false" (input)="submitPsbt()"></textarea>
<label for="taptreeInput" class="form-label mt-2 mb-1 font-weight-bold">Taptree</label>
<label for="taptreeInput" class="form-label mt-2 mb-1 fw-bold">Taptree</label>
<textarea id="taptreeInput" class="form-control font-monospace" rows="1" formControlName="taptree" placeholder="Hex or base64 encoded PSBT_OUT_TAP_TREE field" autocomplete="off" spellcheck="false" (input)="submitPsbt()"></textarea>
<label *ngIf="!addressTypeInfo?.tapscript" for="internalKeyInput" class="form-label mt-2 mb-1 font-weight-bold">Internal Key</label>
<label *ngIf="!addressTypeInfo?.tapscript" for="internalKeyInput" class="form-label mt-2 mb-1 fw-bold">Internal Key</label>
<textarea *ngIf="!addressTypeInfo?.tapscript" id="internalKeyInput" class="form-control font-monospace" rows="1" formControlName="ikey" placeholder="Hex or base64 encoded x-only public key" autocomplete="off" spellcheck="false" (input)="submitPsbt()"></textarea>
<div class="text-danger mt-2 small" *ngIf="psbtError">{{ psbtError }}</div>
</form>
@ -103,7 +103,7 @@
<ng-container *ngIf="(stateService.backend$ | async) === 'esplora' && address && transactions && transactions.length > 2">
<br>
<div class="title-tx">
<h2 class="text-left" i18n="address.balance-history">Balance History</h2>
<h2 class="text-start" i18n="address.balance-history">Balance History</h2>
</div>
<div class="box">
<div class="widget-toggler" *ngIf="showBalancePeriod()">
@ -124,7 +124,7 @@
<ng-container *ngIf="(stateService.backend$ | async) === 'esplora' && address && utxos && utxos.length > 2">
<br>
<div class="title-tx">
<h2 class="text-left" i18n="address.unspent-outputs">Unspent Outputs</h2>
<h2 class="text-start" i18n="address.unspent-outputs">Unspent Outputs</h2>
</div>
<div class="box">
<div class="row">
@ -137,7 +137,7 @@
<br>
<div class="title-tx">
<h2 class="text-left">
<h2 class="text-start">
<ng-template [ngIf]="!transactions?.length">&nbsp;</ng-template>
<ng-template i18n="X of X Address Transaction" [ngIf]="transactions?.length === 1">{{ (transactions?.length | number) || '?' }} of {{ mempoolStats.tx_count + chainStats.tx_count | number }} transaction</ng-template>
<ng-template i18n="X of X Address Transactions (Plural)" [ngIf]="transactions?.length > 1">{{ (transactions?.length | number) || '?' }} of {{ mempoolStats.tx_count + chainStats.tx_count | number }} transactions</ng-template>
@ -286,8 +286,8 @@
</ng-template>
<ng-template #pendingBalanceRow>
<td i18n="accelerator.pending-state" class="font-italic">Pending</td>
<td *ngIf="mempoolStats.funded_txo_sum !== undefined; else confidentialTd" class="font-italic wrap-cell"><app-amount [satoshis]="mempoolStats.balance" [noFiat]="true" [addPlus]="true"></app-amount> <span class="fiat"><app-fiat [value]="mempoolStats.balance"></app-fiat></span></td>
<td i18n="accelerator.pending-state" class="fst-italic">Pending</td>
<td *ngIf="mempoolStats.funded_txo_sum !== undefined; else confidentialTd" class="fst-italic wrap-cell"><app-amount [satoshis]="mempoolStats.balance" [noFiat]="true" [addPlus]="true"></app-amount> <span class="fiat"><app-fiat [value]="mempoolStats.balance"></app-fiat></span></td>
</ng-template>
<ng-template #utxoRow>
@ -296,8 +296,8 @@
</ng-template>
<ng-template #pendingUtxoRow>
<td i18n="address.pending-utxos" class="font-italic">Pending UTXOs</td>
<td class="font-italic wrap-cell">{{ mempoolStats.utxos > 0 ? '+' : ''}}{{ mempoolStats.utxos }}</td>
<td i18n="address.pending-utxos" class="fst-italic">Pending UTXOs</td>
<td class="fst-italic wrap-cell">{{ mempoolStats.utxos > 0 ? '+' : ''}}{{ mempoolStats.utxos }}</td>
</ng-template>
<ng-template #volumeRow>
@ -308,13 +308,13 @@
<ng-template #typeRow>
<td i18n="address.type">Type</td>
<td class="wrap-cell">
<span placement="bottom" class="badge badge-primary">
<span placement="bottom" class="badge bg-primary">
<app-address-type [address]="addressTypeInfo"></app-address-type>
</span>
<button *ngIf="showTaprootPsbtButton()" type="button" class="btn btn-sm taproot-psbt-btn" (click)="taprootPsbtExpanded = !taprootPsbtExpanded" i18n-ngbTooltip="address.taproot-psbt-add-unpublished-spend-paths" ngbTooltip="Add unpublished spending paths">
<fa-icon [icon]="['fas', 'code-fork']" [fixedWidth]="true"></fa-icon>
</button>
<app-address-labels *ngIf="!addressTypeInfo?.tapscript" [channel]="exampleChannel" [address]="addressTypeInfo" class="ml-1"></app-address-labels>
<app-address-labels *ngIf="!addressTypeInfo?.tapscript" [channel]="exampleChannel" [address]="addressTypeInfo" class="ms-1"></app-address-labels>
</td>
</ng-template>

View file

@ -1,5 +1,5 @@
<div [formGroup]="amountForm" class="text-small text-center">
<select formControlName="mode" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" style="width: 70px;" (change)="changeMode()">
<select formControlName="mode" class="form-select form-select-sm form-control-secondary form-control mx-auto" style="width: 75px;" (change)="changeMode()">
<option value="btc" i18n="shared.btc|BTC">BTC</option>
<option value="sats" i18n="shared.sats">sats</option>
<option value="fiat" i18n="shared.fiat|Fiat">Fiat</option>

View file

@ -17,9 +17,7 @@
<form [formGroup]="searchForm">
<div class="input-group mb-2">
<input #instance="ngbTypeahead" [ngbTypeahead]="typeaheadSearchFn" [resultFormatter]="formatterFn" (selectItem)="itemSelected()" (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="Search Assets Placeholder Text" placeholder="Search asset">
<div class="input-group-append">
<button [disabled]="!searchForm.get('searchText')?.value.length" class="btn btn-secondary" type="button" (click)="searchForm.get('searchText')?.setValue('');" autocomplete="off" i18n="Search Clear Button">Clear</button>
</div>
<button [disabled]="!searchForm.get('searchText')?.value.length" class="btn btn-secondary" type="button" (click)="searchForm.get('searchText')?.setValue('');" autocomplete="off" i18n="Search Clear Button">Clear</button>
</div>
</form>
</div>

View file

@ -18,7 +18,7 @@
<form [formGroup]="paymentForm">
<div *ngIf="availableMethods.length > 1" class="form-group">
<div *ngIf="availableMethods.length > 1" class="mb-3">
<div class="btn-group btn-group-toggle" data-toggle="buttons">
<!-- <label *ngIf="invoice.addresses.BTC" class="btn btn-primary" [ngClass]="{'active': paymentForm.get('method')?.value === 'chain'}">
<input type="radio" value="chain" formControlName="method"> <fa-icon [icon]="['fas', 'link']" [fixedWidth]="true" title="Onchain"></fa-icon>
@ -44,9 +44,7 @@
<div class="input-group input-group-sm info-group">
<input type="text" class="form-control input-dark" readonly [value]="invoice.addresses.BTC">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" ><app-clipboard [text]="invoice.addresses.BTC"></app-clipboard></button>
</div>
<button class="btn btn-outline-secondary" type="button" ><app-clipboard [text]="invoice.addresses.BTC"></app-clipboard></button>
</div>
@if (!minimal) {
<p>{{ invoice.btcDue | number: '1.0-8' }} <span class="symbol">BTC</span></p>
@ -64,9 +62,7 @@
<div class="input-group input-group-sm info-group">
<input type="text" class="form-control input-dark" readonly [value]="invoice.addresses.BTC_LightningLike">
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button"><app-clipboard [text]="invoice.addresses.BTC_LightningLike"></app-clipboard></button>
</div>
<button class="btn btn-outline-secondary" type="button"><app-clipboard [text]="invoice.addresses.BTC_LightningLike"></app-clipboard></button>
</div>
@if (!minimal) {
@ -85,9 +81,7 @@
<br>
<div class="input-group input-group-sm info-group">
<input type="text" class="form-control input-dark" readonly [value]="invoice.addresses.LBTC" />
<div class="input-group-append">
<button class="btn btn-outline-secondary" type="button" ><app-clipboard [text]="invoice.addresses.LBTC"></app-clipboard></button>
</div>
<button class="btn btn-outline-secondary" type="button" ><app-clipboard [text]="invoice.addresses.LBTC"></app-clipboard></button>
</div>
@if (!minimal) {
<p>{{ invoice.btcDue | number: '1.0-8' }} <span class="symbol">BTC</span></p>

View file

@ -4,43 +4,51 @@
<div *ngIf="!widget" class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.block-fee-rates">Block Fee Rates</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 144" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 24h
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 432" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 3D
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 1008" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fee-rates' | 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/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 144">
<input type="radio" class="btn-check" id="feerates-24h" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-24h">24h</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 432">
<input type="radio" class="btn-check" id="feerates-3d" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-3d">3D</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 1008">
<input type="radio" class="btn-check" id="feerates-1w" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-1w">1W</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 4320">
<input type="radio" class="btn-check" id="feerates-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="feerates-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="feerates-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="feerates-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="feerates-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="feerates-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="feerates-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-fee-rates' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="feerates-all">ALL</label>
</div>
</form>
</div>

View file

@ -4,34 +4,39 @@
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.block-fees">Block Fees</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-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/mining/block-fees' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 4320">
<input type="radio" class="btn-check" id="blockfees-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="blockfees-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="blockfees-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="blockfees-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="blockfees-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="blockfees-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="blockfees-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-fees' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockfees-all">ALL</label>
</div>
</form>
</div>

View file

@ -4,43 +4,51 @@
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.block-fees-subsidy-subsidy">Block Fees Vs Subsidy</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 144" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 24h
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 432" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 3D
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 1008" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fees-subsidy' | 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/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 144">
<input type="radio" class="btn-check" id="subsidyfees-24h" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-24h">24h</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 432">
<input type="radio" class="btn-check" id="subsidyfees-3d" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-3d">3D</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 1008">
<input type="radio" class="btn-check" id="subsidyfees-1w" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-1w">1W</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 4320">
<input type="radio" class="btn-check" id="subsidyfees-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="subsidyfees-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="subsidyfees-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="subsidyfees-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="subsidyfees-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="subsidyfees-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="subsidyfees-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-fees-subsidy' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="subsidyfees-all">ALL</label>
</div>
</form>
</div>

View file

@ -1,5 +1,5 @@
<div class="block-filters" [class.filters-active]="activeFilters.length > 0" [class.any-mode]="filterMode === 'or'" [class.none-mode]="filterMode === 'nor'" [class.menu-open]="menuOpen" [class.small]="cssWidth < 500" [class.vsmall]="cssWidth < 400" [class.tiny]="cssWidth < 200">
<a *ngIf="menuOpen" [routerLink]="['/docs/faq' | relativeUrl]" fragment="how-do-mempool-goggles-work" class="info-badges float-right" i18n-ngbTooltip="Mempool Goggles&reg; tooltip" ngbTooltip="select filter categories to highlight matching transactions">
<a *ngIf="menuOpen" [routerLink]="['/docs/faq' | relativeUrl]" fragment="how-do-mempool-goggles-work" class="info-badges float-end" i18n-ngbTooltip="Mempool Goggles&reg; tooltip" ngbTooltip="select filter categories to highlight matching transactions">
<fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" size="lg"></fa-icon>
</a>
<div class="filter-bar">
@ -16,27 +16,22 @@
<div class="filter-row">
<div class="filter-element">
<h5 i18n="mempool-goggles.match">Match</h5>
<div class="btn-group btn-group-toggle">
<label class="btn btn-xs blue mode-toggle" [class.active]="filterMode === 'and'">
<input type="radio" [value]="'all'" fragment="all" (click)="setFilterMode('and')"><ng-container i18n>All</ng-container>
</label>
<label class="btn btn-xs green mode-toggle" [class.active]="filterMode === 'or'">
<input type="radio" [value]="'any'" fragment="any" (click)="setFilterMode('or')"><ng-container i18n="mempool-goggles.any">Any</ng-container>
</label>
<label class="btn btn-xs red mode-toggle" [class.active]="filterMode === 'nor'">
<input type="radio" [value]="'nor'" fragment="nor" (click)="setFilterMode('nor')"><ng-container i18n="mempool-goggles.none">None</ng-container>
</label>
<div class="btn-group" role="group">
<input type="radio" class="btn-check" id="match-all" [value]="'all'" fragment="all" (click)="setFilterMode('and')">
<label class="btn btn-xs blue mode-toggle" [class.active]="filterMode === 'and'" for="match-all"><ng-container i18n>All</ng-container></label>
<input type="radio" class="btn-check" id="match-any" [value]="'any'" fragment="any" (click)="setFilterMode('or')">
<label class="btn btn-xs green mode-toggle" [class.active]="filterMode === 'or'" for="match-any"><ng-container i18n="mempool-goggles.any">Any</ng-container></label>
<input type="radio" class="btn-check" id="match-none" [value]="'nor'" fragment="nor" (click)="setFilterMode('nor')">
<label class="btn btn-xs red mode-toggle" [class.active]="filterMode === 'nor'" for="match-none"><ng-container i18n="mempool-goggles.none">None</ng-container></label>
</div>
</div>
<div class="filter-element">
<h5 i18n="mempool-goggles.tint">Tint</h5>
<div class="btn-group btn-group-toggle">
<label class="btn btn-xs yellow mode-toggle" [class.active]="gradientMode === 'fee'">
<input type="radio" [value]="'fee'" fragment="classic" (click)="setGradientMode('fee')"><ng-container i18n="mempool-goggles.classic">Classic</ng-container>
</label>
<label class="btn btn-xs blue mode-toggle" [class.active]="gradientMode === 'age'">
<input type="radio" [value]="'age'" fragment="age" (click)="setGradientMode('age')"><ng-container i18n="mempool-goggles.age">Age</ng-container>
</label>
<div class="btn-group" role="group">
<input type="radio" class="btn-check" id="tint-classic" [value]="'fee'" fragment="classic" (click)="setGradientMode('fee')">
<label class="btn btn-xs yellow mode-toggle" [class.active]="gradientMode === 'fee'" for="tint-classic"><ng-container i18n="mempool-goggles.classic">Classic</ng-container></label>
<input type="radio" class="btn-check" id="tint-age" [value]="'age'" fragment="age" (click)="setGradientMode('age')">
<label class="btn btn-xs blue mode-toggle" [class.active]="gradientMode === 'age'" for="tint-age"><ng-container i18n="mempool-goggles.age">Age</ng-container></label>
</div>
</div>
</div>

View file

@ -96,9 +96,9 @@
&.none-mode {
.filter-tag {
border: solid 1px var(--danger);
border: solid 1px var(--red);
&.selected {
background-color: var(--danger);
background-color: var(--red);
}
}
}
@ -136,9 +136,9 @@
}
}
&.red {
border: solid 1px var(--danger);
border: solid 1px var(--red);
&.active {
background: var(--danger);
background: var(--red);
}
}
&.yellow {

View file

@ -107,7 +107,7 @@ export class BlockFiltersComponent implements OnInit, OnChanges, OnDestroy {
@HostListener('document:click', ['$event'])
onClick(event): boolean {
// click away from menu
if (!event.target.closest('button') && !event.target.closest('label')) {
if (!event.target.closest('button, label, .btn-check')) {
this.menuOpen = false;
}
return true;

View file

@ -4,43 +4,51 @@
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.blocks-health">Block Health</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 144" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 24h
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 432" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 3D
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 1008" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> 3Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount > 157680" [class.active]="radioGroupForm.get('dateSpan').value === 'all'">
<input type="radio" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 144">
<input type="radio" class="btn-check" id="health-24h" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-24h">24h</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 432">
<input type="radio" class="btn-check" id="health-3d" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-3d">3D</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 1008">
<input type="radio" class="btn-check" id="health-1w" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-1w">1W</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 4320">
<input type="radio" class="btn-check" id="health-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="health-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="health-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="health-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="health-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="health-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="health-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-health' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="health-all">ALL</label>
</div>
</form>
</div>

View file

@ -4,8 +4,8 @@
<canvas *browserOnly class="block-overview-canvas" [class.clickable]="!!hoverTx" #blockCanvas></canvas>
@if (!disableSpinner) {
<div class="loader-wrapper" [class.hidden]="!isLoading && !unavailable">
<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="!unavailable" class="spinner-border ms-3 loading" role="status"></div>
<div *ngIf="!isLoading && unavailable" class="ms-3" i18n="block.not-available">not available</div>
</div>
}
<app-block-overview-tooltip

View file

@ -67,28 +67,28 @@
<td class="label" i18n="transaction.audit-status">Audit status</td>
<td class="value">
<ng-container [ngSwitch]="tx?.status">
<span *ngSwitchCase="'found'" class="badge badge-success" i18n="transaction.audit.match">Match</span>
<span *ngSwitchCase="'censored'" class="badge badge-danger" i18n="transaction.audit.removed|Transaction removed state">Removed</span>
<span *ngSwitchCase="'missing'" class="badge badge-warning" i18n="transaction.audit.marginal">Marginal fee rate</span>
<span *ngSwitchCase="'sigop'" class="badge badge-warning" i18n="transaction.audit.sigop">High sigop count</span>
<span *ngSwitchCase="'fresh'" class="badge badge-warning" i18n="transaction.audit.recently-broadcasted">Recently broadcasted</span>
<span *ngSwitchCase="'freshcpfp'" class="badge badge-warning" i18n="transaction.audit.recently-cpfped">Recently CPFP'd</span>
<span *ngSwitchCase="'added'" class="badge badge-warning" i18n="tx-features.tag.added|Added">Added</span>
<span *ngSwitchCase="'prioritized'" class="badge badge-warning" i18n="tx-features.tag.prioritized|Prioritized">Prioritized</span>
<span *ngSwitchCase="'found'" class="badge bg-success" i18n="transaction.audit.match">Match</span>
<span *ngSwitchCase="'censored'" class="badge bg-danger" i18n="transaction.audit.removed|Transaction removed state">Removed</span>
<span *ngSwitchCase="'missing'" class="badge bg-warning" i18n="transaction.audit.marginal">Marginal fee rate</span>
<span *ngSwitchCase="'sigop'" class="badge bg-warning" i18n="transaction.audit.sigop">High sigop count</span>
<span *ngSwitchCase="'fresh'" class="badge bg-warning" i18n="transaction.audit.recently-broadcasted">Recently broadcasted</span>
<span *ngSwitchCase="'freshcpfp'" class="badge bg-warning" i18n="transaction.audit.recently-cpfped">Recently CPFP'd</span>
<span *ngSwitchCase="'added'" class="badge bg-warning" i18n="tx-features.tag.added|Added">Added</span>
<span *ngSwitchCase="'prioritized'" class="badge bg-warning" i18n="tx-features.tag.prioritized|Prioritized">Prioritized</span>
<ng-container *ngSwitchCase="'added_prioritized'">
<span class="badge badge-warning" i18n="tx-features.tag.added|Added">Added</span>
<span class="badge badge-warning ml-1" i18n="tx-features.tag.prioritized|Prioritized">Prioritized</span>
<span class="badge bg-warning" i18n="tx-features.tag.added|Added">Added</span>
<span class="badge bg-warning ms-1" i18n="tx-features.tag.prioritized|Prioritized">Prioritized</span>
</ng-container>
<span *ngSwitchCase="'deprioritized'" class="badge badge-warning" i18n="tx-features.tag.prioritized|Deprioritized">Deprioritized</span>
<span *ngSwitchCase="'deprioritized'" class="badge bg-warning" i18n="tx-features.tag.prioritized|Deprioritized">Deprioritized</span>
<ng-container *ngSwitchCase="'added_deprioritized'">
<span class="badge badge-warning" i18n="tx-features.tag.added|Added">Added</span>
<span class="badge badge-warning ml-1" i18n="tx-features.tag.prioritized|Deprioritized">Deprioritized</span>
<span class="badge bg-warning" i18n="tx-features.tag.added|Added">Added</span>
<span class="badge bg-warning ms-1" i18n="tx-features.tag.prioritized|Deprioritized">Deprioritized</span>
</ng-container>
<span *ngSwitchCase="'selected'" class="badge badge-warning" i18n="transaction.audit.marginal">Marginal fee rate</span>
<span *ngSwitchCase="'rbf'" class="badge badge-warning" i18n="tx-features.tag.conflict|Conflict">Conflict</span>
<span *ngSwitchCase="'selected'" class="badge bg-warning" i18n="transaction.audit.marginal">Marginal fee rate</span>
<span *ngSwitchCase="'rbf'" class="badge bg-warning" i18n="tx-features.tag.conflict|Conflict">Conflict</span>
<span *ngSwitchCase="'accelerated'" class="badge badge-accelerated" i18n="transaction.audit.accelerated">Accelerated</span>
<span *ngSwitchCase="'matched'" class="badge badge-success" i18n="transaction.audit.match">Match</span>
<span *ngSwitchCase="'unmatched'" class="badge badge-warning" i18n="transaction.audit.no-match">No Match</span>
<span *ngSwitchCase="'matched'" class="badge bg-success" i18n="transaction.audit.match">Match</span>
<span *ngSwitchCase="'unmatched'" class="badge bg-warning" i18n="transaction.audit.no-match">No Match</span>
</ng-container>
</td>
</tr>

View file

@ -5,34 +5,39 @@
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.block-rewards">Block Rewards</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(statsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-rewards' | 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/mining/block-rewards' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 4320">
<input type="radio" class="btn-check" id="blockrewards-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="blockrewards-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="blockrewards-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="blockrewards-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="blockrewards-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="blockrewards-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="blockrewards-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-rewards' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="blockrewards-all">ALL</label>
</div>
</form>
</div>

View file

@ -3,43 +3,51 @@
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.block-sizes-weights">Block Sizes and Weights</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(blockSizesWeightsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 144" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 24h
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 432" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 3D
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 1008" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-sizes-weights' | 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/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 144">
<input type="radio" class="btn-check" id="sizesweights-24h" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-24h">24h</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 432">
<input type="radio" class="btn-check" id="sizesweights-3d" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-3d">3D</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 1008">
<input type="radio" class="btn-check" id="sizesweights-1w" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-1w">1W</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 4320">
<input type="radio" class="btn-check" id="sizesweights-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="sizesweights-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="sizesweights-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="sizesweights-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="sizesweights-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="sizesweights-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="sizesweights-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/block-sizes-weights' | relativeUrl]" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="sizesweights-all">ALL</label>
</div>
</form>
</div>

View file

@ -66,7 +66,7 @@
</td>
<td *ngIf="!stateService.env.MINING_DASHBOARD && stateService.env.BASE_MODULE === 'mempool'">
<span [attr.data-cy]="'block-details-miner-badge'" placement="bottom" class="badge"
[class]="!block?.extras.pool.name || block?.extras.pool.slug === 'unknown' ? 'badge-secondary' : 'badge-primary'">
[class]="!block?.extras.pool.name || block?.extras.pool.slug === 'unknown' ? 'bg-secondary' : 'bg-primary'">
<span class="miner-name" *ngIf="block.extras.pool.minerNames?.length > 1 && block.extras.pool.minerNames[1] != ''">
@if (block.extras.pool.minerNames[1].length > 16) {
{{ block.extras.pool.minerNames[1].slice(0, 15) }}…

View file

@ -1,10 +1,10 @@
<div #blockTxTitle id="block-tx-title" class="block-tx-title">
<h2 class="text-left">
<h2 class="text-start">
<ng-container *ngTemplateOutlet="txCount === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: txCount | number}"></ng-container>
<ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} transaction</ng-template>
<ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} transactions</ng-template>
</h2>
<ngb-pagination class="pagination-container float-right" [collectionSize]="txCount" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page, blockTxTitle)" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>
<ngb-pagination class="pagination-container float-end" [collectionSize]="txCount" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page, blockTxTitle)" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>
</div>
<div class="clearfix"></div>
@ -50,4 +50,4 @@
</div>
</ng-template>
<ngb-pagination class="pagination-container float-right" [collectionSize]="txCount" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page, blockTxTitle)" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>
<ngb-pagination class="pagination-container float-end" [collectionSize]="txCount" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page, blockTxTitle)" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>

View file

@ -67,14 +67,14 @@
<td>
<span
class="health-badge badge"
[class.badge-success]="blockAudit?.matchRate >= 99"
[class.badge-warning]="blockAudit?.matchRate >= 75 && blockAudit?.matchRate < 99"
[class.badge-danger]="blockAudit?.matchRate < 75"
[class.bg-success]="blockAudit?.matchRate >= 99"
[class.bg-warning]="blockAudit?.matchRate >= 75 && blockAudit?.matchRate < 99"
[class.bg-danger]="blockAudit?.matchRate < 75"
*ngIf="blockAudit?.matchRate != null && blockAudit?.id === block.id; else nullHealth"
>{{ blockAudit?.matchRate }}%</span>
<ng-template #nullHealth>
<ng-container *ngIf="!isLoadingOverview && blockAudit?.id === block.id; else loadingHealth">
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
<span class="health-badge badge bg-secondary" i18n="unknown">Unknown</span>
</ng-container>
</ng-template>
<ng-template #loadingHealth>
@ -201,7 +201,7 @@
</td>
<td *ngIf="!stateService.env.MINING_DASHBOARD && stateService.env.BASE_MODULE === 'mempool'">
<span placement="bottom" class="badge"
[class]="block.extras.pool.slug === 'unknown' ? 'badge-secondary' : 'badge-primary'">
[class]="block.extras.pool.slug === 'unknown' ? 'bg-secondary' : 'bg-primary'">
{{ block.extras.pool.name }}
</span>
</td>
@ -328,7 +328,7 @@
<tbody>
<tr>
<td class="td-width" i18n="transaction.version">Version</td>
<td>{{ block.version | decimal2hex }} <span *ngIf="displayTaprootStatus() && hasTaproot(block.version)" class="badge badge-success ml-1" i18n="tx-features.tag.taproot|Taproot">Taproot</span></td>
<td>{{ block.version | decimal2hex }} <span *ngIf="displayTaprootStatus() && hasTaproot(block.version)" class="badge bg-success ms-1" i18n="tx-features.tag.taproot|Taproot">Taproot</span></td>
</tr>
<tr *ngIf="network !== 'liquid' && network !== 'liquidtestnet'">
<td i18n="block.bits">Bits</td>
@ -367,7 +367,7 @@
@if (!block?.stale && block?.extras?.orphans?.length > 0) {
<br>
<div class="header-bg box stale-block-alert">
<span class="stale-msg mr-1">
<span class="stale-msg me-1">
@if (block.extras.orphans.length === 1) {
<span i18n="block.stale-block-singular">There is a stale block at this height</span>
} @else {
@ -382,7 +382,7 @@
</div>
}
<div class="text-right mt-3 toggle-btns">
<div class="text-end mt-3 toggle-btns">
<button
*ngIf="webGlEnabled && auditAvailable"
type="button"
@ -407,12 +407,12 @@
} @placeholder {
<div>
<div class="block-tx-title">
<h2 class="text-left">
<h2 class="text-start">
<ng-container *ngTemplateOutlet="block.tx_count === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: block.tx_count | number}"></ng-container>
<ng-template #transactionsSingular let-i i18n="shared.transaction-count.singular">{{ i }} transaction</ng-template>
<ng-template #transactionsPlural let-i i18n="shared.transaction-count.plural">{{ i }} transactions</ng-template>
</h2>
<ngb-pagination class="pagination-container float-right" [disabled]="true" [collectionSize]="block.tx_count" [rotate]="true" [pageSize]="stateService.env.ITEMS_PER_PAGE" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>
<ngb-pagination class="pagination-container float-end" [disabled]="true" [collectionSize]="block.tx_count" [rotate]="true" [pageSize]="stateService.env.ITEMS_PER_PAGE" [maxSize]="paginationMaxSize" [boundaryLinks]="true" [ellipses]="false"></ngb-pagination>
</div>
<div class="clearfix"></div>
<div class="tx-skeleton">
@ -450,7 +450,7 @@
<ng-template #emptyBlockInfo let-emptyBlock>
@if (network === '' && emptyBlock && emptyBlock.height > 100000 && emptyBlock.tx_count <= 1) {
<a
class="info-bubble-link badge badge-primary"
class="info-bubble-link badge bg-primary"
[routerLink]="['/docs/faq/' | relativeUrl]"
fragment="why-empty-blocks"
>

View file

@ -61,7 +61,7 @@
.block-subtitle.actual a {
position: absolute;
top: -3px;
top: 17px;
}
.block-subtitle.actual fa-icon {

View file

@ -1,7 +1,7 @@
<app-indexing-progress *ngIf="!widget"></app-indexing-progress>
<div class="container-xl" style="min-height: 335px" [ngClass]="{'widget': widget, 'full-height': !widget, 'legacy': !isMempoolModule}">
<div *ngIf="!widget" class="float-left" style="display: flex; width: 100%; align-items: center;">
<div *ngIf="!widget" class="float-start" style="display: flex; width: 100%; align-items: center;">
<h1 i18n="master-page.blocks">Blocks</h1>
<app-svg-images name="blocks-2-3" style="width: 275px; max-width: 90%; margin-top: -10px"></app-svg-images>
<div *ngIf="!widget && isLoading" class="spinner-border" role="status"></div>
@ -12,63 +12,63 @@
<div style="min-height: 295px">
<table class="table table-borderless">
<thead>
<th class="height text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}" i18n="latest-blocks.height">Height</th>
<th *ngIf="isMempoolModule" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}" i18n="mining.pool-name"
<th class="height text-start" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}" i18n="latest-blocks.height">Height</th>
<th *ngIf="isMempoolModule" class="pool text-start" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}" i18n="mining.pool-name"
i18n-ngbTooltip="mining.pool-name" ngbTooltip="Pool" placement="bottom" #miningpool [disableTooltip]="!isEllipsisActive(miningpool)">Pool</th>
<th class="timestamp" i18n="latest-blocks.timestamp" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">Timestamp</th>
<th *ngIf="auditAvailable" class="health text-right" i18n="latest-blocks.health" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
<th *ngIf="auditAvailable" class="health text-end" i18n="latest-blocks.health" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
i18n-ngbTooltip="latest-blocks.health" ngbTooltip="Health" placement="bottom" #health [disableTooltip]="!isEllipsisActive(health)">Health</th>
<th *ngIf="isMempoolModule" class="reward text-right" i18n="latest-blocks.reward" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
<th *ngIf="isMempoolModule" class="reward text-end" i18n="latest-blocks.reward" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
i18n-ngbTooltip="latest-blocks.reward" ngbTooltip="Reward" placement="bottom" #reward [disableTooltip]="!isEllipsisActive(reward)">Reward</th>
<th *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-right" i18n="latest-blocks.fees" [class]="isMempoolModule ? '' : 'legacy'">Fees</th>
<th *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-end" i18n="latest-blocks.fees" [class]="isMempoolModule ? '' : 'legacy'">Fees</th>
<th *ngIf="auditAvailable && !widget" class="fee-delta" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"></th>
<th *ngIf="isMempoolModule" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
<th *ngIf="isMempoolModule" class="txs text-end" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}"
i18n-ngbTooltip="dashboard.txs" ngbTooltip="TXs" placement="bottom" #txs [disableTooltip]="!isEllipsisActive(txs)">TXs</th>
<th *ngIf="!isMempoolModule" class="txs text-right" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">Transactions</th>
<th *ngIf="!isMempoolModule" class="txs text-end" i18n="dashboard.txs" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">Transactions</th>
<th class="size" i18n="latest-blocks.size" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">Size</th>
</thead>
<tbody *ngIf="blocks$ | async as blocks; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
<td class="height text-left" [class]="widget ? 'widget' : ''">
<td class="height text-start" [class]="widget ? 'widget' : ''">
<a [routerLink]="['/block' | relativeUrl, block.id]" [state]="{ data: { block: block } }">{{ block.height }}</a>
</td>
<td *ngIf="isMempoolModule" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td *ngIf="isMempoolModule" class="pool text-start" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<div *ngIf="indexingAvailable" class="tooltip-custom">
<a class="clear-link" [routerLink]="['/mining/pool' | relativeUrl, block.extras.pool.slug]">
<img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
onError="this.onerror=null; this.src = '/resources/mining-pools/default.svg'" [alt]="'Logo of ' + block.extras.pool.name + ' mining pool'">
<span class="pool-name">{{ block.extras.pool.name }}</span>
</a>
<span *ngIf="!widget" class="tooltiptext badge badge-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span>
<span *ngIf="!widget" class="tooltiptext badge bg-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span>
</div>
<div *ngIf="!indexingAvailable" class="tooltip-custom">
<img width="22" height="22" src="{{ block.extras.pool['logo'] }}"
onError="this.src = '/resources/mining-pools/default.svg'" [alt]="'Logo of ' + block.extras.pool.name + ' mining pool'">
<span class="pool-name">{{ block.extras.pool.name }}</span>
<span *ngIf="!widget" class="tooltiptext badge badge-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span>
<span *ngIf="!widget" class="tooltiptext badge bg-secondary scriptmessage">{{ block.extras.coinbaseRaw | hex2ascii }}</span>
</div>
</td>
<td class="timestamp" *ngIf="!widget" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<app-timestamp [customFormat]="'yyyy-MM-dd HH:mm:ss'" [unixTime]="block.timestamp" [hideTimeSince]="true"></app-timestamp>
</td>
<td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td *ngIf="auditAvailable" class="health text-end" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<a
*ngIf="block?.extras?.matchRate != null; else nullHealth"
class="health-badge badge"
[class.badge-success]="block.extras.matchRate >= 99"
[class.badge-warning]="block.extras.matchRate >= 75 && block.extras.matchRate < 99"
[class.badge-danger]="block.extras.matchRate < 75"
[class.bg-success]="block.extras.matchRate >= 99"
[class.bg-warning]="block.extras.matchRate >= 75 && block.extras.matchRate < 99"
[class.bg-danger]="block.extras.matchRate < 75"
[routerLink]="block.extras.matchRate != null ? ['/block/' | relativeUrl, block.id] : null"
[state]="{ data: { block: block } }"
>{{ block.extras.matchRate }}%</a>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
<span class="health-badge badge bg-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
<td *ngIf="isMempoolModule" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td *ngIf="isMempoolModule" class="reward text-end" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<app-amount [satoshis]="block.extras.reward" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
</td>
<td *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-right" [class]="isMempoolModule ? '' : 'legacy'">
<td *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-end" [class]="isMempoolModule ? '' : 'legacy'">
<app-amount [satoshis]="block.extras.totalFees" [noFiat]="true" digitsInfo="1.2-2"></app-amount>
</td>
<td *ngIf="auditAvailable" class="fee-delta" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
@ -76,7 +76,7 @@
{{ block.extras.feeDelta > 0 ? '+' : '' }}{{ (block.extras.feeDelta * 100) | amountShortener: 2 }}%
</span>
</td>
<td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td class="txs text-end" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
{{ block.tx_count | number }}
</td>
<td class="size" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
@ -91,28 +91,28 @@
<ng-template #skeleton>
<tbody>
<tr *ngFor="let item of skeletonLines">
<td class="height text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td class="height text-start" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td *ngIf="isMempoolModule" class="pool text-left" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td *ngIf="isMempoolModule" class="pool text-start" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 150px"></span>
</td>
<td class="timestamp" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 150px"></span>
</td>
<td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td *ngIf="auditAvailable" class="health text-end" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td *ngIf="isMempoolModule" class="reward text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td *ngIf="isMempoolModule" class="reward text-end" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-right" [class]="isMempoolModule ? '' : 'legacy'">
<td *ngIf="isMempoolModule && !auditAvailable || isMempoolModule && !widget" class="fees text-end" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td *ngIf="auditAvailable && !widget" class="fee-delta" [class]="isMempoolModule ? '' : 'legacy'">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="txs text-right" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<td class="txs text-end" [ngClass]="{'widget': widget, 'legacy': !isMempoolModule}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="size" *ngIf="!widget" [class]="isMempoolModule ? '' : 'legacy'">
@ -123,7 +123,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget" class="pagination-container float-end mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="blocksCount" [rotate]="true" [maxSize]="maxSize" [pageSize]="15" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -5,8 +5,8 @@
<ng-container *ngIf="(price$ | async) !== undefined; else loading">
<div class="row justify-content-center align-item-center mb-3">
<div class="input-group-prepend">
<div class="row calculator-row justify-content-center align-item-center mb-3">
<div class="input-group calculator-date-group">
<input
class="form-control flex-grow-1 disabled"
style="max-width: 125px"
@ -24,34 +24,26 @@
</div>
</div>
<div class="row justify-content-center">
<form [formGroup]="form">
<div class="row calculator-row justify-content-center">
<form [formGroup]="form" class="calculator-form">
<div class="input-group input-group-lg mb-1">
<div class="input-group-prepend">
<span class="input-group-text">{{ currency$ | async }}</span>
</div>
<span class="input-group-text">{{ currency$ | async }}</span>
<input type="text" inputmode="decimal" class="form-control" formControlName="fiat" (input)="transformInput('fiat')" (click)="selectAll($event)">
<app-clipboard [button]="true" [text]="form.get('fiat').value" [class]="'btn btn-lg btn-secondary ml-1'"></app-clipboard>
<app-clipboard [button]="true" [text]="form.get('fiat').value" [class]="'btn btn-lg btn-secondary ms-1'"></app-clipboard>
</div>
<div class="input-group input-group-lg mb-1">
<div class="input-group-prepend">
<span class="input-group-text">BTC</span>
</div>
<span class="input-group-text">BTC</span>
<input type="text" inputmode="decimal" class="form-control" formControlName="bitcoin" (input)="transformInput('bitcoin')" (click)="selectAll($event)">
<app-clipboard [button]="true" [text]="form.get('bitcoin').value" [class]="'btn btn-lg btn-secondary ml-1'"></app-clipboard>
<app-clipboard [button]="true" [text]="form.get('bitcoin').value" [class]="'btn btn-lg btn-secondary ms-1'"></app-clipboard>
</div>
<div class="input-group input-group-lg mb-1">
<div class="input-group-prepend">
<span class="input-group-text" i18n="shared.sats">sats</span>
</div>
<span class="input-group-text" i18n="shared.sats">sats</span>
<input type="text" inputmode="numeric" class="form-control" formControlName="satoshis" (input)="transformInput('satoshis')" (click)="selectAll($event)">
<app-clipboard [button]="true" [text]="form.get('satoshis').value" [class]="'btn btn-lg btn-secondary ml-1'"></app-clipboard>
<app-clipboard [button]="true" [text]="form.get('satoshis').value" [class]="'btn btn-lg btn-secondary ms-1'"></app-clipboard>
</div>
</form>
</div>
<div class="row justify-content-center mt-3" *ngIf="isMaxSupply">
@ -62,7 +54,7 @@
<br>
<div class="row justify-content-center">
<div class="row calculator-inline-row justify-content-center">
<div class="bitcoin-satoshis-text">
<span [innerHTML]="form.get('bitcoin').value | bitcoinsatoshis"></span>
@ -70,13 +62,13 @@
</div>
</div>
<div class="row justify-content-center">
<div class="row calculator-inline-row justify-content-center">
<div class="fiat-text">
<app-fiat [value]="form.get('satoshis').value" digitsInfo="1.2-2" [blockConversion]="blockConversion"></app-fiat>
</div>
</div>
<div class="row justify-content-center mt-3">
<div class="row calculator-inline-row justify-content-center mt-3">
<div class="symbol" *ngIf="{ value: (price$ | async) } as priceData">
@if (todaySelected) {
<span>Fiat price last updated <app-time kind="since" [time]="lastFiatPrice$ | async" [fastRender]="true"></app-time>: {{ priceData.value | fiatCurrency : '1.0-0' : (currency$ | async) }}</span>
@ -87,8 +79,6 @@
}
</div>
</div>
</ng-container>
<ng-template #loading>
@ -103,4 +93,4 @@
<span class="btn btn-sm" [class.focused]="focused" [class.bg-primary]="selected" [class.hidden]="date.month !== currentMonth" [class.text-muted]="disabled">
{{ date.day }}
</span>
</ng-template>
</ng-template>

View file

@ -33,4 +33,31 @@
pointer-events: none;
background-color: var(--secondary);
opacity: 0.75;
}
.calculator-date-group {
width: 172px;
}
.calculator-form {
width: 100%;
max-width: 373px;
}
.calculator-row > * {
padding-left: 0;
padding-right: 0;
}
.calculator-inline-row > * {
flex: 0 0 auto;
width: auto;
max-width: 100%;
padding-left: 0;
padding-right: 0;
}
:host ::ng-deep ngb-datepicker .ngb-dp-weekdays,
:host ::ng-deep ngb-datepicker .ngb-dp-header {
background-color: var(--bg) !important;
}

View file

@ -9,7 +9,7 @@ import { Component, Input, ChangeDetectionStrategy, ChangeDetectorRef } from '@a
})
export class ClipboardComponent {
@Input() button = false;
@Input() class = 'btn btn-secondary ml-1';
@Input() class = 'btn btn-secondary ms-1';
@Input() size: 'small' | 'normal' | 'large' = 'normal';
@Input() text: string;
@Input() leftPadding = true;

View file

@ -21,17 +21,19 @@
@case ('goggles') {
<div class="col" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card graph-card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
<div class="card-body ps-lg-3 pe-lg-3 ps-2 pe-2">
<a class="title-link mb-0" style="margin-top: -2px" href="" [routerLink]="['/mempool-block/0' | relativeUrl]">
<h5 class="card-title d-inline"><span>Mempool Goggles&reg;</span> : {{ goggleCycle[goggleIndex].name }}</h5>
<span>&nbsp;</span>
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: var(--title-fg)"></fa-icon>
</a>
<div class="quick-filter">
<div class="btn-group btn-group-toggle">
<label class="btn btn-primary btn-xs" [class.active]="filter.index === goggleIndex" *ngFor="let filter of goggleCycle">
<input type="radio" [value]="'3m'" fragment="3m" (click)="setFilter(filter.index)" [attr.data-cy]="'3m'"> {{ filter.name }}
</label>
<div class="btn-group" role="group">
<ng-container *ngFor="let filter of goggleCycle">
<input type="radio" class="btn-check" [value]="'3m'" [id]="'btn-radio-' + filter.index"
[checked]="filter.index === goggleIndex" (click)="setFilter(filter.index)" [attr.data-cy]="'3m'">
<label class="btn btn-primary btn-xs" [for]="'btn-radio-' + filter.index">{{ filter.name }}</label>
</ng-container>
</div>
</div>
<div class="mempool-block-wrapper" *ngIf="webGlEnabled">
@ -118,9 +120,9 @@
<td class="table-cell-old-fee"><app-fee-rate [fee]="replacement.oldFee" [weight]="replacement.oldVsize * 4"></app-fee-rate></td>
<td class="table-cell-new-fee"><app-fee-rate [fee]="replacement.newFee" [weight]="replacement.newVsize * 4"></app-fee-rate></td>
<td class="table-cell-badges">
<span *ngIf="replacement.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="replacement.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="!replacement.fullRbf" class="badge badge-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
<span *ngIf="replacement.mined" class="badge bg-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="replacement.fullRbf" class="badge bg-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="!replacement.fullRbf" class="badge bg-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
</td>
</tr>
</tbody>
@ -294,7 +296,7 @@
@case ('twitter') {
<div class="col" style="min-height:410px" [style.order]="isMobile && widget.mobileOrder || 8">
<div class="card graph-card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2 d-flex flex-column">
<div class="card-body ps-lg-3 pe-lg-3 ps-2 pe-2 d-flex flex-column">
<a class="title-link" [href]="'https://x.com/' + widget.props?.handle" target="_blank">
<h5 class="card-title d-inline" i18n="dashboard.x-timeline">X Timeline</h5>
<span>&nbsp;</span>

View file

@ -3,9 +3,9 @@
<thead>
<tr>
<th class="" i18n="block.height">Height</th>
<th class="date text-left" i18n="mining.adjusted">Adjusted</th>
<th class="text-right" i18n="mining.difficulty">Difficulty</th>
<th class="text-right" i18n="mining.change">Change</th>
<th class="date text-start" i18n="mining.adjusted">Adjusted</th>
<th class="text-end" i18n="mining.difficulty">Difficulty</th>
<th class="text-end" i18n="mining.change">Change</th>
</tr>
</thead>
<tbody *ngIf="(hashrateObservable$ | async) as data">
@ -13,11 +13,11 @@
<td class="">
<a [routerLink]="['/block' | relativeUrl, diffChange.height]">{{ diffChange.height }}</a>
</td>
<td class="date text-left">
<td class="date text-start">
<app-time kind="since" [time]="diffChange.timestamp" [fastRender]="true" [precision]="1" [showTooltip]="true"></app-time>
</td>
<td class="text-right">{{ diffChange.difficultyShorten }}</td>
<td class="text-right" [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'">
<td class="text-end">{{ diffChange.difficultyShorten }}</td>
<td class="text-end" [style]="diffChange.change >= 0 ? 'color: #42B747' : 'color: #B74242'">
{{ diffChange.change >= 0 ? '+' : '' }}{{ diffChange.change | amountShortener: 2 }}%
</td>
</tr>
@ -25,9 +25,9 @@
<tbody *ngIf="isLoading">
<tr *ngFor="let item of [1,2,3,4,5,6]">
<td class=""><span class="skeleton-loader"></span></td>
<td class="date text-left"><span class="skeleton-loader w-75"></span></td>
<td class="text-right"><span class="skeleton-loader w-75"></span></td>
<td class="text-right"><span class="skeleton-loader w-75"></span></td>
<td class="date text-start"><span class="skeleton-loader w-75"></span></td>
<td class="text-end"><span class="skeleton-loader w-75"></span></td>
<td class="text-end"><span class="skeleton-loader w-75"></span></td>
</tr>
</tbody>
</table>

View file

@ -19,16 +19,16 @@
} @else if (!user) {
<!-- User not logged in -->
<div class="alert alert-mempool d-block text-center w-100">
<div class="d-inline align-middle pr-2">
<div class="d-inline align-middle pe-2">
<span>To use the faucet, please</span>
</div>
<app-github-login customClass="btn btn-sm" width="150px" redirectTo="/testnet4/faucet" buttonString="Sign up with"></app-github-login>
</div>
}
@else if (user && user.status === 'pending' && !user.email && user.snsId) {
<div class="alert alert-danger w-100 col d-flex justify-content-center text-left">
<div class="alert alert-danger w-100 col d-flex justify-content-center text-start">
<span class="d-flex">
<fa-icon [icon]="['fas', 'exclamation-triangle']" [fixedWidth]="true" class="mr-1"></fa-icon>
<fa-icon [icon]="['fas', 'exclamation-triangle']" [fixedWidth]="true" class="me-1"></fa-icon>
<span>Please <a class="text-primary" [routerLink]="['/services/account/settings']">verify your account</a> by providing a valid email address. To mitigate spam, we delete unverified accounts at regular intervals.</span>
</span>
</div>
@ -37,7 +37,7 @@
<!-- User logged in but not a paid user or did not link its Github account -->
<div class="alert alert-mempool d-block text-center w-100">
<div class="d-inline align-middle">
<span class="mb-2 mr-2">To use the faucet, please</span>
<span class="mb-2 me-2">To use the faucet, please</span>
</div>
<app-github-login customClass="btn btn-sm" width="180px" redirectTo="/testnet4/faucet" buttonString="Link your"></app-github-login>
</div>
@ -45,7 +45,7 @@
@else if (error === 'account_limited') {
<div class="alert alert-mempool d-block text-center w-100">
<div class="d-inline align-middle">
<span class="mb-2 mr-2">Your account does not allow you to access the faucet</span>
<span class="mb-2 me-2">Your account does not allow you to access the faucet</span>
</div>
</div>
}
@ -58,31 +58,27 @@
<form [formGroup]="faucetForm" class="formGroup" (submit)="requestCoins()">
<div class="row">
<div class="col">
<div class="form-group mb-0">
<div class="mb-0">
<div class="input-group input-group-lg">
<div class="input-group-prepend">
<span class="input-group-text" i18n="amount-sats">Amount (sats)</span>
</div>
<span class="input-group-text" i18n="amount-sats">Amount (sats)</span>
<input type="number" class="form-control" [class]="{invalid: invalidAmount}" formControlName="satoshis" id="satoshis">
<div class="button-group">
<button type="button" class="btn btn-secondary" (click)="setAmount(5000)">5k</button>
<button type="button" class="btn btn-secondary ml-2" (click)="setAmount(50000)">50k</button>
<button type="button" class="btn btn-secondary ml-2" (click)="setAmount(500000)">500k</button>
<button type="button" class="btn btn-secondary ms-2" (click)="setAmount(50000)">50k</button>
<button type="button" class="btn btn-secondary ms-2" (click)="setAmount(500000)">500k</button>
</div>
</div>
<div class="text-danger text-left" *ngIf="invalidAmount">
<div class="text-danger text-start" *ngIf="invalidAmount">
<div *ngIf="amount?.errors?.['required']">Amount is required</div>
<div *ngIf="amount?.errors?.['min']">Minimum is {{ amount?.errors?.['min'].min | number }} tSats</div>
<div *ngIf="amount?.errors?.['max']">Maximum is {{ amount?.errors?.['max'].max | number }} tSats</div>
</div>
<div class="input-group input-group-lg mt-2">
<div class="input-group-prepend">
<span class="input-group-text" i18n="address">Address</span>
</div>
<span class="input-group-text" i18n="address">Address</span>
<input type="text" class="form-control" [class]="{invalid: invalidAddress}" formControlName="address" id="address" placeholder="tb1q...">
<button type="submit" class="btn btn-primary submit-button" [disabled]="!faucetForm.valid || !faucetForm.get('address')?.dirty || isDisabled()" i18n="testnet4.request-coins">Request Testnet4 Coins</button>
</div>
<div class="text-danger text-left" *ngIf="invalidAddress">
<div class="text-danger text-start" *ngIf="invalidAddress">
<div *ngIf="address?.errors?.['required']">Address is required</div>
<div *ngIf="address?.errors?.['pattern']">Must be a valid testnet4 address</div>
<div *ngIf="address?.errors?.['forbiddenAddress']">You cannot use this address</div>

View file

@ -1,5 +1,5 @@
<div [formGroup]="fiatForm" class="text-small text-center">
<select formControlName="fiat" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" style="width: 85px;" (change)="changeFiat()">
<select formControlName="fiat" class="form-select form-select-sm form-control-secondary form-control mx-auto" style="width: 85px;" (change)="changeFiat()">
<option *ngFor="let currency of currencies" [value]="currency[1].code">{{ currency[1].code }}</option>
</select>
</div>

View file

@ -5,7 +5,7 @@
<span class="txPerSecond" i18n="dashboard.incoming-transactions">Incoming Transactions</span>&nbsp;
<ng-template [ngIf]="(isLoadingWebSocket$ | async) === false && mempoolInfoData" [ngIfElse]="loadingTransactions">
<span *ngIf="(mempoolLoadingStatus$ | async) !== 100; else inSync">
&nbsp;<span class="badge badge-pill badge-warning"><ng-container i18n="dashboard.backend-is-synchronizing">Backend is synchronizing</ng-container> ({{ mempoolLoadingStatus$ | async }}%)</span>
&nbsp;<span class="badge rounded-pill bg-warning"><ng-container i18n="dashboard.backend-is-synchronizing">Backend is synchronizing</ng-container> ({{ mempoolLoadingStatus$ | async }}%)</span>
</span>
<ng-template #inSync>
<div class="progress inc-tx-progress-bar">

View file

@ -1,5 +1,5 @@
<a href="#" (click)="githubLogin()" [class]="(disabled ? 'disabled': '') + (customClass ? customClass : 'w-100 btn mt-1 d-flex justify-content-center align-items-center')" style="background-color: rgb(31, 35, 40)" [style]="width ? 'width: ' + width : ''">
<span class="ml-2 text-light align-middle">{{ buttonString }}</span>
<span class="ms-2 text-light align-middle">{{ buttonString }}</span>
<svg height="32" viewBox="0 0 18 16" width="32" style="fill: white; padding-left: 5px">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"/>
</svg>

View file

@ -25,31 +25,35 @@
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.hashrate-difficulty">Hashrate & Difficulty</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'3m'" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'6m'" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'1y'" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'2y'" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'3y'" 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/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'all'" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 12960">
<input type="radio" class="btn-check" id="hashrate-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'3m'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="hashrate-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="hashrate-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'6m'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="hashrate-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="hashrate-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'1y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="hashrate-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="hashrate-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'2y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="hashrate-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="hashrate-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'3y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="hashrate-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="hashrate-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/hashrate-difficulty' | relativeUrl]" [attr.data-cy]="'all'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="hashrate-all">ALL</label>
</div>
</form>
</div>

View file

@ -5,28 +5,31 @@
<div class="card-header mb-0 mb-md-4">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="mining.pools-dominance">Pools Dominance</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="(hashrateObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'6m'" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'1y'" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'2y'" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.blockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'3y'" 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/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'all'" formControlName="dateSpan"> ALL
</label>
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.blockCount >= 25920">
<input type="radio" class="btn-check" id="dominance-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'6m'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dominance-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 52560">
<input type="radio" class="btn-check" id="dominance-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'1y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dominance-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 105120">
<input type="radio" class="btn-check" id="dominance-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'2y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dominance-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.blockCount >= 157680">
<input type="radio" class="btn-check" id="dominance-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'3y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dominance-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="dominance-all" [value]="'all'" fragment="all" [routerLink]="['/graphs/mining/pools-dominance' | relativeUrl]" [attr.data-cy]="'all'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dominance-all">ALL</label>
</div>
</form>
</div>

View file

@ -1,5 +1,5 @@
<div [formGroup]="languageForm" class="text-small text-center">
<select formControlName="language" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" style="width: 120px;" (change)="changeLanguage()">
<select formControlName="language" class="form-select form-select-sm form-control-secondary form-control mx-auto" style="width: 120px;" (change)="changeLanguage()">
<option *ngFor="let lang of languages" [value]="lang.code">{{ lang.name }}</option>
</select>
</div>

View file

@ -18,13 +18,13 @@
<app-svg-images name="liquidNetwork" viewBox="0 0 500 126" class="mempool-logo" [ngStyle]="{'opacity': connectionState.val === 2 ? 1 : 0.5 }"></app-svg-images>
}
<div class="connection-badge">
<div class="badge badge-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge badge-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
</div>
</ng-container>
</a>
<!-- Mobile -->
<a class="navbar-brand d-flex d-md-none" [ngClass]="{'dual-logos': enterpriseInfo?.dualLogo, 'mr-0': enterpriseInfo?.dualLogo}" [routerLink]="['/' | relativeUrl]">
<a class="navbar-brand d-flex d-md-none" [ngClass]="{'dual-logos': enterpriseInfo?.dualLogo, 'me-0': enterpriseInfo?.dualLogo}" [routerLink]="['/' | relativeUrl]">
<ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
@if (enterpriseInfo) {
<div class="subdomain_container">
@ -38,8 +38,8 @@
<app-svg-images name="liquidNetwork" viewBox="0 0 500 126" class="mempool-logo" [ngStyle]="{'opacity': connectionState.val === 2 ? 1 : 0.5 }"></app-svg-images>
}
<div class="connection-badge">
<div class="badge badge-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge badge-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
</div>
</ng-container>
</a>
@ -55,14 +55,14 @@
<app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" [name]="network.val === '' ? 'liquid' : network.val" width="20" height="20" viewBox="0 0 125 125"></app-svg-images>
</button>
<div ngbDropdownMenu [ngClass]="{'dropdown-menu-right' : isMobile}">
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['mainnet'] || '')" ngbDropdownItem class="mainnet"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['signet'] || '/signet')" ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet'] || '/testnet')" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet3</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet4'] || '/testnet4')" ngbDropdownItem *ngIf="env.TESTNET4_ENABLED" class="testnet"><app-svg-images name="testnet4" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet4</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['regtest'] || '/regtest')" ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Regtest</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['mainnet'] || '')" ngbDropdownItem class="mainnet"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Mainnet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['signet'] || '/signet')" ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Signet</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet'] || '/testnet')" ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Testnet3</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['testnet4'] || '/testnet4')" ngbDropdownItem *ngIf="env.TESTNET4_ENABLED" class="testnet"><app-svg-images name="testnet4" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Testnet4</a>
<a [href]="env.MEMPOOL_WEBSITE_URL + urlLanguage + (networkPaths['regtest'] || '/regtest')" ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Regtest</a>
<h6 class="dropdown-header" i18n="master-page.layer2-networks-header">Layer 2 Networks</h6>
<a ngbDropdownItem class="liquid mr-1" [class.active]="network.val === 'liquid'" [routerLink]="networkPaths['liquid'] || '/'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a>
<a ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED" class="liquidtestnet" [class.active]="network.val === 'liquidtestnet'" [routerLink]="networkPaths['liquidtestnet'] || '/testnet'"><app-svg-images name="liquidtestnet" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid Testnet</a>
<a ngbDropdownItem class="liquid me-1" [class.active]="network.val === 'liquid'" [routerLink]="networkPaths['liquid'] || '/'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Liquid</a>
<a ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED" class="liquidtestnet" [class.active]="network.val === 'liquidtestnet'" [routerLink]="networkPaths['liquidtestnet'] || '/testnet'"><app-svg-images name="liquidtestnet" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Liquid Testnet</a>
</div>
</div>

View file

@ -22,30 +22,30 @@
<div style="min-height: 295px">
<table class="table table-borderless">
<thead style="vertical-align: middle;">
<th class="address text-left" [ngClass]="{'widget': widget}" i18n="shared.address">Address</th>
<th class="amount text-right" [ngClass]="{'widget': widget}" i18n="address.balance">Balance</th>
<th class="address text-start" [ngClass]="{'widget': widget}" i18n="shared.address">Address</th>
<th class="amount text-end" [ngClass]="{'widget': widget}" i18n="address.balance">Balance</th>
</thead>
<tbody *ngIf="federationAddresses$ | async as addresses; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<ng-container *ngIf="widget; else regularRows">
<tr *ngFor="let address of addresses | slice:0:6">
<td class="address text-left widget">
<td class="address text-start widget">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/address/' + address.bitcoinaddress }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="address.bitcoinaddress" [lastChars]="6"></app-truncate>
</a>
</td>
<td class="amount text-right widget">
<td class="amount text-end widget">
<app-amount [satoshis]="+address.balance" [noFiat]="true" [forceBtc]="true"></app-amount>
</td>
</tr>
</ng-container>
<ng-template #regularRows>
<tr *ngFor="let address of addresses | slice:(page - 1) * pageSize:page * pageSize">
<td class="address text-left">
<td class="address text-start">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/address/' + address.bitcoinaddress }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="address.bitcoinaddress" [lastChars]="6"></app-truncate>
</a>
</td>
<td class="amount text-right">
<td class="amount text-end">
<app-amount [satoshis]="+address.balance" [noFiat]="true" [forceBtc]="true"></app-amount>
</td>
</tr>
@ -54,20 +54,20 @@
<ng-template #skeleton>
<tbody *ngIf="widget; else regularRowsSkeleton">
<tr *ngFor="let item of skeletonLines">
<td class="address text-left widget">
<td class="address text-start widget">
<span class="skeleton-loader" style="max-width: 400px"></span>
</td>
<td class="amount text-right widget">
<td class="amount text-end widget">
<span class="skeleton-loader" style="max-width: 350px"></span>
</td>
</tr>
</tbody>
<ng-template #regularRowsSkeleton>
<tr *ngFor="let item of skeletonLines">
<td class="address text-left">
<td class="address text-start">
<span class="skeleton-loader" style="max-width: 600px"></span>
</td>
<td class="amount text-right">
<td class="amount text-end">
<span class="skeleton-loader" style="max-width: 400px"></span>
</td>
</tr>
@ -75,7 +75,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget && federationAddresses$ | async as addresses" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget && federationAddresses$ | async as addresses" class="pagination-container float-end mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="addresses.length" [rotate]="true" [maxSize]="maxSize" [pageSize]="15" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -22,47 +22,47 @@
<div style="min-height: 295px">
<table class="table table-borderless">
<thead style="vertical-align: middle;">
<th class="txid text-left" [ngClass]="{'widget': widget}" i18n="transaction.output">Output</th>
<th class="address text-left" *ngIf="!widget" i18n="shared.address">Address</th>
<th class="amount text-right" [ngClass]="{'widget': widget}" i18n="shared.amount">Amount</th>
<th class="pegin text-left" *ngIf="!widget" i18n="liquid.related-peg-in">Related Peg-In</th>
<th class="timestamp text-left" i18n="shared.date" [ngClass]="{'widget': widget}">Date</th>
<th class="expires-in text-left" *ngIf="!widget && showExpiredUtxos === false" i18n="liquid.expires-in">Expires in</th>
<th class="expires-in text-left" *ngIf="!widget && showExpiredUtxos === true" i18n="liquid.expired-since">Expired since</th>
<th class="is-dust text-right" *ngIf="!widget && showExpiredUtxos === true" i18n="liquid.dust">Dust</th>
<th class="txid text-start" [ngClass]="{'widget': widget}" i18n="transaction.output">Output</th>
<th class="address text-start" *ngIf="!widget" i18n="shared.address">Address</th>
<th class="amount text-end" [ngClass]="{'widget': widget}" i18n="shared.amount">Amount</th>
<th class="pegin text-start" *ngIf="!widget" i18n="liquid.related-peg-in">Related Peg-In</th>
<th class="timestamp text-start" i18n="shared.date" [ngClass]="{'widget': widget}">Date</th>
<th class="expires-in text-start" *ngIf="!widget && showExpiredUtxos === false" i18n="liquid.expires-in">Expires in</th>
<th class="expires-in text-start" *ngIf="!widget && showExpiredUtxos === true" i18n="liquid.expired-since">Expired since</th>
<th class="is-dust text-end" *ngIf="!widget && showExpiredUtxos === true" i18n="liquid.dust">Dust</th>
</thead>
<tbody *ngIf="federationUtxos$ | async as utxos; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<ng-container *ngIf="widget; else regularRows">
<tr *ngFor="let utxo of utxos | slice:0:6">
<td class="txid text-left widget">
<td class="txid text-start widget">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/tx/' + utxo.txid + ':' + utxo.txindex }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="utxo.txid + ':' + utxo.txindex" [lastChars]="6"></app-truncate>
</a>
</td>
<td class="amount text-right widget">
<td class="amount text-end widget">
<app-amount [satoshis]="utxo.amount" [noFiat]="true" [forceBtc]="true"></app-amount>
</td>
<td class="timestamp text-left widget">
<td class="timestamp text-start widget">
<app-time kind="since" [time]="utxo.blocktime" [showTooltip]="true"></app-time>
</td>
</tr>
</ng-container>
<ng-template #regularRows>
<tr *ngFor="let utxo of utxos | slice:(page - 1) * pageSize:page * pageSize">
<td class="txid text-left">
<td class="txid text-start">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/tx/' + utxo.txid + ':' + utxo.txindex }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="utxo.txid + ':' + utxo.txindex" [lastChars]="6"></app-truncate>
</a>
</td>
<td class="address text-left">
<td class="address text-start">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/address/' + utxo.bitcoinaddress }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="utxo.bitcoinaddress" [lastChars]="6"></app-truncate>
</a>
</td>
<td class="amount text-right">
<td class="amount text-end">
<app-amount [satoshis]="utxo.amount" [noFiat]="true" [forceBtc]="true"></app-amount>
</td>
<td class="pegin text-left">
<td class="pegin text-start">
<ng-container *ngIf="utxo.pegtxid; else noPeginMessage">
<a [routerLink]="['/tx' | relativeUrl, utxo.pegtxid]" [fragment]="'vin=' + utxo.pegindex">
<app-truncate [text]="utxo.pegtxid + ':' + utxo.pegindex" [lastChars]="6"></app-truncate>
@ -72,13 +72,13 @@
<i><span class="text-muted" i18n="liquid.change-output">Change output</span></i>
</ng-template>
</td>
<td class="timestamp text-left">
<td class="timestamp text-start">
<app-timestamp [customFormat]="'yyyy-MM-dd HH:mm'" [unixTime]="utxo.blocktime"></app-timestamp>
</td>
<td class="expires-in text-left" [ngStyle]="{ 'color': getGradientColor(utxo.blocknumber + utxo.timelock - lastReservesBlockUpdate) }">
<td class="expires-in text-start" [ngStyle]="{ 'color': getGradientColor(utxo.blocknumber + utxo.timelock - lastReservesBlockUpdate) }">
{{ utxo.blocknumber + utxo.timelock - lastReservesBlockUpdate < 0 ? -(utxo.blocknumber + utxo.timelock - lastReservesBlockUpdate) : utxo.blocknumber + utxo.timelock - lastReservesBlockUpdate }} <span i18n="shared.blocks" class="symbol">blocks</span>
</td>
<td *ngIf="!widget && showExpiredUtxos === true" class="is-dust text-right" [ngStyle]="{ 'color': !utxo.isDust ? 'var(--red)' : '' }">
<td *ngIf="!widget && showExpiredUtxos === true" class="is-dust text-end" [ngStyle]="{ 'color': !utxo.isDust ? 'var(--red)' : '' }">
@if (utxo.isDust) {
} @else {
@ -91,35 +91,35 @@
<ng-template #skeleton>
<tbody *ngIf="widget; else regularRowsSkeleton">
<tr *ngFor="let item of skeletonLines">
<td class="txid text-left widget">
<td class="txid text-start widget">
<span class="skeleton-loader" style="max-width: 400px"></span>
</td>
<td class="amount text-right widget">
<td class="amount text-end widget">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="timestamp text-left widget">
<td class="timestamp text-start widget">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
</tr>
</tbody>
<ng-template #regularRowsSkeleton>
<tr *ngFor="let item of skeletonLines">
<td class="txid text-left">
<td class="txid text-start">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="address text-left">
<td class="address text-start">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="amount text-right">
<td class="amount text-end">
<span class="skeleton-loader" style="max-width: 140px"></span>
</td>
<td class="pegin text-left">
<td class="pegin text-start">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="timestamp text-left">
<td class="timestamp text-start">
<span class="skeleton-loader" style="max-width: 140px"></span>
</td>
<td class="expires-in text-left">
<td class="expires-in text-start">
<span class="skeleton-loader" style="max-width: 140px"></span>
</td>
</tr>
@ -127,7 +127,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget && federationUtxos$ | async as utxos" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget && federationUtxos$ | async as utxos" class="pagination-container float-end mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="utxos.length" [rotate]="true" [maxSize]="maxSize" [pageSize]="15" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -10,16 +10,16 @@
<div style="min-height: 295px">
<table class="table table-borderless">
<thead style="vertical-align: middle;">
<th class="transaction text-left" [ngClass]="{'widget': widget}" i18n="shared.transaction">Transaction</th>
<th class="timestamp text-left" i18n="shared.date" [ngClass]="{'widget': widget}">Date</th>
<th class="amount text-right" [ngClass]="{'widget': widget}" i18n="shared.amount">Amount</th>
<th class="output text-left" *ngIf="!widget" i18n="liquid.fund-redemption-tx">Fund / Redemption Tx</th>
<th class="address text-left" *ngIf="!widget" i18n="liquid.bitcoin-address">BTC Address</th>
<th class="transaction text-start" [ngClass]="{'widget': widget}" i18n="shared.transaction">Transaction</th>
<th class="timestamp text-start" i18n="shared.date" [ngClass]="{'widget': widget}">Date</th>
<th class="amount text-end" [ngClass]="{'widget': widget}" i18n="shared.amount">Amount</th>
<th class="output text-start" *ngIf="!widget" i18n="liquid.fund-redemption-tx">Fund / Redemption Tx</th>
<th class="address text-start" *ngIf="!widget" i18n="liquid.bitcoin-address">BTC Address</th>
</thead>
<tbody *ngIf="recentPegsList$ | async as pegs; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<ng-container *ngIf="widget; else regularRows">
<tr *ngFor="let peg of pegs | slice:0:6">
<td class="transaction text-left widget">
<td class="transaction text-start widget">
<ng-container *ngIf="peg.amount > 0">
<a [routerLink]="['/tx' | relativeUrl, peg.txid]" [fragment]="'vin=' + peg.txindex">
<app-truncate [text]="peg.txid"></app-truncate>
@ -31,17 +31,17 @@
</a>
</ng-container>
</td>
<td class="timestamp text-left widget">
<td class="timestamp text-start widget">
<app-time kind="since" [time]="peg.blocktime" [showTooltip]="true"></app-time>
</td>
<td class="amount text-right widget" [ngClass]="{'credit': peg.amount > 0, 'debit': peg.amount < 0, 'glow-effect': peg.amount < 0 && peg.bitcoinaddress && !peg.bitcointxid}">
<td class="amount text-end widget" [ngClass]="{'credit': peg.amount > 0, 'debit': peg.amount < 0, 'glow-effect': peg.amount < 0 && peg.bitcoinaddress && !peg.bitcointxid}">
<app-amount [satoshis]="peg.amount" [noFiat]="true" [forceBtc]="true" [addPlus]="true"></app-amount>
</td>
</tr>
</ng-container>
<ng-template #regularRows>
<tr *ngFor="let peg of pegs;">
<td class="transaction text-left">
<td class="transaction text-start">
<ng-container *ngIf="peg.amount > 0">
<a [routerLink]="['/tx' | relativeUrl, peg.txid]" [fragment]="'vin=' + peg.txindex">
<app-truncate [text]="peg.txid" [lastChars]="6"></app-truncate>
@ -53,13 +53,13 @@
</a>
</ng-container>
</td>
<td class="timestamp text-left">
<td class="timestamp text-start">
<app-timestamp [customFormat]="'yyyy-MM-dd HH:mm'" [unixTime]="peg.blocktime"></app-timestamp>
</td>
<td class="amount text-right" [ngClass]="{'credit': peg.amount > 0, 'debit': peg.amount < 0, 'glow-effect': peg.amount < 0 && peg.bitcoinaddress && !peg.bitcointxid}">
<td class="amount text-end" [ngClass]="{'credit': peg.amount > 0, 'debit': peg.amount < 0, 'glow-effect': peg.amount < 0 && peg.bitcoinaddress && !peg.bitcointxid}">
<app-amount [satoshis]="peg.amount" [noFiat]="true" [forceBtc]="true" [addPlus]="true"></app-amount>
</td>
<td class="output text-left">
<td class="output text-start">
<ng-container *ngIf="peg.bitcointxid; else redeemInProgress">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/tx/' + peg.bitcointxid + ':' + peg.bitcoinindex }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="peg.bitcointxid + ':' + peg.bitcoinindex" [lastChars]="6"></app-truncate>
@ -71,7 +71,7 @@
</ng-container>
</ng-template>
</td>
<td class="address text-left">
<td class="address text-start">
<ng-container *ngIf="peg.bitcoinaddress; else noRedeem">
<a href="{{ env.MEMPOOL_WEBSITE_URL + '/address/' + peg.bitcoinaddress }}" target="_blank" style="color:var(--orange)">
<app-truncate [text]="peg.bitcoinaddress" [lastChars]="6"></app-truncate>
@ -84,32 +84,32 @@
<ng-template #skeleton>
<tbody *ngIf="widget; else regularRowsSkeleton">
<tr *ngFor="let item of skeletonLines">
<td class="transaction text-left widget">
<td class="transaction text-start widget">
<span class="skeleton-loader" style="max-width: 400px"></span>
</td>
<td class="timestamp text-left widget">
<td class="timestamp text-start widget">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="amount text-right widget">
<td class="amount text-end widget">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
</tr>
</tbody>
<ng-template #regularRowsSkeleton>
<tr *ngFor="let item of skeletonLines">
<td class="transaction text-left">
<td class="transaction text-start">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="timestamp text-left">
<td class="timestamp text-start">
<span class="skeleton-loader" style="max-width: 240px"></span>
</td>
<td class="amount text-right">
<td class="amount text-end">
<span class="skeleton-loader" style="max-width: 140px"></span>
</td>
<td class="output text-left">
<td class="output text-start">
<span class="skeleton-loader" style="max-width: 300px"></span>
</td>
<td class="address text-left">
<td class="address text-start">
<span class="skeleton-loader" style="max-width: 240px"></span>
</td>
</tr>
@ -117,7 +117,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget && pegsCount$ | async as pegsCount" class="pagination-container float-right mt-2" [class]="isLoading || isPegCountLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget && pegsCount$ | async as pegsCount" class="pagination-container float-end mt-2" [class]="isLoading || isPegCountLoading ? 'disabled' : ''"
[collectionSize]="pegsCount" [rotate]="true" [maxSize]="maxSize" [pageSize]="15" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -1,3 +1,3 @@
<div *ngIf="this.indexingProgress$ | async as progress" class="sticky-loading">
<span *ngIf="progress >= 0" class="mr-auto badge badge-pill badge-warning">{{ this.label }} ({{ progress }}%)</span>
<span *ngIf="progress >= 0" class="me-auto badge rounded-pill bg-warning">{{ this.label }} ({{ progress }}%)</span>
</div>

View file

@ -12,12 +12,12 @@
</span>
<div [ngSwitch]="network.val">
<span *ngSwitchCase="'signet'" class="network signet"><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Signet</span>
<span *ngSwitchCase="'testnet'" class="network testnet"><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet3</span>
<span *ngSwitchCase="'testnet4'" class="network testnet"><app-svg-images name="testnet4" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet4</span>
<span *ngSwitchCase="'liquid'" class="network liquid"><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span>
<span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Testnet</span>
<span *ngSwitchDefault class="network mainnet"><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet mr-1"></app-svg-images> Mainnet</span>
<span *ngSwitchCase="'signet'" class="network signet"><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet me-1"></app-svg-images> Signet</span>
<span *ngSwitchCase="'testnet'" class="network testnet"><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet me-1"></app-svg-images> Testnet3</span>
<span *ngSwitchCase="'testnet4'" class="network testnet"><app-svg-images name="testnet4" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet me-1"></app-svg-images> Testnet4</span>
<span *ngSwitchCase="'liquid'" class="network liquid"><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet me-1"></app-svg-images> Mainnet</span>
<span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="width: 40px; height: 48px;" class="mainnet me-1"></app-svg-images> Testnet</span>
<span *ngSwitchDefault class="network mainnet"><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="width: 40px; height: 48px;" class="mainnet me-1"></app-svg-images> Mainnet</span>
</div>
</header>
<router-outlet></router-outlet>

View file

@ -30,13 +30,13 @@
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
}
<div class="connection-badge">
<div class="badge badge-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge badge-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
</div>
</ng-container>
</a>
<!-- Mobile -->
<a class="navbar-brand d-flex d-md-none justify-content-center" [ngClass]="{'dual-logos': enterpriseInfo?.dualLogo, 'mr-0': enterpriseInfo?.dualLogo}" [routerLink]="['/' | relativeUrl]" (click)="brandClick($event)">
<a class="navbar-brand d-flex d-md-none justify-content-center" [ngClass]="{'dual-logos': enterpriseInfo?.dualLogo, 'me-0': enterpriseInfo?.dualLogo}" [routerLink]="['/' | relativeUrl]" (click)="brandClick($event)">
<ng-container *ngIf="{ val: connectionState$ | async } as connectionState">
@if (enterpriseInfo) {
<div class="subdomain_container">
@ -51,8 +51,8 @@
<app-svg-images *ngIf="officialMempoolSpace" name="officialMempoolSpace" viewBox="0 0 500 126"></app-svg-images>
}
<div class="connection-badge">
<div class="badge badge-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge badge-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 0" i18n="master-page.offline">Offline</div>
<div class="badge bg-warning" *ngIf="connectionState.val === 1" i18n="master-page.reconnecting">Reconnecting...</div>
</div>
</ng-container>
</a>
@ -62,13 +62,13 @@
<app-svg-images class="d-flex justify-content-center align-items-center current-network-svg" [name]="network.val === '' ? 'bitcoin' : network.val" width="20" height="20" viewBox="0 0 65 65"></app-svg-images>
</button>
<div ngbDropdownMenu [ngClass]="{'dropdown-menu-right' : isMobile}">
<a ngbDropdownItem *ngIf="env.MAINNET_ENABLED" class="mainnet" [routerLink]="networkPaths['mainnet'] || '/'"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Mainnet</a>
<a ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet" [class.active]="network.val === 'signet'" [routerLink]="networkPaths['signet'] || '/signet'"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Signet</a>
<a ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet" [class.active]="network.val === 'testnet'" [routerLink]="networkPaths['testnet'] || '/testnet'"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet3</a>
<a ngbDropdownItem *ngIf="env.TESTNET4_ENABLED" class="testnet4" [class.active]="network.val === 'testnet4'" [routerLink]="networkPaths['testnet4'] || '/testnet4'"><app-svg-images name="testnet4" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Testnet4</a>
<a ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest" [class.active]="network.val === 'regtest'" [routerLink]="networkPaths['regtest'] || '/regtest'"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Regtest</a>
<a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquid'] || '')" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid" [class.active]="network.val === 'liquid'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid</a>
<a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquidtestnet'] || '/testnet')" ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED" class="liquidtestnet" [class.active]="network.val === 'liquid'"><app-svg-images name="liquidtestnet" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet mr-1"></app-svg-images> Liquid Testnet</a>
<a ngbDropdownItem *ngIf="env.MAINNET_ENABLED" class="mainnet" [routerLink]="networkPaths['mainnet'] || '/'"><app-svg-images name="bitcoin" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Mainnet</a>
<a ngbDropdownItem *ngIf="env.SIGNET_ENABLED" class="signet" [class.active]="network.val === 'signet'" [routerLink]="networkPaths['signet'] || '/signet'"><app-svg-images name="signet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Signet</a>
<a ngbDropdownItem *ngIf="env.TESTNET_ENABLED" class="testnet" [class.active]="network.val === 'testnet'" [routerLink]="networkPaths['testnet'] || '/testnet'"><app-svg-images name="testnet" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Testnet3</a>
<a ngbDropdownItem *ngIf="env.TESTNET4_ENABLED" class="testnet4" [class.active]="network.val === 'testnet4'" [routerLink]="networkPaths['testnet4'] || '/testnet4'"><app-svg-images name="testnet4" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Testnet4</a>
<a ngbDropdownItem *ngIf="env.REGTEST_ENABLED" class="regtest" [class.active]="network.val === 'regtest'" [routerLink]="networkPaths['regtest'] || '/regtest'"><app-svg-images name="regtest" width="22" height="22" viewBox="0 0 65 65" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Regtest</a>
<a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquid'] || '')" ngbDropdownItem *ngIf="env.LIQUID_ENABLED" class="liquid" [class.active]="network.val === 'liquid'"><app-svg-images name="liquid" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Liquid</a>
<a [href]="env.LIQUID_WEBSITE_URL + urlLanguage + (networkPaths['liquidtestnet'] || '/testnet')" ngbDropdownItem *ngIf="env.LIQUID_TESTNET_ENABLED" class="liquidtestnet" [class.active]="network.val === 'liquid'"><app-svg-images name="liquidtestnet" width="22" height="22" viewBox="0 0 125 125" style="width: 25px; height: 25px;" class="mainnet me-1"></app-svg-images> Liquid Testnet</a>
</div>
</div>

View file

@ -2,7 +2,7 @@
<div class="title-block">
<h1>{{ ordinal$ | async }}</h1>
<button [routerLink]="['/' | relativeUrl]" class="btn btn-sm float-right">&#10005;</button>
<button [routerLink]="['/' | relativeUrl]" class="btn btn-sm float-end">&#10005;</button>
</div>
<div class="clearfix"></div>

View file

@ -9,15 +9,15 @@
<ng-template #usernamenospace>&#64;{{ user.username }}</ng-template>
</strong>
</span>
<span class="badge mr-1 badge-og" *ngIf="user.ogRank">
<span class="badge me-1 badge-og" *ngIf="user.ogRank">
OG #{{ user.ogRank }}
</span>
@if (user.subscription_tag !== 'free') {
<span class="badge mr-1 badge-default" [class]="'badge-' + user.subscription_tag">
<span class="badge me-1 badge-default" [class]="'badge-' + user.subscription_tag">
{{ user.subscription_tag.toUpperCase() }}
</span>
} @else if (user.type === 'mining_pool') {
<span class="badge mr-1 badge-default" [class]="'badge-mining-pool'">
<span class="badge me-1 badge-default" [class]="'badge-mining-pool'">
MINING POOL
</span>
}

View file

@ -45,13 +45,14 @@
right: 0;
}
.sidenav a, button{
.sidenav a, .sidenav button{
text-decoration: none;
color: lightgray;
margin-left: 20px;
}
.sidenav a:hover {
color: white;
.sidenav a:hover, .sidenav button:hover, .sidenav button:focus-visible {
color: var(--fg);
}
.sidenav nav {
width: 100%;

View file

@ -27,7 +27,7 @@
<!-- pool distribution -->
<div class="col" style="margin-bottom: 1.47rem">
<div class="card">
<div class="card-body pl-2 pr-2">
<div class="card-body ps-2 pe-2">
<div class="mempool-graph">
<app-pool-ranking [height]="poolGraphHeight" [attr.data-cy]="'pool-distribution'" [widget]=true></app-pool-ranking>
</div>
@ -39,7 +39,7 @@
<!-- hashrate -->
<div class="col" style="margin-bottom: 1.47rem">
<div class="card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
<div class="card-body ps-lg-3 pe-lg-3 ps-2 pe-2">
<div class="fixed-mempool-graph">
<app-hashrate-chart [height]="hashrateGraphHeight" [attr.data-cy]="'hashrate-graph'" [widget]="true"></app-hashrate-chart>
</div>

View file

@ -9,11 +9,9 @@
[class.pull-right]="settings.pullRight" [class.dropdown-menu-right]="settings.pullRight" [style.max-height]="settings.maxHeight"
style="display: block; height: auto; overflow-y: auto;" (keydown.tab)="focusItem(1, $event)" (keydown.shift.tab)="focusItem(-1, $event)">
<div class="input-group search-container" *ngIf="settings.enableSearch && (renderFilteredOptions.length > 1 || filterControl.value.length > 0)">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">
<i class="fa fa-search" aria-hidden="true"></i>
</span>
</div>
<span class="input-group-text" id="basic-addon1">
<i class="fa fa-search" aria-hidden="true"></i>
</span>
<input type="text" class="form-control" ssAutofocus [formControl]="filterControl" [placeholder]="texts.searchPlaceholder"
class="form-control">
<div class="input-group-append" *ngIf="filterControl.value.length>0">

View file

@ -35,9 +35,9 @@
<div *ngFor="let contentType of inscriptionsData | keyvalue">
<div>
@if (contentType.key !== 'undefined') {
<span class="badge badge-ord mr-1">{{ contentType.value.count > 1 ? contentType.value.count + " " : "" }}{{ contentType.value?.tag || contentType.key }}</span>
<span class="badge badge-ord me-1">{{ contentType.value.count > 1 ? contentType.value.count + " " : "" }}{{ contentType.value?.tag || contentType.key }}</span>
} @else {
<span class="badge badge-ord mr-1" i18n="unknown">Unknown</span>
<span class="badge badge-ord me-1" i18n="unknown">Unknown</span>
}
<span class="badge badge-ord" *ngIf="contentType.value.totalSize > 0">{{ contentType.value.totalSize | bytes:2:'B':undefined:true }}</span>
<a *ngIf="contentType.value.delegate" [routerLink]="['/tx' | relativeUrl, contentType.value.delegate]">

View file

@ -20,12 +20,15 @@ a.disabled {
}
.badge-ord {
background-color: var(--grey);
--bs-btn-bg: var(--grey);
--bs-btn-border-color: transparent;
background-color: var(--bs-btn-bg);
border-color: var(--bs-btn-border-color);
position: relative;
top: -2px;
font-size: 81%;
&.primary {
background-color: var(--primary);
--bs-btn-bg: var(--primary);
}
}

View file

@ -34,43 +34,50 @@
<div class="card-header" *ngIf="!widget">
<div class="d-flex d-md-table-cell align-items-baseline">
<span i18n="mining.pools">Pools Ranking</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<form [formGroup]="radioGroupForm" class="formRadioGroup"
*ngIf="!widget && (miningStatsObservable$ | async) as stats">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 144" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'24h'" formControlName="dateSpan"> 24h
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 432" [class.active]="radioGroupForm.get('dateSpan').value === '3d'">
<input type="radio" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3d'" formControlName="dateSpan"> 3D
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 1008" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1w'" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 4320" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1m'" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 12960" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3m'" formControlName="dateSpan"> 3M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 25920" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'6m'" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 52560" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1y'" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 105120" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'2y'" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" *ngIf="stats.totalBlockCount >= 157680" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3y'" 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/mining/pools' | relativeUrl]" [attr.data-cy]="'all'" formControlName="dateSpan"><span i18n>All</span>
</label>
<form [formGroup]="radioGroupForm" class="formRadioGroup" *ngIf="!widget && (miningStatsObservable$ | async) as stats">
<div class="btn-group" role="group" name="radioBasic">
<ng-container *ngIf="stats.totalBlockCount >= 144">
<input type="radio" class="btn-check" id="mining-24h" [value]="'24h'" fragment="24h" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'24h'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-24h">24h</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 432">
<input type="radio" class="btn-check" id="mining-3d" [value]="'3d'" fragment="3d" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3d'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-3d">3D</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 1008">
<input type="radio" class="btn-check" id="mining-1w" [value]="'1w'" fragment="1w" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1w'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-1w">1W</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 4320">
<input type="radio" class="btn-check" id="mining-1m" [value]="'1m'" fragment="1m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1m'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-1m">1M</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 12960">
<input type="radio" class="btn-check" id="mining-3m" [value]="'3m'" fragment="3m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3m'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-3m">3M</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 25920">
<input type="radio" class="btn-check" id="mining-6m" [value]="'6m'" fragment="6m" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'6m'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-6m">6M</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 52560">
<input type="radio" class="btn-check" id="mining-1y" [value]="'1y'" fragment="1y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'1y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-1y">1Y</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 105120">
<input type="radio" class="btn-check" id="mining-2y" [value]="'2y'" fragment="2y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'2y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-2y">2Y</label>
</ng-container>
<ng-container *ngIf="stats.totalBlockCount >= 157680">
<input type="radio" class="btn-check" id="mining-3y" [value]="'3y'" fragment="3y" [routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'3y'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-3y">3Y</label>
</ng-container>
<input type="radio" class="btn-check" id="mining-all" [value]="'all'" fragment="all"[routerLink]="['/graphs/mining/pools' | relativeUrl]" [attr.data-cy]="'all'" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="mining-all"><span i18n>All</span></label>
</div>
</form>
</div>
@ -92,7 +99,7 @@
<th class="" i18n="mining.pool-name">Pool</th>
<th class="" *ngIf="['24h', '3d', '1w'].includes(this.miningWindowPreference)" i18n="mining.hashrate">Hashrate</th>
<th class="" i18n="master-page.blocks">Blocks</th>
<th *ngIf="auditAvailable" class="health text-right widget" [ngClass]="{'health-column': ['24h', '3d', '1w'].includes(this.miningWindowPreference)}" i18n="latest-blocks.avg_health"
<th *ngIf="auditAvailable" class="health text-end widget" [ngClass]="{'health-column': ['24h', '3d', '1w'].includes(this.miningWindowPreference)}" i18n="latest-blocks.avg_health"
i18n-ngbTooltip="latest-blocks.avg_health" ngbTooltip="Avg Health" placement="bottom" #health [disableTooltip]="!isEllipsisActive(health)">Avg Health</th>
<th *ngIf="auditAvailable" class="d-none d-sm-table-cell" i18n="mining.fees-per-block">Avg Block Fees</th>
<th class="d-none d-lg-table-cell" i18n="mining.empty-blocks">Empty Blocks</th>
@ -101,7 +108,7 @@
<tbody [attr.data-cy]="'pools-table'" *ngIf="(miningStatsObservable$ | async) as miningStats">
<tr *ngFor="let pool of miningStats.pools">
<td class="d-none d-md-table-cell">{{ pool.rank }}</td>
<td class="text-right">
<td class="text-end">
<img width="25" height="25" src="{{ pool.logo }}" [alt]="pool.name + ' mining pool logo'" onError="this.onerror=null; this.src = '/resources/mining-pools/default.svg'">
</td>
<td class="pool-name"><a [routerLink]="[('/mining/pool/' + pool.slug) | relativeUrl]">{{ pool.name }}</a></td>
@ -111,16 +118,16 @@
<td class="d-flex justify-content-center">
{{ pool.blockCount }}<span class="d-none d-md-table-cell">&nbsp;({{ pool.share }}%)</span>
</td>
<td *ngIf="auditAvailable" class="health text-right" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable, 'health-column': ['24h', '3d', '1w'].includes(this.miningWindowPreference)}">
<td *ngIf="auditAvailable" class="health text-end" [ngClass]="{'widget': widget, 'legacy': !indexingAvailable, 'health-column': ['24h', '3d', '1w'].includes(this.miningWindowPreference)}">
<a
class="health-badge badge"
[class.badge-success]="pool.avgMatchRate >= 99"
[class.badge-warning]="pool.avgMatchRate >= 75 && pool.avgMatchRate < 99"
[class.badge-danger]="pool.avgMatchRate < 75"
[class.bg-success]="pool.avgMatchRate >= 99"
[class.bg-warning]="pool.avgMatchRate >= 75 && pool.avgMatchRate < 99"
[class.bg-danger]="pool.avgMatchRate < 75"
*ngIf="pool.avgMatchRate != null; else nullHealth"
>{{ pool.avgMatchRate }}%</a>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
<span class="health-badge badge bg-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
<td *ngIf="auditAvailable" class="d-none d-sm-table-cell">
@ -135,7 +142,7 @@
</tr>
<tr style="border-top: 1px solid #555">
<td class="d-none d-md-table-cell"></td>
<td class="text-right"></td>
<td class="text-end"></td>
<td class=""><b i18n="mining.all-miners">All miners</b></td>
<td class="" *ngIf="'24h' === this.miningWindowPreference">{{ miningStats.lastEstimatedHashrate| number: '1.2-2' }} {{ miningStats.miningUnits.hashrateUnit }}</td>
<td class="" *ngIf="'3d' === this.miningWindowPreference">{{ miningStats.lastEstimatedHashrate3d | number: '1.2-2' }} {{ miningStats.miningUnits.hashrateUnit }}</td>

View file

@ -6,7 +6,7 @@
<div *ngIf="poolStats$ | async as poolStats; else loadingMain">
<div style="display:flex" class="mb-3">
<img width="50" height="50" src="{{ poolStats['logo'] }}" [alt]="poolStats.pool.name + ' mining pool logo'"
onError="this.onerror=null; this.src = '/resources/mining-pools/default.svg'" class="mr-3">
onError="this.onerror=null; this.src = '/resources/mining-pools/default.svg'" class="me-3">
<h1 class="m-0 pt-1 pt-md-0">{{ poolStats.pool.name }}</h1>
</div>
@ -68,7 +68,7 @@
<span class="label" i18n="mining.addresses">Addresses</span>
<div *ngIf="poolStats.pool.addresses.length else nodatamobile">
<button *ngIf="poolStats.pool.addresses.length >= 2" type="button"
class="btn btn-sm btn-primary float-right small-button mobile" (click)="collapse.toggle()"
class="btn btn-sm btn-primary float-end small-button mobile" (click)="collapse.toggle()"
[attr.aria-expanded]="!gfg" aria-controls="collapseExample">
<span *ngIf="gfg"><span i18n="show-all">Show all</span> ({{ poolStats.pool.addresses.length }})</span>
<span *ngIf="!gfg" i18n="hide">Hide</span>
@ -102,19 +102,19 @@
<table class="table table-xs table-data">
<thead>
<tr>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.reward">Reward</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.hashrate">Hashrate (24h)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="latest-blocks.avg_health" *ngIf="auditAvailable">Avg Health</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.reward">Reward</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.hashrate">Hashrate (24h)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="latest-blocks.avg_health" *ngIf="auditAvailable">Avg Health</th>
</tr>
</thead>
<tbody>
<td class="text-center"><app-amount [satoshis]="poolStats.totalReward" digitsInfo="1.0-0" [noFiat]="true" [ignoreViewMode]="true"></app-amount></td>
<td class="text-center">{{ poolStats.estimatedHashrate | amountShortener : 3 : 'H/s' : false : true }}</td>
<td class="text-center" *ngIf="auditAvailable; else emptyTd"><span class="health-badge badge" [class.badge-success]="poolStats.avgBlockHealth >= 99"
[class.badge-warning]="poolStats.avgBlockHealth >= 75 && poolStats.avgBlockHealth < 99" [class.badge-danger]="poolStats.avgBlockHealth < 75"
<td class="text-center" style="padding: 0.1rem;"><app-amount [satoshis]="poolStats.totalReward" digitsInfo="1.0-0" [noFiat]="true" [ignoreViewMode]="true"></app-amount></td>
<td class="text-center" style="padding: 0.1rem;">{{ poolStats.estimatedHashrate | amountShortener : 3 : 'H/s' : false : true }}</td>
<td class="text-center" style="padding: 0.1rem;" *ngIf="auditAvailable; else emptyTd"><span class="health-badge badge" [class.bg-success]="poolStats.avgBlockHealth >= 99"
[class.bg-warning]="poolStats.avgBlockHealth >= 75 && poolStats.avgBlockHealth < 99" [class.bg-danger]="poolStats.avgBlockHealth < 75"
*ngIf="poolStats.avgBlockHealth != null; else nullHealth">{{ poolStats.avgBlockHealth }}%</span>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
<span class="health-badge badge bg-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
</tbody>
@ -128,17 +128,17 @@
<table class="table table-xs table-data">
<thead>
<tr>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="24h">Blocks (24h)</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="1w">1w</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="all">All</th>
</tr>
</thead>
<tbody>
<td class="text-center">{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
<td class="text-center" style="padding: 0.1rem;">{{ formatNumber(poolStats.blockCount['24h'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['24h'], this.locale, '1.0-0') }}%)</td>
<td class="text-center">{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
<td class="text-center" style="padding: 0.1rem;">{{ formatNumber(poolStats.blockCount['1w'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['1w'], this.locale, '1.0-0') }}%)</td>
<td class="text-center">{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
<td class="text-center" style="padding: 0.1rem;">{{ formatNumber(poolStats.blockCount['all'], this.locale, '1.0-0') }} ({{ formatNumber(100 *
poolStats.blockShare['all'], this.locale, '1.0-0') }}%)</td>
</tbody>
</table>
@ -151,13 +151,13 @@
<table class="table table-xs table-data">
<thead>
<tr>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="1w">Out-of-band Fees (1w)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="1m">1m</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="all">All</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="1w">Out-of-band Fees (1w)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="1m">1m</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="all">All</th>
</tr>
</thead>
<tbody>
<td *ngFor="let total of oob" class="text-center clip"><app-amount [satoshis]="total.cost" [digitsInfo]="isMobile() ? '1.2-4' : '1.8-8'" [ignoreViewMode]="true"></app-amount></td>
<td *ngFor="let total of oob" class="text-center clip" style="padding: 0.1rem;"><app-amount [satoshis]="total.cost" [digitsInfo]="isMobile() ? '1.2-4' : '1.8-8'" [ignoreViewMode]="true"></app-amount></td>
</tbody>
</table>
</td>
@ -314,11 +314,11 @@
<th class="height" i18n="latest-blocks.height">Height</th>
<th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th>
<th class="mined" i18n="latest-blocks.mined">Mined</th>
<th class="coinbase text-left" i18n="latest-blocks.coinbasetag">Coinbase tag</th>
<th *ngIf="auditAvailable" class="health text-right" i18n="latest-blocks.health">Health</th>
<th class="reward text-right" i18n="latest-blocks.reward">Reward</th>
<th *ngIf="!auditAvailable" class="fees text-right" i18n="latest-blocks.fees">Fees</th>
<th class="txs text-right" i18n="dashboard.txs">TXs</th>
<th class="coinbase text-start" i18n="latest-blocks.coinbasetag">Coinbase tag</th>
<th *ngIf="auditAvailable" class="health text-end" i18n="latest-blocks.health">Health</th>
<th class="reward text-end" i18n="latest-blocks.reward">Reward</th>
<th *ngIf="!auditAvailable" class="fees text-end" i18n="latest-blocks.fees">Fees</th>
<th class="txs text-end" i18n="dashboard.txs">TXs</th>
<th class="size" i18n="latest-blocks.size">Size</th>
</thead>
<tbody [style]="isLoading ? 'opacity: 0.75' : ''">
@ -333,31 +333,31 @@
<app-time kind="since" [time]="block.timestamp" [fastRender]="true" [showTooltip]="true"></app-time>
</td>
<td class="coinbase">
<span class="badge badge-secondary scriptmessage longer">
<span class="badge bg-secondary scriptmessage longer">
{{ block.extras.coinbaseRaw | hex2ascii }}
</span>
</td>
<td *ngIf="auditAvailable" class="health text-right">
<td *ngIf="auditAvailable" class="health text-end">
<a
class="health-badge badge"
[class.badge-success]="block.extras.matchRate >= 99"
[class.badge-warning]="block.extras.matchRate >= 75 && block.extras.matchRate < 99"
[class.badge-danger]="block.extras.matchRate < 75"
[class.bg-success]="block.extras.matchRate >= 99"
[class.bg-warning]="block.extras.matchRate >= 75 && block.extras.matchRate < 99"
[class.bg-danger]="block.extras.matchRate < 75"
[routerLink]="block.extras.matchRate != null ? ['/block/' | relativeUrl, block.id] : null"
[state]="{ data: { block: block } }"
*ngIf="block.extras.matchRate != null; else nullHealth"
>{{ block.extras.matchRate }}%</a>
<ng-template #nullHealth>
<span class="health-badge badge badge-secondary" i18n="unknown">Unknown</span>
<span class="health-badge badge bg-secondary" i18n="unknown">Unknown</span>
</ng-template>
</td>
<td class="reward text-right">
<td class="reward text-end">
<app-amount [satoshis]="block.extras.reward" digitsInfo="1.2-2" [noFiat]="true" [ignoreViewMode]="true"></app-amount>
</td>
<td *ngIf="!auditAvailable" class="fees text-right">
<td *ngIf="!auditAvailable" class="fees text-end">
<app-amount [satoshis]="block.extras.totalFees" digitsInfo="1.2-2" [noFiat]="true" [ignoreViewMode]="true"></app-amount>
</td>
<td class="txs text-right">
<td class="txs text-end">
{{ block.tx_count | number }}
</td>
<td class="size">
@ -376,10 +376,10 @@
<th class="height" i18n="latest-blocks.height">Height</th>
<th class="timestamp" i18n="latest-blocks.timestamp">Timestamp</th>
<th class="mined" i18n="latest-blocks.mined">Mined</th>
<th class="coinbase text-left" i18n="latest-blocks.coinbasetag">Coinbase tag</th>
<th class="reward text-right" i18n="latest-blocks.reward">Reward</th>
<th class="fees text-right" i18n="latest-blocks.fees">Fees</th>
<th class="txs text-right" i18n="dashboard.txs">TXs</th>
<th class="coinbase text-start" i18n="latest-blocks.coinbasetag">Coinbase tag</th>
<th class="reward text-end" i18n="latest-blocks.reward">Reward</th>
<th class="fees text-end" i18n="latest-blocks.fees">Fees</th>
<th class="txs text-end" i18n="dashboard.txs">TXs</th>
<th class="size" i18n="latest-blocks.size">Size</th>
</thead>
<tbody>
@ -396,16 +396,16 @@
<td class="coinbase">
<span class="skeleton-loader"></span>
</td>
<td class="reward text-right">
<td class="reward text-end">
<span class="skeleton-loader"></span>
</td>
<td class="fees text-right">
<td class="fees text-end">
<span class="skeleton-loader"></span>
</td>
<td class="txs text-right">
<td class="txs text-end">
<span class="skeleton-loader"></span>
</td>
<td class="size text-right">
<td class="size text-end">
<span class="skeleton-loader"></span>
</td>
</tr>
@ -419,13 +419,13 @@
<ng-template #loadingMain>
<div>
<div class="mb-3" style="display:flex; position: relative">
<div class="skeleton-loader mr-3" style="width: 50px; height: 50px"></div>
<div class="skeleton-loader me-3" style="width: 50px; height: 50px"></div>
<h1 class="m-0 pt-1 pt-md-0">
<div class="skeleton-loader" style="position: absolute; top: 32%; width: 150px; height: 20px"></div>
</h1>
</div>
<div class="box">
<div class="box pool-details">
<div class="row">
<div class="col-lg-6">
@ -451,8 +451,8 @@
<!-- Addresses desktop -->
<tr *ngIf="!isMobile()" class="taller-row">
<td class="label" i18n="mining.addresses">Addresses</td>
<td style="vertical-align: middle;">
<td class="label addresses" i18n="mining.addresses">Addresses</td>
<td style="padding-top: 25px;">
<div class="skeleton-loader"></div>
<div #collapse="ngbCollapse" [(ngbCollapse)]="gfg">
<div class="skeleton-loader"></div>
@ -485,19 +485,19 @@
<table class="table table-xs table-data text-center">
<thead>
<tr>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.total-reward">Reward</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.total-reward">Reward</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th>
</tr>
</thead>
<tbody>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center" *ngIf="auditAvailable">
<td class="text-center" style="padding: 0.1rem;" *ngIf="auditAvailable; else emptyTd">
<div class="skeleton-loader data"></div>
</td>
</tbody>
@ -510,19 +510,19 @@
<table class="table table-xs table-data text-center">
<thead>
<tr>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.total-reward">Reward</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.total-reward">Reward</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.estimated">Hashrate (24h)</th>
<th scope="col" class="data-title clip text-center" style="width: 33%; padding: 0.1rem;" i18n="mining.luck" *ngIf="auditAvailable">Avg Health</th>
</tr>
</thead>
<tbody>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center" *ngIf="auditAvailable">
<td class="text-center" style="padding: 0.1rem;" *ngIf="auditAvailable; else emptyTd">
<div class="skeleton-loader data"></div>
</td>
</tbody>
@ -536,19 +536,19 @@
<table class="table table-xs table-data text-center">
<thead>
<tr>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="24h">Blocks (24h)</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="1w">1w</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="all">All</th>
</tr>
</thead>
<tbody>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
</tbody>
@ -561,19 +561,19 @@
<table class="table table-xs table-data text-center">
<thead>
<tr>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="24h">Blocks (24h)</th>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="1w">1w</th>
<th scope="col" class="data-title text-center" style="width: 33%" i18n="all">All</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="24h">Blocks (24h)</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="1w">1w</th>
<th scope="col" class="data-title text-center" style="width: 33%; padding: 0.1rem;" i18n="all">All</th>
</tr>
</thead>
<tbody>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
<td class="text-center">
<td class="text-center" style="padding: 0.1rem;">
<div class="skeleton-loader data"></div>
</td>
</tbody>

View file

@ -165,6 +165,7 @@ div.scrollable {
}
.skeleton-loader.data {
max-width: 70px;
background-color: var(--skeleton-bg);
}
@ -283,4 +284,8 @@ div.scrollable {
display: block;
text-decoration: none;
color: inherit;
}
.health-badge {
padding: 0.25em 0.4em;
}

View file

@ -22,7 +22,7 @@
<div class="card-header mb-0 mb-md-4" [style]="widget ? 'display:none' : ''">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="price-chart.title">Bitcoin Price</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart()">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>

View file

@ -9,7 +9,7 @@
<br><br>
<div class="text-left">
<div class="text-start">
<h4>USE YOUR OWN SELF-HOSTED MEMPOOL EXPLORER</h4>

View file

@ -1,17 +1,17 @@
<div class="container-xl">
<h1 class="text-left" i18n="shared.broadcast-transaction|Broadcast Transaction">Broadcast Transaction</h1>
<h1 class="text-start" i18n="shared.broadcast-transaction|Broadcast Transaction">Broadcast Transaction</h1>
<form [formGroup]="pushTxForm" (submit)="pushTxForm.valid && postTx()" novalidate>
<div class="mb-3">
<textarea formControlName="txHash" class="form-control" rows="5" i18n-placeholder="transaction.hex" placeholder="Transaction hex"></textarea>
</div>
<button [disabled]="isLoading" type="submit" class="btn btn-primary mr-2" i18n="shared.broadcast-transaction|Broadcast Transaction">Broadcast Transaction</button>
<button [disabled]="isLoading" type="submit" class="btn btn-primary me-2" i18n="shared.broadcast-transaction|Broadcast Transaction">Broadcast Transaction</button>
<p class="red-color d-inline">{{ error }}</p> <a *ngIf="txId" [routerLink]="['/tx/' | relativeUrl, txId]">{{ txId }}</a>
</form>
@if (network === '' || network === 'testnet' || network === 'testnet4' || network === 'signet') {
<br>
<h1 class="text-left" style="margin-top: 1rem;" i18n="shared.submit-transactions|Submit Package">Submit Package</h1>
<h1 class="text-start" style="margin-top: 1rem;" i18n="shared.submit-transactions|Submit Package">Submit Package</h1>
<form [formGroup]="submitTxsForm" (submit)="submitTxsForm.valid && submitTxs()" novalidate>
<div class="mb-3">
@ -24,7 +24,7 @@
<input type="number" class="form-control input-dark" formControlName="maxburnamount" id="maxburnamount"
[value]="0" placeholder="0 sat" [class]="{invalid: invalidMaxburnamount}">
<br>
<button [disabled]="isLoadingPackage" type="submit" class="btn btn-primary mr-2" i18n="shared.submit-transactions|Submit Package">Submit Package</button>
<button [disabled]="isLoadingPackage" type="submit" class="btn btn-primary me-2" i18n="shared.submit-transactions|Submit Package">Submit Package</button>
<p *ngIf="errorPackage" class="red-color d-inline">{{ errorPackage }}</p>
<p *ngIf="packageMessage" class="d-inline">{{ packageMessage }}</p>

View file

@ -1,5 +1,5 @@
<div [formGroup]="rateUnitForm" class="text-small text-center">
<select formControlName="rateUnits" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" style="width: 95px;" (change)="changeUnits()">
<select formControlName="rateUnits" class="form-select form-select-sm form-control-secondary form-control mx-auto" style="width: 95px;" (change)="changeUnits()">
<option *ngFor="let unit of units" [value]="unit.name">{{ unit.label }}</option>
</select>
</div>

View file

@ -1,14 +1,14 @@
<div class="container-xl" style="min-height: 335px">
<h1 class="float-left" i18n="page.rbf-replacements">RBF Replacements</h1>
<div *ngIf="isLoading" class="spinner-border ml-3" role="status"></div>
<h1 class="float-start" i18n="page.rbf-replacements">RBF Replacements</h1>
<div *ngIf="isLoading" class="spinner-border ms-3" role="status"></div>
<div class="mode-toggle float-right">
<div class="mode-toggle float-end">
<form class="formRadioGroup">
<div class="btn-group btn-group-toggle" name="radioBasic">
<label class="btn btn-primary btn-sm" [class.active]="!fullRbf">
<input type="radio" [value]="'All'" fragment="" [routerLink]="[]"><span i18n="all">All</span></label>
<input type="radio" class="btn-check" [value]="'All'" fragment="" [routerLink]="[]"><span i18n="all">All</span></label>
<label class="btn btn-primary btn-sm" [class.active]="fullRbf">
<input type="radio" [value]="'Full RBF'" fragment="fullrbf" [routerLink]="[]" i18n="transaction.full-rbf">Full RBF</label>
<input type="radio" class="btn-check" [value]="'Full RBF'" fragment="fullrbf" [routerLink]="[]" i18n="transaction.full-rbf">Full RBF</label>
</div>
</form>
</div>
@ -20,8 +20,8 @@
<div *ngFor="let tree of trees" class="tree">
<p class="info">
<span class="type">
<span *ngIf="tree.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="tree.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="tree.mined" class="badge bg-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="tree.fullRbf" class="badge bg-info" i18n="transaction.full-rbf">Full RBF</span>
</span>
<app-time kind="since" [time]="tree.time" [showTooltip]="true"></app-time>
</p>

View file

@ -32,10 +32,10 @@
<tr>
<td class="td-width" i18n="transaction.status|Transaction Status">Status</td>
<td>
<span *ngIf="rbfInfo.tx.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="rbfInfo.tx.rbf; else rbfDisabled" class="badge badge-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
<ng-template #rbfDisabled><span class="badge badge-danger mr-1"><del i18n="tx-features.tag.rbf|RBF">RBF</del></span></ng-template>
<span *ngIf="rbfInfo.tx.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="rbfInfo.tx.fullRbf" class="badge bg-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="rbfInfo.tx.rbf; else rbfDisabled" class="badge bg-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
<ng-template #rbfDisabled><span class="badge bg-danger me-1"><del i18n="tx-features.tag.rbf|RBF">RBF</del></span></ng-template>
<span *ngIf="rbfInfo.tx.mined" class="badge bg-success" i18n="transaction.rbf.mined">Mined</span>
</td>
</tr>
</tbody>

View file

@ -1,11 +1,11 @@
<form [class]="{hamburgerOpen: hamburgerOpen}" [formGroup]="searchForm" (submit)="searchForm.valid && search()" novalidate>
<div class="d-flex">
<div class="search-box-container mr-2">
<div class="search-box-container me-2">
<input #searchInput (focus)="focus$.next($any($event).target.value)" (click)="click$.next($any($event).target.value)" formControlName="searchText" type="text" class="form-control" i18n-placeholder="search-form.searchbar-placeholder" placeholder="Explore the full Bitcoin ecosystem">
<app-search-results #searchResults [hidden]="dropdownHidden" [results]="typeAhead$ | async" (selectedResult)="selectedResult($event)"></app-search-results>
</div>
<div>
<button [disabled]="isSearching" type="submit" class="btn btn-block btn-purple">
<button [disabled]="isSearching" type="submit" class="btn btn-purple search-submit">
<fa-icon *ngIf="!(isTypeaheading$ | async) else searchLoading" [icon]="['fas', 'search']" [fixedWidth]="true" i18n-title="search-form.search-title" title="Search"></fa-icon>
</button>
</div>

View file

@ -29,7 +29,7 @@ form {
}
}
.btn-block {
.search-submit {
width: 62px;
}

View file

@ -1,5 +1,5 @@
<div class="container-xl" style="min-height: 335px" [ngClass]="{'widget': widget, 'full-height': !widget}">
<div *ngIf="!widget" class="float-left" style="display: flex; width: 100%; align-items: center;">
<div *ngIf="!widget" class="float-start" style="display: flex; width: 100%; align-items: center;">
<h1>
<img src="/resources/cubo.svg" style="width: 1.1em; height: 1.1em; margin-right: 0.1em; transform: translateY(-0.1em);">
{{ label }}
@ -12,7 +12,7 @@
@if (isLoading) {
loading!
<div class="spinner-wrapper">
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
<div class="ms-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
} @else if (error || !verified.length) {
<div class="error-wrapper">
@ -31,21 +31,21 @@
</div>
<table class="table table-borderless table-fixed">
<thead>
<th class="student text-left sortable" [ngClass]="{'widget': widget}" (click)="$event.stopPropagation(); sortBy('student_name')" style="cursor: pointer;">
<th class="student text-start sortable" [ngClass]="{'widget': widget}" (click)="$event.stopPropagation(); sortBy('student_name')" style="cursor: pointer;">
<span i18n="simpleproof.student_name">Student Name</span>
<div class="sort-icons ml-1">
<div class="sort-icons ms-1">
<fa-icon [icon]="['fas', 'caret-up']" [fixedWidth]="true" [class.active]="sortField === 'student_name' && sortDirection === 'asc'" (click)="$event.stopPropagation(); sortBy('student_name', 'asc')"></fa-icon>
<fa-icon [icon]="['fas', 'caret-down']" [fixedWidth]="true" [class.active]="sortField === 'student_name' && sortDirection === 'desc'" (click)="$event.stopPropagation(); sortBy('student_name', 'desc')"></fa-icon>
</div>
</th>
<th class="id text-left sortable" [ngClass]="{'widget': widget}" (click)="$event.stopPropagation(); sortBy('id_code')" style="cursor: pointer;">
<th class="id text-start sortable" [ngClass]="{'widget': widget}" (click)="$event.stopPropagation(); sortBy('id_code')" style="cursor: pointer;">
<span i18n="simpleproof.id_code">ID</span>
<div class="sort-icons ml-1">
<div class="sort-icons ms-1">
<fa-icon [icon]="['fas', 'caret-up']" [fixedWidth]="true" [class.active]="sortField === 'id_code' && sortDirection === 'asc'" (click)="$event.stopPropagation(); sortBy('id_code', 'asc')"></fa-icon>
<fa-icon [icon]="['fas', 'caret-down']" [fixedWidth]="true" [class.active]="sortField === 'id_code' && sortDirection === 'desc'" (click)="$event.stopPropagation(); sortBy('id_code', 'desc')"></fa-icon>
</div>
</th>
<th class="proof text-right" [ngClass]="{'widget': widget}" i18n="simpleproof.proof">Proof</th>
<th class="proof text-end" [ngClass]="{'widget': widget}" i18n="simpleproof.proof">Proof</th>
</thead>
<tbody *ngIf="verifiedPage; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngIf="widget" class="search-row">
@ -63,11 +63,11 @@
</tr>
<tr *ngFor="let item of verifiedPage">
@if (widget) {
<td class="student text-left" [class]="widget ? 'widget' : ''">
<td class="student text-start" [class]="widget ? 'widget' : ''">
@if (item.sanitized_download_url) {
<a [href]="item.sanitized_download_url" target="_blank">
<span>{{ item.student_name }}</span>
<span class="icon ml-2">
<span class="icon ms-2">
<fa-icon [icon]="['fas', 'file-pdf']" [fixedWidth]="true"></fa-icon>
</span>
</a>
@ -76,12 +76,12 @@
}
</td>
} @else {
<td class="student text-left" [class]="widget ? 'widget' : ''">{{ item.student_name }}</td>
<td class="id text-left" [class]="widget ? 'widget' : ''">
<td class="student text-start" [class]="widget ? 'widget' : ''">{{ item.student_name }}</td>
<td class="id text-start" [class]="widget ? 'widget' : ''">
@if (item.sanitized_download_url) {
<a [href]="item.sanitized_download_url" target="_blank">
<span>{{ item.id_code }}</span>
<span class="icon ml-2">
<span class="icon ms-2">
<fa-icon [icon]="['fas', 'file-pdf']" [fixedWidth]="true"></fa-icon>
</span>
</a>
@ -90,8 +90,8 @@
}
</td>
}
<td class="proof text-right" [class]="widget ? 'widget' : ''">
<a [href]="item.sanitized_simpleproof_url" target="_blank" class="badge badge-primary badge-verify" style="font-size: 1.035em;">
<td class="proof text-end" [class]="widget ? 'widget' : ''">
<a [href]="item.sanitized_simpleproof_url" target="_blank" class="badge bg-primary badge-verify" style="font-size: 1.035em;">
<span class="icon">
<img class="icon-img" src="/resources/sp.svg">
</span>
@ -103,13 +103,13 @@
<ng-template #skeleton>
<tbody>
<tr *ngFor="let item of [].constructor(itemsPerPage)">
<td class="filename text-left" [ngClass]="{'widget': widget}">
<td class="filename text-start" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="id text-left" [ngClass]="{'widget': widget}">
<td class="id text-start" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="proof text-right" [ngClass]="{'widget': widget}">
<td class="proof text-end" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
</tr>
@ -117,7 +117,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget" class="pagination-container float-end mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="verified.length" [rotate]="true" [maxSize]="paginationMaxSize" [pageSize]="itemsPerPage" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -1,5 +1,5 @@
<div class="container-xl" style="min-height: 335px" [ngClass]="{'widget': widget, 'full-height': !widget}">
<div *ngIf="!widget" class="float-left" style="display: flex; width: 100%; align-items: center;">
<div *ngIf="!widget" class="float-start" style="display: flex; width: 100%; align-items: center;">
<h1>{{ label }}</h1>
<div *ngIf="!widget && isLoading" class="spinner-border" role="status"></div>
</div>
@ -9,7 +9,7 @@
@if (isLoading) {
loading!
<div class="spinner-wrapper">
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
<div class="ms-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
} @else if (error || !verified.length) {
<div class="error-wrapper">
@ -19,20 +19,20 @@
<div style="min-height: 295px">
<table class="table table-borderless" [class.table-fixed]="widget">
<thead>
<th class="filename text-left" [ngClass]="{'widget': widget}" i18n="simpleproof.filename">Filename</th>
<th class="hash text-left" [ngClass]="{'widget': widget}" i18n="simpleproof.hash">Hash</th>
<th class="verified text-right" [ngClass]="{'widget': widget}" i18n="simpleproof.verified">Verified</th>
<th class="proof text-right" [ngClass]="{'widget': widget}" i18n="simpleproof.proof">Proof</th>
<th class="filename text-start" [ngClass]="{'widget': widget}" i18n="simpleproof.filename">Filename</th>
<th class="hash text-start" [ngClass]="{'widget': widget}" i18n="simpleproof.hash">Hash</th>
<th class="verified text-end" [ngClass]="{'widget': widget}" i18n="simpleproof.verified">Verified</th>
<th class="proof text-end" [ngClass]="{'widget': widget}" i18n="simpleproof.proof">Proof</th>
</thead>
<tbody *ngIf="verifiedPage; else skeleton" [style]="isLoading ? 'opacity: 0.75' : ''">
<tr *ngFor="let item of verifiedPage">
<td class="filename text-left" [class]="widget ? 'widget' : ''">{{ item.file_name }}</td>
<td class="hash text-left" [class]="widget ? 'widget' : ''">{{ item.sha256 }}</td>
<td class="verified text-right" [class]="widget ? 'widget' : ''">
<td class="filename text-start" [class]="widget ? 'widget' : ''">{{ item.file_name }}</td>
<td class="hash text-start" [class]="widget ? 'widget' : ''">{{ item.sha256 }}</td>
<td class="verified text-end" [class]="widget ? 'widget' : ''">
<app-timestamp [unixTime]="item.block_time" [customFormat]="'yyyy-MM-dd'" [hideTimeSince]="true"></app-timestamp>
</td>
<td class="proof text-right" [class]="widget ? 'widget' : ''">
<a [href]="item.sanitized_url" target="_blank" class="badge badge-primary badge-verify">
<td class="proof text-end" [class]="widget ? 'widget' : ''">
<a [href]="item.sanitized_url" target="_blank" class="badge bg-primary badge-verify">
<span class="icon">
<img class="icon-img" src="/resources/sp.svg">
</span>
@ -44,16 +44,16 @@
<ng-template #skeleton>
<tbody>
<tr *ngFor="let item of [].constructor(itemsPerPage)">
<td class="filename text-left" [ngClass]="{'widget': widget}">
<td class="filename text-start" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="hash text-left" [ngClass]="{'widget': widget}">
<td class="hash text-start" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="verified text-right" [ngClass]="{'widget': widget}">
<td class="verified text-end" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
<td class="proof text-right" [ngClass]="{'widget': widget}">
<td class="proof text-end" [ngClass]="{'widget': widget}">
<span class="skeleton-loader" style="max-width: 75px"></span>
</td>
</tr>
@ -61,7 +61,7 @@
</ng-template>
</table>
<ngb-pagination *ngIf="!widget" class="pagination-container float-right mt-2" [class]="isLoading ? 'disabled' : ''"
<ngb-pagination *ngIf="!widget" class="pagination-container float-end mt-2" [class]="isLoading ? 'disabled' : ''"
[collectionSize]="verified.length" [rotate]="true" [maxSize]="paginationMaxSize" [pageSize]="itemsPerPage" [(page)]="page"
(pageChange)="pageChange(page)" [boundaryLinks]="true" [ellipses]="false">
</ngb-pagination>

View file

@ -1,6 +1,6 @@
<div class="container-xl" style="min-height: 335px">
<h1 class="float-left"><span i18n="page.recent-stale-chain-tips">Recent Stale Chain Tips</span><span class="badge badge-pill badge-warning beta" i18n="beta">beta</span></h1>
<div *ngIf="isLoading" class="spinner-border ml-3" role="status"></div>
<h1 class="float-start"><span i18n="page.recent-stale-chain-tips">Recent Stale Chain Tips</span><span class="badge rounded-pill bg-warning beta" i18n="beta">beta</span></h1>
<div *ngIf="isLoading" class="spinner-border ms-3" role="status"></div>
<div class="clearfix"></div>
@ -11,19 +11,19 @@
<span class="height"><a [routerLink]="[('/block/' + (chainTip.canonical?.id || chainTip.height)) | relativeUrl]">{{ chainTip.height }}</a></span>
<span class="badges">
<span class="type" [ngSwitch]="chainTip.status">
<span *ngSwitchCase="'headers-only'" class="badge badge-info" i18n="chain-tips.headers-only">Headers Only</span>
<span *ngSwitchCase="'valid-headers'" class="badge badge-info" i18n="chain-tips.valid-headers">Valid Headers</span>
<span *ngSwitchCase="'valid-fork'" class="badge badge-info" i18n="chain-tips.valid-fork">Valid Fork</span>
<span *ngSwitchCase="'invalid'" class="badge badge-info" i18n="chain-tips.invalid">Invalid</span>
<span *ngSwitchCase="'headers-only'" class="badge bg-info" i18n="chain-tips.headers-only">Headers Only</span>
<span *ngSwitchCase="'valid-headers'" class="badge bg-info" i18n="chain-tips.valid-headers">Valid Headers</span>
<span *ngSwitchCase="'valid-fork'" class="badge bg-info" i18n="chain-tips.valid-fork">Valid Fork</span>
<span *ngSwitchCase="'invalid'" class="badge bg-info" i18n="chain-tips.invalid">Invalid</span>
<span *ngSwitchDefault>{{ chainTip.status }}</span>
</span>
<span class="badge badge-secondary depth-badge" i18n="chain-tips.depth">Depth {{ chainTip.branchlen + 1 }}</span>
<span class="badge bg-secondary depth-badge" i18n="chain-tips.depth">Depth {{ chainTip.branchlen + 1 }}</span>
</span>
</p>
<div class="stale-tip-wrapper">
<div class="block-comparison">
<div class="block-column stale">
<div class="block-label" i18n="chain-tips.stale-block"><span class="badge badge-secondary">Stale</span></div>
<div class="block-label" i18n="chain-tips.stale-block"><span class="badge bg-secondary">Stale</span></div>
<div class="block-wrapper">
<div class="bitcoin-block mined-block stale-block" [style.background]="getBlockGradient(chainTip.stale)" [routerLink]="[('/block/' + chainTip.stale.id) | relativeUrl]"></div>
<div class="block-body">
@ -70,7 +70,7 @@
<div class="vs-label">vs</div>
<div class="block-column canonical">
<div class="block-label" i18n="chain-tips.winning-block"><span class="badge badge-success">Winning</span></div>
<div class="block-label" i18n="chain-tips.winning-block"><span class="badge bg-success">Winning</span></div>
<div class="bitcoin-block mined-block canonical-block" [style.background]="getBlockGradient(chainTip.canonical)" [routerLink]="[('/block/' + chainTip.canonical.id) | relativeUrl]">
<div class="block-body">
<div *ngIf="chainTip.canonical?.extras; else emptyCanonicalBlockFees" class="fees">

View file

@ -5,7 +5,7 @@
<div class="card-header">
<div class="d-flex d-md-block align-items-baseline">
<span i18n="statistics.memory-by-vBytes">Mempool by vBytes (sat/vByte)</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart('mempool')">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart('mempool')">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
@ -18,44 +18,31 @@
</a>
</div>
<div class="btn-toggle-rows" name="radioBasic">
<div class="btn-group btn-group-toggle">
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '2h'">
<input type="radio" [value]="'2h'" [routerLink]="['/graphs' | relativeUrl]" fragment="2h" formControlName="dateSpan"> 2H
(LIVE)
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '24h'">
<input type="radio" [value]="'24h'" [routerLink]="['/graphs' | relativeUrl]" fragment="24h" formControlName="dateSpan">
24H
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1w'">
<input type="radio" [value]="'1w'" [routerLink]="['/graphs' | relativeUrl]" fragment="1w" formControlName="dateSpan"> 1W
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1m'">
<input type="radio" [value]="'1m'" [routerLink]="['/graphs' | relativeUrl]" fragment="1m" formControlName="dateSpan"> 1M
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3m'">
<input type="radio" [value]="'3m'" [routerLink]="['/graphs' | relativeUrl]" fragment="3m" formControlName="dateSpan"> 3M
</label>
<div class="btn-group" role="group">
<input type="radio" class="btn-check" id="dateSpan-2h" [value]="'2h'" [routerLink]="['/graphs' | relativeUrl]" fragment="2h" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-2h">2H (LIVE)</label>
<input type="radio" class="btn-check" id="dateSpan-24h" [value]="'24h'" [routerLink]="['/graphs' | relativeUrl]" fragment="24h" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-24h">24H</label>
<input type="radio" class="btn-check" id="dateSpan-1w" [value]="'1w'" [routerLink]="['/graphs' | relativeUrl]" fragment="1w" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-1w">1W</label>
<input type="radio" class="btn-check" id="dateSpan-1m" [value]="'1m'" [routerLink]="['/graphs' | relativeUrl]" fragment="1m" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-1m">1M</label>
<input type="radio" class="btn-check" id="dateSpan-3m" [value]="'3m'" [routerLink]="['/graphs' | relativeUrl]" fragment="3m" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-3m">3M</label>
</div>
<div class="btn-group btn-group-toggle">
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '6m'">
<input type="radio" [value]="'6m'" [routerLink]="['/graphs' | relativeUrl]" fragment="6m" formControlName="dateSpan"> 6M
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '1y'">
<input type="radio" [value]="'1y'" [routerLink]="['/graphs' | relativeUrl]" fragment="1y" formControlName="dateSpan"> 1Y
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '2y'">
<input type="radio" [value]="'2y'" [routerLink]="['/graphs' | relativeUrl]" fragment="2y" formControlName="dateSpan"> 2Y
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '3y'">
<input type="radio" [value]="'3y'" [routerLink]="['/graphs' | relativeUrl]" fragment="3y" formControlName="dateSpan"> 3Y
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === '4y'">
<input type="radio" [value]="'4y'" [routerLink]="['/graphs' | relativeUrl]" fragment="4y" formControlName="dateSpan"> 4Y
</label>
<label class="btn btn-primary btn-sm" [class.active]="radioGroupForm.get('dateSpan').value === 'all'">
<input type="radio" [value]="'all'" [routerLink]="['/graphs' | relativeUrl]" fragment="all" formControlName="dateSpan"><span i18n="all">All</span>
</label>
<div class="btn-group" role="group">
<input type="radio" class="btn-check" id="dateSpan-6m" [value]="'6m'" [routerLink]="['/graphs' | relativeUrl]" fragment="6m" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-6m">6M</label>
<input type="radio" class="btn-check" id="dateSpan-1y" [value]="'1y'" [routerLink]="['/graphs' | relativeUrl]" fragment="1y" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-1y">1Y</label>
<input type="radio" class="btn-check" id="dateSpan-2y" [value]="'2y'" [routerLink]="['/graphs' | relativeUrl]" fragment="2y" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-2y">2Y</label>
<input type="radio" class="btn-check" id="dateSpan-3y" [value]="'3y'" [routerLink]="['/graphs' | relativeUrl]" fragment="3y" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-3y">3Y</label>
<input type="radio" class="btn-check" id="dateSpan-4y" [value]="'4y'" [routerLink]="['/graphs' | relativeUrl]" fragment="4y" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-4y">4Y</label>
<input type="radio" class="btn-check" id="dateSpan-all" [value]="'all'" [routerLink]="['/graphs' | relativeUrl]" fragment="all" formControlName="dateSpan">
<label class="btn btn-primary btn-sm" for="dateSpan-all"><span i18n="all">All</span></label>
</div>
</div>
<div class="small-buttons">
@ -108,12 +95,12 @@
<div class="vbytes-title">
<div>
<span i18n="statistics.transaction-vbytes-per-second">Transaction vBytes per second (vB/s)</span>
<button class="btn p-0 pl-2" style="margin: 0 0 4px 0px" (click)="onSaveChart('incoming')">
<button class="btn p-0 ps-2" style="margin: 0 0 4px 0px" (click)="onSaveChart('incoming')">
<fa-icon [icon]="['fas', 'download']" [fixedWidth]="true"></fa-icon>
</button>
</div>
<div class="form-check">
<input style="margin-top: 9px" class="form-check-input" type="checkbox" [checked]="outlierCappingEnabled" id="hide-outliers" (change)="onOutlierToggleChange($event)">
<input style="margin-top: 6px" class="form-check-input" type="checkbox" [checked]="outlierCappingEnabled" id="hide-outliers" (change)="onOutlierToggleChange($event)">
<label class="form-check-label" for="hide-outliers">
<small i18n="statistics.cap-outliers">Cap outliers</small>
</label>

View file

@ -153,7 +153,6 @@
width: 50%;
flex-grow: 1;
flex-shrink: 1;
margin: 1px 0;
margin-right: 0.5rem;
@media (min-width: 830px) {
width: auto;
@ -196,11 +195,11 @@
}
@media (min-width: 500px) {
.btn-group:first-child > .btn:last-child {
.btn-group:first-child > .btn:last-of-type {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.btn-group:last-child > .btn:first-child {
.btn-group:last-child > .btn:first-of-type {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
@ -209,16 +208,16 @@
@media (max-width: 499px) {
flex-direction: column;
.btn-group:first-child > .btn:first-child {
.btn-group:first-child > .btn:first-of-type {
border-bottom-left-radius: 0;
}
.btn-group:first-child > .btn:last-child {
.btn-group:first-child > .btn:last-of-type {
border-bottom-right-radius: 0;
}
.btn-group:last-child > .btn:first-child {
.btn-group:last-child > .btn:first-of-type {
border-top-left-radius: 0;
}
.btn-group:last-child > .btn:last-child {
.btn-group:last-child > .btn:last-of-type {
border-top-right-radius: 0;
}
}

View file

@ -1,5 +1,5 @@
<div class="container-xl" style="min-height: 335px">
<h1 class="float-left" i18n="master-page.blocks">Stratum Jobs</h1>
<h1 class="float-start" i18n="master-page.blocks">Stratum Jobs</h1>
<div class="clearfix"></div>

View file

@ -9,7 +9,7 @@
<br><br>
<div class="text-left">
<div class="text-start">
<p *ngIf="officialMempoolSpace">The <a href="https://mempool.space/">mempool.space</a> website, the <a href="https://liquid.network/">liquid.network</a> website, the <a href="https://bitcoin.gob.sv/">bitcoin.gob.sv</a> website, their associated API services, and related network and server infrastructure (collectively, the "Website") are operated by Mempool Holdings S.A. de C.V. in El Salvador ("Mempool", "We", or "Us") and self-hosted from <a href="https://bgp.tools/as/142052#connectivity">AS142052</a>.</p>

View file

@ -1,6 +1,6 @@
<div class="container-xl">
<div style="display: flex; width: 100%; align-items: center; flex-wrap: wrap;">
<h1 class="text-left" i18n="shared.test-transactions|Test Transactions">Test Transactions</h1>
<h1 class="text-start" i18n="shared.test-transactions|Test Transactions">Test Transactions</h1>
<app-svg-images name="blocks-3-2" style="width: 275px; max-width: 90%; margin-top: -9px"></app-svg-images>
</div>
@ -13,7 +13,7 @@
<input type="number" class="form-control input-dark" formControlName="maxfeerate" id="maxfeerate"
[value]="10000" placeholder="10,000 s/vb" [class]="{invalid: invalidMaxfeerate}">
<br>
<button [disabled]="isLoading" type="submit" class="btn btn-primary mr-2" i18n="shared.test-transactions|Test Transactions">Test Transactions</button>
<button [disabled]="isLoading" type="submit" class="btn btn-primary me-2" i18n="shared.test-transactions|Test Transactions">Test Transactions</button>
<p class="red-color d-inline">{{ error }}</p>
</form>

View file

@ -1,5 +1,5 @@
<div [formGroup]="themeForm" class="text-small text-center">
<select formControlName="theme" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" (change)="changeTheme()">
<select formControlName="theme" class="form-select form-select-sm form-control-secondary form-control mx-auto" (change)="changeTheme()">
<option value="default">wiz</option>
<option value="contrast">BlueMatt</option>
<option value="softsimon">softsimon</option>

View file

@ -1,7 +1,7 @@
.custom-select {
width: 100px;
.form-select {
width: 108px;
}
.custom-select:disabled {
.form-select:disabled {
opacity: 0.6;
}

View file

@ -1,5 +1,5 @@
<div [formGroup]="timezoneForm" class="text-small text-center" style="overflow-x: hidden;">
<select formControlName="mode" class="custom-select custom-select-sm form-control-secondary form-control mx-auto" style="width: 110px;" (change)="changeMode()">
<select formControlName="mode" class="form-select form-select-sm form-control-secondary form-control mx-auto" style="width: 110px;" (change)="changeMode()">
<option value="local">UTC{{ localTimezoneOffset !== '+0' ? localTimezoneOffset : '' }} {{ localTimezoneName ? '- ' + localTimezoneName : '' }}</option>
<option value="+0" *ngIf="localTimezoneOffset !== '+0'">UTC - Greenwich Mean Time (GMT)</option>
<option disabled>────</option>

View file

@ -18,13 +18,13 @@
}
@if (!enterpriseInfo || !enterpriseInfo.dualLogo) {
<div [ngSwitch]="network" class="network-label">
<span *ngSwitchCase="'signet'" class="network signet"><span class="name">Bitcoin Signet</span><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchCase="'testnet'" class="network testnet"><span class="name">Bitcoin Testnet3</span><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchCase="'testnet4'" class="network testnet"><span class="name">Bitcoin Testnet4</span><app-svg-images name="testnet4" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchCase="'liquid'" class="network liquid"><span class="name">Liquid</span><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><span class="name">Liquid Testnet</span><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<span *ngSwitchDefault class="network mainnet"><span class="name">Bitcoin</span><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ml-2"></app-svg-images></span>
<div [ngSwitch]="network" class="network-label" [class.hide-name]="enterpriseInfo?.header_img">
<span *ngSwitchCase="'signet'" class="network signet"><span class="name">Bitcoin Signet</span><app-svg-images name="signet" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ms-2"></app-svg-images></span>
<span *ngSwitchCase="'testnet'" class="network testnet"><span class="name">Bitcoin Testnet3</span><app-svg-images name="testnet" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ms-2"></app-svg-images></span>
<span *ngSwitchCase="'testnet4'" class="network testnet"><span class="name">Bitcoin Testnet4</span><app-svg-images name="testnet4" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ms-2"></app-svg-images></span>
<span *ngSwitchCase="'liquid'" class="network liquid"><span class="name">Liquid</span><app-svg-images name="liquid" width="35" height="35" viewBox="0 0 125 125" style="display: inline-block" class="mainnet ms-2"></app-svg-images></span>
<span *ngSwitchCase="'liquidtestnet'" class="network liquidtestnet"><span class="name">Liquid Testnet</span><app-svg-images name="liquidtestnet" width="35" height="35" viewBox="0 0 125 125" style="display: inline-block" class="mainnet ms-2"></app-svg-images></span>
<span *ngSwitchDefault class="network mainnet"><span class="name">Bitcoin</span><app-svg-images name="bitcoin" width="35" height="35" viewBox="0 0 65 65" style="display: inline-block" class="mainnet ms-2"></app-svg-images></span>
</div>
}
</div>
@ -205,4 +205,4 @@
<span><ng-container i18n="accelerator.show-more-details">See more details</ng-container>&nbsp;<fa-icon [icon]="['fas', 'arrow-alt-circle-right']"></fa-icon></span>
</div>
</div>
</div>
</div>

View file

@ -204,7 +204,7 @@
}
.alert-replaced {
background: var(--danger);
background: var(--red);
margin: 1em 0.5em;
padding: 0.5em;
border-radius: 0.5em;

View file

@ -11,7 +11,7 @@
<h6>Updated: February 11, 2025</h6>
<br>
<div class="text-left">
<div class="text-start">
<ol>

View file

@ -1,6 +1,6 @@
<br>
<div class="title">
<h2 class="text-left" i18n="transaction.related-transactions|CPFP List">Related Transactions</h2>
<h2 class="text-start" i18n="transaction.related-transactions|CPFP List">Related Transactions</h2>
</div>
<div class="box cpfp-details">
<table class="table table-fixed table-borderless table-striped">
@ -17,7 +17,7 @@
<tbody>
<ng-template [ngIf]="cpfpInfo?.descendants?.length">
<tr *ngFor="let cpfpTx of cpfpInfo.descendants; trackBy: trackByIndex">
<td><span class="badge badge-primary" i18n="transaction.descendant|Descendant">Descendant</span></td>
<td><span class="badge bg-primary" i18n="transaction.descendant|Descendant">Descendant</span></td>
<td>
<app-truncate [text]="cpfpTx.txid" [link]="['/tx' | relativeUrl, cpfpTx.txid]"></app-truncate>
</td>
@ -29,7 +29,7 @@
</ng-template>
<ng-template [ngIf]="cpfpInfo?.bestDescendant">
<tr>
<td><span class="badge badge-success" i18n="transaction.descendant|Descendant">Descendant</span></td>
<td><span class="badge bg-success" i18n="transaction.descendant|Descendant">Descendant</span></td>
<td class="txids">
<app-truncate [text]="cpfpInfo.bestDescendant.txid" [link]="['/tx' | relativeUrl, cpfpInfo.bestDescendant.txid]"></app-truncate>
</td>
@ -41,7 +41,7 @@
</ng-template>
<ng-template [ngIf]="cpfpInfo?.ancestors?.length">
<tr *ngFor="let cpfpTx of cpfpInfo.ancestors; trackBy: trackByIndex">
<td><span class="badge badge-primary" i18n="transaction.ancestor|Transaction Ancestor">Ancestor</span></td>
<td><span class="badge bg-primary" i18n="transaction.ancestor|Transaction Ancestor">Ancestor</span></td>
<td class="txids">
<app-truncate [text]="cpfpTx.txid" [link]="['/tx' | relativeUrl, cpfpTx.txid]"></app-truncate>
</td>

View file

@ -124,22 +124,22 @@
<td class="wrap-cell">
<ng-container>
@if (auditStatus.coinbase) {
<span class="badge badge-primary mr-1" i18n="transactions-list.coinbase">Coinbase</span>
<span class="badge bg-primary me-1" i18n="transactions-list.coinbase">Coinbase</span>
} @else if (auditStatus.expected) {
<span 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>
<span class="badge bg-success me-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>
} @else if (auditStatus.seen) {
<span 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>
<span class="badge bg-success me-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>
} @else if (!auditStatus.conflict) {
<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>
<span class="badge bg-warning me-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>
}
@if (auditStatus.added) {
<span class="badge badge-warning mr-1" i18n-ngbTooltip="Added transaction tooltip" ngbTooltip="This transaction may have been added out-of-band" placement="bottom" i18n="tx-features.tag.added|Added">Added</span>
<span class="badge bg-warning me-1" i18n-ngbTooltip="Added transaction tooltip" ngbTooltip="This transaction may have been added out-of-band" placement="bottom" i18n="tx-features.tag.added|Added">Added</span>
}
@if (auditStatus.prioritized) {
<span class="badge badge-warning mr-1" i18n-ngbTooltip="Prioritized transaction tooltip" ngbTooltip="This transaction may have been prioritized out-of-band" placement="bottom" i18n="tx-features.tag.prioritized|Prioritized">Prioritized</span>
<span class="badge bg-warning me-1" i18n-ngbTooltip="Prioritized transaction tooltip" ngbTooltip="This transaction may have been prioritized out-of-band" placement="bottom" i18n="tx-features.tag.prioritized|Prioritized">Prioritized</span>
}
@if (auditStatus.conflict) {
<span 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>
<span class="badge bg-warning me-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>
@ -170,7 +170,7 @@
@if (!tx?.acceleration && acceleratorAvailable && accelerateCtaType === 'button' && !showAccelerationSummary && notAcceleratedOnLoad) {
<div class="d-flex accelerate">
<a class="btn btn-sm accelerateDeepMempool btn-small-height" [class.disabled]="!eligibleForAcceleration" i18n="transaction.accelerate|Accelerate button label" (click)="onAccelerateClicked()">Accelerate</a>
<a *ngIf="!eligibleForAcceleration" href="https://mempool.space/accelerator#why-cant-accelerate" target="_blank" class="info-badges ml-1" i18n-ngbTooltip="Mempool Accelerator&reg; tooltip" ngbTooltip="This transaction cannot be accelerated">
<a *ngIf="!eligibleForAcceleration" href="https://mempool.space/accelerator#why-cant-accelerate" target="_blank" class="info-badges ms-1" i18n-ngbTooltip="Mempool Accelerator&reg; tooltip" ngbTooltip="This transaction cannot be accelerated">
<fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true"></fa-icon>
</a>
</div>
@ -198,10 +198,10 @@
</td>
<td class="wrap-cell">
@if (isAcceleration) {
<span class="badge badge-accelerated mr-1" i18n="transaction.audit.accelerated">Accelerated</span>
<span class="badge badge-accelerated me-1" i18n="transaction.audit.accelerated">Accelerated</span>
}
<ng-container *ngFor="let filter of filters;">
<span class="badge badge-primary filter-tag mr-1">{{ filter.label }}</span>
<span class="badge bg-primary filter-tag me-1">{{ filter.label }}</span>
</ng-container>
</td>
</tr>
@ -260,11 +260,11 @@
}
@if (tx?.status?.confirmed && !tx.acceleration && !accelerationInfo && tx.fee && tx.effectiveFeePerVsize) {
<app-tx-fee-rating class="ml-2 mr-2 effective-fee-rating" [tx]="tx"></app-tx-fee-rating>
<app-tx-fee-rating class="ms-2 me-2 effective-fee-rating" [tx]="tx"></app-tx-fee-rating>
}
</div>
@if (hasCpfp) {
<button type="button" class="btn btn-outline-info btn-sm btn-small-height float-right" (click)="toggleCpfp()">CPFP</button>
<button type="button" class="btn btn-outline-info cpfp-toggle btn-sm btn-small-height float-end" (click)="toggleCpfp()">CPFP</button>
}
</td>
</tr>

View file

@ -133,6 +133,11 @@
}
}
.cpfp-toggle {
--bs-btn-active-color: var(--bs-btn-hover-color);
--bs-btn-active-bg: var(--bs-btn-hover-bg);
}
.eta {
display: flex;
flex-wrap: wrap;
@ -158,6 +163,9 @@
.accelerateDeepMempool {
background-color: var(--tertiary);
margin-left: 5px;
--bs-btn-active-bg: var(--tertiary);
--bs-btn-active-border-color: transparent;
--bs-btn-active-color: var(--fg);
}
.goggles-icon {

View file

@ -8,20 +8,20 @@
</div>
<div *ngIf="network !== 'liquid' && network !== 'liquidtestnet'" class="features">
<app-tx-features [tx]="tx"></app-tx-features>
<span *ngIf="cpfpInfo && (cpfpInfo?.bestDescendant || cpfpInfo?.descendants?.length || cpfpInfo?.ancestors?.length)" class="badge badge-primary ml-1 mr-1">
<span *ngIf="cpfpInfo && (cpfpInfo?.bestDescendant || cpfpInfo?.descendants?.length || cpfpInfo?.ancestors?.length)" class="badge bg-primary ms-1 me-1">
CPFP
</span>
</div>
</div>
<div class="top-data row">
<span class="field col-sm-4 text-left">
<span class="field col-sm-4 text-start">
<ng-template [ngIf]="isLiquid && haveBlindedOutputValues(tx)" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
<ng-template #defaultAmount>
<app-amount [satoshis]="totalValue"></app-amount>
</ng-template>
</span>
<span class="field col-sm-4 text-center"><ng-container *ngIf="transactionTime > 0">&lrm;{{ transactionTime * 1000 | date:'yyyy-MM-dd HH:mm' }}</ng-container></span>
<span class="field col-sm-4 text-right"><span class="label" i18n="transaction.fee|Transaction fee">Fee</span> {{ tx.fee | number }} <span class="symbol" i18n="shared.sats">sats</span></span>
<span class="field col-sm-4 text-end"><span class="label" i18n="transaction.fee|Transaction fee">Fee</span> {{ tx.fee | number }} <span class="symbol" i18n="shared.sats">sats</span></span>
</div>

View file

@ -8,7 +8,7 @@
<div class="mb-3">
<textarea formControlName="txRaw" class="form-control" rows="5" i18n-placeholder="transaction.hex-and-psbt" placeholder="Transaction hex or base64 encoded PSBT"></textarea>
</div>
<button [disabled]="isLoading" type="submit" class="btn btn-primary mr-2" i18n="shared.preview|Preview">Preview</button>
<button [disabled]="isLoading" type="submit" class="btn btn-primary me-2" i18n="shared.preview|Preview">Preview</button>
<input type="checkbox" [checked]="!offlineMode" id="offline-mode" (change)="onOfflineModeChange($event)">
<label class="label" for="offline-mode">
<span i18n="transaction.fetch-prevout-data">Fetch missing prevouts</span>
@ -97,11 +97,11 @@
<br>
<ng-container *ngIf="flowEnabled; else flowPlaceholder">
<div class="title float-left">
<div class="title float-start">
<h2 id="flow" i18n="transaction.flow|Transaction flow">Flow</h2>
</div>
<button type="button" class="btn btn-outline-info flow-toggle btn-sm float-right" (click)="toggleGraph()" i18n="hide-diagram">Hide diagram</button>
<button type="button" class="btn btn-outline-info flow-toggle btn-sm float-end" (click)="toggleGraph()" i18n="hide-diagram">Hide diagram</button>
<div class="clearfix"></div>
@ -152,7 +152,7 @@
<app-transactions-list #txList [transactions]="[transaction]" [transactionPage]="true" [txPreview]="true" [forceSignaturesMode]="isCoinbase ? 'none' : 'all'"></app-transactions-list>
<div class="title text-left">
<div class="title text-start">
<h2 i18n="transaction.details|Transaction Details">Details</h2>
</div>
<div class="box">

View file

@ -40,7 +40,7 @@
<ng-container i18n="transaction.duplicate.notice|Duplicate transaction notice">
This transaction ID appears twice in the blockchain as the coinbase of blocks <a [routerLink]="['/block/' | relativeUrl, duplicateTxBlocks[0]]">{{ duplicateTxBlocks[0] }}</a> and <a [routerLink]="['/block/' | relativeUrl, duplicateTxBlocks[1]]">{{ duplicateTxBlocks[1] }}</a>, due to a bug later mitigated by <a href="https://github.com/bitcoin/bips/blob/master/bip-0030.mediawiki" target="_blank" rel="noopener">BIP-30</a>.
</ng-container>
<span class="mr-3"></span>
<span class="me-3"></span>
<a href="https://blog.bitmex.com/bitcoins-duplicate-transactions/" target="_blank" rel="noopener" i18n="transaction.duplicate.read-more|Duplicate transaction read more" style="white-space: nowrap;">Read more</a>
</span>
</div>
@ -86,11 +86,11 @@
<ng-container *ngIf="!tx?.status?.confirmed && showAccelerationSummary && (ETA$ | async) as eta;">
<span id='accelerate' #accelerate class="anchor"></span>
<br>
<div class="title float-left mb-1">
<div class="title float-start mb-1">
<h2><a [href]="[ isMempoolSpaceBuild ? '/accelerator' : 'https://mempool.space/accelerator']" [target]="isMempoolSpaceBuild ? '' : 'blank'"><app-svg-images name="accelerator" [height]="isMobile ? '35px' : '45px'"></app-svg-images></a></h2>
</div>
<button type="button" class="btn btn-outline-info accelerator-toggle btn-sm float-right" [class.hide-on-mobile]="hasAccelerationDetails" (click)="closeAccelerator()" i18n="accelerator.hide">Hide accelerator</button>
<button *ngIf="hasAccelerationDetails" class="btn btn-sm btn-outline-info details-button float-right ml-2" (click)="showAccelerationDetails = !showAccelerationDetails" i18n="transaction.details|Transaction Details">Details</button>
<button type="button" class="btn btn-outline-info accelerator-toggle btn-sm float-end" [class.hide-on-mobile]="hasAccelerationDetails" (click)="closeAccelerator()" i18n="accelerator.hide">Hide accelerator</button>
<button *ngIf="hasAccelerationDetails" class="btn btn-sm btn-outline-info details-button float-end ms-2" (click)="showAccelerationDetails = !showAccelerationDetails" i18n="transaction.details|Transaction Details">Details</button>
<div class="clearfix"></div>
@ -114,7 +114,7 @@
<br>
<ng-container *ngIf="rbfInfo">
<div class="title float-left">
<div class="title float-start">
<h2 id="rbf" i18n="transaction.rbf-history|RBF Timeline">RBF Timeline</h2>
</div>
<div class="clearfix"></div>
@ -123,7 +123,7 @@
</ng-container>
<ng-container *ngIf="transactionTime > 0 && tx.acceleratedAt > 0 && (isAcceleration || accelerationCanceled)">
<div class="title float-left">
<div class="title float-start">
<h2 id="acceleration-timeline" i18n="transaction.acceleration-timeline|Acceleration Timeline">Acceleration Timeline</h2>
</div>
<div class="clearfix"></div>
@ -132,11 +132,11 @@
</ng-container>
<ng-container *ngIf="flowEnabled; else flowPlaceholder">
<div class="title float-left">
<div class="title float-start">
<h2 id="flow" #flow class="anchor" i18n="transaction.flow|Transaction flow">Flow</h2>
</div>
<button type="button" class="btn btn-outline-info flow-toggle btn-sm float-right" (click)="toggleGraph()" i18n="hide-diagram">Hide diagram</button>
<button type="button" class="btn btn-outline-info flow-toggle btn-sm float-end" (click)="toggleGraph()" i18n="hide-diagram">Hide diagram</button>
<div class="clearfix"></div>
@ -187,7 +187,7 @@
<app-transactions-list #txList [transactions]="[tx]" [cached]="isCached" [errorUnblinded]="errorUnblinded" [inputIndex]="inputIndex" [outputIndex]="outputIndex" [transactionPage]="true"></app-transactions-list>
<div class="title text-left">
<div class="title text-start">
<h2 i18n="transaction.details|Transaction Details">Details</h2>
</div>
<div class="box">

View file

@ -87,7 +87,7 @@
}
<td class="address-cell">
<div [ngSwitch]="true">
<ng-container *ngSwitchCase="vin.is_coinbase"><span i18n="transactions-list.coinbase">Coinbase</span><ng-template [ngIf]="network !== 'liquid' && network !== 'liquidtestnet'">&nbsp;<span i18n="transactions-list.newly-generated-coins">(Newly Generated Coins)</span></ng-template><br /><a placement="bottom" [ngbTooltip]="vin.scriptsig | hex2ascii"><span class="badge badge-secondary scriptmessage longer">{{ vin.scriptsig | hex2ascii }}</span></a></ng-container>
<ng-container *ngSwitchCase="vin.is_coinbase"><span i18n="transactions-list.coinbase">Coinbase</span><ng-template [ngIf]="network !== 'liquid' && network !== 'liquidtestnet'">&nbsp;<span i18n="transactions-list.newly-generated-coins">(Newly Generated Coins)</span></ng-template><br /><a placement="bottom" [ngbTooltip]="vin.scriptsig | hex2ascii"><span class="badge bg-secondary scriptmessage longer">{{ vin.scriptsig | hex2ascii }}</span></a></ng-container>
<ng-container *ngSwitchCase="vin.is_pegin">
<span i18n="transactions-list.peg-in">Peg-in</span>
</ng-container>
@ -119,7 +119,7 @@
</ng-container>
</div>
</td>
<td class="text-right nowrap amount" [class]="{large: tx.largeInput}">
<td class="text-end nowrap amount" [class]="{large: tx.largeInput}">
<button *ngIf="vin.isInscription" (click)="toggleOrdData(tx.txid, 'vin', vindex)" type="button" class="btn btn-sm badge badge-ord primary" style="margin-right: 10px;" i18n="transaction.inscription-tag">Inscription</button>
<ng-template [ngIf]="vin.prevout && vin.prevout.asset && vin.prevout.asset !== nativeAssetId" [ngIfElse]="defaultOutput">
<div *ngIf="assetsMinimal && assetsMinimal[vin.prevout.asset] else assetVinNotFound">
@ -362,18 +362,18 @@
} @else {
<a placement="bottom" style="cursor: pointer;">
@if ((vout.scriptpubkey_asm | hex2ascii).length > 200) {
<span *ngIf="vout.scriptpubkey_asm !== 'OP_RETURN'" class="badge badge-secondary scriptmessage opreturn-msg" (click)="toggleShowFullOpReturnPreview(vindex)">{{ vout.scriptpubkey_asm | hex2ascii | slice:0:200 }}</span>
<span *ngIf="vout.scriptpubkey_asm !== 'OP_RETURN'" class="badge bg-secondary scriptmessage opreturn-msg" (click)="toggleShowFullOpReturnPreview(vindex)">{{ vout.scriptpubkey_asm | hex2ascii | slice:0:200 }}</span>
<ng-container *ngIf="(showDetails$ | async) === false">
@if ((vout.scriptpubkey_asm | hex2ascii).length > 200) {
@if (!showFullOpReturnPreview[vindex]) {
<span class="badge badge-primary" (click)="toggleShowFullOpReturnPreview(vindex)">Show more</span>
<span class="badge bg-primary" (click)="toggleShowFullOpReturnPreview(vindex)">Show more</span>
} @else {
<span class="badge badge-primary" (click)="toggleShowFullOpReturnPreview(vindex)">Show less</span>
<span class="badge bg-primary" (click)="toggleShowFullOpReturnPreview(vindex)">Show less</span>
}
}
</ng-container>
} @else {
<span *ngIf="vout.scriptpubkey_asm !== 'OP_RETURN'" [ngbTooltip]="vout.scriptpubkey_asm | hex2ascii" class="badge badge-secondary scriptmessage">{{ vout.scriptpubkey_asm | hex2ascii }}</span>
<span *ngIf="vout.scriptpubkey_asm !== 'OP_RETURN'" [ngbTooltip]="vout.scriptpubkey_asm | hex2ascii" class="badge bg-secondary scriptmessage">{{ vout.scriptpubkey_asm | hex2ascii }}</span>
}
</a>
}
@ -382,7 +382,7 @@
</ng-template>
</ng-template>
</td>
<td class="text-right nowrap amount" [class]="{large: tx.largeOutput}">
<td class="text-end nowrap amount" [class]="{large: tx.largeOutput}">
<ng-template [ngIf]="vout.asset && vout.asset !== nativeAssetId" [ngIfElse]="defaultOutput">
<div *ngIf="assetsMinimal && assetsMinimal[vout.asset] else assetNotFound">
<ng-container *ngTemplateOutlet="assetBox; context:{ $implicit: vout }"></ng-container>
@ -512,17 +512,17 @@
</div>
<div class="summary">
<div class="float-left mt-2-5" *ngIf="!transactionPage && !tx.vin[0].is_coinbase && tx.fee !== -1">
<div class="float-start mt-2-5" *ngIf="!transactionPage && !tx.vin[0].is_coinbase && tx.fee !== -1">
<app-fee-rate [fee]="tx.fee" [weight]="tx.weight"></app-fee-rate>
<span class="d-none d-sm-inline-block">&nbsp;&ndash; {{ tx.fee | number }} <span class="symbol"
i18n="shared.sats">sats</span> <span class="fiat"><app-fiat [blockConversion]="tx.price" [value]="tx.fee"></app-fiat></span></span>
</div>
<div class="float-left mt-2-5 grey-info-text" *ngIf="tx.fee === -1" i18n="transactions-list.load-to-reveal-fee-info">Show more inputs to reveal fee data</div>
<div class="float-start mt-2-5 grey-info-text" *ngIf="tx.fee === -1" i18n="transactions-list.load-to-reveal-fee-info">Show more inputs to reveal fee data</div>
<div class="float-right" [class.has-accelerate]="!tx.status?.confirmed && acceleratedTxids">
<div class="float-end" [class.has-accelerate]="!tx.status?.confirmed && acceleratedTxids">
@if (!tx.status?.confirmed && acceleratedTxids) {
<button type="button" class="btn btn-sm accelerate mt-2 mr-2" [class.blink]="acceleratedTxids.has(tx.txid)" [routerLink]="['/tx/' | relativeUrl, tx.txid]" [fragment]="'accelerate'">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="15" class="mr-2" />
<button type="button" class="btn btn-sm accelerate mt-2 me-2" [class.blink]="acceleratedTxids.has(tx.txid)" [routerLink]="['/tx/' | relativeUrl, tx.txid]" [fragment]="'accelerate'">
<img src="/resources/mempool-accelerator-sparkles-light.svg" height="15" class="me-2" />
@if (acceleratedTxids.has(tx.txid)) {
<span i18n="transaction.audit.accelerated">Accelerated</span>
} @else {
@ -533,14 +533,14 @@
<ng-container *ngIf="showConfirmations && latestBlock$ | async as latestBlock">
<app-confirmations [chainTip]="latestBlock?.height" [height]="tx?.status?.block_height" [buttonClass]="(!tx.status?.confirmed && acceleratedTxids) ? 'mt-2 confirmation-compact' : 'mt-2'"></app-confirmations>
</ng-container>
<button *ngIf="addresses.length === 0; else viewingAddress" type="button" class="btn btn-sm btn-primary mt-2 ml-2" (click)="switchCurrency()">
<button *ngIf="addresses.length === 0; else viewingAddress" type="button" class="btn btn-sm btn-primary mt-2 ms-2" (click)="switchCurrency()">
<ng-template [ngIf]="(network === 'liquid' || network === 'liquidtestnet') && haveBlindedOutputValues(tx)" [ngIfElse]="defaultAmount" i18n="shared.confidential">Confidential</ng-template>
<ng-template #defaultAmount>
<app-amount [blockConversion]="tx.price" [satoshis]="getTotalTxOutput(tx)"></app-amount>
</ng-template>
</button>
<ng-template #viewingAddress>
<button type="button" class="btn btn-sm mt-2 ml-2" (click)="switchCurrency()" [ngClass]="{'btn-success': tx['addressValue'] >= 0, 'btn-danger': tx['addressValue'] < 0}">
<button type="button" class="btn btn-sm mt-2 ms-2" (click)="switchCurrency()" [ngClass]="{'btn-success': tx['addressValue'] >= 0, 'btn-danger': tx['addressValue'] < 0}">
<app-amount [blockConversion]="tx.price" [satoshis]="tx['addressValue']" [addPlus]="true"></app-amount>
</button>
</ng-template>

View file

@ -332,13 +332,16 @@ h2 {
}
.badge-ord {
background-color: var(--grey);
--bs-btn-bg: var(--grey);
--bs-btn-border-color: transparent;
background-color: var(--bs-btn-bg);
border-color: var(--bs-btn-border-color);
position: relative;
top: -2px;
font-size: 81%;
border: 0;
&.primary {
background-color: var(--primary);
--bs-btn-bg: var(--primary);
}
}

View file

@ -46,7 +46,7 @@
</div>
<div class="col">
<div class="card">
<div class="card-body pl-2 pr-2">
<div class="card-body ps-2 pe-2">
<h5 class="card-title" i18n="dashboard.treasury-distribution">Treasury Distribution</h5>
<div *ngIf="walletStats$ | async as walletStats">
<app-treasuries-pie
@ -87,7 +87,7 @@
</div>
<div class="col" style="margin-bottom: 1.47rem">
<div class="card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
<div class="card-body ps-lg-3 pe-lg-3 ps-2 pe-2">
<app-price-chart [height]="335" [widget]="true"></app-price-chart>
<div class="mt-1"><a [routerLink]="['/graphs/price' | relativeUrl]" fragment="1y" i18n="dashboard.view-more">View more &raquo;</a></div>
</div>

View file

@ -1,6 +1,6 @@
<a href="#" (click)="twitterLogin()"
[class]="(disabled ? 'disabled': '') + (customClass ? customClass : 'w-100 btn mt-1 d-flex justify-content-center align-items-center')"
style="background-color: rgb(31, 35, 40)" [style]="width ? 'width: ' + width : ''">
<span class="ml-2 text-light align-middle">{{ buttonString }}</span>
<span class="ms-2 text-light align-middle">{{ buttonString }}</span>
<img src="./resources/x.svg" height="25" style="padding: 2px; padding-left: 5px" [alt]="buttonString + ' with Twitter'" />
</a>

View file

@ -1,6 +1,6 @@
@if (loading) {
<div class="spinner-wrapper">
<div class="ml-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
<div class="ms-2 spinner-border text-light" style="width: 25px; height: 25px"></div>
</div>
} @else if (error) {
<div class="error-wrapper">

View file

@ -1,30 +1,30 @@
<ng-template [ngIf]="segwitEnabled">
<span *ngIf="segwitGains.realizedSegwitGains && !segwitGains.potentialSegwitGains; else segwitTwo" class="badge badge-success mr-1" i18n-ngbTooltip="ngbTooltip about segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedSegwitGains * 100 | number: '1.0-0' }}% on fees by using native SegWit" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
<span *ngIf="segwitGains.realizedSegwitGains && !segwitGains.potentialSegwitGains; else segwitTwo" class="badge bg-success me-1" i18n-ngbTooltip="ngbTooltip about segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedSegwitGains * 100 | number: '1.0-0' }}% on fees by using native SegWit" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
<ng-template #segwitTwo>
<span *ngIf="segwitGains.realizedSegwitGains && segwitGains.potentialSegwitGains; else potentialP2shSegwitGains" class="badge badge-warning mr-1" i18n-ngbTooltip="ngbTooltip about double segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedSegwitGains * 100 | number: '1.0-0' }}% on fees by using SegWit and could save {{ segwitGains.potentialSegwitGains * 100 | number : '1.0-0' }}% more by fully upgrading to native SegWit" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
<span *ngIf="segwitGains.realizedSegwitGains && segwitGains.potentialSegwitGains; else potentialP2shSegwitGains" class="badge bg-warning me-1" i18n-ngbTooltip="ngbTooltip about double segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedSegwitGains * 100 | number: '1.0-0' }}% on fees by using SegWit and could save {{ segwitGains.potentialSegwitGains * 100 | number : '1.0-0' }}% more by fully upgrading to native SegWit" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
<ng-template #potentialP2shSegwitGains>
<span *ngIf="segwitGains.potentialP2shSegwitGains" class="badge badge-danger mr-1" i18n-ngbTooltip="ngbTooltip about missed out gains" ngbTooltip="This transaction could save {{ segwitGains.potentialSegwitGains * 100 | number : '1.0-0' }}% on fees by upgrading to native SegWit or {{ segwitGains.potentialP2shSegwitGains * 100 | number: '1.0-0' }}% by upgrading to SegWit-P2SH" placement="bottom"><del i18n="tx-features.tag.segwit|SegWit">SegWit</del></span>
<span *ngIf="segwitGains.potentialP2shSegwitGains" class="badge bg-danger me-1" i18n-ngbTooltip="ngbTooltip about missed out gains" ngbTooltip="This transaction could save {{ segwitGains.potentialSegwitGains * 100 | number : '1.0-0' }}% on fees by upgrading to native SegWit or {{ segwitGains.potentialP2shSegwitGains * 100 | number: '1.0-0' }}% by upgrading to SegWit-P2SH" placement="bottom"><del i18n="tx-features.tag.segwit|SegWit">SegWit</del></span>
</ng-template>
</ng-template>
</ng-template>
<ng-template [ngIf]="taprootEnabled">
<span *ngIf="segwitGains.realizedTaprootGains && !segwitGains.potentialTaprootGains; else notFullyTaproot" class="badge badge-success mr-1" i18n-ngbTooltip="Tooltip about fees saved with taproot" ngbTooltip="This transaction uses Taproot and thereby saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span>
<span *ngIf="segwitGains.realizedTaprootGains && !segwitGains.potentialTaprootGains; else notFullyTaproot" class="badge bg-success me-1" i18n-ngbTooltip="Tooltip about fees saved with taproot" ngbTooltip="This transaction uses Taproot and thereby saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span>
<ng-template #notFullyTaproot>
<span *ngIf="segwitGains.realizedTaprootGains && segwitGains.potentialTaprootGains; else noTaproot" class="badge badge-warning mr-1" i18n-ngbTooltip="Tooltip about fees that saved and could be saved with taproot" ngbTooltip="This transaction uses Taproot and already saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees, but could save an additional {{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}% by fully using Taproot" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span>
<span *ngIf="segwitGains.realizedTaprootGains && segwitGains.potentialTaprootGains; else noTaproot" class="badge bg-warning me-1" i18n-ngbTooltip="Tooltip about fees that saved and could be saved with taproot" ngbTooltip="This transaction uses Taproot and already saved at least {{ segwitGains.realizedTaprootGains * 100 | number: '1.0-0' }}% on fees, but could save an additional {{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}% by fully using Taproot" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span>
<ng-template #noTaproot>
<span *ngIf="segwitGains.potentialTaprootGains && segwitGains.potentialTaprootGains > 0; else negativeTaprootGains" class="badge badge-danger mr-1" i18n-ngbTooltip="Tooltip about fees that could be saved with taproot" ngbTooltip="This transaction could save {{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}% on fees by using Taproot" placement="bottom"><del i18n="tx-features.tag.taproot|Taproot">Taproot</del></span>
<span *ngIf="segwitGains.potentialTaprootGains && segwitGains.potentialTaprootGains > 0; else negativeTaprootGains" class="badge bg-danger me-1" i18n-ngbTooltip="Tooltip about fees that could be saved with taproot" ngbTooltip="This transaction could save {{ segwitGains.potentialTaprootGains * 100 | number: '1.0-0' }}% on fees by using Taproot" placement="bottom"><del i18n="tx-features.tag.taproot|Taproot">Taproot</del></span>
<ng-template #negativeTaprootGains>
<span *ngIf="!isTaproot; else taprootButNoGains" class="badge badge-danger mr-1" i18n-ngbTooltip="Tooltip about using taproot" ngbTooltip="This transaction does not use Taproot" placement="bottom"><del i18n="tx-features.tag.taproot|Taproot">Taproot</del></span>
<span *ngIf="!isTaproot; else taprootButNoGains" class="badge bg-danger me-1" i18n-ngbTooltip="Tooltip about using taproot" ngbTooltip="This transaction does not use Taproot" placement="bottom"><del i18n="tx-features.tag.taproot|Taproot">Taproot</del></span>
</ng-template>
<ng-template #taprootButNoGains>
<span *ngIf="isTaproot" class="badge badge-success mr-1" i18n-ngbTooltip="Tooltip about taproot" ngbTooltip="This transaction uses Taproot" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span>
<span *ngIf="isTaproot" class="badge bg-success me-1" i18n-ngbTooltip="Tooltip about taproot" ngbTooltip="This transaction uses Taproot" placement="bottom" i18n="tx-features.tag.taproot|Taproot">Taproot</span>
</ng-template>
</ng-template>
</ng-template>
</ng-template>
<ng-template [ngIf]="rbfEnabled">
<span *ngIf="isRbfTransaction; else rbfDisabled" class="badge badge-success" i18n-ngbTooltip="RBF tooltip" ngbTooltip="This transaction supports Replace-By-Fee (RBF) allowing fee bumping" placement="bottom" i18n="tx-features.tag.rbf|RBF">RBF</span>
<ng-template #rbfDisabled><span class="badge badge-danger mr-1" i18n-ngbTooltip="RBF disabled tooltip" ngbTooltip="This transaction does NOT support Replace-By-Fee (RBF) and cannot be fee bumped using this method" placement="bottom"><del i18n="tx-features.tag.rbf|RBF">RBF</del></span></ng-template>
<span *ngIf="isRbfTransaction; else rbfDisabled" class="badge bg-success" i18n-ngbTooltip="RBF tooltip" ngbTooltip="This transaction supports Replace-By-Fee (RBF) allowing fee bumping" placement="bottom" i18n="tx-features.tag.rbf|RBF">RBF</span>
<ng-template #rbfDisabled><span class="badge bg-danger me-1" i18n-ngbTooltip="RBF disabled tooltip" ngbTooltip="This transaction does NOT support Replace-By-Fee (RBF) and cannot be fee bumped using this method" placement="bottom"><del i18n="tx-features.tag.rbf|RBF">RBF</del></span></ng-template>
</ng-template>

View file

@ -1,3 +1,3 @@
<span *ngIf="feeRating === 1" class="badge badge-success" i18n="tx-fee-rating.optimal|TX Fee Rating is Optimal">Optimal</span>
<span *ngIf="feeRating === 2" class="badge badge-warning" placement="bottom" i18n-ngbTooltip="tx-fee-rating.warning-tooltip" ngbTooltip="Only ~{{ medianFeeNeeded | feeRounding }} sat/vB was needed to get into this block" i18n="tx-fee-rating.overpaid.warning|TX Fee Rating is Warning">Overpaid {{ overpaidTimes }}x</span>
<span *ngIf="feeRating === 3" class="badge badge-danger" placement="bottom" i18n-ngbTooltip="tx-fee-rating.warning-tooltip" ngbTooltip="Only ~{{ medianFeeNeeded | feeRounding }} sat/vB was needed to get into this block" i18n="tx-fee-rating.overpaid.warning|TX Fee Rating is Warning">Overpaid {{ overpaidTimes }}x</span>
<span *ngIf="feeRating === 1" class="badge bg-success" i18n="tx-fee-rating.optimal|TX Fee Rating is Optimal">Optimal</span>
<span *ngIf="feeRating === 2" class="badge bg-warning" placement="bottom" i18n-ngbTooltip="tx-fee-rating.warning-tooltip" ngbTooltip="Only ~{{ medianFeeNeeded | feeRounding }} sat/vB was needed to get into this block" i18n="tx-fee-rating.overpaid.warning|TX Fee Rating is Warning">Overpaid {{ overpaidTimes }}x</span>
<span *ngIf="feeRating === 3" class="badge bg-danger" placement="bottom" i18n-ngbTooltip="tx-fee-rating.warning-tooltip" ngbTooltip="Only ~{{ medianFeeNeeded | feeRounding }} sat/vB was needed to get into this block" i18n="tx-fee-rating.overpaid.warning|TX Fee Rating is Warning">Overpaid {{ overpaidTimes }}x</span>

View file

@ -62,7 +62,7 @@
<ng-container *ngIf="(walletStats$ | async) as walletStats">
<br>
<div class="title-tx">
<h2 class="text-left" i18n="address.balance-history">Balance History</h2>
<h2 class="text-start" i18n="address.balance-history">Balance History</h2>
</div>
<div class="box">
<div class="row">
@ -77,7 +77,7 @@
<br>
<div class="title-tx">
<h2 class="text-left" i18n="address.transactions">Transactions</h2>
<h2 class="text-start" i18n="address.transactions">Transactions</h2>
</div>
<app-transactions-list [transactions]="transactions" [showConfirmations]="true" [addresses]="addressStrings" (loadMore)="loadMore()"></app-transactions-list>

View file

@ -16,17 +16,19 @@
</ng-container>
<div class="col">
<div class="card graph-card">
<div class="card-body pl-lg-3 pr-lg-3 pl-2 pr-2">
<div class="card-body ps-lg-3 pe-lg-3 ps-2 pe-2">
<a class="title-link mb-0" style="margin-top: -2px" href="" [routerLink]="['/mempool-block/0' | relativeUrl]">
<h5 class="card-title d-inline"><span>Mempool Goggles&reg;</span> : {{ goggleCycle[goggleIndex].name }}</h5>
<span>&nbsp;</span>
<fa-icon [icon]="['fas', 'external-link-alt']" [fixedWidth]="true" style="vertical-align: text-top; font-size: 13px; color: var(--title-fg)"></fa-icon>
</a>
<div class="quick-filter">
<div class="btn-group btn-group-toggle">
<label class="btn btn-primary btn-xs" [class.active]="filter.index === goggleIndex" *ngFor="let filter of goggleCycle">
<input type="radio" [value]="'3m'" fragment="3m" (click)="setFilter(filter.index)" [attr.data-cy]="'3m'"> {{ filter.name }}
</label>
<div class="btn-group" role="group">
<ng-container *ngFor="let filter of goggleCycle">
<input type="radio" class="btn-check" [value]="'3m'" [id]="'btn-radio-' + filter.index"
[checked]="filter.index === goggleIndex" (click)="setFilter(filter.index)" [attr.data-cy]="'3m'">
<label class="btn btn-primary btn-xs" [for]="'btn-radio-' + filter.index">{{ filter.name }}</label>
</ng-container>
</div>
</div>
<div class="mempool-block-wrapper" *ngIf="webGlEnabled">
@ -83,9 +85,9 @@
<td class="table-cell-old-fee"><app-fee-rate [fee]="replacement.oldFee" [weight]="replacement.oldVsize * 4"></app-fee-rate></td>
<td class="table-cell-new-fee"><app-fee-rate [fee]="replacement.newFee" [weight]="replacement.newVsize * 4"></app-fee-rate></td>
<td class="table-cell-badges">
<span *ngIf="replacement.mined" class="badge badge-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="replacement.fullRbf" class="badge badge-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="!replacement.fullRbf" class="badge badge-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
<span *ngIf="replacement.mined" class="badge bg-success" i18n="transaction.rbf.mined">Mined</span>
<span *ngIf="replacement.fullRbf" class="badge bg-info" i18n="transaction.full-rbf">Full RBF</span>
<span *ngIf="!replacement.fullRbf" class="badge bg-success" i18n="tx-features.tag.rbf|RBF">RBF</span>
</td>
</tr>
</tbody>
@ -182,7 +184,7 @@
<div class="col">
<div class="card-liquid card">
<h5 class="card-title" style="padding-top: 20px;" i18n="dashboard.lbtc-supply-vs-btc-holdings">LBTC Supply vs. BTC Holdings</h5>
<div class="card-body pl-0" style="padding-top: 10px;">
<div class="card-body ps-0" style="padding-top: 10px;">
<app-lbtc-pegs-graph [data]="fullHistory$ | async" [height]="lbtcPegGraphHeight"></app-lbtc-pegs-graph>
</div>
</div>
@ -326,7 +328,7 @@
<div class="col">
<div class="card-liquid card">
<h5 class="card-title" style="padding-top: 20px;" i18n="dashboard.lbtc-supply-vs-btc-holdings">LBTC Supply vs. BTC Holdings</h5>
<div class="card-body pl-0" style="padding-top: 25px;">
<div class="card-body ps-0" style="padding-top: 25px;">
<app-lbtc-pegs-graph [height]="lbtcPegGraphHeight" [auditInProgress]="auditInProgress"></app-lbtc-pegs-graph>
</div>
</div>

View file

@ -1,5 +1,5 @@
<ng-container *ngIf="{ val: network$ | async } as network">
<div class="container-xl text-left">
<div class="container-xl text-start">
<div id="faq" *ngIf="whichTab === 'faq'">

View file

@ -39,13 +39,13 @@
</span>
</span>
<ng-template [ngIf]="channel.base_fee_mtokens !== null">
<span class="badge badge-success" *ngIf="channel.base_fee_mtokens === 0; else nonZeroBaseFee"
<span class="badge bg-success" *ngIf="channel.base_fee_mtokens === 0; else nonZeroBaseFee"
i18n-ngbTooltip="lightning.zero-base-fee-tooltip"
ngbTooltip="This channel supports zero base fee routing"
placement="bottom" i18n="lightning.zero-base-fee">Zero base fee</span>
</ng-template>
<ng-template #nonZeroBaseFee>
<span class="badge badge-danger"
<span class="badge bg-danger"
i18n-ngbTooltip="lightning.non-zero-base-fee-tooltip"
ngbTooltip="This channel does not support zero base fee routing"
placement="bottom" i18n="lightning.non-zero-base-fee">Non-zero base fee</span>

Some files were not shown because too many files have changed in this diff Show more