github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/client/www/templates/txs.html (about) 1 <script type="text/javascript" src="webui/jquery.min.js"></script> 2 <script type="text/javascript" src="webui/jquery.flot.min.js"></script> 3 <style> 4 table.txs { 5 font-size:75% 6 } 7 td.maturity { 8 text-align: right; 9 white-space: nowrap; 10 } 11 td.txid { 12 font-family: monospace; 13 font-size:7px; 14 } 15 </style> 16 <div id="light" class="white_content"> 17 <table width="100%"><tr> 18 <td><h3><b class="mono" id="disp_txid"></b></h3> 19 <td align="right"><img title="Close this popup" src="webui/close.png" class="hand" onclick="closepopup()"> 20 </table> 21 <pre id="rawdiv" style="background-color:white"></pre> 22 </div><div id="fade" class="black_overlay"></div> 23 <table width="100%"> 24 <tr> 25 <td><b>Memory Pool:</b></td> 26 <td align="right"> 27 <span onclick="mempool_new_sort.click()" class="hand" title="Uses less bandwidth"> 28 <input type="checkbox" id="mempool_new_sort" onchange="show_mempool_fees()" onclick="event.stopPropagation()">Quick 29 </span> 30 • 31 <span onclick="mempool_spb_range.click()" class="hand"> 32 <input type="checkbox" id="mempool_spb_range" onchange="show_mempool_fees()" onclick="event.stopPropagation()">Limit Y 33 </span> 34 • 35 X for 36 <span onclick="mempool_siz_range_1.click()" class="hand"> 37 <input type="radio" name="mempool_siz_range" id="mempool_siz_range_1" onchange="show_mempool_fees()" onclick="event.stopPropagation()">Block 38 </span> 39 <span onclick="mempool_siz_range_6.click()" class="hand"> 40 <input type="radio" name="mempool_siz_range" id="mempool_siz_range_6" onchange="show_mempool_fees()" onclick="event.stopPropagation()" checked>Hour 41 </span> 42 <span onclick="mempool_siz_range_a.click()" class="hand"> 43 <input type="radio" name="mempool_siz_range" id="mempool_siz_range_a" onchange="show_mempool_fees()" onclick="event.stopPropagation()">All 44 </span> 45 </td> 46 </tr> 47 </table> 48 49 <table width="100%"> 50 <tr> 51 <td colspan="2"> 52 <div id="mempool_fees" style="height:200px;margin:5px"></div> 53 </tr> 54 55 56 <tr> 57 <td valign="top"> 58 <table> 59 <colgroup> 60 <col width="200"> 61 <col width="100"> 62 <col width="100"> 63 </colgroup> 64 <tr><td>Memory pool size: 65 <td colspan="2"> 66 <input type="button" id="ts_t2s_size" onclick="show_mempool_fees()" 67 title="Click to see mempool fee statistics" 68 style="width:100%"> 69 <td align="right"> 70 <tr><td>UTXOs spent in memory: 71 <td><b id="outspent"></b> 72 <td align="right" nowrap="nowrap" style="font-size:70%">avg. <b id="avgoutspertx"></b> / tx 73 <tr><td>Rejected transactions: 74 <td><input type="button" id="butre" value="" onclick="show_txsre()"> 75 <td align="right" nowrap="nowrap"><b id="ts_tre_size"></b> 76 <tr><td>Waiting for inputs:<td><input type="button" id="butw4i" value="" onclick="show_txw4i()"> 77 <td align="right" nowrap="nowrap" title="FeeFiler value"><b id="min_spb"></b> spb 78 <tr><td>Being processed: 79 <td><b id="ts_ptr1_cnt"></b> / <b id="ts_ptr2_cnt"></b> 80 <td><input type="button" onclick="show_txs2s('&ownonly=1')" value="Own TXs"> 81 <tr><td>Estmated fees: 82 <td colspan="2"><b id="fees_from_first_block">...</b> BTC from 1st block 83 </table> 84 <td valign="top"> 85 <table> 86 <col width="150"> 87 <col width="100"> 88 <col width="*"> 89 <tr> 90 <td>Memory pool: 91 <td><b><!--MEM_POOL_ENABLED--></b> 92 <td><span id="el_txp_switch" style="display:none">[<a href="javascript:config('txponoff')">Switch ON/OFF</a>]</span> 93 <tr> 94 <td>Relay transactions: 95 <td><b><!--TX_ROUTE_ENABLED--></b> 96 <td><span id="el_txr_switch" style="display:none">[<a href="javascript:config('txronoff')">Switch ON/OFF</a>]</span> 97 <tr><td colspan="3"> 98 <tr> 99 <td colspan="3" bgcolor="#f0fff0" style="border:1px solid black"> 100 <b>Upload Transaction File:</b><br> 101 <br> 102 <form id="theform" method="post" enctype="multipart/form-data" onchange="theform.submit()"> 103 <input name="txfile" type="file"> 104 </form> 105 ... or use 106 <a href="https://www.blockchain.com/btc/pushtx" target="_blank">blockchain.com</a> 107 | <a href="https://blockstream.info/tx/push" target="_blank">blockstream</a> 108 | <a href="https://coinb.in/send-raw-transaction.html" target="_blank">coinb.in</a> 109 | <a href="https://en.bitcoin.it/wiki/Transaction_broadcasting" target="_blank">more...</a> 110 to push it. 111 </table> 112 113 <tr> 114 <td colspan="2"> 115 <hr> 116 Up to 117 <select id="mp_show_cnt"> 118 <option selected>50</option> 119 <option>100</option> 120 <option>250</option> 121 <option>500</option> 122 <option>1000</option> 123 <option>2000</option> 124 <option>5000</option> 125 <option>10000</option> 126 </select> 127 mempool transactions, 128 sorted by 129 <select id="mp_show_sort"> 130 <option value="age">age</option> 131 <option value="siz">length</option> 132 <option value="wgh">weight</option> 133 <option value="swc">SegWit compression</option> 134 <option value="inp">inputs count</option> 135 <option value="out">outputs count</option> 136 <option value="btc">BTC volume</option> 137 <option value="fee">fee amount</option> 138 <option value="ops">sigops count</option> 139 <option value="spb" selected>fee per byte</option> 140 <option value="rbf">RFB first</option> 141 <option value="ver">verify time</option> 142 </select> 143 in descending <input id="mp_show_sort_desc" type="checkbox" checked="checked"> order 144 - <input type="button" value="show me now..." onclick="show_txs2s('')"> 145 146 <input type="button" value="Decode mempool TX" onclick="show_txid()"> 147 </table> 148 149 150 <!--TX_LOAD--> 151 <table class="txs bord" id="txs2s" style="display:none" width="100%"> 152 <tr> 153 <th width="20" align="right"># 154 <th width="20" align="right">totlen 155 <th>Transaction ID 156 <th onclick="sortclick('age')" style="cursor:pointer" width="60" align="right">Maturity 157 <th onclick="sortclick('siz')" style="cursor:pointer" width="80" align="right">Len 158 <th onclick="sortclick('wgh')" style="cursor:pointer" width="80" align="right">Wght 159 <th onclick="sortclick('swc')" style="cursor:pointer" width="80" align="right">SWC 160 <th onclick="sortclick('inp')" style="cursor:pointer" width="30" align="right">Inps 161 <th onclick="sortclick('out')" style="cursor:pointer" width="30" align="right">Outs 162 <th onclick="sortclick('btc')" style="cursor:pointer" width="90" align="right">Total BTC 163 <th onclick="sortclick('fee')" style="cursor:pointer" width="80" align="right">Fee BTC 164 <th onclick="sortclick('spb')" style="cursor:pointer" width="60" align="right">SPB 165 <th onclick="sortclick('ops')" style="cursor:pointer" width="40" align="right">SOps 166 <th onclick="sortclick('rbf')" style="cursor:pointer" width="30" align="right" title="Transaction is not final">RBF 167 <th onclick="sortclick('ver')" style="cursor:pointer" width="40" align="right" title="Verification time in ms">ms 168 <th width="40" align="right">Sent 169 <th align="right">Extras 170 </tr> 171 </table> 172 <table class="txs bord" id="txsre" style="display:none" width="100%"> 173 <tr> 174 <th width="20" align="right"># 175 <th>Transaction ID 176 <th onclick="sorttab('txsre', 2)" style="cursor:pointer" width="60" align="right">Maturity 177 <th onclick="sorttab('txsre', 3)" style="cursor:pointer" width="60" align="right">Size 178 <th width="100" align="right">Reason rejected 179 </table> 180 <table class="txs bord" id="txw4i" style="display:none" width="100%"> 181 <tr> 182 <th width="20" align="right"># 183 <th>Waiting for 184 <th>Pending Tx 185 <th onclick="sorttab('txw4i', 3)" style="cursor:pointer" width="60" align="right">Maturity 186 </table> 187 <script> 188 if (!server_mode) { 189 el_txp_switch.style.display='inline' 190 el_txr_switch.style.display='inline' 191 } 192 193 function sortclick(type) { 194 var os = mp_show_sort.options 195 if (os[mp_show_sort.selectedIndex].value!=type) { 196 mp_show_sort_desc.checked = true 197 for (var i=0; i<os.length; i++) { 198 if (os[i].value==type) { 199 mp_show_sort.selectedIndex = i 200 break 201 } 202 } 203 } else { 204 mp_show_sort_desc.checked = !mp_show_sort_desc.checked 205 } 206 show_txs2s('') 207 } 208 209 function sorter(a,b) { 210 return a.val<b.val 211 } 212 213 function sorttab(tid,col) { 214 var tbl = document.getElementById(tid).tBodies[0] 215 var store = [] 216 for(var i=0, len=tbl.rows.length; i<len; i++) { 217 var row = tbl.rows[i]; 218 var sortnr = row.cells[col]["numeric_value"] 219 if (isNaN(sortnr)) { 220 sortnr = parseFloat(row.cells[col].textContent || row.cells[col].innerText); 221 } 222 if (!isNaN(sortnr)) store.push([sortnr, row]); 223 } 224 store.sort(function(x,y) { 225 return y[0] - x[0]; 226 }); 227 for(var i=0, len=store.length; i<len; i++) { 228 tbl.appendChild(store[i][1]); 229 } 230 for (var i=0; i<tbl.rows.length; i++) { 231 tbl.rows[i].cells[0].innerHTML = i.toString() 232 } 233 store = null 234 } 235 236 function get_maturity(t) { 237 var secs = parseInt(((new Date()).getTime()/1000) - parseInt(t)) 238 if (secs<0) secs=0 239 if (secs<180) return secs + ' s' 240 var mins = secs / 60 241 if (mins>300) return (mins/60).toFixed(2) + ' h' 242 return mins.toFixed(1) + ' min' 243 } 244 245 function send1tx_click(id) { 246 if (confirm("Send TX "+id+" to one random peer")) { 247 quiet_txs2s('&sendone='+id) 248 setTimeout("show_txs2s('&ownonly=1')", 1000) 249 } 250 } 251 252 function sendtx_click(id) { 253 if (confirm("Broadcast TX "+id)) { 254 quiet_txs2s('&send='+id) 255 setTimeout("show_txs2s('&ownonly=1')", 1000) 256 } 257 } 258 259 function deltx_click(id) { 260 if (confirm("Delete TX "+id)) { 261 show_txs2s('&del='+id+'&ownonly=1') 262 } 263 txrawdata.innerText = '' 264 } 265 266 var tx_decoding_in_progress = false 267 268 function decode_tx() { 269 if (!tx_decoding_in_progress) { 270 decode_tx_id(this.id) 271 } 272 } 273 274 function decode_tx_id(txid) { 275 var aj = ajax() 276 tx_decoding_in_progress = true 277 aj.onreadystatechange=function() { 278 if(aj.readyState==4) { 279 tx_decoding_in_progress = false 280 281 var sta = xval(aj.responseXML, "status") 282 if (sta!="OK") { 283 alert("Error: " + sta) 284 return 285 } 286 287 disp_txid.innerHTML = xval(aj.responseXML, "id") 288 289 var tin=0, tout=0, s = '' 290 var all_input_values = true 291 292 s += "Version: " + xval(aj.responseXML, "version") + "\n\n" 293 294 var is = aj.responseXML.getElementsByTagName('input') 295 for (var i=0; i<is.length; i++) { 296 s += (i+1) + ") " + xval(is[i], "txid-vout") + " " 297 298 var bl = xval(is[i], "block") 299 if (isNaN(bl) || bl==0) { 300 s += "(unconfirmed)" 301 } else { 302 s += "(#"+xval(is[i], "block")+")" 303 } 304 s += " seq=" + parseInt(xval(is[i], "sequence")).toString(16) 305 s += " " 306 307 var st = xval(is[i], "status") 308 s += "\n Status : " + st 309 var val = parseInt(xval(is[i], "value")) 310 if (!isNaN(val)) { 311 tin += val 312 s += " • " 313 s += (parseFloat(val)/1e8).toFixed(8) 314 s += " BTC @ " 315 var ad = xval(is[i], "addr") 316 if (typeof(ad)!="string") { 317 s += xval(is[i], "pkscript") 318 } else { 319 s += ad 320 } 321 } else all_input_values = false 322 323 var sops = parseInt(xval(is[i], "input_sigops")) 324 if (!isNaN(sops)) { 325 s += " + " + sops + ' sigops' 326 } 327 var inspcr = xval(is[i], "script_sig") 328 if (typeof(inspcr)=="string") { 329 s += "\n SigScript length " +inspcr.length/2 + ":" 330 for (var k=0; k<inspcr.length; k+=140) { 331 s += "\n " + inspcr.substr(k, 140) 332 } 333 } 334 335 var segwit = is[i].getElementsByTagName("witness") 336 if (segwit.length>0) { 337 s += "\n SegWit stack:" 338 for (var k=0; k<segwit.length; k++) { 339 if (segwit[k].childNodes.length>0) { 340 s += "\n " + segwit[k].childNodes[0].nodeValue 341 } else { 342 s += "\n OP_0" 343 } 344 } 345 } 346 347 s += "\n\n" 348 } 349 s += "Total input: " + (parseFloat(tin)/1e8).toFixed(8) + " BTC\n" 350 s += "\n" 351 352 is = aj.responseXML.getElementsByTagName('output') 353 for (var i=0; i<is.length; i++) { 354 s += (i+1) + ") " 355 var val = parseInt(xval(is[i], "value")) 356 tout += val 357 s += (parseFloat(val)/1e8).toFixed(8) 358 s += " BTC => " + xval(is[i], "addr") 359 s += "\n" 360 } 361 s += "Total output: " + (parseFloat(tout)/1e8).toFixed(8) + " BTC\n" 362 s += "\n" 363 s += "Lock time: " + xval(aj.responseXML, "lock_time") + "\n\n" 364 var fee = tin-tout 365 366 var sw_compr = + '%' 367 368 var size = parseInt(xval(aj.responseXML, "size")) 369 var nwsize = parseInt(xval(aj.responseXML, "nwsize")) 370 var weight = parseInt(xval(aj.responseXML, "weight")) 371 var vsize = (size==nwsize) ? size : ((3*(nwsize+1) + size) >> 2) 372 s += 'TxSize: ' + size 373 s += ' / NoWit:' + nwsize 374 s += ' (' + (xval(aj.responseXML, "sw_compress") / 10.0).toFixed(1) + '%)' 375 s += ' / Weight: ' + weight 376 s += ' / VSize:' + vsize 377 s += ' / Sigops: ' + xval(aj.responseXML, "sigops") + '\n' 378 379 if (all_input_values) { 380 s += "Fee: " + (parseFloat(fee)/1e8).toFixed(8) + " BTC" 381 s += ' ==> ' + parseFloat(fee/vsize).toFixed(5) + ' Satoshis per byte\n' 382 } 383 384 s += 'Verification took: ' + xval(aj.responseXML, "verify_us") + ' microseconds\n' 385 386 rawdiv.innerHTML = s 387 388 if (prvpos==null) { 389 fade.addEventListener('click', closepopup) 390 fade.style.cursor = 'pointer' 391 fade.title = 'Click here to close the popup' 392 } 393 394 395 prvpos = document.body.scrollTop 396 window.scrollTo(0,0) 397 398 light.style.display='block' 399 fade.style.display='block' 400 document.addEventListener("scroll", noscroll) 401 } 402 } 403 aj.open("GET","txs2s.xml?id="+txid+'&sid='+sid, true); 404 aj.send(null); 405 } 406 407 function quiet_txs2s(extrapar) { 408 var aj = ajax() 409 aj.open("GET","txs2s.xml?quiet=1&sid="+sid+extrapar, true); 410 aj.send(null); 411 } 412 413 function show_txs2s(extrapar) { 414 var aj = ajax() 415 aj.onreadystatechange=function() { 416 if(aj.readyState==4) { 417 while (txs2s.rows.length>1) txs2s.deleteRow(1) 418 txs = aj.responseXML.getElementsByTagName('tx') 419 var lensofar = 0 420 for (var i=0; i<txs.length; i++) { 421 var c,row 422 var own = xval(txs[i], 'own')==='true' 423 var txid = xval(txs[i], 'id') 424 425 row = txs2s.insertRow(-1) 426 row.className='hov' 427 428 var len = parseInt(xval(txs[i], 'size')) 429 lensofar += len 430 431 c=row.insertCell(-1);c.align='right' 432 c.innerHTML = (i+1).toString() 433 434 c=row.insertCell(-1);c.align='right' 435 c.innerHTML = lensofar 436 437 c = row.insertCell(-1) 438 c.className ='txid' 439 c.innerHTML = txid 440 c.id = txid 441 c.addEventListener('click', decode_tx, false) 442 c.style.cursor='pointer' 443 444 c=row.insertCell(-1);c.className='maturity' 445 var tim = xval(txs[i], 'time') 446 c["numeric_value"] = tim 447 c.innerHTML = get_maturity(tim) 448 449 c=row.insertCell(-1);c.align='right' 450 c.innerHTML = len 451 var nws = 'No witness size:' + xval(txs[i], 'nwsize') 452 c.title = nws 453 454 c=row.insertCell(-1);c.align='right' 455 var weight = xval(txs[i], 'weight') 456 c.innerHTML += weight 457 c.title = 'Virtual size:' + (weight/4).toFixed(0) 458 459 c=row.insertCell(-1);c.align='right' 460 c.innerHTML += (xval(txs[i], 'sw_compress') / 10.0).toFixed(0) + '%' 461 c.title = nws 462 463 c=row.insertCell(-1);c.align='right' 464 c.innerHTML = xval(txs[i], 'inputs') 465 466 c=row.insertCell(-1);c.align='right' 467 c.innerHTML = xval(txs[i], 'outputs') 468 469 470 c=row.insertCell(-1);c.align='right' 471 c.innerHTML = (parseFloat(xval(txs[i], 'volume'))/1e8).toFixed(8) 472 473 var fee = parseFloat(xval(txs[i], 'fee')) 474 475 c=row.insertCell(-1);c.align='right' 476 c.innerHTML = (fee/1e8).toFixed(8) 477 478 c=row.insertCell(-1);c.align='right' 479 c.innerHTML = (parseFloat(fee)/(parseFloat(xval(txs[i], 'weight'))/4)).toFixed(1) 480 481 c=row.insertCell(-1);c.align='right' 482 c.innerHTML = xval(txs[i], 'sigops') 483 484 c=row.insertCell(-1);c.align='center' 485 if (xval(txs[i], 'final')!='true') c.innerHTML = '*' 486 487 c=row.insertCell(-1);c.align='right' 488 c.innerHTML = (xval(txs[i], 'verify_us')/1e3).toFixed(1) 489 490 c=row.insertCell(-1);c.align='right' 491 var sc = xval(txs[i], 'sentcnt') 492 c.innerHTML = sc + "/" + xval(txs[i], 'invsentcnt') 493 if (sc>0) { 494 var tim = new Date(xval(txs[i], 'sentlast')*1000) 495 c.title = "Last sent at "+tim.getHours()+":"+leftpad(tim.getMinutes(),'0',2)+":"+leftpad(tim.getSeconds(),'0',2) 496 } 497 498 c=row.insertCell(-1);c.align='right' 499 if (own) { 500 c.innerHTML = '<img style="cursor:pointer" title="Send this TX to one random peer" onclick="send1tx_click(\''+txid+'\')" src="webui/send_once.png">' 501 c.innerHTML += ' ' 502 c.innerHTML += '<img style="cursor:pointer" title="Broadcast this TX" onclick="sendtx_click(\''+txid+'\')" src="webui/send.png">' 503 c.innerHTML += ' ' 504 c.innerHTML += '<img style="cursor:pointer" title="Remove this TX" onclick="deltx_click(\''+txid+'\')" src="webui/del.png">' 505 } else { 506 c.innerHTML = xval(txs[i], 'blocked') 507 } 508 509 if (own) { 510 row.classList.add('own') 511 row.title = 'Your own transaction' 512 } 513 514 if (xval(txs[i], 'witness_cnt') > 0) { 515 row.classList.add('segwit') 516 row.title = 'Segregated Witness transaction' 517 } 518 } 519 txs2s.style.display = 'table' 520 } 521 } 522 txs2s.style.display = txsre.style.display = txw4i.style.display = 'none' 523 524 extrapar += '&cnt='+mp_show_cnt.options[mp_show_cnt.selectedIndex].value 525 extrapar += '&sort='+mp_show_sort.options[mp_show_sort.selectedIndex].value 526 if (mp_show_sort_desc.checked) { 527 extrapar += '&descending' 528 } 529 aj.open("GET","txs2s.xml?sid="+sid+extrapar, true); 530 aj.send(null); 531 } 532 533 534 function show_txsre() { 535 var aj = ajax() 536 aj.onreadystatechange=function() { 537 if(aj.readyState==4) { 538 while (txsre.rows.length>1) txsre.deleteRow(1) 539 txs = aj.responseXML.getElementsByTagName('tx') 540 butre.value = ' ' + txs.length + ' ' 541 for (var i=0; i<txs.length; i++) { 542 var t,c,row = txsre.insertRow(-1) 543 544 row.className='hov' 545 546 c=row.insertCell(-1);c.align='right' 547 c.innerHTML = (i+1).toString() 548 549 c = row.insertCell(-1) 550 c.className ='mono' 551 t = xval(txs[i], 'id') 552 c.innerHTML = '<a href="https://blockchain.info/tx/'+t+'">'+t+'</a>' 553 554 c=row.insertCell(-1);className='maturity' 555 var tim = xval(txs[i], 'time') 556 c["numeric_value"] = tim 557 c.innerHTML = get_maturity(tim) 558 559 c=row.insertCell(-1);c.align='right' 560 c.innerHTML = xval(txs[i], 'size') 561 562 c=row.insertCell(-1);c.align='right' 563 c.innerHTML = xval(txs[i], 'reason') 564 } 565 txsre.style.display = 'table' 566 } 567 } 568 txs2s.style.display = txsre.style.display = txw4i.style.display = 'none' 569 aj.open("GET","txsre.xml", true); 570 aj.send(null); 571 } 572 573 function show_txw4i() { 574 var aj = ajax() 575 aj.onreadystatechange=function() { 576 if(aj.readyState==4) { 577 while (txw4i.rows.length>1) txw4i.deleteRow(1) 578 wait4s = aj.responseXML.getElementsByTagName('wait4') 579 var idx=0 580 //butw4i.value = ' ' + wait4s.length + ' ' 581 for (var i=0; i<wait4s.length; i++) { 582 pendtxs = wait4s[i].getElementsByTagName('tx') 583 idx++ 584 for (var j=0; j<pendtxs.length; j++) { 585 var t,c,row = txw4i.insertRow(-1) 586 587 row.className='hov' 588 589 c=row.insertCell(-1);c.align='right' 590 if (j==0) { 591 c.innerHTML = idx.toString() 592 } 593 594 c = row.insertCell(-1) 595 c.className ='mono' 596 if (j==0) { 597 t = xval(wait4s[i], 'id') 598 c.innerHTML = '<a href="https://blockchain.info/tx/'+t+'">'+t+'</a>' 599 } 600 601 c = row.insertCell(-1) 602 c.className ='mono' 603 t = xval(pendtxs[j], 'id') 604 c.innerHTML = '<a href="https://blockchain.info/tx/'+t+'">'+t+'</a>' 605 606 c=row.insertCell(-1);className='maturity' 607 var tim = xval(pendtxs[j], 'time') 608 c["numeric_value"] = tim 609 c.innerHTML = get_maturity(tim) 610 } 611 } 612 txw4i.style.display = 'table' 613 } 614 } 615 txs2s.style.display = txsre.style.display = txw4i.style.display = 'none' 616 aj.open("GET","txw4i.xml", true); 617 aj.send(null); 618 } 619 620 var previousPoint = null 621 var mp = [] 622 var first_run = true 623 var loading_in_progress = false 624 625 function showTooltip(x, y, contents) { 626 $('<div id="tooltip">' + contents + '</div>').css( { 627 position: 'absolute', 628 display: 'none', 629 top: y - 30, 630 left: x + 5, 631 border: '2px solid #fdd', 632 padding: '5px', 633 'font-size' : '14px', 634 'background-color': '#fee', 635 opacity: 1 636 }).appendTo("body").fadeIn(200); 637 } 638 639 function time2str(sec) { 640 if (sec < 3600) { 641 return (sec/60).toFixed(1) + ' min' 642 } 643 if (sec < 24*3600) { 644 return (sec/3600).toFixed(1) + ' hour' 645 } 646 return (sec/(24*3600)).toFixed(1) + ' day' 647 } 648 649 function handlehover(event, pos, item) { 650 if (item) { 651 if (previousPoint != item.dataIndex) { 652 previousPoint = item.dataIndex; 653 $("#tooltip").remove(); 654 655 if (loading_in_progress) return 656 657 var rec = mp[item.dataIndex] 658 659 var str = '' 660 if (typeof(rec.Current_tx_spb)!="number") { 661 str += (rec[1]/1000).toFixed(2) + ' SPB' 662 str += ' @ ' + (rec[0]/4e6).toFixed(2) + 'BL' 663 } else { 664 str += 'Tx #'+(rec.Txs_so_far+1) + ' - ' 665 str += rec.Current_tx_spb.toFixed(2) + ' SPB<br>' 666 str += parseInt(rec.Current_tx_weight/4) + ' bytes' 667 str += ', ' + time2str(parseInt(new Date().getTime())/1000 - rec.Time_received) +' old<br>' 668 str += '' + (rec.Real_len_so_far/1e6).toFixed(2) + ' MB' 669 str += ' → ' + (rec.Weight_so_far/4e6).toFixed(2) + ' Blocks<br>' 670 str += ' Fees: ' + val2str(rec.Fees_so_far) + ' BTC<br>' 671 str += ' Ord: ' + (100*rec.Ord_weight_so_far/rec.Weight_so_far).toFixed(0) + '% weight<br>' 672 str += ' ' + val2str(rec.Ord_fees_so_far) + ' BTC<br>' 673 } 674 showTooltip(item.pageX, item.pageY, str) 675 } 676 } else { 677 $("#tooltip").remove(); 678 previousPoint = null; 679 } 680 } 681 682 function handleclick(event, pos, item) { 683 if (!loading_in_progress && !mempool_new_sort.checked && !tx_decoding_in_progress) { 684 var rec = mp[item.dataIndex] 685 decode_tx_id(rec.Current_tx_id) 686 } 687 } 688 689 function show_txid() { 690 if (!tx_decoding_in_progress) { 691 var tid = prompt("Enter ID of the TX"); 692 if (tid!=null) { 693 decode_tx_id(tid) 694 } 695 } 696 } 697 698 699 function show_mempool_fees() { 700 var aj = ajax() 701 var one_block = mempool_siz_range_1.checked 702 703 loading_in_progress = true 704 705 aj.onreadystatechange=function() { 706 if(aj.readyState==4) { 707 mp = JSON.parse(aj.responseText) 708 if (mp==null) return 709 710 console.log(mp.length, mp[0], mp[1]) 711 var plot_data = [ { data : [], color : 4, points: { show:!one_block }, lines: {show:true, fill:true}} ]; 712 var plot_options = { 713 grid: { 714 markings: [ { xaxis: { from: 0, to: 4e6 }, color: "#e0ffe0" }, 715 { xaxis: { from: 4e6, to: 8e6 }, color: "#f0f0e0" }, 716 { xaxis: { from: 8e6 }, color: "#ffe0e0" }, 717 ], 718 hoverable: true, 719 clickable: true 720 }, 721 xaxis: { 722 //tickLength : 1e6, 723 minTickSize : one_block ? 4e5 : 4e6, 724 tickFormatter : function(a,b) {return (a/4e6).toFixed(1)} 725 }, 726 yaxis : { 727 //position : "left" 728 } 729 } 730 731 var max_spb = 0 732 var max_spb_corrected = 0 733 var feesfrom1stblock = 0 734 var lenforfee = 0 735 var cr_spb, prv_spb = 21e14 736 737 if (mempool_new_sort.checked) { 738 for (var i=0; i < mp.length; i++) { 739 if (mp[i][1] > max_spb) { 740 max_spb = mp[i][1] 741 } 742 if (mp[i][0] < 4e6) { 743 feesfrom1stblock = mp[i][2] 744 lenforfee = mp[i][0] 745 } 746 747 cur_spb = (mp[i][1])/1000 748 if (cur_spb > prv_spb) { 749 cur_spb = prv_spb 750 } else { 751 prv_spb = cur_spb 752 } 753 plot_data[0].data.push([mp[i][0], cur_spb]) 754 } 755 } else { 756 for (var i=0; i<mp.length; i++) { 757 if (mp[i].Current_tx_spb>max_spb) { 758 max_spb = mp[i].Current_tx_spb 759 } 760 if (mp[i].Weight_so_far < 4e6) { 761 feesfrom1stblock = mp[i].Fees_so_far 762 lenforfee = mp[i].Weight_so_far 763 } 764 765 cur_spb = mp[i].Current_tx_spb 766 if (cur_spb > prv_spb) { 767 cur_spb = prv_spb 768 } else { 769 prv_spb = cur_spb 770 } 771 plot_data[0].data.push([mp[i].Weight_so_far+mp[i].Current_tx_weight, cur_spb]) 772 } 773 774 } 775 776 max_spb_corrected = 20*(feesfrom1stblock/lenforfee) 777 if (mempool_spb_range.checked && max_spb > max_spb_corrected) { 778 plot_options.yaxis.max = max_spb_corrected 779 } 780 781 if (first_run) { 782 $("#mempool_fees").bind("plothover", handlehover) 783 $("#mempool_fees").bind("plotclick", handleclick) 784 first_run = false 785 } 786 $.plot($("#mempool_fees"), plot_data, plot_options) 787 788 fees_from_first_block.innerText = (feesfrom1stblock/1e8).toFixed(3) 789 loading_in_progress = false 790 } 791 } 792 793 var url = mempool_new_sort.checked ? "mempool_fees.json" : "mempool_stats.json" 794 795 localStorage.setItem("txs_chart_y_limit", mempool_spb_range.checked) 796 localStorage.setItem("txs_chart_new_sort", mempool_new_sort.checked) 797 798 if (mempool_siz_range_1.checked) { 799 localStorage.setItem("txs_chart_x", "1") 800 url += "?max=4000000&div=1" 801 } else if (mempool_siz_range_6.checked) { 802 localStorage.setItem("txs_chart_x", "6") 803 url += "?max=24000000" 804 } else { 805 localStorage.setItem("txs_chart_x", "a") 806 } 807 aj.open("GET", url, true) 808 aj.send(null) 809 } 810 811 812 813 function refreshtxstat() { 814 var aj = ajax() 815 aj.onerror=function() { 816 setTimeout(refreshtxstat, 5000) 817 } 818 aj.onload=function() { 819 try { 820 var ts = JSON.parse(aj.responseText) 821 822 ts_t2s_size.value = bignum(ts.t2s_size)+'B in ' + ts.t2s_cnt + ' txs' 823 ts_t2s_size.title = "Average TX size: " + (ts.t2s_size/ts.t2s_cnt).toFixed(0) + " Bytes" 824 outspent.innerText = ts.spent_outs_cnt 825 if (ts.t2s_cnt>0) { 826 avgoutspertx.innerText = (ts.spent_outs_cnt/ts.t2s_cnt).toFixed(2) 827 } else { 828 avgoutspertx.innerText = '?' 829 } 830 butre.value = ts.tre_cnt 831 ts_tre_size.innerText = bignum(ts.tre_size)+'B' 832 butw4i.value = ts.awaiting_inputs + " / " + bignum(ts.awaiting_inputs_size) 833 ts_ptr1_cnt.innerText = ts.ptr1_cnt 834 ts_ptr2_cnt.innerText = ts.ptr2_cnt 835 min_spb.innerText = (ts.min_fee_per_kb/1000.0).toFixed(3) 836 } catch(e) { 837 console.log(e) 838 } 839 setTimeout(refreshtxstat, 1000) 840 } 841 aj.open("GET","txstat.json",true) 842 aj.send(null) 843 } 844 845 function restore_settings() { 846 var el = document.getElementById('mempool_siz_range_'+localStorage.getItem("txs_chart_x")) 847 if (el!=null) el.checked = true 848 mempool_spb_range.checked = localStorage.getItem("txs_chart_y_limit") !== "false" 849 mempool_new_sort.checked = localStorage.getItem("txs_chart_new_sort") !== "false" 850 } 851 restore_settings() 852 853 document.addEventListener('DOMContentLoaded', function() { 854 refreshtxstat() 855 window.onkeyup = function (event) { 856 if(event.keyCode == 27) closepopup() 857 } 858 }) 859 860 blno.addEventListener("lastblock", function(e) { 861 show_mempool_fees() 862 }) 863 864 </script>