mirror of
https://github.com/mempool/mempool.git
synced 2025-03-24 08:42:06 +01:00
Merge branch 'master' into simon/angular-universal
* master: (42 commits) i18n: Added missing Bisq translations. Minor missing space and character fixes. add missing 'sat/vb' string for i18n i18n: Removed CR from "In X minutes" translation i18n: Updated strings for "x confirmations", "x transactions", "x blocks" and "block ETA". Peg-out, and bisq headers. Update translation strings from Transifex Enable 'ka' locale for Georgian Update translation strings from Transifex Disable Vietnamese locale 'vi' until translations are completed Update translation strings from Transifex add 'sat' string for i18n Update translation strings from Transifex Update translation strings from Transifex i18n update Remove extra garbage characters from OP_RETURN tooltip. fixes #254 Fix for changing locale on other networks than mainnet. fixes #253 i18n: Asset search box Update translation strings from Transifex i18n: Added X of X transaction. Flipped collapse/expand i18n: Added "miner identification" and updated "navigate to sponsor" Update translations from Transifex ... # Conflicts: # frontend/src/app/components/app/app.component.ts # frontend/src/app/components/mempool-block/mempool-block.component.ts
This commit is contained in:
commit
f9e8dfb079
frontend
.tx
angular.jsonpackage.jsonsrc
app
app.constants.tsapp.module.ts
assets
bisq
bisq-address
bisq-block
bisq-blocks
bisq-stats
bisq-transaction-details
bisq-transaction
bisq-transactions
bisq-transfers
components
about
address
api-docs
app
asset
block
blockchain-blocks
clipboard
fees-box
latest-blocks
master-page
mempool-block
mempool-blocks
miner
search-form
statistics
television
transaction
transactions-list
translation-strings
tx-features
tx-fee-rating
dashboard
locale
messages.ar.xlfmessages.cs.xlfmessages.de.xlfmessages.en_US.xlfmessages.es.xlfmessages.fa.xlfmessages.fi_FI.xlfmessages.fr.xlfmessages.hr.xlfmessages.ja.xlfmessages.ka.xlfmessages.nb.xlfmessages.nl.xlfmessages.pl.xlfmessages.pt.xlfmessages.sl.xlfmessages.sv.xlfmessages.tr.xlfmessages.uk.xlfmessages.vi.xlfmessages.xlfmessages.zh.xlf
production
@ -1,7 +1,7 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[mempool.frontend-src-locale-messages-xlf--wiz-i18n]
|
||||
[mempool.frontend-src-locale-messages-xlf--master]
|
||||
file_filter = frontend/src/locale/messages.<lang>.xlf
|
||||
source_lang = en-US
|
||||
type = XLIFF
|
||||
|
@ -19,6 +19,10 @@
|
||||
"baseHref":"/"
|
||||
},
|
||||
"locales": {
|
||||
"ar": {
|
||||
"translation": "src/locale/messages.ar.xlf",
|
||||
"baseHref": "/ar/"
|
||||
},
|
||||
"cs": {
|
||||
"translation": "src/locale/messages.cs.xlf",
|
||||
"baseHref": "/cs/"
|
||||
@ -43,13 +47,17 @@
|
||||
"translation": "src/locale/messages.ja.xlf",
|
||||
"baseHref": "/ja/"
|
||||
},
|
||||
"ka": {
|
||||
"translation": "src/locale/messages.ka.xlf",
|
||||
"baseHref": "/ka/"
|
||||
},
|
||||
"nl": {
|
||||
"translation": "src/locale/messages.nl.xlf",
|
||||
"baseHref": "/nl/"
|
||||
},
|
||||
"nn": {
|
||||
"translation": "src/locale/messages.nn.xlf",
|
||||
"baseHref": "/nn/"
|
||||
"nb": {
|
||||
"translation": "src/locale/messages.nb.xlf",
|
||||
"baseHref": "/nb/"
|
||||
},
|
||||
"pt": {
|
||||
"translation": "src/locale/messages.pt.xlf",
|
||||
@ -71,6 +79,10 @@
|
||||
"translation": "src/locale/messages.uk.xlf",
|
||||
"baseHref": "/uk/"
|
||||
},
|
||||
"vi": {
|
||||
"translation": "src/locale/messages.vi.xlf",
|
||||
"baseHref": "/vi/"
|
||||
},
|
||||
"zh": {
|
||||
"translation": "src/locale/messages.zh.xlf",
|
||||
"baseHref": "/zh/"
|
||||
|
@ -23,7 +23,7 @@
|
||||
"ng": "./node_modules/@angular/cli/bin/ng",
|
||||
"tsc": "./node_modules/typescript/bin/tsc",
|
||||
"i18n-extract-from-source": "./node_modules/@angular/cli/bin/ng xi18n --ivy --out-file ./src/locale/messages.xlf",
|
||||
"i18n-pull-from-transifex": "tx pull -a --parallel --minimum-perc 1",
|
||||
"i18n-pull-from-transifex": "tx pull -a --parallel --minimum-perc 1 --force",
|
||||
"serve": "ng serve --proxy-config proxy.conf.json",
|
||||
"start": "npm run generate-config && npm run sync-assets-dev && ng serve --proxy-config proxy.conf.json",
|
||||
"build": "npm run generate-config && ng build --prod --localize && npm run sync-assets",
|
||||
|
@ -65,7 +65,7 @@ export interface Language {
|
||||
}
|
||||
|
||||
export const languages: Language[] = [
|
||||
// { code: 'ar', name: 'العربية' }, // Arabic
|
||||
{ code: 'ar', name: 'العربية' }, // Arabic
|
||||
// { code: 'bg', name: 'Български' }, // Bulgarian
|
||||
// { code: 'bs', name: 'Bosanski' }, // Bosnian
|
||||
// { code: 'ca', name: 'Català' }, // Catalan
|
||||
@ -81,6 +81,7 @@ export const languages: Language[] = [
|
||||
{ code: 'fa', name: 'فارسی' }, // Persian
|
||||
{ code: 'fr', name: 'Français' }, // French
|
||||
// { code: 'gl', name: 'Galego' }, // Galician
|
||||
{ code: 'ka', name: 'ქართული' }, // Georgian
|
||||
// { code: 'ko', name: '한국어' }, // Korean
|
||||
// { code: 'hr', name: 'Hrvatski' }, // Croatian
|
||||
// { code: 'id', name: 'Bahasa Indonesia' },// Indonesian
|
||||
@ -94,8 +95,8 @@ export const languages: Language[] = [
|
||||
// { code: 'ms', name: 'Bahasa Melayu' }, // Malay
|
||||
{ code: 'nl', name: 'Nederlands' }, // Dutch
|
||||
{ code: 'ja', name: '日本語' }, // Japanese
|
||||
// { code: 'nb', name: 'Norsk bokmål' }, // Norwegian Bokmål
|
||||
{ code: 'nn', name: 'Norsk' }, // Norwegian Nynorsk
|
||||
{ code: 'nb', name: 'Norsk' }, // Norwegian Bokmål
|
||||
// { code: 'nn', name: 'Norsk Nynorsk' }, // Norwegian Nynorsk
|
||||
// { code: 'pl', name: 'Polski' }, // Polish
|
||||
{ code: 'pt', name: 'Português' }, // Portuguese
|
||||
// { code: 'pt-BR', name: 'Português (Brazil)' }, // Portuguese (Brazil)
|
||||
|
@ -43,11 +43,10 @@ import { NgbTypeaheadModule } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { FeesBoxComponent } from './components/fees-box/fees-box.component';
|
||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
|
||||
import { faAngleDoubleDown, faAngleDoubleUp, faAngleDown, faAngleUp, faBolt, faChartArea, faCogs, faCubes, faDatabase, faExchangeAlt, faInfoCircle,
|
||||
import { faAngleDown, faAngleUp, faBolt, faChartArea, faCogs, faCubes, faDatabase, faExchangeAlt, faInfoCircle,
|
||||
faLink, faList, faSearch, faTachometerAlt, faThList, faTint, faTv } from '@fortawesome/free-solid-svg-icons';
|
||||
import { ApiDocsComponent } from './components/api-docs/api-docs.component';
|
||||
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
|
||||
import { TranslationStringsComponent } from './components/translation-strings/translation-strings.component';
|
||||
import { StorageService } from './services/storage.service';
|
||||
import { HttpCacheInterceptor } from './services/http-cache.interceptor';
|
||||
|
||||
@ -84,7 +83,6 @@ import { HttpCacheInterceptor } from './services/http-cache.interceptor';
|
||||
DashboardComponent,
|
||||
ApiDocsComponent,
|
||||
TermsOfServiceComponent,
|
||||
TranslationStringsComponent,
|
||||
],
|
||||
imports: [
|
||||
BrowserModule.withServerTransition({ appId: 'serverApp' }),
|
||||
|
@ -1,14 +1,14 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Registered assets</h1>
|
||||
<h1 style="float: left;" i18n="Registered assets page header">Registered assets</h1>
|
||||
<br>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<form [formGroup]="searchForm" class="form-inline">
|
||||
<div class="input-group m-2">
|
||||
<input style="width: 250px;" formControlName="searchText" type="text" class="form-control" placeholder="Search asset">
|
||||
<input style="width: 250px;" 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">Clear</button>
|
||||
<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>
|
||||
</div>
|
||||
</form>
|
||||
@ -16,11 +16,11 @@
|
||||
<ng-container *ngIf="(assets$ | async) as filteredAssets; else isLoading">
|
||||
<table class="table table-borderless table-striped">
|
||||
<thead>
|
||||
<th class="td-name">Name</th>
|
||||
<th>Ticker</th>
|
||||
<th class="d-none d-md-block">Issuer domain</th>
|
||||
<th>Asset ID</th>
|
||||
<th class="d-none d-lg-block">Issuance TX</th>
|
||||
<th class="td-name" i18n="Asset name header">Name</th>
|
||||
<th i18n="Asset ticker header">Ticker</th>
|
||||
<th class="d-none d-md-block" i18n="Asset Issuer Domain header">Issuer domain</th>
|
||||
<th i18n="Asset ID header">Asset ID</th>
|
||||
<th class="d-none d-lg-block" i18n="Asset issuance transaction header">Issuance TX</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let asset of filteredAssets; trackBy: trackByAsset">
|
||||
@ -43,11 +43,11 @@
|
||||
|
||||
<table class="table table-borderless table-striped">
|
||||
<thead>
|
||||
<th>Name</th>
|
||||
<th>Ticker</th>
|
||||
<th>Issuer domain</th>
|
||||
<th>Asset ID</th>
|
||||
<th>Issuance TX</th>
|
||||
<th i18n="Asset name header">Name</th>
|
||||
<th i18n="Asset ticker header">Ticker</th>
|
||||
<th i18n="Asset Issuer Domain header">Issuer domain</th>
|
||||
<th i18n="Asset ID header">Asset ID</th>
|
||||
<th i18n="Asset issuance transaction header">Issuance TX</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let dummy of [0,0,0]">
|
||||
@ -64,7 +64,7 @@
|
||||
|
||||
<ng-template [ngIf]="error">
|
||||
<div class="text-center">
|
||||
Error loading assets data.
|
||||
<ng-container i18n="Asset data load error">Error loading assets data.</ng-container>
|
||||
<br>
|
||||
<i>{{ error.error }}</i>
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@ import { distinctUntilChanged, map, filter, mergeMap, tap, take } from 'rxjs/ope
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { merge, combineLatest, Observable } from 'rxjs';
|
||||
import { AssetExtended } from '../interfaces/electrs.interface';
|
||||
import { SeoService } from '../services/seo.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-assets',
|
||||
@ -32,9 +33,11 @@ export class AssetsComponent implements OnInit {
|
||||
private formBuilder: FormBuilder,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private seoService: SeoService,
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.setTitle($localize`:@@ee8f8008bae6ce3a49840c4e1d39b4af23d4c263:Assets`);
|
||||
this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
|
||||
|
||||
this.searchForm = this.formBuilder.group({
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Address</h1>
|
||||
<h1 style="float: left;" i18n="shared.address">Address</h1>
|
||||
<a [routerLink]="['/address/' | relativeUrl, addressString]" style="line-height: 56px; margin-left: 10px;">
|
||||
<span class="d-inline d-lg-none">{{ addressString | shortenString : 24 }}</span>
|
||||
<span class="d-none d-lg-inline">{{ addressString }}</span>
|
||||
@ -17,15 +17,15 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Total received</td>
|
||||
<td i18n="address.total-received">Total received</td>
|
||||
<td>{{ totalReceived / 100 | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total sent</td>
|
||||
<td i18n="address.total-sent">Total sent</td>
|
||||
<td>{{ totalSent / 100 | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Final balance</td>
|
||||
<td i18n="address.balance">Balance</td>
|
||||
<td>{{ (totalReceived - totalSent) / 100 | number: '1.2-2' }} BSQ (<app-bsq-amount [bsq]="totalReceived - totalSent" [forceFiat]="true" [green]="true"></app-bsq-amount>)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -43,7 +43,11 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2>{{ transactions.length | number }} transactions</h2>
|
||||
<h2>
|
||||
<ng-container *ngTemplateOutlet="transactions.length === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: transactions.length}"></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>
|
||||
|
||||
<ng-template ngFor let-tx [ngForOf]="transactions">
|
||||
|
||||
|
@ -36,7 +36,7 @@ export class BisqAddressComponent implements OnInit, OnDestroy {
|
||||
this.transactions = null;
|
||||
document.body.scrollTo(0, 0);
|
||||
this.addressString = params.get('id') || '';
|
||||
this.seoService.setTitle('Address: ' + this.addressString);
|
||||
this.seoService.setTitle($localize`:@@bisq-address.component.browser-title:Address: ${this.addressString}:INTERPOLATION:`);
|
||||
|
||||
return this.bisqApiService.getAddress$(this.addressString)
|
||||
.pipe(
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="container-xl">
|
||||
|
||||
<div class="title-block">
|
||||
<h1>Block <ng-template [ngIf]="blockHeight"><a [routerLink]="['/block/' | relativeUrl, blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
||||
<h1><ng-template [ngIf]="blockHeight" i18n="block.block">Block <a [routerLink]="['/block/' | relativeUrl, blockHash]">{{ blockHeight }}</a></ng-template></h1>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@ -14,15 +14,15 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Hash</td>
|
||||
<td class="td-width" i18n="block.hash">Hash</td>
|
||||
<td><a [routerLink]="['/block/' | relativeUrl, block.hash]" title="{{ block.hash }}">{{ block.hash | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="block.hash"></app-clipboard></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Timestamp</td>
|
||||
<td i18n="transaction.timestamp|Transaction Timestamp">Timestamp</td>
|
||||
<td>
|
||||
{{ block.time | date:'yyyy-MM-dd HH:mm' }}
|
||||
<div class="lg-inline">
|
||||
<i>(<app-time-since [time]="block.time / 1000" [fastRender]="true"></app-time-since> ago)</i>
|
||||
<i>(<app-time-since [time]="block.time / 1000" [fastRender]="true"></app-time-since>)</i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@ -32,7 +32,7 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Previous hash</td>
|
||||
<td class="td-width" i18n="block.previous_hash|Transaction Previous Hash">Previous hash</td>
|
||||
<td><a [routerLink]="['/block/' | relativeUrl, block.previousBlockHash]" title="{{ block.hash }}">{{ block.previousBlockHash | shortenString : 13 }}</a> <app-clipboard class="d-none d-sm-inline-block" [text]="block.previousBlockHash"></app-clipboard></td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -44,7 +44,11 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2>{{ block.txs.length | number }} transactions</h2>
|
||||
<h2>
|
||||
<ng-container *ngTemplateOutlet="block.txs.length === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: block.txs.length| 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>
|
||||
|
||||
<ng-template ngFor let-tx [ngForOf]="block.txs">
|
||||
|
||||
@ -73,11 +77,11 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Hash</td>
|
||||
<td class="td-width" i18n="block.hash">Hash</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Timestamp</td>
|
||||
<td i18n="transaction.timestamp|Transaction Timestamp">Timestamp</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -86,7 +90,7 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Previous hash</td>
|
||||
<td class="td-width" i18n="block.previous_hash|Transaction Previous Hash">Previous hash</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -82,7 +82,7 @@ export class BisqBlockComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
this.isLoading = false;
|
||||
this.blockHeight = block.height;
|
||||
this.seoService.setTitle('Block: #' + block.height + ': ' + block.hash);
|
||||
this.seoService.setTitle($localize`:@@bisq-block.component.browser-title:Block ${block.height}:BLOCK_HEIGHT:: ${block.hash}:BLOCK_HASH:`);
|
||||
this.block = block;
|
||||
});
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Blocks</h1>
|
||||
<h1 style="float: left;" i18n="Bisq blocks header">Blocks</h1>
|
||||
<br>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@ -9,15 +9,15 @@
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-borderless table-striped">
|
||||
<thead>
|
||||
<th style="width: 25%;">Height</th>
|
||||
<th style="width: 25%;">Confirmed</th>
|
||||
<th style="width: 25%;">Total Sent</th>
|
||||
<th class="d-none d-md-block" style="width: 25%;">Transactions</th>
|
||||
<th style="width: 25%;" i18n="Bisq block height header">Height</th>
|
||||
<th style="width: 25%;" i18n="Bisq block confirmed time header">Confirmed</th>
|
||||
<th style="width: 25%;" i18n="Bisq block total BSQ tokens sent header">Total sent</th>
|
||||
<th class="d-none d-md-block" style="width: 25%;" i18n="Bisq block transactions title">Transactions</th>
|
||||
</thead>
|
||||
<tbody *ngIf="blocks.value; else loadingTmpl">
|
||||
<tr *ngFor="let block of blocks.value[0]; trackBy: trackByFn">
|
||||
<td><a [routerLink]="['/block/' | relativeUrl, block.hash]" [state]="{ data: { block: block } }">{{ block.height }}</a></td>
|
||||
<td><app-time-since [time]="block.time / 1000" [fastRender]="true"></app-time-since> ago</td>
|
||||
<td><app-time-since [time]="block.time / 1000" [fastRender]="true"></app-time-since></td>
|
||||
<td>{{ calculateTotalOutput(block) / 100 | number: '1.2-2' }}<span class="d-none d-md-inline"> BSQ</span></td>
|
||||
<td class="d-none d-md-block">{{ block.txs.length }}</td>
|
||||
</tr>
|
||||
|
@ -32,7 +32,7 @@ export class BisqBlocksComponent implements OnInit {
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.seoService.setTitle('Blocks');
|
||||
this.seoService.setTitle($localize`:@@8a7b4bd44c0ac71b2e72de0398b303257f7d2f54:Blocks`);
|
||||
this.itemsPerPage = Math.max(Math.round(this.contentSpace / this.fiveItemsPxSize) * 5, 10);
|
||||
this.loadingItems = Array(this.itemsPerPage);
|
||||
if (document.body.clientWidth < 768) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">BSQ Statistics</h1>
|
||||
<h1 style="float: left;" i18n="BSQ statistics header">BSQ statistics</h1>
|
||||
<br>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@ -7,41 +7,37 @@
|
||||
<div class="row">
|
||||
<div class="col-sm">
|
||||
<table class="table table-borderless table-striped">
|
||||
<thead>
|
||||
<th>Property</th>
|
||||
<th>Value</th>
|
||||
</thead>
|
||||
<tbody *ngIf="!isLoading; else loadingTemplate">
|
||||
<tr>
|
||||
<td class="td-width">Existing amount</td>
|
||||
<td class="td-width" i18n="BSQ existing amount">Existing amount</td>
|
||||
<td>{{ (stats.minted - stats.burnt) / 100 | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minted amount</td>
|
||||
<td i18n="BSQ minted amount">Minted amount</td>
|
||||
<td>{{ stats.minted | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Burnt amount</td>
|
||||
<td i18n="BSQ burnt amount">Burnt amount</td>
|
||||
<td>{{ stats.burnt | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Addresses</td>
|
||||
<td i18n="BSQ addresses">Addresses</td>
|
||||
<td>{{ stats.addresses | number }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unspent TXOs</td>
|
||||
<td i18n="BSQ unspent transaction outputs">Unspent TXOs</td>
|
||||
<td>{{ stats.unspent_txos | number }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Spent TXOs</td>
|
||||
<td i18n="BSQ spent transaction outputs">Spent TXOs</td>
|
||||
<td>{{ stats.spent_txos | number }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td i18n="BSQ token price">Price</td>
|
||||
<td><app-fiat [value]="price"></app-fiat></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Market cap</td>
|
||||
<td i18n="BSQ token market cap">Market cap</td>
|
||||
<td><app-fiat [value]="price * (stats.minted - stats.burnt) / 100"></app-fiat></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -55,23 +51,23 @@
|
||||
<ng-template #loadingTemplate>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Existing amount</td>
|
||||
<td class="td-width" i18n>Existing amount</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Minted amount</td>
|
||||
<td i18n>Minted amount</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Burnt amount</td>
|
||||
<td i18n>Burnt amount</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Addresses</td>
|
||||
<td i18n>Addresses</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Unspent TXOs</td>
|
||||
<td i18n>Unspent TXOs</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
@ -79,11 +75,11 @@
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Price</td>
|
||||
<td i18n>Price</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Market cap</td>
|
||||
<td i18n>Market cap</td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -21,8 +21,7 @@ export class BisqStatsComponent implements OnInit {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.setTitle('BSQ Statistics');
|
||||
|
||||
this.seoService.setTitle($localize`:@@2a30a4cdb123a03facc5ab8c5b3e6d8b8dbbc3d4:BSQ statistics`);
|
||||
this.stateService.bsqPrice$
|
||||
.subscribe((bsqPrice) => {
|
||||
this.price = bsqPrice;
|
||||
|
@ -4,15 +4,15 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Inputs</td>
|
||||
<td class="td-width" i18n="transaction.inputs">Inputs</td>
|
||||
<td>{{ totalInput / 100 | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Outputs</td>
|
||||
<td i18n="transaction.outputs">Outputs</td>
|
||||
<td>{{ totalOutput / 100 | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Issuance</td>
|
||||
<td i18n="asset.issued-amount|Liquid Asset issued amount">Issued amount</td>
|
||||
<td>{{ totalIssued / 100 | number: '1.2-2' }} BSQ</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
@ -22,11 +22,11 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody class="mobile-even">
|
||||
<tr>
|
||||
<td class="td-width">Type</td>
|
||||
<td class="td-width" i18n>Type</td>
|
||||
<td><app-bisq-icon class="mr-1" [txType]="tx.txType"></app-bisq-icon> {{ tx.txTypeDisplayString }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Version</td>
|
||||
<td i18n="transaction.version">Version</td>
|
||||
<td>{{ tx.txVersion }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -1,11 +1,14 @@
|
||||
<div class="container-xl">
|
||||
|
||||
<h1 class="float-left mr-3 mb-md-3">Transaction</h1>
|
||||
<h1 class="float-left mr-3 mb-md-3" i18n="shared.transaction">Transaction</h1>
|
||||
|
||||
<ng-template [ngIf]="!isLoading && !error">
|
||||
|
||||
<button *ngIf="(latestBlock$ | async) as latestBlock" type="button" class="btn btn-sm btn-success float-right mr-2 mt-1 mt-md-3">{{ latestBlock.height - bisqTx.blockHeight + 1 }} confirmation<ng-container *ngIf="latestBlock.height - bisqTx.blockHeight + 1 > 1">s</ng-container></button>
|
||||
|
||||
<button *ngIf="(latestBlock$ | async) as latestBlock" type="button" class="btn btn-sm btn-success float-right mr-2 mt-1 mt-md-3">
|
||||
<ng-container *ngTemplateOutlet="latestBlock.height - bisqTx.blockHeight + 1 == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: latestBlock.height - bisqTx.blockHeight + 1}"></ng-container>
|
||||
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
|
||||
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
|
||||
</button>
|
||||
<div>
|
||||
<a [routerLink]="['/bisq-tx' | relativeUrl, bisqTx.id]" style="line-height: 56px;">
|
||||
<span class="d-inline d-lg-none">{{ bisqTx.id | shortenString : 24 }}</span>
|
||||
@ -21,22 +24,22 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Timestamp</td>
|
||||
<td i18n="transaction.timestamp|Transaction Timestamp">Timestamp</td>
|
||||
<td>
|
||||
{{ bisqTx.time | date:'yyyy-MM-dd HH:mm' }}
|
||||
<div class="lg-inline">
|
||||
<i>(<app-time-since [time]="bisqTx.time / 1000" [fastRender]="true"></app-time-since> ago)</i>
|
||||
<i>(<app-time-since [time]="bisqTx.time / 1000" [fastRender]="true"></app-time-since>)</i>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="td-width">Included in block</td>
|
||||
<td class="td-width" i18n="transaction.included-in-block|Transaction included in block">Included in block</td>
|
||||
<td>
|
||||
<a [routerLink]="['/block/' | relativeUrl, bisqTx.blockHash]" [state]="{ data: { blockHeight: bisqTx.blockHeight } }">{{ bisqTx.blockHeight }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="td-width">Features</td>
|
||||
<td class="td-width" i18n="transaction.features|Transaction features">Features</td>
|
||||
<td>
|
||||
<app-tx-features *ngIf="tx; else loadingTx" [tx]="tx"></app-tx-features>
|
||||
<ng-template #loadingTx>
|
||||
@ -51,12 +54,12 @@
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width">Burnt</td>
|
||||
<td class="td-width" i18n="BSQ burnt amount">Burnt amount</td>
|
||||
<td>
|
||||
{{ bisqTx.burntFee / 100 | number: '1.2-2' }} BSQ (<app-bsq-amount [bsq]="bisqTx.burntFee" [forceFiat]="true" [green]="true"></app-bsq-amount>)
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fee per vByte</td>
|
||||
<td i18n="transaction.fee-per-vbyte|Transaction fee">Fee per vByte</td>
|
||||
<td *ngIf="!isLoadingTx; else loadingTxFee">
|
||||
{{ tx.fee / (tx.weight / 4) | number : '1.1-1' }} sat/vB
|
||||
|
||||
@ -75,14 +78,14 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2>Details</h2>
|
||||
<h2 i18n="transaction.details">Details</h2>
|
||||
|
||||
|
||||
<app-bisq-transaction-details [tx]="bisqTx"></app-bisq-transaction-details>
|
||||
|
||||
<br>
|
||||
|
||||
<h2>Inputs & Outputs</h2>
|
||||
<h2 i18n="transaction.inputs-and-outputs|Transaction inputs and outputs">Inputs & Outputs</h2>
|
||||
|
||||
<app-bisq-transfers [tx]="bisqTx"></app-bisq-transfers>
|
||||
|
||||
@ -121,7 +124,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2>Details</h2>
|
||||
<h2 i18n="transaction.details">Details</h2>
|
||||
<div class="box">
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
@ -142,7 +145,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2>Inputs & Outputs</h2>
|
||||
<h2 i18n="transaction.inputs-and-outputs|Transaction inputs and outputs">Inputs & Outputs</h2>
|
||||
|
||||
<div class="box">
|
||||
<div class="row">
|
||||
|
@ -43,7 +43,7 @@ export class BisqTransactionComponent implements OnInit, OnDestroy {
|
||||
this.error = null;
|
||||
document.body.scrollTo(0, 0);
|
||||
this.txId = params.get('id') || '';
|
||||
this.seoService.setTitle('Transaction: ' + this.txId);
|
||||
this.seoService.setTitle($localize`:@@bisq.transaction.browser-title:Transaction: ${this.txId}:INTERPOLATION:`);
|
||||
if (history.state.data) {
|
||||
return of(history.state.data);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Transactions</h1>
|
||||
<h1 style="float: left;" i18n>Transactions</h1>
|
||||
|
||||
<div class="d-block float-right">
|
||||
<form [formGroup]="radioGroupForm">
|
||||
@ -15,11 +15,11 @@
|
||||
|
||||
<table class="table table-borderless table-striped">
|
||||
<thead>
|
||||
<th style="width: 20%;">Transaction</th>
|
||||
<th class="d-none d-md-block" style="width: 100%;">Type</th>
|
||||
<th style="width: 20%;">Amount</th>
|
||||
<th style="width: 20%;">Confirmed</th>
|
||||
<th class="d-none d-md-block">Height</th>
|
||||
<th style="width: 20%;" i18n>Transaction</th>
|
||||
<th class="d-none d-md-block" style="width: 100%;" i18n>Type</th>
|
||||
<th style="width: 20%;" i18n>Amount</th>
|
||||
<th style="width: 20%;" i18n>Confirmed</th>
|
||||
<th class="d-none d-md-block" i18n>Height</th>
|
||||
</thead>
|
||||
<tbody *ngIf="transactions.value; else loadingTmpl">
|
||||
<tr *ngFor="let tx of transactions.value[0]; trackBy: trackByFn">
|
||||
@ -37,7 +37,7 @@
|
||||
{{ calculateTotalOutput(tx.outputs) / 100 | number: '1.2-2' }}<span class="d-none d-md-inline"> BSQ</span>
|
||||
</ng-template>
|
||||
</td>
|
||||
<td><app-time-since [time]="tx.time / 1000" [fastRender]="true"></app-time-since> ago</td>
|
||||
<td><app-time-since [time]="tx.time / 1000" [fastRender]="true"></app-time-since></td>
|
||||
<td class="d-none d-md-block"><a [routerLink]="['/block/' | relativeUrl, tx.blockHash]" [state]="{ data: { blockHeight: tx.blockHeight } }">{{ tx.blockHeight }}</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@ -52,7 +52,9 @@ export class BisqTransactionsComponent implements OnInit {
|
||||
};
|
||||
|
||||
txTypeDropdownTexts: IMultiSelectTexts = {
|
||||
defaultTitle: 'Filter',
|
||||
defaultTitle: $localize`:@@bisq-transactions.filter:Filter`,
|
||||
checkAll: $localize`:@@bisq-transactions.selectall:Select all`,
|
||||
uncheckAll: $localize`:@@bisq-transactions.unselectall:Unselect all`,
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
@ -72,7 +74,7 @@ export class BisqTransactionsComponent implements OnInit {
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.seoService.setTitle('Transactions');
|
||||
this.seoService.setTitle($localize`:@@add4cd82e3e38a3110fe67b3c7df56e9602644ee:Transactions`);
|
||||
|
||||
this.radioGroupForm = this.formBuilder.group({
|
||||
txTypes: [this.txTypesDefaultChecked],
|
||||
|
@ -59,12 +59,16 @@
|
||||
|
||||
<div>
|
||||
<div class="float-left mt-2-5" *ngIf="showConfirmations && tx.burntFee">
|
||||
Burnt: {{ tx.burntFee / 100 | number: '1.2-2' }} BSQ (<app-bsq-amount [bsq]="tx.burntFee" [forceFiat]="true" [green]="true"></app-bsq-amount>)
|
||||
<ng-container i18n="BSQ burnt amount">Burnt amount</ng-container>: {{ tx.burntFee / 100 | number: '1.2-2' }} BSQ (<app-bsq-amount [bsq]="tx.burntFee" [forceFiat]="true" [green]="true"></app-bsq-amount>)
|
||||
</div>
|
||||
|
||||
<div class="float-right">
|
||||
<span *ngIf="showConfirmations && latestBlock$ | async as latestBlock">
|
||||
<button type="button" class="btn btn-sm btn-success mt-2">{{ latestBlock.height - tx.blockHeight + 1 }} confirmation<ng-container *ngIf="latestBlock.height - tx.blockHeight + 1 > 1">s</ng-container></button>
|
||||
<button type="button" class="btn btn-sm btn-success mt-2">
|
||||
<ng-container *ngTemplateOutlet="latestBlock.height - tx.blockHeight + 1 == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: latestBlock.height - tx.blockHeight + 1}"></ng-container>
|
||||
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
|
||||
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
|
||||
</button>
|
||||
|
||||
</span>
|
||||
<button type="button" class="btn btn-sm btn-primary mt-2" (click)="switchCurrency()">
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
<h2 i18n="about.about-the-project">About the project</h2>
|
||||
<div class="row row-cols-1">
|
||||
<div class="col col-md-6 offset-md-3">
|
||||
<div class="col col-md-6 mx-auto">
|
||||
<p i18n>The mempool open-source project aims to implement a high quality explorer and visualization website for the entire Bitcoin ecosystem, without distractions like altcoins, advertising, or third-party trackers.</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -22,7 +22,7 @@
|
||||
<h2 i18n="about.maintainers">Maintainers</h2>
|
||||
|
||||
<div class="container text-center">
|
||||
<div class="row row-cols-2">
|
||||
<div class="row row-cols-2" dir="ltr">
|
||||
<div class="col col-md-2 offset-md-4">
|
||||
<a href="https://twitter.com/softsimon_">
|
||||
<div class="profile_photo mx-auto" style="background-image: url(/resources/profile_softsimon.jpg)"></div>
|
||||
@ -62,7 +62,7 @@
|
||||
|
||||
<button type="button" class="btn btn-primary" (click)="donationStatus = 2" [hidden]="donationStatus !== 1" i18n="about.become-a-sponsor">Become a sponsor ❤️</button>
|
||||
<p *ngIf="donationStatus === 2 && !sponsorsEnabled">
|
||||
<span i18n="about.navigate-to">Navigate to</span> <a href="https://mempool.space/about" target="_blank">https://mempool.space/about</a> <span i18n="about.to-sponsor">to sponsor</span>
|
||||
<ng-container i18n="about.navigate-to-sponsor">Navigate to <a href="https://mempool.space/about" target="_blank">https://mempool.space/about</a> to sponsor</ng-container>
|
||||
</p>
|
||||
|
||||
<div style="max-width: 300px;" class="mx-auto" [hidden]="donationStatus !== 2 || !sponsorsEnabled">
|
||||
@ -178,19 +178,19 @@
|
||||
|
||||
<br><br><br><br>
|
||||
|
||||
<a target="_blank" class="mr-4 fw6 mb3 mt2 truncate black-80 f4 link" href="https://github.com/mempool/mempool">
|
||||
<a target="_blank" class="m-2 fw6 mb3 mt2 truncate black-80 f4 link" href="https://github.com/mempool/mempool">
|
||||
<span class="dib v-mid">
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="github" class="svg-inline--fa fa-github fa-w-16 fa-3x" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path></svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a target="_blank" class="mr-4 fw6 mb3 mt2 truncate black-80 f4 link" href="https://twitter.com/mempoolspace">
|
||||
<a target="_blank" class="m-2 fw6 mb3 mt2 truncate black-80 f4 link" href="https://twitter.com/mempoolspace">
|
||||
<span class="dib v-mid">
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="twitter" class="svg-inline--fa fa-twitter fa-w-16 fa-3x" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"></path></svg>
|
||||
</span>
|
||||
</a>
|
||||
|
||||
<a target="_blank" class="fw6 mb3 mt2 truncate black-80 f4 link" href="https://keybase.io/team/mempool">
|
||||
<a target="_blank" class="m-2 fw6 mb3 mt2 truncate black-80 f4 link" href="https://keybase.io/team/mempool">
|
||||
<span class="dib v-mid">
|
||||
<svg aria-hidden="true" focusable="false" data-prefix="fab" data-icon="keybase" class="svg-inline--fa fa-keybase fa-w-14 fa-3x" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M286.17 419a18 18 0 1 0 18 18 18 18 0 0 0-18-18zm111.92-147.6c-9.5-14.62-39.37-52.45-87.26-73.71q-9.1-4.06-18.38-7.27a78.43 78.43 0 0 0-47.88-104.13c-12.41-4.1-23.33-6-32.41-5.77-.6-2-1.89-11 9.4-35L198.66 32l-5.48 7.56c-8.69 12.06-16.92 23.55-24.34 34.89a51 51 0 0 0-8.29-1.25c-41.53-2.45-39-2.33-41.06-2.33-50.61 0-50.75 52.12-50.75 45.88l-2.36 36.68c-1.61 27 19.75 50.21 47.63 51.85l8.93.54a214 214 0 0 0-46.29 35.54C14 304.66 14 374 14 429.77v33.64l23.32-29.8a148.6 148.6 0 0 0 14.56 37.56c5.78 10.13 14.87 9.45 19.64 7.33 4.21-1.87 10-6.92 3.75-20.11a178.29 178.29 0 0 1-15.76-53.13l46.82-59.83-24.66 74.11c58.23-42.4 157.38-61.76 236.25-38.59 34.2 10.05 67.45.69 84.74-23.84.72-1 1.2-2.16 1.85-3.22a156.09 156.09 0 0 1 2.8 28.43c0 23.3-3.69 52.93-14.88 81.64-2.52 6.46 1.76 14.5 8.6 15.74 7.42 1.57 15.33-3.1 18.37-11.15C429 443 434 414 434 382.32c0-38.58-13-77.46-35.91-110.92zM142.37 128.58l-15.7-.93-1.39 21.79 13.13.78a93 93 0 0 0 .32 19.57l-22.38-1.34a12.28 12.28 0 0 1-11.76-12.79L107 119c1-12.17 13.87-11.27 13.26-11.32l29.11 1.73a144.35 144.35 0 0 0-7 19.17zm148.42 172.18a10.51 10.51 0 0 1-14.35-1.39l-9.68-11.49-34.42 27a8.09 8.09 0 0 1-11.13-1.08l-15.78-18.64a7.38 7.38 0 0 1 1.34-10.34l34.57-27.18-14.14-16.74-17.09 13.45a7.75 7.75 0 0 1-10.59-1s-3.72-4.42-3.8-4.53a7.38 7.38 0 0 1 1.37-10.34L214 225.19s-18.51-22-18.6-22.14a9.56 9.56 0 0 1 1.74-13.42 10.38 10.38 0 0 1 14.3 1.37l81.09 96.32a9.58 9.58 0 0 1-1.74 13.44zM187.44 419a18 18 0 1 0 18 18 18 18 0 0 0-18-18z"></path></svg>
|
||||
</span>
|
||||
|
@ -34,7 +34,7 @@ export class AboutComponent implements OnInit {
|
||||
|
||||
ngOnInit() {
|
||||
this.gitCommit$ = this.stateService.gitCommit$.pipe(map((str) => str.substr(0, 8)));
|
||||
this.seoService.setTitle('About');
|
||||
this.seoService.setTitle($localize`:@@004b222ff9ef9dd4771b777950ca1d0e4cd4348a:About`);
|
||||
this.websocketService.want(['blocks']);
|
||||
|
||||
this.donationForm = this.formBuilder.group({
|
||||
|
@ -43,7 +43,11 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2><ng-template [ngIf]="transactions?.length">{{ (transactions?.length | number) || '?' }} <span i18n="shared.of">of</span> </ng-template>{{ txCount | number }} <span i18n="shared.transactions">transactions</span></h2>
|
||||
<h2>
|
||||
<ng-template [ngIf]="!transactions?.length"> </ng-template>
|
||||
<ng-template i18n="X of X Address Transaction" [ngIf]="transactions?.length === 1">{{ (transactions?.length | number) || '?' }} of {{ txCount | number }} transaction</ng-template>
|
||||
<ng-template i18n="X of X Address Transactions (Plural)" [ngIf]="transactions?.length > 1">{{ (transactions?.length | number) || '?' }} of {{ txCount | number }} transactions</ng-template>
|
||||
</h2>
|
||||
|
||||
<app-transactions-list [transactions]="transactions" [showConfirmations]="true" (loadMore)="loadMore()"></app-transactions-list>
|
||||
|
||||
|
@ -61,7 +61,7 @@ export class AddressComponent implements OnInit, OnDestroy {
|
||||
this.transactions = null;
|
||||
document.body.scrollTo(0, 0);
|
||||
this.addressString = params.get('id') || '';
|
||||
this.seoService.setTitle('Address: ' + this.addressString);
|
||||
this.seoService.setTitle($localize`:@@address.component.browser-title:Address: ${this.addressString}:INTERPOLATION:`);
|
||||
|
||||
return merge(
|
||||
of(true),
|
||||
|
@ -1,7 +1,7 @@
|
||||
<ng-container *ngIf="{ val: network$ | async } as network">
|
||||
<div class="container-xl">
|
||||
<div class="text-center">
|
||||
<h2>{{ network.val === '' ? 'Bitcoin' : network.val.charAt(0).toUpperCase() + network.val.slice(1) }} API Service</h2>
|
||||
<h2>{{ network.val === '' ? 'Bitcoin' : network.val.charAt(0).toUpperCase() + network.val.slice(1) }} <ng-container i18n="api-docs.title">API Service</ng-container></h2>
|
||||
</div>
|
||||
|
||||
<ul ngbNav #nav="ngbNav" [(activeId)]="active" class="nav-tabs">
|
||||
|
@ -2,6 +2,7 @@ import { Component, OnInit } from '@angular/core';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
import { WebsocketService } from 'src/app/services/websocket.service';
|
||||
import { Observable, merge, of } from 'rxjs';
|
||||
import { SeoService } from 'src/app/services/seo.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-api-docs',
|
||||
@ -16,9 +17,11 @@ export class ApiDocsComponent implements OnInit {
|
||||
constructor(
|
||||
private stateService: StateService,
|
||||
private websocketService: WebsocketService,
|
||||
private seoService: SeoService,
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
this.seoService.setTitle($localize`:@@e351b40b3869a5c7d19c3d4918cb1ac7aaab95c4:API`);
|
||||
this.network$ = merge(of(''), this.stateService.networkChanged$);
|
||||
this.websocketService.want(['blocks']);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Component, HostListener, OnInit } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Component, HostListener, OnInit, Inject, LOCALE_ID, HostBinding } from '@angular/core';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import { WebsocketService } from '../../services/websocket.service';
|
||||
import { StateService } from 'src/app/services/state.service';
|
||||
@ -17,8 +17,14 @@ export class AppComponent implements OnInit {
|
||||
private websocketService: WebsocketService,
|
||||
private stateService: StateService,
|
||||
private location: Location,
|
||||
) { }
|
||||
@Inject(LOCALE_ID) private locale: string,
|
||||
) {
|
||||
if (this.locale.startsWith('ar') || this.locale.startsWith('fa')) {
|
||||
this.dir = 'rtl';
|
||||
}
|
||||
}
|
||||
|
||||
@HostBinding('attr.dir') dir = 'ltr';
|
||||
@HostListener('document:keydown', ['$event'])
|
||||
handleKeyboardEvents(event: KeyboardEvent) {
|
||||
if (event.target instanceof HTMLInputElement) {
|
||||
|
@ -72,7 +72,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2><ng-template [ngIf]="transactions?.length">{{ (transactions?.length | number) || '?' }} of </ng-template>{{ txCount | number }} <ng-template [ngIf]="isNativeAsset" [ngIfElse]="defaultAsset">Peg In/Out and Burn Transactions</ng-template><ng-template #defaultAsset>In/Out and Burn Transactions</ng-template></h2>
|
||||
<h2><ng-template [ngIf]="transactions?.length">{{ (transactions?.length | number) || '?' }} of </ng-template>{{ txCount | number }} <ng-template [ngIf]="isNativeAsset" [ngIfElse]="defaultAsset" i18n="Liquid native asset transactions title">Peg In/Out and Burn Transactions</ng-template><ng-template #defaultAsset i18n="Default asset transactions title">Issuance and Burn Transactions</ng-template></h2>
|
||||
|
||||
<app-transactions-list [transactions]="transactions" [showConfirmations]="true" (loadMore)="loadMore()"></app-transactions-list>
|
||||
|
||||
|
@ -70,7 +70,7 @@ export class AssetComponent implements OnInit, OnDestroy {
|
||||
this.transactions = null;
|
||||
document.body.scrollTo(0, 0);
|
||||
this.assetString = params.get('id') || '';
|
||||
this.seoService.setTitle('Asset: ' + this.assetString);
|
||||
this.seoService.setTitle($localize`:@@asset.component.asset-browser-title:Asset: ${this.assetString}:INTERPOLATION:`);
|
||||
|
||||
return merge(
|
||||
of(true),
|
||||
|
@ -43,7 +43,7 @@
|
||||
<tbody>
|
||||
<tr *ngIf="block.medianFee !== undefined">
|
||||
<td class="td-width" i18n="block.median-fee">Median fee</td>
|
||||
<td>~{{ block.medianFee | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="block.medianFee * 140" digitsInfo="1.2-2" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)</td>
|
||||
<td>~{{ block.medianFee | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="block.medianFee * 140" digitsInfo="1.2-2" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)</td>
|
||||
</tr>
|
||||
<ng-template [ngIf]="fees !== undefined" [ngIfElse]="loadingFees">
|
||||
<tr>
|
||||
@ -82,7 +82,11 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2 class="float-left">{{ block.tx_count | number }} <ng-template [ngIf]="block.tx_count === 1" i18n="shared.transaction-count.singular">transaction</ng-template><ng-template [ngIf]="block.tx_count !== 1" i18n="shared.transaction-count.plural">transactions</ng-template></h2>
|
||||
<h2 class="float-left">
|
||||
<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="float-right" [collectionSize]="block.tx_count" [rotate]="true" [pageSize]="itemsPerPage" [(page)]="page" (pageChange)="pageChange(page)" [maxSize]="paginationMaxSize" [boundaryLinks]="true"></ngb-pagination>
|
||||
|
||||
|
@ -95,7 +95,7 @@ export class BlockComponent implements OnInit, OnDestroy {
|
||||
tap((block: Block) => {
|
||||
this.block = block;
|
||||
this.blockHeight = block.height;
|
||||
this.seoService.setTitle('Block: #' + block.height + ': ' + block.id);
|
||||
this.seoService.setTitle($localize`:@@block.component.browser-title:Block ${block.height}:BLOCK_HEIGHT:: ${block.id}:BLOCK_ID:`);
|
||||
this.isLoadingBlock = false;
|
||||
if (block.coinbaseTx) {
|
||||
this.coinbaseTx = block.coinbaseTx;
|
||||
|
@ -7,13 +7,17 @@
|
||||
</div>
|
||||
<div class="block-body">
|
||||
<div class="fees">
|
||||
~{{ block.medianFee | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span>
|
||||
~{{ block.medianFee | number:'1.0-0' }} <ng-container i18n="shared.sat-vbyte|sat/vB">sat/vB</ng-container>
|
||||
</div>
|
||||
<div class="fee-span">
|
||||
{{ block.feeRange[1] | number:'1.0-0' }} - {{ block.feeRange[block.feeRange.length - 1] | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span>
|
||||
{{ block.feeRange[1] | number:'1.0-0' }} - {{ block.feeRange[block.feeRange.length - 1] | number:'1.0-0' }} <ng-container i18n="shared.sat-vbyte|sat/vB">sat/vB</ng-container>
|
||||
</div>
|
||||
<div class="block-size">{{ block.size | bytes: 2 }}</div>
|
||||
<div class="transaction-count">{{ block.tx_count | number }} <ng-template [ngIf]="block.tx_count === 1" i18n="shared.transaction">transaction</ng-template><ng-template [ngIf]="block.tx_count !== 1" i18n="shared.transactions">transactions</ng-template></div>
|
||||
<div class="transaction-count">
|
||||
<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>
|
||||
</div>
|
||||
<div class="time-difference"><app-time-since [time]="block.timestamp" [fastRender]="true"></app-time-since></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<span #buttonWrapper [attr.data-tlite]="'Copied!'" style="position: relative;">
|
||||
<span #buttonWrapper [attr.data-tlite]="copiedMessage" style="position: relative;">
|
||||
<button #btn class="btn btn-sm btn-link pt-0" style="line-height: 0.9;" [attr.data-clipboard-text]="text">
|
||||
<img src="./resources/clippy.svg" width="13">
|
||||
</button>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Component, OnInit, ViewChild, ElementRef, AfterViewInit, Input, ChangeDetectionStrategy } from '@angular/core';
|
||||
import { Component, ViewChild, ElementRef, AfterViewInit, Input, ChangeDetectionStrategy } from '@angular/core';
|
||||
import * as ClipboardJS from 'clipboard';
|
||||
import * as tlite from 'tlite';
|
||||
|
||||
@ -12,6 +12,7 @@ export class ClipboardComponent implements AfterViewInit {
|
||||
@ViewChild('btn') btn: ElementRef;
|
||||
@ViewChild('buttonWrapper') buttonWrapper: ElementRef;
|
||||
@Input() text: string;
|
||||
copiedMessage: string = $localize`:@@clipboard.copied-message:Copied!`;
|
||||
|
||||
clipboard: any;
|
||||
|
||||
@ -19,7 +20,7 @@ export class ClipboardComponent implements AfterViewInit {
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.clipboard = new ClipboardJS(this.btn.nativeElement);
|
||||
this.clipboard.on('success', (e) => {
|
||||
this.clipboard.on('success', () => {
|
||||
tlite.show(this.buttonWrapper.nativeElement);
|
||||
setTimeout(() => {
|
||||
tlite.hide(this.buttonWrapper.nativeElement);
|
||||
|
@ -3,19 +3,19 @@
|
||||
<td class="d-none d-md-block">
|
||||
<h5 class="card-title" i18n="fees-box.low-priority">Low priority</h5>
|
||||
<p class="card-text">
|
||||
{{ feeEstimations.hourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="feeEstimations.hourFee * 140" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)
|
||||
{{ feeEstimations.hourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="feeEstimations.hourFee * 140" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<h5 class="card-title" i18n="fees-box.medium-priority">Medium priority</h5>
|
||||
<p class="card-text">
|
||||
{{ feeEstimations.halfHourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="feeEstimations.halfHourFee * 140" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)
|
||||
{{ feeEstimations.halfHourFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="feeEstimations.halfHourFee * 140" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
<h5 class="card-title" i18n="fees-box.high-priority">High priority</h5>
|
||||
<p class="card-text">
|
||||
{{ feeEstimations.fastestFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="feeEstimations.fastestFee * 140" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)
|
||||
{{ feeEstimations.fastestFee }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="feeEstimations.fastestFee * 140" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="container-xl">
|
||||
<h1 style="float: left;">Blocks</h1>
|
||||
<h1 style="float: left;" i18n="latest-blocks.blocks">Blocks</h1>
|
||||
<br>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
@ -10,7 +10,7 @@
|
||||
<th class="d-none d-md-block" style="width: 20%;" i18n="latest-blocks.timestamp">Timestamp</th>
|
||||
<th style="width: 20%;" i18n="latest-blocks.mined">Mined</th>
|
||||
<th class="d-none d-lg-block" style="width: 15%;" i18n="latest-blocks.transactions">Transactions</th>
|
||||
<th style="width: 20%;" i18n="latest-blocks.filled">Filled</th>
|
||||
<th style="width: 20%;" i18n="latest-blocks.size">Size</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let block of blocks; let i= index; trackBy: trackByBlock">
|
||||
|
@ -34,7 +34,7 @@ export class LatestBlocksComponent implements OnInit, OnDestroy {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.setTitle('Blocks');
|
||||
this.seoService.setTitle($localize`:@@f4cba7faeb126346f09cc6af30124f9a343f7a28:Blocks`);
|
||||
this.websocketService.want(['blocks']);
|
||||
|
||||
this.network$ = merge(of(''), this.stateService.networkChanged$);
|
||||
|
@ -26,37 +26,37 @@
|
||||
<ul class="navbar-nav mr-auto pt-2 pb-2 pb-md-0 pt-md-0 {{ network.val }}">
|
||||
<ng-template [ngIf]="network.val === 'bisq'" [ngIfElse]="notBisq">
|
||||
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
|
||||
<a class="nav-link" [routerLink]="['/bisq']" (click)="collapse()"><fa-icon [icon]="['fas', 'list']" [fixedWidth]="true" title="Transactions"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/bisq']" (click)="collapse()"><fa-icon [icon]="['fas', 'list']" [fixedWidth]="true" i18n-title="master-page.transactions" title="Transactions"></fa-icon></a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/bisq/blocks']" (click)="collapse()"><fa-icon [icon]="['fas', 'cubes']" [fixedWidth]="true" title="Blocks"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/bisq/blocks']" (click)="collapse()"><fa-icon [icon]="['fas', 'cubes']" [fixedWidth]="true" i18n-title="master-page.blocks" title="Blocks"></fa-icon></a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/bisq/stats']" (click)="collapse()"><fa-icon [icon]="['fas', 'tachometer-alt']" [fixedWidth]="true" title="Stats"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/bisq/stats']" (click)="collapse()"><fa-icon [icon]="['fas', 'tachometer-alt']" [fixedWidth]="true" i18n-title="master-page.stats" title="Stats"></fa-icon></a>
|
||||
</li>
|
||||
</ng-template>
|
||||
<ng-template #notBisq>
|
||||
<li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{exact: true}">
|
||||
<a class="nav-link" [routerLink]="['/' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tachometer-alt']" [fixedWidth]="true" title="Dashboard"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tachometer-alt']" [fixedWidth]="true" i18n-title="master-page.dashboard" title="Dashboard"></fa-icon></a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/blocks' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'cubes']" [fixedWidth]="true" title="Blocks"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/blocks' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'cubes']" [fixedWidth]="true" i18n-title="master-page.blocks" title="Blocks"></fa-icon></a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/graphs' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'chart-area']" [fixedWidth]="true" title="Graphs"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/graphs' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'chart-area']" [fixedWidth]="true" i18n-title="master-page.graphs" title="Graphs"></fa-icon></a>
|
||||
</li>
|
||||
<li class="nav-item d-none d-sm-block" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/tv' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tv']" [fixedWidth]="true" title="Full screen TV view"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/tv' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'tv']" [fixedWidth]="true" i18n-title="master-page.tvview" title="TV view"></fa-icon></a>
|
||||
</li>
|
||||
</ng-template>
|
||||
<li *ngIf="network.val === 'liquid'" class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/liquid/assets']" (click)="collapse()"><fa-icon [icon]="['fas', 'database']" [fixedWidth]="true" title="Assets"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/liquid/assets']" (click)="collapse()"><fa-icon [icon]="['fas', 'database']" [fixedWidth]="true" i18n-title="master-page.assets" title="Assets"></fa-icon></a>
|
||||
</li>
|
||||
<li [hidden]="isMobile" class="nav-item mr-2" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/api' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'cogs']" [fixedWidth]="true" title="API"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/api' | relativeUrl]" (click)="collapse()"><fa-icon [icon]="['fas', 'cogs']" [fixedWidth]="true" i18n-title="master-page.api" title="API"></fa-icon></a>
|
||||
</li>
|
||||
<li class="nav-item" routerLinkActive="active">
|
||||
<a class="nav-link" [routerLink]="['/about']" (click)="collapse()"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" title="About"></fa-icon></a>
|
||||
<a class="nav-link" [routerLink]="['/about']" (click)="collapse()"><fa-icon [icon]="['fas', 'info-circle']" [fixedWidth]="true" i18n-title="master-page.about" title="About"></fa-icon></a>
|
||||
</li>
|
||||
</ul>
|
||||
<app-search-form location="top" (searchTriggered)="collapse()"></app-search-form>
|
||||
|
@ -14,11 +14,11 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td i18n="mempool-block.median-fee">Median fee</td>
|
||||
<td>~{{ mempoolBlock.medianFee | number:'1.0-0' }} sat/vB (<app-fiat [value]="mempoolBlock.medianFee * 140" digitsInfo="1.2-2" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)</td>
|
||||
<td>~{{ mempoolBlock.medianFee | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span> (<app-fiat [value]="mempoolBlock.medianFee * 140" digitsInfo="1.2-2" i18n-ngbTooltip="Transaction fee tooltip" ngbTooltip="Based on average native segwit transaction of 140 vBytes" placement="bottom"></app-fiat>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td i18n="mempool-block.fee-span">Fee span</td>
|
||||
<td><span class="yellow-color">{{ mempoolBlock.feeRange[0] | number:'1.0-0' }} - {{ mempoolBlock.feeRange[mempoolBlock.feeRange.length - 1] | number:'1.0-0' }} sat/vB</span></td>
|
||||
<td><span class="yellow-color">{{ mempoolBlock.feeRange[0] | number:'1.0-0' }} - {{ mempoolBlock.feeRange[mempoolBlock.feeRange.length - 1] | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td i18n="mempool-block.total-fees">Total fees</td>
|
||||
@ -29,7 +29,7 @@
|
||||
<td>{{ mempoolBlock.nTx }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td i18n="mempool-block.filled">Filled</td>
|
||||
<td i18n="mempool-block.size">Size</td>
|
||||
<td>
|
||||
<div class="progress position-relative">
|
||||
<div class="progress-bar progress-mempool {{ (network$ | async) }}" role="progressbar" [ngStyle]="{'width': (mempoolBlock.blockVSize / 1000000) * 100 + '%' }"></div>
|
||||
|
@ -68,13 +68,11 @@ export class MempoolBlockComponent implements OnInit, OnDestroy {
|
||||
getOrdinal(mempoolBlock: MempoolBlock): string {
|
||||
const blocksInBlock = Math.ceil(mempoolBlock.blockVSize / 1000000);
|
||||
if (this.mempoolBlockIndex === 0) {
|
||||
return 'Next block';
|
||||
} else if (this.mempoolBlockIndex === this.stateService.env.KEEP_BLOCKS_AMOUNT - 1 && blocksInBlock > 1 ) {
|
||||
return `Stack of ${blocksInBlock} blocks`;
|
||||
return $localize`:@@mempool-block.next.block:Next block`;
|
||||
} else if (this.mempoolBlockIndex === this.stateService.env.KEEP_BLOCKS_AMOUNT - 1 && blocksInBlock > 1) {
|
||||
return $localize`:@@mempool-block.stack.of.blocks:Stack of ${blocksInBlock}:INTERPOLATION: mempool blocks`;
|
||||
} else {
|
||||
const s = ['th', 'st', 'nd', 'rd'];
|
||||
const v = this.mempoolBlockIndex + 1 % 100;
|
||||
return this.mempoolBlockIndex + 1 + (s[(v - 20) % 10] || s[v] || s[0]) + ' next block';
|
||||
return $localize`:@@mempool-block.block.no:Mempool block ${this.mempoolBlockIndex + 1}:INTERPOLATION:`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,17 +11,24 @@
|
||||
{{ projectedBlock.feeRange[0] | number:'1.0-0' }} - {{ projectedBlock.feeRange[projectedBlock.feeRange.length - 1] | number:'1.0-0' }} <span i18n="shared.sat-vbyte|sat/vB">sat/vB</span>
|
||||
</div>
|
||||
<div class="block-size">{{ projectedBlock.blockSize | bytes: 2 }}</div>
|
||||
<div class="transaction-count">{{ projectedBlock.nTx | number }} <ng-template [ngIf]="projectedBlock.nTx === 1" i18n="shared.transaction-count.singular">transaction</ng-template><ng-template [ngIf]="projectedBlock.nTx !== 1" i18n="shared.transaction-count.plural">transactions</ng-template></div>
|
||||
<div class="transaction-count">
|
||||
<ng-container *ngTemplateOutlet="projectedBlock.nTx === 1 ? transactionsSingular : transactionsPlural; context: {$implicit: projectedBlock.nTx | 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>
|
||||
</div>
|
||||
<div class="time-difference" *ngIf="projectedBlock.blockVSize <= 1000000; else mergedBlock">
|
||||
<ng-template [ngIf]="network === 'liquid'" [ngIfElse]="timeDiffMainnet">
|
||||
<span i18n="mempool-blocks.eta-of-next-block|Block Frequency">In</span> < {{ 1 * i + 1 }} <span i18n="shared.minute">minute</span>
|
||||
<ng-container *ngTemplateOutlet="1 * i + 1 === 1 ? nextBlockEta : nextBlockEtaPlural; context:{ $implicit: 1 * i + 1 }"></ng-container>
|
||||
</ng-template>
|
||||
<ng-template #timeDiffMainnet>
|
||||
<span i18n="mempool-blocks.eta-of-next-block|Block Frequency">In</span> ~{{ 10 * i + 10 }} <span i18n="shared.minutes">minutes</span>
|
||||
<ng-container *ngTemplateOutlet="nextBlockEtaPlural; context:{ $implicit: 10 * i + 10 }"></ng-container>
|
||||
</ng-template>
|
||||
</div>
|
||||
<ng-template #mergedBlock>
|
||||
<div class="time-difference"><b>({{ projectedBlock.blockVSize / 1000000 | ceil }} <span i18n="shared.blocks">blocks</span>)</b></div>
|
||||
<div class="time-difference">
|
||||
<ng-container *ngTemplateOutlet="blocksPlural; context: {$implicit: projectedBlock.blockVSize / 1000000 | ceil }"></ng-container>
|
||||
<b>(<ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} blocks</ng-template>)</b>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
<span class="animated-border"></span>
|
||||
@ -30,3 +37,7 @@
|
||||
</div>
|
||||
<div *ngIf="arrowVisible" id="arrow-up" [ngStyle]="{'right': rightPosition + 75 + 'px', transition: transition }"></div>
|
||||
</div>
|
||||
|
||||
<ng-template let-i #nextBlockEtaPlural i18n="mempool-blocks.eta-of-next-block-plural|Block Frequency (plural)">In ~{{ i }} minutes</ng-template>
|
||||
|
||||
<ng-template let-i #nextBlockEta i18n="mempool-blocks.eta-of-next-block|Block Frequency">In ~{{ i }} minute</ng-template>
|
||||
|
@ -39,7 +39,7 @@ export class MinerComponent implements OnChanges {
|
||||
|
||||
if (pools.payout_addresses[vout.scriptpubkey_address]) {
|
||||
this.miner = pools.payout_addresses[vout.scriptpubkey_address].name;
|
||||
this.title = 'Identified by payout address: ' + vout.scriptpubkey_address;
|
||||
this.title = $localize`:@@miner-identified-by-payout:Identified by payout address: '${vout.scriptpubkey_address}:PAYOUT_ADDRESS:'`;
|
||||
this.url = pools.payout_addresses[vout.scriptpubkey_address].link;
|
||||
break;
|
||||
}
|
||||
@ -49,7 +49,7 @@ export class MinerComponent implements OnChanges {
|
||||
const coinbaseAscii = this.hex2ascii(this.coinbaseTransaction.vin[0].scriptsig);
|
||||
if (coinbaseAscii.indexOf(tag) > -1) {
|
||||
this.miner = pools.coinbase_tags[tag].name;
|
||||
this.title = 'Identified by coinbase tag: \'' + tag + '\'';
|
||||
this.title = $localize`:@@miner-identified-by-coinbase:Identified by coinbase tag: '${tag}:TAG:'`;
|
||||
this.url = pools.coinbase_tags[tag].link;
|
||||
break;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
<input #instance="ngbTypeahead" [ngbTypeahead]="typeaheadSearch" (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-form.searchbar-placeholder" placeholder="TXID, block height, hash or address">
|
||||
</div>
|
||||
<div>
|
||||
<button [disabled]="isSearching" type="submit" class="btn btn-block btn-primary"><fa-icon [icon]="['fas', 'search']" [fixedWidth]="true" title="Search"></fa-icon></button>
|
||||
<button [disabled]="isSearching" type="submit" class="btn btn-block btn-primary"><fa-icon [icon]="['fas', 'search']" [fixedWidth]="true" i18n-title="search-form.search-title" title="Search"></fa-icon></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -40,12 +40,12 @@
|
||||
<input ngbButton type="radio" [value]="'1y'" [routerLink]="['/graphs' | relativeUrl]" fragment="1y"> 1Y
|
||||
</label>
|
||||
</div>
|
||||
<button (click)="invertGraph()" class="btn btn-primary btn-sm ml-2 d-none d-md-inline"><fa-icon [icon]="['fas', 'exchange-alt']" [rotate]="90" [fixedWidth]="true" title="Invert"></fa-icon></button>
|
||||
<button (click)="invertGraph()" class="btn btn-primary btn-sm ml-2 d-none d-md-inline"><fa-icon [icon]="['fas', 'exchange-alt']" [rotate]="90" [fixedWidth]="true" i18n-title="statistics.component-invert.title" title="Invert"></fa-icon></button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div style="height: 600px;">
|
||||
<app-mempool-graph [data]="mempoolStats" [dateSpan]="radioGroupForm.controls.dateSpan.value"></app-mempool-graph>
|
||||
<app-mempool-graph dir="ltr" [data]="mempoolStats" [dateSpan]="radioGroupForm.controls.dateSpan.value"></app-mempool-graph>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,7 +52,7 @@ export class StatisticsComponent implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.setTitle('Graphs');
|
||||
this.seoService.setTitle($localize`:@@5d4f792f048fcaa6df5948575d7cb325c9393383:Graphs`);
|
||||
this.stateService.networkChanged$.subscribe((network) => this.network = network);
|
||||
this.inverted = this.storageService.getValue('inverted-graph') === 'true';
|
||||
const isMobile = window.innerWidth <= 767.98;
|
||||
|
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
|
||||
<div class="chart-holder" *ngIf="mempoolStats.length">
|
||||
<app-mempool-graph [data]="mempoolStats"></app-mempool-graph>
|
||||
<app-mempool-graph dir="ltr" [data]="mempoolStats"></app-mempool-graph>
|
||||
</div>
|
||||
|
||||
<div class="text-center" class="blockchain-wrapper">
|
||||
|
@ -24,7 +24,7 @@ export class TelevisionComponent implements OnInit {
|
||||
) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.seoService.setTitle('TV view');
|
||||
this.seoService.setTitle($localize`:@@46ce8155c9ab953edeec97e8950b5a21e67d7c4e:TV view`);
|
||||
this.websocketService.want(['blocks', 'live-2h-chart', 'mempool-blocks']);
|
||||
|
||||
this.apiService.list2HStatistics$()
|
||||
|
@ -12,7 +12,11 @@
|
||||
<h1 class="float-left mr-3 mb-md-3" i18n="shared.transaction">Transaction</h1>
|
||||
|
||||
<ng-template [ngIf]="tx?.status?.confirmed">
|
||||
<button *ngIf="latestBlock" type="button" class="btn btn-sm btn-success float-right mr-2 mt-1 mt-md-3">{{ latestBlock.height - tx.status.block_height + 1 }} <ng-container *ngIf="latestBlock.height - tx.status.block_height + 1 == 1" i18n="shared.confirmation-count.singular|Transaction singular confirmation count">confirmation</ng-container><ng-container *ngIf="latestBlock.height - tx.status.block_height + 1 > 1" i18n="shared.confirmation-count.plural|Transaction plural confirmation count">confirmations</ng-container></button>
|
||||
<button *ngIf="latestBlock" type="button" class="btn btn-sm btn-success float-right mr-2 mt-1 mt-md-3">
|
||||
<ng-container *ngTemplateOutlet="latestBlock.height - tx.status.block_height + 1 == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: latestBlock.height - tx.status.block_height + 1}"></ng-container>
|
||||
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
|
||||
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
|
||||
</button>
|
||||
</ng-template>
|
||||
<ng-template [ngIf]="tx && !tx?.status.confirmed">
|
||||
<button type="button" class="btn btn-sm btn-danger float-right mr-2 mt-1 mt-md-3" i18n="transaction.unconfirmed|Transaction unconfirmed state">Unconfirmed</button>
|
||||
@ -56,7 +60,7 @@
|
||||
<ng-template [ngIf]="transactionTime > 0">
|
||||
<tr>
|
||||
<td i18n="transaction.confirmed|Transaction Confirmed state">Confirmed</td>
|
||||
<td><span i18n="transaction.confirmed.after|Transaction confirmed after">After</span> <app-timespan [time]="tx.status.block_time - transactionTime"></app-timespan></td>
|
||||
<td><ng-container i18n="transaction.confirmed.after|Transaction confirmed after">After <app-timespan [time]="tx.status.block_time - transactionTime"></app-timespan></ng-container></td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<tr *ngIf="network !== 'liquid'">
|
||||
@ -73,7 +77,7 @@
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="td-width" i18n="transaction.fee|Transaction fee">Fee</td>
|
||||
<td>{{ tx.fee | number }} sat (<app-fiat [value]="tx.fee"></app-fiat>)</td>
|
||||
<td>{{ tx.fee | number }} <span i18n="transaction.fee.sat|Transaction Fee sat">sat</span> (<app-fiat [value]="tx.fee"></app-fiat>)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td i18n="transaction.fee-per-vbyte|Transaction fee">Fee per vByte</td>
|
||||
@ -123,10 +127,10 @@
|
||||
</ng-template>
|
||||
<ng-template #belowBlockLimit>
|
||||
<ng-template [ngIf]="network === 'liquid'" [ngIfElse]="timeEstimateDefault">
|
||||
< {{ 1 * txInBlockIndex + 1 }} <span i18n="transaction.minutes|Transaction Minutes">minutes</span> <i>({{ txInBlockIndex + 1 }} <span i18n="transaction.eta.block|Transaction ETA (X blocks)">block</span>{{ txInBlockIndex > 0 ? 's' : '' }})</i>
|
||||
<ng-container *ngTemplateOutlet="1 * txInBlockIndex + 1 === 1 ? nextBlockEta : nextBlockEtaPlural; context:{ $implicit: 1 * txInBlockIndex + 1 }"></ng-container> <i>(<ng-container *ngTemplateOutlet="txInBlockIndex === 0 ? blocksSingular : blocksPlural; context: {$implicit: txInBlockIndex + 1 }"></ng-container>)</i>
|
||||
</ng-template>
|
||||
<ng-template #timeEstimateDefault>
|
||||
~{{ 10 * txInBlockIndex + 10 }} <span i18n="transaction.minutes|Transaction Minutes">minutes</span> <i>({{ txInBlockIndex + 1 }} <span i18n="transaction.eta.block|Transaction ETA (X blocks)">block</span>{{ txInBlockIndex > 0 ? 's' : '' }})</i>
|
||||
<ng-container *ngTemplateOutlet="nextBlockEtaPlural; context:{ $implicit: 10 * txInBlockIndex + 10 }"></ng-container> <i>(<ng-container *ngTemplateOutlet="txInBlockIndex === 0 ? blocksSingular : blocksPlural; context: {$implicit: txInBlockIndex + 1 }"></ng-container>)</i>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
@ -177,6 +181,10 @@
|
||||
<td i18n="transaction.size|Transaction Size">Size</td>
|
||||
<td>{{ tx.size | bytes: 2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td i18n="transaction.vsize|Transaction Virtual Size">Virtual size</td>
|
||||
<td>{{ tx.weight / 4 | vbytes: 2 }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td i18n="transaction.weight|Transaction Weight">Weight</td>
|
||||
<td>{{ tx.weight | wuBytes: 2 }}</td>
|
||||
@ -241,7 +249,7 @@
|
||||
|
||||
<br>
|
||||
|
||||
<h2>Details</h2>
|
||||
<h2 i18n="transaction.details">Details</h2>
|
||||
<div class="box">
|
||||
<table class="table table-borderless table-striped">
|
||||
<tbody>
|
||||
@ -253,6 +261,10 @@
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
<td><span class="skeleton-loader"></span></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@ -277,3 +289,10 @@
|
||||
</div>
|
||||
|
||||
<br>
|
||||
|
||||
<ng-template let-i #nextBlockEtaPlural i18n="mempool-blocks.eta-of-next-block-plural|Block Frequency (plural)">In ~{{ i }} minutes</ng-template>
|
||||
|
||||
<ng-template let-i #nextBlockEta i18n="mempool-blocks.eta-of-next-block|Block Frequency">In ~{{ i }} minute</ng-template>
|
||||
|
||||
<ng-template #blocksSingular let-i i18n="shared.block">{{ i }} block</ng-template>
|
||||
<ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} blocks</ng-template>
|
@ -45,7 +45,7 @@ export class TransactionComponent implements OnInit, OnDestroy {
|
||||
this.subscription = this.route.paramMap.pipe(
|
||||
switchMap((params: ParamMap) => {
|
||||
this.txId = params.get('id') || '';
|
||||
this.seoService.setTitle('Transaction: ' + this.txId);
|
||||
this.seoService.setTitle($localize`:@@bisq.transaction.browser-title:Transaction: ${this.txId}:INTERPOLATION:`);
|
||||
this.resetTransaction();
|
||||
return merge(
|
||||
of(true),
|
||||
|
@ -122,15 +122,17 @@
|
||||
</a>
|
||||
<ng-template #scriptpubkey_type>
|
||||
<ng-template [ngIf]="vout.pegout" [ngIfElse]="defaultscriptpubkey_type">
|
||||
<span i18n="transactions-list.peg-out-to">Peg-out to</span>
|
||||
<a [routerLink]="['/address/', vout.pegout.scriptpubkey_address]" title="{{ vout.pegout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.pegout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vout.pegout.scriptpubkey_address | shortenString : 35 }}</span>
|
||||
</a>
|
||||
<ng-container i18n="transactions-list.peg-out-to">Peg-out to <ng-container *ngTemplateOutlet="pegOutLink"></ng-container></ng-container>
|
||||
<ng-template #pegOutLink>
|
||||
<a [routerLink]="['/address/', vout.pegout.scriptpubkey_address]" title="{{ vout.pegout.scriptpubkey_address }}">
|
||||
<span class="d-block d-lg-none">{{ vout.pegout.scriptpubkey_address | shortenString : 16 }}</span>
|
||||
<span class="d-none d-lg-block">{{ vout.pegout.scriptpubkey_address | shortenString : 35 }}</span>
|
||||
</a>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
<ng-template #defaultscriptpubkey_type>
|
||||
<ng-template [ngIf]="vout.scriptpubkey_type === 'op_return'" [ngIfElse]="otherPubkeyType">
|
||||
<a placement="bottom" [ngbTooltip]="vout.scriptpubkey | hex2ascii">OP_RETURN</a> <span *ngIf="vout.scriptpubkey_asm !== 'OP_RETURN'" class="badge badge-secondary scriptmessage">{{ vout.scriptpubkey_asm | hex2ascii }}</span>
|
||||
<a placement="bottom" [ngbTooltip]="vout.scriptpubkey_asm | hex2ascii">OP_RETURN</a> <span *ngIf="vout.scriptpubkey_asm !== 'OP_RETURN'" class="badge badge-secondary scriptmessage">{{ vout.scriptpubkey_asm | hex2ascii }}</span>
|
||||
</ng-template>
|
||||
<ng-template #otherPubkeyType>{{ vout.scriptpubkey_type | scriptpubkeyType }}</ng-template>
|
||||
</ng-template>
|
||||
@ -198,7 +200,11 @@
|
||||
|
||||
<div class="float-right">
|
||||
<span *ngIf="showConfirmations && latestBlock$ | async as latestBlock">
|
||||
<button *ngIf="tx.status.confirmed; else unconfirmedButton" type="button" class="btn btn-sm btn-success mt-2">{{ latestBlock.height - tx.status.block_height + 1 }} <ng-container *ngIf="latestBlock.height - tx.status.block_height + 1 == 1" i18n="shared.confirmation-count.singular">confirmation</ng-container><ng-container *ngIf="latestBlock.height - tx.status.block_height + 1 > 1" i18n="shared.confirmation-count.plural">confirmations</ng-container></button>
|
||||
<button *ngIf="tx.status.confirmed; else unconfirmedButton" type="button" class="btn btn-sm btn-success mt-2">
|
||||
<ng-container *ngTemplateOutlet="latestBlock.height - tx.status.block_height + 1 == 1 ? confirmationSingular : confirmationPlural; context: {$implicit: latestBlock.height - tx.status.block_height + 1}"></ng-container>
|
||||
<ng-template #confirmationSingular let-i i18n="shared.confirmation-count.singular|Transaction singular confirmation count">{{ i }} confirmation</ng-template>
|
||||
<ng-template #confirmationPlural let-i i18n="shared.confirmation-count.plural|Transaction plural confirmation count">{{ i }} confirmations</ng-template>
|
||||
</button>
|
||||
<ng-template #unconfirmedButton>
|
||||
<button type="button" class="btn btn-sm btn-danger mt-2" i18n="transactions-list.unconfirmed">Unconfirmed</button>
|
||||
</ng-template>
|
||||
|
@ -1,22 +0,0 @@
|
||||
<!-- this component is only used for the angular string extractor -->{{counter}}
|
||||
<div>
|
||||
<span i18n="@@time-since.just-now">Just now</span>
|
||||
<span i18n="@@time-since.sec.ago">{{counter}} sec ago</span>
|
||||
<span i18n="@@time-since.secs.ago">{{counter}} secs ago</span>
|
||||
<span i18n="@@time-since.second.ago">{{counter}} second ago</span>
|
||||
<span i18n="@@time-since.seconds.ago">{{counter}} seconds ago</span>
|
||||
<span i18n="@@time-since.min.ago">{{counter}} min ago</span>
|
||||
<span i18n="@@time-since.mins.ago">{{counter}} mins ago</span>
|
||||
<span i18n="@@time-since.minute.ago">{{counter}} minute ago</span>
|
||||
<span i18n="@@time-since.minutes.ago">{{counter}} minutes ago</span>
|
||||
<span i18n="@@time-since.hour.ago">{{counter}} hour ago</span>
|
||||
<span i18n="@@time-since.hours.ago">{{counter}} hours ago</span>
|
||||
<span i18n="@@time-since.day.ago">{{counter}} day ago</span>
|
||||
<span i18n="@@time-since.days.ago">{{counter}} days ago</span>
|
||||
<span i18n="@@time-since.week.ago">{{counter}} week ago</span>
|
||||
<span i18n="@@time-since.weeks.ago">{{counter}} weeks ago</span>
|
||||
<span i18n="@@time-since.month.ago">{{counter}} month ago</span>
|
||||
<span i18n="@@time-since.months.ago">{{counter}} months ago</span>
|
||||
<span i18n="@@time-since.year.ago">{{counter}} year ago</span>
|
||||
<span i18n="@@time-since.years.ago">{{counter}} years ago</span>
|
||||
</div>
|
@ -1,10 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-translation-strings',
|
||||
templateUrl: './translation-strings.component.html'
|
||||
})
|
||||
export class TranslationStringsComponent {
|
||||
counter: string;
|
||||
constructor() { }
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
<span *ngIf="segwitGains.realizedGains && !segwitGains.potentialBech32Gains; else segwitTwo" class="badge badge-success mr-1" ngbTooltip="This transaction saved {{ segwitGains.realizedGains * 100 | number: '1.0-0' }}% on fees by using native SegWit-Bech32" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
|
||||
<span *ngIf="segwitGains.realizedGains && !segwitGains.potentialBech32Gains; else segwitTwo" class="badge badge-success mr-1" i18n-ngbTooltip="ngbTooltip about segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedGains * 100 | number: '1.0-0' }}% on fees by using native SegWit-Bech32" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
|
||||
<ng-template #segwitTwo>
|
||||
<span *ngIf="segwitGains.realizedGains && segwitGains.potentialBech32Gains else potentialP2shGains" class="badge badge-warning mr-1" ngbTooltip="This transaction saved {{ segwitGains.realizedGains * 100 | number: '1.0-0' }}% on fees by using SegWit and could save {{ segwitGains.potentialBech32Gains * 100 | number : '1.0-0' }}% more by fully upgrading to native SegWit-Bech32" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
|
||||
<span *ngIf="segwitGains.realizedGains && segwitGains.potentialBech32Gains else potentialP2shGains" class="badge badge-warning mr-1" i18n-ngbTooltip="ngbTooltip about double segwit gains" ngbTooltip="This transaction saved {{ segwitGains.realizedGains * 100 | number: '1.0-0' }}% on fees by using SegWit and could save {{ segwitGains.potentialBech32Gains * 100 | number : '1.0-0' }}% more by fully upgrading to native SegWit-Bech32" placement="bottom" i18n="tx-features.tag.segwit|SegWit">SegWit</span>
|
||||
<ng-template #potentialP2shGains>
|
||||
<span *ngIf="segwitGains.potentialP2shGains" class="badge badge-danger mr-1" ngbTooltip="This transaction could save {{ segwitGains.potentialBech32Gains * 100 | number : '1.0-0' }}% on fees by upgrading to native SegWit-Bech32 or {{ segwitGains.potentialP2shGains * 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.potentialP2shGains" class="badge badge-danger mr-1" i18n-ngbTooltip="ngbTooltip about missed out gains" ngbTooltip="This transaction could save {{ segwitGains.potentialBech32Gains * 100 | number : '1.0-0' }}% on fees by upgrading to native SegWit-Bech32 or {{ segwitGains.potentialP2shGains * 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>
|
||||
<span *ngIf="isRbfTransaction" class="badge badge-success" ngbTooltip="This transaction support Replace-By-Fee (RBF) allowing fee bumping" placement="bottom" i18n="tx-features.tag.rbf|RBF">RBF</span>
|
||||
<span *ngIf="isRbfTransaction" class="badge badge-success" i18n-ngbTooltip="RBF tooltip" ngbTooltip="This transaction support Replace-By-Fee (RBF) allowing fee bumping" placement="bottom" i18n="tx-features.tag.rbf|RBF">RBF</span>
|
||||
|
@ -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" title="Only ~{{ medianFeeNeeded }} 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" title="Only ~{{ medianFeeNeeded }} sat/vB was needed to get into this block" i18n="tx-fee-rating.overpaid.danger|TX Fee Rating is Danger">Overpaid {{ overpaidTimes }}x</span>
|
||||
<span *ngIf="feeRating === 2" class="badge badge-warning" placement="bottom" i18n-ngbTooltip="tx-fee-rating.warning-tooltip" ngbTooltip="Only ~{{ medianFeeNeeded }} 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.danger-tooltip" ngbTooltip="Only ~{{ medianFeeNeeded }} sat/vB was needed to get into this block" i18n="tx-fee-rating.overpaid.danger|TX Fee Rating is Danger">Overpaid {{ overpaidTimes }}x</span>
|
||||
|
@ -128,8 +128,8 @@
|
||||
|
||||
<button type="button" class="btn btn-secondary btn-sm d-block mx-auto" (click)="toggleCollapsed()">
|
||||
<div [ngSwitch]="collapseLevel">
|
||||
<fa-icon *ngSwitchCase="'three'" [icon]="['fas', 'angle-down']" [fixedWidth]="true" title="Collapse"></fa-icon>
|
||||
<fa-icon *ngSwitchDefault [icon]="['fas', 'angle-up']" [fixedWidth]="true" title="Expand"></fa-icon>
|
||||
<fa-icon *ngSwitchCase="'three'" [icon]="['fas', 'angle-down']" [fixedWidth]="true" i18n-title="dashboard.expand" title="Expand"></fa-icon>
|
||||
<fa-icon *ngSwitchDefault [icon]="['fas', 'angle-up']" [fixedWidth]="true" i18n-title="dashboard.collapse" title="Collapse"></fa-icon>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
@ -161,7 +161,9 @@
|
||||
<td>
|
||||
<h5 class="card-title" i18n="dashboard.mempool-size|Mempool size">Mempool size</h5>
|
||||
<p class="card-text" *ngIf="(mempoolBlocksData$ | async) as mempoolBlocksData; else loading">
|
||||
{{ mempoolBlocksData.size | bytes }} ({{ mempoolBlocksData.blocks }} <span [hidden]="mempoolBlocksData.blocks == 1" i18n="dashboard.block">block</span><span [hidden]="mempoolBlocksData.blocks != 1">blocks</span>)
|
||||
{{ mempoolBlocksData.size | bytes }} (<ng-container *ngTemplateOutlet="mempoolBlocksData.blocks === 1 ? blocksSingular : blocksPlural; context: {$implicit: mempoolBlocksData.blocks }"></ng-container>)
|
||||
<ng-template #blocksSingular let-i i18n="shared.block">{{ i }} block</ng-template>
|
||||
<ng-template #blocksPlural let-i i18n="shared.blocks">{{ i }} blocks</ng-template>
|
||||
</p>
|
||||
</td>
|
||||
<td>
|
||||
@ -182,7 +184,7 @@
|
||||
</span>
|
||||
<ng-template #inSync>
|
||||
<div class="progress sub-text" style="max-width: 250px;">
|
||||
<div class="progress-bar {{ mempoolInfoData.value.progressClass }}" style="padding: 4px;" role="progressbar" [ngStyle]="{'width': mempoolInfoData.value.progressWidth}">{{ mempoolInfoData.value.vBytesPerSecond | ceil | number }} <ng-template i18n="shared.vbytes-per-second|vB/s">vB/s</ng-template></div>
|
||||
<div class="progress-bar {{ mempoolInfoData.value.progressClass }}" style="padding: 4px;" role="progressbar" [ngStyle]="{'width': mempoolInfoData.value.progressWidth}">{{ mempoolInfoData.value.vBytesPerSecond | ceil | number }} <ng-container i18n="shared.vbytes-per-second|vB/s">vB/s</ng-container></div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
|
@ -256,9 +256,9 @@ export class DashboardComponent implements OnInit {
|
||||
|
||||
changeLanguage() {
|
||||
const language = this.languageForm.get('language').value;
|
||||
this.document.location.href = (language === 'en' ? '/' : '/' + language);
|
||||
try {
|
||||
document.cookie = `lang=${language}; expires=Thu, 18 Dec 2050 12:00:00 UTC; path=/`;
|
||||
} catch (e) { }
|
||||
this.document.location.href = `${language === 'en' ? '' : '/' + language}/${this.stateService.network}`;
|
||||
}
|
||||
}
|
||||
|
2735
frontend/src/locale/messages.ar.xlf
Normal file
2735
frontend/src/locale/messages.ar.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2604
frontend/src/locale/messages.fi_FI.xlf
Normal file
2604
frontend/src/locale/messages.fi_FI.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2763
frontend/src/locale/messages.ka.xlf
Normal file
2763
frontend/src/locale/messages.ka.xlf
Normal file
File diff suppressed because it is too large
Load Diff
2812
frontend/src/locale/messages.nb.xlf
Normal file
2812
frontend/src/locale/messages.nb.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2575
frontend/src/locale/messages.vi.xlf
Normal file
2575
frontend/src/locale/messages.vi.xlf
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -102,10 +102,12 @@ Log notice syslog
|
||||
|
||||
CookieAuthentication 1
|
||||
CookieAuthFileGroupReadable 1
|
||||
CookieAuthFile /var/db/tor/control_auth_cookie
|
||||
DataDirectory /var/db/tor
|
||||
DataDirectoryGroupReadable 1
|
||||
|
||||
HiddenServiceDir /var/db/tor/mempool
|
||||
HiddenServicePort 80 127.0.0.1:81
|
||||
HiddenServicePort 80 127.0.0.1:80
|
||||
HiddenServiceVersion 3
|
||||
```
|
||||
|
||||
|
@ -33,23 +33,21 @@
|
||||
|
||||
# fallback for all URLs i.e. /address/foo /tx/foo /block/000
|
||||
location / {
|
||||
#return 302 https://mempool.space/$request_uri;
|
||||
try_files /$lang/$uri /$lang/$uri/ $uri $uri/ /en-US/$uri @index;
|
||||
# /$lang/index.html /en-US/index.html =404;
|
||||
try_files /$lang/$uri /$lang/$uri/ $uri $uri/ /en-US/$uri @index-redirect;
|
||||
}
|
||||
location @index {
|
||||
add_header Cache-Control must-revalidate;
|
||||
try_files /$lang/index.html /en-US/index.html =404;
|
||||
location @index-redirect {
|
||||
add_header vary accept-language;
|
||||
rewrite (.*) /$lang/index.html;
|
||||
}
|
||||
|
||||
# location block using regex are matched in order
|
||||
|
||||
# used to rewrite resources from /<lang>/ to /en-US/
|
||||
location ~ ^/(ar|bg|bs|ca|cs|da|de|et|el|es|eo|eu|fa|fr|gl|ko|hr|id|it|he|ka|lv|lt|hu|mk|ms|nl|ja|no|nb|nn|pl|pt|pt-BR|ro|ru|sk|sl|sr|sh|fi|sv|th|tr|uk|vi|zh)/resources/ {
|
||||
location ~ ^/(ar|bg|bs|ca|cs|da|de|et|el|es|eo|eu|fa|fr|gl|ko|hr|id|it|he|ka|lv|lt|hu|mk|ms|nl|ja|ka|no|nb|nn|pl|pt|pt-BR|ro|ru|sk|sl|sr|sh|fi|sv|th|tr|uk|vi|zh)/resources/ {
|
||||
rewrite ^/[a-zA-Z-]*/resources/(.*) /en-US/resources/$1;
|
||||
}
|
||||
# used for cookie override
|
||||
location ~ ^/(ar|bg|bs|ca|cs|da|de|et|el|es|eo|eu|fa|fr|gl|ko|hr|id|it|he|ka|lv|lt|hu|mk|ms|nl|ja|no|nb|nn|pl|pt|pt-BR|ro|ru|sk|sl|sr|sh|fi|sv|th|tr|uk|vi|zh)/ {
|
||||
location ~ ^/(ar|bg|bs|ca|cs|da|de|et|el|es|eo|eu|fa|fr|gl|ko|hr|id|it|he|ka|lv|lt|hu|mk|ms|nl|ja|ka|no|nb|nn|pl|pt|pt-BR|ro|ru|sk|sl|sr|sh|fi|sv|th|tr|uk|vi|zh)/ {
|
||||
try_files $uri $uri/ /$1/index.html =404;
|
||||
}
|
||||
|
||||
|
@ -54,25 +54,37 @@ http {
|
||||
proxy_cache_path /var/cache/nginx keys_zone=cache:20m levels=1:2 inactive=600s max_size=500m;
|
||||
types_hash_max_size 2048;
|
||||
|
||||
# exempt localhost from rate limit
|
||||
geo $limited_ip {
|
||||
default 1;
|
||||
127.0.0.1 0;
|
||||
}
|
||||
map $limited_ip $limited_ip_key {
|
||||
1 $binary_remote_addr;
|
||||
0 '';
|
||||
}
|
||||
|
||||
# rate limit requests
|
||||
limit_req_zone $binary_remote_addr zone=api:5m rate=200r/m;
|
||||
limit_req_zone $binary_remote_addr zone=electrs:5m rate=2000r/m;
|
||||
limit_req_zone $limited_ip_key zone=api:5m rate=200r/m;
|
||||
limit_req_zone $limited_ip_key zone=electrs:5m rate=2000r/m;
|
||||
limit_req_status 429;
|
||||
|
||||
# rate limit connections
|
||||
limit_conn_zone $binary_remote_addr zone=websocket:10m;
|
||||
limit_conn_zone $limited_ip_key zone=websocket:10m;
|
||||
limit_conn_status 429;
|
||||
|
||||
map $http_accept_language $header_lang {
|
||||
default en-US;
|
||||
~*^en-US en-US;
|
||||
~*^en en-US;
|
||||
~*^ar ar;
|
||||
~*^cs cs;
|
||||
~*^de de;
|
||||
~*^es es;
|
||||
~*^fa fa;
|
||||
~*^fr fr;
|
||||
~*^ja ja;
|
||||
~*^ka ka;
|
||||
~*^nl nl;
|
||||
~*^nn nn;
|
||||
~*^pt pt;
|
||||
@ -80,6 +92,7 @@ http {
|
||||
~*^sv sv;
|
||||
~*^tr tr;
|
||||
~*^uk uk;
|
||||
~*^vi vi;
|
||||
~*^zh zh;
|
||||
}
|
||||
|
||||
@ -87,12 +100,14 @@ http {
|
||||
default $header_lang;
|
||||
~*^en-US en-US;
|
||||
~*^en en-US;
|
||||
~*^ar ar;
|
||||
~*^cs cs;
|
||||
~*^de de;
|
||||
~*^es es;
|
||||
~*^fa fa;
|
||||
~*^fr fr;
|
||||
~*^ja ja;
|
||||
~*^ka ka;
|
||||
~*^nl nl;
|
||||
~*^nn nn;
|
||||
~*^pt pt;
|
||||
@ -100,6 +115,7 @@ http {
|
||||
~*^sv sv;
|
||||
~*^tr tr;
|
||||
~*^uk uk;
|
||||
~*^vi vi;
|
||||
~*^zh zh;
|
||||
}
|
||||
|
||||
@ -153,7 +169,7 @@ http {
|
||||
}
|
||||
|
||||
server {
|
||||
listen 127.0.0.1:81;
|
||||
listen 127.0.0.1:80;
|
||||
listen 443 ssl default http2 backlog=1024;
|
||||
server_name mempool.space;
|
||||
ssl_certificate /usr/local/etc/letsencrypt/live/mempool.space/fullchain.pem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user