Commit c38b7651 authored by tom's avatar tom

Merge branch 'main' of github.com:blockscout/frontend into hide-zero-nonce

parents c78aa89a d7b7b83b
......@@ -18,6 +18,8 @@ docker run -p 3000:3000 --env-file <path-to-your-env-file> ghcr.io/blockscout/fr
Alternatively, you can build your own docker image and run your app from that. Please follow this [guide](./docs/CUSTOM_BUILD.md).
For more information on migrating from the previous frontend, please see the [frontend migration docs](https://docs.blockscout.com/for-developers/frontend-migration).
## Contributing
See our [Contribution guide](./docs/CONTRIBUTING.md) for pull request protocol. We expect contributors to follow our [code of conduct](./CODE_OF_CONDUCT.md) when submitting code or comments.
......@@ -25,7 +27,8 @@ See our [Contribution guide](./docs/CONTRIBUTING.md) for pull request protocol.
## Resources
- [App ENVs list](./docs/ENVS.md)
- [Contribution guide](./docs/CONTRIBUTING.md)
- [Making custom build](./docs/CUSTOM_BUILD.md)
- [Making a custom build](./docs/CUSTOM_BUILD.md)
- [Frontend migration guide](https://docs.blockscout.com/for-developers/frontend-migration)
## License
......
<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.6l.713.4.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.399a1.511 1.511 0 0 0-.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-.173H4.34Zm7.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.297a1.031 1.031 0 0 1 0 1.435.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.089a.852.852 0 0 0 .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>
......@@ -40,7 +40,7 @@ import type { L2TxnBatchesResponse } from 'types/api/l2TxnBatches';
import type { L2WithdrawalsResponse } from 'types/api/l2Withdrawals';
import type { LogsResponseTx, LogsResponseAddress } from 'types/api/log';
import type { RawTracesResponse } from 'types/api/rawTrace';
import type { SearchRedirectResult, SearchResult, SearchResultFilters } from 'types/api/search';
import type { SearchRedirectResult, SearchResult, SearchResultFilters, SearchResultItem } from 'types/api/search';
import type { Counters, StatsCharts, StatsChart, HomeStats } from 'types/api/stats';
import type {
TokenCounters,
......@@ -420,6 +420,10 @@ export const RESOURCES = {
},
// SEARCH
quick_search: {
path: '/api/v2/search/quick',
filterFields: [ 'q' ],
},
search: {
path: '/api/v2/search',
filterFields: [ 'q' ],
......@@ -597,6 +601,7 @@ Q extends 'token_instance_transfers' ? TokenInstanceTransferResponse :
Q extends 'token_instance_holders' ? TokenHolders :
Q extends 'token_inventory' ? TokenInventoryResponse :
Q extends 'tokens' ? TokensResponse :
Q extends 'quick_search' ? Array<SearchResultItem> :
Q extends 'search' ? SearchResult :
Q extends 'search_check_redirect' ? SearchRedirectResult :
Q extends 'contract' ? SmartContract :
......
......@@ -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: [],
......
......@@ -11,6 +11,7 @@ export const token1: SearchResultToken = {
token_type: 'ERC-721',
total_supply: '10000001',
exchange_rate: null,
is_verified_via_admin_panel: true,
is_smart_contract_verified: true,
};
......@@ -25,6 +26,7 @@ export const token2: SearchResultToken = {
token_type: 'ERC-20',
total_supply: '10000001',
exchange_rate: '1.11',
is_verified_via_admin_panel: false,
is_smart_contract_verified: false,
};
......
......@@ -10,6 +10,7 @@ export const SEARCH_RESULT_ITEM: SearchResultItem = {
token_url: '/token/0x3714A8C7824B22271550894f7555f0a672f97809',
type: 'token',
icon_url: null,
is_verified_via_admin_panel: false,
is_smart_contract_verified: false,
exchange_rate: '1.11',
total_supply: null,
......
......@@ -13,6 +13,7 @@ export interface SearchResultToken {
token_type: TokenType;
exchange_rate: string | null;
total_supply: string | null;
is_verified_via_admin_panel: boolean;
is_smart_contract_verified: boolean;
}
......
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,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 Utilization from 'ui/shared/Utilization/Utilization';
type Props = Block & {
......@@ -18,16 +16,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
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>
<BlockEntity
isLoading={ isLoading }
number={ data.height }
hash={ data.type === 'reorg' ? data.hash : undefined }
noIcon
fontWeight={ 600 }
/>
</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
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>
<BlockEntity
isLoading={ isLoading }
number={ data.height }
hash={ data.type === 'reorg' ? data.hash : undefined }
noIcon
fontSize="sm"
lineHeight={ 5 }
fontWeight={ 600 }
/>
</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"
hash={ tx.hash }
fontWeight="700"
/>
<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"
isLoading={ isLoading }
/>
<Address width="100%">
<AddressLink
hash={ tx.hash }
type="transaction"
fontWeight="700"
truncation="constant"
isLoading={ isLoading }
/>
</Address>
</Flex>
<TxEntity
isLoading={ isLoading }
hash={ tx.hash }
fontWeight="700"
truncation="constant"
/>
{ 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 } }) }
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>
<TxEntityL1
isLoading={ isLoading }
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'
}
......
......@@ -21,7 +21,7 @@ import useSearchQuery from 'ui/snippets/searchBar/useSearchQuery';
const SearchResultsPageContent = () => {
const router = useRouter();
const { query, redirectCheckQuery, searchTerm, debouncedSearchTerm, handleSearchTermChange } = useSearchQuery(true);
const { query, redirectCheckQuery, searchTerm, debouncedSearchTerm, handleSearchTermChange } = useSearchQuery();
const { data, isError, isPlaceholderData, pagination } = query;
const [ showContent, setShowContent ] = React.useState(false);
......
......@@ -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 }
noCopy={ false }
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 }
noCopy={ false }
fontWeight={ 600 }
/>
</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 verifiedToken from 'icons/verified_token.svg';
import dayjs from 'lib/date/dayjs';
import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index';
......@@ -16,6 +15,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';
......@@ -49,7 +50,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
const name = data.name + (data.symbol ? ` (${ data.symbol })` : '');
return (
<Flex alignItems="flex-start" flexGrow={ 1 } overflow="hidden">
<Flex alignItems="center" overflow="hidden">
<TokenLogo boxSize={ 6 } data={ data } flexShrink={ 0 } isLoading={ isLoading }/>
<LinkInternal
ml={ 2 }
......@@ -69,6 +70,7 @@ const SearchResultListItem = ({ data, searchTerm, isLoading }: Props) => {
textOverflow="ellipsis"
/>
</LinkInternal>
{ data.is_verified_via_admin_panel && <Icon as={ verifiedToken } boxSize={ 4 } ml={ 1 } color="green.500"/> }
</Flex>
);
}
......@@ -143,28 +145,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 verifiedToken from 'icons/verified_token.svg';
import dayjs from 'lib/date/dayjs';
import highlightText from 'lib/highlightText';
import * as mixpanel from 'lib/mixpanel/index';
......@@ -16,6 +15,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';
......@@ -69,6 +70,7 @@ const SearchResultTableItem = ({ data, searchTerm, isLoading }: Props) => {
dangerouslySetInnerHTML={{ __html: highlightText(name, searchTerm) }}
/>
</LinkInternal>
{ data.is_verified_via_admin_panel && <Icon as={ verifiedToken } boxSize={ 4 } ml={ 1 } color="green.500"/> }
</Flex>
</Td>
<Td fontSize="sm" verticalAlign="middle">
......@@ -220,16 +222,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 +255,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) {
......
......@@ -19,6 +19,9 @@ interface Props {
maxW: StyleProps['maxW'];
}
/**
* @deprecated use `ui/shared/entities/token/**` instead
*/
const TokenSnippet = ({ data, className, logoSize = 6, isDisabled, hideSymbol, hideIcon, isLoading, maxW }: Props) => {
const withSymbol = data && data.symbol && !hideSymbol;
......
......@@ -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"
isLoading={ isLoading }
/>
<Address width="100%" ml={ 2 }>
<AddressLink
hash={ txHash }
type="transaction"
fontWeight="700"
truncation="constant"
isLoading={ isLoading }
/>
</Address>
</Flex>
<TxEntity
isLoading={ isLoading }
hash={ txHash }
truncation="constant"
fontWeight="700"
/>
{ 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);
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.
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