diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6791e814b7..b26ab858ad 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,9 @@
## Current
### Features
+- [#2733](https://github.com/poanetwork/blockscout/pull/2733) - Add cache for first page of uncles
+- [#2735](https://github.com/poanetwork/blockscout/pull/2735) - Add pending transactions cache
+- [#2726](https://github.com/poanetwork/blockscout/pull/2726) - Remove internal_transaction block_number setting from blocks runner
- [#2717](https://github.com/poanetwork/blockscout/pull/2717) - Improve speed of nonconsensus data removal
- [#2679](https://github.com/poanetwork/blockscout/pull/2679) - added fixed height for card chain blocks and card chain transactions
- [#2678](https://github.com/poanetwork/blockscout/pull/2678) - fixed dashboard banner height bug
@@ -9,8 +12,18 @@
- [#2666](https://github.com/poanetwork/blockscout/pull/2666) - fetch token counters in parallel
- [#2665](https://github.com/poanetwork/blockscout/pull/2665) - new menu layout for mobile devices
- [#2663](https://github.com/poanetwork/blockscout/pull/2663) - Fetch address counters in parallel
+- [#2642](https://github.com/poanetwork/blockscout/pull/2642) - add ERC721 coin instance page
### Fixes
+- [#2753](https://github.com/poanetwork/blockscout/pull/2753) - fix nft token instance images
+- [#2750](https://github.com/poanetwork/blockscout/pull/2750) - fixed contract buttons color for NFT token instance on each theme
+- [#2746](https://github.com/poanetwork/blockscout/pull/2746) - fixed wrong alignment in logs decoded view
+- [#2745](https://github.com/poanetwork/blockscout/pull/2745) - optimize addresses page
+- [#2742](https://github.com/poanetwork/blockscout/pull/2742) -
+fixed menu hovers in dark mode desktop view
+- [#2737](https://github.com/poanetwork/blockscout/pull/2737) - switched hardcoded subnetwork value to elixir expression for mobile menu
+- [#2736](https://github.com/poanetwork/blockscout/pull/2736) - do not update cache if no blocks were inserted
+- [#2731](https://github.com/poanetwork/blockscout/pull/2731) - fix library verification
- [#2718](https://github.com/poanetwork/blockscout/pull/2718) - Include all addresses taking part in transactions in wallets' addresses counter
- [#2709](https://github.com/poanetwork/blockscout/pull/2709) - Fix stuck label and value for uncle block height
- [#2707](https://github.com/poanetwork/blockscout/pull/2707) - fix for dashboard banner chart legend items
@@ -26,11 +39,11 @@
- [#2671](https://github.com/poanetwork/blockscout/pull/2671) - fixed buttons color at smart contract section
- [#2660](https://github.com/poanetwork/blockscout/pull/2660) - set correct last value for coin balances chart data
- [#2619](https://github.com/poanetwork/blockscout/pull/2619) - Enforce DB transaction's order to prevent deadlocks
+- [#2738](https://github.com/poanetwork/blockscout/pull/2738) - do not fail block `internal_transactions_indexed_at` field update
### Chore
- [#2724](https://github.com/poanetwork/blockscout/pull/2724) - fix ci by commenting a line in hackney library
- [#2708](https://github.com/poanetwork/blockscout/pull/2708) - add log index to logs view
-
- [#2723](https://github.com/poanetwork/blockscout/pull/2723) - get rid of ex_json_schema warnings
diff --git a/README.md b/README.md
index 138ddf18d8..d8cb35d7a0 100644
--- a/README.md
+++ b/README.md
@@ -32,7 +32,7 @@ Currently available full-featured block explorers (Etherscan, Etherchain, Blockc
|--------------------------------------------------------|-------------------------------------------------------|------------------------------------------------------|----------------------------------------------------------------|
| [Callisto](https://blockscout.com/callisto/mainnet) | [Goerli Testnet](https://blockscout.com/eth/goerli) | [ARTIS](https://explorer.sigma1.artis.network) | [Celo Testnet](https://alfajores-blockscout.celo-testnet.org/) |
| [Ethereum Classic](https://blockscout.com/etc/mainnet) | [Kovan Testnet](https://blockscout.com/eth/kovan) | [Ether-1](https://blocks.ether1.wattpool.net/) | [Matic Testnet](https://explorer.testnet2.matic.network/) |
-| [Ethereum Mainnet](https://blockscout.com/eth/mainnet) | [LUKSO L14 Testnet](https://blockscout.com/lukso/l14) | [Kotti Testnet](https://kottiexplorer.ethernode.io/) | |
+| [Ethereum Mainnet](https://blockscout.com/eth/mainnet) | [LUKSO L14 Testnet](https://blockscout.com/lukso/l14) | [Kotti Testnet](https://kottiexplorer.ethernode.io/) | [Mordor Testnet](https://mordorexplorer.ethernode.io/) |
| [POA Core Network](https://blockscout.com/poa/core) | [POA Sokol Testnet](https://blockscout.com/poa/sokol) | [Fuse Network](https://explorer.fuse.io/) | |
| [RSK](https://blockscout.com/rsk/mainnet) | [Rinkeby Testnet](https://blockscout.com/eth/rinkeby) | [Oasis Labs](https://blockexplorer.oasiscloud.io/) | |
| [xDai Chain](https://blockscout.com/poa/dai) | [Ropsten Testnet](https://blockscout.com/eth/ropsten) | [Petrichor](https://explorer.petrachor.com/) | |
diff --git a/apps/block_scout_web/assets/css/_layout.scss b/apps/block_scout_web/assets/css/_layout.scss
index f1a4e92312..da36762bee 100644
--- a/apps/block_scout_web/assets/css/_layout.scss
+++ b/apps/block_scout_web/assets/css/_layout.scss
@@ -8,3 +8,7 @@
background-color: #fbfafc;
}
}
+
+.logs-hash {
+ line-height: 24px !important;
+}
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/app.scss b/apps/block_scout_web/assets/css/app.scss
index 4563ec33d5..a6c5e40c01 100644
--- a/apps/block_scout_web/assets/css/app.scss
+++ b/apps/block_scout_web/assets/css/app.scss
@@ -100,6 +100,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/form";
@import "components/btn_copy";
@import "components/btn_qr";
+@import "components/btn_contract";
@import "components/btn_address_card";
@import "components/btn_dropdown_line";
@import "components/transaction";
@@ -114,6 +115,7 @@ $fa-font-path: "~@fortawesome/fontawesome-free/webfonts";
@import "components/radio_big";
@import "components/btn_no_border";
@import "components/custom_tooltips_block_details";
+@import "components/_erc721_token_image_container";
@import "theme/dark-theme";
diff --git a/apps/block_scout_web/assets/css/components/_address-overview.scss b/apps/block_scout_web/assets/css/components/_address-overview.scss
index a936aec99f..f758e4affc 100644
--- a/apps/block_scout_web/assets/css/components/_address-overview.scss
+++ b/apps/block_scout_web/assets/css/components/_address-overview.scss
@@ -79,4 +79,8 @@
&:last-child {
margin-bottom: 0;
}
+}
+
+.logs-decoded {
+ line-height: 25px!important;
}
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/components/_btn_contract.scss b/apps/block_scout_web/assets/css/components/_btn_contract.scss
new file mode 100644
index 0000000000..e78fbc200a
--- /dev/null
+++ b/apps/block_scout_web/assets/css/components/_btn_contract.scss
@@ -0,0 +1,6 @@
+$btn-contract-color: $primary !default;
+$btn-contract-dimensions: 31px !default;
+
+.btn-contract-icon {
+ @include square-icon-button($btn-contract-color, $btn-contract-dimensions);
+}
diff --git a/apps/block_scout_web/assets/css/components/_erc721_token_image_container.scss b/apps/block_scout_web/assets/css/components/_erc721_token_image_container.scss
new file mode 100644
index 0000000000..261cab7d78
--- /dev/null
+++ b/apps/block_scout_web/assets/css/components/_erc721_token_image_container.scss
@@ -0,0 +1,10 @@
+/* ERC721 image block */
+.erc721-image {
+ display: flex;
+ justify-content: center;
+}
+
+ .erc721-image img {
+ height: 150px;
+}
+/* ERC721 image block end */
diff --git a/apps/block_scout_web/assets/css/theme/_dark-theme.scss b/apps/block_scout_web/assets/css/theme/_dark-theme.scss
index bd4a97aa11..b6bfa5d202 100644
--- a/apps/block_scout_web/assets/css/theme/_dark-theme.scss
+++ b/apps/block_scout_web/assets/css/theme/_dark-theme.scss
@@ -234,7 +234,7 @@ $labels-dark: #8a8dba; // header nav, labels
}
}
- .btn-copy-icon, .btn-qr-icon, .btn-address-card-icon {
+ .btn-copy-icon, .btn-qr-icon, .btn-address-card-icon .btn-contract-icon {
border-color: $dark-primary;
path {
fill: $dark-primary;
@@ -504,7 +504,7 @@ $labels-dark: #8a8dba; // header nav, labels
border-top-color: darken($labels-dark, 30);
border-bottom-color: darken($labels-dark, 30);
}
-
+
// Form Controlls
.form-control {
background-color: $dark-light;
@@ -749,7 +749,7 @@ $labels-dark: #8a8dba; // header nav, labels
color: #fff;
}
}
-
+
// alerts
.alert-link {
color: $labels-dark;
@@ -792,35 +792,37 @@ $labels-dark: #8a8dba; // header nav, labels
.dark-theme-applied .dropdown-item.active, .dark-theme-applied .dropdown-item:hover, .dark-theme-applied .dropdown-item:focus {
background-image: none;
width: 100%;
- background-color: #35335d!important;
-}
- .dark-theme-applied .dropdown-item:hover:before {
- content: "|";
- height: 50px;
- width: 50%;
- opacity: 1;
- background: none;
- right: 17%;
- color: $dark-primary;
- position: relative;
+ background-color: #3f426c!important;
}
-.dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link:hover,
-.dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link.activeLink,
-.dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link:focus {
- background-image: none;
- width: 100%;
- background-color: #35335d!important;
- color: white;
- border: none;
- }
- .dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link:hover:before
- {
- content: "|";
- height: 50px;
- width: 50%;
- opacity: 1;
- background: none;
- left: 24%;
- top: 14%;
- color: $dark-primary;
- }
\ No newline at end of file
+@media (max-width: 991.98px) {
+ .dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link:hover,
+ .dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link.activeLink,
+ .dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link:focus {
+ background-image: none;
+ width: 100%;
+ background-color: #35335d!important;
+ color: white;
+ border: none;
+ }
+ .dark-theme-applied .dropdown-item:hover:before {
+ content: "|";
+ height: 50px;
+ width: 50%;
+ opacity: 1;
+ background: none;
+ right: 17%;
+ color: $dark-primary;
+ position: relative;
+ }
+ .dark-theme-applied .navbar.navbar-primary .navbar-nav .nav-link:hover:before
+ {
+ content: "|";
+ height: 50px;
+ width: 50%;
+ opacity: 1;
+ background: none;
+ left: 24%;
+ top: 14%;
+ color: $dark-primary;
+ }
+ }
diff --git a/apps/block_scout_web/assets/css/theme/_ether1_variables.scss b/apps/block_scout_web/assets/css/theme/_ether1_variables.scss
index 323ceb22ac..ec5e65bb95 100644
--- a/apps/block_scout_web/assets/css/theme/_ether1_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ether1_variables.scss
@@ -37,7 +37,7 @@ $btn-line-bg: #fff; // button bg
$btn-line-color: #4b021e; // button border and font color && hover bg color
$btn-copy-color: #4b021e; // btn copy
$btn-qr-color: #4b021e; // btn qr-code
-
+$btn-contract-color: #4b021e;
//links & tile
.tile a { color: $tertiary !important; } // links color for badges
.tile-type-block {
diff --git a/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss b/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
index 6b8d6d7f96..ffcdc4a44b 100644
--- a/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ethereum_classic_variables.scss
@@ -35,6 +35,7 @@ $btn-line-color: $tertiary; // button border and font color && hover bg color
$btn-copy-color: $tertiary; // btn copy
$btn-qr-color: $tertiary; // btn qr-code
$btn-address-card-icon-color: $tertiary; // btn address color
+$btn-contract-color: $tertiary;
//links & tile
$tile-body-a-color: $tertiary;
diff --git a/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss b/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
index a06e0be93e..564242b150 100644
--- a/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ethereum_variables.scss
@@ -38,6 +38,7 @@ $btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
$btn-address-card-icon-color: $secondary; // btn address color
+$btn-contract-color: $secondary;
//links & tile
$tile-body-a-color: $secondary;
diff --git a/apps/block_scout_web/assets/css/theme/_goerli_variables.scss b/apps/block_scout_web/assets/css/theme/_goerli_variables.scss
index af57f2d1a2..d9d5d2ea17 100644
--- a/apps/block_scout_web/assets/css/theme/_goerli_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_goerli_variables.scss
@@ -44,6 +44,7 @@ $btn-line-color: $sub-accent-color; // button border and font color && hover bg
$btn-copy-color: $sub-accent-color; // btn copy
$btn-qr-color: $sub-accent-color; // btn qr-code
$btn-address-card-icon-color: $sub-accent-color; // btn address color
+$btn-contract-color: $sub-accent-color;
//links & tile
$tile-body-a-color: $sub-accent-color;
diff --git a/apps/block_scout_web/assets/css/theme/_kovan_variables.scss b/apps/block_scout_web/assets/css/theme/_kovan_variables.scss
index b47c3de0b2..dc1cceafbd 100644
--- a/apps/block_scout_web/assets/css/theme/_kovan_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_kovan_variables.scss
@@ -39,6 +39,7 @@ $btn-line-color: $tertiary; // button border and font color && hover bg color
$btn-copy-color: $tertiary; // btn copy
$btn-qr-color: $tertiary; // btn qr-code
$btn-address-card-icon-color: $tertiary; // btn address color
+$btn-contract-color: $tertiary;
//links & tile
$tile-body-a-color: $tertiary;
diff --git a/apps/block_scout_web/assets/css/theme/_poa_variables.scss b/apps/block_scout_web/assets/css/theme/_poa_variables.scss
index 536ecdc105..88dcb6eb06 100644
--- a/apps/block_scout_web/assets/css/theme/_poa_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_poa_variables.scss
@@ -41,6 +41,7 @@ $btn-line-color: $primary; // button border and font color && hover bg color
$btn-copy-color: $primary; // btn copy
$btn-qr-color: $primary; // btn qr-code
$btn-address-card-icon-color: $primary; // btn address color
+$btn-contract-color: $primary;
//links & tile
$tile-body-a-color: $primary;
diff --git a/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss b/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
index 21388bb315..68631dc349 100644
--- a/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_rinkeby_variables.scss
@@ -38,6 +38,7 @@ $btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
$btn-address-card-icon-color: $secondary; // btn address color
+$btn-contract-color: $secondary;
//links & tile
$tile-body-a-color: $secondary;
diff --git a/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss b/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
index 21388bb315..68631dc349 100644
--- a/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_ropsten_variables.scss
@@ -38,6 +38,7 @@ $btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
$btn-address-card-icon-color: $secondary; // btn address color
+$btn-contract-color: $secondary;
//links & tile
$tile-body-a-color: $secondary;
diff --git a/apps/block_scout_web/assets/css/theme/_rsk_variables.scss b/apps/block_scout_web/assets/css/theme/_rsk_variables.scss
index 8d3bff31d2..1e23b819c4 100644
--- a/apps/block_scout_web/assets/css/theme/_rsk_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_rsk_variables.scss
@@ -39,7 +39,7 @@ $btn-line-color: $secondary; // button border and font color && hover bg color
$btn-copy-color: $secondary; // btn copy
$btn-qr-color: $secondary; // btn qr-code
$btn-address-card-icon-color: $secondary; // btn address color
-
+$btn-contract-color: $secondary;
// card
$card-background-1: $secondary;
$card-tab-active: $secondary;
diff --git a/apps/block_scout_web/assets/css/theme/_social_variables.scss b/apps/block_scout_web/assets/css/theme/_social_variables.scss
index 3d878dcf10..22718bd084 100644
--- a/apps/block_scout_web/assets/css/theme/_social_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_social_variables.scss
@@ -5,4 +5,4 @@ $tertiary: #53a9ff;
$footer-background-color: $primary;
$footer-title-color: #fff;
$footer-text-color: #fff;
-$footer-item-disc-color: $secondary;
+$footer-item-disc-color: $secondary;
\ No newline at end of file
diff --git a/apps/block_scout_web/assets/css/theme/_sokol_variables.scss b/apps/block_scout_web/assets/css/theme/_sokol_variables.scss
index 2860342f1e..836cc8a114 100644
--- a/apps/block_scout_web/assets/css/theme/_sokol_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_sokol_variables.scss
@@ -50,7 +50,7 @@ $btn-line-color: $sub-accent-color; // button border and font color && hover bg
$btn-copy-color: $sub-accent-color; // btn copy
$btn-qr-color: $sub-accent-color; // btn qr-code
$btn-address-card-icon-color: $sub-accent-color; // btn address color
-
+$btn-contract-color: $sub-accent-color;
//links & tile
$tile-body-a-color: $sub-accent-color;
$tile-type-block-color: $sub-accent-color;
diff --git a/apps/block_scout_web/assets/css/theme/_tomochain_variables.scss b/apps/block_scout_web/assets/css/theme/_tomochain_variables.scss
index 6f7694de7d..d3c3a166d5 100644
--- a/apps/block_scout_web/assets/css/theme/_tomochain_variables.scss
+++ b/apps/block_scout_web/assets/css/theme/_tomochain_variables.scss
@@ -1,3 +1,4 @@
$primary: #211841;
$secondary: #f16950;
$tertiary: #8b84bc;
+$btn-contract-color: $primary;
diff --git a/apps/block_scout_web/assets/static/images/controller.svg b/apps/block_scout_web/assets/static/images/controller.svg
new file mode 100644
index 0000000000..c62d55bebe
--- /dev/null
+++ b/apps/block_scout_web/assets/static/images/controller.svg
@@ -0,0 +1,7 @@
+
diff --git a/apps/block_scout_web/config/config.exs b/apps/block_scout_web/config/config.exs
index 0126a7d410..1347195b91 100644
--- a/apps/block_scout_web/config/config.exs
+++ b/apps/block_scout_web/config/config.exs
@@ -38,6 +38,7 @@ config :block_scout_web, BlockScoutWeb.Counters.BlocksIndexedCounter, enabled: t
config :block_scout_web, BlockScoutWeb.Endpoint,
instrumenters: [BlockScoutWeb.Prometheus.Instrumenter, SpandexPhoenix.Instrumenter],
url: [
+ scheme: System.get_env("BLOCKSCOUT_PROTOCOL") || "http",
host: System.get_env("BLOCKSCOUT_HOST") || "localhost",
path: System.get_env("NETWORK_PATH") || "/"
],
diff --git a/apps/block_scout_web/config/prod.exs b/apps/block_scout_web/config/prod.exs
index c388caab64..00cedfe8c3 100644
--- a/apps/block_scout_web/config/prod.exs
+++ b/apps/block_scout_web/config/prod.exs
@@ -20,7 +20,7 @@ config :block_scout_web, BlockScoutWeb.Endpoint,
check_origin: System.get_env("CHECK_ORIGIN") || false,
http: [port: System.get_env("PORT")],
url: [
- scheme: "https",
+ scheme: System.get_env("BLOCKSCOUT_PROTOCOL") || "https",
port: System.get_env("PORT"),
host: System.get_env("BLOCKSCOUT_HOST") || "localhost",
path: System.get_env("NETWORK_PATH") || "/"
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
index e2cb1f6db7..d91552229a 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_controller.ex
@@ -44,8 +44,7 @@ defmodule BlockScoutWeb.AddressController do
index: index,
exchange_rate: exchange_rate,
total_supply: total_supply,
- tx_count: tx_count,
- validation_count: validation_count(address.hash)
+ tx_count: tx_count
)
end)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
index 9236c433a7..eeb5a5c11b 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/address_transaction_controller.ex
@@ -62,6 +62,7 @@ defmodule BlockScoutWeb.AddressTransactionController do
View.render_to_string(
TransactionView,
"_emission_reward_tile.html",
+ conn: conn,
current_address: address,
emission_funds: emission_reward,
validator: validator_reward
@@ -71,6 +72,7 @@ defmodule BlockScoutWeb.AddressTransactionController do
View.render_to_string(
TransactionView,
"_tile.html",
+ conn: conn,
current_address: address,
transaction: transaction
)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
index dd362cd065..9351f9f886 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/block_transaction_controller.ex
@@ -50,7 +50,8 @@ defmodule BlockScoutWeb.BlockTransactionController do
View.render_to_string(
TransactionView,
"_tile.html",
- transaction: transaction
+ transaction: transaction,
+ conn: conn
)
end)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/pending_transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/pending_transaction_controller.ex
index 1128f04616..9385ee5616 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/pending_transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/pending_transaction_controller.ex
@@ -43,7 +43,8 @@ defmodule BlockScoutWeb.PendingTransactionController do
View.render_to_string(
TransactionView,
"_tile.html",
- transaction: transaction
+ transaction: transaction,
+ conn: conn
)
end),
next_page_path: next_page_url
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex
index a98e380e67..3b9830476c 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/recent_transactions_controller.ex
@@ -23,7 +23,7 @@ defmodule BlockScoutWeb.RecentTransactionsController do
%{
transaction_hash: Hash.to_string(transaction.hash),
transaction_html:
- View.render_to_string(BlockScoutWeb.TransactionView, "_tile.html", transaction: transaction)
+ View.render_to_string(BlockScoutWeb.TransactionView, "_tile.html", transaction: transaction, conn: conn)
}
end)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/metadata_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/metadata_controller.ex
new file mode 100644
index 0000000000..90b2006543
--- /dev/null
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/metadata_controller.ex
@@ -0,0 +1,34 @@
+defmodule BlockScoutWeb.Tokens.Instance.MetadataController do
+ use BlockScoutWeb, :controller
+
+ alias Explorer.{Chain, Market}
+
+ def index(conn, %{"token_id" => token_address_hash, "instance_id" => token_id}) do
+ options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}]
+
+ with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
+ {:ok, token} <- Chain.token_from_address_hash(hash, options),
+ {:ok, token_transfer} <-
+ Chain.erc721_token_instance_from_token_id_and_token_address(token_id, hash) do
+ if token_transfer.instance && token_transfer.instance.metadata do
+ render(
+ conn,
+ "index.html",
+ token_instance: token_transfer,
+ current_path: current_path(conn),
+ token: Market.add_price(token),
+ total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id)
+ )
+ else
+ not_found(conn)
+ end
+ else
+ _ ->
+ not_found(conn)
+ end
+ end
+
+ def index(conn, _) do
+ not_found(conn)
+ end
+end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/transfer_controller.ex
new file mode 100644
index 0000000000..4ea0bd2d76
--- /dev/null
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance/transfer_controller.ex
@@ -0,0 +1,74 @@
+defmodule BlockScoutWeb.Tokens.Instance.TransferController do
+ use BlockScoutWeb, :controller
+
+ alias BlockScoutWeb.Tokens.TransferView
+ alias Explorer.{Chain, Market}
+ alias Phoenix.View
+
+ import BlockScoutWeb.Chain, only: [split_list_by_page: 1, paging_options: 1, next_page_params: 3]
+
+ def index(conn, %{"token_id" => token_address_hash, "instance_id" => token_id, "type" => "JSON"} = params) do
+ with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
+ {:ok, token} <- Chain.token_from_address_hash(hash),
+ token_transfers <-
+ Chain.fetch_token_transfers_from_token_hash_and_token_id(hash, token_id, paging_options(params)) do
+ {token_transfers_paginated, next_page} = split_list_by_page(token_transfers)
+
+ next_page_path =
+ case next_page_params(next_page, token_transfers_paginated, params) do
+ nil ->
+ nil
+
+ next_page_params ->
+ token_instance_transfer_path(
+ conn,
+ :index,
+ token_id,
+ token.contract_address_hash,
+ Map.delete(next_page_params, "type")
+ )
+ end
+
+ transfers_json =
+ Enum.map(token_transfers_paginated, fn transfer ->
+ View.render_to_string(
+ TransferView,
+ "_token_transfer.html",
+ conn: conn,
+ token: token,
+ token_transfer: transfer
+ )
+ end)
+
+ json(conn, %{items: transfers_json, next_page_path: next_page_path})
+ else
+ _ ->
+ not_found(conn)
+ end
+ end
+
+ def index(conn, %{"token_id" => token_address_hash, "instance_id" => token_id}) do
+ options = [necessity_by_association: %{[contract_address: :smart_contract] => :optional}]
+
+ with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
+ {:ok, token} <- Chain.token_from_address_hash(hash, options),
+ {:ok, token_transfer} <-
+ Chain.erc721_token_instance_from_token_id_and_token_address(token_id, hash) do
+ render(
+ conn,
+ "index.html",
+ token_instance: token_transfer,
+ current_path: current_path(conn),
+ token: Market.add_price(token),
+ total_token_transfers: Chain.count_token_transfers_from_token_hash_and_token_id(hash, token_id)
+ )
+ else
+ _ ->
+ not_found(conn)
+ end
+ end
+
+ def index(conn, _) do
+ not_found(conn)
+ end
+end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance_controller.ex
new file mode 100644
index 0000000000..d3c43bda46
--- /dev/null
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/instance_controller.ex
@@ -0,0 +1,20 @@
+defmodule BlockScoutWeb.Tokens.InstanceController do
+ use BlockScoutWeb, :controller
+
+ alias Explorer.Chain
+
+ def show(conn, %{"token_id" => token_address_hash, "id" => token_id}) do
+ with {:ok, hash} <- Chain.string_to_address_hash(token_address_hash),
+ :ok <- Chain.check_token_exists(hash),
+ :ok <- Chain.check_erc721_token_instance_exists(token_id, hash) do
+ redirect(conn, to: token_instance_transfer_path(conn, :index, token_address_hash, token_id))
+ else
+ _ ->
+ not_found(conn)
+ end
+ end
+
+ def show(conn, _) do
+ not_found(conn)
+ end
+end
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex
index ddd12eb392..622dc35946 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/inventory_controller.ex
@@ -40,7 +40,9 @@ defmodule BlockScoutWeb.Tokens.InventoryController do
View.render_to_string(
InventoryView,
"_token.html",
- token_transfer: token_transfer
+ token_transfer: token_transfer,
+ token: token,
+ conn: conn
)
end)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex
index f977d091f1..d7bd40cfab 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/tokens/transfer_controller.ex
@@ -30,7 +30,7 @@ defmodule BlockScoutWeb.Tokens.TransferController do
"_token_transfer.html",
conn: conn,
token: token,
- transfer: transfer
+ token_transfer: transfer
)
end)
diff --git a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
index 3f849c0e7c..db0cae65d8 100644
--- a/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
+++ b/apps/block_scout_web/lib/block_scout_web/controllers/transaction_controller.ex
@@ -41,7 +41,8 @@ defmodule BlockScoutWeb.TransactionController do
View.render_to_string(
TransactionView,
"_tile.html",
- transaction: transaction
+ transaction: transaction,
+ conn: conn
)
end),
next_page_path: next_page_path
diff --git a/apps/block_scout_web/lib/block_scout_web/csp_header.ex b/apps/block_scout_web/lib/block_scout_web/csp_header.ex
index 199ee9f189..75cfbf0cb6 100644
--- a/apps/block_scout_web/lib/block_scout_web/csp_header.ex
+++ b/apps/block_scout_web/lib/block_scout_web/csp_header.ex
@@ -15,7 +15,7 @@ defmodule BlockScoutWeb.CSPHeader do
default-src 'self';\
script-src 'self' 'unsafe-inline' 'unsafe-eval';\
style-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com;\
- img-src 'self' 'unsafe-inline' 'unsafe-eval' data:;\
+ img-src 'self' * data:;\
font-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.gstatic.com data:;\
"
})
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
index 56f1a2bbb2..4945dca50c 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address/_tile.html.eex
@@ -29,11 +29,6 @@
<%= @tx_count %>
<%= gettext "Transactions sent" %>
- <% if validator?(@address) do %>
-
- <%= @validation_count %>
- <%= gettext "Validations" %>
- <% end %>
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
index 92a8ebc6cc..945049ace6 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/address_logs/_logs.html.eex
@@ -17,7 +17,7 @@
- <%= gettext "Transaction" %>
-
-
+
<%= link(
@log.transaction,
to: transaction_path(@conn, :show, @log.transaction),
diff --git a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
index 0463d28a15..2b21120556 100644
--- a/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
+++ b/apps/block_scout_web/lib/block_scout_web/templates/layout/_topnav.html.eex
@@ -16,7 +16,7 @@
Sokol Testnet
+ <%= subnetwork_title() %>