Commit 93099d26 authored by tom goriunov's avatar tom goriunov Committed by GitHub

components for Block and Tx entities (#1108)

* base implementation of entity

* refactor other components to make use of BlockEntity

* tests

* migrate entities w/o icon + L2 blocks

* base implementation of tx entity

* delet TransactionSnippet

* remove type="transaction" from AddressLink

* tests for TxEntity

* make EntityBase components

* common styles for icon color and spacing to text

* update icon color in tests

* update icons to slime format

* Address entity
parent 2df78df4
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.83 0 1 5.03v10.267l6.825 3.976-.034-1.67-5.421-3.175V6.8l6.757 3.818V19.6L9.84 20l.736-.401v-8.98L17.323 6.8v7.628l-5.388 3.108v1.67l6.858-3.834V5.029L9.829 0Zm0 9.415L3.238 5.531l6.59-3.877 6.75 3.877-6.75 3.884Zm-5.082 3.767 1.32-.752-.112-.196-1.32.752.112.196ZM7.06 11.86l1.32-.752-.113-.196-1.32.752.113.196Zm2.868-3.527V6.821h-.226v1.512h.226Zm0-2.636v-1.52h-.226v1.52h.226Zm0-2.534v-1.52h-.226v1.52h.226Zm2.854 8.51-1.31-.76-.114.195 1.311.76.114-.196Zm2.287 1.322-1.32-.76-.113.195 1.32.76.113-.195Zm-12.654 1.52 1.311-.751-.112-.196-1.311.751.112.196Zm14.979-.198-1.311-.76-.114.195 1.311.76.114-.195Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.392 1.45c.252-.288.592-.45.948-.45h8.038a.63.63 0 0 1 .474.225L17.54 6.61a.83.83 0 0 1 .196.544v12.308c0 .408-.141.799-.393 1.087-.25.289-.592.451-.947.451H4.34c-.356 0-.696-.162-.948-.45A1.661 1.661 0 0 1 3 19.461V2.538c0-.408.141-.799.392-1.087Zm.948 1.088h6.87v4.497c0 .388.315.702.702.702h4.485v11.725H4.34V2.538Zm8.274.59 2.791 3.205h-2.791V3.128ZM6.5 11a.5.5 0 0 0 0 1h7.2a.5.5 0 0 0 0-1H6.5ZM6 13.9a.5.5 0 0 1 .5-.5h7.2a.5.5 0 1 1 0 1H6.5a.5.5 0 0 1-.5-.5Zm4.5 2.1a.5.5 0 0 0 0 1h3.2a.5.5 0 0 0 0-1h-3.2Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.28 1.352A1.408 1.408 0 0 1 4.34.85h8.038a.78.78 0 0 1 .587.276l4.689 5.385a.98.98 0 0 1 .233.642v12.308c0 .442-.153.869-.43 1.187a1.408 1.408 0 0 1-1.06.502H4.34c-.403 0-.783-.184-1.06-.502a1.811 1.811 0 0 1-.43-1.187V2.538c0-.442.153-.869.43-1.186Zm1.06-.202c-.308 0-.61.14-.834.399-.226.259-.356.615-.356.99V19.46c0 .375.13.73.356.99.225.258.526.399.834.399h12.057c.309 0 .61-.14.834-.4.226-.259.356-.614.356-.989V7.153a.68.68 0 0 0-.16-.445L12.74 1.323a.48.48 0 0 0-.36-.173h-8.04Zm7.02 1.238v4.647c0 .304.248.551.552.551h4.635v12.025H4.19V2.388h7.17Zm-6.87.3v16.623h11.757V7.886h-4.335a.852.852 0 0 1-.852-.851V2.688H4.49Zm7.974.039 3.27 3.756h-3.27V2.727Zm.3.801v2.655h2.312l-2.312-2.655ZM6.5 11.15a.35.35 0 1 0 0 .7h7.2a.35.35 0 1 0 0-.7H6.5Zm-.65.35a.65.65 0 0 1 .65-.65h7.2a.65.65 0 1 1 0 1.3H6.5a.65.65 0 0 1-.65-.65Zm0 2.4a.65.65 0 0 1 .65-.65h7.2a.65.65 0 1 1 0 1.3H6.5a.65.65 0 0 1-.65-.65Zm.65-.35a.35.35 0 1 0 0 .7h7.2a.35.35 0 1 0 0-.7H6.5Zm4 2.6a.35.35 0 1 0 0 .7h3.2a.35.35 0 1 0 0-.7h-3.2Zm-.65.35a.65.65 0 0 1 .65-.65h3.2a.65.65 0 1 1 0 1.3h-3.2a.65.65 0 0 1-.65-.65Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.392.45C3.644.163 3.984 0 4.34 0h8.038a.63.63 0 0 1 .474.225L17.54 5.61a.83.83 0 0 1 .196.544v12.308c0 .408-.141.799-.393 1.087-.25.289-.592.451-.947.451H4.34c-.356 0-.696-.162-.948-.45A1.661 1.661 0 0 1 3 18.461V1.538c0-.408.141-.799.392-1.087Zm8.709 1.088H4.34v16.924h12.057V6.472l-4.296-4.934Z" fill="currentColor"/>
<path d="m7.3 13.357 2.2 2.357L13.9 11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.912.42c.388 0 .702.315.702.703v4.21h4.21a.702.702 0 1 1 0 1.404h-4.912a.702.702 0 0 1-.702-.702V1.123c0-.388.315-.702.702-.702Z" fill="currentColor"/>
</svg>
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.77 7.794H.987a.97.97 0 0 1-.549-.17 1.009 1.009 0 0 1-.364-.453 1.041 1.041 0 0 1 .218-1.106l3.722-3.827a.97.97 0 0 1 1.333.06 1.033 1.033 0 0 1 .058 1.37L3.371 5.764H17.77c.262 0 .513.107.698.297.185.19.29.449.29.718 0 .269-.105.527-.29.717a.973.973 0 0 1-.698.297ZM2.23 12.066h16.783c.195 0 .386.059.549.17.162.11.289.269.364.454a1.042 1.042 0 0 1-.218 1.106l-3.737 3.842-.006.007a.99.99 0 0 1-.711.354.963.963 0 0 1-.736-.296 1.017 1.017 0 0 1-.289-.757 1.04 1.04 0 0 1 .345-.731l.007-.007 2.047-2.112H2.23a.973.973 0 0 1-.698-.298 1.03 1.03 0 0 1-.29-.717c0-.27.105-.527.29-.718a.974.974 0 0 1 .698-.297Z" fill="currentColor"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="M14.806 21.313H4.582A.583.583 0 0 1 4 20.731V6.179c0-.322.261-.583.582-.583h2.654V3.27c0-.321.26-.582.582-.582h7.313c.007 0 .013.002.02.004.005.001.01.003.017.003a.558.558 0 0 1 .153.031l.02.006a.575.575 0 0 1 .194.118l4.285 4.11-.002.002a.58.58 0 0 1 .181.419v9.064a1.96 1.96 0 0 1-1.958 1.959h-1.277v.95a1.96 1.96 0 0 1-1.96 1.959ZM18.31 6.798l-2.598-2.506v1.713c0 .437.356.793.793.793h1.805Zm-3.42-3.289H8.058v14.072h10.327a.794.794 0 0 0 .793-.793V7.62h-2.671c-1.08 0-1.616-.535-1.616-1.615V3.509ZM7.236 6.42H4.822v14.07H15.15c.437 0 .793-.7.793-1.136v-.951H7.818a.582.582 0 0 1-.582-.583V6.42Zm9.482 4.532a.39.39 0 1 0 0-.78h-5.12l.502-.504a.39.39 0 0 0-.55-.549l-1.168 1.169a.39.39 0 0 0 .059.599.39.39 0 0 0 .216.065h6.06Zm-.012 1.363h-6.061a.39.39 0 0 0 0 .779h5.12l-.502.504a.39.39 0 1 0 .549.55l1.168-1.17a.39.39 0 0 0-.058-.598.39.39 0 0 0-.216-.065Z" clip-rule="evenodd"/>
<path fill="currentColor" d="M7.236 5.596v.25h.25v-.25h-.25Zm7.915-2.905-.07.24.07-.24Zm.017.003.014-.25-.014.25Zm.153.031.085-.235-.003-.001-.082.236Zm.02.006.072-.239-.072.24Zm.031.012.104-.228h-.001l-.103.228Zm.162.106.173-.18-.173.18Zm4.287 4.111.177.177.18-.18-.184-.177-.173.18Zm-.002.002-.176-.177-.18.18.183.177.173-.18Zm-3.054 11.442v-.25h-.25v.25h.25ZM15.713 4.292l.174-.18-.424-.408v.588h.25Zm2.598 2.506v.25h.62l-.446-.43-.174.18ZM8.058 3.51v-.25h-.25v.25h.25Zm6.833 0h.25v-.25h-.25v.25ZM8.058 17.581h-.25v.25h.25v-.25Zm11.12-9.96h.25v-.25h-.25v.25ZM4.822 6.418v-.25h-.25v.25h.25Zm2.414 0h.25v-.25h-.25v.25ZM4.822 20.49h-.25v.25h.25v-.25Zm11.12-2.087h.25v-.25h-.25v.25Zm1.051-7.567-.177-.177.177.177Zm0-.551-.177.177.177-.177Zm-5.396-.114-.177-.177-.425.427h.602v-.25Zm.503-.505.177.177.007-.007.006-.007-.19-.163Zm.093-.268.25-.01-.25.01Zm-.114-.26.177-.177-.177.177Zm-.26-.114.01-.25-.01.25Zm-.268.093-.163-.19-.007.007-.007.007.177.176Zm-1.169 1.169.177.177-.177-.177Zm-.107.199.245.05-.245-.05Zm.022.225-.232.095.001.001.23-.096Zm.143.175.139-.209-.139.209Zm.217.065v-.25.25Zm6.049 1.363v.25-.25Zm-6.337.114.177.177-.177-.177Zm0 .55.177-.176-.177.177Zm5.396.115.177.176.425-.426h-.602v.25Zm-.502.504.162.19.008-.007.007-.007-.177-.176Zm-.098.126.225.11-.225-.11Zm-.038.155-.25-.01.25.01Zm.026.157.233-.091-.233.09Zm.088.133-.177.177.177-.177Zm.29.114-.01-.25.01.25Zm.154-.039.11.225-.11-.225Zm.127-.097-.177-.177-.007.007-.006.007.19.163Zm1.168-1.168-.176-.178v.001l.176.177Zm.086-.425.23-.095v-.001l-.23.096Zm-.144-.174-.139.208.139-.208Zm-12.34 9.184h10.224v-.5H4.582v.5Zm-.832-.832c0 .46.373.832.832.832v-.5a.333.333 0 0 1-.332-.332h-.5Zm0-14.552V20.73h.5V6.179h-.5Zm.832-.833a.833.833 0 0 0-.832.833h.5c0-.184.149-.333.332-.333v-.5Zm2.654 0H4.582v.5h2.654v-.5Zm-.25-2.077v2.327h.5V3.27h-.5Zm.832-.832a.832.832 0 0 0-.832.832h.5c0-.183.148-.332.332-.332v-.5Zm7.313 0H7.818v.5h7.313v-.5Zm.09.014c-.002 0-.041-.014-.09-.014v.5a.202.202 0 0 1-.042-.004c-.007-.002-.013-.004-.009-.002l.14-.48Zm-.04-.006a.2.2 0 0 1 .034.004l.006.002-.14.48s.034.01.073.013l.027-.5Zm.222.044a.808.808 0 0 0-.22-.044l-.03.499a.307.307 0 0 1 .085.017l.165-.472Zm.01.003a2.077 2.077 0 0 1-.007-.002s-.001 0 0 0l-.17.47.032.01.145-.478Zm.062.022a.443.443 0 0 0-.062-.022l-.145.479a.198.198 0 0 1 .008.002l-.006-.002.205-.457Zm.232.154a.823.823 0 0 0-.231-.153l-.208.455c.041.018.07.038.093.06l.346-.362Zm4.287 4.112-4.287-4.111-.346.36 4.287 4.112.346-.361Zm.002.359.002-.002-.354-.354-.001.002.353.354Zm.254.242a.83.83 0 0 0-.257-.6l-.347.361a.33.33 0 0 1 .104.239h.5Zm0 9.064V7.381h-.5v9.064h.5Zm-2.208 2.209a2.21 2.21 0 0 0 2.208-2.209h-.5a1.71 1.71 0 0 1-1.708 1.709v.5Zm-1.277 0h1.277v-.5h-1.277v.5Zm.25.7v-.95h-.5v.95h.5Zm-2.21 2.209a2.21 2.21 0 0 0 2.21-2.208h-.5a1.71 1.71 0 0 1-1.71 1.708v.5Zm.735-17.09 2.598 2.505.347-.36-2.598-2.506-.348.36Zm.423 1.532V4.292h-.5v1.713h.5Zm.543.543a.544.544 0 0 1-.543-.543h-.5c0 .575.468 1.043 1.043 1.043v-.5Zm1.805 0h-1.805v.5h1.805v-.5ZM8.058 3.76h6.833v-.5H8.058v.5Zm.25 13.822V3.51h-.5v14.072h.5Zm10.077-.25H8.058v.5h10.327v-.5Zm.543-.543c0 .3-.244.543-.543.543v.5c.575 0 1.043-.468 1.043-1.043h-.5Zm0-9.168v9.168h.5V7.62h-.5Zm-2.421.25h2.67v-.5h-2.67v.5ZM14.64 6.005c0 .578.143 1.057.476 1.39.333.332.812.475 1.39.475v-.5c-.502 0-.831-.124-1.037-.33-.205-.205-.33-.533-.33-1.035h-.5Zm0-2.496v2.496h.5V3.509h-.5ZM4.822 6.67h2.414v-.5H4.822v.5Zm.25 13.822V6.419h-.5V20.49h.5Zm10.077-.25H4.822v.5h10.326v-.5Zm.543-.886c0 .162-.07.401-.195.599-.13.21-.264.287-.348.287v.5c.352 0 .616-.272.772-.522.164-.26.27-.59.27-.864h-.5Zm0-.951v.95h.5v-.95h-.5Zm-7.874.25h8.124v-.5H7.818v.5Zm-.832-.833c0 .46.372.833.832.833v-.5a.332.332 0 0 1-.332-.333h-.5Zm0-11.402v11.4h.5V6.42h-.5Zm9.83 4.24a.14.14 0 0 1-.098.042v.5a.64.64 0 0 0 .452-.188l-.354-.353Zm.041-.098a.14.14 0 0 1-.04.099l.353.353a.64.64 0 0 0 .187-.452h-.5Zm-.04-.098a.14.14 0 0 1 .04.098h.5a.64.64 0 0 0-.187-.452l-.354.354Zm-.1-.041a.14.14 0 0 1 .1.04l.353-.353a.64.64 0 0 0-.452-.187v.5Zm-5.12 0h5.12v-.5h-5.12v.5Zm.326-.931-.503.504.355.353.502-.504-.354-.353Zm.02-.082a.14.14 0 0 1-.033.096l.38.325a.64.64 0 0 0 .153-.44l-.5.019Zm-.04-.093a.14.14 0 0 1 .04.093l.5-.02a.64.64 0 0 0-.187-.427l-.353.354Zm-.094-.041a.14.14 0 0 1 .094.04l.353-.353a.64.64 0 0 0-.427-.187l-.02.5Zm-.096.033a.14.14 0 0 1 .096-.033l.02-.5a.64.64 0 0 0-.44.153l.324.38Zm-1.154 1.155 1.168-1.168-.353-.353-1.168 1.168.353.354Zm-.039.072a.139.139 0 0 1 .039-.071l-.353-.355a.64.64 0 0 0-.176.328l.49.098Zm.008.081a.139.139 0 0 1-.008-.08l-.49-.1a.64.64 0 0 0 .036.37l.462-.19Zm.05.061a.14.14 0 0 1-.05-.062l-.462.192c.049.117.13.217.236.287l.277-.417Zm.078.024a.14.14 0 0 1-.077-.024l-.277.417a.64.64 0 0 0 .356.107l-.002-.5Zm6.062 0h-6.061v.5h6.06v-.5Zm-6.073 1.863h6.06v-.5h-6.06v.5Zm-.099.04a.14.14 0 0 1 .099-.04v-.5a.64.64 0 0 0-.452.187l.353.354Zm-.04.1a.14.14 0 0 1 .04-.1l-.353-.353a.639.639 0 0 0-.188.452h.5Zm.04.098a.14.14 0 0 1-.04-.099h-.5c0 .17.067.333.187.452l.353-.353Zm.099.04a.14.14 0 0 1-.099-.04l-.353.353a.64.64 0 0 0 .452.188v-.5Zm5.12 0h-5.12v.5h5.12v-.5Zm-.325.931.502-.504-.354-.353-.502.505.354.352Zm-.05.06a.138.138 0 0 1 .035-.046l-.325-.38a.639.639 0 0 0-.16.207l.45.218Zm-.014.054a.14.14 0 0 1 .014-.055l-.45-.218a.64.64 0 0 0-.063.254l.5.02Zm.01.057a.139.139 0 0 1-.01-.057l-.5-.019a.64.64 0 0 0 .045.258l.465-.182Zm.031.047a.139.139 0 0 1-.03-.047l-.466.182a.64.64 0 0 0 .143.219l.353-.354Zm.048.032a.139.139 0 0 1-.048-.032l-.353.354a.64.64 0 0 0 .219.143l.182-.465Zm.056.01a.139.139 0 0 1-.056-.01l-.182.465a.64.64 0 0 0 .258.044l-.02-.5Zm.056-.015a.138.138 0 0 1-.056.014l.02.5a.64.64 0 0 0 .253-.064l-.217-.45Zm.045-.035a.138.138 0 0 1-.045.035l.217.45a.64.64 0 0 0 .208-.16l-.38-.325Zm1.181-1.182-1.168 1.168.354.354 1.168-1.168-.354-.354Zm.04-.072a.139.139 0 0 1-.04.071l.353.355a.64.64 0 0 0 .176-.327l-.49-.099Zm-.009-.08a.14.14 0 0 1 .008.08l.49.099a.64.64 0 0 0-.035-.37l-.463.19Zm-.05-.062a.14.14 0 0 1 .051.063l.461-.193a.64.64 0 0 0-.236-.286l-.276.416Zm-.078-.023a.14.14 0 0 1 .078.023l.276-.416a.639.639 0 0 0-.355-.107l.001.5Z"/>
</svg>
<svg viewBox="0 0 20 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.013 21H2.035a.626.626 0 0 1-.625-.625V4.749c0-.345.28-.625.625-.625h2.85V1.625c0-.345.279-.625.624-.625h7.853c.008 0 .014.002.021.004l.018.004a.6.6 0 0 1 .186.04.616.616 0 0 1 .208.126l4.603 4.414-.002.002a.622.622 0 0 1 .194.45v9.733c0 1.16-.943 2.103-2.102 2.103h-1.372v1.021c0 1.16-.944 2.103-2.103 2.103Zm3.764-15.586-2.79-2.69v1.838c0 .47.382.852.852.852h1.938Zm-3.673-3.531H5.767v15.11h11.089c.469 0 .851-.382.851-.852V6.297H14.84c-1.16 0-1.735-.575-1.735-1.735v-2.68Zm-8.22 3.124H2.293v15.11H13.38c.47 0 .852-.75.852-1.22v-1.02H5.509a.625.625 0 0 1-.625-.626V5.007Zm10.182 4.866a.418.418 0 1 0 0-.836H9.568l.54-.542a.418.418 0 0 0-.302-.69c-.105-.004-.226-.068-.306 0L8.172 9.103c-.06.058-.007.191-.024.272a.418.418 0 0 0 .178.43c.069.045.137.157.22.157l6.52-.088Zm-.013 1.377H8.545c-.11 0-.217.05-.295.129-.079.078-.123.265-.123.376a.418.418 0 0 0 .418.418h5.498l-.54.542a.417.417 0 0 0 .12.707.415.415 0 0 0 .47-.118l1.347-1.218c.059-.058.007-.169.023-.25a.417.417 0 0 0-.178-.43c-.068-.045-.15-.156-.232-.156Z" fill="currentColor"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.784 1.625c0-.4.325-.725.725-.725h7.853c.023 0 .042.006.048.008h.001a.705.705 0 0 1 .205.044h.002l.044.016a.72.72 0 0 1 .202.134l4.677 4.485-.007.007a.717.717 0 0 1 .156.446v9.733a2.205 2.205 0 0 1-2.202 2.203h-1.272v.921a2.205 2.205 0 0 1-2.203 2.203H2.035a.726.726 0 0 1-.725-.725V4.749c0-.4.325-.725.725-.725h2.75V1.625ZM18.255 5.59l-4.53-4.344a.518.518 0 0 0-.167-.103l-.026-.008a.492.492 0 0 0-.136-.027m4.86 4.482-.003.002.074.07c.1.097.163.23.163.378v9.733a2.005 2.005 0 0 1-2.002 2.003h-1.472v1.121a2.005 2.005 0 0 1-2.003 2.003H2.035a.526.526 0 0 1-.525-.525V4.749c0-.29.235-.525.525-.525h2.95V1.625c0-.29.234-.525.524-.525h7.846m-7.688.683h7.537v2.78c0 .564.14.968.403 1.231.264.263.668.403 1.232.403h2.968v9.944a.953.953 0 0 1-.951.952H5.667V1.783Zm.2.2v14.91h10.989a.753.753 0 0 0 .751-.752V6.397H14.84c-.595 0-1.059-.147-1.373-.462-.314-.314-.462-.778-.462-1.373v-2.58H5.867Zm8.02.505 3.138 3.026h-2.186a.953.953 0 0 1-.952-.952V2.488Zm.2.471v1.603c0 .415.337.752.752.752h1.69L14.087 2.96ZM2.193 4.907h2.791V17.25c0 .29.235.525.525.525h8.824v1.121c0 .257-.103.58-.265.84-.16.254-.399.48-.687.48H2.193V4.907Zm.2.2v14.91H13.38c.18 0 .368-.148.517-.387.146-.234.235-.52.235-.733v-.92H5.509a.725.725 0 0 1-.725-.726V5.107H2.393Zm7.193 2.872L8.334 9.231a.32.32 0 0 0-.07.347.318.318 0 0 0 .294.195h6.508a.318.318 0 0 0 0-.636H9.327l.707-.71a.319.319 0 0 0-.448-.448Zm-.133-.15a.518.518 0 0 1 .73.731l-.004.006-.37.37h5.257a.518.518 0 0 1 0 1.037H8.56m-.366-.884a.518.518 0 0 0 .366.884m.894-2.143-1.26 1.26 1.26-1.26Zm-.908 3.607a.318.318 0 1 0 0 .636h5.739l-.715.718a.319.319 0 0 0 .09.537.319.319 0 0 0 .358-.089l.005-.006 1.255-1.254a.318.318 0 0 0-.047-.489.318.318 0 0 0-.177-.053H8.545Zm-.366-.048a.518.518 0 0 1 .366-.152h6.508m.365.883a.518.518 0 0 0-.365-.883m.365.883-1.251 1.252a.518.518 0 1 1-.732-.73l.367-.369H8.545a.518.518 0 0 1-.366-.884" fill="currentColor"/>
</svg>
......@@ -9,7 +9,7 @@ export const hash = '0xd789a607CEac2f0E14867de4EB15b15C9FFB5859';
export const withName: AddressParam = {
hash: hash,
implementation_name: null,
is_contract: true,
is_contract: false,
is_verified: null,
name: 'ArianeeStore',
private_tags: [],
......@@ -20,7 +20,7 @@ export const withName: AddressParam = {
export const withoutName: AddressParam = {
hash: hash,
implementation_name: null,
is_contract: true,
is_contract: false,
is_verified: null,
name: null,
private_tags: [],
......
import { Box, Text, Grid, Skeleton } from '@chakra-ui/react';
import { Box, Text, Grid } from '@chakra-ui/react';
import type { UseQueryResult } from '@tanstack/react-query';
import { useRouter } from 'next/router';
import React from 'react';
......@@ -7,7 +7,6 @@ import type { Address as TAddress } from 'types/api/address';
import { route } from 'nextjs-routes';
import blockIcon from 'icons/block.svg';
import type { ResourceError } from 'lib/api/resources';
import useApiQuery from 'lib/api/useApiQuery';
import getQueryParamString from 'lib/router/getQueryParamString';
......@@ -15,10 +14,11 @@ import { ADDRESS_COUNTERS } from 'stubs/address';
import AddressCounterItem from 'ui/address/details/AddressCounterItem';
import AddressLink from 'ui/shared/address/AddressLink';
import AddressHeadingInfo from 'ui/shared/AddressHeadingInfo';
import Icon from 'ui/shared/chakra/Icon';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DetailsInfoItem from 'ui/shared/DetailsInfoItem';
import DetailsSponsoredItem from 'ui/shared/DetailsSponsoredItem';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -104,7 +104,7 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
>
<AddressLink type="address" hash={ data.creator_address_hash } truncation="constant"/>
<Text whiteSpace="pre"> at txn </Text>
<AddressLink hash={ data.creation_tx_hash } type="transaction" truncation="constant"/>
<TxEntity hash={ data.creation_tx_hash } truncation="constant" noIcon/>
</DetailsInfoItem>
) }
{ data.is_contract && data.implementation_address && (
......@@ -210,16 +210,10 @@ const AddressDetails = ({ addressQuery, scrollRef }: Props) => {
py={{ base: '2px', lg: 1 }}
isLoading={ addressQuery.isPlaceholderData }
>
<LinkInternal
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block_number_balance_updated_at) } }) }
display="flex"
alignItems="center"
>
<Box mr={ 2 }>
<Icon as={ blockIcon } boxSize={ 6 } isLoading={ addressQuery.isPlaceholderData }/>
</Box>
<Skeleton isLoaded={ !addressQuery.isPlaceholderData }>{ data.block_number_balance_updated_at }</Skeleton>
</LinkInternal>
<BlockEntity
number={ data.block_number_balance_updated_at }
isLoading={ addressQuery.isPlaceholderData }
/>
</DetailsInfoItem>
) }
<DetailsSponsoredItem isLoading={ addressQuery.isPlaceholderData }/>
......
......@@ -4,12 +4,10 @@ import React from 'react';
import type { Block } from 'types/api/block';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import LinkInternal from 'ui/shared/LinkInternal';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import Utilization from 'ui/shared/Utilization/Utilization';
......@@ -19,16 +17,18 @@ type Props = Block & {
};
const AddressBlocksValidatedListItem = (props: Props) => {
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: props.height.toString() } });
const timeAgo = useTimeAgoIncrement(props.timestamp, props.page === 1);
const totalReward = getBlockTotalReward(props);
return (
<ListItemMobile rowGap={ 2 } isAnimated>
<Flex justifyContent="space-between" w="100%">
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
<LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal>
</Skeleton>
<BlockEntity
isLoading={ props.isLoading }
number={ props.height }
noIcon
fontWeight={ 700 }
/>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
<span>{ timeAgo }</span>
</Skeleton>
......
......@@ -4,11 +4,9 @@ import React from 'react';
import type { Block } from 'types/api/block';
import { route } from 'nextjs-routes';
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import LinkInternal from 'ui/shared/LinkInternal';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import Utilization from 'ui/shared/Utilization/Utilization';
type Props = Block & {
......@@ -17,16 +15,20 @@ type Props = Block & {
};
const AddressBlocksValidatedTableItem = (props: Props) => {
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(props.height) } });
const timeAgo = useTimeAgoIncrement(props.timestamp, props.page === 1);
const totalReward = getBlockTotalReward(props);
return (
<Tr>
<Td>
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
<LinkInternal href={ blockUrl } fontWeight="700">{ props.height }</LinkInternal>
</Skeleton>
<BlockEntity
isLoading={ props.isLoading }
number={ props.height }
noIcon
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 700 }
/>
</Td>
<Td>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
......
......@@ -4,14 +4,11 @@ import React from 'react';
import type { AddressCoinBalanceHistoryItem } from 'types/api/address';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import { WEI, ZERO } from 'lib/consts';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Address from 'ui/shared/address/Address';
import AddressLink from 'ui/shared/address/AddressLink';
import LinkInternal from 'ui/shared/LinkInternal';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
type Props = AddressCoinBalanceHistoryItem & {
......@@ -20,7 +17,6 @@ type Props = AddressCoinBalanceHistoryItem & {
};
const AddressCoinBalanceListItem = (props: Props) => {
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(props.block_number) } });
const deltaBn = BigNumber(props.delta).div(WEI);
const isPositiveDelta = deltaBn.gte(ZERO);
const timeAgo = useTimeAgoIncrement(props.block_timestamp, props.page === 1);
......@@ -44,16 +40,23 @@ const AddressCoinBalanceListItem = (props: Props) => {
</Flex>
<Flex columnGap={ 2 } w="100%">
<Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Block</Skeleton>
<Skeleton isLoaded={ !props.isLoading }>
<LinkInternal href={ blockUrl } fontWeight="700">{ props.block_number }</LinkInternal>
</Skeleton>
<BlockEntity
isLoading={ props.isLoading }
number={ props.block_number }
noIcon
fontWeight={ 700 }
/>
</Flex>
{ props.transaction_hash && (
<Flex columnGap={ 2 } w="100%">
<Skeleton isLoaded={ !props.isLoading } fontWeight={ 500 } flexShrink={ 0 }>Txs</Skeleton>
<Address maxW="150px" fontWeight="700">
<AddressLink hash={ props.transaction_hash } type="transaction" isLoading={ props.isLoading }/>
</Address>
<TxEntity
hash={ props.transaction_hash }
isLoading={ props.isLoading }
noIcon
fontWeight={ 700 }
maxW="150px"
/>
</Flex>
) }
<Flex columnGap={ 2 } w="100%">
......
......@@ -4,13 +4,10 @@ import React from 'react';
import type { AddressCoinBalanceHistoryItem } from 'types/api/address';
import { route } from 'nextjs-routes';
import { WEI, ZERO } from 'lib/consts';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Address from 'ui/shared/address/Address';
import AddressLink from 'ui/shared/address/AddressLink';
import LinkInternal from 'ui/shared/LinkInternal';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
type Props = AddressCoinBalanceHistoryItem & {
page: number;
......@@ -18,7 +15,6 @@ type Props = AddressCoinBalanceHistoryItem & {
};
const AddressCoinBalanceTableItem = (props: Props) => {
const blockUrl = route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(props.block_number) } });
const deltaBn = BigNumber(props.delta).div(WEI);
const isPositiveDelta = deltaBn.gte(ZERO);
const timeAgo = useTimeAgoIncrement(props.block_timestamp, props.page === 1);
......@@ -26,18 +22,25 @@ const AddressCoinBalanceTableItem = (props: Props) => {
return (
<Tr>
<Td>
<Skeleton isLoaded={ !props.isLoading } display="inline-block">
<LinkInternal href={ blockUrl } fontWeight="700">{ props.block_number }</LinkInternal>
</Skeleton>
<BlockEntity
isLoading={ props.isLoading }
number={ props.block_number }
noIcon
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 700 }
/>
</Td>
<Td>
{ props.transaction_hash &&
(
<Address w="150px" fontWeight="700">
<AddressLink hash={ props.transaction_hash } type="transaction" isLoading={ props.isLoading }/>
</Address>
)
}
{ props.transaction_hash && (
<TxEntity
hash={ props.transaction_hash }
isLoading={ props.isLoading }
noIcon
fontWeight={ 700 }
maxW="150px"
/>
) }
</Td>
<Td>
<Skeleton isLoaded={ !props.isLoading } color="text_secondary" display="inline-block">
......@@ -51,7 +54,7 @@ const AddressCoinBalanceTableItem = (props: Props) => {
</Td>
<Td isNumeric display="flex" justifyContent="end">
<Skeleton isLoaded={ !props.isLoading }>
<Stat flexGrow="0">
<Stat flexGrow="0" lineHeight={ 5 }>
<StatHelpText display="flex" mb={ 0 } alignItems="center">
<StatArrow type={ isPositiveDelta ? 'increase' : 'decrease' }/>
<Text as="span" color={ isPositiveDelta ? 'green.500' : 'red.500' } fontWeight={ 600 }>
......
......@@ -4,8 +4,6 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import eastArrowIcon from 'icons/arrows/east.svg';
import dayjs from 'lib/date/dayjs';
......@@ -15,8 +13,9 @@ import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TxStatus from 'ui/shared/TxStatus';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
......@@ -50,16 +49,25 @@ const TxInternalsListItem = ({
<TxStatus status={ success ? 'ok' : 'error' } errorText={ error } isLoading={ isLoading }/>
</Flex>
<Flex justifyContent="space-between" width="100%">
<AddressLink fontWeight="700" hash={ txnHash } truncation="constant" type="transaction" isLoading={ isLoading }/>
<TxEntity
hash={ txnHash }
isLoading={ isLoading }
fontWeight={ 700 }
truncation="constant"
/>
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
<span>{ dayjs(timestamp).fromNow() }</span>
</Skeleton>
</Flex>
<HStack spacing={ 1 }>
<Skeleton isLoaded={ !isLoading } fontSize="sm" fontWeight={ 500 }>Block</Skeleton>
<Skeleton isLoaded={ !isLoading }>
<LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: block.toString() } }) }>{ block }</LinkInternal>
</Skeleton>
<BlockEntity
isLoading={ isLoading }
number={ block }
noIcon
fontSize="sm"
lineHeight={ 5 }
/>
</HStack>
<Box w="100%" display="flex" columnGap={ 3 }>
<Address width="calc((100% - 48px) / 2)">
......
......@@ -4,8 +4,6 @@ import React from 'react';
import type { InternalTransaction } from 'types/api/internalTransaction';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
......@@ -15,8 +13,9 @@ import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag';
import LinkInternal from 'ui/shared/LinkInternal';
import TxStatus from 'ui/shared/TxStatus';
import { TX_INTERNALS_ITEMS } from 'ui/tx/internals/utils';
......@@ -48,7 +47,12 @@ const AddressIntTxsTableItem = ({
<Tr alignItems="top">
<Td verticalAlign="middle">
<Flex rowGap={ 3 } flexWrap="wrap">
<AddressLink fontWeight="700" hash={ txnHash } type="transaction" isLoading={ isLoading }/>
<TxEntity
hash={ txnHash }
isLoading={ isLoading }
fontWeight={ 700 }
noIcon
/>
{ timestamp && (
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
<span>{ timeAgo }</span>
......@@ -67,11 +71,14 @@ const AddressIntTxsTableItem = ({
</Flex>
</Td>
<Td verticalAlign="middle">
<Skeleton isLoaded={ !isLoading } display="inline-block">
<LinkInternal href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: block.toString() } }) }>
{ block }
</LinkInternal>
</Skeleton>
<BlockEntity
isLoading={ isLoading }
number={ block }
noIcon
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 500 }
/>
</Td>
<Td verticalAlign="middle">
<Address display="inline-flex" maxW="100%">
......
......@@ -458,7 +458,15 @@ const BlockDetails = ({ query }: Props) => {
hint="The hash of the block from which this block was generated"
flexWrap="nowrap"
>
<AddressLink hash={ data.parent_hash } type="block" blockHeight={ String(data.height - 1) }/>
<LinkInternal
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.height - 1) } }) }
overflow="hidden"
whiteSpace="nowrap"
>
<HashStringShortenDynamic
hash={ data.parent_hash }
/>
</LinkInternal>
<CopyToClipboard text={ data.parent_hash }/>
</DetailsInfoItem>
) }
......
......@@ -15,6 +15,7 @@ import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
......@@ -38,17 +39,13 @@ const BlocksListItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
<ListItemMobile rowGap={ 3 } key={ String(data.height) } isAnimated>
<Flex justifyContent="space-between" w="100%">
<Flex columnGap={ 2 } alignItems="center">
<Skeleton isLoaded={ !isLoading } display="inline-block">
<LinkInternal
<BlockEntity
isLoading={ isLoading }
number={ data.height }
hash={ data.type === 'reorg' ? data.hash : undefined }
noIcon
fontWeight={ 600 }
href={ route({
pathname: '/block/[height_or_hash]',
query: { height_or_hash: data.type === 'reorg' ? String(data.hash) : String(data.height) },
}) }
>
{ data.height }
</LinkInternal>
</Skeleton>
/>
</Flex>
<BlockTimestamp ts={ data.timestamp } isEnabled={ enableTimeIncrement } isLoading={ isLoading }/>
</Flex>
......
......@@ -14,6 +14,7 @@ import { WEI } from 'lib/consts';
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
import GasUsedToTargetRatio from 'ui/shared/GasUsedToTargetRatio';
import LinkInternal from 'ui/shared/LinkInternal';
import TextSeparator from 'ui/shared/TextSeparator';
......@@ -45,17 +46,15 @@ const BlocksTableItem = ({ data, isLoading, enableTimeIncrement }: Props) => {
<Td fontSize="sm">
<Flex columnGap={ 2 } alignItems="center" mb={ 2 }>
<Tooltip isDisabled={ data.type !== 'reorg' } label="Chain reorganizations">
<Skeleton isLoaded={ !isLoading } display="inline-block">
<LinkInternal
<BlockEntity
isLoading={ isLoading }
number={ data.height }
hash={ data.type === 'reorg' ? data.hash : undefined }
noIcon
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
href={ route({
pathname: '/block/[height_or_hash]',
query: { height_or_hash: data.type === 'reorg' ? String(data.hash) : String(data.height) },
}) }
>
{ data.height }
</LinkInternal>
</Skeleton>
/>
</Tooltip>
</Flex>
<BlockTimestamp ts={ data.timestamp } isEnabled={ enableTimeIncrement } isLoading={ isLoading }/>
......
......@@ -10,12 +10,11 @@ import React from 'react';
import type { Block } from 'types/api/block';
import config from 'configs/app';
import blockIcon from 'icons/block.svg';
import getBlockTotalReward from 'lib/block/getBlockTotalReward';
import getNetworkValidatorTitle from 'lib/networks/getNetworkValidatorTitle';
import BlockTimestamp from 'ui/blocks/BlockTimestamp';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import BlockEntity from 'ui/shared/entities/block/BlockEntity';
type Props = {
block: Block;
......@@ -41,17 +40,14 @@ const LatestBlocksItem = ({ block, h, isLoading }: Props) => {
w="100%"
>
<Flex alignItems="center" overflow="hidden" w="100%" mb={ 3 }>
<Icon as={ blockIcon } boxSize="30px" color="link" isLoading={ isLoading } borderRadius="base"/>
<AddressLink
<BlockEntity
isLoading={ isLoading }
type="block"
hash={ String(block.height) }
blockHeight={ String(block.height) }
number={ block.height }
tailLength={ 2 }
fontSize="xl"
fontWeight="500"
ml={ 2 }
lineHeight={ 7 }
fontWeight={ 500 }
mr="auto"
tailLength={ 2 }
/>
<BlockTimestamp
ts={ block.timestamp }
......
......@@ -8,17 +8,12 @@ import React from 'react';
import type { L2DepositsItem } from 'types/api/l2Deposits';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import useIsMobile from 'lib/hooks/useIsMobile';
import Icon from 'ui/shared/chakra/Icon';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
const feature = config.features.rollup;
......@@ -36,51 +31,31 @@ const LatestTxsItem = ({ item, isLoading }: Props) => {
}
const l1BlockLink = (
<LinkExternal
href={ feature.L1BaseUrl +
route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l1_block_number.toString() } })
}
fontWeight={ 700 }
display="inline-flex"
mr={ 2 }
<BlockEntityL1
number={ item.l1_block_number }
isLoading={ isLoading }
>
<Icon as={ blockIcon } boxSize="30px" isLoading={ isLoading } borderRadius="base"/>
<Skeleton isLoaded={ !isLoading } ml={ 1 }>{ item.l1_block_number }</Skeleton>
</LinkExternal>
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 700 }
/>
);
const l1TxLink = (
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
maxW="100%"
display="inline-flex"
alignItems="center"
overflow="hidden"
<TxEntityL1
isLoading={ isLoading }
my="3px"
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
hash={ item.l1_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
);
const l2TxLink = (
<LinkInternal
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
display="flex"
alignItems="center"
overflow="hidden"
w="100%"
<TxEntity
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l2_tx_hash }/>
</Skeleton>
</LinkInternal>
hash={ item.l2_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
);
const content = (() => {
......
......@@ -12,13 +12,13 @@ import type { Transaction } from 'types/api/transaction';
import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import transactionIcon from 'icons/transactions.svg';
import getValueWithUnit from 'lib/getValueWithUnit';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
import TxType from 'ui/txs/TxType';
......@@ -54,24 +54,20 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
mt={ 2 }
alignItems="center"
>
<Icon
as={ transactionIcon }
boxSize="30px"
color="link"
display="inline"
<TxEntity
isLoading={ isLoading }
borderRadius="base"
/>
<Address overflow="hidden" w="calc(100% - 130px)" maxW="calc(100% - 130px)" ml={ 2 } mr={ 2 }>
<AddressLink
hash={ tx.hash }
type="transaction"
fontWeight="700"
isLoading={ isLoading }
/>
</Address>
{ tx.timestamp && (
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
<Skeleton
isLoaded={ !isLoading }
color="text_secondary"
fontWeight="400"
fontSize="sm"
flexShrink={ 0 }
ml={ 2 }
>
<span>{ timeAgo }</span>
</Skeleton>
) }
......
......@@ -11,13 +11,13 @@ import type { Transaction } from 'types/api/transaction';
import config from 'configs/app';
import rightArrowIcon from 'icons/arrows/east.svg';
import transactionIcon from 'icons/transactions.svg';
import getValueWithUnit from 'lib/getValueWithUnit';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxStatus from 'ui/shared/TxStatus';
import TxAdditionalInfo from 'ui/txs/TxAdditionalInfo';
import TxType from 'ui/txs/TxType';
......@@ -54,26 +54,14 @@ const LatestTxsItem = ({ tx, isLoading }: Props) => {
justifyContent="space-between"
mb={ 6 }
>
<Flex mr={ 3 }>
<Icon
as={ transactionIcon }
boxSize="30px"
mr={ 2 }
color="link"
<TxEntity
isLoading={ isLoading }
/>
<Address width="100%">
<AddressLink
hash={ tx.hash }
type="transaction"
fontWeight="700"
truncation="constant"
isLoading={ isLoading }
/>
</Address>
</Flex>
{ tx.timestamp && (
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm" ml={ 3 }>
<span>{ timeAgo }</span>
</Skeleton>
) }
......
......@@ -7,14 +7,13 @@ import type { L2DepositsItem } from 'types/api/l2Deposits';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import AddressIcon from 'ui/shared/address/AddressIcon';
import Icon from 'ui/shared/chakra/Icon';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
const feature = config.features.rollup;
......@@ -33,33 +32,23 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 block No</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l1_block_number.toString() } }) }
fontWeight={ 600 }
display="flex"
<BlockEntityL1
number={ item.l1_block_number }
isLoading={ isLoading }
>
<Icon as={ blockIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } ml={ 1 }>{ item.l1_block_number }</Skeleton>
</LinkExternal>
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkInternal
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
display="flex"
width="fit-content"
alignItems="center"
overflow="hidden"
w="100%"
<TxEntity
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l2_tx_hash }/>
</Skeleton>
</LinkInternal>
hash={ item.l2_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Age</ListItemMobileGrid.Label>
......@@ -69,18 +58,12 @@ const DepositsListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
maxW="100%"
display="flex"
overflow="hidden"
<TxEntityL1
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
hash={ item.l1_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn origin</ListItemMobileGrid.Label>
......
......@@ -7,14 +7,13 @@ import type { L2DepositsItem } from 'types/api/l2Deposits';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import blockIcon from 'icons/block.svg';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import AddressIcon from 'ui/shared/address/AddressIcon';
import Icon from 'ui/shared/chakra/Icon';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShorten from 'ui/shared/HashStringShorten';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
const feature = config.features.rollup;
......@@ -29,51 +28,35 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
return (
<Tr>
<Td verticalAlign="middle" fontWeight={ 600 }>
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l1_block_number.toString() } }) }
fontWeight={ 600 }
display="inline-flex"
<Td verticalAlign="middle">
<BlockEntityL1
number={ item.l1_block_number }
isLoading={ isLoading }
>
<Icon as={ blockIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } ml={ 1 }>
{ item.l1_block_number }
</Skeleton>
</LinkExternal>
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</Td>
<Td verticalAlign="middle">
<LinkInternal
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
display="flex"
width="fit-content"
alignItems="center"
overflow="hidden"
w="100%"
<TxEntity
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" ml={ 1 } overflow="hidden" whiteSpace="nowrap">
<HashStringShorten hash={ item.l2_tx_hash }/>
</Skeleton>
</LinkInternal>
hash={ item.l2_tx_hash }
fontSize="sm"
lineHeight={ 5 }
truncation="constant"
/>
</Td>
<Td verticalAlign="middle" pr={ 12 }>
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block"><span>{ timeAgo }</span></Skeleton>
</Td>
<Td verticalAlign="middle">
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
maxW="100%"
display="inline-flex"
overflow="hidden"
<TxEntityL1
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShorten hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
hash={ item.l1_tx_hash }
truncation="constant"
fontSize="sm"
lineHeight={ 5 }
/>
</Td>
<Td verticalAlign="middle">
<LinkExternal
......
......@@ -3,16 +3,12 @@ import React from 'react';
import type { L2OutputRootsItem } from 'types/api/l2OutputRoots';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
const feature = config.features.rollup;
......@@ -43,31 +39,23 @@ const OutputRootsListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block #</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value>
<LinkInternal
display="flex"
width="fit-content"
alignItems="center"
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
<BlockEntityL2
isLoading={ isLoading }
>
<Skeleton isLoaded={ !isLoading } display="inline-block">{ item.l2_block_number }</Skeleton>
</LinkInternal>
number={ item.l2_block_number }
fontSize="sm"
lineHeight={ 5 }
noIcon
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkExternal
maxW="100%"
display="flex"
overflow="hidden"
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
<TxEntityL1
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
hash={ item.l1_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>Output root</ListItemMobileGrid.Label>
......
......@@ -3,17 +3,12 @@ import React from 'react';
import type { L2OutputRootsItem } from 'types/api/l2OutputRoots';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import txIcon from 'icons/transactions.svg';
import txBatchIcon from 'icons/txBatch.svg';
import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
const feature = config.features.rollup;
......@@ -35,34 +30,21 @@ const OutputRootsTableItem = ({ item, isLoading }: Props) => {
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block"><span>{ timeAgo }</span></Skeleton>
</Td>
<Td verticalAlign="middle">
<LinkInternal
fontWeight={ 600 }
display="flex"
width="fit-content"
alignItems="center"
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
<BlockEntityL2
isLoading={ isLoading }
>
<Icon as={ txBatchIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } display="inline-block" ml={ 1 }>
{ item.l2_block_number }
</Skeleton>
</LinkInternal>
number={ item.l2_block_number }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</Td>
<Td verticalAlign="middle" pr={ 12 }>
<Flex>
<LinkExternal
maxW="100%"
display="inline-flex"
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
<TxEntityL1
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 } >
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
</Flex>
hash={ item.l1_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
</Td>
<Td verticalAlign="middle">
<Flex overflow="hidden" whiteSpace="nowrap" w="100%" alignItems="center">
......
......@@ -6,12 +6,10 @@ import type { L2TxnBatchesItem } from 'types/api/l2TxnBatches';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import txIcon from 'icons/transactions.svg';
import txBatchIcon from 'icons/txBatch.svg';
import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
......@@ -31,19 +29,13 @@ const TxnBatchesListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block #</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkInternal
fontWeight={ 600 }
display="flex"
width="fit-content"
alignItems="center"
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
<BlockEntityL2
isLoading={ isLoading }
>
<Icon as={ txBatchIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } ml={ 1 }>
{ item.l2_block_number }
</Skeleton>
</LinkInternal>
number={ item.l2_block_number }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 block txn count</ListItemMobileGrid.Label>
......@@ -60,34 +52,28 @@ const TxnBatchesListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>Epoch number</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value>
<LinkExternal
fontWeight={ 600 }
display="inline-flex"
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.epoch_number.toString() } }) }
<BlockEntityL1
isLoading={ isLoading }
>
<Skeleton isLoaded={ !isLoading }>
{ item.epoch_number }
</Skeleton>
</LinkExternal>
number={ item.epoch_number }
noIcon
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</ListItemMobileGrid.Value>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<VStack spacing={ 3 } w="100%" overflow="hidden" alignItems="flex-start">
{ item.l1_tx_hashes.map(hash => (
<LinkExternal
maxW="100%"
display="inline-flex"
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }
<TxEntityL1
key={ hash }
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ hash }/>
</Skeleton>
</LinkExternal>
hash={ hash }
fontSize="sm"
lineHeight={ 5 }
maxW="100%"
/>
)) }
</VStack>
</ListItemMobileGrid.Value>
......
......@@ -6,12 +6,10 @@ import type { L2TxnBatchesItem } from 'types/api/l2TxnBatches';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import txIcon from 'icons/transactions.svg';
import txBatchIcon from 'icons/txBatch.svg';
import dayjs from 'lib/date/dayjs';
import Icon from 'ui/shared/chakra/Icon';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import BlockEntityL1 from 'ui/shared/entities/block/BlockEntityL1';
import BlockEntityL2 from 'ui/shared/entities/block/BlockEntityL2';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import LinkInternal from 'ui/shared/LinkInternal';
const feature = config.features.rollup;
......@@ -28,19 +26,13 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
return (
<Tr>
<Td>
<LinkInternal
fontWeight={ 600 }
display="flex"
width="fit-content"
alignItems="center"
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.l2_block_number.toString() } }) }
<BlockEntityL2
isLoading={ isLoading }
>
<Icon as={ txBatchIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } ml={ 1 }>
{ item.l2_block_number }
</Skeleton>
</LinkInternal>
number={ item.l2_block_number }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</Td>
<Td>
<LinkInternal
......@@ -53,33 +45,27 @@ const TxnBatchesTableItem = ({ item, isLoading }: Props) => {
</LinkInternal>
</Td>
<Td>
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: item.epoch_number.toString() } }) }
fontWeight={ 600 }
display="inline-flex"
<BlockEntityL1
isLoading={ isLoading }
number={ item.epoch_number }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
py="2px"
>
<Skeleton isLoaded={ !isLoading } display="inline-block">
{ item.epoch_number }
</Skeleton>
</LinkExternal>
noIcon
/>
</Td>
<Td pr={ 12 }>
<VStack spacing={ 3 } alignItems="flex-start">
{ item.l1_tx_hashes.map(hash => (
<LinkExternal
maxW="100%"
display="inline-flex"
<TxEntityL1
key={ hash }
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ hash }/>
</Skeleton>
</LinkExternal>
hash={ hash }
fontSize="sm"
lineHeight={ 5 }
maxW="100%"
/>
)) }
</VStack>
</Td>
......
......@@ -3,18 +3,14 @@ import React from 'react';
import type { L2WithdrawalsItem } from 'types/api/l2Withdrawals';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
import ListItemMobileGrid from 'ui/shared/ListItemMobile/ListItemMobileGrid';
const feature = config.features.rollup;
......@@ -53,19 +49,12 @@ const WithdrawalsListItem = ({ item, isLoading }: Props) => {
<ListItemMobileGrid.Label isLoading={ isLoading }>L2 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkInternal
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
display="flex"
width="fit-content"
alignItems="center"
overflow="hidden"
w="100%"
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l2_tx_hash }/>
</Skeleton>
</LinkInternal>
<TxEntity
isLoading={ isLoading }
hash={ item.l2_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
</ListItemMobileGrid.Value>
{ timeAgo && (
......@@ -90,18 +79,12 @@ const WithdrawalsListItem = ({ item, isLoading }: Props) => {
<>
<ListItemMobileGrid.Label isLoading={ isLoading }>L1 txn hash</ListItemMobileGrid.Label>
<ListItemMobileGrid.Value py="3px">
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
maxW="100%"
display="inline-flex"
overflow="hidden"
<TxEntityL1
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 44px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShortenDynamic hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
hash={ item.l1_tx_hash }
fontSize="sm"
lineHeight={ 5 }
/>
</ListItemMobileGrid.Value>
</>
) }
......
......@@ -3,18 +3,14 @@ import React from 'react';
import type { L2WithdrawalsItem } from 'types/api/l2Withdrawals';
import { route } from 'nextjs-routes';
import config from 'configs/app';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import HashStringShorten from 'ui/shared/HashStringShorten';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TxEntityL1 from 'ui/shared/entities/tx/TxEntityL1';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
const feature = config.features.rollup;
......@@ -42,18 +38,13 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
) : 'N/A' }
</Td>
<Td verticalAlign="middle">
<LinkInternal
href={ route({ pathname: '/tx/[hash]', query: { hash: item.l2_tx_hash } }) }
display="flex"
width="fit-content"
alignItems="center"
<TxEntity
isLoading={ isLoading }
>
<Icon as={ txIcon } boxSize={ 6 } isLoading={ isLoading }/>
<Skeleton isLoaded={ !isLoading } w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap" ml={ 1 }>
<HashStringShorten hash={ item.l2_tx_hash }/>
</Skeleton>
</LinkInternal>
hash={ item.l2_tx_hash }
truncation="constant"
fontSize="sm"
lineHeight={ 5 }
/>
</Td>
<Td verticalAlign="middle" pr={ 12 }>
<Skeleton isLoaded={ !isLoading } color="text_secondary" display="inline-block">
......@@ -68,15 +59,13 @@ const WithdrawalsTableItem = ({ item, isLoading }: Props) => {
</Td>
<Td verticalAlign="middle">
{ item.l1_tx_hash ? (
<LinkExternal
href={ feature.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
<TxEntityL1
isLoading={ isLoading }
display="inline-flex"
>
<Skeleton isLoaded={ !isLoading }>
<HashStringShorten hash={ item.l1_tx_hash }/>
</Skeleton>
</LinkExternal>
hash={ item.l1_tx_hash }
truncation="constant"
fontSize="sm"
lineHeight={ 5 }
/>
) :
'N/A'
}
......
......@@ -29,7 +29,7 @@ export default function useMarketplaceApps(filter: string, selectedCategoryId: s
async() => apiFetch(configUrl),
{
select: (data) => (data as Array<MarketplaceAppOverview>).sort((a, b) => a.title.localeCompare(b.title)),
placeholderData: Array(9).fill(MARKETPLACE_APP),
placeholderData: feature.isEnabled ? Array(9).fill(MARKETPLACE_APP) : undefined,
staleTime: Infinity,
enabled: feature.isEnabled,
});
......
......@@ -4,9 +4,9 @@ import React, { useCallback } from 'react';
import type { TransactionTag } from 'types/api/account';
import Tag from 'ui/shared/chakra/Tag';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import TransactionSnippet from 'ui/shared/TransactionSnippet';
interface Props {
item: TransactionTag;
......@@ -27,7 +27,13 @@ const TransactionTagListItem = ({ item, isLoading, onEditClick, onDeleteClick }:
return (
<ListItemMobile>
<Flex alignItems="flex-start" flexDirection="column" maxW="100%">
<TransactionSnippet hash={ item.transaction_hash } isLoading={ isLoading }/>
<TxEntity
hash={ item.transaction_hash }
isLoading={ isLoading }
withCopy
fontWeight={ 600 }
maxW="100%"
/>
<HStack spacing={ 3 } mt={ 4 }>
<Text fontSize="sm" fontWeight={ 500 }>Private tag</Text>
<Tag isLoading={ isLoading } isTruncated>{ item.name }</Tag>
......
......@@ -7,8 +7,8 @@ import React, { useCallback } from 'react';
import type { TransactionTag } from 'types/api/account';
import Tag from 'ui/shared/chakra/Tag';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import TableItemActionButtons from 'ui/shared/TableItemActionButtons';
import TransactionSnippet from 'ui/shared/TransactionSnippet';
interface Props {
item: TransactionTag;
......@@ -29,7 +29,12 @@ const TransactionTagTableItem = ({ item, isLoading, onEditClick, onDeleteClick }
return (
<Tr alignItems="top" key={ item.id }>
<Td>
<TransactionSnippet hash={ item.transaction_hash } isLoading={ isLoading }/>
<TxEntity
hash={ item.transaction_hash }
isLoading={ isLoading }
fontWeight={ 600 }
withCopy
/>
</Td>
<Td>
<Tag isLoading={ isLoading } isTruncated>{ item.name }</Tag>
......
import { Flex, Grid, Icon, Image, Box, Text, chakra, Skeleton, useColorMode } from '@chakra-ui/react';
import { Flex, Grid, Icon, Image, Box, Text, Skeleton, useColorMode } from '@chakra-ui/react';
import React from 'react';
import type { SearchResultItem } from 'types/api/search';
import { route } from 'nextjs-routes';
import blockIcon from 'icons/block.svg';
import labelIcon from 'icons/publictags.svg';
import iconSuccess from 'icons/status/success.svg';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index';
......@@ -16,6 +14,8 @@ import { saveToRecentKeywords } from 'lib/recentSearchKeywords';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -143,28 +143,42 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
case 'block': {
const shouldHighlightHash = data.block_hash.toLowerCase() === searchTerm.toLowerCase();
return (
<Flex alignItems="center">
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<LinkInternal
fontWeight={ 700 }
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block_hash) } }) }
<BlockEntity.Container>
<BlockEntity.Icon/>
<BlockEntity.Link
hash={ data.block_hash }
number={ Number(data.block_number) }
onClick={ handleLinkClick }
mr={ 4 }
>
<Box as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
</LinkInternal>
</Flex>
<BlockEntity.Content
asProp={ shouldHighlightHash ? 'span' : 'mark' }
number={ Number(data.block_number) }
fontSize="sm"
fontWeight={ 700 }
/>
</BlockEntity.Link>
</BlockEntity.Container>
);
}
case 'transaction': {
return (
<Flex alignItems="center" overflow="hidden">
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<chakra.mark display="block" overflow="hidden">
<AddressLink hash={ data.tx_hash } type="transaction" fontWeight={ 700 } display="block" onClick={ handleLinkClick }/>
</chakra.mark>
</Flex>
<TxEntity.Container>
<TxEntity.Icon/>
<TxEntity.Link
isLoading={ isLoading }
hash={ data.tx_hash }
onClick={ handleLinkClick }
>
<TxEntity.Content
asProp="mark"
hash={ data.tx_hash }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 700 }
/>
</TxEntity.Link>
</TxEntity.Container>
);
}
}
......
import { chakra, Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode } from '@chakra-ui/react';
import { Tr, Td, Text, Flex, Icon, Image, Box, Skeleton, useColorMode } from '@chakra-ui/react';
import React from 'react';
import type { SearchResultItem } from 'types/api/search';
import { route } from 'nextjs-routes';
import blockIcon from 'icons/block.svg';
import labelIcon from 'icons/publictags.svg';
import iconSuccess from 'icons/status/success.svg';
import txIcon from 'icons/transactions.svg';
import dayjs from 'lib/date/dayjs';
import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index';
......@@ -16,6 +14,8 @@ import { saveToRecentKeywords } from 'lib/recentSearchKeywords';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import * as BlockEntity from 'ui/shared/entities/block/BlockEntity';
import * as TxEntity from 'ui/shared/entities/tx/TxEntity';
import HashStringShortenDynamic from 'ui/shared/HashStringShortenDynamic';
import LinkExternal from 'ui/shared/LinkExternal';
import LinkInternal from 'ui/shared/LinkInternal';
......@@ -220,16 +220,22 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
return (
<>
<Td fontSize="sm">
<Flex alignItems="center">
<Icon as={ blockIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<LinkInternal
fontWeight={ 700 }
href={ route({ pathname: '/block/[height_or_hash]', query: { height_or_hash: String(data.block_hash) } }) }
<BlockEntity.Container>
<BlockEntity.Icon/>
<BlockEntity.Link
hash={ data.block_hash }
number={ Number(data.block_number) }
onClick={ handleLinkClick }
>
<Box as={ shouldHighlightHash ? 'span' : 'mark' }>{ data.block_number }</Box>
</LinkInternal>
</Flex>
<BlockEntity.Content
asProp={ shouldHighlightHash ? 'span' : 'mark' }
number={ Number(data.block_number) }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 700 }
/>
</BlockEntity.Link>
</BlockEntity.Container>
</Td>
<Td fontSize="sm" verticalAlign="middle">
<Box overflow="hidden" whiteSpace="nowrap" as={ shouldHighlightHash ? 'mark' : 'span' } display="block">
......@@ -247,12 +253,22 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
return (
<>
<Td colSpan={ 2 } fontSize="sm">
<Flex alignItems="center">
<Icon as={ txIcon } boxSize={ 6 } mr={ 2 } color="gray.500"/>
<chakra.mark overflow="hidden">
<AddressLink display="block" hash={ data.tx_hash } type="transaction" fontWeight={ 700 } onClick={ handleLinkClick } truncation="dynamic"/>
</chakra.mark>
</Flex>
<TxEntity.Container>
<TxEntity.Icon/>
<TxEntity.Link
isLoading={ isLoading }
hash={ data.tx_hash }
onClick={ handleLinkClick }
>
<TxEntity.Content
asProp="mark"
hash={ data.tx_hash }
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 700 }
/>
</TxEntity.Link>
</TxEntity.Container>
</Td>
<Td fontSize="sm" verticalAlign="middle" isNumeric>
<Text variant="secondary">{ dayjs(data.timestamp).format('llll') }</Text>
......
......@@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
import CopyIcon from 'icons/copy.svg';
interface Props {
export interface Props {
text: string;
className?: string;
isLoading?: boolean;
......
import { Tooltip } from '@chakra-ui/react';
import { Tooltip, chakra } from '@chakra-ui/react';
import type { As } from '@chakra-ui/react';
import React from 'react';
import shortenString from 'lib/shortenString';
......@@ -6,16 +7,17 @@ import shortenString from 'lib/shortenString';
interface Props {
hash: string;
isTooltipDisabled?: boolean;
as?: As;
}
const HashStringShorten = ({ hash, isTooltipDisabled }: Props) => {
const HashStringShorten = ({ hash, isTooltipDisabled, as = 'span' }: Props) => {
if (hash.length <= 8) {
return <span>{ hash }</span>;
return <chakra.span as={ as }>{ hash }</chakra.span>;
}
return (
<Tooltip label={ hash } isDisabled={ isTooltipDisabled }>
{ shortenString(hash) }
<chakra.span as={ as }>{ shortenString(hash) }</chakra.span>
</Tooltip>
);
};
......
......@@ -8,7 +8,8 @@
// so i did it with js
import { Tooltip } from '@chakra-ui/react';
import type { As } from '@chakra-ui/react';
import { Tooltip, chakra } from '@chakra-ui/react';
import _debounce from 'lodash/debounce';
import React, { useCallback, useEffect, useRef } from 'react';
import type { FontFace } from 'use-font-face-observer';
......@@ -24,9 +25,10 @@ interface Props {
fontWeight?: string | number;
isTooltipDisabled?: boolean;
tailLength?: number;
as?: As;
}
const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled, tailLength = TAIL_LENGTH }: Props) => {
const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled, tailLength = TAIL_LENGTH, as = 'span' }: Props) => {
const elementRef = useRef<HTMLSpanElement>(null);
const [ displayedString, setDisplayedString ] = React.useState(hash);
......@@ -88,7 +90,7 @@ const HashStringShortenDynamic = ({ hash, fontWeight = '400', isTooltipDisabled,
};
}, [ calculateString ]);
const content = <span ref={ elementRef }>{ displayedString }</span>;
const content = <chakra.span ref={ elementRef } as={ as }>{ displayedString }</chakra.span>;
const isTruncated = hash.length !== displayedString.length;
if (isTruncated) {
......
......@@ -5,7 +5,6 @@ import React from 'react';
import type { TokenTransfer } from 'types/api/tokenTransfer';
import eastArrowIcon from 'icons/arrows/east.svg';
import transactionIcon from 'icons/transactions.svg';
import useTimeAgoIncrement from 'lib/hooks/useTimeAgoIncrement';
import Address from 'ui/shared/address/Address';
import AddressIcon from 'ui/shared/address/AddressIcon';
......@@ -13,6 +12,7 @@ import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag';
import ListItemMobile from 'ui/shared/ListItemMobile/ListItemMobile';
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
......@@ -66,23 +66,12 @@ const TokenTransferListItem = ({
{ 'token_id' in total && <TokenTransferNft hash={ token.address } id={ total.token_id } isLoading={ isLoading }/> }
{ showTxInfo && txHash && (
<Flex justifyContent="space-between" alignItems="center" lineHeight="24px" width="100%">
<Flex>
<Icon
as={ transactionIcon }
boxSize="30px"
color="link"
<TxEntity
isLoading={ isLoading }
/>
<Address width="100%" ml={ 2 }>
<AddressLink
hash={ txHash }
type="transaction"
fontWeight="700"
truncation="constant"
isLoading={ isLoading }
fontWeight="700"
/>
</Address>
</Flex>
{ timestamp && (
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" fontSize="sm">
<span>{ timeAgo }</span>
......
......@@ -10,6 +10,7 @@ import AddressIcon from 'ui/shared/address/AddressIcon';
import AddressLink from 'ui/shared/address/AddressLink';
import Tag from 'ui/shared/chakra/Tag';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
import TxEntity from 'ui/shared/entities/tx/TxEntity';
import InOutTag from 'ui/shared/InOutTag';
import TokenSnippet from 'ui/shared/TokenSnippet/TokenSnippet';
import { getTokenTransferTypeText } from 'ui/shared/TokenTransfer/helpers';
......@@ -59,9 +60,13 @@ const TokenTransferTableItem = ({
</Td>
{ showTxInfo && txHash && (
<Td>
<Address display="inline-flex" maxW="100%" fontWeight={ 600 } mt="7px">
<AddressLink type="transaction" hash={ txHash } isLoading={ isLoading }/>
</Address>
<TxEntity
hash={ txHash }
isLoading={ isLoading }
fontWeight={ 600 }
noIcon
mt="7px"
/>
{ timestamp && (
<Skeleton isLoaded={ !isLoading } color="text_secondary" fontWeight="400" mt="10px" display="inline-block">
<span>{ timeAgo }</span>
......
import { useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import transactionIcon from 'icons/transactions.svg';
import Address from 'ui/shared/address/Address';
import AddressLink from 'ui/shared/address/AddressLink';
import Icon from 'ui/shared/chakra/Icon';
import CopyToClipboard from 'ui/shared/CopyToClipboard';
interface Props {
hash: string;
isLoading?: boolean;
}
const TransactionSnippet = ({ hash, isLoading }: Props) => {
return (
<Address maxW="100%">
<Icon as={ transactionIcon } boxSize={ 6 } color={ useColorModeValue('gray.500', 'gray.400') } isLoading={ isLoading }/>
<AddressLink hash={ hash } fontWeight="600" type="transaction" ml={ 2 } isLoading={ isLoading }/>
<CopyToClipboard text={ hash } isLoading={ isLoading }/>
</Address>
);
};
export default React.memo(TransactionSnippet);
......@@ -6,6 +6,9 @@ interface Props {
children: React.ReactNode;
}
/**
* @deprecated use `ui/shared/entities/address` instead
*/
const Address = ({ children, className }: Props) => {
return <Flex alignItems="center" overflow="hidden" className={ className }>{ children }</Flex>;
};
......
......@@ -24,35 +24,25 @@ type CommonProps = {
}
type AddressTokenTxProps = {
type: 'address' | 'token' | 'transaction';
type: 'address' | 'token';
hash: 'hash';
}
type BlockProps = {
type: 'block';
hash: string;
blockHeight: string;
}
type AddressTokenProps = {
type: 'address_token';
hash: string;
tokenHash: string;
}
type Props = CommonProps & (AddressTokenTxProps | BlockProps | AddressTokenProps);
type Props = CommonProps & (AddressTokenTxProps | AddressTokenProps);
const AddressLink = (props: Props) => {
const { alias, type, className, truncation = 'dynamic', hash, fontWeight, target = '_self', isDisabled, isLoading } = props;
const isMobile = useIsMobile();
let url;
if (type === 'transaction') {
url = route({ pathname: '/tx/[hash]', query: { ...props.query, hash } });
} else if (type === 'token') {
if (type === 'token') {
url = route({ pathname: '/token/[hash]', query: { ...props.query, hash } });
} else if (type === 'block') {
url = route({ pathname: '/block/[height_or_hash]', query: { ...props.query, height_or_hash: props.blockHeight } });
} else if (type === 'address_token') {
url = route({ pathname: '/address/[hash]', query: { ...props.query, hash, tab: 'token_transfers', token: props.tokenHash, scroll_to_tabs: 'true' } });
} else {
......
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import * as addressMock from 'mocks/address/address';
import TestApp from 'playwright/TestApp';
import AddressEntity from './AddressEntity';
const iconSizes = [ 'md', 'lg' ];
test.use({ viewport: { width: 180, height: 100 } });
test.describe('icon size', () => {
iconSizes.forEach((size) => {
test(size, async({ mount }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={ addressMock.withoutName }
iconSize={ size }
/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
});
});
test.describe('contract', () => {
test('unverified', async({ mount, page }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={{ ...addressMock.contract, is_verified: false }}
/>
</TestApp>,
);
await component.getByText(/eternal/i).hover();
await expect(page).toHaveScreenshot();
});
test('verified', async({ mount }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={{ ...addressMock.contract, is_verified: true }}
/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
});
test.describe('loading', () => {
test('without alias', async({ mount }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={ addressMock.withoutName }
isLoading
/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
test('with alias', async({ mount }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={ addressMock.withName }
isLoading
/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
});
test('external link', async({ mount }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={ addressMock.withoutName }
isExternal
/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
test('customization', async({ mount }) => {
const component = await mount(
<TestApp>
<AddressEntity
address={ addressMock.withoutName }
truncation="constant"
p={ 3 }
borderWidth="1px"
borderColor="blue.700"
/>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
import type { As } from '@chakra-ui/react';
import { Flex, Skeleton, Tooltip, chakra } from '@chakra-ui/react';
import _omit from 'lodash/omit';
import React from 'react';
import Jazzicon, { jsNumberForAddress } from 'react-jazzicon';
import type { AddressParam } from 'types/api/addressParams';
import { route } from 'nextjs-routes';
import iconContractVerified from 'icons/contract_verified.svg';
import iconContract from 'icons/contract.svg';
import * as EntityBase from 'ui/shared/entities/base/components';
import { getIconProps } from '../base/utils';
interface LinkProps extends Pick<EntityProps, 'className' | 'address' | 'onClick' | 'isLoading' | 'isExternal' | 'href' | 'query'> {
children: React.ReactNode;
}
const Link = chakra((props: LinkProps) => {
const defaultHref = route({ pathname: '/address/[hash]', query: { ...props.query, hash: props.address.hash } });
return (
<EntityBase.Link
{ ...props }
href={ props.href ?? defaultHref }
>
{ props.children }
</EntityBase.Link>
);
});
type IconProps = Pick<EntityProps, 'address' | 'isLoading' | 'iconSize'> & {
asProp?: As;
};
const Icon = (props: IconProps) => {
const styles = {
...getIconProps(props.iconSize),
marginRight: 2,
};
if (props.isLoading) {
return <Skeleton { ...styles } borderRadius="full" flexShrink={ 0 }/>;
}
if (props.address.is_contract) {
if (props.address.is_verified) {
return (
<EntityBase.Icon
{ ...props }
asProp={ iconContractVerified }
color="green.500"
/>
);
}
return (
<EntityBase.Icon
{ ...props }
asProp={ iconContract }
/>
);
}
return (
<Tooltip label={ props.address.implementation_name }>
<Flex { ...styles }>
<Jazzicon diameter={ props.iconSize === 'lg' ? 30 : 20 } seed={ jsNumberForAddress(props.address.hash) }/>
</Flex>
</Tooltip>
);
};
type ContentProps = Omit<EntityBase.ContentBaseProps, 'text'> & Pick<EntityProps, 'address'>;
const Content = chakra((props: ContentProps) => {
if (props.address.name) {
return (
<Tooltip label={ props.address.hash } maxW="100vw">
<Skeleton isLoaded={ !props.isLoading } overflow="hidden" textOverflow="ellipsis" whiteSpace="nowrap" as="span">
{ props.address.name }
</Skeleton>
</Tooltip>
);
}
return (
<EntityBase.Content
{ ...props }
text={ props.address.hash }
/>
);
});
type CopyProps = Omit<EntityBase.CopyBaseProps, 'text'> & Pick<EntityProps, 'address'>;
const Copy = (props: CopyProps) => {
return (
<EntityBase.Copy
{ ...props }
text={ props.address.hash }
withCopy={ props.withCopy ?? true }
/>
);
};
const Container = EntityBase.Container;
export interface EntityProps extends EntityBase.EntityBaseProps {
address: Pick<AddressParam, 'hash' | 'name' | 'is_contract' | 'is_verified' | 'implementation_name'>;
}
const AddressEntry = (props: EntityProps) => {
const linkProps = _omit(props, [ 'className' ]);
const partsProps = _omit(props, [ 'className', 'onClick' ]);
return (
<Container className={ props.className }>
<Icon { ...partsProps }/>
<Link { ...linkProps }>
<Content { ...partsProps }/>
</Link>
<Copy { ...partsProps }/>
</Container>
);
};
export default React.memo(chakra(AddressEntry));
export {
Container,
Link,
Icon,
Content,
Copy,
};
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment