Explorer redesign part 2

This commit is contained in:
Martin Boehm 2022-11-08 12:08:47 +01:00 committed by Martin
parent a939b2d93f
commit 3e816b931f
8 changed files with 416 additions and 263 deletions

View File

@ -51,6 +51,10 @@ a:hover {
padding: 0.75rem 1rem; padding: 0.75rem 1rem;
} }
#header .container {
min-height: 50px;
}
.bb-group { .bb-group {
border: 0.6rem solid #F6F6F6; border: 0.6rem solid #F6F6F6;
background-color: #F6F6F6; background-color: #F6F6F6;
@ -244,16 +248,179 @@ span.btn-paging:hover {
width: 128px; width: 128px;
height: 32px; height: 32px;
position: absolute; position: absolute;
top: 15px; top: 16px;
background-size: cover; background-size: cover;
background-image: url("data:image/svg+xml, %3Csvg style='width: 128px%3B' version='1.1' xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 163.7 41.9' space='preserve'%3E%3Cpolygon points='101.1 12.8 118.2 12.8 118.2 17.3 108.9 29.9 118.2 29.9 118.2 35.2 101.1 35.2 101.1 30.7 110.4 18.1 101.1 18.1'%3E%3C/polygon%3E%3Cpath d='M158.8 26.9c2.1-0.8 4.3-2.9 4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1 7.5h6.7L158.8 26.9z M154.7 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C157.2 21.6 156.2 22.5 154.7 22.5z'%3E%3C/path%3E%3Cpath d='M130.8 12.5c-6.8 0-11.6 4.9-11.6 11.5s4.9 11.5 11.6 11.5s11.7-4.9 11.7-11.5S137.6 12.5 130.8 12.5z M130.8 30.3c-3.4 0-5.7-2.6-5.7-6.3c0-3.8 2.3-6.3 5.7-6.3c3.4 0 5.8 2.6 5.8 6.3C136.6 27.7 134.2 30.3 130.8 30.3z'%3E%3C/path%3E%3Cpolygon points='82.1 12.8 98.3 12.8 98.3 18 87.9 18 87.9 21.3 98 21.3 98 26.4 87.9 26.4 87.9 30 98.3 30 98.3 35.2 82.1 35.2'%3E%3C/polygon%3E%3Cpath d='M24.6 9.7C24.6 4.4 20 0 14.4 0S4.2 4.4 4.2 9.7v3.1H0v22.3h0l14.4 6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4 9.7c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5v3.1H9.4V9.7z M23 31.5l-8.6 4l-8.6-4V18.1H23V31.5z'%3E%3C/path%3E%3Cpath d='M79.4 20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1 7.5H80l-4.9-8.3C77.2 26.1 79.4 24 79.4 20.3z M71 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C73.5 21.6 72.5 22.5 71 22.5z'%3E%3C/path%3E%3Cpolygon points='40.5 12.8 58.6 12.8 58.6 18.1 52.4 18.1 52.4 35.2 46.6 35.2 46.6 18.1 40.5 18.1'%3E%3C/polygon%3E%3C/svg%3E"); background-image: url("data:image/svg+xml,%3Csvg style='width: 128px%3B' version='1.1' xmlns='http://www.w3.org/2000/svg' x='0px' y='0px' viewBox='0 0 163.7 41.9' space='preserve'%3E%3Cpolygon points='101.1 12.8 118.2 12.8 118.2 17.3 108.9 29.9 118.2 29.9 118.2 35.2 101.1 35.2 101.1 30.7 110.4 18.1 101.1 18.1'%3E%3C/polygon%3E%3Cpath d='M158.8 26.9c2.1-0.8 4.3-2.9 4.3-6.6c0-4.5-3.1-7.4-7.7-7.4h-10.5v22.3h5.8v-7.5h2.2l4.1 7.5h6.7L158.8 26.9z M154.7 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C157.2 21.6 156.2 22.5 154.7 22.5z'%3E%3C/path%3E%3Cpath d='M130.8 12.5c-6.8 0-11.6 4.9-11.6 11.5s4.9 11.5 11.6 11.5s11.7-4.9 11.7-11.5S137.6 12.5 130.8 12.5z M130.8 30.3c-3.4 0-5.7-2.6-5.7-6.3c0-3.8 2.3-6.3 5.7-6.3c3.4 0 5.8 2.6 5.8 6.3C136.6 27.7 134.2 30.3 130.8 30.3z'%3E%3C/path%3E%3Cpolygon points='82.1 12.8 98.3 12.8 98.3 18 87.9 18 87.9 21.3 98 21.3 98 26.4 87.9 26.4 87.9 30 98.3 30 98.3 35.2 82.1 35.2'%3E%3C/polygon%3E%3Cpath d='M24.6 9.7C24.6 4.4 20 0 14.4 0S4.2 4.4 4.2 9.7v3.1H0v22.3h0l14.4 6.7l14.4-6.7h0V12.9h-4.2V9.7z M9.4 9.7c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5v3.1H9.4V9.7z M23 31.5l-8.6 4l-8.6-4V18.1H23V31.5z'%3E%3C/path%3E%3Cpath d='M79.4 20.3c0-4.5-3.1-7.4-7.7-7.4H61.2v22.3H67v-7.5h2.2l4.1 7.5H80l-4.9-8.3C77.2 26.1 79.4 24 79.4 20.3z M71 22.5h-4V18h4c1.5 0 2.5 0.9 2.5 2.2C73.5 21.6 72.5 22.5 71 22.5z'%3E%3C/path%3E%3Cpolygon points='40.5 12.8 58.6 12.8 58.6 18.1 52.4 18.1 52.4 35.2 46.6 35.2 46.6 18.1 40.5 18.1'%3E%3C/polygon%3E%3C/svg%3E");
} }
.copy-icon { .copyable::before,
width: 16px; .copied::before {
width: 18px;
height: 16px; height: 16px;
margin: 3px -18px;
content: "";
position: absolute;
background-size: cover; background-size: cover;
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 10.4996H13.5V2.49963H5.5V5.49963' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M10.4998 5.49976H2.49976V13.4998H10.4998V5.49976Z' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); }
.copyable::before {
display: none;
cursor: pointer;
background-image: url("data:image/svg+xml,%3Csvg width='18' height='16' viewBox='0 0 18 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M10.5 10.4996H13.5V2.49963H5.5V5.49963' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3Cpath d='M10.4998 5.49976H2.49976V13.4998H10.4998V5.49976Z' stroke='%2300854D' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.copyable:hover::before {
display: inline-block;
}
.copied::before {
transition: all 0.4s ease;
transform: scale(1.2);
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='16' viewBox='-30 -30 330 330'%3E%3Cpath d='M 30,180 90,240 240,30' style='stroke:%2300854D; stroke-width:32; fill:none'/%3E%3C/svg%3E");
}
.h-data {
letter-spacing: 0.12em;
font-weight: normal !important;
}
.tx-detail {
background: #F6F6F6;
color: #757575;
border-radius: 10px;
box-shadow: 0 0 0 10px white;
width: calc(100% - 20px);
margin-left: 10px;
margin-top: 3rem;
overflow-wrap: break-word;
}
.tx-detail:first-child {
margin-top: 1rem;
}
.tx-detail:last-child {
margin-bottom: 3rem;
}
.tx-detail span.ellipsis,
.tx-detail a.ellipsis {
display: block;
float: left;
max-width: 100%;
}
.tx-detail>.head {
padding: 1.5rem;
border-radius: 10px 10px 0 0;
--bs-gutter-x: 0;
}
.tx-detail .txid {
font-size: 106%;
letter-spacing: -0.01em;
}
.tx-detail>.body {
padding: 0 1.5rem;
--bs-gutter-x: 0;
letter-spacing: -0.01em;
}
.tx-detail>.footer {
padding: 1.5rem;
--bs-gutter-x: 0;
}
.tx-in .col-12,
.tx-out .col-12 {
background-color: white;
padding: 1.2rem 1.3rem;
border-bottom: 1px solid #F6F6F6;
}
.tx-in .col-12:last-child,
.tx-out .co-12l:last-child {
border-bottom: none;
}
.tx-own {
background-color: #FFF9E3 !important;
}
.tx-amt {
float: right !important;
}
.tx-in .tx-own .tx-amt,
.spent {
color: #dc3545 !important;
}
.tx-out .tx-own .tx-amt,
.unspent {
color: #28a745 !important;
}
.outpoint {
color: #757575 !important;
}
.spent,
.unspent,
.outpoint {
display: inline-block;
text-align: right;
min-width: 18px;
text-decoration: none !important;
}
.octicon {
height: 24px;
width: 24px;
margin-left: -12px;
margin-top: 19px;
position: absolute;
background-size: cover;
background-image: url("data:image/svg+xml,%3Csvg width='24' height='24' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9 4.5L16.5 12L9 19.5' stroke='%23AFAFAF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E%0A");
}
.txvalue {
color: black;
font-weight: bold;
}
.unconfirmed {
color: white;
background-color: #C51E13;
padding: 0.7rem 1.2rem;
border-radius: 1.4rem;
}
.json {
word-wrap: break-word;
font-size: smaller;
background: #002B31;
border-radius: 8px;
}
#raw {
padding: 1.5rem 2rem;
color: #FFFFFF;
letter-spacing: 0.02em;
}
#raw .string {
color: #2BCA87;
}
#raw .number,
#raw .boolean {
color: #EFC941;
}
#raw .null {
color: red;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
@ -261,16 +428,29 @@ span.btn-paging:hover {
font-size: 0.8rem; font-size: 0.8rem;
} }
.octicon {
scale: 60% !important;
margin-top: -2px;
}
.btn { .btn {
--bs-btn-font-size: 0.8rem; --bs-btn-font-size: 0.8rem;
} }
} }
@media (max-width: 991px) { @media (max-width: 991px) {
#header .container {
min-height: 40px
}
.trezor-logo { .trezor-logo {
top: 10px; top: 10px;
} }
.octicon {
scale: 80%;
}
.table.data-table>:not(caption)>*>* { .table.data-table>:not(caption)>*>* {
padding: 0.8rem 0.4rem; padding: 0.8rem 0.4rem;
} }

View File

@ -11,9 +11,39 @@
<meta name="description" content="Trezor {{.CoinLabel}} Explorer"> <meta name="description" content="Trezor {{.CoinLabel}} Explorer">
<title>Trezor {{.CoinLabel}} Explorer</title> <title>Trezor {{.CoinLabel}} Explorer</title>
<script type="text/javascript"> <script type="text/javascript">
function syntaxHighlight(json) {
json = JSON.stringify(json, undefined, 2);
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
window.onload=()=>{ window.onload=()=>{
document.querySelectorAll('[tt]').forEach(e=>new bootstrap.Tooltip(e,{title:e.getAttribute("tt")})); document.querySelectorAll('[tt]').forEach(e=>new bootstrap.Tooltip(e,{title:e.getAttribute("tt")}));
document.querySelectorAll("#header .bb-group>.btn-check").forEach(e=>e.addEventListener('click',(x)=>console.log("clicked",x.target.id))); document.querySelectorAll("#header .bb-group>.btn-check").forEach(e=>e.addEventListener('click',e=>console.log("clicked",e.target.id)));
document.querySelectorAll('.copyable').forEach(e=>e.addEventListener('click',e=>{
console.log("clicked",e.clientX<e.target.getBoundingClientRect().x,e.offsetX, e.clientX, e.target.getBoundingClientRect(), e);
if(e.clientX<e.target.getBoundingClientRect().x){
let t=e.target.getAttribute("copy-content");
if(!t) t=e.target.innerText;
navigator.clipboard.writeText(t);
e.target.className=e.target.className.replace('copyable','copied');
setTimeout(()=>e.target.className=e.target.className.replace('copied','copyable'),1000);
e.preventDefault();
}
}));
} }
</script> </script>
</head> </head>

View File

@ -1,75 +1,75 @@
{{define "specific"}}{{$cs := .CoinShortcut}}{{$b := .Block}}{{$data := . -}} {{define "specific"}}{{$cs := .CoinShortcut}}{{$b := .Block}}{{$data := . -}}
<h1>Block {{formatUint32 $b.Height}}</h1> <div class="row">
<div class="alert alert-data ellipsis"> <h1 class="col-sm-6">Block</h1>
<span class="data">{{$b.Hash}}</span> <nav class="col-sm-6 paging justify-content-end pb-1">
</div>
<div class="row h-container">
<h3 class="col-md-6">Summary</h3>
<nav class="col-md-6 paging justify-content-end">
{{if $b.Prev}}<a class="btn btn-paging" href="/block/{{$b.Prev}}">Previous Block</a>{{else}}<span class="btn btn-paging">Previous Block</span>{{end}} {{if $b.Prev}}<a class="btn btn-paging" href="/block/{{$b.Prev}}">Previous Block</a>{{else}}<span class="btn btn-paging">Previous Block</span>{{end}}
{{if $b.Next}}<a class="btn btn-paging ms-2" href="/block/{{$b.Next}}">Next Block</a>{{else}}<span class="btn btn-paging ms-2">Next Block</span>{{end}} {{if $b.Next}}<a class="btn btn-paging ms-2" href="/block/{{$b.Next}}">Next Block</a>{{else}}<span class="btn btn-paging ms-2">Next Block</span>{{end}}
</nav> </nav>
</div> </div>
<div class="data-div row"> <div class="row pt-3">
<h5 class="col-lg-3 h-data"><span class="ellipsis copyable">{{formatUint32 $b.Height}}</span></h5>
<h5 class="col-lg-9 justify-content-end d-flex h-data"><span class="copyable ellipsis">{{$b.Hash}}</span></h5>
</div>
<div class="row">
<div class="col-md-6"> <div class="col-md-6">
<table class="table data-table"> <table class="table data-table info-table">
<tbody> <tbody>
<tr> <tr>
<td style="width: 25%;">Transactions</td> <td>Transactions</td>
<td class="data">{{$b.TxCount}}</td> <td>{{formatInt $b.TxCount}}</td>
</tr> </tr>
<tr> <tr>
<td>Height</td> <td>Height</td>
<td class="data">{{$b.Height}}</td> <td>{{formatUint32 $b.Height}}</td>
</tr> </tr>
<tr> <tr>
<td>Confirmations</td> <td>Confirmations</td>
<td class="data">{{$b.Confirmations}}</td> <td>{{formatInt $b.Confirmations}}</td>
</tr> </tr>
<tr> <tr>
<td>Timestamp</td> <td>Timestamp</td>
<td class="data">{{formatUnixTime $b.Time}}</td> <td>{{formatUnixTime $b.Time}}</td>
</tr> </tr>
<tr> <tr>
<td>Size (bytes)</td> <td>Size (bytes)</td>
<td class="data">{{$b.Size}}</td> <td>{{formatInt $b.Size}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="col-md-6"> <div class="col-md-6">
<table class="table data-table"> <table class="table data-table info-table">
<tbody> <tbody>
<tr> <tr>
<td style="width: 25%;">Version</td> <td>Version</td>
<td class="data ellipsis">{{$b.Version}}</td> <td class="ellipsis">{{$b.Version}}</td>
</tr> </tr>
<tr> <tr>
<td>Merkle Root</td> <td>Merkle&nbsp;Root</td>
<td class="data ellipsis">{{$b.MerkleRoot}}</td> <td style="max-width: 280px;" class="ellipsis">{{$b.MerkleRoot}}</td>
</tr> </tr>
<tr> <tr>
<td>Nonce</td> <td>Nonce</td>
<td class="data ellipsis">{{$b.Nonce}}</td> <td class="ellipsis">{{$b.Nonce}}</td>
</tr> </tr>
<tr> <tr>
<td>Bits</td> <td>Bits</td>
<td class="data ellipsis">{{$b.Bits}}</td> <td class="ellipsis">{{$b.Bits}}</td>
</tr> </tr>
<tr> <tr>
<td>Difficulty</td> <td>Difficulty</td>
<td class="data ellipsis">{{$b.Difficulty}}</td> <td class="ellipsis">{{$b.Difficulty}}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
{{- if $b.Transactions -}} {{- if $b.Transactions -}}
<div class="row h-container"> <div class="row pt-3">
<h3 class="col-md-6 col-sm-12">Transactions</h3> <h3 class="col-md-6">Transactions</h3>
<div class="col-md-6 col-sm-12">{{template "paging" $data}}</div> <div class="col-md-6">{{template "paging" $data}}</div>
</div> </div>
<div class="data-div"> <div>
{{- range $tx := $b.Transactions}}{{$data := setTxToTemplateData $data $tx}}{{template "txdetail" $data}}{{end -}} {{- range $tx := $b.Transactions}}{{$data := setTxToTemplateData $data $tx}}{{template "txdetail" $data}}{{end -}}
</div> </div>
{{template "paging" $data }} {{template "paging" $data }}

View File

@ -3,23 +3,23 @@
<div class="col-lg-6"><h1>Mempool Transactions</h1><h5 class="mb-lg-0">{{$.MempoolTxids.MempoolSize}} transactions in mempool</h5></div> <div class="col-lg-6"><h1>Mempool Transactions</h1><h5 class="mb-lg-0">{{$.MempoolTxids.MempoolSize}} transactions in mempool</h5></div>
<div class="col-lg-6">{{if $txs}}{{template "paging" $data }}{{end}}</div> <div class="col-lg-6">{{if $txs}}{{template "paging" $data }}{{end}}</div>
</row> </row>
<div> {{if $txs}}
<table class="table data-table table-hover"> <table class="table data-table table-hover">
<thead> <thead>
<tr> <tr>
<th style="width: 70%;">Transaction</th> <th style="width: 70%;">Transaction</th>
<th style="width: 30%;">Time of appearance</th> <th style="width: 30%;">Time of appearance</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{{- range $tx := $txs -}} {{range $tx := $txs}}
<tr> <tr>
<td class="ellipsis"><a href="/tx/{{$tx.Txid}}">{{$tx.Txid}}</a></td> <td class="ellipsis"><a href="/tx/{{$tx.Txid}}">{{$tx.Txid}}</a></td>
<td>{{formatUnixTime $tx.Time}}</td> <td>{{formatUnixTime $tx.Time}}</td>
</tr> </tr>
{{- end -}} {{end}}
</tbody> </tbody>
</table> </table>
</div> {{end}}
{{template "paging" $data }} {{template "paging" $data }}
{{end}} {{end}}

View File

@ -29,32 +29,13 @@
</div> </div>
<div class="col-md-6" id="image"></div> <div class="col-md-6" id="image"></div>
</div> </div>
<div class="data-div" id="metadatablock"> <div id="metadatablock">
<h5>Metadata</h5> <h5>Metadata</h5>
<div class="alert alert-data" style="word-wrap: break-word; font-size: smaller;"> <div class="json">
<pre id="metadata" style="margin: 0;">Loading metadata from <a href="{{$data.URI}}">{{$data.URI}}</a>...</pre> <pre id="raw">Loading metadata from <a href="{{$data.URI}}">{{$data.URI}}</a>...</pre>
</div> </div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
function syntaxHighlight(json) {
json = JSON.stringify(json, undefined, 2);
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
function showImage(s) { function showImage(s) {
const img = document.createElement("img"); const img = document.createElement("img");
img.className="border w-100"; img.className="border w-100";
@ -79,7 +60,7 @@
document.getElementById("metadatablock").style.display='none'; document.getElementById("metadatablock").style.display='none';
} else { } else {
const data = await response.json(); const data = await response.json();
document.getElementById("metadata").innerHTML = syntaxHighlight(data); document.getElementById("raw").innerHTML = syntaxHighlight(data);
if (data.name) { if (data.name) {
nftInfo('name',data.name) nftInfo('name',data.name)
} }
@ -100,10 +81,10 @@
} }
} }
} else { } else {
document.getElementById("metadata").innerText = "Error: cannot get metadata link from blockchain"; document.getElementById("raw").innerText = "Error: cannot get metadata link from blockchain";
} }
} catch(e) { } catch(e) {
document.getElementById("metadata").innerText = "Error loading metadata: "+e; document.getElementById("raw").innerText = "Error loading metadata: "+e;
} }
} }
getMetadata(); getMetadata();

View File

@ -1,100 +1,100 @@
{{define "specific"}}{{$cs := .CoinShortcut}}{{$tx := .Tx}} {{define "specific"}}{{$cs := .CoinShortcut}}{{$tx := .Tx}}
<h1>Transaction</h1> <div class="row">
<div class="alert alert-data ellipsis"> <h1 class="col-12">Transaction</h1>
<span class="data">{{$tx.Txid}}</span>
</div> </div>
<h3>Summary</h3> <div class="row pt-3">
<div class="data-div"> <h5 class="col-12 d-flex h-data"><span class="ellipsis copyable">{{$tx.Txid}}</span></h5>
<table class="table data-table">
<tbody>
{{- if $tx.Confirmations -}}
<tr>
<td style="width: 25%;">Mined Time</td>
<td class="data">{{formatUnixTime $tx.Blocktime}}</td>
</tr>{{end -}}
<tr>
<td style="width: 25%;">In Block</td>
<td class="ellipsis data">{{if $tx.Confirmations}}{{$tx.Blockhash}}{{else}}Unconfirmed{{end}}</td>
</tr>
{{- if $tx.Confirmations -}}
<tr>
<td>In Block Height</td>
<td class="data"><a href="/block/{{$tx.Blockheight}}">{{$tx.Blockheight}}</a></td>
</tr>{{end}}
{{- if $tx.EthereumSpecific -}}
<tr>
<td>Status</td>
{{- if $tx.EthereumSpecific.Status -}}
{{- if eq $tx.EthereumSpecific.Status 1 -}}
<td class="data text-success">Success</td>
{{- else -}}
{{- if eq $tx.EthereumSpecific.Status -1 -}}
<td class="data">Pending</td>
{{- else -}}
<td class="data">Unknown</td>
{{- end -}}
{{- end -}}
{{- else -}}
<td class="data text-danger">Fail</td>
{{- end -}}
</tr>
<tr>
<td>Value</td>
<td class="data">{{formatAmount $tx.ValueOutSat}} {{$cs}}</td>
</tr>
<tr>
<td>Gas Used / Limit</td>
<td class="data">{{if $tx.EthereumSpecific.GasUsed}}{{$tx.EthereumSpecific.GasUsed}}{{else}}pending{{end}} / {{$tx.EthereumSpecific.GasLimit}}</td>
</tr>
<tr>
<td>Gas Price</td>
<td class="data">{{formatAmount $tx.EthereumSpecific.GasPrice}} {{$cs}}</td>
</tr>
{{- else -}}
<tr>
<td>Total Input</td>
<td class="data">{{formatAmount $tx.ValueInSat}} {{$cs}}</td>
</tr>
<tr>
<td>Total Output</td>
<td class="data">{{formatAmount $tx.ValueOutSat}} {{$cs}}</td>
</tr>
{{- if $tx.VSize -}}
<tr>
<td>Size / vSize</td>
<td class="data">{{$tx.Size}} / {{$tx.VSize}}</td>
</tr>
{{- else -}}
{{- if $tx.Size -}}
<tr>
<td>Size</td>
<td class="data">{{$tx.Size}}</td>
</tr>
{{- end -}}
{{- end -}}
{{- end -}}
{{- if $tx.FeesSat -}}
<tr>
<td>Fees</td>
<td class="data">{{formatAmount $tx.FeesSat}} {{$cs}}{{if $tx.Size}} ({{feePerByte $tx}}){{end}}</td>
</tr>{{end -}}
{{- if not $tx.Confirmations}}
<tr>
<td><span title="Replace by fee">RBF</span></td>
<td class="data">
{{- if $tx.Rbf}}
<span title="Replace by fee transaction, could be replaced.">ON</span>
{{- else -}}
<span title="Final transaction that can not be replaced unless it is dropped from the mempool.">OFF</span>
{{end -}}
</td>
</tr>
{{end -}}
</tbody>
</table>
</div> </div>
<table class="table data-table info-table">
<tbody>
{{- if $tx.Confirmations -}}
<tr>
<td>Mined Time</td>
<td>{{formatUnixTime $tx.Blocktime}}</td>
</tr>
{{end}}
<tr>
<td>In Block</td>
<td class="ellipsis" style="max-width: 280px">{{if $tx.Confirmations}}{{$tx.Blockhash}}{{else}}<span class="badge bg-danger">Unconfirmed</span>{{end}}</td>
</tr>
{{if $tx.Confirmations}}
<tr>
<td>In Block Height</td>
<td><a href="/block/{{$tx.Blockheight}}">{{formatInt $tx.Blockheight}}</a></td>
</tr>{{end}}
{{- if $tx.EthereumSpecific -}}
<tr>
<td>Status</td>
{{if $tx.EthereumSpecific.Status}}
{{if eq $tx.EthereumSpecific.Status 1}}
<td class="text-success">Success</td>
{{else}}
{{if eq $tx.EthereumSpecific.Status -1}}
<td>Pending</td>
{{else}}
<td>Unknown</td>
{{end}}
{{end}}
{{else}}
<td class="text-danger">Fail{{if $tx.EthereumSpecific.Error}} ({{$tx.EthereumSpecific.Error}})</div>{{end}}</td>
{{end}}
</tr>
<tr>
<td>Value</td>
<td>{{formatAmount $tx.ValueOutSat}} {{$cs}}</td>
</tr>
<tr>
<td>Gas Used / Limit</td>
<td>{{if $tx.EthereumSpecific.GasUsed}}{{$tx.EthereumSpecific.GasUsed}}{{else}}pending{{end}} / {{$tx.EthereumSpecific.GasLimit}}</td>
</tr>
<tr>
<td>Gas Price</td>
<td>{{formatAmount $tx.EthereumSpecific.GasPrice}} {{$cs}}</td>
</tr>
{{- else -}}
<tr>
<td>Total Input</td>
<td>{{formatAmount $tx.ValueInSat}} {{$cs}}</td>
</tr>
<tr>
<td>Total Output</td>
<td>{{formatAmount $tx.ValueOutSat}} {{$cs}}</td>
</tr>
{{if $tx.VSize}}
<tr>
<td>Size / vSize</td>
<td>{{formatInt $tx.Size}} / {{formatInt $tx.VSize}}</td>
</tr>
{{else}}
{{if $tx.Size}}
<tr>
<td>Size</td>
<td>{{formatInt $tx.Size}}</td>
</tr>
{{- end -}}
{{- end -}}
{{- end -}}
{{- if $tx.FeesSat -}}
<tr>
<td>Fees</td>
<td>{{formatAmount $tx.FeesSat}} {{$cs}}{{if $tx.Size}} ({{feePerByte $tx}}){{end}}</td>
</tr>{{end -}}
{{if not $tx.Confirmations}}
<tr>
<td><span tt="Replace by fee">RBF</span></td>
<td>
{{if $tx.Rbf}}
<span tt="Replace by fee transaction, could be replaced.">ON</span>
{{else}}
<span tt="Final transaction that can not be replaced unless it is dropped from the mempool.">OFF</span>
{{end}}
</td>
</tr>
{{end -}}
</tbody>
</table>
<h3>Details</h3> <h3>Details</h3>
<div class="data-div"> <div>
{{template "txdetail" .}} {{template "txdetail" .}}
</div> </div>
{{if eq .ChainType 1}} {{if eq .ChainType 1}}
@ -139,31 +139,12 @@
{{end}} {{end}}
<div class="data-div"> <div class="data-div">
<h5>Raw Transaction</h5> <h5>Raw Transaction</h5>
<div class="alert alert-data" style="word-wrap: break-word; font-size: smaller;"> <div class="json">
<pre id="txSpecific"></pre> <pre id="raw"></pre>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
txSpecific = {{$tx.CoinSpecificData}}; var raw = {{$tx.CoinSpecificData}};
function syntaxHighlight(json) { document.getElementById('raw').innerHTML = syntaxHighlight(raw);
json = JSON.stringify(json, undefined, 2);
json = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '<span class="' + cls + '">' + match + '</span>';
});
}
document.getElementById('txSpecific').innerHTML = syntaxHighlight(txSpecific);
</script> </script>
</div> </div>
{{end}} {{end}}

View File

@ -1,93 +1,74 @@
{{define "txdetail"}}{{$cs := .CoinShortcut}}{{$addr := .AddrStr}}{{$tx := .Tx}}{{$data := .}} {{define "txdetail"}}{{$cs := .CoinShortcut}}{{$addr := .AddrStr}}{{$tx := .Tx}}{{$data := .}}
<div class="alert alert-data"> <div class="tx-detail">
<div class="row line-bot"> <div class="row head">
<div class="col-xs-7 col-md-8 ellipsis"> <div class="col-xs-7 col-md-8">
<a href="/tx/{{$tx.Txid}}">{{$tx.Txid}}</a> <a href="/tx/{{$tx.Txid}}" class="ellipsis copyable txid">{{$tx.Txid}}</a>
{{- if $tx.Rbf}}<span title="Replace-by-Fee (RBF) transaction, could be overriden"> RBF</span>{{end -}} {{- if $tx.Rbf}}<span class="ps-1" tt="Replace-by-Fee (RBF) transaction, could be overriden"> RBF</span>{{end -}}
</div> </div>
{{- if $tx.Blocktime}}<div class="col-xs-5 col-md-4 text-muted text-right">{{if $tx.Confirmations}}mined{{else}}first seen{{end}} {{formatUnixTime $tx.Blocktime}}</div>{{end -}} {{- if $tx.Blocktime}}<div class="col-xs-5 col-md-4 text-end">{{if $tx.Confirmations}}mined{{else}}first seen{{end}} <span class="txvalue">{{formatUnixTime $tx.Blocktime}}</span></div>{{end -}}
</div> </div>
<div class="row line-mid"> <div class="row body">
<div class="col-md-5"> <div class="col-md-5">
<div class="row tx-in"> <div class="row tx-in">
<table class="table data-table"> {{range $vin := $tx.Vin}}
<tbody> <div class="col-12{{if $vin.IsOwn}} tx-own{{end}}">
{{- range $vin := $tx.Vin -}} {{range $a := $vin.Addresses}}
<tr{{if $vin.IsOwn}} class="tx-own"{{end}}> <span class="ellipsis tx-addr copyable">
<td> {{if and (ne $a $addr) $vin.IsAddress}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
{{- if $vin.Txid -}} </span>
<a class="float-left text-muted" href="/tx/{{$vin.Txid}}" title="Outpoint {{$vin.Txid}},{{$vin.Vout}}">&nbsp;</a> {{else}}
{{- end -}} <span class="tx-addr">{{if $vin.Hex}}Unparsed address{{else}}No Inputs (Newly Generated Coins){{end}}</span>
{{- range $a := $vin.Addresses -}} {{end}}
<span class="ellipsis tx-addr"> {{if $vin.Txid}}
{{if and (ne $a $addr) $vin.IsAddress}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}} <a class="outpoint" href="/tx/{{$vin.Txid}}" tt="Outpoint {{$vin.Txid}},{{$vin.Vout}}"></a>
</span> {{end}}
{{- else -}} {{if $vin.Addresses}}<span class="tx-amt copyable">{{formatAmount $vin.ValueSat}} {{$cs}}</span>{{end}}
<span class="tx-addr">{{- if $vin.Hex -}}Unparsed address{{- else -}}No Inputs (Newly Generated Coins){{- end -}}</span> </div>
{{- end -}}{{- if $vin.Addresses -}} {{else}}
<span class="tx-amt">{{formatAmount $vin.ValueSat}} {{$cs}}</span> <div class="col-12">No Inputs</div>
{{- end -}} {{end}}
</td>
</tr>
{{- else -}}
<tr>
<td>No Inputs</td>
</tr>
{{- end -}}
</tbody>
</table>
</div> </div>
</div> </div>
<div class="col-md-1 col-xs-12 text-center"> <div class="col-md-1 col-xs-12 text-center">&nbsp;<span class="octicon"></span></div>
<svg class="octicon" viewBox="0 0 8 16">
<path fill-rule="evenodd" d="M7.5 8l-5 5L1 11.5 4.75 8 1 4.5 2.5 3l5 5z"></path>
</svg>
</div>
<div class="col-md-6"> <div class="col-md-6">
<div class="row tx-out"> <div class="row tx-out">
<table class="table data-table">
<tbody>
{{- range $vout := $tx.Vout -}} {{- range $vout := $tx.Vout -}}
<tr{{if $vout.IsOwn}} class="tx-own"{{end}}> <div class="col-12{{if $vout.IsOwn}} tx-own{{end}}">
<td> {{range $a := $vout.Addresses}}
{{- range $a := $vout.Addresses -}} <span class="ellipsis tx-addr copyable">
<span class="ellipsis tx-addr"> {{if and (ne $a $addr) $vout.IsAddress}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{end}}
{{- if and (ne $a $addr) $vout.IsAddress}}<a href="/address/{{$a}}">{{$a}}</a>{{else}}{{$a}}{{- end -}} </span>
</span> {{- else -}}
{{- else -}} <span class="tx-addr">Unparsed address</span>
<span class="tx-addr">Unparsed address</span> {{- end -}}
{{- end -}} <span class="tx-amt">
<span class="tx-amt"> <span class="copyable">{{formatAmount $vout.ValueSat}} {{$cs}}</span>{{if $vout.Spent}}<a class="spent" href="{{if $vout.SpentTxID}}/tx/{{$vout.SpentTxID}}{{else}}/spending/{{$tx.Txid}}/{{$vout.N}}{{end}}" tt="Spent"></a>{{else}}<span class="unspent" tt="Unspent">×</span>
{{formatAmount $vout.ValueSat}} {{$cs}} {{if $vout.Spent}}<a class="text-danger" href="{{if $vout.SpentTxID}}/tx/{{$vout.SpentTxID}}{{else}}/spending/{{$tx.Txid}}/{{$vout.N}}{{end}}" title="Spent"></a>{{else -}} {{end}}
<span class="text-success" title="Unspent"> <b>×</b></span> </span>
{{- end -}}
</span>
</td> </td>
</tr> </div>
{{- else -}} {{else}}
<tr> <div class="col-12">No Outputs</div>
<td>No Outputs</td> {{end}}
</tr>
{{- end -}}
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
<div class="row line-top"> <div class="row footer">
<div class="col-xs-6 col-sm-4 col-md-4"> <div class="col-sm-12 col-md-4">
{{- if $tx.FeesSat -}} {{- if $tx.FeesSat -}}
<span class="txvalues txvalues-default">Fee: {{formatAmount $tx.FeesSat}} {{$cs}}</span> Fee: <span class="txvalue">{{formatAmount $tx.FeesSat}} {{$cs}}</span>
{{- end -}} {{- end -}}
</div> </div>
<div class="col-xs-6 col-sm-8 col-md-8 text-right"> <div class="col-sm-12 col-md-8 text-end">
<span class="me-4">
{{- if $tx.Confirmations -}} {{- if $tx.Confirmations -}}
<span class="txvalues txvalues-success">{{$tx.Confirmations}} Confirmations</span> <span class="txvalue">{{formatUint32 $tx.Confirmations}}</span> Confirmations
{{- else -}} {{- else -}}
<span class="txvalues txvalues-danger ng-hide">Unconfirmed Transaction!</span> <span class="txvalue unconfirmed">Unconfirmed Transaction!</span>
{{- end -}} {{- end -}}
<span class="txvalues txvalues-primary">{{formatAmount $tx.ValueOutSat}} {{$cs}}</span> </span>
<span class="txvalue">{{formatAmount $tx.ValueOutSat}} {{$cs}}</span>
</div> </div>
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@ -1,5 +1,5 @@
{{define "txdetail"}}{{$cs := .CoinShortcut}}{{$addr := .AddrStr}}{{$tx := .Tx}}{{$data := .}} {{define "txdetail"}}{{$cs := .CoinShortcut}}{{$addr := .AddrStr}}{{$tx := .Tx}}{{$data := .}}
<div class="alert alert-data"{{if eq $tx.EthereumSpecific.Status 0}} style="background-color: #faf2ee;"{{end}}> <div class="tx-detail"{{if eq $tx.EthereumSpecific.Status 0}} style="background-color: #faf2ee;"{{end}}>
<div class="row line-bot"> <div class="row line-bot">
<div class="col-xs-7 col-md-8 ellipsis"> <div class="col-xs-7 col-md-8 ellipsis">
<a href="/tx/{{$tx.Txid}}">{{$tx.Txid}}</a> <a href="/tx/{{$tx.Txid}}">{{$tx.Txid}}</a>