├── README.md └── index.php /README.md: -------------------------------------------------------------------------------- 1 | Simple Block Explorer 2 | ===================================== 3 | 4 | A trivial block explorer written in a single PHP file. 5 | 6 | Demo 7 | ------- 8 | https://bitcoin.jonasschnelli.ch/explorer/ 9 | 10 | Features 11 | ------- 12 | * Only requires Bitcoin Core (no additional index) 13 | * Does UTXO-set lookups 14 | * Can scan UTXO-set for address balances 15 | * Can scan blockfilters to create a transaction history of given address 16 | 17 | Install 18 | ------- 19 | * Place the `index.php` script into a php enabled http docs directory 20 | * Run Bitcoin Core with txindex and blockfilters `-txindex -blockfilterindex` 21 | * Edit the index.php config section 22 | 23 | Nice links 24 | ------- 25 | 26 | Use `mod_rewrite` use a propper URL scheme (/block/), etc. 27 | Apache users can place a `.htaccess` file into the same folder as the PHP script. 28 | 29 | ``` 30 | RewriteEngine On 31 | RewriteRule ^testnet$ index.php?testnet=1 [L,QSA] 32 | RewriteRule ^testnet/$ index.php?testnet=1 [L,QSA] 33 | RewriteRule ^testnet/tx/([a-fA-F0-9]*)$ index.php?testnet=1&tx=$1 [L,QSA] 34 | RewriteRule ^testnet/tx/([a-fA-F0-9]*)/n/([a-fA-F0-9]*)$ index.php?testnet=1&tx=$1&n=$2 [L,QSA] 35 | RewriteRule ^testnet/block/([a-fA-F0-9]*)$ index.php?testnet=1&block=$1 [L,QSA] 36 | RewriteRule ^testnet/block/([a-fA-F0-9]*)/txid/([a-fA-F0-9]*)$ index.php?testnet=1&block=$1&txid=$2 [L,QSA] 37 | RewriteRule ^testnet/height/([0-9]*)$ index.php?testnet=1&search=$1 [L,QSA] 38 | RewriteRule ^tx/([a-fA-F0-9]*)$ index.php?tx=$1 [L,QSA] 39 | RewriteRule ^tx/([a-fA-F0-9]*)/n/([0-9]*)$ index.php?tx=$1&n=$2 [L,QSA] 40 | RewriteRule ^block/([a-fA-F0-9]*)$ index.php?block=$1 [L,QSA] 41 | RewriteRule ^block/([a-fA-F0-9]*)/txid/([a-fA-F0-9]*)$ index.php?block=$1&txid=$2 [L,QSA] 42 | RewriteRule ^height/([0-9]*)$ index.php?search=$1 [L,QSA] 43 | RewriteRule ^testnet/([a-zA-Z0-9]*)$ index.php?testnet=1&$1=1 [L,QSA] 44 | RewriteRule ^([a-zA-Z0-9]*)$ index.php?$1=1 [L,QSA] 45 | 46 | ``` 47 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | instead of index.php?block= 19 | $FOOTER = 'Simple Block Explorer for Bitcoin Core'; 20 | $TITLE = "Block Explorer"; 21 | ###### END CONFIG SECTION 22 | 23 | $HTMLTITLE = $TITLE; 24 | abstract class ViewType { const Overview = 0; const Block = 1; const Transaction = 2; const NotFound = 3; const NodeInfo = 4; const AddrSearch = 5; const TxHistory = 6;}; 25 | function clean_hex($in) { return htmlentities(strip_tags(preg_replace("/[^a-fA-F0-9]/", "", $in))); } 26 | function clean_search($in) { return htmlentities(strip_tags(preg_replace("/[^a-zA-Z0-9]/", "", $in))); } 27 | function clean_num($in) { return htmlentities(strip_tags(preg_replace("/[^0-9]/", "", $in))); } 28 | $ENDPOINT = isset($_REQUEST['testnet']) ? $TEST_ENDPOINT : $MAIN_ENDPOINT; 29 | $LINKADD = isset($_REQUEST['testnet']) ? (USE_MOD_REWRITE ? "testnet/" : "?testnet=1&") : ( USE_MOD_REWRITE ? "":"?"); 30 | $NOW = time(); 31 | $VIEWTYPE = ViewType::Overview; 32 | if(isset($_REQUEST['txhistory'])) { 33 | // try to scan all relevant blocks for a given address (in multiple steps due to execution timeout) 34 | // generates a transaction list with received and spent transactions 35 | 36 | // get raw post data sent through AJAX 37 | $json_in = file_get_contents('php://input'); 38 | $data = json_decode($json_in, true); 39 | $addr = clean_search($_REQUEST['txhistory']); 40 | $unspents = array(); 41 | $received = array(); 42 | $spent = array(); 43 | $txlist = array(); 44 | $txhistoryneedle = $addr; 45 | 46 | $processed = 0; 47 | if (isset($data)) { 48 | // TODO, sanitize txlist 49 | if (isset($data["unspents"])) { 50 | $unspents = $data["unspents"]; 51 | } 52 | if (isset($data["txlist"])) { 53 | $txlist = $data["txlist"]; 54 | } 55 | if (isset($data["remainingblocks"])) { 56 | $blocks = $data["remainingblocks"]; 57 | } 58 | } 59 | 60 | // fetch the whole blocks and check for spent and received transaction 61 | while (count($blocks) > 0 && $processed < TXHISTORY_MAX_BLOCKS_PER_CALL) { 62 | // only process TXHISTORY_MAX_BLOCKS_PER_CALL per call 63 | 64 | // get the next blockhash to process 65 | $blockhash = array_shift($blocks); 66 | $blockhash = rtrim($blockhash); 67 | if (strlen($blockhash) != 64) { continue; } 68 | 69 | // fetch the block over RPC with transaction data 70 | $block = rpcFetch("getblock", '["'.chop($blockhash).'", 2]'); 71 | foreach($block->result->tx as $tx) { 72 | if (count($unspents) > 0) { // only check for spent transactions if we have unspents 73 | foreach($tx->vin as $in) { 74 | if (isset($in->txid) && isset($unspents[$in->txid.$in->vout])) { 75 | // hit spent 76 | $spent = array("txid" => $tx->txid, "n" => $in->vout, "value" => $unspents[$in->txid.$in->vout], "tx" => $tx); 77 | array_push($txlist, array("type" => "out", "time" => $block->result->mediantime, "addr" => $addr, "txid" => $tx->txid, "n" => $in->vout, "value" => $unspents[$in->txid.$in->vout], "tx" => "")); 78 | unset($unspents[$in->txid.$in->vout]); 79 | } 80 | } 81 | } 82 | foreach($tx->vout as $out) { 83 | if (isset($out->scriptPubKey->address) && $out->scriptPubKey->address == $addr) { 84 | // hit received 85 | $received = array("txid" => $tx->txid, "n" => $out->n, "value" => $out->value, "tx" => $tx); 86 | array_push($txlist, array("type" => "in", "time" => $block->result->mediantime, "addr" => $out->scriptPubKey->address, "txid" => $tx->txid, "n" => $out->n, "value" => $out->value, "tx" => "")); 87 | 88 | // store the value and txid in the unspent array 89 | $unspents[$tx->txid.$out->n] = $out->value; 90 | } 91 | } 92 | } 93 | $processed++; 94 | } 95 | 96 | // calculate the total unspent balance 97 | $txhistorybalance = 0; 98 | foreach($unspents as $k => $v) { 99 | $txhistorybalance += $v; 100 | } 101 | 102 | // construct data set for hits 103 | $json_txlist = json_encode(array("totalblocks" => $data['totalblocks'], "remainingcount" => count($blocks), "remainingblocks" => $blocks, "txlist" => $txlist, "unspents" => $unspents)); 104 | $remainingblocks = count($blocks); 105 | $VIEWTYPE = ViewType::TxHistory; 106 | 107 | if (count($blocks) == 0) { 108 | // no more blocks, return html list 109 | 110 | echo "

Transaction History (only confirmed transactions)

\n"; 111 | echo "
Balance: ".btcamount($txhistorybalance)."
\n"; 112 | echo '\n"; 128 | 129 | die(); 130 | } 131 | echo $json_txlist; die(); 132 | } 133 | if(isset($_REQUEST['search'])) { 134 | $search = clean_search($_REQUEST['search']); 135 | //check if it is an address 136 | if(preg_match("/^(bc1|BC1|[13mt])[a-zA-HJ-NP-Z0-9]{25,75}$/", $search)) { 137 | $ADDRESSSEARCH = $search; 138 | if (isset($_REQUEST['utxolookupstatus'])) { 139 | // check if scan active (AJAX) 140 | $data = rpcFetch("scantxoutset", '["status"]'); 141 | if(!is_null($data->result)) { 142 | echo $data->result->progress; 143 | } 144 | die(); //end the programm as we want an AJAX response 145 | } 146 | else if (isset($_REQUEST['utxolookup'])) { 147 | // check if scan active 148 | $data = rpcFetch("scantxoutset", '["status"]'); 149 | if(is_null($data->result)) { 150 | $data = rpcFetch("scantxoutset", '["start", ["addr('.$search.')"]]'); 151 | if(!is_null($data->result)) { 152 | // ajax response for the scantxoutset report 153 | echo "
Total unspent BTC: ".$data->result->total_amount."

\n"; 154 | echo '

UTXOs (unspent transaction outputs)

'."\n"; 155 | echo ''."\n"; 156 | echo "\n"; 157 | foreach($data->result->unspents as $utxo) { 158 | echo "\n"; 159 | echo "\n"; 160 | echo "\n"; 161 | echo "\n"; 162 | echo "\n"; 163 | } 164 | echo "
AmountTXIDVout
".btcamount($utxo->amount)."txid, $utxo->vout)."\">".$utxo->txid."".$utxo->vout."
\n"; 165 | } 166 | } else { 167 | echo "A scan is currently running (done ".$data->result->progress."%). Please try again later. No concurrent scans are allowed."; 168 | } 169 | die(); 170 | } 171 | else if (isset($_REQUEST['scanfiltersstatus'])) { 172 | // check if scan active 173 | $data = rpcFetch("scanblocks", '["status"]'); 174 | if(!is_null($data->result)) { 175 | echo $data->result->progress; 176 | } 177 | die(); 178 | } 179 | else if (isset($_REQUEST['scanfilters'])) { 180 | // check if scan active 181 | $data = rpcFetch("scanblocks", '["status"]'); 182 | if(is_null($data->result)) { 183 | // no scan present 184 | $data = rpcFetch("scanblocks", '["start", ["addr('.$search.')"], '.(isset($_REQUEST['startheight']) ? clean_num($_REQUEST['startheight']) : 0 ).']'); 185 | if(!is_null($data->result)) { 186 | // ajax report for the blockfilter scan result 187 | $textblock = "{\"totalblocks\":".count($data->result->relevant_blocks).", \"remainingblocks\":["; 188 | foreach($data->result->relevant_blocks as $block) { 189 | $textblock .= "\"".$block."\",\n"; 190 | } 191 | $textblock = rtrim($textblock, ",\n"); 192 | $textblock .= "]}"; 193 | // build the HTML response for the blockfilter scan results including a form to build the transaction history 194 | echo "
195 | Found ".count($data->result->relevant_blocks)." relevant blocks (Show details)
196 | 197 | 198 | 199 | 200 |
201 |
202 |
203 |
Relevant blocks from height ".$data->result->from_height." to height ".$data->result->to_height."

204 |

Relevant blocks (".count($data->result->relevant_blocks)." relevant blocks)

205 | 206 | 207 | "; 208 | foreach($data->result->relevant_blocks as $block) { 209 | echo "\n"; 210 | echo "\n"; 211 | echo "\n"; 212 | } 213 | echo "
Blockhash
".$block."
\n
\n
"; 214 | } 215 | } else { 216 | echo "A scan is currently running (done ".$data->result->progress."%). Please try again later. No concurrent scans are allowed."; 217 | } 218 | die(); 219 | } 220 | 221 | $VIEWTYPE = ViewType::AddrSearch; 222 | } 223 | else { 224 | // not an address 225 | if (is_numeric($search)) { 226 | $blockhash = getBlockHashByHeight($search); 227 | if (strlen($blockhash) == 64) { $search = $blockhash; } 228 | } 229 | if (BLOCK_TXDETAILS) { 230 | $_REQUEST['txdetails'] = 1; 231 | } 232 | $block = getBlockJSON($search, true, isset($_REQUEST['txdetails'])); 233 | $VIEWTYPE = ViewType::Block; 234 | if (isset($block->height)) { $HTMLTITLE = $TITLE.", height ".$block->height; } 235 | if (!$block) { 236 | $tx = getTxJSON($search); 237 | if (!$tx) { 238 | $VIEWTYPE = ViewType::NotFound; 239 | } 240 | else { 241 | if(!isset($tx->confirmations)) { 242 | $tx->confirmations = 0; 243 | // check mempool 244 | $data = rpcFetch("getmempoolentry", '["'.$tx->txid.'"]')->result; 245 | $tx->mempool = $data; 246 | 247 | if(isset($_REQUEST['mempooltxdetails'])) { 248 | $cnt = 0; 249 | $total_in = 0; 250 | foreach($tx->vin as $txin) { 251 | $rawtx = rpcFetch("getrawtransaction", '["'.$txin->txid.'", 3]'); 252 | $tx->vin[$cnt]->prevout = $rawtx->result->vout[$txin->vout]; 253 | $total_in += $tx->vin[$cnt]->prevout->value; 254 | $cnt++; 255 | } 256 | $tx->total_in = $total_in; 257 | } 258 | } 259 | $VIEWTYPE = ViewType::Transaction; 260 | } 261 | } 262 | } 263 | } else if(isset($_REQUEST['block'])) { 264 | if (BLOCK_TXDETAILS) { 265 | $_REQUEST['txdetails'] = 1; 266 | } 267 | $VIEWTYPE = ViewType::Block; 268 | $block = getBlockJSON(clean_hex($_REQUEST['block']), true, isset($_REQUEST['txdetails'])); 269 | if (isset($block->height)) { $HTMLTITLE = $TITLE.", height ".$block->height; } 270 | } else if(isset($_REQUEST['tx'])) { 271 | $VIEWTYPE = ViewType::Transaction; 272 | $tx = getTxJSON(clean_hex($_REQUEST['tx'])); 273 | } else if(isset($_REQUEST['nodeinfo'])) { 274 | $VIEWTYPE = ViewType::NodeInfo; 275 | } 276 | if ($VIEWTYPE == ViewType::Overview) { 277 | $data = rpcFetch("getblockchaininfo")->result; 278 | $blocks = $data->blocks; 279 | $bestblockhash = $data->bestblockhash; 280 | 281 | $lastblocks = getLastBlocks($bestblockhash); 282 | } 283 | function getLastBlocks($tophash, $blk_count = 12) { 284 | global $NOW; 285 | $lastblocks = array(); 286 | $hash = $tophash; 287 | for ($i=0;$i<$blk_count;$i++) { 288 | array_push($lastblocks, getBlockJSON($hash)); 289 | $hash = $lastblocks[count($lastblocks)-1]->previousblockhash; 290 | $age_in_s = $NOW - $lastblocks[count($lastblocks)-1]->time; 291 | if ($age_in_s > 3600) { 292 | $lastblocks[count($lastblocks)-1]->age = gmdate("G", $age_in_s)." hours, ".gmdate("i", $age_in_s)." min"; 293 | } 294 | else if ($age_in_s > 60) { 295 | $lastblocks[count($lastblocks)-1]->age = gmdate("i", $age_in_s)." mins, ".gmdate("s", $age_in_s)." secs"; 296 | } 297 | else { 298 | $lastblocks[count($lastblocks)-1]->age = "New block"; 299 | } 300 | } 301 | return $lastblocks; 302 | } 303 | function rpcFetch($method, $json_params = "[]") { 304 | global $ENDPOINT; 305 | $opts = array('http' => 306 | array( 307 | 'method' => 'POST', 308 | 'header' => 'Content-type: text/plain', 309 | 'content' => '{"jsonrpc":"1.0","method":"'.$method.'","params":'.$json_params.'}' 310 | ) 311 | ); 312 | $context = stream_context_create($opts); 313 | $url = $ENDPOINT; 314 | $url = str_replace("://", "://".RPC_USER.":".RPC_PASS."@", $url); 315 | $response = file_get_contents($url, false, $context); 316 | return json_decode($response); 317 | } 318 | function getUTXOJSON($hash, $n) { 319 | $gettxout = rpcFetch("gettxout", '["'.$hash.'", '.$n.']')->result; 320 | return $gettxout; 321 | } 322 | function getBlockHeader($hash) { 323 | $block = rpcFetch("getblockheader", '["'.$hash.'"]'); 324 | if (isset($block->result)) { 325 | $block = $block->result; 326 | } 327 | if(!$block) { 328 | return; 329 | } 330 | return $block; 331 | } 332 | function getBlockHashByHeight($height) { 333 | # requires Core 0.18 334 | $blockhash = rpcFetch("getblockhash", '['.$height.']')->result; 335 | return $blockhash; 336 | } 337 | function getBlockJSON($hash, $stats = false, $withtxdetails = false) { 338 | $block = rpcFetch("getblock", '["'.$hash.'", '.($withtxdetails ? "2" : "1").']'); 339 | if (isset($block->result)) { 340 | $block = $block->result; 341 | } 342 | if (!$block) { 343 | $block = getBlockHeader($hash); 344 | } 345 | if ($stats) { 346 | $stats = rpcFetch("getblockstats", '["'.$hash.'"]'); 347 | if (isset($stats->result)) { 348 | $block->stats = $stats->result; 349 | } 350 | } 351 | return $block; 352 | } 353 | function getTxJSON($hash) { 354 | global $VIEWTYPE; 355 | $rawtx = rpcFetch("getrawtransaction", '["'.$hash.'", 3]'); 356 | if(isset($rawtx->result)) { 357 | $json = $rawtx->result; 358 | } 359 | if (!isset($json)) { $VIEWTYPE = ViewType::NotFound; return; } 360 | if (isset($json->blockhash)) { $json->blockheader = getBlockHeader($json->blockhash); } 361 | $missing_prevout = false; 362 | if (!$missing_prevout) { 363 | $total_in = 0; 364 | foreach($json->vin as &$vin) { 365 | if (isset($vin->prevout)) { 366 | $total_in += $vin->prevout->value; 367 | } 368 | } 369 | $json->total_in = $total_in; 370 | } 371 | $total_out = 0; 372 | foreach($json->vout as &$vout) { 373 | $total_out += $vout->value; 374 | $utxo = getUTXOJSON($json->txid, $vout->n); 375 | if (is_object($utxo)) { 376 | $vout->is_unspent = true; 377 | } 378 | } 379 | $json->total_out = $total_out; 380 | if (!$missing_prevout) { $json->fee = round($total_in-$total_out, 8); } 381 | if ($total_in == 0) { 382 | $json->fee = 0; 383 | } 384 | return $json; 385 | } 386 | function txlink($hash, $vout="") { 387 | global $LINKADD; 388 | if (USE_MOD_REWRITE) { return BASE_URL.$LINKADD."tx/".$hash.(strlen($vout) > 0 ? "/n/".$vout : ""); } 389 | return "index.php".$LINKADD."tx=".$hash.(strlen($vout) > 0 ? "&n=".$vout : ""); 390 | } 391 | function blocklink($hash, $txid="") { 392 | global $LINKADD; 393 | if (strlen($txid) > 0) { 394 | if (USE_MOD_REWRITE) { return BASE_URL.$LINKADD."block/".$hash."/txid/".$txid; } 395 | return BASE_URL."index.php".$LINKADD."block=".$hash."&txid=".$txid; 396 | } 397 | if (USE_MOD_REWRITE) { return BASE_URL.$LINKADD."block/".$hash; } 398 | return BASE_URL."index.php".$LINKADD."block=".$hash; 399 | } 400 | function addresslink($addr) { 401 | global $LINKADD; 402 | if (strlen($addr) > 0) { 403 | if (USE_MOD_REWRITE) { return BASE_URL.$LINKADD."?&search=".$addr; } 404 | return BASE_URL."index.php".$LINKADD."&search=".$addr; 405 | } 406 | } 407 | function overviewlink($testnet=0) { 408 | global $LINKADD; 409 | if ($testnet) { 410 | if (USE_MOD_REWRITE) { return BASE_URL."testnet/"; } 411 | return BASE_URL."index.php".$LINKADD."testnet=1"; 412 | } 413 | return BASE_URL; 414 | } 415 | function nodeInfolink() { 416 | global $LINKADD; 417 | if (USE_MOD_REWRITE) { return BASE_URL.$LINKADD."nodeinfo"; } 418 | return BASE_URL."index.php".$LINKADD."nodeinfo=1"; 419 | } 420 | function homelink() { 421 | global $LINKADD; 422 | if (USE_MOD_REWRITE) { return BASE_URL; } 423 | return BASE_URL."index.php"; 424 | } 425 | function btcamount($amount) { 426 | return number_format($amount, 8, ".", "'")." BTC"; 427 | } 428 | function shortHash($hash) { 429 | if(strlen($hash) < 12) { 430 | return $hash; 431 | } 432 | return substr($hash, 0, 6)."...".substr($hash, strlen($hash)-12, 12); 433 | } 434 | function shortAddr($addr) { 435 | if (strlen($addr) <= 36) return $addr; 436 | return substr($addr, 0, 25)."...".substr($addr, strlen($addr)-8, 8); 437 | } 438 | ?> 439 | 440 | 441 | 442 | 443 | 444 | <?php echo $HTMLTITLE; ?> 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 517 | 518 | 519 | 567 | 568 |
569 |
570 | 571 |
​ 572 |
573 |

Latest Blocks

574 |

Last blocks

575 | 576 |
577 |
578 |
height; ?>
579 |

hash; ?>

580 |
581 |
    582 |
  • nTx; ?> Transactions
  • 583 |
  • size)) echo number_format($block->size, 0, ".", "'"); ?> bytes
  • 584 |
  • age; ?> ago
  • 585 |
586 |
587 | Details 588 |
589 |
590 | 591 |
592 |
593 | result; 595 | ?> 596 |
597 |

Address Info

598 |
599 | isvalid): ?> 600 |
601 |
602 |
    603 |
  1. 604 |
    605 |
    Address
    606 | address;?> 607 |
    608 |
  2. 609 | witness_version)): ?> 610 |
  3. 611 |
    612 |
    Witness Version
    613 | witness_version; ?> 614 |
    615 |
  4. 616 |
  5. 617 |
    618 |
    Witness Program
    619 | witness_program; ?> 620 |
    621 |
  6. 622 | 623 |
624 |
625 |
626 |
    627 |
  1. 628 |
    629 |
    scriptPubKey
    630 | scriptPubKey; ?> 631 |
    632 |
  2. 633 |
634 |
635 |
636 | 637 |
638 |
639 | 645 | 648 |
649 |
650 |
651 |
652 |
653 |
654 | 655 | 656 |
657 |
658 | Invalid Address error)) echo " (Error: ".$addrdata->error.")"; ?> 659 |
660 |
661 | 662 | 783 | 784 | 785 | result; 787 | $blockchaininfo = rpcFetch("getblockchaininfo")->result; 788 | ?> 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 |
Chainchain; ?>
Versionsubversion; ?>
Connectionsconnections; ?>
Blocksblocks; ?>
Difficultydifficulty; ?>
813 | 814 |
815 |

Block Details

816 |
817 |
818 |
819 |
    820 |
  1. 821 |
    822 |
    Height
    823 | height; ?> 824 |
    825 |
  2. 826 |
  3. 827 |
    828 |
    Hash
    829 | hash); ?> 830 | 831 |
    832 |
    833 | hash; ?> 834 |
    835 |
    836 |
    837 |
  4. 838 |
  5. 839 |
    840 |
    Time
    841 | time); ?> 842 |
    843 |
  6. 844 |
  7. 845 |
    846 |
    Total amount in all outputs
    847 | stats->total_out/100000000.0); ?> 848 |
    849 |
  8. 850 |
  9. 851 |
    852 |
    Total fees
    853 | stats->totalfee/100000000); ?> 854 |
    855 |
  10. 856 |
  11. 857 |
    858 |
    Total fees & blockreward
    859 | stats->totalfee+$block->stats->subsidy)/100000000); ?> 860 |
    861 |
  12. 862 |
  13. 863 |
    864 |
    Previous Block
    865 | previousblockhash)): ?> 866 | previousblockhash); ?> 867 | 868 |
    869 |
    870 | previousblockhash; ?> 871 |
    872 |
    873 | 874 |
    875 |
  14. 876 |
877 |
878 |
879 |
    880 |
  1. 881 |
    882 |
    Size in Bytes
    883 | size)) echo number_format($block->size, 0, ".", "'"); else echo "N/A"; ?> 884 |
    885 |
  2. 886 |
  3. 887 |
    888 |
    Weight in Bytes
    889 | weight)) echo number_format($block->weight, 0, ".", "'"); else echo "N/A"; ?> 890 |
    891 |
  4. 892 |
  5. 893 |
    894 |
    Transactions
    895 | nTx; ?> 896 |
    897 |
  6. 898 |
  7. 899 |
    900 |
    Total inputs/outputs
    901 | stats->ins."/".$block->stats->outs; ?> 902 |
    903 |
  8. 904 |
  9. 905 |
    906 |
    Feerange
    907 | stats->minfeerate; ?>-stats->maxfeerate; ?> sats/vB 908 |
    909 |
  10. 910 |
  11. 911 |
    912 |
    Medianfee
    913 | stats->medianfee; ?> sats 914 |
    915 |
  12. 916 |
  13. 917 |
    918 |
    Next Block
    919 | nextblockhash)): ?> 920 | nextblockhash); ?> 921 | 922 |
    923 |
    924 | nextblockhash; ?> 925 |
    926 |
    927 | 928 |
    929 |
  14. 930 |
931 |
932 |
933 |
934 |
935 |

Transactions (nTx; ?>)

936 | tx)): ?> 937 | 938 | 939 |
    940 | tx as $tx): $i++; 941 | $total = 0; 942 | foreach($tx->vout as $out) { 943 | $total += $out->value; 944 | } 945 | ?> 946 |
  • ">
    fee)): ?>fee*100000000/$tx->vsize); ?> sat/vBvin)."/".count($tx->vout).""; ?>
    947 |
  • 948 | 949 |
950 | 951 |
    952 | tx as $tx): $i++?> 953 |
  • "> 954 |   
    955 |
  • 956 | 957 |
958 | 959 | 960 | Block data not available 961 | 962 |
963 |
964 | 965 |
966 |
967 |

Transaction Detailsconfirmations > 0) { echo "bg-secondary"; } else { echo "bg-danger"; } ?> align-middle ms-4 mb-1" style="font-size: 0.8rem;">confirmations > 0) ? $tx->confirmations." Confirmations" : "mempool"; ?>

968 |
969 |
970 |
971 |
972 |
    973 |
  1. 974 |
    975 | mempool)): ?> 976 |
    Time entered mempool
    977 | mempool->time); ?> 978 | 979 |
    Time
    980 | time); ?> 981 | 982 |
    983 |
  2. 984 |
  3. 985 |
    986 |
    TX ID
    987 | txid); ?> 988 | 989 |
    990 |
    991 | txid; ?> 992 |
    993 |
    994 |
    995 |
  4. 996 |
  5. 997 |
    998 |
    Block
    999 | mempool)) { echo "mempool"; } ?> 1000 | blockhash)): ?> 1001 | blockhash); ?> blockheader)) echo " / Height: blockhash, $tx->txid)."\">".$tx->blockheader->height.""; else echo "-"; ?> 1002 | 1003 |
    1004 |
  6. 1005 |
  7. 1006 |
    1007 |
    Confirmations
    1008 | confirmations; ?> 1009 |
    1010 |
  8. 1011 |
  9. 1012 |
    1013 |
    Fee
    1014 | fee); ?> 1015 |
    1016 |
  10. 1017 |
  11. 1018 |
    1019 |
    Total inputs (vin); ?>)
    1020 | total_in); ?> 1021 |
    1022 |
  12. 1023 |
  13. 1024 |
    1025 |
    Total outputs (vout); ?>)
    1026 | total_out); ?> 1027 |
    1028 |
  14. 1029 |
1030 |
1031 |
1032 |
    1033 |
  1. 1034 |
    1035 |
    Feerate
    1036 | mempool) ? $tx->mempool->fees->base : $tx->fee)*100000000/$tx->vsize, 2); ?> sats/vB 1037 |
    1038 |
  2. 1039 |
  3. 1040 |
    1041 |
    Size
    1042 | size; ?> Bytes 1043 |
    1044 |
  4. 1045 |
  5. 1046 |
    1047 |
    Virtual Size
    1048 | vsize; ?> vBytes 1049 |
    1050 |
  6. 1051 |
  7. 1052 |
    1053 |
    Weight
    1054 | weight; ?> 1055 |
    1056 |
  8. 1057 |
  9. 1058 |
    1059 |
    Locktime
    1060 | locktime; ?> 1061 |
    1062 |
  10. 1063 |
  11. 1064 |
    1065 |
    Version
    1066 | version; ?> 1067 |
    1068 |
  12. 1069 |
1070 |
1071 |
1072 | 1073 |
1074 |
1075 |

Inputs / Outputs

1076 |
1077 |
1078 |
1079 |
1080 |
    1081 | vin as $vin): ?> 1082 |
  1. 1083 | prevout)):?> 1084 | prevout->value); ?> 1085 | txid)): ?> 1086 | 1087 | 1088 |
    Coinbase
    1089 | 1090 |
  2. 1091 | 1092 |
1093 |
1094 |
1095 |
    1096 | vout as $vout): ?> 1097 |
  1. "> 1098 |
    scriptPubKey->address)) echo "scriptPubKey->address)."\">".shortAddr($vout->scriptPubKey->address).""; ?>
    ">scriptPubKey->type != "nulldata") { echo btcamount($vout->value); } else { echo "".$vout->scriptPubKey->asm.""; }; ?> 1099 |
    1100 | scriptPubKey->type; ?>is_unspent) || !isset($tx->blockhash)): ?>unspentspent 1101 | 1102 |
    1103 |
  2. 1104 | 1105 |
1106 |
1107 |
1108 | 1109 |
1110 | 1113 |
1114 | 1115 |
1116 |
1117 |

Transaction History (only confirmed transactions)

1118 |

1119 |
Total transactions found:
1120 | 0): ?>
Remaining Blocks to process:
1121 | 1122 | 1123 |
Balance:
1124 |
    1125 | 1126 |
  • 1127 |
    1128 |  "> 1129 | 1130 |
    1131 |
    1132 |
  • 1133 | 1134 |
1135 | 1136 | 0): ?> 1137 |
1138 | 1139 | 1140 |
1141 | 1149 | 1150 |
1151 |
1152 | 1153 |

Object not found

1154 | 1155 |
1156 |
1157 |
1158 |
1159 |
1160 |

1161 |
1162 |
1163 |
1164 |
1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1177 | 1178 | 1179 | --------------------------------------------------------------------------------