|
7 | 7 | </div> |
8 | 8 | <div class="row border-bottom p-1 mx-0"> |
9 | 9 | <div class="col-md-2"><span data-bs-toggle="tooltip" data-bs-placement="top" title="KZG Commitment">KZG Commitment:</span></div> |
10 | | - <div class="col-md-10 text-monospace"> |
| 10 | + <div class="col-md-10 text-monospace text-break"> |
11 | 11 | 0x{{ printf "%x" $blob.KzgCommitment }} |
12 | 12 | <i class="fa fa-copy text-muted p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x{{ printf "%x" $blob.KzgCommitment }}"></i> |
13 | 13 | </div> |
14 | 14 | </div> |
15 | 15 | {{ if $blob.HaveData }} |
16 | 16 | <div class="row border-bottom p-1 mx-0"> |
17 | | - <div class="col-md-2"><span data-bs-toggle="tooltip" data-bs-placement="top" title="KZG Proof">KZG Proof:</span></div> |
18 | | - <div class="col-md-10 text-monospace"> |
19 | | - 0x{{ printf "%x" $blob.KzgProof }} |
20 | | - <i class="fa fa-copy text-muted p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x{{ printf "%x" $blob.KzgProof }}"></i> |
| 17 | + <div class="col-md-2"> |
| 18 | + <span data-bs-toggle="tooltip" data-bs-placement="top" title="Blob Data">Data:</span> |
| 19 | + <div class="btn-group btn-group-sm ms-2" role="group"> |
| 20 | + <button type="button" class="btn btn-outline-secondary btn-sm blob-view-toggle active" data-mode="hex" data-blob-idx="{{ $blob.Index }}">Hex</button> |
| 21 | + <button type="button" class="btn btn-outline-secondary btn-sm blob-view-toggle" data-mode="ascii" data-blob-idx="{{ $blob.Index }}">ASCII</button> |
| 22 | + </div> |
21 | 23 | </div> |
22 | | - </div> |
23 | | - <div class="row border-bottom p-1 mx-0"> |
24 | | - <div class="col-md-2"><span data-bs-toggle="tooltip" data-bs-placement="top" title="Blob Data">Data:</span></div> |
25 | | - <div class="col-md-10 text-monospace"> |
26 | | - 0x{{ printf "%x" $blob.BlobShort }} |
27 | | - {{- if $blob.IsShort -}}...{{ end }} |
| 24 | + <div class="col-md-10"> |
| 25 | + <div class="blob-data-container" data-blob-idx="{{ $blob.Index }}" data-blob-hex="{{ printf "%x" $blob.Blob }}"> |
| 26 | + <pre class="blob-data-view text-monospace mb-0" style="max-height: 300px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; background: var(--bs-tertiary-bg); padding: 0.5rem; border-radius: 0.25rem;">0x{{ printf "%x" $blob.BlobShort }}{{- if $blob.IsShort -}}...{{ end }}</pre> |
| 27 | + </div> |
28 | 28 | <i class="fa fa-copy text-muted p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x{{ printf "%x" $blob.Blob }}"></i> |
29 | 29 | </div> |
30 | 30 | </div> |
31 | 31 | {{ else }} |
32 | | - <div class="blobloader-container" data-commitment="0x{{ printf "%x" $blob.KzgCommitment }}"> |
| 32 | + <div class="blobloader-container" data-blob-idx="{{ $blob.Index }}"> |
33 | 33 | <div class="row border-bottom p-1 mx-0"> |
34 | 34 | <div class="col text-center"> |
35 | | - <a class="btn btn-primary blobloader-button" href="?blob=0x{{ printf "%x" $blob.KzgCommitment }}#blobSidecars" role="button">Load Blob Data</a> |
| 35 | + <a class="btn btn-primary blobloader-button" href="?blob={{ $blob.Index }}#blobSidecars" role="button">Load Blob Data</a> |
36 | 36 | </div> |
37 | 37 | </div> |
38 | 38 | </div> |
|
42 | 42 | {{ end }} |
43 | 43 | <script type="text/javascript"> |
44 | 44 | $(function() { |
| 45 | + function hexToAscii(hex) { |
| 46 | + var str = ''; |
| 47 | + for (var i = 0; i < hex.length; i += 2) { |
| 48 | + var code = parseInt(hex.substr(i, 2), 16); |
| 49 | + str += (code >= 32 && code <= 126) ? String.fromCharCode(code) : '.'; |
| 50 | + } |
| 51 | + return str; |
| 52 | + } |
| 53 | + |
| 54 | + function formatBlobData(hex, mode, maxLen) { |
| 55 | + if (mode === 'ascii') { |
| 56 | + var ascii = hexToAscii(hex); |
| 57 | + if (maxLen && ascii.length > maxLen) { |
| 58 | + return ascii.substring(0, maxLen) + '...'; |
| 59 | + } |
| 60 | + return ascii; |
| 61 | + } else { |
| 62 | + if (maxLen && hex.length > maxLen * 2) { |
| 63 | + return '0x' + hex.substring(0, maxLen * 2) + '...'; |
| 64 | + } |
| 65 | + return '0x' + hex; |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + $(".blob-view-toggle").on("click", function() { |
| 70 | + var btn = $(this); |
| 71 | + var mode = btn.data("mode"); |
| 72 | + var blobIdx = btn.data("blob-idx"); |
| 73 | + var container = $(".blob-data-container[data-blob-idx='" + blobIdx + "']"); |
| 74 | + var hex = container.data("blob-hex"); |
| 75 | + var view = container.find(".blob-data-view"); |
| 76 | + |
| 77 | + btn.siblings().removeClass("active"); |
| 78 | + btn.addClass("active"); |
| 79 | + |
| 80 | + view.text(formatBlobData(hex, mode, 512)); |
| 81 | + }); |
| 82 | + |
45 | 83 | $(".blobloader-button").each(function() { |
46 | 84 | var button = $(this); |
47 | 85 | var container = button.closest(".blobloader-container"); |
| 86 | + var blobIdx = container.data("blob-idx"); |
48 | 87 | button.on("click", function(evt) { |
49 | 88 | evt.preventDefault(); |
50 | 89 | if(button.hasClass("disabled")) return; |
51 | 90 | button.attr("disabled", "disabled").addClass("disabled"); |
52 | | - var commitment = container.data("commitment"); |
53 | | - jQuery.get("/slot/0x{{ printf "%x" .Block.BlockRoot }}/blob/" + commitment).then(function(data, status) { |
| 91 | + jQuery.get("/slot/0x{{ printf "%x" .Block.BlockRoot }}/blob/" + blobIdx).then(function(data, status) { |
54 | 92 | if(status == "success") |
55 | 93 | onSuccess(data); |
56 | 94 | else |
|
60 | 98 | button.attr("disabled", "").removeClass("disabled"); |
61 | 99 | } |
62 | 100 | function onSuccess(data) { |
63 | | - var blobShort = data.blob; |
64 | | - if(blobShort.length > 1024 + 2) { |
65 | | - blobShort = blobShort.substring(0, 1024 + 2) + "..."; |
| 101 | + var blobHex = data.blob; |
| 102 | + var blobShort = blobHex; |
| 103 | + if(blobShort.length > 1024) { |
| 104 | + blobShort = blobShort.substring(0, 1024) + "..."; |
66 | 105 | } |
67 | 106 | var rowHtml = [ |
68 | 107 | '<div class="row border-bottom p-1 mx-0">', |
69 | | - '<div class="col-md-2"><span data-bs-toggle="tooltip" data-bs-placement="top" title="KZG Proof">KZG Proof:</span></div>', |
70 | | - '<div class="col-md-10 text-monospace">', |
71 | | - data.kzg_proof, |
72 | | - '<i class="fa fa-copy text-muted p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="' + data.kzg_proof + '"></i>', |
| 108 | + '<div class="col-md-2">', |
| 109 | + '<span data-bs-toggle="tooltip" data-bs-placement="top" title="Blob Data">Data:</span>', |
| 110 | + '<div class="btn-group btn-group-sm ms-2" role="group">', |
| 111 | + '<button type="button" class="btn btn-outline-secondary btn-sm blob-view-toggle active" data-mode="hex" data-blob-idx="' + blobIdx + '">Hex</button>', |
| 112 | + '<button type="button" class="btn btn-outline-secondary btn-sm blob-view-toggle" data-mode="ascii" data-blob-idx="' + blobIdx + '">ASCII</button>', |
| 113 | + '</div>', |
73 | 114 | '</div>', |
74 | | - '</div>', |
75 | | - '<div class="row border-bottom p-1 mx-0">', |
76 | | - '<div class="col-md-2"><span data-bs-toggle="tooltip" data-bs-placement="top" title="Blob Data">Data:</span></div>', |
77 | | - '<div class="col-md-10 text-monospace">', |
78 | | - blobShort, |
79 | | - '<i class="fa fa-copy text-muted p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="' + data.blob + '"></i>', |
| 115 | + '<div class="col-md-10">', |
| 116 | + '<div class="blob-data-container" data-blob-idx="' + blobIdx + '" data-blob-hex="' + blobHex + '">', |
| 117 | + '<pre class="blob-data-view text-monospace mb-0" style="max-height: 300px; overflow-y: auto; white-space: pre-wrap; word-break: break-all; background: var(--bs-tertiary-bg); padding: 0.5rem; border-radius: 0.25rem;">0x' + blobShort + '</pre>', |
| 118 | + '</div>', |
| 119 | + '<i class="fa fa-copy text-muted p-1" role="button" data-bs-toggle="tooltip" title="Copy to clipboard" data-clipboard-text="0x' + blobHex + '"></i>', |
80 | 120 | '</div>', |
81 | 121 | '</div>', |
82 | 122 | ].join(""); |
83 | 123 | container.html(rowHtml); |
| 124 | + |
| 125 | + // Re-bind click handlers for the new toggle buttons |
| 126 | + container.find(".blob-view-toggle").on("click", function() { |
| 127 | + var btn = $(this); |
| 128 | + var mode = btn.data("mode"); |
| 129 | + var idx = btn.data("blob-idx"); |
| 130 | + var cont = $(".blob-data-container[data-blob-idx='" + idx + "']"); |
| 131 | + var hex = cont.data("blob-hex"); |
| 132 | + var view = cont.find(".blob-data-view"); |
| 133 | + |
| 134 | + btn.siblings().removeClass("active"); |
| 135 | + btn.addClass("active"); |
| 136 | + |
| 137 | + if (mode === 'ascii') { |
| 138 | + var ascii = ''; |
| 139 | + for (var i = 0; i < hex.length; i += 2) { |
| 140 | + var code = parseInt(hex.substr(i, 2), 16); |
| 141 | + ascii += (code >= 32 && code <= 126) ? String.fromCharCode(code) : '.'; |
| 142 | + } |
| 143 | + if (ascii.length > 512) ascii = ascii.substring(0, 512) + '...'; |
| 144 | + view.text(ascii); |
| 145 | + } else { |
| 146 | + var short = hex.length > 1024 ? hex.substring(0, 1024) + '...' : hex; |
| 147 | + view.text('0x' + short); |
| 148 | + } |
| 149 | + }); |
| 150 | + |
84 | 151 | explorer.initControls(); |
85 | 152 | } |
86 | 153 | }); |
87 | 154 | }); |
88 | | - |
89 | 155 | }); |
90 | 156 | </script> |
91 | 157 | {{ end }} |
0 commit comments