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  &nbsp;&bull;&nbsp;
    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  &nbsp;&bull;&nbsp;
    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">&nbsp;
    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  &nbsp;&nbsp;&nbsp;
   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 += " &bull; "
   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 += '&nbsp;'
   502                      c.innerHTML += '<img style="cursor:pointer" title="Broadcast this TX" onclick="sendtx_click(\''+txid+'\')" src="webui/send.png">'
   503  					c.innerHTML += '&nbsp;'
   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 += ' &#8594; ' + (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 += ' &nbsp;&nbsp;&nbsp;' + 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>