github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/client/www/templates/home.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  <script type="text/javascript" src="webui/jquery.flot.time.min.js"></script>
     4  <script type="text/javascript" src="webui/jquery.flot.crosshair.js"></script>
     5  
     6  <!-- include fees_chart.html -->
     7  
     8  <table width="100%" border="0">
     9  <colgroup>
    10  	<col width="50%">
    11  	<col width="50%">
    12  </colgroup>
    13  
    14  <tr><td colspan="2" style="padding:0px">
    15  <div align="right" style="float:right;font-size:12px;padding-top:0px">
    16  WebUI Settings:&nbsp;<input style="display:none" type="file" id="import_file" accept=".json">
    17  <a href="javascript:export_settings()"><img valign="bottom" title="Backup" src="webui/backup.png"> Export</a>
    18  &nbsp;
    19  <a href="javascript:import_file_click()"><img valign="bottom" title="Restore" src="webui/restore.png"> Import</a>
    20  </div>
    21  <h2 style="margin-top:10px;margin-bottom:5px">Recent Blocks</h2>
    22  
    23  <table width="100%"><tr style="border:0">
    24  <td style="padding:0">
    25  <span onclick="chart_type_spb.click()" class="hand">
    26  	<input type="radio" name="chart_type" id="chart_type_spb" onchange="draw_chart()" onclick="event.stopPropagation()"> Average SPB
    27  </span>
    28  &nbsp;&bull;&nbsp;
    29  <span onclick="chart_type_siz.click()" class="hand">
    30  	<input type="radio" name="chart_type" id="chart_type_siz" onchange="draw_chart()" onclick="event.stopPropagation()"> Blocksize KB
    31  </span>
    32  &nbsp;&bull;&nbsp;
    33  <span onclick="chart_type_txs.click()" class="hand">
    34  	<input type="radio" name="chart_type" id="chart_type_txs" onchange="draw_chart()" onclick="event.stopPropagation()"> Transactions
    35  </span>
    36  &nbsp;&bull;&nbsp;
    37  <span onclick="chart_type_wgt.click()" class="hand">
    38  	<input type="radio" name="chart_type" id="chart_type_wgt" onchange="draw_chart()" onclick="event.stopPropagation()"> Weight
    39  </span>
    40  &nbsp;&bull;&nbsp;
    41  
    42  <span onclick="chart_type_avg.click()" class="hand" style="display:inline">
    43  	<input type="checkbox" id="chart_type_avg" onchange="draw_chart()" onclick="event.stopPropagation()">
    44  	<span id="avg_size">.</span> bl. avg
    45  </span>
    46  &nbsp;
    47  <span onclick="chart_type_ord.click()" class="hand" title="See how much is used by Ordinal Inscriptions" id="ord_label">
    48  	<input type="checkbox" id="chart_type_ord" onchange="draw_chart()" onclick="event.stopPropagation()">
    49  	Ord. %
    50  </span>
    51  
    52  </td>
    53  <td align="right" style="padding:0px">
    54  	<table>
    55  	<tr style="border:0"><td style="padding-top:0px;padding-bottom:0px;" >Average:
    56  	<td align="right" style="padding-top:0px;padding-bottom:0px;" nowrap="nowrap" title="Mining hash rate"><a href="http://bitcoin.sipa.be/" target="_blank"><span id="si_network_hashrate"></span></a>
    57  	<td align="right" style="padding-top:0px;padding-bottom:0px;" title="Transaction fee"><a href="https://mempool.space/" target="_blank"><span id="si_avg_fee_spb"></span> SPB</a>
    58  	<td align="right" style="padding-top:0px;padding-bottom:0px;" title="Block size"><a href="https://www.blockchain.com/explorer/charts/avg-block-size" target="_blank" id="si_avg_block_size"></a>
    59  	</table>
    60  
    61  </td>
    62  </tr></table>
    63  <div id="chart" style="height:200px;margin-left:0px;margin-right:5px;margin-top:0px;margin-bottom:5px"></div>
    64  
    65  
    66  <tr><td colspan="2">
    67  	<h2>Last Block</h2>
    68  <table border="0" width="100%">
    69  	<tr><td align="right" class="nw">Block Hash:<td colspan="7"><b id="last_block_hash"></b>
    70  		<td align="right" class="nw">Last Header:
    71  			<td><b title="Last known header" id="si_last_hdr_height"></b>
    72  
    73  	<tr>
    74  		<td align="right" colspan="1">Version:
    75  			<td colspan="1"><b id="last_block_version"></b>
    76  		<td align="right">Received:
    77  			<td><b id="last_block_received"></b>
    78  		<td align="right">Timestamp:
    79  			<td class="nw"><b id="last_block_timestamp"></b>
    80  		<td align="right">Median:
    81  			<td class="nw"><b id="last_block_median"></b>
    82  		<td align="right">Difficulty:
    83  			<td><b id="last_block_difficulty"></b>
    84  	</table>
    85  </td>
    86  </tr>
    87  
    88  <tr><td valign="top">
    89  	<h2>Network</h2>
    90  	<table width="90%">
    91  	<colgroup>
    92  		<col width="25%">
    93  		<col width="20%">
    94  		<col width="25%">
    95  		<col width="30%">
    96  	</colgroup>
    97  	<tr><td nowrap="nowrap">Connections:
    98  		<td align="right"><b id="bw_open_conns_total"></b>
    99  		<td align="right" class="nw"><img title="outgoing" src="webui/outgoing.png"> <b id="bw_open_conns_out"></b>
   100  		<td align="right" class="nw"><img title="incoming" src="webui/incoming.png"> <b id="bw_open_conns_in"></b>
   101  	<tr><td>Downloading:
   102  		<td align="right" class="nw"><b id="bw_dl_speed_now"></b> KB/s
   103  		<td align="right" class="nw"><b id="bw_dl_speed_max"></b> KB/s max
   104  		<td align="right" class="nw"><b id="bw_dl_total"></b> tot
   105  	<tr><td>Uploading:
   106  		<td align="right" class="nw"><b id="bw_ul_speed_now"></b> KB/s
   107  		<td align="right" class="nw"><b id="bw_ul_speed_max"></b> KB/s max
   108  		<td align="right" class="nw"><b id="bw_ul_total"></b> tot
   109  	<tr><td>External IP:
   110  		<td colspan="1" align="right" id="external_ip0" style="font-weight:bold">
   111  		<td colspan="2" align="right" id="external_others" style="font-size:70%;font-style:italic;overlay-x:">
   112  	<tr title="Public Authorization Key"><td>Auth Key:
   113  		<td colspan="3" align="left" class="small"><b>@<!--PUB_AUTH_KEY--></b>
   114  	</table>
   115  <td valign="top">
   116  	<h2>Node</h2>
   117  	<table width="100%">
   118  	<tr><td>Uptime:<td>
   119  		<b id="si_node_uptime"></b>
   120  		&nbsp;&bull;&nbsp;
   121  		<b title="Known peers" id="si_known_peers"></b> peers
   122  		&nbsp;&bull;&nbsp;
   123  		<b title="ECDSA verify operations" id="si_ecdsa_verify_cnt"></b> ECs
   124  	<tr><td>Mem Used MB:<td>
   125  		<b title="Total memory used" id="si_total_mem"></b>
   126  		(<b title="Native Go heap" id="si_heap_size"></b> +
   127  		<b title="QDB UTXO records" id="si_qdb_extramem"></b>)
   128  		&nbsp;<span id="el_free_mem" style="display:none">[<a href="javascript:config('freemem')">FREE</a>]</span>
   129  
   130  	<tr><td nowrap="nowrap">TX Mempool:<td aligh="left">
   131  		<b title="Accepted" id="ts_t2s_size"></b>
   132  		&nbsp;&bull;&nbsp;
   133  		<b title="Rejected" id="ts_tre_size" style="font-weight:bold"></b>
   134  		&nbsp;&bull;&nbsp;
   135  		<b title="UTXOs spent in memory" id="outspent" style="font-weight:bold"></b>
   136  		&nbsp;&bull;&nbsp;
   137  		<b title="Minimum SPB" id="min_spb" style="font-weight:bold"></b> spb
   138  	<tr><td>Pending Data:<td><b id="si_net_tx_qsize"></b> txs,
   139  		&nbsp;<b id="si_net_block_qsize"></b> blocks,
   140  		&nbsp;<b id="si_blocks_cached"></b> <span id="si_blocks_cached_label"></span>,
   141  		&nbsp;<b id="si_blocks_to_get"></b> to get
   142  		<img id="si_saving" src="webui/saving.png" style="float:right;display:none" title="Saving UTXO.db in progress">
   143  	</tr>
   144  	<tr id="showcfg" style="display:none">
   145  
   146  <form method="post" style="margin:0" action="cfg" onsubmit="return confirm('Are you sure that you want to shut down this node?');">
   147  <td align="left" style="padding:0px"><input type="button" value="Edit configuration" onclick="shwcfg()">
   148  <td align="right" style="padding:0px">
   149  <input type="button" value="Save configuration" onclick="savecfg()">
   150  <input type="hidden" name="shutdown" value="1">
   151  <input type="submit" value="Shutdown Node">
   152  </form>
   153  </td>
   154  
   155  </tr>
   156  	</table>
   157  </table>
   158  
   159  <div id="formcfg" style="display:none">
   160  <h2>Configuration</h2>
   161  <table width="100%">
   162  <form method="post" action="cfg">
   163  <tr><td colspan="2"align="left">See <a href="http://gocoin.pl/gocoin_manual_client_config.html" target="_blank">help page</a> for the format of the configuration data.
   164  <tr><td colspan="2">
   165  	<textarea name="configjson" id="configjson" style="width:100%" rows="26">{CONFIG_FILE}</textarea>
   166  <tr><td align="center">
   167  	<i>Please note that some config values require a restart in order to be applied.
   168  	<td align="right">
   169  	<input type="button" value="Cancel" onclick="location.reload()">
   170  	<input type="submit" name="apply" value="Apply">
   171  	<input type="submit" name="save" value="Apply & Save">
   172  </form>
   173  </table>
   174  </div>
   175  
   176  <script>
   177  if (!server_mode) {
   178  	showcfg.style.display='table-row'
   179  	el_free_mem.style.display='inline'
   180  }
   181  
   182  
   183  var previousPoint = null;
   184  var cs
   185  
   186  const blks_average = 6
   187  
   188  function restore_chart_setting() {
   189  	var mod = localStorage.getItem("home_chart")
   190  	if ((mod+'').length!=3) mod = "spb"
   191  	document.getElementById('chart_type_'+mod).checked = true
   192  	chart_type_avg.checked = localStorage.getItem("home_chart_avg") === 'true'
   193  	chart_type_ord.checked = localStorage.getItem("home_chart_ord") === 'true'
   194  	avg_size.innerText = blks_average
   195  }
   196  restore_chart_setting()
   197  var chart_type_ord_prev = chart_type_ord.checked
   198  
   199  function showTooltip(x, y, contents) {
   200  	$('<div id="tooltip">' + contents + '</div>').css( {
   201  		position: 'absolute',
   202  		display: 'none',
   203  		top: y - 30,
   204  		left: x + 5,
   205  		border: '2px solid #fdd',
   206  		padding: '5px',
   207  		'font-size' : '14px',
   208  		'background-color': '#fee',
   209  		opacity: 1
   210  	}).appendTo("body").fadeIn(200);
   211  }
   212  
   213  function handlehover(event, pos, item) {
   214  	if (item) {
   215  		if (previousPoint != item.dataIndex) {
   216  			previousPoint = item.dataIndex;
   217  			$("#tooltip").remove();
   218  
   219  			var rec = cs[item.dataIndex]
   220  			var str = 'Block #'+rec.Height+', Version 0x'+rec.Version.toString(16)+'<br>'
   221  			str += tim2str(rec.Received)+' ... '+tim2str(rec.Timestamp, true)+'<br>'
   222  			str += ''+rec.TxCnt+' transactions / '+rec.Size+' bytes<br>'
   223  			str += val2str(rec.Reward)+' BTC / ' + rec.FeeSPB.toFixed(2)+' SPB<br>'
   224  			str += 'Block Weight: ' + rec.Weight + "<br>"
   225  			str += 'Mined by ' + rec.Miner + '<br>'
   226  			str += 'Ords use ' + (100*rec.OrdCnt/rec.TxCnt).toFixed(0) + '% txs, '
   227  			str += (100*rec.OrdSize/rec.Size).toFixed(0) + '% size, '
   228  			str += (100*rec.OrdWeight/rec.Weight).toFixed(0) + '% of weight'
   229  			//if (rec.Weight > 0)
   230  
   231  			showTooltip(item.pageX, item.pageY, str)
   232  		}
   233  	} else {
   234  		$("#tooltip").remove();
   235  		previousPoint = null;
   236  	}
   237  }
   238  
   239  
   240  function handleclick(event, pos, item) {
   241  	if (item) {
   242  		var rec = cs[item.dataIndex]
   243  		if (rec.HaveFeeStats) {
   244  			show_block_fees(rec.Height,rec.Size,rec.Miner.substr(0,12))
   245  		} else {
   246  			//alert("No fee stats for this block")
   247  		}
   248  	}
   249  }
   250  
   251  function draw_chart() {
   252  	// check if would have both SPB and Ord...
   253  	if (chart_type_spb.checked && chart_type_ord.checked) {
   254  		if (!chart_type_ord_prev) {
   255  			chart_type_wgt.checked = true // if clicking Ord: switch to Weigth
   256  		} else {
   257  			chart_type_ord.checked = false // clicking SPB: disable Ord
   258  		}
   259  	}
   260  	chart_type_ord_prev = chart_type_ord.checked
   261  	
   262  	var aj = ajax()
   263  	aj.onerror=function() {
   264  		setTimeout(draw_chart, 1000)
   265  	}
   266  
   267  	aj.onload=function() {
   268  		try {
   269  			_cs = JSON.parse(aj.responseText)
   270  			var plot_data = [ { data : [], points: { show:true, fill:true }, lines: {show:true, fill:true}},
   271  							{ data : [], bars:{ show:true, fill:true,  lineWidth:5}, color:"black" } ];
   272  			var plot_options = {
   273  				grid: { hoverable: true, clickable: true,  markings:[] },
   274  				xaxis: { mode: 'time', timeformat: "%H:%M", timezone: "browser" },
   275  				yaxis : {labelWidth : 30, min : 0, position : "right"}
   276  			}
   277  
   278  			if (chart_type_siz.checked) {
   279  				plot_data[0].color = 3
   280  				//plot_options.yaxis.max = 1100
   281  				//plot_options.yaxis.tickFormatter = function(a,b) {return (a/1e3).toFixed(1)+'M'}
   282  				localStorage.setItem("home_chart", "siz")
   283  			} else if (chart_type_spb.checked) {
   284  				plot_data[0].color = 2
   285  				localStorage.setItem("home_chart", "spb")
   286  			} else if (chart_type_wgt.checked) {
   287  				plot_data[0].color = 5
   288  				localStorage.setItem("home_chart", "wgt")
   289  			} else {
   290  				plot_data[0].color = 4
   291  				localStorage.setItem("home_chart", "txs")
   292  			}
   293  			localStorage.setItem("home_chart_avg", chart_type_avg.checked)
   294  			localStorage.setItem("home_chart_ord", chart_type_ord.checked)
   295  
   296  			//console.log(_cs)
   297  			cs = new Array()
   298  			for (var i=0; i<_cs.length; i++) {
   299  				if (_cs[i].TxCnt==1) {
   300  					//plot_data[1].data.push([_cs[i].Timestamp*1000, 100])
   301  					var tt = _cs[i].Timestamp*1000
   302  					plot_options.grid.markings.push({ xaxis: { from: tt, to: tt+240000 }, color: "#f0f0d0" })
   303  					continue // ignore blocks with a single conbase tx
   304  				}
   305  				cs.push(_cs[i])
   306  				if (chart_type_avg.checked) {
   307  					var sum=0, avgcnt=0, sumord=0;
   308  					for (var ii=i; avgcnt<blks_average && ii>=0; ii--) {
   309  						if (_cs[i].TxCnt==1) {
   310  							continue
   311  						}
   312  						avgcnt++;
   313  						if (chart_type_siz.checked) {
   314  							sum += _cs[ii].Size/1000.0
   315  							sumord += _cs[ii].OrdSize/1000.0
   316  						} else if (chart_type_spb.checked) {
   317  							sum += _cs[ii].FeeSPB
   318  						} else if (chart_type_wgt.checked) {
   319  							sum += _cs[ii].Weight
   320  							sumord += _cs[ii].OrdWeight
   321  						} else {
   322  							sum += _cs[ii].TxCnt
   323  							sumord += _cs[ii].OrdCnt
   324  						}
   325  					}
   326  					if (avgcnt>0) {
   327  						if (chart_type_spb.checked || !chart_type_ord.checked) {
   328  							plot_data[0].data.push([_cs[i].Timestamp*1000, sum/avgcnt])
   329  						} else {
   330  							plot_data[0].data.push([_cs[i].Timestamp*1000, 100*sumord/sum])
   331  						}
   332  					}
   333  				} else {
   334  					if (chart_type_siz.checked) {
   335  						if (chart_type_ord.checked) {
   336  							plot_data[0].data.push([_cs[i].Timestamp*1000, 100*_cs[i].OrdSize/_cs[i].Size])
   337  						} else {
   338  							plot_data[0].data.push([_cs[i].Timestamp*1000, _cs[i].Size/1000.0])
   339  						}
   340  					} else if (chart_type_spb.checked) {
   341  						plot_data[0].data.push([_cs[i].Timestamp*1000, _cs[i].FeeSPB])
   342  					} else if (chart_type_wgt.checked) {
   343  						if (chart_type_ord.checked) {
   344  							plot_data[0].data.push([_cs[i].Timestamp*1000, 100*_cs[i].OrdWeight/_cs[i].Weight])
   345  						} else {
   346  							plot_data[0].data.push([_cs[i].Timestamp*1000, _cs[i].Weight])
   347  						}
   348  					} else {
   349  						if (chart_type_ord.checked) {
   350  							plot_data[0].data.push([_cs[i].Timestamp*1000, 100*_cs[i].OrdCnt/_cs[i].TxCnt])
   351  						} else {
   352  							plot_data[0].data.push([_cs[i].Timestamp*1000, _cs[i].TxCnt])
   353  						}
   354  					}
   355  				}
   356  			}
   357  			
   358  			plot_options.yaxis.max = chart_type_ord.checked ? 100 : null
   359  			$("#chart").bind("plothover", handlehover)
   360  			$("#chart").bind("plotclick", handleclick)
   361  			$.plot($("#chart"), plot_data, plot_options)
   362  
   363  		} catch(e) {
   364  			console.log(e)
   365  		}
   366  	}
   367  	aj.open("GET","blocks.json",true)
   368  	aj.send(null)
   369  }
   370  
   371  
   372  var last_block_height = -1
   373  
   374  function shwcfg() {
   375  	showcfg.style.display='none'
   376  	formcfg.style.display='block'
   377  	window.scrollTo(0,document.body.scrollHeight)
   378  }
   379  
   380  blno.addEventListener("lastblock", function(e) {
   381  	var stat = e.block
   382  	if (last_block_height != stat.Height) {
   383  		last_block_hash.innerText = stat.Hash
   384  		last_block_timestamp.innerText = tim2str(stat.Timestamp)
   385  		last_block_height = stat.Height
   386  		last_block_difficulty.innerText = bignum(stat.Diff)
   387  		last_block_median.innerText = tim2str(stat.Median)
   388  		last_block_version.innerText = '0x' + leftpad(stat.Version.toString(16),  '0',  8)
   389  		draw_chart()
   390  	}
   391  	var ago = stat.Time_now - stat.Received
   392  	if (ago<120) {
   393  		last_block_received.innerText = ago + ' sec ago'
   394  	} else if (ago<2*3600) {
   395  		last_block_received.innerText = (ago/60.0).toFixed(1) + ' min ago'
   396  	}
   397  })
   398  
   399  </script>
   400  
   401  <script>
   402  function refreshsysinfo() {
   403  	var aj = ajax()
   404  	aj.onerror=function() {
   405  		setTimeout(refreshsysinfo, 5000)
   406  	}
   407  	aj.onload=function() {
   408  		try {
   409  			var si = JSON.parse(aj.responseText)
   410  			si_known_peers.innerText = si.Known_peers
   411  			si_total_mem.innerText = ((si.Heap_size+si.Qdb_extramem)/0x100000).toFixed(0)
   412  			el_free_mem.title = (si.Heap_sysmem/0x100000).toFixed(0)
   413  			si_heap_size.innerText = (si.Heap_size/0x100000).toFixed(0)
   414  			si_qdb_extramem.innerText = (si.Qdb_extramem/0x100000).toFixed(0)
   415  			si_net_block_qsize.innerText = si.Net_block_qsize
   416  			si_net_tx_qsize.innerText = si.Net_tx_qsize
   417  			si_ecdsa_verify_cnt.innerText = si.Ecdsa_verify_cnt
   418  			si_avg_block_size.innerText = (si.Average_block_size/1000).toFixed(1) + ' kB'
   419  			si_avg_fee_spb.innerText = si.Average_fee.toFixed(0)
   420  			if (si.Blocks_on_disk>0) {
   421  				si_blocks_cached.innerText = si.Blocks_on_disk
   422  				si_blocks_cached_label.innerText = "on disk"
   423  			} else {
   424  				si_blocks_cached.innerText = si.Blocks_cached
   425  				si_blocks_cached_label.innerText = "cached"
   426  			}
   427  			si_blocks_to_get.innerText = si.BlocksToGet
   428  			si_node_uptime.innerText = period2str(si.Node_uptime)
   429  			si_last_hdr_height.innerText = si.LastHeaderHeight
   430  			si_network_hashrate.innerText = bignum(si.NetworkHashRate) +'H/s'
   431  			si_saving.style.display = si.SavingUTXO ? "block" : "none"
   432  		} catch(e) {
   433  			console.log(e)
   434  		}
   435  		setTimeout(refreshsysinfo, 1000)
   436  	}
   437  	aj.open("GET","system.json",true)
   438  	aj.send(null)
   439  }
   440  refreshsysinfo()
   441  </script>
   442  
   443  <script>
   444  function refreshbwinfo() {
   445  	var aj = ajax()
   446  	aj.onerror=function() {
   447  		setTimeout(refreshbwinfo, 5000)
   448  	}
   449  	aj.onload=function() {
   450  		try {
   451  			var bw = JSON.parse(aj.responseText)
   452  			bw_open_conns_total.innerText = bw.Open_conns_total
   453  			bw_open_conns_out.innerText = bw.Open_conns_out
   454  			bw_open_conns_in.innerText = bw.Open_conns_in
   455  			bw_dl_speed_now.innerText = bw.Dl_speed_now >> 10
   456  			bw_dl_speed_max.innerText = bw.Dl_speed_max >> 10
   457  			bw_dl_total.innerText = bignum(bw.Dl_total)+'B'
   458  			bw_ul_speed_now.innerText = bw.Ul_speed_now >> 10
   459  			bw_ul_speed_max.innerText = bw.Ul_speed_max >> 10
   460  			bw_ul_total.innerText = bignum(bw.Ul_total)+'B'
   461  
   462  			// external IP
   463  			if (bw.ExternalIP.length==0) {
   464  				external_ip0.innerText = '?'
   465  				external_ip0.title = ''
   466  				external_others.innerHTML = ''
   467  			} else {
   468  				var ht=''
   469  				if (bw.ExternalIP.length>1) {
   470  					for (var i=1; i<bw.ExternalIP.length; i++) {
   471  						if (i>1) ht += ', '
   472  						ht += '<span title="'+bw.ExternalIP[i].Count+' times, last at '+tim2str(bw.ExternalIP[i].Timestamp)+
   473  						'">' + bw.ExternalIP[i].Ip + '</span>'
   474  						if (i==2 && bw.ExternalIP.length>=3) {
   475  							ht+= ', <span title="' + (bw.ExternalIP.length-3) + ' more">...</span>'
   476  							break
   477  						}
   478  					}
   479  				}
   480  				external_ip0.innerText = bw.ExternalIP[0].Ip
   481  				external_ip0.title = bw.ExternalIP[0].Count+' times, last at '+tim2str(bw.ExternalIP[0].Timestamp)
   482  				external_others.innerHTML = ht
   483  			}
   484  		} catch(e) {
   485  			console.log(e)
   486  		}
   487  		setTimeout(refreshbwinfo, 1000)
   488  	}
   489  	aj.open("GET","bwidth.json",true)
   490  	aj.send(null)
   491  }
   492  refreshbwinfo()
   493  
   494  
   495  function refreshtxstat() {
   496  	var aj = ajax()
   497  	aj.onerror=function() {
   498  		setTimeout(refreshtxstat, 5000)
   499  	}
   500  	aj.onload=function() {
   501  		try {
   502  			var ts = JSON.parse(aj.responseText)
   503  			ts_t2s_size.innerText = bignum(ts.t2s_size)+'B'
   504  			ts_t2s_size.title = ts.t2s_cnt + ' transactions accepted'
   505  			outspent.innerText = ts.spent_outs_cnt
   506  			ts_tre_size.innerText = bignum(ts.tre_size)+'B'
   507  			ts_tre_size.title = ts.tre_cnt + ' transactions rejected'
   508  			min_spb.innerText = (ts.min_fee_per_kb/1000.0).toFixed(1)
   509  		} catch(e) {
   510  			console.log(e)
   511  		}
   512  		setTimeout(refreshtxstat, 1000)
   513  	}
   514  	aj.open("GET","txstat.json",true)
   515  	aj.send(null)
   516  }
   517  refreshtxstat()
   518  
   519  function export_settings() {
   520  	var jsonstring = JSON.stringify(localStorage)
   521  	var a = document.createElement("a")
   522  	var file = new Blob([jsonstring], {type: 'application/json'})
   523  	a.href = URL.createObjectURL(file)
   524  	a.download = "gocoin-config.json"
   525  	a.click()
   526  }
   527  
   528  function import_file_click() {
   529  	import_file.click()
   530  }
   531  
   532  function import_file_selected(e) {
   533  	var f = import_file.files[0]
   534  	var reader = new FileReader()
   535  	reader.onload = function(e) {
   536  		//console.log('aac', e, e.target.result)
   537  		try {
   538  			var sets = JSON.parse(e.target.result)
   539  			var wlts = ''
   540  			localStorage.clear()
   541  			for (var nam in sets) {
   542  				localStorage.setItem(nam, sets[nam])
   543  			}
   544  			location.reload()
   545  		} catch (ex) {
   546  			console.log(ex)
   547  		}
   548  	};
   549  	reader.readAsText(f)
   550  }
   551  
   552  document.addEventListener('DOMContentLoaded', function() {
   553  	window.onkeyup = function (event) {
   554  		if(event.keyCode == 27)  closepopup()
   555  	}
   556  	import_file.addEventListener('change', import_file_selected, false);
   557  })
   558  
   559  </script>