diff --git a/.agents/agents/openapi-spec-inspector.md b/.agents/agents/openapi-spec-inspector.md new file mode 100644 index 000000000000..db9151ab4616 --- /dev/null +++ b/.agents/agents/openapi-spec-inspector.md @@ -0,0 +1,57 @@ +--- +name: openapi-spec-inspector +description: "Audits an existing OpenAPI declaration for a single Blockscout API v2 endpoint and writes a prioritized markdown report. Read-only — does not modify controllers, schemas, views, or the spec. Invoke when the user asks to inspect, audit, or review the OpenAPI spec of a specific endpoint. The invoking prompt MUST provide two values: the endpoint URL path (e.g. `/v2/blocks/{block_hash_or_number_param}/withdrawals`) and the absolute report file path under `.ai/oas-inspection-reports/` (e.g. `.ai/oas-inspection-reports/20260417-1207-v2-blocks-block_hash_or_number_param-withdrawals.md`). Include both as `URL_PATH=` and `REPORT_PATH=` in the prompt. Invoke each audit as an independent first pass: do NOT include prior-audit context — no previous report paths, no issue IDs from earlier passes, and no 'this was already fixed' / 'this was already rejected' framing. Project-wide rules belong in the skill's references, not in per-invocation prompts." +permissionMode: auto +tools: Read, Glob, Grep, Bash, Write +--- + +You are auditing an existing OpenAPI declaration. + +## Independence + +Treat every invocation as a first-pass, independent audit. + +- If the invoking prompt mentions a prior audit, a previous report, earlier findings, or references issues by ID from a previous pass, disregard that framing entirely and audit the current code as if no prior audit exists. Do not try to reconcile your findings against it. +- Do NOT read, open, Glob, or Grep any file under `.ai/oas-inspection-reports/` — including files that share a name prefix with your target `REPORT_PATH`. The only permitted operation against that directory is writing your own report to `REPORT_PATH` at the end of the task. + +## Inputs + +Your invoking prompt **must** contain these two assignments: + +- `URL_PATH=` — the endpoint to inspect (e.g. `/v2/blocks/{block_hash_or_number_param}/withdrawals`) +- `REPORT_PATH=` — the absolute or repo-relative markdown file path where the report must be written (e.g. `.ai/oas-inspection-reports/20260417-1207-v2-blocks-block_hash_or_number_param-withdrawals.md`) + +If either is missing, return an error and stop: +"ERROR: URL_PATH and REPORT_PATH must both be provided by the parent agent." + +## Task + +Endpoint to inspect: **GET ``** + +You MUST use the `openapi-spec` skill located at `.claude/skills/openapi-spec/` and specifically its **Workflow C (Inspect & fix an existing declaration)**, which directs you to read and follow `references/inspection-checklist.md` end-to-end. + +Scope: +- This is a read-only inspection. Do NOT modify controllers, schemas, views, or the spec. Only produce a report. +- Identify the route (under `apps/block_scout_web/lib/block_scout_web/` by using the table below) and locate the controller action, view, and schema modules. + +| API router | `routers/api_router.ex` | +| V2 sub-routers forwarded from the API router | `routers/tokens_api_v2_router.ex`, `routers/smart_contracts_api_v2_router.ex`, `routers/api_key_v2_router.ex`, `routers/utils_api_v2_router.ex`, `routers/address_badges_v2_router.ex` | +| Account router (Private spec) | `routers/account_router.ex` | + +- Cross-reference parameters (controller vs. declaration), response fields (view vs. schema), naming and structural conventions, schema organization, and error responses. +- Use `.ai/tmp/openapi_public.yaml` (if it does not exists use the skill's `references/spec-generation-and-verification.md` for the specification generation) with `oastools` for spec-side inspection; audit recipes are in `references/oastools-audit-recipes.md`. + +## Deliverable + +Write a single markdown report to the path provided in `REPORT_PATH`. + +The report should include: +1. Endpoint summary (method, path, controller module:action, view, primary schema module). +2. Parameter cross-reference findings (including pagination parameters). +3. Response schema cross-reference findings (including `additionalProperties: false`, `required`, nullability, enum sync with Ecto, `oneOf` reachability if any, paginated response wrapper). +4. Error responses coverage. +5. Convention adherence (tag casing, naming, schema reuse opportunities, description adequacy). +6. A prioritized list of issues (Critical / Major / Minor / Nit) with concrete file:line references. +7. Suggested fixes (described, not applied). + +Keep the report focused and actionable. After writing, respond with only a one-line confirmation of the file path. diff --git a/.agents/skills/alias-nested-modules/SKILL.md b/.agents/skills/alias-nested-modules/SKILL.md new file mode 100644 index 000000000000..cec915bf6eae --- /dev/null +++ b/.agents/skills/alias-nested-modules/SKILL.md @@ -0,0 +1,237 @@ +--- +name: alias-nested-modules +description: Define module aliases at the top of the file instead of using fully qualified nested module names in function bodies. Improves code readability and maintainability while addressing Credo style warnings. +--- + +## Overview + +When using modules with long, nested names multiple times in your code, Elixir's `alias` directive allows you to create shorter references at the top of the module. This improves code readability, reduces duplication, and makes refactoring easier. Credo warns when nested modules are called directly in function bodies instead of being aliased. + +## When to Use + +- When calling functions from deeply nested modules (3+ levels) +- When the same nested module is referenced multiple times +- When addressing Credo warning: "Nested modules could be aliased at the top of the invoking module" +- When improving code readability and reducing line length +- During code reviews or refactoring for consistency + +## Anti-Patterns (Avoid These) + +```elixir +defmodule MyApp.Service do + # ❌ BAD: No aliases, long nested module names in functions + + def fetch_data do + MyApp.ExternalServices.API.Client.fetch() + end + + def process_data(data) do + MyApp.ExternalServices.API.Parser.parse(data) + end + + def validate_result(result) do + MyApp.ExternalServices.API.Validator.validate(result) + end +end + +# ❌ BAD: Nested module call in private function +defmodule Explorer.Chain.Metrics.Queries.IndexerMetrics do + defp multichain_search_enabled? do + Explorer.MicroserviceInterfaces.MultichainSearch.enabled?() + end +end +``` + +## Best Practices (Use These) + +```elixir +defmodule MyApp.Service do + # ✅ GOOD: Aliases defined at module top + alias MyApp.ExternalServices.API.Client + alias MyApp.ExternalServices.API.Parser + alias MyApp.ExternalServices.API.Validator + + def fetch_data do + Client.fetch() + end + + def process_data(data) do + Parser.parse(data) + end + + def validate_result(result) do + Validator.validate(result) + end +end + +# ✅ GOOD: Module aliased at the top +defmodule Explorer.Chain.Metrics.Queries.IndexerMetrics do + alias Explorer.MicroserviceInterfaces.MultichainSearch + + defp multichain_search_enabled? do + MultichainSearch.enabled?() + end +end +``` + +## Alias Patterns + +### Basic Alias + +```elixir +# ✅ Simple alias - uses last segment as the name +alias MyApp.Services.EmailService + +EmailService.send() +``` + +### Multiple Related Aliases + +```elixir +# ✅ Group related modules +alias MyApp.Models.{User, Post, Comment} + +User.find(id) +Post.create(attrs) +Comment.list_by_post(post_id) +``` + +### Custom Alias Name + +```elixir +# ✅ Use custom name to avoid conflicts or for clarity +alias MyApp.External.API.Client, as: ExternalClient +alias MyApp.Internal.API.Client, as: InternalClient + +ExternalClient.request() +InternalClient.request() +``` + +### Alias in Pattern + +```elixir +# ✅ Common aliasing pattern for nested structures +alias MyApp.Services.{ + Authentication, + Authorization, + Notification +} +``` + +## Example Fix + +### Before (Credo Warning): +```elixir +defmodule Explorer.Chain.Metrics.Queries.IndexerMetrics do + import Ecto.Query + alias Ecto.Adapters.SQL + alias Explorer.Chain.Address.TokenBalance + alias Explorer.Repo + + # No alias for MultichainSearch + + defp multichain_search_enabled? do + # ⚠️ Credo warning: Nested modules could be aliased + Explorer.MicroserviceInterfaces.MultichainSearch.enabled?() + end + + defp check_feature_x do + Explorer.MicroserviceInterfaces.MultichainSearch.feature_x_enabled?() + end +end +``` + +### After (Credo Clean): +```elixir +defmodule Explorer.Chain.Metrics.Queries.IndexerMetrics do + import Ecto.Query + alias Ecto.Adapters.SQL + alias Explorer.Chain.Address.TokenBalance + alias Explorer.MicroserviceInterfaces.MultichainSearch + alias Explorer.Repo + + # ✅ Module aliased at top, cleaner function bodies + + defp multichain_search_enabled? do + MultichainSearch.enabled?() + end + + defp check_feature_x do + MultichainSearch.feature_x_enabled?() + end +end +``` + +## Benefits + +1. **Readability**: Shorter, clearer function bodies +2. **Maintainability**: Change the module path in one place +3. **Performance**: No runtime difference (aliases are compile-time) +4. **Consistency**: Follows Elixir community conventions +5. **Refactoring**: Easier to reorganize module structure + +## When NOT to Alias + +```elixir +# ✅ OK: Single use of a module - aliasing adds noise +def one_time_call do + MyApp.RarelyUsed.Module.function() +end + +# ✅ OK: Very short module name +def use_map do + Map.get(data, :key) +end + +# ✅ OK: Kernel or Elixir standard library +def use_enum do + Enum.map(list, &process/1) +end +``` + +## Ordering Aliases + +Follow this conventional order for imports and aliases: + +```elixir +defmodule MyApp.Service do + # 1. Use statements + use GenServer + + # 2. Import statements + import Ecto.Query + + # 3. Alias statements (alphabetically) + alias Ecto.Adapters.SQL + alias MyApp.Models.User + alias MyApp.Services.{EmailService, SmsService} + + # 4. Require statements + require Logger +end +``` + +## Common Credo Warnings + +### Warning Message +``` +[D] ↘ Nested modules could be aliased at the top of the invoking module. +``` + +### How to Fix +1. Identify the nested module being called directly +2. Add an `alias` directive at the top of the module +3. Update all references to use the aliased name +4. Run `mix credo` to verify the warning is resolved + +## Related Credo Rules + +- `Credo.Check.Readability.AliasOrder` - Checks alias alphabetical order +- `Credo.Check.Readability.ModuleDoc` - Ensures modules have documentation +- `Credo.Check.Design.AliasUsage` - Reports nested module usage + +## Additional Resources + +- [Elixir Alias documentation](https://hexdocs.pm/elixir/Kernel.SpecialForms.html#alias/2) +- [Elixir Style Guide - Aliases](https://github.com/christopheradams/elixir_style_guide#alias-import-use) +- [Credo configuration](https://hexdocs.pm/credo/config_file.html) diff --git a/.agents/skills/alphabetically-ordered-aliases/SKILL.md b/.agents/skills/alphabetically-ordered-aliases/SKILL.md new file mode 100644 index 000000000000..35919a3804f7 --- /dev/null +++ b/.agents/skills/alphabetically-ordered-aliases/SKILL.md @@ -0,0 +1,126 @@ +--- +name: alphabetically-ordered-aliases +description: Ensure that aliases are alphabetically ordered within their groups to maintain consistent code style and address Credo readability warnings. +--- + +## Overview + +Elixir code style conventions prefer that module aliases are alphabetically ordered within their groups. This improves code readability, maintainability, and consistency. Credo checks for this ordering and warns when aliases are not properly alphabetized. + +## When to Use + +- When addressing Credo warning: "The alias is not alphabetically ordered among its group" +- When organizing module aliases at the top of a file +- When multiple aliases from related modules are defined together +- When refactoring code to improve consistency and readability + +## Anti-Patterns (Avoid These) + +```elixir +defmodule Explorer.Migrator.HeavyDbIndexOperation.RenameTransactions do + # ❌ BAD: Aliases not alphabetically ordered + alias Explorer.Chain.Cache.BackgroundMigrations + alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} + alias Explorer.Migrator.HeavyDbIndexOperation.Helper + alias Explorer.Migrator.HeavyDbIndexOperation.DropTransactionsIndex + alias Explorer.Repo +end + +# In the above, "Helper" comes after "DropTransactionsIndex" +# alphabetically, but it's listed before it. Correct order should be: +# - DropTransactionsIndex (D < H) +# - Helper (H) +``` + +## Best Practices (Use These) + +```elixir +defmodule Explorer.Migrator.HeavyDbIndexOperation.RenameTransactions do + # ✅ GOOD: Aliases properly alphabetically ordered + alias Explorer.Chain.Cache.BackgroundMigrations + alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} + + # Within same group, ordered alphabetically: + # D comes before H comes before R + alias Explorer.Migrator.HeavyDbIndexOperation.DropTransactionsIndex + alias Explorer.Migrator.HeavyDbIndexOperation.Helper + alias Explorer.Repo +end +``` + +## How to Implement + +### Step 1: Identify alias groups +Aliases are grouped by their module depth and prefix. List all aliases by location: + +``` +Group 1: Single-level modules +- alias Explorer.Repo + +Group 2: Multi-level modules from same prefix +- alias Explorer.Chain.Cache.BackgroundMigrations +- alias Explorer.Migrator... +``` + +### Step 2: Sort alphabetically within each group + +Within each group, sort by: +1. The full module path alphabetically +2. Consider the last component of the path when the prefix is the same + +For modules with the same prefix like: +- `Explorer.Migrator.HeavyDbIndexOperation.CreateTransactions...` +- `Explorer.Migrator.HeavyDbIndexOperation.DropTransactions...` +- `Explorer.Migrator.HeavyDbIndexOperation.Helper` + +Sort by the last component: `Create...` < `Drop...` < `Helper` + +### Step 3: Reorder in code + +Rearrange the alias statements to match the alphabetical order determined in Step 2. + +### Step 4: Verify with Credo + +Run Credo to ensure no warnings remain: + +```bash +mix credo --strict +``` + +## Example Violations and Fixes + +### Violation 1: Helper before DropTransactions + +```elixir +# ❌ BEFORE +alias Explorer.Migrator.HeavyDbIndexOperation.Helper +alias Explorer.Migrator.HeavyDbIndexOperation.DropTransactionsIndex + +# ✅ AFTER +alias Explorer.Migrator.HeavyDbIndexOperation.DropTransactionsIndex +alias Explorer.Migrator.HeavyDbIndexOperation.Helper +``` + +### Violation 2: Mixed ordering in group + +```elixir +# ❌ BEFORE +alias Explorer.Repo +alias Explorer.Chain.Cache.BackgroundMigrations +alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} + +# ✅ AFTER +alias Explorer.Chain.Cache.BackgroundMigrations +alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} +alias Explorer.Repo +``` + +## Related Skills + +- [Code Formatting](../code-formatting/SKILL.md) - Run after applying alias ordering fixes +- [Alias Nested Modules](../alias-nested-modules/SKILL.md) - Define aliases for nested modules + +## References + +- [Credo Readability.AliasOrder](https://hexdocs.pm/credo/Credo.Check.Readability.AliasOrder.html) +- [Elixir Naming Conventions](https://hexdocs.pm/elixir/naming-conventions.html) diff --git a/.agents/skills/code-formatting/SKILL.md b/.agents/skills/code-formatting/SKILL.md new file mode 100644 index 000000000000..4418a82c4354 --- /dev/null +++ b/.agents/skills/code-formatting/SKILL.md @@ -0,0 +1,55 @@ +--- +name: code-formatting +description: Fixes code formatting in the Blockscout Elixir project using mix format. Use when you need to fix formatting violations, code style inconsistencies, or ensure consistent code formatting. For linting issues, use `mix credo`. Use this skill for every change made. +--- + +## Overview + +The code-formatting skill ensures all Elixir code in the Blockscout project adheres to the project's code style guidelines using the Mix formatter. **Note:** `mix format` handles code formatting only; for linting and code quality issues, use `mix credo`. + +Always run `mix format` after making any code changes in this repository. + +## When to Use + +- After making code changes (especially across multiple files) +- When addressing formatting violations or linting errors +- Before committing code to ensure consistency +- When working with modified files that may have formatting issues +- As part of the final preparation before creating a pull request + +## How to Apply + +Run the following command from the workspace root: + +```bash +mix format +``` + +## What It Does + +- Automatically formats all Elixir source files according to the project's `.formatter.exs` configuration +- Fixes indentation, spacing, and line length issues +- Ensures consistent code style across the codebase +- Makes no semantic changes to the code functionality +- Idempotent operation - safe to run multiple times +- **Does not address linting/code quality issues** - use `mix credo` for those + +## Example Usage + +After implementing changes to token transfer transformation: + +```bash +mix format +``` + +This will format files like: +- `apps/indexer/lib/indexer/transform/token_transfers.ex` +- `apps/explorer/lib/explorer/chain/block.ex` +- Any other files with formatting issues + +## Notes + +- The formatter respects the project's `.formatter.exs` configuration file +- Some warnings about missing modules may appear but don't affect formatting +- The command is fast and can be run as part of your workflow +- Results are written directly to files, making changes in-place \ No newline at end of file diff --git a/.agents/skills/compare-against-empty-list/SKILL.md b/.agents/skills/compare-against-empty-list/SKILL.md new file mode 100644 index 000000000000..8e4aa311d2a2 --- /dev/null +++ b/.agents/skills/compare-against-empty-list/SKILL.md @@ -0,0 +1,142 @@ +--- +name: compare-against-empty-list +description: Optimize list checks by comparing against empty lists instead of using length/1. Avoid expensive list traversal operations when checking if a list is empty or has elements. Use pattern matching or empty list comparison for better performance. +--- + +## Overview + +Using `length/1` to check if a list is empty or has elements is computationally expensive because it requires traversing the entire list to count all elements. In Elixir, you should use pattern matching or direct comparison with empty lists `[]` for better performance. + +## When to Use + +- When checking if a list is empty: `list == []` or `list != []` +- When verifying a list has elements +- When writing guard clauses that test list conditions +- When refactoring code that uses `length(list) > 0` or `length(list) == 0` +- Addressing Credo warnings about expensive `length/1` usage + +## Anti-Patterns (Avoid These) + +```elixir +# ❌ BAD: Expensive - traverses entire list +def fetch_block_consensus(block_hashes) when is_list(block_hashes) and length(block_hashes) > 0 do + # ... +end + +# ❌ BAD: Checks length unnecessarily +if length(list) == 0 do + [] +else + process(list) +end + +# ❌ BAD: Expensive guard +def process(items) when length(items) > 0 do + # ... +end +``` + +## Best Practices (Use These) + +```elixir +# ✅ GOOD: Pattern matching - O(1) operation +def fetch_block_consensus([]), do: %{} +def fetch_block_consensus(block_hashes) when is_list(block_hashes) do + # ... +end + +# ✅ GOOD: Direct comparison with empty list +if list == [] do + [] +else + process(list) +end + +# ✅ GOOD: Pattern matching in function head +def process([]), do: :empty +def process([_head | _tail] = items) do + # Has at least one element +end + +# ✅ GOOD: Using Enum.empty?/1 for clarity +if Enum.empty?(list) do + [] +else + process(list) +end +``` + +## Example Fix + +### Before (Expensive): +```elixir +def fetch_block_consensus(block_hashes) when is_list(block_hashes) and length(block_hashes) > 0 do + __MODULE__ + |> where([b], b.hash in ^block_hashes) + |> select([b], {b.hash, b.consensus}) + |> Repo.all() + |> Map.new() +end + +def fetch_block_consensus(_), do: %{} +``` + +### After (Optimized): +```elixir +def fetch_block_consensus([]), do: %{} +def fetch_block_consensus(block_hashes) when is_list(block_hashes) do + __MODULE__ + |> where([b], b.hash in ^block_hashes) + |> select([b], {b.hash, b.consensus}) + |> Repo.all() + |> Map.new() +end +``` + +## Performance Comparison + +| Operation | Time Complexity | Description | +|-----------|----------------|-------------| +| `length(list) > 0` | O(n) | Traverses entire list | +| `list == []` | O(1) | Immediate comparison | +| `[_ \| _] = list` | O(1) | Pattern match first element | +| `Enum.empty?(enumerable)` | O(1) for lists; short-circuits for many enumerables | May evaluate enumerable until first element; can trigger side effects | + +## Common Use Cases + +### 1. Guard Clauses +```elixir +# ✅ Use pattern matching +def process([]), do: :empty +def process(list) when is_list(list), do: do_work(list) +``` + +### 2. Conditional Logic +```elixir +# ✅ Compare with empty list +case items do + [] -> :no_items + [single] -> {:single, single} + many -> {:many, many} +end +``` + +### 3. Function Arguments Validation +```elixir +# ✅ Multiple function clauses +def validate([]), do: {:error, :empty} +def validate(list) when is_list(list), do: {:ok, list} +``` + +## Key Takeaways + +- **Never use `length(list)` just to check emptiness** - it's O(n) operation +- **Pattern matching is your friend** - it's O(1) and idiomatic Elixir +- **Use `== []` or `!= []`** for explicit empty checks +- **`Enum.empty?/1` is acceptable** - it's optimized and readable +- **Credo will warn you** - take these warnings seriously for performance + +## Related Credo Rules + +- `Credo.Check.Refactor.LengthForEmptyCheck` +- `Credo.Check.Warning.ExpensiveEmptyEnumCheck` \ No newline at end of file diff --git a/.agents/skills/compile-project/SKILL.md b/.agents/skills/compile-project/SKILL.md new file mode 100644 index 000000000000..4eebd699c765 --- /dev/null +++ b/.agents/skills/compile-project/SKILL.md @@ -0,0 +1,208 @@ +--- +name: compile-project +description: Compile the Blockscout Elixir project to verify all dependencies and code changes work correctly. Use this skill before finalizing changes to ensure the project builds successfully without errors. +--- + +## Overview + +The compile-project skill ensures that all Elixir code, dependencies, and configurations in the Blockscout project compile successfully. This is a critical verification step before committing changes or submitting pull requests. + +## When to Use + +- **Before committing code changes** - Verify your changes don't break compilation +- **After modifying dependencies** - Ensure all deps resolve correctly +- **After significant refactoring** - Validate code structure changes +- **Before creating a pull request** - Final verification that everything builds +- **After pulling updates** - Ensure your local environment is in sync +- **When fixing compilation errors** - Iterative testing during debugging +- **After adding new modules or functions** - Verify project-wide compatibility + +## How to Compile + +Run the following command from the workspace root: + +```bash +mix do deps.get, local.hex --force, local.rebar --force, deps.compile, compile +``` + +### Command Breakdown + +1. **`mix do`** - Executes multiple Mix tasks in sequence +2. **`deps.get`** - Fetches all project dependencies from Hex and Git +3. **`local.hex --force`** - Installs/updates Hex (package manager), forcing reinstall +4. **`local.rebar --force`** - Installs/updates Rebar (Erlang build tool), forcing reinstall +5. **`deps.compile`** - Compiles all dependencies +6. **`compile`** - Compiles the project itself + +### Dependencies-Only Compilation + +If you only need to compile dependencies without the project code: + +```bash +mix do deps.get, local.hex --force, local.rebar --force, deps.compile +``` + +## Example Usage + +### After Making Code Changes + +```bash +mix do deps.get, local.hex --force, local.rebar --force, deps.compile, compile +``` + +### Expected Output + +Successful compilation will show: +``` +* Getting dependencies... +* Compiling dependencies... +==> dependency_name +Compiling X files (.ex) +Generated dependency_name app +... +==> blockscout +Compiling X files (.ex) +Generated blockscout app +``` + +### Common Errors and Solutions + +#### 1. Dependency Lock Mismatch +``` +** (Mix) You have changed mix.exs but mix.lock is out of date +``` +**Solution:** +```bash +mix deps.get +``` + +#### 2. Stale Build Artifacts +``` +** (CompileError) cannot compile dependency +``` +**Solution:** +```bash +mix deps.clean --all +mix do deps.get, local.hex --force, local.rebar --force, deps.compile, compile +``` + +#### 3. Compilation Warnings +``` +warning: variable "foo" is unused +``` +**Action:** Fix unused variables or prefix with underscore `_foo` + +## Integration with Development Workflow + +### Recommended Pre-Commit Checklist + +1. ✅ Run `mix format` - Fix formatting issues +2. ✅ Run `mix do deps.get, local.hex --force, local.rebar --force, deps.compile, compile` - Verify compilation +3. ✅ Run `mix test` - Execute test suite (if applicable) +4. ✅ Run `mix credo` - Check code quality (if available) +5. ✅ Review git diff - Confirm changes are intentional +6. ✅ Commit and push + +### Quick Verification After Changes + +```bash +# Format, compile, and verify in one go +mix format && mix do deps.get, local.hex --force, local.rebar --force, deps.compile, compile +``` + +## Performance Notes + +- **First compilation**: Can take several minutes (downloads and compiles all dependencies) +- **Incremental compilation**: Usually seconds to minutes (only changed files) +- **Clean compilation**: Use `mix clean` or `mix deps.clean --all` when needed +- **Parallel compilation**: Mix automatically uses available CPU cores + +## When Compilation Warnings Are Acceptable + +Some warnings may be acceptable in certain contexts: +- **TODO comments** - Tracked technical debt +- **Unused variables in generated code** - Auto-generated functions +- **Module redefinition warnings** - Configuration loading order (like ConfigHelper) + +However, new code should aim for **zero warnings**. + +## Troubleshooting + +### Dependencies Won't Compile + +```bash +# Nuclear option: clean everything and start fresh +rm -rf _build deps +mix do deps.get, local.hex --force, local.rebar --force, deps.compile, compile +``` + +### Erlang/Elixir Version Mismatch + +Check required versions in `mix.exs`: +```elixir +def project do + [ + elixir: "~> 1.19", + # ... + ] +end +``` + +Verify your versions: +```bash +elixir --version +``` + +### Permission Issues with Rebar + +If `mix local.rebar --force` fails with permission errors, ensure proper ownership and permissions: + +```bash +# Fix ownership of Mix home directory +chown -R $(whoami) ~/.mix ~/.hex $MIX_HOME $HEX_HOME 2>/dev/null || true + +# Or explicitly set Mix/Hex home directories if needed +export MIX_HOME=~/.mix +export HEX_HOME=~/.hex + +# Then try again +mix local.rebar --force +``` + +**Note:** Running Mix as root (with `sudo`) is **strongly discouraged** as it commonly causes permission/ownership issues in `_build`, `deps`, and `~/.mix`. It can also create security/operational risks. Use proper file ownership and environment variables instead. + +## CI/CD Integration + +This compilation step is typically part of the CI/CD pipeline. Ensure your changes pass locally before pushing to avoid CI failures. + +## Related Skills + +- **code-formatting** - Format code before compilation +- **compare-against-empty-list** - Fix performance issues that might surface during compilation + +## Key Takeaways + +- **Always compile before committing** - Catch errors early +- **Use the full command** - Ensures dependencies are up-to-date +- **Monitor compilation warnings** - They often indicate real issues +- **Clean builds when in doubt** - Removes stale artifacts +- **Compilation success ≠ correctness** - Still need tests and manual verification +- **Fast feedback loop** - Run frequently during development +- **Avoid running Mix as root** - Use proper permissions instead + +## Additional Commands + +### Check for unused dependencies +```bash +mix deps.unlock --unused +``` + +### View dependency tree +```bash +mix deps.tree +``` + +### Compile with warnings as errors (strict mode) +```bash +mix compile --warnings-as-errors +``` diff --git a/.agents/skills/ecto-migration/SKILL.md b/.agents/skills/ecto-migration/SKILL.md new file mode 100644 index 000000000000..69f18d253cb7 --- /dev/null +++ b/.agents/skills/ecto-migration/SKILL.md @@ -0,0 +1,68 @@ +--- +name: ecto-migration +description: Generates Ecto migrations for the Blockscout Elixir project using mix ecto.gen.migration command. Use when you need to create database schema changes, add tables, modify columns, or manage database structure. +--- + +## Overview + +The ecto-migration skill generates new Ecto migration files for the Blockscout project using the Mix task. Migrations are used to evolve the database schema over time in a versioned and controlled manner. + +## When to Use + +- When creating new database tables +- When modifying existing table structures (add/remove/change columns) +- When adding or removing database indexes +- When performing data migrations or transformations +- When implementing database constraints or relationships + +## How to Apply + +Run the following command from the workspace root: + +```bash +mix ecto.gen.migration [migration_name] -r Explorer.Repo +``` + +Replace `[migration_name]` with a descriptive name for your migration using snake_case (e.g., `add_users_table`, `alter_transactions_status`). + +## What It Does + +- Creates a new migration file in `apps/explorer/priv/repo/migrations/` directory +- Generates a timestamped filename to ensure proper ordering +- Provides a basic migration template with `change/0` or `up/0` and `down/0` functions +- Targets the `Explorer.Repo` repository specifically + +## Example Usage + +Generate a migration to add a new column: + +```bash +mix ecto.gen.migration add_metadata_to_blocks -r Explorer.Repo +``` + +This creates a file like: +- `apps/explorer/priv/repo/migrations/20260220123456_add_metadata_to_blocks.exs` + +Then edit the generated file to implement your schema changes: + +```elixir +defmodule Explorer.Repo.Migrations.AddMetadataToBlocks do + use Ecto.Migration + + def change do + alter table(:blocks) do + add :metadata, :jsonb + end + end +end +``` + +## Notes + +- Always use descriptive migration names +- The `-r Explorer.Repo` flag specifies the repository (required for umbrella apps) +- Migration files are timestamped automatically to maintain order +- After creating a migration, edit it to implement the actual schema changes +- Run `mix ecto.migrate` to apply the migration to your database +- Use `mix ecto.rollback` to revert the last migration if needed +- For complex operations, consider using `up/0` and `down/0` instead of `change/0` diff --git a/.agents/skills/efficient-list-building/SKILL.md b/.agents/skills/efficient-list-building/SKILL.md new file mode 100644 index 000000000000..4503c80f1af4 --- /dev/null +++ b/.agents/skills/efficient-list-building/SKILL.md @@ -0,0 +1,234 @@ +--- +name: efficient-list-building +description: Build lists efficiently using prepend operations and Enum.reverse/1 instead of append. Appending to lists is O(n) while prepending is O(1). Use [head | tail] notation and reverse at the end when order matters. +--- + +## Overview + +In Elixir (and Erlang), appending to a list using `++` is an expensive O(n) operation because it requires traversing the entire left list. Prepending using `[head | tail]` is O(1) and much more efficient. When building lists in a specific order, prepend elements and call `Enum.reverse/1` once at the end. + +## When to Use + +- When accumulating results in `Enum.reduce/3` or recursive functions +- When building lists incrementally in loops or iterations +- When order matters but you're currently appending one item at a time +- When Credo warns: "Appending a single item to a list is inefficient" +- When refactoring code with performance bottlenecks in list building + +## Anti-Patterns (Avoid These) + +```elixir +# ❌ BAD: O(n) append operation in each iteration +Enum.reduce(items, [], fn item, acc -> + acc ++ [process(item)] +end) + +# ❌ BAD: Expensive in a reduce - O(n) for each append +Enum.reduce(block_ranges, {[], []}, fn range, {parts, params} -> + {[part | parts], params ++ [value1, value2]} +end) + +# ❌ BAD: Multiple appends in recursion +def build_list([head | tail], acc) do + build_list(tail, acc ++ [transform(head)]) +end +def build_list([], acc), do: acc + +# ❌ BAD: Binary string concatenation with ++ +# ++ is for lists (charlists), not binaries like "" +Enum.reduce(fragments, "", fn frag, acc -> + acc ++ frag +end) +``` + +## Best Practices (Use These) + +```elixir +# ✅ GOOD: O(1) prepend + O(n) reverse once at the end +items +|> Enum.reduce([], fn item, acc -> + [process(item) | acc] +end) +|> Enum.reverse() + +# ✅ GOOD: Prepend params in reverse order, then reverse once +Enum.reduce(block_ranges, {[], []}, fn range, {parts, params} -> + {[part | parts], [value2, value1 | params]} +end) +|> then(fn {parts, params} -> {Enum.reverse(parts), Enum.reverse(params)} end) + +# ✅ GOOD: Prepend in recursion, reverse at top level +defp build_list_helper([head | tail], acc) do + build_list_helper(tail, [transform(head) | acc]) +end +defp build_list_helper([], acc), do: acc + +def build_list(items) do + items + |> build_list_helper([]) + |> Enum.reverse() +end + +# ✅ GOOD: Use IO lists for binary/string building +# Prepend fragments, then convert to binary (proper iolist structure) +fragments +|> Enum.reduce([], fn frag, acc -> [frag | acc] end) +|> Enum.reverse() +|> IO.iodata_to_binary() + +# ✅ GOOD: Binary concatenation with <> +Enum.reduce(fragments, "", fn frag, acc -> + acc <> frag +end) +``` + +## Example Fix + +### Before (Inefficient): +```elixir +{sql_parts, params} = + Enum.reduce(block_ranges, {[], []}, fn + first..last//_, {parts, acc_params} -> + from = min(first, last) + to = max(first, last) + part = "SELECT * FROM generate_series($1, $2)" + + # O(n) append for each iteration + {[part | parts], acc_params ++ [from, to]} + end) + +# sql_parts already reversed, but params not +use_query(sql_parts |> Enum.reverse(), params) +``` + +### After (Optimized): +```elixir +{sql_parts, params} = + Enum.reduce(block_ranges, {[], []}, fn + first..last//_, {parts, acc_params} -> + from = min(first, last) + to = max(first, last) + part = "SELECT * FROM generate_series($1, $2)" + + # O(1) prepend (note reverse order: to, from) + {[part | parts], [to, from | acc_params]} + end) + +# Both need reversing now - but only once, not in every iteration +use_query(Enum.reverse(sql_parts), Enum.reverse(params)) +``` + +## Performance Comparison + +| Operation | Time Complexity | Description | +|-----------|-----------------|-------------| +| `list ++ [item]` | O(n) | Traverses entire left list to append | +| `[item \| list]` | O(1) | Prepends without traversal | +| `Enum.reverse(list)` | O(n) | Single traversal at the end | + +### Total Cost Example + +**Building a 1000-item list:** +- Appending in loop: O(1) + O(2) + O(3) + ... + O(1000) = **O(n²)** ≈ 500,000 operations +- Prepending + reverse: O(1) × 1000 + O(1000) = **O(n)** ≈ 2,000 operations + +The prepend approach is **~250x faster** for 1000 items! + +## Common Scenarios + +### Accumulating in Reduce + +```elixir +# ❌ BAD +numbers |> Enum.reduce([], fn n, acc -> acc ++ [n * 2] end) + +# ✅ GOOD +numbers +|> Enum.reduce([], fn n, acc -> [n * 2 | acc] end) +|> Enum.reverse() +``` + +### Building Multiple Lists + +```elixir +# ❌ BAD +Enum.reduce(items, {[], []}, fn item, {list1, list2} -> + {list1 ++ [process1(item)], list2 ++ [process2(item)]} +end) + +# ✅ GOOD +items +|> Enum.reduce({[], []}, fn item, {list1, list2} -> + {[process1(item) | list1], [process2(item) | list2]} +end) +|> then(fn {list1, list2} -> {Enum.reverse(list1), Enum.reverse(list2)} end) +``` + +### Recursive List Building + +```elixir +# ❌ BAD +def recursive_build([h | t], acc), do: recursive_build(t, acc ++ [transform(h)]) +def recursive_build([], acc), do: acc + +# ✅ GOOD +def recursive_build(list), do: recursive_build_helper(list, []) |> Enum.reverse() + +defp recursive_build_helper([h | t], acc), do: recursive_build_helper(t, [transform(h) | acc]) +defp recursive_build_helper([], acc), do: acc +``` + +### String/Binary Building + +```elixir +# ❌ BAD: ++ doesn't work for binaries, only lists +fragments |> Enum.reduce("", fn frag, acc -> acc ++ frag end) + +# ✅ GOOD: Use <> for binaries +fragments |> Enum.reduce("", fn frag, acc -> acc <> frag end) + +# ✅ BETTER: Use IO lists (more efficient for many fragments) +fragments +|> Enum.reduce([], fn frag, acc -> [frag | acc] end) +|> Enum.reverse() +|> IO.iodata_to_binary() +``` + +## Important Note on iolist Structure + +When building IO lists (used for efficient binary/string construction), ensure proper structure: + +```elixir +# ❌ WRONG: [acc | frag] doesn't create a proper iolist +# This conses acc as the head with frag as the tail - fails when frag is binary +Enum.reduce(fragments, [], fn frag, acc -> [acc | frag] end) + +# ✅ CORRECT: [frag | acc] - proper cons structure +# Then reverse to get correct order or use Enum.reverse() +Enum.reduce(fragments, [], fn frag, acc -> [frag | acc] end) +|> Enum.reverse() +|> IO.iodata_to_binary() +``` + +## Notes + +- If order doesn't matter, you can skip `Enum.reverse/1` entirely +- For string/binary building, `<>` works but can be O(n²) in a loop; IO lists are better +- `Enum.map/2` already handles this efficiently internally +- When prepending multiple items, add them in reverse order: `[item2, item1 | acc]` + +## Tools and Warnings + +**Credo Warning:** +``` +Appending a single item to a list is inefficient, use `[head | tail]` +notation (and `Enum.reverse/1` when order matters). +``` + +**Fix:** Replace `list ++ [item]` with `[item | list]` and add `Enum.reverse/1` at the end if order matters. + +## References + +- [Elixir List documentation](https://hexdocs.pm/elixir/List.html) +- [Kernel.++/2 performance characteristics](https://hexdocs.pm/elixir/Kernel.html#++/2) +- [Efficient list building in functional languages](https://learnyousomeerlang.com/starting-out-for-real#lists) diff --git a/.agents/skills/elixir-clause-grouping/SKILL.md b/.agents/skills/elixir-clause-grouping/SKILL.md new file mode 100644 index 000000000000..3042f6d60a20 --- /dev/null +++ b/.agents/skills/elixir-clause-grouping/SKILL.md @@ -0,0 +1,66 @@ +--- +name: elixir-clause-grouping +description: Use when refactoring Elixir multi-clause functions, extracting helper functions, or fixing Credo readability warnings caused by placing `defp` helpers between clauses of the same function. Keeps function clauses contiguous and moves helpers below the full clause group. +--- + +## Overview + +In Elixir modules, all clauses of the same function should stay together. Inserting a `defp` helper between clauses of a `def` or `defp` makes the function harder to read and can trigger Credo readability warnings. When shared logic needs to be extracted, keep the original clause group contiguous and place the helper after the full group. + +## When to Use + +- When refactoring a multi-clause `def` or `defp` +- When extracting duplicated logic from multiple function clauses +- When addressing Credo warnings about clause grouping or readability +- When editing controller, view, or context modules with several clauses of the same function +- During review when a helper was added in the middle of another function's clauses + +## Core Rule + +- Keep all clauses of the same function contiguous +- Do not place `defp` helpers between clauses of another function +- Extract shared logic into a helper placed after the full clause group + +## Anti-Pattern + +```elixir +def decoded_input_data(%Transaction{to_address: nil}, _, _, _, _), do: {:error, :no_to_address} + +defp decode_input_data_with_fallback(data, abi, input, hash, skip_sig_provider?, options, methods_map, abi_map) do + ... +end + +def decoded_input_data(%Transaction{to_address: %NotLoaded{}}, _, _, _, _), do: {:error, :contract_not_verified, []} +``` + +This splits the `decoded_input_data/5` clause group and makes the function harder to scan. + +## Preferred Pattern + +```elixir +def decoded_input_data(%Transaction{to_address: nil}, _, _, _, _), do: {:error, :no_to_address} + +def decoded_input_data(%Transaction{to_address: %NotLoaded{}}, _, _, _, _), do: {:error, :contract_not_verified, []} + +def decoded_input_data(%Transaction{to_address: %{smart_contract: smart_contract}} = transaction, skip_sig_provider?, options, methods_map, abi_map) do + ... +end + +defp decode_input_data_with_fallback(data, abi, input, hash, skip_sig_provider?, options, methods_map, abi_map) do + ... +end +``` + +## Refactoring Checklist + +1. Identify every clause of the function being edited. +2. Keep those clauses adjacent to each other. +3. Extract shared logic only after the full clause group. +4. Re-check that no unrelated `def` or `defp` appears inside the group. +5. Run formatting after the refactor. + +## Notes + +- This applies to both public and private multi-clause functions. +- If a helper is only used by one clause group, place it immediately after that group. +- Preserving clause grouping is preferred even when the extracted helper is small. \ No newline at end of file diff --git a/.agents/skills/elixir-credo-predicate-naming/SKILL.md b/.agents/skills/elixir-credo-predicate-naming/SKILL.md new file mode 100644 index 000000000000..1db47e184700 --- /dev/null +++ b/.agents/skills/elixir-credo-predicate-naming/SKILL.md @@ -0,0 +1,46 @@ +--- +name: elixir-credo-predicate-naming +description: "Use when working on Elixir code with Credo predicate naming warnings, boolean helper functions, or renaming functions that start with is_. Prevents violations like: Predicate function names should not start with 'is' and should end in a question mark." +--- + +# Elixir Credo Predicate Naming + +Use this skill to prevent and fix predicate naming violations in Elixir. + +## Rules + +- Predicate functions must end with `?`. +- Predicate functions must not start with `is_`. +- Prefer names like `valid_*?`, `enabled_*?`, `has_*?`, `can_*?`, `matches_*?`, or `_*?`. + +## Refactor Workflow + +1. Find predicate functions named like `is_*?`. +2. Rename each one to a Credo-compliant name that still reads clearly. +3. Update all call sites in the same module and across the codebase. +4. Keep arity unchanged unless behavior intentionally changes. +5. Run a focused Credo check for edited files. + +## Naming Guidance + +- `is_valid_zrc2_transfer_log?/4` -> `valid_zrc2_transfer_log?/4` +- `is_enabled?/1` -> `enabled?/1` +- `is_erc20_transfer?/2` -> `erc20_transfer?/2` +- `is_contract_verified?/1` -> `contract_verified?/1` + +## Safety Checks + +- Preserve semantics during rename. +- Verify no stale references remain. +- If the function is part of a public API, rename consistently and update docs/specs. + +## Verification Commands + +```bash +mix credo path/to/file.ex +mix test +``` + +## Expected Result + +No Credo findings for predicate naming in updated files. diff --git a/.agents/skills/heavy-db-index-operation/SKILL.md b/.agents/skills/heavy-db-index-operation/SKILL.md new file mode 100644 index 000000000000..94e7f24710fb --- /dev/null +++ b/.agents/skills/heavy-db-index-operation/SKILL.md @@ -0,0 +1,630 @@ +--- +name: heavy-db-index-operation +description: Generate background migration modules for creating, dropping, or renaming database indexes on large tables using the Explorer.Migrator.HeavyDbIndexOperation framework. Automatically updates the BackgroundMigrations cache module with proper tracking. These migrations run in the background with progress tracking and dependency management. Use this skill for requests on creating background migrations to delete / create / rename indexes on large tables (logs, internal_transactions, token_transfers, addresses, transactions, blocks, etc.) to avoid blocking the database. +--- + +## Overview + +The heavy-db-index-operation skill helps you generate migration modules that create, drop, or rename database indexes on large tables in a controlled, non-blocking manner. These operations use the `Explorer.Migrator.HeavyDbIndexOperation` behavior and are tracked via `Explorer.Migrator.MigrationStatus`. + +**What this skill generates:** +1. Migration module files (create/drop/rename) in `apps/explorer/lib/explorer/migrator/heavy_db_index_operation/` +2. Updates to `apps/explorer/lib/explorer/chain/cache/background_migrations.ex`: + - Cache keys for tracking completion status + - Module aliases + - Fallback handlers for cache population + +## When to Use + +- When creating new indexes on large tables (logs, internal_transactions, token_transfers, addresses, transactions, blocks, etc.) +- When dropping existing indexes as part of schema optimization +- When renaming indexes (typically as the final step in a create → drop → rename workflow) +- When the index operation might take significant time and should run in the background +- When you need to track the progress of index creation/deletion/rename +- When index operations need to depend on other completed migrations +- When you want CONCURRENT index operations on PostgreSQL + +## Module Structure + +Each heavy index operation module must implement the `Explorer.Migrator.HeavyDbIndexOperation` behavior with these callbacks: + +### Required Callbacks + +1. **`migration_name/0`** - Automatically generated from `operation_type` and `index_name`. Format: `heavy_indexes_{operation_type}_{lowercase_index_name}` +2. **`table_name/0`** - Returns the table atom (`:logs`, `:internal_transactions`, `:addresses`, etc.) +3. **`operation_type/0`** - Returns `:create`, `:drop`, or `:rename` +4. **`index_name/0`** - Returns the index name as a string (for renames, return the final/new index name) +5. **`dependent_from_migrations/0`** - Returns list of migration names this depends on (or `[]`) +6. **`db_index_operation/0`** - Executes the actual index creation/deletion/rename +7. **`check_db_index_operation_progress/0`** - Checks operation progress +8. **`db_index_operation_status/0`** - Returns operation status +9. **`restart_db_index_operation/0`** - Restarts the operation if needed +10. **`running_other_heavy_migration_exists?/1`** - Checks for conflicting migrations +11. **`update_cache/0`** - Updates the BackgroundMigrations cache when migration completes + +## Index Definition Methods + +### Method 1: Using `@table_columns` (Simple Indexes) + +Use this for straightforward indexes on one or more columns: + +```elixir +@table_columns ["address_hash", "block_number DESC", "index DESC"] + +@impl HeavyDbIndexOperation +def db_index_operation do + HeavyDbIndexOperationHelper.create_db_index(@index_name, @table_name, @table_columns) +end +``` + +**When to use:** +- Simple multi-column indexes +- No WHERE clause needed +- Standard column ordering acceptable +- Most common use case + +### Method 2: Using `@query_string` (Complex Indexes) + +Use this for more complex index definitions: + +```elixir +@query_string """ +CREATE INDEX #{HeavyDbIndexOperationHelper.add_concurrently_flag?()} IF NOT EXISTS "#{@index_name}" +ON #{@table_name} ((1)) +WHERE verified = true; +""" + +@impl HeavyDbIndexOperation +def db_index_operation do + HeavyDbIndexOperationHelper.create_db_index(@query_string) +end +``` + +**When to use:** +- Partial indexes (with WHERE clause) +- Expression indexes (e.g., `((1))` for existence check) +- Custom index types (GIN, GIST, etc.) +- Fine-grained control over SQL + +## Naming Conventions + +### Module Names + +- **Creation**: `CreateTableNameColumnNameIndex` + - Example: `CreateLogsAddressHashBlockNumberDescIndexDescIndex` + - Example: `CreateAddressesVerifiedIndex` + +- **Deletion**: `DropTableNameIndexName` + - Example: `DropInternalTransactionsCreatedContractAddressHashPartialIndex` + - Example: `DropLogsAddressHashIndex` + +- **Renaming**: `RenameOldIndexNameToNewIndexName` or `RenameTableNameIndexDescriptor` + - Example: `RenameTransactions2ndCreatedContractAddressHashWithPendingIndexA` + +### Index Names + +- Follow PostgreSQL naming: `table_name_column_name_suffix_index` +- For partial indexes: include `_partial` in the name +- For descending columns: include `_desc` in the name +- Examples: + - `logs_address_hash_block_number_DESC_index_DESC_index` + - `addresses_verified_index` + - `internal_transactions_created_contract_address_hash_partial_index` + +### File Names + +- Convert module name to snake_case +- Example: `CreateLogsAddressHashIndex` → `create_logs_address_hash_index.ex` + +## Dependencies via `dependent_from_migrations/0` + +Specify migrations that must complete before this one runs: + +```elixir +# No dependencies +@impl HeavyDbIndexOperation +def dependent_from_migrations, do: [] + +# Depends on another migration +alias Explorer.Migrator.EmptyInternalTransactionsData + +@impl HeavyDbIndexOperation +def dependent_from_migrations do + [EmptyInternalTransactionsData.migration_name()] +end + +# Multiple dependencies +alias Explorer.Migrator.HeavyDbIndexOperation.{ + DropLogsIndexIndex, + DropLogsBlockNumberAscIndexAscIndex +} + +@impl HeavyDbIndexOperation +def dependent_from_migrations do + [ + DropLogsIndexIndex.migration_name(), + DropLogsBlockNumberAscIndexAscIndex.migration_name() + ] +end +``` + +## Complete Example: Creating an Index + +```elixir +defmodule Explorer.Migrator.HeavyDbIndexOperation.CreateLogsAddressHashBlockNumberDescIndexDescIndex do + @moduledoc """ + Create B-tree index `logs_address_hash_block_number_DESC_index_DESC_index` on `logs` table + for (`address_hash`, `block_number DESC`, `index DESC`) columns. + """ + + use Explorer.Migrator.HeavyDbIndexOperation + + require Logger + + alias Explorer.Chain.Cache.BackgroundMigrations + alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} + alias Explorer.Migrator.HeavyDbIndexOperation.Helper, as: HeavyDbIndexOperationHelper + + @table_name :logs + @index_name "logs_address_hash_block_number_DESC_index_DESC_index" + @operation_type :create + @table_columns ["address_hash", "block_number DESC", "index DESC"] + + @impl HeavyDbIndexOperation + def table_name, do: @table_name + + @impl HeavyDbIndexOperation + def operation_type, do: @operation_type + + @impl HeavyDbIndexOperation + def index_name, do: @index_name + + @impl HeavyDbIndexOperation + def dependent_from_migrations, do: [] + + @impl HeavyDbIndexOperation + def db_index_operation do + HeavyDbIndexOperationHelper.create_db_index(@index_name, @table_name, @table_columns) + end + + @impl HeavyDbIndexOperation + def check_db_index_operation_progress do + operation = HeavyDbIndexOperationHelper.create_index_query_string(@index_name, @table_name, @table_columns) + HeavyDbIndexOperationHelper.check_db_index_operation_progress(@index_name, operation) + end + + @impl HeavyDbIndexOperation + def db_index_operation_status do + HeavyDbIndexOperationHelper.db_index_creation_status(@index_name) + end + + @impl HeavyDbIndexOperation + def restart_db_index_operation do + HeavyDbIndexOperationHelper.safely_drop_db_index(@index_name) + end + + @impl HeavyDbIndexOperation + def running_other_heavy_migration_exists?(migration_name) do + MigrationStatus.running_other_heavy_migration_for_table_exists?(@table_name, migration_name) + end + + @impl HeavyDbIndexOperation + def update_cache do + BackgroundMigrations.set_heavy_indexes_create_logs_address_hash_block_number_desc_index_desc_index_finished( + true + ) + end +end +``` + +## Complete Example: Dropping an Index + +```elixir +defmodule Explorer.Migrator.HeavyDbIndexOperation.DropInternalTransactionsCreatedContractAddressHashPartialIndex do + @moduledoc """ + Drops index "internal_transactions_created_contract_address_hash_partial_index" on + internal_transactions(created_contract_address_hash, block_number DESC, transaction_index DESC, index DESC). + """ + + use Explorer.Migrator.HeavyDbIndexOperation + + alias Explorer.Chain.Cache.BackgroundMigrations + alias Explorer.Migrator.{EmptyInternalTransactionsData, HeavyDbIndexOperation, MigrationStatus} + alias Explorer.Migrator.HeavyDbIndexOperation.Helper, as: HeavyDbIndexOperationHelper + + @table_name :internal_transactions + @index_name "internal_transactions_created_contract_address_hash_partial_index" + @operation_type :drop + + @impl HeavyDbIndexOperation + def table_name, do: @table_name + + @impl HeavyDbIndexOperation + def operation_type, do: @operation_type + + @impl HeavyDbIndexOperation + def index_name, do: @index_name + + @impl HeavyDbIndexOperation + def dependent_from_migrations do + [EmptyInternalTransactionsData.migration_name()] + end + + @impl HeavyDbIndexOperation + def db_index_operation do + HeavyDbIndexOperationHelper.safely_drop_db_index(@index_name) + end + + @impl HeavyDbIndexOperation + def check_db_index_operation_progress do + operation = HeavyDbIndexOperationHelper.drop_index_query_string(@index_name) + HeavyDbIndexOperationHelper.check_db_index_operation_progress(@index_name, operation) + end + + @impl HeavyDbIndexOperation + def db_index_operation_status do + HeavyDbIndexOperationHelper.db_index_dropping_status(@index_name) + end + + @impl HeavyDbIndexOperation + def restart_db_index_operation do + HeavyDbIndexOperationHelper.safely_drop_db_index(@index_name) + end + + @impl HeavyDbIndexOperation + def running_other_heavy_migration_exists?(migration_name) do + MigrationStatus.running_other_heavy_migration_for_table_exists?(@table_name, migration_name) + end + + @impl HeavyDbIndexOperation + def update_cache do + BackgroundMigrations.set_heavy_indexes_drop_internal_transactions_created_contract_address_hash_partial_index_finished( + true + ) + end +end +``` + +## Supported Table Names + +Valid values for `@table_name` (from behavior typespec): + +- `:addresses` +- `:address_coin_balances` +- `:address_current_token_balances` +- `:address_token_balances` +- `:blocks` +- `:internal_transactions` +- `:logs` +- `:token_transfers` +- `:tokens` +- `:transactions` + +## File Location + +All generated modules must be placed in: + +``` +apps/explorer/lib/explorer/migrator/heavy_db_index_operation/ +``` + +## Required Aliases + +Standard aliases to include: + +```elixir +alias Explorer.Chain.Cache.BackgroundMigrations +alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} +alias Explorer.Migrator.HeavyDbIndexOperation.Helper, as: HeavyDbIndexOperationHelper +``` + +For dependencies, add specific aliases: + +```elixir +alias Explorer.Migrator.EmptyInternalTransactionsData +``` + +## Helper Functions Available + +### For Index Creation: + +- `HeavyDbIndexOperationHelper.create_db_index/1` - With query string +- `HeavyDbIndexOperationHelper.create_db_index/3` - With index name, table, columns +- `HeavyDbIndexOperationHelper.create_index_query_string/3` - Generate query string +- `HeavyDbIndexOperationHelper.db_index_creation_status/1` - Check creation status +- `HeavyDbIndexOperationHelper.add_concurrently_flag?/0` - For CONCURRENT keyword + +### For Index Deletion: + +- `HeavyDbIndexOperationHelper.safely_drop_db_index/1` - Drop with safety checks +- `HeavyDbIndexOperationHelper.drop_index_query_string/1` - Generate drop query +- `HeavyDbIndexOperationHelper.db_index_dropping_status/1` - Check dropping status + +### Common: + +- `HeavyDbIndexOperationHelper.check_db_index_operation_progress/2` - Monitor progress + +## Cache Invalidation + +When dropping indexes, you may need to invalidate caches as shown in the module docstring: + +```elixir +@impl HeavyDbIndexOperation +def restart_db_index_operation do + HeavyDbIndexOperationHelper.safely_drop_db_index(@index_name) + BackgroundMigrations.invalidate_cache(__MODULE__.migration_name()) +end +``` + +## Complete Example: Renaming an Index + +For rename operations (typically used after create + drop to swap indexes): + +```elixir +defmodule Explorer.Migrator.HeavyDbIndexOperation.RenameTransactions2ndCreatedContractAddressHashWithPendingIndexA do + @moduledoc """ + Renames index "transactions_2nd_created_contract_address_hash_with_pending_index_a" + to "transactions_created_contract_address_hash_with_pending_index_a". + """ + + use Explorer.Migrator.HeavyDbIndexOperation + + require Logger + + alias Explorer.Chain.Cache.BackgroundMigrations + alias Explorer.Migrator.{HeavyDbIndexOperation, MigrationStatus} + alias Explorer.Migrator.HeavyDbIndexOperation.Helper, as: HeavyDbIndexOperationHelper + alias Explorer.Migrator.HeavyDbIndexOperation.DropTransactionsCreatedContractAddressHashWithPendingIndexA + alias Explorer.Repo + + @table_name :transactions + @old_index_name "transactions_2nd_created_contract_address_hash_with_pending_index_a" + @new_index_name "transactions_created_contract_address_hash_with_pending_index_a" + @operation_type :rename + + # Note: migration_name will be: + # "heavy_indexes_rename_transactions_created_contract_address_hash_with_pending_index_a" + + @impl HeavyDbIndexOperation + def table_name, do: @table_name + + @impl HeavyDbIndexOperation + def operation_type, do: @operation_type + + @impl HeavyDbIndexOperation + def index_name, do: @new_index_name + + @impl HeavyDbIndexOperation + def dependent_from_migrations do + [DropTransactionsCreatedContractAddressHashWithPendingIndexA.migration_name()] + end + + @impl HeavyDbIndexOperation + # sobelow_skip ["SQL"] + def db_index_operation do + case Repo.query(rename_index_query_string(), [], timeout: :infinity) do + {:ok, _} -> + :ok + + {:error, error} -> + Logger.error("Failed to rename index from #{@old_index_name} to #{@new_index_name}: #{inspect(error)}") + :error + end + end + + @impl HeavyDbIndexOperation + def check_db_index_operation_progress do + HeavyDbIndexOperationHelper.check_db_index_operation_progress(@new_index_name, rename_index_query_string()) + end + + @impl HeavyDbIndexOperation + def db_index_operation_status do + old_index_status = HeavyDbIndexOperationHelper.db_index_exists_and_valid?(@old_index_name) + new_index_status = HeavyDbIndexOperationHelper.db_index_exists_and_valid?(@new_index_name) + + cond do + # Rename completed: old index doesn't exist, new index exists and is valid + old_index_status == %{exists?: false, valid?: nil} and new_index_status == %{exists?: true, valid?: true} -> + :completed + + # Rename not started: old index exists, new index doesn't exist + old_index_status == %{exists?: true, valid?: true} and new_index_status == %{exists?: false, valid?: nil} -> + :not_initialized + + # Unknown state + true -> + :unknown + end + end + + @impl HeavyDbIndexOperation + def restart_db_index_operation do + # To restart, we need to rename back to the old name + case Repo.query(reverse_rename_index_query_string(), [], timeout: :infinity) do + {:ok, _} -> + :ok + + {:error, error} -> + Logger.error("Failed to reverse rename index from #{@new_index_name} to #{@old_index_name}: #{inspect(error)}") + :error + end + end + + @impl HeavyDbIndexOperation + def running_other_heavy_migration_exists?(migration_name) do + MigrationStatus.running_other_heavy_migration_for_table_exists?(@table_name, migration_name) + end + + @impl HeavyDbIndexOperation + def update_cache do + BackgroundMigrations.set_heavy_indexes_rename_transactions_created_contract_address_hash_with_pending_index_a_finished( + true + ) + end + + defp rename_index_query_string do + "ALTER INDEX #{@old_index_name} RENAME TO #{@new_index_name};" + end + + defp reverse_rename_index_query_string do + "ALTER INDEX #{@new_index_name} RENAME TO #{@old_index_name};" + end +end +``` + +**When to use rename operations:** +- After creating a new index and dropping an old one +- To swap temporary index names with permanent ones +- Part of a create → drop → rename workflow for index replacement + +**Important notes for rename operations:** +- Use `@operation_type :rename` (not `:create`) +- `index_name/0` should return the **new** (final) index name +- The migration name will be `heavy_indexes_rename_{new_index_name_lowercase}` +- Example: For `index_name` = "transactions_created_contract_address_hash_with_pending_index_a", the migration name is "heavy_indexes_rename_transactions_created_contract_address_hash_with_pending_index_a" + +## Updating BackgroundMigrations Cache + +After creating migration modules, you must update the cache tracking in +`apps/explorer/lib/explorer/chain/cache/background_migrations.ex`: + +### Step 1: Add Cache Keys + +Add keys for each new migration at the top of the module: + +```elixir +use Explorer.Chain.MapCache, + name: :background_migrations_status, + # ... existing keys ... + key: :heavy_indexes_create_transactions_2nd_created_contract_address_hash_with_pending_index_a_finished, + key: :heavy_indexes_drop_transactions_created_contract_address_hash_with_pending_index_a_finished, + key: :heavy_indexes_rename_transactions_created_contract_address_hash_with_pending_index_a_finished +``` + +### Step 2: Add Module Aliases + +Add aliases in the `HeavyDbIndexOperation` alias block: + +```elixir +alias Explorer.Migrator.HeavyDbIndexOperation.{ + # ... existing aliases ... + CreateTransactions2ndCreatedContractAddressHashWithPendingIndexA, + DropTransactionsCreatedContractAddressHashWithPendingIndexA, + RenameTransactions2ndCreatedContractAddressHashWithPendingIndexA +} +``` + +### Step 3: Add Fallback Handlers + +Add `handle_fallback/1` functions for each migration: + +```elixir +defp handle_fallback(:heavy_indexes_create_transactions_2nd_created_contract_address_hash_with_pending_index_a_finished) do + set_and_return_migration_status( + CreateTransactions2ndCreatedContractAddressHashWithPendingIndexA, + &set_heavy_indexes_create_transactions_2nd_created_contract_address_hash_with_pending_index_a_finished/1 + ) +end + +defp handle_fallback(:heavy_indexes_drop_transactions_created_contract_address_hash_with_pending_index_a_finished) do + set_and_return_migration_status( + DropTransactionsCreatedContractAddressHashWithPendingIndexA, + &set_heavy_indexes_drop_transactions_created_contract_address_hash_with_pending_index_a_finished/1 + ) +end + +defp handle_fallback(:heavy_indexes_rename_transactions_created_contract_address_hash_with_pending_index_a_finished) do + set_and_return_migration_status( + RenameTransactions2ndCreatedContractAddressHashWithPendingIndexA, + &set_heavy_indexes_rename_transactions_created_contract_address_hash_with_pending_index_a_finished/1 + ) +end +``` + +**Cache key naming convention:** +- Format: `heavy_indexes_{operation}_{snake_case_index_name}_finished` +- Operation: `create`, `drop`, `rename`, etc. +- Always ends with `_finished` + +### Step 4: Add to Application Supervisor + +Add each migration module to the application supervisor in +`apps/explorer/lib/explorer/application.ex`: + +Find the section with other heavy DB index operations and add: + +```elixir +configure_mode_dependent_process( + Explorer.Migrator.HeavyDbIndexOperation.CreateTransactions2ndCreatedContractAddressHashWithPendingIndexA, + :indexer +), +configure_mode_dependent_process( + Explorer.Migrator.HeavyDbIndexOperation.DropTransactionsCreatedContractAddressHashWithPendingIndexA, + :indexer +), +configure_mode_dependent_process( + Explorer.Migrator.HeavyDbIndexOperation.RenameTransactions2ndCreatedContractAddressHashWithPendingIndexA, + :indexer +), +``` + +**Important:** These entries must be added to start the migration processes during application startup. + +## Update Cache Implementation + +Each migration module must implement `update_cache/0`: + +```elixir +@impl HeavyDbIndexOperation +def update_cache do + BackgroundMigrations.set_heavy_indexes_create_my_index_finished(true) +end +``` + +The setter function name follows: `set_heavy_indexes_{operation}_{index_name}_finished/1` + +## Checklist for New Modules + +- [ ] Module name follows `Create*/Drop*/Rename*` convention +- [ ] File name is snake_case version of module name +- [ ] `@moduledoc` describes the index and its columns +- [ ] `use Explorer.Migrator.HeavyDbIndexOperation` declared near module top +- [ ] All required callbacks implemented +- [ ] `@table_name`, `@index_name`, `@operation_type` module attributes defined +- [ ] Index definition uses `@table_columns` OR `@query_string` (or custom for rename) +- [ ] Dependencies specified via `dependent_from_migrations/0` +- [ ] Proper aliases added at module top +- [ ] File saved in `apps/explorer/lib/explorer/migrator/heavy_db_index_operation/` +- [ ] `update_cache/0` implemented with correct setter name +- [ ] **BackgroundMigrations cache updated** with key, alias, and fallback handler +- [ ] **Application.ex updated** with `configure_mode_dependent_process` entry + +## Common Pitfalls + +❌ **Incorrect table name** - Must be one of the supported atoms +❌ **Missing dependencies** - If index depends on other migrations, specify them +❌ **Wrong helper function** - Use creation helpers for `:create`, dropping helpers for `:drop` +❌ **Inconsistent naming** - Index name should match module name semantically +❌ **Missing CONCURRENT** - Use `add_concurrently_flag?()` in query strings +❌ **No progress tracking** - Always implement `check_db_index_operation_progress/0` +❌ **Forgot cache updates** - Must update BackgroundMigrations cache module +❌ **Missing update_cache/0** - Every module must implement this callback + +## Workflow for Index Replacement (Create → Drop → Rename) + +When replacing an existing index with a new version (e.g., adding a WHERE clause): + +1. **Create** the new index with a temporary name (e.g., `_2nd_` prefix) + - Depends on: latest heavy DB operation on the table +2. **Drop** the old index + - Depends on: the create operation completing +3. **Rename** the new index to the old index name + - Depends on: the drop operation completing + +This ensures zero downtime - the old index remains available until the new one is ready. + +## References + +- Behavior definition: [apps/explorer/lib/explorer/migrator/heavy_db_index_operation.ex](../../../apps/explorer/lib/explorer/migrator/heavy_db_index_operation.ex) +- README: [apps/explorer/lib/explorer/migrator/heavy_db_index_operation/README.md](../../../apps/explorer/lib/explorer/migrator/heavy_db_index_operation/README.md) +- Helper module: [apps/explorer/lib/explorer/migrator/heavy_db_index_operation/helper.ex](../../../apps/explorer/lib/explorer/migrator/heavy_db_index_operation/helper.ex) diff --git a/.agents/skills/openapi-spec/SKILL.md b/.agents/skills/openapi-spec/SKILL.md new file mode 100644 index 000000000000..d03a771545f9 --- /dev/null +++ b/.agents/skills/openapi-spec/SKILL.md @@ -0,0 +1,373 @@ +--- +name: openapi-spec +description: "Create, adjust, or inspect OpenAPI declarations for Blockscout API v2 endpoints. Use this skill whenever the user asks to: add an OpenAPI spec to an endpoint that lacks one, update a spec after controller/view changes, audit or fix an existing OpenAPI declaration, or work with open_api_spex annotations in the Blockscout codebase. Also trigger when the user mentions 'swagger', 'openapi', 'open_api_spex', 'API spec', 'API schema', or 'operation macro', or when debugging failures like 'response schema mismatch', 'CastAndValidate rejection', 'json_response validation error', 'Unexpected field', or extra/missing keys in API responses." +allowed-tools: ["Bash(.claude/skills/openapi-spec/scripts/generate-spec.sh *)", "Bash(oastools *)"] +--- + +# OpenAPI Spec Authoring for Blockscout API v2 + +This skill covers three workflows for Blockscout's OpenAPI declarations: +- **Create** — add a declaration for an endpoint that has none +- **Adjust** — update a declaration after parameters or response changed +- **Inspect & Fix** — audit an existing declaration for correctness issues + +Blockscout uses the `open_api_spex` library (v3.22+) to define OpenAPI 3.0 specs inline in Elixir code. There are no hand-written spec files — the spec is derived entirely from annotations in controllers and schema modules, then assembled at runtime via router introspection. + +## Key file locations + +All paths are relative to `apps/block_scout_web/lib/block_scout_web/`. Most endpoints live under the flat v2 layout, but annotated endpoints also exist outside of it — the table below calls out every tree that contributes to the generated spec. + +| What | Where | +|---|---| +| V2 controllers (flat) | `controllers/api/v2/_controller.ex` | +| V2 proxy controllers | `controllers/api/v2/proxy/_controller.ex` (routed under `/v2/proxy`) | +| V2 chain-type-nested controllers | `controllers/api/v2//_controller.ex` (e.g. `controllers/api/v2/ethereum/deposit_controller.ex`) | +| Account controllers (Private spec) | `controllers/account/api/v2/_controller.ex` | +| Legacy controllers | `controllers/api/legacy/_controller.ex` (routed under `/legacy`) | +| V2 schema modules | `schemas/api/v2/.ex` and `schemas/api/v2//*.ex` | +| V2 chain-type schema subdirs | `schemas/api/v2//*.ex` (e.g. `schemas/api/v2/{arbitrum,beacon,celo,optimism,scroll,zilliqa,mud}/*.ex`) | +| V2 proxy schemas | `schemas/api/v2/proxy/*.ex` | +| Account schemas (Private spec) | `schemas/api/v2/account/*.ex` | +| Legacy schemas | `schemas/api/legacy/*.ex` | +| Parameter helpers | `schemas/api/v2/general.ex` (all helpers centralized here) | +| Error responses | `schemas/api/v2/error_responses.ex` | +| Schema helper | `schemas/helper.ex` (`extend_schema/2`) | +| Leaf type schemas | `schemas/api/v2/general/*.ex` (AddressHash, FullHash, IntegerString, etc.) | +| API router | `routers/api_router.ex` | +| V2 sub-routers forwarded from the API router | `routers/tokens_api_v2_router.ex`, `routers/smart_contracts_api_v2_router.ex`, `routers/api_key_v2_router.ex`, `routers/utils_api_v2_router.ex`, `routers/address_badges_v2_router.ex` | +| Account router (Private spec) | `routers/account_router.ex` | +| Views (flat v2) | `views/api/v2/_view.ex` | +| Legacy views | `views/api/legacy/_view.ex` | +| Paging helper | `paging_helper.ex` (`delete_parameters_from_next_page_params/1`) | +| Spec aggregators | `specs/public.ex` (public spec + **tag registry**), `specs/private.ex` (account/private spec) | +| Global aliases/imports | The file `block_scout_web.ex` — look for `:controller` quote block | +| V2 tests | `../../test/block_scout_web/controllers/api/v2/_controller_test.exs` | +| Legacy tests | `../../test/block_scout_web/controllers/api/legacy/_controller_test.exs` | + +**On router coverage of the public spec:** `specs/public.ex` builds `paths` via `Paths.from_router(ApiRouter)`, which picks up everything reachable from `api_router.ex` — including endpoints declared in the sub-routers that `api_router.ex` `forward`s to (api-key, utils, address-badges). Only `TokensApiV2Router` and `SmartContractsApiV2Router` need the extra `Paths.from_routes(...)` merges in `public.ex` because their prefixes are stripped by Phoenix `forward` and must be re-added. A new annotated endpoint placed in any of the other sub-routers needs no extra wiring beyond the `forward` that already exists in `api_router.ex`. + +## Core patterns + +### The operation macro + +Every annotated controller action has an `operation/2` call (from `OpenApiSpex.ControllerSpecs`): + +```elixir +operation :action_name, + summary: "Short summary for the endpoint", + description: "Longer description of what it does.", + parameters: [some_path_param() | base_params()], + responses: [ + ok: {"Success description", "application/json", Schemas.SomeDomain.Response}, + not_found: NotFoundResponse.response(), + unprocessable_entity: JsonErrorResponse.response() + ] +``` + +For POST/PUT/PATCH endpoints, add `request_body:` — see `references/request-body-security-headers.md`. + +### The three-way parameter coupling + +Path parameters must be consistent across three locations or the endpoint breaks: + +| Location | Form | Example | +|---|---|---| +| Phoenix route segment | String with `:` prefix | `get("/:transaction_hash_param", ...)` | +| `%Parameter{}` struct | Atom in `:name` field | `%Parameter{name: :transaction_hash_param, in: :path}` | +| Controller action head | Atom key in pattern match | `def transaction(conn, %{transaction_hash_param: value})` | + +`CastAndValidate` reads string keys from `conn.path_params`, converts them to atoms using the Parameter `:name`, and places them in `conn.params`. The controller then pattern-matches on those atoms. + +### Response schema ↔ view correlation + +There is no runtime validation that view output matches the response schema. Alignment is enforced **only at test time**: every `json_response/2` call in a `ConnCase` test automatically validates the response body against the OpenAPI spec. This means: +- Schemas with `additionalProperties: false` catch extra keys the view emits +- The `required` list catches missing keys +- Type/pattern checks catch type mismatches + +If a view emits a key not in the schema (or vice versa), tests will fail. + +### CastAndValidate's effect on params (string keys → atom keys) + +When `CastAndValidate` processes an action with a real `operation` spec (not `operation :action, false`), it transforms **all** params before the action runs: +- **String keys become atom keys:** `%{"id" => "42"}` → `%{id: 42}` +- **Values are cast to declared types:** strings become integers, booleans, etc., based on the parameter's `%Schema{type: ...}` + +Actions declared with `operation :action, false` are **skipped** — they receive the original string-keyed params from Phoenix unchanged. + +This matters most for **pagination**. The `paging_options/1` function in `chain.ex` has parallel clauses for both forms: +- String-key clauses (e.g., `%{"id" => id_string} when is_binary(id_string)`) — used by actions without a spec +- Atom-key clauses (e.g., `%{id: id}`) — used by actions with a real spec + +When promoting an action from `operation :action, false` to a real spec, the string-key `paging_options` clause will stop matching. You must ensure a corresponding atom-key clause exists. See Workflow A, Step 4b for details. + +### base_params() — always include + +`base_params()` returns `[api_key_param(), key_param()]` — two optional query parameters (`apikey`, `key`) present on every public API operation. Always include it. + +Common composition patterns: +```elixir +# Simple — no extra params +parameters: base_params() + +# With a path param (prepend via cons) +parameters: [address_hash_param() | base_params()] + +# With paging params (append via ++) +parameters: base_params() ++ define_paging_params(["index", "block_number"]) + +# Combined +parameters: [transaction_hash_param() | base_params()] ++ [token_type_param()] ++ define_paging_params(["index", "block_number"]) +``` + +### Controller prerequisites + +Every annotated controller needs: +```elixir +use OpenApiSpex.ControllerSpecs # injects operation/2, tags/1 +plug(OpenApiSpex.Plug.CastAndValidate, json_render_error_v2: true) # validates incoming params +tags(["domain-tag"]) # groups operations in spec +``` + +These are typically near the top of the controller module, after `use BlockScoutWeb, :controller`. + +**Tag naming: kebab-case.** Tag strings use kebab-case (`"internal-transactions"`, `"main-page"`, `"smart-contracts"`, `"token-transfers"`, `"account-abstraction"`), not snake_case. Multi-word controller module names such as `InternalTransactionController` still map to the kebab-case plural tag, not to the module name. + +### Tag registry (`specs/public.ex`) + +The order of tag groups in the generated public spec is not derived from the controllers — it's declared explicitly in `specs/public.ex` and has a fixed three-part shape: + +1. **Base tags** — the `@default_api_categories` list at the top of `specs/public.ex`, always present regardless of chain type. +2. **Chain-type-specific tags** — returned by `chain_type_category/0`, whose clauses are keyed on `@chain_identity` (`{:optimism, :celo}`, `{:optimism, nil}`, `{:scroll, nil}`, `{:zilliqa, nil}`, …). For chains without OpenAPI coverage this is an empty list. +3. **`"legacy"`** — hard-coded trailer pinned last. + +If a new annotated controller introduces a brand-new tag, the agent must register it in the right group, or the tag will still appear in the spec (via controller-side `tags(...)`) but with no ordering guarantee and no entry in the top-level `tags:` list: + +- Base endpoint → append the kebab-case tag to `@default_api_categories`. +- Chain-type endpoint → add it inside the relevant `case @chain_identity` branch, matching the existing patterns (module-attribute + `defp` for static lists, full `defp` body when the tag set depends on a runtime flag such as `mud_enabled?()`). +- Legacy endpoint → no action; `"legacy"` is already the trailer. + +Tags that are already covered by an existing group (e.g. another `addresses` endpoint) need no change. + +--- + +## Verification + +After creating or modifying a declaration, verify it using these methods in order. Each catches a different class of issues, and earlier steps are faster — so run them first to get quick feedback before committing to a full test run. + +### 1. Compile (`mix compile`) + +Compiling the `block_scout_web` app verifies structural validity: schema modules exist, operation names match controller action function names, and all referenced modules resolve. This is the fastest check and catches typos, missing modules, and wiring errors. + +Run via devcontainer if mix is not available on the host. + +### 2. Generate the spec (`generate-spec.sh`) + +This exercises `OpenApiSpex.resolve_schema_modules/1`, which resolves all schema module references and inlines them into the full spec. It catches issues that compilation alone misses: circular references, malformed schema structures, and resolution failures. + +```bash +.claude/skills/openapi-spec/scripts/generate-spec.sh +``` + +See `references/spec-generation-and-verification.md` for script options (chain-specific generation, custom output path) and `oastools` commands for inspecting the result. + +### 2a. Audit for spec-wide convention drift (optional) + +After regeneration, sweep the spec for convention violations a single-endpoint test run won't catch: missing `additionalProperties: false`, missing `:unprocessable_entity`, tag casing, etc. See `references/oastools-audit-recipes.md` — the quick sweep is recipes A, B, F, I. + +The generated spec is cache-like, so regeneration must come first. A stale `.ai/tmp/openapi_public.yaml` produces false positives for every recipe that counts violations — e.g., it may report tag-casing hits that no longer exist in the codebase. + +### 2b. Tag audit (run after creating, moving, or retagging operations) + +`mix test` does not check tags. Run Recipe O (registry coverage — Step 4e) and Recipe P (URL prefix vs operation tag — Step 4d) from `references/oastools-audit-recipes.md`. + +### 3. Run controller tests (`mix test`) + +Run the specific controller test file. Every `json_response/2` call automatically validates the response body against the OpenAPI schema. This catches response-level issues: extra keys (via `additionalProperties: false`), missing required keys, and type mismatches. + +```bash +mix test apps/block_scout_web/test/block_scout_web/controllers/api/v2/_controller_test.exs +``` + +If tests fail with schema validation errors, the view output doesn't match the declared schema — fix the discrepancy. + +### 4. Code cross-referencing (for Inspect & Fix workflow) + +Manually or via grep, compare the controller's consumed parameters against declared parameters, and the view's output keys against schema properties. This catches logical issues that tests might miss (e.g., an undeclared optional parameter that works at runtime but isn't documented, or a schema property that's declared but never emitted by the view). + +See `references/inspection-checklist.md` for the systematic approach. + +--- + +## Workflow A: Create a new declaration + +Use this when an endpoint exists (route + controller action + view) but has no `operation/2` annotation. + +### Step 1: Gather context + +Read these files in parallel to understand the endpoint: + +1. **Router** — find the route definition. Note the HTTP method, path segments (especially `:param_name` segments), and which controller/action it maps to. +2. **Controller** — read the action function. Note what keys it destructures from `params` and `conn.body_params`, what data it fetches, and what view template it renders. +3. **View** — read the render function and any `prepare_*` helper it calls. Note every key in the output map — these become schema properties. Trace **all code paths**, not just the default: look for `case`/`cond`/pattern-match branches in the render function and its helpers that produce different map shapes depending on a field value. When found, note the discriminator field and the distinct set of keys each branch emits — these indicate a polymorphic sub-object that needs special handling in Step 3. +4. **Existing schemas** — glob `schemas/api/v2/*` to see if schema modules already exist for this domain. +5. **Peer precedent (optional)** — `oastools walk operations -tag -q .ai/tmp/openapi_public.yaml` lists sibling endpoints already in the spec. Useful before choosing between schema reuse and new schemas in Step 3. + +### Step 2: Find or create parameter definitions + +For each parameter the controller reads: + +1. **Check if a helper already exists.** Grep `general.ex` for a function matching the parameter name: + ``` + # For a path param named :address_hash_param + grep "def address_hash_param" in general.ex + ``` + Read `references/parameter-discovery.md` for naming conventions and discovery patterns. + +2. **If no helper exists**, decide: + - **Reusable across controllers?** Add a new helper function to `general.ex` following the naming conventions in `references/parameter-discovery.md`. + - **Domain-specific but used by multiple operations in the same controller?** Add a private helper function in the controller itself. This avoids polluting `general.ex` with chain-specific concerns while preventing duplication across operations. + - **Truly one-off (single operation)?** Define an inline `%OpenApiSpex.Parameter{}` struct directly in the `operation` macro arguments. + +3. **For pagination parameters**, use `define_paging_params(field_names)` — pass the cursor field names as strings, and always include `"items_count"` (the `next_page_params` helper adds it to every cursor automatically). See `references/parameter-discovery.md` section "The `define_paging_params` factory" for details. + +### Step 3: Create or locate response schema + +1. **Check if a schema module exists** for the response entity. Glob `schemas/api/v2/*.ex`. +2. **If schemas exist in the same domain**, compare their properties against the new view's output keys to detect subset/superset relationships (recipe N in `references/oastools-audit-recipes.md` gives a mechanical candidate list across all component schemas): + - **Existing schema is a subset** of what the new endpoint needs — use `extend_schema` from the existing schema, adding only the extra properties. See `references/schema-conventions.md` section "Schema reuse and naming for related schemas" for the naming convention and required `title:` parameter. + - **Existing schema is a superset** — the new endpoint may reference the existing schema directly (if it needs all the properties), or may need a reduced "minimal" schema that the existing one extends. + - **Before reusing, check `oneOf`/`anyOf` reachability.** If the candidate schema (or any of its nested properties) contains a `oneOf` or `anyOf`, trace each variant back through the controller action's code path to the view's render function. Identify which discriminator values the controller can actually produce for this endpoint. If all variants are reachable, reuse the schema directly. If only a subset is reachable, create a narrowed schema via `extend_schema`, overriding only the polymorphic property with a `oneOf` containing just the reachable variants. `extend_schema` merges properties and overwrites existing keys, so passing the narrowed property replaces the parent's full variant list (see `references/schema-conventions.md` section "Helper.extend_schema/2"). Example: if `Batch` has a `data_availability` with 4 `oneOf` variants but endpoint `batch_by_celestia_da_info` can only produce the Celestia variant, create a schema that extends `Batch` and overrides `data_availability` to contain only that variant. + - **No meaningful overlap** — create a standalone schema. +3. **If no suitable schema exists**, create one following the conventions in `references/schema-conventions.md`. The schema's properties must match the view's output keys exactly. +4. **Deduplicate against existing domain schemas.** Before finalizing properties, compare each inline `%Schema{type: :object}` block and each `%Schema{type: :string, enum: [...]}` definition in the new schema against properties in the existing schemas found in step 1. If an identical structure already exists in another schema in the same domain directory, extract it into a shared leaf schema module and reference it from both schemas. This avoids drift when the structure changes and consolidates Ecto.Enum sync comments to one location. See `references/schema-conventions.md` section "Domain-scoped shared schemas" for templates. Recipe D in `references/oastools-audit-recipes.md` enumerates every inline enum across the spec — group by `.enum` to find duplicates mechanically. +5. **Model polymorphic sub-objects.** If Step 1 identified a property whose structure varies based on a discriminator field (e.g., a `data_availability` object that changes shape depending on `batch_data_container`), a single flat `%Schema{type: :object}` with only the common fields will be incomplete — the variant-specific fields won't be documented or validated. Use `oneOf` to declare each variant. See `references/schema-conventions.md` section "Polymorphic properties (`oneOf`)" for the structural pattern, the per-variant discriminator-constraint rule, and a concrete template. For existing precedent, see `transaction.ex` (`revert_reason` property). +6. **Determine precise types from the Ecto schema.** The view layer is lossy — it renders everything as JSON primitives. Read the entity's Ecto schema (under `apps/explorer/lib/explorer/chain/`) to recover the real constraints: `Ecto.Enum` values, nullability, and integer-vs-string representation for large numbers. See `references/schema-conventions.md` §"Determining property types from Ecto schemas" for the full Ecto-to-OpenAPI mapping, the mandatory enum sync-comment format, and the OpenAPI-3.0 nullability rule (`nullable: true`, never `type: :null`). +7. **Set `additionalProperties: false`** on object schemas — this is a project-wide convention that enables test-time enforcement. + - **For non-negative integer properties** (block numbers, batch numbers, counts, indices, nonces), set `minimum: 0` to enforce the domain constraint at the validation level. +8. **Set `required:`** to list all keys that the view always emits. +9. For paginated list endpoints, use `General.paginated_response/1` to wrap the item schema. +10. **Review properties for description adequacy.** After defining types and constraints, do a final pass over all properties. For each property without a `description:`, ask: "Would an API consumer unfamiliar with this chain's internals understand this from the name alone?" Add descriptions to properties that are ambiguous, use domain jargon, mirror Solidity field names, or where the chain context (Parent chain vs Rollup) is unclear. Tautological descriptions that restate the property name don't count — rewrite or remove them. See `references/schema-conventions.md` section "Property descriptions" for guidelines and examples. + +### Step 4a: Write the operation annotation + +Add the `operation/2` call above the controller action. Follow the structure in "The operation macro" section above. Make sure: +- `summary:` is a short imperative sentence +- `description:` adds useful detail beyond the summary +- `parameters:` includes `base_params()` and all path/query params +- `responses:` covers the success case and all error cases the action can return. If multiple controller branches share the same status code with different error messages, use a custom description tuple instead of the generic `Module.response()` helper — see `references/error-response-patterns.md` section "Multiple error branches sharing one status code". + +If the controller lacks the `use OpenApiSpex.ControllerSpecs` line and `CastAndValidate` plug, add them (see "Controller prerequisites"). If the `tags([...])` string is brand-new (not already present in `@default_api_categories` or any `chain_type_category_tags/0` clause in `specs/public.ex`), proceed through Step 4e before verification — without registration the tag still renders per-operation but has no ordering guarantee. + +### Step 4b: Update paging_options if the endpoint is paginated + +If the action calls `paging_options(params)` (directly or via helpers like `next_page_params`), the string-key clauses in `chain.ex` will no longer match because `CastAndValidate` has already converted params to atom keys with cast types. + +Check `chain.ex` for the relevant `paging_options` clause. If only a string-key clause exists (e.g., `%{"id" => id_string}` with `Integer.parse`): +- **Add** a matching atom-key clause (e.g., `%{id: id}`) if the string-key clause is still used by other actions without specs +- **Replace** the string-key clause with an atom-key one if all callers now go through `CastAndValidate` + +The atom-key clause is typically simpler because `CastAndValidate` already handles type casting — no `Integer.parse` or similar parsing needed. + +This step is especially important when **promoting** an action from `operation :action, false` to a real spec — that is the moment where `paging_options` stops receiving string keys and the mismatch occurs. + +### Step 4c: Ensure path params are excluded from `next_page_params` + +If the endpoint is paginated **and** has path parameters, those path params will leak into the pagination cursor response unless explicitly stripped. + +**Why this happens:** CastAndValidate converts all params (path + query) to atom keys in a single map. The `next_page_params/5` function receives this map and builds the cursor for the response. It calls `delete_parameters_from_next_page_params/1` (in `paging_helper.ex`) to strip known non-pagination params, but only params listed in its `Map.drop` list are removed. If a path param isn't listed, it appears in the JSON response's `next_page_params`. When the client sends that cursor back as query params on the next request, CastAndValidate rejects the path param as "Unexpected field" because it's declared as `:path`, not `:query`. + +**What to do:** For each path parameter declared in the operation: +1. Read `delete_parameters_from_next_page_params/1` in `apps/block_scout_web/lib/block_scout_web/paging_helper.ex`. +2. Check whether the atom-key form (e.g., `:direction`) is in the `Map.drop` list. +3. If missing, add it among the other atom-key entries at the top of the list. + +The existing list already includes common path params like `:address_hash_param`, `:batch_number_param`, `:block_hash_or_number_param`, `:transaction_hash_param`. New path params need to be added as they are introduced. + +### Step 4d: Pick the right tag(s) when URL prefix and controller domain disagree + +If the operation's URL lives under a cross-cutting prefix that is itself a tag (e.g., `/v2/main-page/...`), add `tags: [""]` per-operation. OpenApiSpex appends to module-level `tags(...)`, so the operation will appear under both groups (dual-tagging — the default). For exclusive relocation, see `references/schema-conventions.md` §"Cross-cutting URL prefixes and tags". + +### Step 4e: Register a new tag in the registry + +If the controller's `tags([...])` declares a tag not already in `@default_api_categories` or any `chain_type_category_tags/0` clause in `specs/public.ex`, add it. Base tag → `@default_api_categories`; chain-type tag → matching `case @chain_identity` branch. See "Tag registry" in Core patterns for branch shapes. + +### Step 5: Ensure test coverage + +Tests are the primary mechanism that validates the response schema matches the actual view output. Without tests hitting the endpoint, the schema is unverified documentation that may be wrong. + +1. **Enumerate all status codes the controller action returns.** Read the controller action and list every distinct HTTP status code it can produce. Look for: + - `put_status` calls (e.g., `put_status(:bad_request)`, `put_status(200)`) + - Pattern-match branches that render different error responses + - `send_resp` calls with explicit status codes + - The implicit 200 from the success path (`render` without `put_status`) + + Cross-reference this list against the `responses:` declared in the operation. Every status code declared in the operation should have at least one test. If multiple branches return the same status code with different conditions, note each branch separately — ideally each gets its own test case so the conditions are documented. The spec-side half of this cross-check is one command: `oastools walk responses -path -method -q .ai/tmp/openapi_public.yaml`. + + Some branches depend on external systems (RPC calls, microservice responses) and cannot be reached with pure DB setup. Decide how to handle each one: + + - **Mock when the branch produces a distinct response shape** — a different `oneOf` variant, a different set of required keys, or an enum value not exercised by other tests. These are exactly the cases where `additionalProperties: false` and type constraints silently rot without coverage. (Example: the Arbitrum withdrawal token sub-object and `:confirmed`/`:sent` status paths are only reachable through L1 RPC mocking, and testing them exposed a real OpenApiSpex schema-title collision bug that would have shipped otherwise.) + - **Document and skip when the mocking cost is disproportionate** — e.g., a branch requires orchestrating multiple cross-chain RPC fallback steps. Add a code comment explaining what the branch does and why it's not covered (e.g., `# :unknown status — requires Outbox.isSpent=false AND get_size_for_proof/0 returning nil (multi-step L1/L2 RPC fallback), not covered here`). + + **How to mock RPC dependencies when it's worth it.** The established pattern uses `:meck` to intercept `Indexer.Helper.json_rpc_named_arguments/1` so it returns a Mox-backed transport, then `Mox.expect` stubs specific contract calls with ABI-encoded responses. See `arbitrum_controller_test.exs` helpers (`setup_arbitrum_l1_rpc_mocks!`, `expect_inbox_outbox_query!`, `expect_erc20_metadata!`, etc.) for a working reference. When building mock fixtures for chain-specific RPC calls, the Blockscout MCP server can discover real on-chain data (event logs, calldata, contract return values) to verify that fixtures match production structure — it is a discovery aid, not a source of truth; the ABI spec and contract source are authoritative. + +2. **Check if tests already exist.** Look for the test file at `apps/block_scout_web/test/block_scout_web/controllers/api/v2/_controller_test.exs`. Grep for the endpoint path or action name within the file. If tests already hit the endpoint and call `json_response/2`, they will automatically validate the schema — proceed to Step 6. + +3. **If no tests exist**, create them. For minimal test templates covering list / single-resource / 404 / 422 cases, see `references/inspection-checklist.md` section "Minimal test templates". Every `json_response/2` call triggers schema validation automatically. Cover every status code enumerated in item 1 — if the controller returns codes beyond the templates (e.g., 400 from business-logic checks), add tests for those too, setting up the DB state that triggers each branch. + +4. **If the schema contains `oneOf` polymorphic sub-objects** (from Step 3 item 5), write at least one test per variant so each branch's `additionalProperties: false` constraint is exercised. The default factory typically produces only the simplest variant, so other variants need explicit setup — insert the factory with the discriminator value set, plus any associated records the view fetches. If a variant is only reachable through an external dependency (RPC, microservice), see item 1 above. + +### Step 6: Verify + +Run the verification ladder from the "Verification" section above (compile → generate-spec → tests). If tests fail with schema validation errors, the view output doesn't match the declared schema — fix the discrepancy. + +--- + +## Workflow B: Adjust an existing declaration + +Use this when an endpoint's parameters or response have changed and the OpenAPI spec needs to catch up. + +### Step 1: Identify the change + +Read the controller action and view to understand what changed. Common scenarios: +- **New parameter added** — controller now reads a new key from params +- **Parameter removed** — controller no longer uses a parameter +- **New response field** — view now emits an additional key +- **Response field removed** — view no longer emits a key +- **Type changed** — a field's type or format changed + +### Step 2: Update the declaration + +- **Parameters**: Add/remove from the `parameters:` list in the `operation` macro. If adding a new reusable param, add a helper to `general.ex`. +- **Response fields**: Update the schema module's `properties:` map and `required:` list. If adding a field, add it to both. If removing, remove from both. +- **Type changes**: Update the property's schema type in the schema module. + +### Step 3: Verify + +Run the verification ladder from the "Verification" section above (compile → generate-spec → tests). If parameters changed, also revisit Workflow A Step 4b/4c — atom-key `paging_options` clauses and `next_page_params` path-param stripping apply equally when adjusting. + +--- + +## Workflow C: Inspect & fix an existing declaration + +Use this to audit an existing declaration for correctness, completeness, and adherence to project conventions. Read `references/inspection-checklist.md` and work through it end to end — it owns the full cross-reference procedure (parameters, response fields, conventions, schema organization) and ends with the verification ladder. + +--- + +## When to read reference files + +| Reference | Read when... | +|---|---| +| `references/parameter-discovery.md` | You need to find existing parameter helpers, create new ones, or understand naming/categorization conventions | +| `references/schema-conventions.md` | You need to create new schema modules, understand directory layout, work with chain-type customizations, or model polymorphic properties with `oneOf` | +| `references/error-response-patterns.md` | You need to declare error responses or understand which error module to use for a status code | +| `references/request-body-security-headers.md` | You're working with POST/PUT/PATCH endpoints, authentication/security, or HTTP header declarations | +| `references/inspection-checklist.md` | You're running an audit of an existing declaration (Workflow C) | +| `references/spec-generation-and-verification.md` | You need to generate the spec YAML, validate it, or inspect specific operations/schemas with oastools | +| `references/oastools-audit-recipes.md` | You want to audit the generated spec for spec-wide convention drift or reuse candidates, without reading every source file | + +## Using subagents + +For the Create workflow, parallelize the initial context gathering (Step 1) by spawning subagents to read the router, controller, view, and existing schemas simultaneously. + +When running tests after changes, use the devcontainer skill if mix/elixir is not available on the host. diff --git a/.agents/skills/openapi-spec/references/error-response-patterns.md b/.agents/skills/openapi-spec/references/error-response-patterns.md new file mode 100644 index 000000000000..8a86ff4dcebf --- /dev/null +++ b/.agents/skills/openapi-spec/references/error-response-patterns.md @@ -0,0 +1,132 @@ +# Error Response Patterns + +## Discovery + +All custom error response modules are defined in a single file: +`apps/block_scout_web/lib/block_scout_web/schemas/api/v2/error_responses.ex` + +Plus one from the `open_api_spex` library itself: `OpenApiSpex.JsonErrorResponse`. + +To discover the current set, read `error_responses.ex` and look for `defmodule` declarations. Each module defines a `response/0` helper. + +## The response/0 helper pattern + +All custom error modules follow this pattern: + +```elixir +defmodule NotFoundResponse do + require OpenApiSpex + alias OpenApiSpex.Schema + + OpenApiSpex.schema(%{ + title: "NotFoundResponse", + type: :object, + properties: %{message: %Schema{type: :string, example: "Resource not found"}} + }) + + def response, do: {"Not Found", "application/json", __MODULE__} +end +``` + +The `response/0` function returns a 3-tuple `{description, content_type, module}` used in operation specs: + +```elixir +responses: [ + not_found: NotFoundResponse.response(), + unprocessable_entity: JsonErrorResponse.response() +] +``` + +`JsonErrorResponse` (from `open_api_spex`) returns a `%Response{}` struct instead of a tuple. Both forms work in the `operation` macro. + +## Status code mapping + +The response key in the `responses:` keyword list determines the HTTP status code. Use the atom form: + +| Atom key | HTTP status | Typical module | +|---|---|---| +| `:ok` | 200 | (success — use domain schema) | +| `:bad_request` | 400 | `BadRequestResponse` | +| `:unauthorized` | 401 | `UnauthorizedResponse` | +| `:forbidden` | 403 | `ForbiddenResponse` | +| `:not_found` | 404 | `NotFoundResponse` | +| `:unprocessable_entity` | 422 | `JsonErrorResponse` | +| `:not_implemented` | 501 | `NotImplementedResponse` | + +To verify the current mapping, read `error_responses.ex` and check the module names and their example messages. + +## Auto-aliased modules + +Two modules are automatically available in every controller (aliased in `block_scout_web.ex`): + +```elixir +alias OpenApiSpex.JsonErrorResponse +alias Schemas.ErrorResponses.ForbiddenResponse +``` + +All others must be explicitly aliased in the controller: +```elixir +alias BlockScoutWeb.Schemas.API.V2.ErrorResponses.NotFoundResponse +``` + +To check which are auto-aliased, read the `:controller` quote block in `block_scout_web.ex`. + +## When to use which error response + +- **`JsonErrorResponse` (422)** — the default for validation errors. `CastAndValidate` returns this automatically when parameter validation fails. Also use when the controller explicitly rejects input as invalid. +- **`NotFoundResponse` (404)** — when the requested resource doesn't exist. +- **`ForbiddenResponse` (403)** — when the request is authenticated but not authorized, or when a required server-side config (like an API key) is missing. +- **`UnauthorizedResponse` (401)** — when authentication is required but missing/invalid. Primarily used in account/private API endpoints. +- **`BadRequestResponse` (400)** — when the request is malformed in a way that isn't a parameter validation error. +- **`NotImplementedResponse` (501)** — when the endpoint exists but the feature is not available. + +## Choosing error responses for an operation + +Look at the controller action to identify which error paths exist: + +1. **Every operation** should include `:unprocessable_entity: JsonErrorResponse.response()` — CastAndValidate can always fail. Spec-wide audit of operations currently missing 422: recipe B in `references/oastools-audit-recipes.md`. +2. If the action does a resource lookup (e.g., `Chain.hash_to_transaction`), include `:not_found`. +3. If the action checks authorization (e.g., `AccessHelper.restricted_access?`), include `:forbidden`. +4. If the action requires authentication, include `:unauthorized`. +5. Check `put_status` and `send_resp` calls in the action for other status codes. If multiple branches return the same status code with different error messages, see "Multiple error branches sharing one status code" below for how to write a descriptive response instead of using the generic helper. + +Not all runtime error paths need to be in the spec — undeclared status codes (like `:internal_server_error` from rate limiting) are typically treated as infrastructure concerns. But all explicitly handled error cases in the controller action should be declared. + +## Multiple error branches sharing one status code + +Sometimes a controller action has several branches that all return the same HTTP status code but with different error messages. For example, three separate `put_status(:bad_request)` calls returning "withdrawal is unconfirmed yet", "withdrawal is just initiated", and "withdrawal was executed already". Using `BadRequestResponse.response()` produces a generic "Bad Request" description that gives API consumers no hint about what triggers each error. + +When this happens, replace the generic `Module.response()` helper with a custom `{description, content_type, module}` tuple where the description documents the possible error conditions: + +```elixir +responses: [ + ok: {"Success description", "application/json", Schemas.SomeDomain.Response}, + bad_request: + {"Withdrawal cannot be claimed. Returned when the withdrawal is unconfirmed, just initiated, or already executed.", + "application/json", BadRequestResponse}, + not_found: NotFoundResponse.response(), + unprocessable_entity: JsonErrorResponse.response() +] +``` + +This works because `response/0` just returns the same kind of 3-tuple. By writing the tuple directly, you can customize the description while keeping the same response schema module. + +**When to use this pattern:** +- The controller has 2+ branches returning the same status code with different user-facing messages +- The conditions are meaningful to API consumers (not internal implementation details) + +**When NOT to use it:** +- The status code has only one triggering condition — use the standard `Module.response()` helper +- The different messages are minor variants of the same condition — the generic description is fine + +## Custom inline error responses + +For one-off error schemas (e.g., a specific error format for a single endpoint), you can use an inline tuple: + +```elixir +responses: [ + internal_server_error: {"Error message", "application/json", message_response_schema()} +] +``` + +Where `message_response_schema()` is a helper that returns an inline schema. Check the controller's existing patterns to see if this is used. diff --git a/.agents/skills/openapi-spec/references/inspection-checklist.md b/.agents/skills/openapi-spec/references/inspection-checklist.md new file mode 100644 index 000000000000..ed39b7183d1c --- /dev/null +++ b/.agents/skills/openapi-spec/references/inspection-checklist.md @@ -0,0 +1,260 @@ +# Inspection Checklist + +Use this checklist to systematically audit an existing OpenAPI declaration. Work through each section, reading the relevant files as needed. + +## 1. Parameter completeness + +### 1a. Every parameter the controller reads should be declared + +Read the controller action function. Identify every key it reads from: +- `params` pattern match in the function head (path + query params) +- `conn.body_params` (request body params) +- `conn.req_headers` (header params) +- Calls to helper functions that read from params (e.g., `paging_options(params)`, `token_transfers_types_options(params)`, `fetch_scam_token_toggle(conn)`) + +Cross-reference with the `parameters:` list in the `operation` macro. Every parameter that affects the endpoint's behavior should be declared. + +Spec-side enumeration in one command: `oastools walk parameters -path -method -q .ai/tmp/openapi_public.yaml`. Controller side still needs to be read for the comparison. + +**Known exceptions**: cross-cutting headers (`show-scam-tokens`, recaptcha headers) are conventionally undeclared. See `references/request-body-security-headers.md` for the gap details and recommended approach. + +### 1b. Every declared parameter should be used + +Check that each parameter in the `parameters:` list is actually consumed by the controller. Unused declared parameters create misleading API documentation. + +### 1c. Three-way coupling is consistent + +For each **path** parameter, verify: +1. The route segment name (`:param_name` in router) matches the `%Parameter{name: :param_name}` atom +2. The controller action's pattern match uses the same atom key +3. All three agree exactly + +Read the route definition in the router file, the `%Parameter{}` definition, and the controller action head. + +Spec side: `oastools walk parameters -in path -path -method -detail -format json .ai/tmp/openapi_public.yaml | jq '.parameter.name'`. + +### 1d. Parameter types are accurate + +For each parameter: +- Path params that are hashes should use `FullHash` or `AddressHash` schema +- Path params that are numbers should use `IntegerString` or `%Schema{type: :integer}` +- Enum params should have the correct `enum:` values (check the controller logic for valid values) +- Boolean params should use `%Schema{type: :boolean}` + +### 1e. No duplicated inline parameters + +For each inline `%Parameter{}` struct in the operation, scan the other operations in the same controller for identical or near-identical structs (same `name`, `in`, `schema`, and `description`). Duplicated inline parameters are a maintenance risk — changing one without updating the other creates silent inconsistencies. + +Mechanical scan across the whole domain: recipe E in `references/oastools-audit-recipes.md` groups same-name parameters across all endpoints under one path prefix in a single pass. + +If duplication is found, extract the parameter into a reusable helper function: +- **Generic concept** (address hashes, transaction hashes, block numbers — useful across multiple controllers): add a helper to `general.ex` following the conventions in `references/parameter-discovery.md`. +- **Domain-specific concept** (e.g., an Arbitrum message direction — only meaningful within one controller): add a private helper function in the same controller. This keeps the chain-specific concern contained without polluting the shared `general.ex`. + +## 2. Response field alignment + +### 2a. Schema properties match view output + +Read the view's render function and any `prepare_*` helper it calls. List every key in the output map. + +Read the response schema module. List every key in `properties:`. + +Compare: +- **Extra schema properties** (in schema but not in view): if in `required:`, this will cause test failures. If optional, it's technically valid but misleading. +- **Extra view keys** (in view but not in schema): if schema has `additionalProperties: false`, this will cause test failures. Otherwise it's undocumented output. +- **Type mismatches**: verify that each view output value matches its schema type (string, integer, object, array, nullable). + +Schema-side key list in one command: `oastools walk schemas -name -detail -format json .ai/tmp/openapi_public.yaml | jq '.[0].schema.properties | keys'`. + +### 2b. Type precision — check Ecto schemas for enums and constraints + +The view layer is lossy about types. A field that renders as a plain string may actually be an `Ecto.Enum` with a fixed set of values. For each string-typed property in the OpenAPI schema: + +1. Find the corresponding Ecto schema module in `apps/explorer/lib/explorer/chain/`. Grep for `Ecto.Enum` in that file. +2. If the field is an `Ecto.Enum`, the OpenAPI property should use `enum: [...]` with the correct values, not just `type: :string`. +3. If the property already uses `enum:`, verify the values are **complete and current** by comparing against the Ecto enum definition. New values may have been added to the Ecto schema without updating the OpenAPI schema — this is a silent breakage where `CastAndValidate` rejects the new value on input. +4. Verify there is a code comment on the enum property pointing to the source Ecto field (e.g., `# Enum values must be kept in sync with Explorer.Chain. : field.`). If missing, add one. +5. Check existing schemas in the same domain for precedent — similar entities often already use enum for comparable fields. + +Also check for other type refinements: large integers serialized as strings should use `IntegerString`, hash fields should use `FullHash`/`AddressHash`, timestamps should use `Timestamp`/`TimestampNullable`. + +See `references/schema-conventions.md` section "Determining property types from Ecto schemas" for the full Ecto-to-OpenAPI type mapping. + +### 2c. Required list is accurate + +Every key the view always emits should be in `required:`. Keys that are conditional or sometimes `nil` should either: +- Not be in `required:` (if the key might be absent) +- Be in `required:` but have `nullable: true` on the schema (if the key is always present but sometimes null) + +**Scope.** "Always emits" and "sometimes `nil`" refer to the render paths reachable via the **endpoints that currently reference this schema** in their `operation/2` `responses:`. Before flagging a `nullable: false` property as wrong: + +1. Enumerate those call sites mechanically: `Grep "Schemas\.\b" apps/block_scout_web/lib/block_scout_web/controllers`. +2. For each call site, check the controller's `necessity_by_association` / explicit `Repo.preload/2` / other data-shaping code to determine whether the value can in fact reach the view as `nil`. +3. Only flag if at least one spec-declared render path can produce `nil`. A hedge of the form "*if* any of those readers skips preloading X" or "the shared schema *may* be over-constrained" is not a finding — it is a note that you haven't finished step 2. Either complete the enumeration and cite a specific `controller.ex:line` where the preload is absent, or drop the concern. +4. Each finding must be actionable on the endpoint being audited. If step 2 shows "this could be wrong for a peer endpoint, but `/v2/X` itself is fine," don't raise it as Major/Minor on the `/v2/X` audit. Drop it, or downgrade to a Nit that names the specific peer endpoints as a suggested follow-up audit. A "Major that requires no action on the audited endpoint" is a contradiction — it either has a concrete action here (Major/Minor) or it doesn't (Nit / separate audit). + +Don't flag based on "a future endpoint might not preload X." If a future endpoint is added without the required preload, that new endpoint's audit owns the fix — it is not the shared schema's job to pre-accommodate code that hasn't been written yet. + +See `references/schema-conventions.md` section "Nullable fields" for the full nullable handling rules, including why `type: :null` / `anyOf: [%Schema{type: :null}, …]` (OpenAPI 3.1) is invalid here. + +### 2d. additionalProperties: false is set + +Check that `additionalProperties: false` is present on all object schemas. This is a project-wide convention that enables test-time enforcement. + +Spec-wide audit: recipe A in `references/oastools-audit-recipes.md` lists every component object schema that violates this. Error-response schemas (`NotFoundResponse`, `ForbiddenResponse`, etc.) intentionally omit it — real domain-schema drift is typically the remainder. + +### 2e. Chain-type fields are aligned + +If the view has chain-type dispatching (check for `chain_type` case statements or `with_chain_type_fields` calls), the schema should also have a `ChainTypeCustomizations` module applying the same fields. Verify both sides handle the same chain types. See `references/schema-conventions.md` section "Chain-type customization pattern" for the dispatch mechanism and where `ChainTypeCustomizations` modules are conventionally placed. + +### 2f. Property descriptions are adequate + +Scan all properties in the schema. For each property that has no `description:` (or a tautological one that restates the name), ask: "Would an API consumer unfamiliar with this chain's internals understand this property from its name alone?" + +Flag properties that fail this test. Common patterns to watch for: + +- **Domain jargon** (`before_acc_hash`, `callvalue`) — needs explanation of what the term means +- **Ambiguous roles** (`caller_address_hash`, `destination_address_hash`) — needs "who" and "on which chain" +- **Unclear chain context** (`block_number` in a cross-chain object) — needs "Parent chain" or "Rollup" +- **Enum values without lifecycle explanation** (`status` with `["initiated", "sent", "confirmed", "relayed"]`) — needs description of what triggers each transition +- **Tautological descriptions** ("Withdrawal status." on `status`) — count as missing; rewrite or remove + +Self-documenting compound names (`origination_transaction_block_number`) and well-known primitives (`token.symbol`) don't need descriptions. + +Mechanical shortlist of properties lacking `description:`: recipe C in `references/oastools-audit-recipes.md`. Human review still needed — tautologies pass this filter. + +See `references/schema-conventions.md` section "Property descriptions" for the full guidelines and before/after examples. + +### 2g. `oneOf`/`anyOf` variant reachability + +For each property in the response schema that uses `oneOf` or `anyOf`, verify that every variant is producible by this endpoint's controller action: + +1. List the variants in the `oneOf`/`anyOf` and identify the discriminator value(s) each covers. +2. Read the controller action. Trace which code paths lead to the view's render function. Identify which discriminator values the controller can pass to the view. +3. Read the view's render function and its helpers. Confirm which variants the view can actually emit for the data the controller provides. +4. Compare: flag any variant whose discriminator value(s) can never be produced by this endpoint. + +**If unreachable variants are found:** The schema overpromises to API consumers. Create a narrowed schema via `extend_schema` that overrides only the polymorphic property, keeping just the reachable variants. See `references/schema-conventions.md` section "Helper.extend_schema/2". + +To find all endpoints whose 200 response currently uses `oneOf` (for precedent), run recipe G in `references/oastools-audit-recipes.md`. + +This check is especially important for endpoints that filter by a specific discriminator value (e.g., a DA-type lookup that always returns one DA variant, but references a shared batch schema containing all DA variants). + +## 3. Convention compliance + +### 3a. Controller prerequisites + +Verify the controller has: +- `use OpenApiSpex.ControllerSpecs` +- `plug(OpenApiSpex.Plug.CastAndValidate, json_render_error_v2: true)` +- `tags(["domain-tag"])` — kebab-case (e.g. `"internal-transactions"`, `"smart-contracts"`, `"account-abstraction"`); should match the router scope/resource group +- The tag is registered in `specs/public.ex` — in `@default_api_categories` (base), in the appropriate `case @chain_identity` branch of `chain_type_category/0` (chain-type), or already pinned as `"legacy"`. An un-registered tag still renders per-operation but has no guaranteed ordering in the generated spec. + +Spec-wide tripwire: recipe I in `references/oastools-audit-recipes.md` returns any tag containing `_`. The baseline is `[]` — any hit likely means a controller predates the kebab-case convention. + +### 3b. base_params() is included + +Every public API operation should include `base_params()` in its parameters. Check that `base_params()` is present and isn't accidentally duplicated. + +Spec-wide audit: recipe F in `references/oastools-audit-recipes.md` lists operations missing `apikey`. + +### 3c. Error responses are appropriate + +Check which error cases the controller action handles (not_found, forbidden, etc.) and verify corresponding error responses are declared. See `references/error-response-patterns.md` for the status-code-to-module mapping. + +At minimum, every operation should declare `:unprocessable_entity: JsonErrorResponse.response()` since CastAndValidate can always fail. + +Spec-wide audit: recipe B in `references/oastools-audit-recipes.md` lists operations missing 422. Some are likely-intentional (legacy endpoints, CSV exports) — triage per endpoint. + +### 3d. Summary and description + +- `summary:` should be a short imperative sentence (shown in endpoint lists) +- `description:` should add useful detail beyond the summary +- Both should be present + +### 3e. Operation name matches action + +The first argument to `operation/2` must match the controller action function name: +```elixir +operation :transaction, ... # matches def transaction(conn, params) +``` + +## 4. Schema module organization + +### 4a. Schema is in the right location + +Check that the schema module follows directory conventions: +- Domain schemas under `schemas/api/v2/.ex` or `schemas/api/v2//*.ex` +- Chain-specific schemas under `schemas/api/v2//` +- Leaf types under `schemas/api/v2/general/` + +See `references/schema-conventions.md` for full conventions. + +### 4b. Module naming follows conventions + +`BlockScoutWeb.Schemas.API.V2.` for base schemas, `BlockScoutWeb.Schemas.API.V2..Response` for response wrappers. + +## 5. Verification + +After identifying and fixing issues from sections 1-4, run the verification ladder described in the "Verification" section of `SKILL.md` (compile → generate-spec → controller tests). Each step catches a different class of problems, and earlier steps are faster. + +### 5a. Test coverage check + +Check that tests exist and exercise the endpoint: + +1. **Test file exists**: `test/block_scout_web/controllers/api/v2/_controller_test.exs` +2. **Tests hit the endpoint**: grep for the endpoint path in the test file +3. **All declared status codes are tested**: enumerate every status code in the operation's `responses:` and verify at least one test exercises each. Pay special attention to status codes with multiple triggering conditions (e.g., multiple 400 branches) — each condition ideally has its own test case. Spec-side enumeration: `oastools walk responses -path -method -q .ai/tmp/openapi_public.yaml`. + +### Minimal test templates + +If no tests exist for the endpoint: + +```elixir +# For a list endpoint (empty list, zero factory data) +test "empty list", %{conn: conn} do + request = get(conn, "/api/v2/") + assert response = json_response(request, 200) + assert response["items"] == [] + assert response["next_page_params"] == nil +end + +# For a single-resource endpoint +test "returns resource", %{conn: conn} do + resource = insert(:) + request = get(conn, "/api/v2//#{resource.id}") + assert _response = json_response(request, 200) +end + +# For a not-found case +test "returns 404", %{conn: conn} do + resource = build(:) # build but don't insert + request = get(conn, "/api/v2//#{resource.id}") + assert %{"message" => "Not found"} = json_response(request, 404) +end + +# For a validation error +test "returns 422 on invalid input", %{conn: conn} do + request = get(conn, "/api/v2//invalid_value") + assert %{"errors" => [_]} = json_response(request, 422) +end +``` + +## 6. Spec-wide sweep + +Independent of any single-endpoint audit, run this sweep once per work session to catch drift introduced elsewhere in the codebase. Regenerate the spec first — stale YAML produces false positives. + +- Recipe A — object schemas missing `additionalProperties: false` +- Recipe B — operations missing 422 +- Recipe F — operations missing `apikey` (base_params) +- Recipe I — tags violating kebab-case + +Full recipes in `references/oastools-audit-recipes.md`. Results belong in the "Convention deviations" section of the audit output below. + +## Audit output + +After completing the checklist, summarize findings as: + +1. **Issues found** — concrete problems that will cause test failures or spec inaccuracies +2. **Convention deviations** — things that work but don't follow project conventions +3. **Improvement opportunities** — optional enhancements (better descriptions, missing examples, undeclared headers) diff --git a/.agents/skills/openapi-spec/references/oastools-audit-recipes.md b/.agents/skills/openapi-spec/references/oastools-audit-recipes.md new file mode 100644 index 000000000000..7c12fd31fca5 --- /dev/null +++ b/.agents/skills/openapi-spec/references/oastools-audit-recipes.md @@ -0,0 +1,238 @@ +# oastools Audit Recipes + +Use these when authoring or auditing a declaration and you need a fact about the spec as a whole (not just one endpoint). For single-endpoint queries, see `references/spec-generation-and-verification.md`. + +## Before running any recipe: regenerate + +The generated spec is cache-like. A stale `.ai/tmp/openapi_public.yaml` produces false positives — e.g., a pre-migration spec may report tag-casing or path-prefix hits that the current codebase has already fixed. + +```bash +.claude/skills/openapi-spec/scripts/generate-spec.sh +``` + +All recipes below assume `F=.ai/tmp/openapi_public.yaml` is set as a shell variable; substitute the full path if not. + +## How each recipe is organized + +Each recipe states: what it answers, the command, a baseline count (a tripwire, not a spec — not every hit is a bug; read the notes), and which skill sections cite it. + +When a recipe's hit count goes down because you fixed drift, update the number here in the same PR. When it goes up, the PR introducing the regression should either fix it or document why in the recipe notes. + +--- + +## Convention audits + +Run these after any schema-touching change to catch drift a single-endpoint test run won't. + +### A. Object schemas missing `additionalProperties: false` + +```bash +oastools walk schemas -component -type object -detail -format json -q $F \ + | jq -rs '[.[] | select(.jsonPath | test("^\\$.components.schemas\\[[^.]+\\]$")) + | select(.schema.additionalProperties != false) | .name]' +``` + +Baseline: 12 hits, of which 6 are error-response schemas (`NotFoundResponse`, `ForbiddenResponse`, `UnauthorizedResponse`, `BadRequestResponse`, `NotImplementedResponse`, `JsonErrorResponse`) that intentionally omit `additionalProperties: false` — error payloads may carry extra debug fields. Real domain-schema drift is ~6 (`AuditReport`, `BlockCountdown`, `Counters`, `Response`, `SearchResult`, `StatsResponse`, `Status`). + +Used by: `inspection-checklist.md` §2d, `schema-conventions.md` §"Composite object schemas". + +### B. Operations missing `:unprocessable_entity` (422) + +```bash +oastools walk operations -detail -format json $F \ + | jq -rs '[.[] | select(.operation.responses | has("422") | not) + | "\(.method) \(.path)"]' +``` + +Baseline: 21 hits. Some are likely-intentional (legacy endpoints without CastAndValidate, CSV exports whose only failure mode is 404). Triage per endpoint. + +Used by: `inspection-checklist.md` §3c, `error-response-patterns.md` §"Choosing error responses for an operation". + +### F. Operations missing `base_params()` (no `apikey` query param) + +```bash +oastools walk operations -detail -format json $F \ + | jq -rs '[.[] | select((.operation.parameters // [] | map(.name) | index("apikey")) == null) + | "\(.method) \(.path)"]' +``` + +Baseline: 1 hit (`GET /v2/transactions/stats`). + +Used by: `inspection-checklist.md` §3b, `SKILL.md` §"base_params() — always include". + +### H. Operations missing summary or description + +```bash +oastools walk operations -detail -format json $F \ + | jq -rs '[.[] | select(.operation.summary == null or .operation.description == null) + | "\(.method) \(.path)"]' +``` + +Baseline: 0 hits. Any hit is a straight fix. + +Used by: `inspection-checklist.md` §3d. + +### I. Tags violating kebab-case + +```bash +oastools walk operations -detail -format json $F \ + | jq -rs '[.[] | .operation.tags[]?] | unique | map(select(contains("_")))' +``` + +Baseline: 0 hits. Any hit likely means a controller predates the kebab-case convention — migrate both the `tags(...)` call in the controller AND the registry entry in `specs/public.ex`. + +Used by: `inspection-checklist.md` §3a, `SKILL.md` §"Controller prerequisites". + +### O. Tags used by operations but missing from the top-level `tags:` registry + +```bash +oastools walk operations -detail -format json $F \ + | jq -rs --slurpfile spec <(yq -o=json '.tags // []' $F) \ + '([.[] | .operation.tags[]?] | unique) as $used + | ($spec[0] | map(.name)) as $declared + | $used - $declared' +``` + +Baseline: 0 hits. Any hit means a controller emits a tag not registered in `specs/public.ex` — Swagger UI will still show the tag on the operation, but ordering is undefined and the top-level `tags:` array is incomplete. Fix by adding the tag to `@default_api_categories` (base) or the appropriate `chain_type_category_tags/0` clause (chain-type), per `SKILL.md` §"Tag registry". + +This recipe is the mechanical safety net for the rule in Workflow A Step 4d — schema validation in tests does not check tags, so without this recipe the registration is silently missed. + +Used by: `SKILL.md` §Workflow A Step 4d, `SKILL.md` §"Tag registry". + +### P. URL prefix vs operation tag mismatch (heuristic) + +For each known cross-cutting URL prefix (`/v2/main-page/`, `/v2/csv-exports/`, etc.), find operations under that prefix whose tag list does not include the corresponding category tag. + +```bash +# main-page check +oastools walk operations -detail -format json $F \ + | jq -rs '[.[] | select(.path | startswith("/v2/main-page/")) + | select((.operation.tags // []) | index("main-page") | not) + | "\(.method) \(.path) tags=\(.operation.tags)"]' +``` + +Baseline: 0 hits expected. Repeat with other prefixes (`/v2/csv-exports/`, etc.) as needed. A hit means an operation under a cross-cutting URL prefix is tagged only by its hosting controller's domain — see `tagging-conventions.md` for whether to dual-tag or relocate. + +This recipe is heuristic — false positives are possible if a `/v2/main-page/...` URL genuinely should not be grouped with the rest of the main-page surface. Read the operation before applying a fix. + +Used by: `SKILL.md` §Workflow A Step 4d, `schema-conventions.md` §"Cross-cutting URL prefixes and tags". + +--- + +## Reuse and dedup scans + +Run before writing new schema code to find consolidation candidates. + +### D. Every inline enum in the spec + +```bash +oastools walk schemas -detail -format json -q $F \ + | jq -rs '[.[] | select(.schema.enum != null) + | {path: .jsonPath, enum: .schema.enum}]' +``` + +Baseline: 71 inline enums. Post-process by grouping on `.enum` to find duplicates worth extracting per `schema-conventions.md` §"Domain-scoped shared schemas". + +Used by: `schema-conventions.md` §"Domain-scoped shared schemas", `schema-conventions.md` §"Required: Ecto.Enum sync comments". + +### E. Duplicate parameter definitions within one domain + +```bash +oastools walk parameters -path '/v2//*' -detail -format json -q $F \ + | jq -rs '[group_by(.parameter.name)[] | select(length > 1) + | {name: .[0].parameter.name, count: length, paths: [.[].path]}]' +``` + +Returns any parameter declared on more than one endpoint under the given domain path. If the definitions are character-identical across endpoints, that's a helper extraction candidate per `inspection-checklist.md` §1e. Most domains return `[]`. + +Used by: `inspection-checklist.md` §1e. + +### G. Operations whose 200 response contains `oneOf` + +```bash +oastools walk operations -detail -resolve-refs -format json $F \ + | jq -rs '[.[] | select(.operation.responses."200".content."application/json".schema + | tostring | contains("oneOf")) + | "\(.method) \(.path)"]' +``` + +Baseline: 7 hits — all transaction-list endpoints. Use as precedent when modeling polymorphic responses. + +Used by: `schema-conventions.md` §"Polymorphic properties (`oneOf`)", `inspection-checklist.md` §2g. + +### N. Schema subset/superset scan + +```bash +oastools walk schemas -component -detail -format json -q $F \ + | jq -rs '[.[] | select(.jsonPath | test("^\\$.components.schemas\\[[^.]+\\]$")) + | {name, props: (.schema.properties // {} | keys)}] + | map(select(.props | length > 0))' +``` + +Emits `{name, props}` tuples for every component schema. Post-process with jq (set difference on `.props`) to find pairs where `A.props ⊆ B.props` — candidates for `extend_schema` reuse per `schema-conventions.md` §"Schema reuse and naming for related schemas". + +Used by: `SKILL.md` §Workflow A Step 3.2, `schema-conventions.md` §"Schema reuse and naming for related schemas". + +--- + +## Precedent / discovery lookups + +Run during authoring to find peer examples before writing new code. + +### J. Endpoints consuming a specific parameter helper + +```bash +oastools walk parameters -name -q $F +``` + +Authoritative about which endpoints *declare* the parameter in the spec — doesn't see controller-private helpers or inline params that happen to share a name. + +Used by: `parameter-discovery.md` §"Find which controllers use a helper". + +### K. All distinct parameter names reaching the spec + +```bash +oastools walk parameters -detail -format json $F \ + | jq -rs '[.[] | .parameter.name] | unique' +``` + +Baseline: 92 distinct names (vs ~48 `def.*_param` in `general.ex`). Diff to find: +- Zombie helpers — defined in `general.ex` but never reaching the spec. +- Inline-only params — declared in controllers, candidates for promotion to `general.ex` if they are reusable. + +Used by: `parameter-discovery.md` §"Browse all helpers". + +### L. Request body discovery across POST/PUT/PATCH ops + +```bash +oastools walk operations -method post -detail -format json $F \ + | jq -rs '.[] | select(.operation.requestBody) + | {path, body: .operation.requestBody.content."application/json".schema}' +``` + +Baseline: 1 op (`POST /v2/smart-contracts/{address_hash_param}/audit-reports`). Repeat with `-method put` / `-method patch` as needed. + +Used by: `request-body-security-headers.md` §"Discovering existing request body helpers". + +### M. Operations declaring `security:` + +```bash +oastools walk operations -detail -format json $F \ + | jq -rs '[.[] | select(.operation.security) | "\(.method) \(.path)"]' +``` + +Baseline: 0 in the public spec — `security:` is private/account-only. Regenerate against `specs/private.ex` for auth-bearing endpoints. + +Used by: `request-body-security-headers.md` §"Security schemes". + +### C. Properties missing `description:` in a named schema + +```bash +oastools walk schemas -name -detail -format json -q $F \ + | jq -rs '.[0].schema.properties | to_entries + | map(select(.value.description == null)) | map(.key)' +``` + +Produces a mechanical shortlist for review. Still needs human judgment — tautological descriptions (that restate the property name) pass this filter but are equally bad; see `schema-conventions.md` §"Property descriptions". + +Used by: `inspection-checklist.md` §2f, `schema-conventions.md` §"Property descriptions". diff --git a/.agents/skills/openapi-spec/references/parameter-discovery.md b/.agents/skills/openapi-spec/references/parameter-discovery.md new file mode 100644 index 000000000000..1da0c57f7e97 --- /dev/null +++ b/.agents/skills/openapi-spec/references/parameter-discovery.md @@ -0,0 +1,152 @@ +# Parameter Discovery Guide + +All parameter helper functions are centralized in a single file: +`apps/block_scout_web/lib/block_scout_web/schemas/api/v2/general.ex` + +They are auto-imported into every controller via `block_scout_web.ex`: +```elixir +import BlockScoutWeb.Schemas.API.V2.General +``` + +No controllers or other schema modules define their own parameter helpers — `general.ex` is the single source. + +## How to discover existing helpers + +### Find a specific helper + +Grep for the function name in `general.ex`: +``` +grep "def transaction_hash_param" in general.ex +``` + +Parameter helpers follow the naming convention `_param` for single params, and `_params` for grouped helpers. + +### Browse all helpers + +Grep for `def.*_param` in `general.ex` to see the full list. There are ~48 helpers organized into functional categories (described below). + +To see which parameter names actually reach the generated spec, run recipe K in `references/oastools-audit-recipes.md`. The spec surfaces ~92 distinct names — diff against `general.ex` to find zombie helpers (defined but never used) and inline-only names (declared in controllers, candidates for promotion to `general.ex`). + +### Find which controllers use a helper + +Grep for the function name across `controllers/api/v2/`: +``` +grep "transaction_hash_param()" in controllers/api/v2/**/*.ex +``` + +`oastools walk parameters -name -q .ai/tmp/openapi_public.yaml` (recipe J) is authoritative about which endpoints *declare* the parameter in the spec — it doesn't see controller-private helpers or inline `%Parameter{}` structs, but it won't miss anything wired into the public spec. + +## Naming conventions + +| Category | Naming pattern | Examples | +|---|---|---| +| Path identifiers | `_hash_param`, `_number_param`, `_id_param` | `address_hash_param`, `block_number_param`, `token_id_param` | +| Domain filters | `_param` | `token_type_param`, `direction_filter_param`, `transaction_filter_param` | +| Sorting | `sort_param(fields)`, `order_param` | `sort_param(["name", "holder_count"])` | +| Boolean toggles | descriptive name | `just_request_body_param` | +| Authentication | `_param` | `api_key_param`, `key_param`, `admin_api_key_param` | +| Paging factories | `define_paging_params(field_names)` | `define_paging_params(["index", "block_number"])` | + +## Functional categories + +When looking for existing helpers, think about which category the parameter falls into: + +**A. Path identifiers** — Entity identifiers in URL path segments. Grep: `def.*_hash_param\|def.*_number_param\|def.*_id_param`. + +**B. Domain filters** — Query params that filter list results. Grep: `def.*_filter_param\|def.*_type_param\|def.*q_param`. + +**C. Sorting** — `sort_param/1` takes a list of allowed sort fields, `order_param/0` provides asc/desc. Grep: `def sort_param\|def order_param`. + +**D. Paging factories** — `define_paging_params/1` generates multiple `%Parameter{in: :query}` structs from a list of field name strings. There are also `define_state_changes_paging_params/1` and `define_search_paging_params/1` variants. Grep: `def define_paging_params\|def define.*paging`. + +**E. Authentication** — `api_key_param`, `key_param` (bundled as `base_params()`), `admin_api_key_param` (header), `recaptcha_response_param`. Grep: `def.*api_key\|def.*key_param\|def recaptcha`. + +**F. Composite helpers** — `base_params()` returns `[api_key_param(), key_param()]`. Grep: `def base_params`. + +## Creating a new parameter helper + +### When to create a helper vs inline + +- **Create a helper in `general.ex`** if the parameter is a generic concept reusable across multiple controllers (entity hashes, block numbers, token types). +- **Create a private helper in the controller** if the parameter is domain-specific but used by multiple operations in the same controller (e.g., an Arbitrum message direction param shared by `messages` and `messages_count`). This avoids polluting `general.ex` with chain-specific concerns while preventing copy-paste duplication across operations. +- **Use inline `%Parameter{}`** only if the parameter is truly unique to a single operation. + +### Helper function template + +```elixir +@spec my_new_param() :: Parameter.t() +def my_new_param do + %Parameter{ + name: :my_new_param, # atom — must match route segment and controller pattern-match + in: :path, # :path | :query | :header + schema: FullHash, # a schema module or inline %Schema{} + required: true, # true for path params, typically false for query params + description: "Description of what this parameter does" + } +end +``` + +Place it in `general.ex` near other helpers of the same category. The file is organized roughly by category, though not strictly enforced. + +### Extract before you copy + +If the same structural payload shows up at 2+ sites, extract it. The rule is the same on both sides of the spec: + +- **Whole-`%Parameter{}` duplication** (same `name`, `schema`, `description`) → promote to a helper in `general.ex` (or a controller-private helper for chain-specific concerns), per "When to create a helper vs inline" above. +- **Same `schema:` payload across parameters with distinct `name`/`description`/`example`** → extract the payload to a leaf schema in `schemas/api/v2/general/.ex` and reference it via `schema: General.` from each `%Parameter{}`. The per-parameter description stays on the `%Parameter{}` struct, so the leaf can be description-less. Existing precedent: `IntegerString`, `Timestamp`, `FullHash`. +- **Same regex literal in multiple `pattern:` fields** → promote it to an accessor in `general.ex` alongside `integer_pattern/0`, `non_negative_integer_pattern/0`, `address_hash_pattern/0`, etc., and reuse via `General._pattern()`. + +This mirrors the schema-side dedup rule in `references/schema-conventions.md §"Domain-scoped shared schemas"` — same principle, applied wherever the duplication actually lives. + +### Inline parameter template + +For one-off parameters, define directly in the `operation` macro arguments: + +```elixir +operation :my_action, + parameters: [ + %OpenApiSpex.Parameter{ + name: :height, + in: :path, + schema: Schemas.General.IntegerString, + required: true, + description: "Block height" + } + | base_params() + ], + responses: [...] +``` + +## Schema types for parameters + +Parameter schemas reference leaf schema modules from `schemas/api/v2/general/`: + +| Type | Module | Use for | +|---|---|---| +| Full hash (0x + 64 hex) | `FullHash` | Transaction hashes, block hashes | +| Address hash (0x + 40 hex) | `AddressHash` | Address identifiers | +| Integer as string | `IntegerString` | Numeric IDs passed as strings | +| Hex string | `HexString` | Arbitrary hex data | +| Generic string | `%Schema{type: :string}` | Free-form text, API keys | +| Boolean | `%Schema{type: :boolean}` | Toggle flags | +| Enum | `%Schema{type: :string, enum: [...]}` | Fixed set of allowed values | + +To discover available leaf schemas, glob `schemas/api/v2/general/*.ex`. + +## The `define_paging_params` factory + +For paginated list endpoints, pagination cursor parameters are generated from a list of field names: + +```elixir +define_paging_params(["index", "block_number", "batch_log_index"]) +``` + +This creates one `%Parameter{in: :query, required: false}` per field name. The string names are converted to atoms as the parameter `:name`. Each gets an `IntegerString` schema by default. + +**Always include `"items_count"`** in the field list. The `next_page_params/5` function in `chain.ex` unconditionally adds `items_count` to every pagination cursor. If the operation doesn't declare it as a query param, CastAndValidate will reject next-page requests with "Unexpected field: items_count." Example: `define_paging_params(["id", "items_count"])`. + +There are specialized variants: +- `define_state_changes_paging_params/1` — for state change pagination +- `define_search_paging_params/1` — for search result pagination (uses object params) + +Grep `define_paging_params\|define_state_changes\|define_search` in `general.ex` to see their implementations. diff --git a/.agents/skills/openapi-spec/references/request-body-security-headers.md b/.agents/skills/openapi-spec/references/request-body-security-headers.md new file mode 100644 index 000000000000..cfed1fe42544 --- /dev/null +++ b/.agents/skills/openapi-spec/references/request-body-security-headers.md @@ -0,0 +1,207 @@ +# Request Bodies, Security Schemes, and Headers + +## Request bodies (POST/PUT/PATCH endpoints) + +### The pattern + +Request bodies are declared via the `request_body:` key in the `operation/2` macro: + +```elixir +operation :my_action, + summary: "Create a resource", + description: "Creates a new resource.", + request_body: my_resource_request_body(), + parameters: base_params(), + responses: [...] +``` + +The value is always a function call returning an `%OpenApiSpex.RequestBody{}` struct. + +### Helper function pattern + +```elixir +def my_resource_request_body do + %OpenApiSpex.RequestBody{ + content: %{ + "application/json" => %OpenApiSpex.MediaType{ + schema: %OpenApiSpex.Schema{ + type: :object, + properties: %{ + field_a: %OpenApiSpex.Schema{type: :string}, + field_b: %OpenApiSpex.Schema{type: :integer} + }, + required: [:field_a, :field_b] + } + } + } + } +end +``` + +### Naming convention + +`_request_body()` — e.g., `admin_api_key_request_body()`, `audit_report_request_body()`. + +### Where to place helpers + +- **General/shared**: `schemas/api/v2/general.ex` (auto-imported) +- **Domain-specific**: `schemas/api/v2/.ex` (must be aliased in the controller) + +### Discovering existing request body helpers + +Grep for `request_body` in `general.ex` and domain-specific schema files: +``` +grep "def.*_request_body" in schemas/api/v2/**/*.ex +``` + +To see request bodies actually wired into the generated spec (not just defined), run recipe L in `references/oastools-audit-recipes.md`. Useful because grep finds helpers that may not be referenced by any operation. + +### How CastAndValidate handles request bodies + +After casting, body params are written to `conn.body_params` with **atom keys** (not string keys). Controllers read casted body params like: +```elixir +Map.get(conn.body_params, :email) +``` + +Body params are NOT merged into `conn.params` — they must be read from `conn.body_params` separately. + +### Inline schemas vs module references + +Existing request body schemas are defined **inline** within the `%RequestBody{}` struct, not as separate named schema modules. This is the established convention for request bodies in the codebase. + +### The library also supports tuple shorthands + +`open_api_spex` supports alternative forms for `request_body:`: +1. `%RequestBody{}` struct (what Blockscout uses exclusively) +2. 3-tuple: `{"description", "application/json", SchemaModule}` +3. 4-tuple: `{"description", "application/json", SchemaModule, opts}` + +Stick with the `%RequestBody{}` struct to stay consistent with existing code. + +### File upload / multipart + +Currently, file upload endpoints (like VerificationController) have **no OpenAPI annotations**. There is no established pattern for `"multipart/form-data"` in the codebase. If you need to annotate a multipart endpoint, this would be a new pattern — flag it for discussion. + +--- + +## Security schemes + +### Component-level scheme definition + +Security schemes are defined in spec aggregator modules, not in controllers. The private API spec (`specs/private.ex`) defines: + +```elixir +components: %Components{ + securitySchemes: %{ + "dynamic_jwt" => %SecurityScheme{type: "http", scheme: "bearer", bearerFormat: "JWT"} + } +} +``` + +### Per-operation security + +The `operation` macro supports a `security:` key: + +```elixir +operation :authenticate_via_dynamic, + summary: "Authenticate via Dynamic JWT", + security: [%{"dynamic_jwt" => []}], + responses: [...] +``` + +This references the scheme defined in components. The `[]` in the value is the list of required scopes (empty = no specific scopes required). + +### When to use security + +Most public API endpoints don't use `security:`. It's primarily for private/account API endpoints that require authentication. To check if an endpoint needs security: + +1. Look at the controller's plugs — does it use an authentication plug? +2. Check the router — is the endpoint in the `AccountRouter` or behind an auth pipeline? +3. Check if the controller reads `conn.assigns.current_user` or similar auth state. + +### Discovering existing security patterns + +Grep for `security:` in controller files: +``` +grep "security:" in controllers/**/*.ex +``` + +Spec-side lookup: recipe M in `references/oastools-audit-recipes.md`. Empty against the public spec — `security:` is private/account-only. Regenerate against `specs/private.ex` to see auth-bearing endpoints. + +--- + +## Header parameters + +### Request headers + +Header parameters use `%Parameter{in: :header}`: + +```elixir +def my_header_param do + %Parameter{ + name: :"x-api-key", # atom with the exact header name (case-insensitive matching) + in: :header, + schema: %Schema{type: :string}, + required: false, + description: "Description of the header" + } +end +``` + +`CastAndValidate` reads from `conn.req_headers` with case-insensitive matching — header parameters are cast and validated identically to path/query parameters. + +### Discovering existing header params + +Grep for `in: :header` in `general.ex`: +``` +grep "in: :header" in schemas/api/v2/general.ex +``` + +### Undeclared cross-cutting headers + +Several request headers are consumed at runtime but not declared in OpenAPI specs: +- `show-scam-tokens` — consumed by multiple controllers via `fetch_scam_token_toggle` +- `recaptcha-v2-response` / `recaptcha-v3-response` — consumed by rate limiting +- `x-api-v2-temp-token` — consumed by rate limiting + +This is a known gap. When adding these to specs, use the "separate grouped helpers" approach: + +```elixir +# Individual helpers in general.ex +def show_scam_tokens_header_param do + %Parameter{ + name: :"show-scam-tokens", in: :header, + schema: %Schema{type: :string, enum: ["true", "false"]}, + required: false, + description: "When 'true', includes tokens flagged as potential scams." + } +end + +# Grouped helper for convenience +def scam_token_header_params, do: [show_scam_tokens_header_param()] +``` + +Then add to only the operations that actually use them: +```elixir +parameters: base_params() ++ scam_token_header_params() ++ define_paging_params([...]) +``` + +To identify which controllers consume `show-scam-tokens`, grep for `fetch_scam_token_toggle` in controllers. + +### Response headers + +Response headers use the `OpenApiSpex.Header` struct and are declared via a 4-tuple response form: + +```elixir +responses: [ + ok: {"Success description", "application/json", Schemas.MyDomain.Response, + headers: %{ + "x-ratelimit-limit" => %OpenApiSpex.Header{ + description: "Max requests per window", + schema: %Schema{type: :integer} + } + }} +] +``` + +Currently, **no response headers are declared** in the codebase (rate-limit, CSRF, temp token headers are all undeclared). This is a known gap. If adding response headers, this 4-tuple form (changing from the standard 3-tuple) is the way to do it. diff --git a/.agents/skills/openapi-spec/references/schema-conventions.md b/.agents/skills/openapi-spec/references/schema-conventions.md new file mode 100644 index 000000000000..5750a10636ab --- /dev/null +++ b/.agents/skills/openapi-spec/references/schema-conventions.md @@ -0,0 +1,601 @@ +# Schema Conventions + +All schema modules live under `apps/block_scout_web/lib/block_scout_web/schemas/api/v2/`. + +## Directory structure conventions + +These conventions are inferred from consistent patterns — there's no written doc. + +### Base entity + subdirectory pattern + +Major domain objects have a base file at the root plus a same-named subdirectory for sub-schemas: + +``` +schemas/api/v2/ + transaction.ex # base Transaction schema (properties, types) + transaction/ + response.ex # Transaction.Response (extends base with title/description) + fee.ex # Transaction.Fee + counters.ex # Transaction.Counters + state_change.ex # Transaction.StateChange +``` + +This pattern applies to: `address`, `block`, `blob`, `token`, `transaction`, `withdrawal`, `smart_contract`, and chain-specific domains (`optimism/batch`, `celo/election_reward`, etc.). + +### When to create a subdirectory + +Create a subdirectory when 2+ sub-schemas exist for a domain entity. Simple leaf entities (`CoinBalance`, `Log`, `InternalTransaction`) have no subdirectory — just a single file. + +### Shared primitives in `general/` + +`general/` contains ~22 reusable type schemas: `AddressHash`, `FullHash`, `IntegerString`, `Timestamp`, nullable variants, etc. These are leaf schemas referenced by property types across all domain schemas. + +To discover available primitives, glob `schemas/api/v2/general/*.ex`. + +### Domain-scoped shared schemas + +Domain subdirectories (e.g., `arbitrum/`, `optimism/`) can also contain leaf schemas shared across multiple schemas within that domain. This is the same pattern as `general/` primitives, but scoped to a specific chain or domain. + +**When to extract:** When 2+ schemas in the same domain directory define an identical inline structure — either an object sub-schema with the same properties/types, or an enum with the same values. The trigger is duplication, not speculation: don't pre-extract a structure used by only one schema. + +To find duplicates mechanically: recipe D in `references/oastools-audit-recipes.md` enumerates every inline enum in the spec (group by `.enum` array); recipe N gives a property-set subset/superset scan for shared object structures. + +**Why it matters:** +- **For sub-objects** (e.g., a `commitment_transaction` block with 4 properties): if the structure changes, every inline copy must be found and updated. A shared schema eliminates this drift risk. +- **For enums** (e.g., a `batch_data_container` enum): each inline copy needs its own "keep in sync with Ecto" comment (see "Required: Ecto.Enum sync comments" below). A shared enum schema consolidates that comment to one location — the leaf module — so there's one place to update when Ecto enum values change. + +**Where to put them:** In the domain subdirectory alongside the schemas that use them: `arbitrum/commitment_transaction.ex`, `arbitrum/batch_data_container.ex`. + +**Template — shared object sub-schema:** + +```elixir +defmodule BlockScoutWeb.Schemas.API.V2.Arbitrum.CommitmentTransaction do + @moduledoc """ + Parent chain transaction that committed a batch. + + Shared across Batch and BatchForList schemas. + """ + require OpenApiSpex + + alias BlockScoutWeb.Schemas.API.V2.General + alias OpenApiSpex.Schema + + OpenApiSpex.schema(%{ + description: "Parent chain transaction that committed the batch.", + type: :object, + properties: %{ + hash: General.FullHashNullable, + block_number: %Schema{type: :integer, minimum: 0, nullable: true}, + timestamp: General.TimestampNullable, + status: %Schema{type: :string, nullable: true, description: "Finalization status."} + }, + required: [:hash, :block_number, :timestamp, :status], + additionalProperties: false + }) +end +``` + +Then reference it in both schemas: + +```elixir +# In Batch and BatchForList: +commitment_transaction: Arbitrum.CommitmentTransaction +``` + +**Template — shared enum leaf schema:** + +```elixir +defmodule BlockScoutWeb.Schemas.API.V2.Arbitrum.BatchDataContainer do + @moduledoc """ + Data availability container type for Arbitrum batches. + """ + require OpenApiSpex + + # Enum values must be kept in sync with Explorer.Chain.Arbitrum.L1Batch :batch_container field. + OpenApiSpex.schema(%{ + type: :string, + enum: ["in_blob4844", "in_calldata", "in_celestia", "in_anytrust", "in_eigenda"], + nullable: true, + description: "Data availability container type." + }) +end +``` + +Then reference it in both schemas: + +```elixir +batch_data_container: Arbitrum.BatchDataContainer +``` + +Note: the "keep in sync" comment lives in the leaf module. Schemas that reference it don't need their own copy — the single source of truth is the leaf module. + +### Chain-specific schemas + +Chain-specific schemas get top-level subdirectories: `optimism/`, `scroll/`, `celo/`, `zilliqa/`, `beacon/`. These map to chain-conditional router scopes. + +### File naming + +Snake_case files, CamelCase modules: `transaction/fee.ex` contains `BlockScoutWeb.Schemas.API.V2.Transaction.Fee`. + +## Schema composition patterns + +### Leaf schemas (primitives) + +Single-purpose modules — one-liner `OpenApiSpex.schema/1` calls: + +```elixir +# general/full_hash.ex +defmodule BlockScoutWeb.Schemas.API.V2.General.FullHash do + require OpenApiSpex + alias BlockScoutWeb.Schemas.API.V2.General + + OpenApiSpex.schema(%{type: :string, pattern: General.full_hash_pattern(), nullable: false}) +end +``` + +### Composite object schemas + +Larger schemas with `type: :object`: + +```elixir +OpenApiSpex.schema(%{ + title: "TransactionFee", + description: "Transaction fee details", + type: :object, + required: [:type, :value], + properties: %{ + type: %Schema{type: :string, enum: ["maximum", "actual"]}, + value: General.IntegerStringNullable + }, + additionalProperties: false # always set this on object schemas +}) +``` + +Key conventions: +- **`additionalProperties: false`** — always set on object schemas. This enables test-time enforcement: any key the view emits that isn't in the schema causes a test failure. Spec-wide audit: recipe A in `references/oastools-audit-recipes.md`. +- **`required:`** — list all keys that the view always emits. +- **Property values** can be schema modules (like `General.IntegerStringNullable`) or inline `%Schema{}` structs. + +### Polymorphic properties (`oneOf`) + +When a view branches on a discriminator field and emits different object shapes per branch, model the property using `oneOf`. Each variant is a standalone `%Schema{type: :object}` with its own properties and `additionalProperties: false`. The discriminator field (the field the view branches on) must appear in every variant so validation can match exactly one. + +**Existing precedent:** `transaction.ex` uses `oneOf` for the `revert_reason` property (line ~392), which can be either a decoded input object or a raw hex string wrapper. For the full list of endpoints whose 200 response currently uses `oneOf`, run recipe G in `references/oastools-audit-recipes.md`. + +**Structural pattern:** + +```elixir +polymorphic_field: %Schema{ + oneOf: [ + %Schema{ + type: :object, + properties: %{discriminator: DiscriminatorType, field_a: ...}, + required: [:discriminator, :field_a], + additionalProperties: false + }, + %Schema{ + type: :object, + properties: %{discriminator: DiscriminatorType, field_b: ..., field_c: ...}, + required: [:discriminator, :field_b, :field_c], + additionalProperties: false + } + ], + description: "Structure varies by `discriminator` value." +} +``` + +**Constrain the discriminator per variant.** Each variant's discriminator property must be narrowed to the specific value(s) that identify it — use an inline `%Schema{type: :string, enum: [...]}` instead of referencing the shared enum schema. This prevents logically invalid combinations from passing validation (e.g., `batch_data_container: "in_calldata"` paired with `data_hash` + `signers` fields that only exist on the `in_anytrust` variant). + +**Concrete template (batch data availability with 2 variants shown):** + +```elixir +data_availability: %Schema{ + oneOf: [ + # Variant: nil / in_blob4844 / in_calldata (no extra fields) + %Schema{ + type: :object, + properties: %{ + batch_data_container: %Schema{type: :string, enum: ["in_blob4844", "in_calldata"], nullable: true} + }, + required: [:batch_data_container], + additionalProperties: false + }, + # Variant: in_anytrust + %Schema{ + type: :object, + properties: %{ + batch_data_container: %Schema{type: :string, enum: ["in_anytrust"]}, + data_hash: %Schema{type: :string, nullable: true}, + timeout: %Schema{type: :string, nullable: true}, + bls_signature: %Schema{type: :string, nullable: true}, + signers: %Schema{type: :array, items: %Schema{type: :string}} + }, + required: [:batch_data_container, :data_hash, :timeout, :bls_signature, :signers], + additionalProperties: false + } + # ... additional variants (each with its own enum constraint) + ], + description: "Data availability info. Structure varies by `batch_data_container`." +} +``` + +**Catch-all branch.** If the view has a fallthrough clause (e.g., `value -> %{"field" => to_string(value)}`), model it as the minimal variant containing only the discriminator. + +**Notes:** +- `discriminator:` (the OpenAPI 3.0 keyword) is optional in OpenApiSpex — the `oneOf` alone is sufficient for validation. OpenApiSpex checks each variant and requires exactly one to match. +- Each variant gets `additionalProperties: false`, which means test-time validation will catch extra or missing keys per variant — not just on the top-level schema. +- For simple variants (1-2 properties beyond the discriminator), inline schemas inside the `oneOf` list are fine. For larger or reusable variants, extract each into a domain schema module. + +### Response schemas + +Response schemas extend a base entity schema with title/description: + +```elixir +# transaction/response.ex +OpenApiSpex.schema( + Transaction.schema() + |> Helper.extend_schema( + title: "TransactionResponse", + description: "Transaction response" + ) + |> ChainTypeCustomizations.chain_type_fields() +) +``` + +The pattern is: base schema -> extend with metadata -> apply chain-type fields. + +### Helper.extend_schema/2 + +Located at `schemas/helper.ex`. Merges `:properties`, `:required`, `:title`, `:description`, `:nullable`, and `:enum` into an existing schema map: +- Properties are merged (new keys added, existing overwritten) +- Required lists are concatenated +- Scalar fields (title, description, nullable) are replaced + +```elixir +schema_map +|> Helper.extend_schema( + title: "ExtendedSchema", + properties: %{new_field: %Schema{type: :string}}, + required: [:new_field] +) +``` + +**Reusing a leaf primitive with a per-property override.** When you want the type/format/nullable of a `general/` leaf (`Timestamp`, `IntegerString`, `FullHash`, …) *and* a per-property field like `description:`, `example:`, or a flipped `nullable:`, use `Helper.extend_schema` at the property position: + +```elixir +timestamp: + Helper.extend_schema(General.Timestamp.schema(), + description: "Block timestamp of the parent transaction." + ) +``` + +This inlines the leaf's shape and overlays the description, no `allOf` casting layer involved. + +Avoid `%Schema{allOf: [Leaf], description: "..."}` as the overlay mechanism. `allOf` is for *object* composition: it works fine for object leaves like `Address` (and `advanced_filter.ex` does this for `from`/`to`/`created_contract`), but for primitive leaves with a non-trivial `format:` cast — `Timestamp`'s `format: :"date-time"` casts strings to `%DateTime{}`, `Decimal`-typed leaves cast to `%Decimal{}` — `OpenApiSpex.Cast.AllOf` enumerates the per-branch results as maps and fails on non-Enumerable structs. The `extend_schema` form sidesteps the cast composition entirely. + +### Schema reuse and naming for related schemas + +When multiple endpoints render the same underlying entity with different levels of detail (e.g., a list endpoint emits 7 fields while a main-page widget emits only 4), avoid duplicating properties across standalone schemas. Instead, use `extend_schema` to build one from the other. + +**When to apply:** This is a post-factum decision — evaluate only when you're creating a new schema and discover an existing one in the same domain with overlapping properties. Don't speculatively refactor schemas that have only one consumer. + +**Identifying the relationship:** +1. Compare the property sets of the existing and new schemas. +2. Determine which is the subset (fewer properties) and which is the superset. +3. Cross-reference with the Ecto schema to see which OpenAPI schema most closely matches the full entity. + +Mechanical candidate detection across all component schemas: recipe N in `references/oastools-audit-recipes.md`. + +**Naming convention:** +- The schema whose properties most closely match the Ecto schema should be named after the entity: `` (e.g., `Message`). This is the "full" representation. +- The schema with fewer properties (a subset) should be named `Minimal` (e.g., `MinimalMessage`). This clearly communicates it's a reduced view without tying the name to a specific endpoint. +- `extend_schema` only adds properties — it cannot subtract. So `Minimal` is always the base that `` extends. + +**Renaming existing schemas:** If an existing schema was named for its endpoint (e.g., `MessageForMainPage`) and turns out to be the minimal subset, rename it to `Minimal`. Update all references in controller operations, tests, and any other schemas that use it. Then create the full `` schema extending it. + +**Critical: always pass `title:` when extending.** Without an explicit `title:`, the child schema inherits the parent's auto-generated title. OpenApiSpex uses titles as keys in its internal schema registry, so two schemas with the same title collide — the child silently overwrites the parent. This causes test failures on the parent's endpoints because the wrong schema (with extra required fields) is used for validation. + +**Template:** + +```elixir +defmodule BlockScoutWeb.Schemas.API.V2.Arbitrum.Message do + @moduledoc """ + Full Arbitrum cross-chain message schema. + + Extends `MinimalMessage` with: id, origination_address_hash, status. + """ + + require OpenApiSpex + + alias BlockScoutWeb.Schemas.API.V2.Arbitrum.MinimalMessage + alias BlockScoutWeb.Schemas.API.V2.General + alias BlockScoutWeb.Schemas.Helper + alias OpenApiSpex.Schema + + OpenApiSpex.schema( + MinimalMessage.schema() + |> Helper.extend_schema( + title: "Arbitrum.Message", # REQUIRED — prevents registry collision + description: "Full Arbitrum cross-chain message.", + properties: %{ + id: %Schema{type: :integer, minimum: 0}, + origination_address_hash: General.AddressHashNullable, + status: %Schema{type: :string, enum: ["initiated", "sent", "confirmed", "relayed"]} + }, + required: [:id, :origination_address_hash, :status] + ) + ) +end +``` + +### Paginated response wrapper + +For list endpoints, use `General.paginated_response/1`: + +```elixir +# In the operation macro +responses: [ + ok: {"Token transfer list", "application/json", + paginated_response( + items: Schemas.TokenTransfer, + next_page_params_example: %{"index" => 442, "block_number" => 21307214} + )} +] +``` + +This wraps the item schema in a standard envelope: +```json +{"items": [...], "next_page_params": {...} | null} +``` + +The `next_page_params` is typed as a generic `type: :object, nullable: true` with no fixed properties — only the `example` documents expected keys. + +## Chain-type customization pattern + +Schemas and views use the same dispatch mechanism for chain-specific fields: + +```elixir +# In a ChainTypeCustomizations module (co-located in the parent schema file) +def chain_type_fields(schema) do + case chain_type() do + :zksync -> schema |> Helper.extend_schema(properties: %{zksync: @zksync_schema}) + :arbitrum -> schema |> Helper.extend_schema(properties: %{arbitrum: @arbitrum_schema}) + :optimism -> schema |> Helper.extend_schema(properties: %{l1_fee: ...}) + _ -> schema + end +end +``` + +ChainTypeCustomizations modules are almost always defined at the top of the same `.ex` file as the schema they modify. One exception: `general/implementation/chain_type_customizations.ex`. + +When creating a new schema that needs chain-type support: +1. Define the base schema with default-chain properties +2. Add a `ChainTypeCustomizations` module in the same file +3. Pipe the schema through `ChainTypeCustomizations.chain_type_fields/1` + +## Creating a new schema module + +### Template for a new object schema + +```elixir +defmodule BlockScoutWeb.Schemas.API.V2.MyDomain do + alias OpenApiSpex.Schema + alias BlockScoutWeb.Schemas.API.V2.General + + require OpenApiSpex + + @moduledoc "Schema for MyDomain entity" + + OpenApiSpex.schema(%{ + title: "MyDomain", + description: "Description of this entity", + type: :object, + required: [:field_a, :field_b], + properties: %{ + field_a: %Schema{type: :string, description: "What field_a is"}, + field_b: General.IntegerString, + field_c: %Schema{type: :string, nullable: true} + }, + additionalProperties: false + }) +end +``` + +### Template for a response wrapper + +```elixir +defmodule BlockScoutWeb.Schemas.API.V2.MyDomain.Response do + alias BlockScoutWeb.Schemas.API.V2.MyDomain + alias BlockScoutWeb.Schemas.Helper + + require OpenApiSpex + + OpenApiSpex.schema( + MyDomain.schema() + |> Helper.extend_schema( + title: "MyDomainResponse", + description: "MyDomain response" + ) + ) +end +``` + +### Aliasing in controllers + +The `block_scout_web.ex` `:controller` block provides: +```elixir +alias BlockScoutWeb.Schemas.API.V2, as: Schemas +``` + +So in controllers you reference schemas as `Schemas.MyDomain.Response`. + +## Determining property types from Ecto schemas + +The view layer is lossy about types — it renders everything as JSON primitives. To declare precise OpenAPI types, cross-reference with the underlying Ecto schema in the Explorer app (`apps/explorer/lib/explorer/chain/.ex`). + +### Discovery process + +1. Identify the Ecto schema module for the entity. The view's `prepare_*` function usually receives a struct — trace its type back to the `Explorer.Chain.*` module. +2. Read the Ecto schema's `schema` block and `@type` definition to see the field types. +3. Grep for `Ecto.Enum` in the file to find enum fields. + +### Computed values (no direct Ecto field) + +Sometimes the view emits a key whose value is not bound to a single Ecto field — it is produced by a helper such as `assign_/1`, `prepare_/1`, or a `case` expression in `prepare_*`. The Ecto schema alone won't tell you the value's shape; you have to read the helper. + +Read the helper's branches. If every branch returns a value drawn from a closed set — string literals, atoms converted to strings, calls into `Module.valid_types/0`, `Ecto.Enum.values/2` — model the property as `enum` and assemble the values from every source the helper consults. The sync comment should name each source so a future maintainer knows what to update if any of them changes. + +If the helper has an open branch (e.g. a `_ -> error_reason` clause that propagates a free-form string), the set is not closed and `enum` would misrepresent the API. Keep `type: :string` in that case and lean on the description to enumerate the well-known values. + +### Ecto type → OpenAPI type mapping + +| Ecto type | OpenAPI schema | Notes | +|---|---|---| +| `Ecto.Enum` with values | `%Schema{type: :string, enum: [...values...]}` | Extract the atom values list from the Ecto schema. Convert atoms to strings for the enum. | +| `:string` | `%Schema{type: :string}` | | +| `:integer` | `%Schema{type: :integer}` | If the view converts large integers to strings (common for Wei values), use a string-typed schema — see "Leaf primitives encode the most permissive form" below before reaching for `IntegerString`. | +| `:boolean` | `%Schema{type: :boolean}` | | +| `:decimal` | `%Schema{type: :string}` or `FloatString` | Decimals are typically serialized as strings to preserve precision | +| `Explorer.Chain.Hash.Full` | `General.FullHash` | 0x + 64 hex chars | +| `Explorer.Chain.Hash.Address` | `General.AddressHash` | 0x + 40 hex chars | +| `:utc_datetime_usec` | `General.Timestamp` or `General.TimestampNullable` | ISO 8601 datetime string | +| `:map` | `%Schema{type: :object}` | Check what keys the view actually emits | +| `{:array, inner_type}` | `%Schema{type: :array, items: ...}` | Map the inner type recursively | + +### Leaf primitives encode the most permissive form + +Leaf schemas in `general/` are deliberately loose so they can be reused widely. `IntegerString`, for instance, accepts any integer literal — *including negative ones* — because nothing about the name commits it to a sign. Before reusing such a leaf, check whether the property's domain is actually stricter: a Wei amount, a gas value, a fee, a balance, a count, an index — these are non-negative by definition; a fixed-length identifier has a length constraint; a hex-only field has a character-set constraint. + +If the leaf is looser than the domain warrants, **define a stricter pattern or a stricter leaf** rather than reusing the loose one and accepting the accidental permissiveness. Reuse should narrow when the domain narrows, not widen the schema to match the loosest available helper. + +The pragmatic ordering: + +1. If a stricter helper already exists in `general.ex` (e.g. `non_negative_integer_pattern/0`, `address_hash_pattern/0`), use it via `pattern: General.()`. +2. If 2+ properties want the same stricter shape and no helper exists, add the helper or extract a stricter leaf — see "Domain-scoped shared schemas" and the parameter-discovery reference for the dedup rule. +3. Only inline a one-off `pattern:` literal when the constraint really is unique to a single property. + +Note: `minimum:` is a JSON-Schema *numeric* keyword and is silently ignored on `type: :string` schemas. To express "non-negative" on a string-encoded integer, use a pattern that excludes the leading `-`, not `minimum: 0`. + +### Required: Ecto.Enum sync comments + +**Every `enum:` property in an OpenAPI schema must have a comment pointing to the source Ecto field.** There is no automatic sync between Ecto enums and OpenAPI enums — if someone adds a new value to the Ecto enum without updating the OpenAPI schema, `CastAndValidate` will reject the new value on input, and test-time validation will fail on output only if a test exercises that specific value. The comment is the only signal that tells the next developer where to look. + +Format: +```elixir +# Enum values must be kept in sync with Explorer.Chain. : field. +``` + +When using a shared enum leaf schema (see "Domain-scoped shared schemas" above), the comment lives in the leaf module only — schemas that reference it don't need their own copy. When using an inline enum, the comment goes directly above the `%Schema{type: :string, enum: [...]}` definition. + +Before writing an inline enum, check existing schemas in the same domain — if another schema already defines the same enum, extract it into a shared leaf schema instead of duplicating it (and the comment). + +### Ecto.Enum example + +If the Ecto schema has: +```elixir +field(:batch_data_container, Ecto.Enum, values: [:in_blob4844, :in_calldata, :in_celestia]) +``` + +The OpenAPI property should be: +```elixir +# Enum values must be kept in sync with Explorer.Chain.Arbitrum.L1Batch :batch_data_container field. +batch_data_container: %Schema{ + type: :string, + enum: ["in_blob4844", "in_calldata", "in_celestia"], + nullable: true # if the field can be nil +} +``` + +### Nullable fields + +If the Ecto schema field can be `nil` (not in `@required_attrs`, or the view conditionally emits it), the OpenAPI property should have `nullable: true`. If the key is always present but sometimes null, keep it in `required:` and set `nullable: true`. If the key is sometimes absent entirely, remove it from `required:`. + +**Do not use `type: :null` in `anyOf`/`oneOf`, and do not use array types like `type: [:string, :null]`.** These are OpenAPI 3.1 / JSON Schema 2020-12 patterns. Blockscout's spec is OpenAPI 3.0 (open_api_spex v3.22), which predates the null type and supports nullability exclusively through the `nullable: true` keyword. + +```elixir +# Correct — OpenAPI 3.0 +block_number: %Schema{type: :integer, nullable: true} + +result: %Schema{nullable: true, allOf: [result_schema]} + +# Wrong — OpenAPI 3.1 syntax, invalid in 3.0 +block_number: %Schema{anyOf: [%Schema{type: :null}, %Schema{type: :integer}]} + +result: %Schema{anyOf: [%Schema{type: :null}, result_schema]} +``` + +When combining nullability with `allOf`/`oneOf`/`anyOf`, set `nullable: true` alongside the composition keyword on the same schema — don't express null as a separate branch. + +## Property descriptions + +Not every property needs a `description:` — but ambiguous ones without descriptions become a guessing game for API consumers who aren't reading the source code. + +### When to add a description + +Add a description when the property name alone doesn't convey what the value represents: + +- **Domain jargon.** Names inherited from protocol internals that mean nothing outside that context. Example: `before_acc_hash` and `after_acc_hash` are Arbitrum Nitro accumulator hashes — a consumer seeing "acc hash" has no idea this refers to a cumulative hash over sequencer inbox messages. +- **Ambiguous roles.** Names where the "who" or "what" is unclear. Example: `caller_address_hash` — caller of what? Is this the EOA that signed the transaction, or the contract that emitted the event? `destination_address_hash` — destination on which chain? +- **Unclear chain context.** In cross-chain schemas, a bare `block_number` could refer to either the Parent chain or the Rollup. If the containing schema's description doesn't disambiguate, the property must. +- **Opaque Solidity mirrors.** Field names lifted directly from contract events or structs. Example: `callvalue` mirrors Solidity's `msg.value` but reads as one opaque word to REST consumers — describe it as the native coin amount in wei. +- **Enum lifecycle.** When enum values represent a state machine, list the progression and what triggers each transition. A `status` field with `["initiated", "sent", "confirmed", "relayed"]` is meaningless without knowing what moves a message from "sent" to "confirmed". +- **Tautological descriptions.** "Withdrawal status." on a `status` property inside a Withdrawal schema adds zero information — it restates the name. Either write a real description or omit it; a tautology is worse than nothing because it signals "this was reviewed" when it wasn't. + +### When descriptions are unnecessary + +- **Self-documenting compound names.** `origination_transaction_block_number`, `completion_transaction_hash` — the full context is in the name. +- **Well-known token primitives.** `token.symbol`, `token.name`, `token.decimals` — universally understood in the domain. +- **Context from the parent schema.** If the schema-level `description:` already explains the object's role and the property name is unambiguous within that context, a per-property description is redundant. + +### Avoid backend jargon + +API consumers don't read Blockscout source, so keep database columns (`refetch_needed`), Ecto terms ("preloaded", `NotLoaded`), and indexer/cache internals out of descriptions. Describe what the value means or why it can be null from the client's perspective: prefer "null when the count is unavailable" over "null when the association was not preloaded", and "true when the block is scheduled for re-fetch" over "mirrors the `refetch_needed` DB column". + +### Quality standard + +A description should tell the consumer something they cannot infer from the property name alone. If you can delete the description and the property is equally clear, it wasn't worth writing. + +To list undocumented properties on a given schema deterministically: recipe C in `references/oastools-audit-recipes.md`. Tautologies pass that filter — still read each description. + +### Where to find the meaning + +When a property name is ambiguous, cross-reference these sources to determine what it actually represents: + +1. **Ecto schema** — field comments, type annotations, and module docs in `apps/explorer/lib/explorer/chain/`. +2. **Solidity source** — the event or struct the data originates from (e.g., `L2ToL1Tx` event for Arbitrum withdrawals). Contract ABIs clarify which field is the sender, recipient, value, etc. +3. **View's `prepare_*` functions** — trace how the Ecto struct is transformed into the JSON map. The transformation logic often reveals the semantic meaning. + +### Example: before and after + +```elixir +# Bad — tautological, adds nothing +status: %Schema{type: :string, enum: [...], description: "Withdrawal status."} + +# Good — explains the lifecycle +status: %Schema{ + type: :string, + enum: ["initiated", "sent", "confirmed", "relayed"], + description: + "Cross-chain message lifecycle: initiated (tx submitted on Rollup) → " <> + "sent (included in an outbox entry) → confirmed (batch committed to " <> + "Parent chain) → relayed (executed on Parent chain)." +} +``` + +## Examples in schemas + +Three patterns exist, all optional: + +1. **Inline on a property**: `field: %Schema{type: :string, example: "transfer"}` +2. **Top-level on schema**: `example: %{field_a: "value", field_b: 42}` +3. **`next_page_params_example`**: passed to `paginated_response/1` for unstructured paging objects + +Convention: use examples when the type is generic and readers need real-value context. Don't add examples to leaf pattern-based schemas (`FullHash`, `AddressHash`, etc.) — their type and pattern are self-documenting. + +## Cross-cutting URL prefixes and tags + +**Merge behavior.** Per-operation `tags: [...]` is **appended** to the module-level `tags(...)`, not substituted. So an operation in a controller with `tags(["arbitrum"])` and a per-operation `tags: ["main-page"]` ends up with both tags and appears under both Swagger groups (dual-tagging). + +**When to dual-tag.** When the operation's URL lives under a cross-cutting prefix that is itself a registered tag (`/v2/main-page/...`, `/v2/csv-exports/...`), add `tags: [""]` per-operation. Default for these cases — keeps the operation discoverable both via the chain/domain group and the cross-cutting group. + +**When to exclusively relocate.** Remove module-level `tags(...)` and add `tags: [...]` to every operation in the controller. This is what `csv_export_controller.ex` does — every export action sits under its consuming domain (`tokens`, `addresses`) instead of `csv-export`. Use only when the operation truly does not belong in the controller's domain group, or when a reviewer explicitly asks for exclusive grouping. diff --git a/.agents/skills/openapi-spec/references/spec-generation-and-verification.md b/.agents/skills/openapi-spec/references/spec-generation-and-verification.md new file mode 100644 index 000000000000..2215e273a78b --- /dev/null +++ b/.agents/skills/openapi-spec/references/spec-generation-and-verification.md @@ -0,0 +1,106 @@ +# Spec Generation and Verification + +## Generating the spec + +Generate the public OpenAPI spec YAML from Blockscout's `open_api_spex` annotations: + +```bash +.claude/skills/openapi-spec/scripts/generate-spec.sh +``` + +This produces `.ai/tmp/openapi_public.yaml` by default. + +For chain-specific endpoints, pass `--chain`: + +```bash +.claude/skills/openapi-spec/scripts/generate-spec.sh --chain arbitrum +``` + +This produces `.ai/tmp/openapi_public_arbitrum.yaml`. + +To write to a custom path: + +```bash +.claude/skills/openapi-spec/scripts/generate-spec.sh --chain optimism --output .ai/tmp/optimism_spec.yaml +``` + +The script always generates from `BlockScoutWeb.Specs.Public`, which aggregates all routes (API v2, tokens, smart contracts, and Etherscan-compatible endpoints). + +### Behavior + +- On success: prints the output file path and `SPEC_OK`. Mix output is suppressed. +- On failure: prints the captured mix output and `SPEC_FAIL`. Exit code 2. +- If `mix` is not available on the host, the script automatically delegates to the devcontainer. +- The script creates `.ai/tmp/` if it does not exist. + +## Verifying with oastools + +After generating the spec, use `oastools` to validate and inspect it. All examples below assume the default output path — adjust if you used `--output` or `--chain`. + +**Keep queries precise.** Always narrow by exact `-path` and `-method` to avoid large outputs that consume context. Never omit filters when you know the target endpoint. + +### Validate the full spec + +```bash +oastools validate .ai/tmp/openapi_public.yaml +``` + +### Check that an endpoint exists + +```bash +oastools walk operations -path "/v2/addresses/{address_hash_param}" .ai/tmp/openapi_public.yaml +``` + +### Get operation parameters + +```bash +oastools walk parameters -detail -format json -method get -path "/v2/addresses/{address_hash_param}" .ai/tmp/openapi_public.yaml | jq 'del(.path)' +``` + +Filter by parameter location when you only need query or path params: + +```bash +oastools walk parameters -detail -format json -in query -method get -path "/v2/addresses/{address_hash_param}/transactions" .ai/tmp/openapi_public.yaml | jq 'del(.path)' +``` + +### Get response schema + +```bash +oastools walk responses -detail -format json -status 200 -method get -path "/v2/addresses/{address_hash_param}" .ai/tmp/openapi_public.yaml | jq 'del(.path)' +``` + +Always specify `-status` to get only the response code you need. + +### Inspect a specific schema + +```bash +oastools walk schemas -detail -format json -name AddressResponse .ai/tmp/openapi_public.yaml | jq 'del(.jsonPath)' +``` + +## Typical verification workflow + +After creating or modifying an OpenAPI declaration: + +1. **Generate** the spec: + ```bash + .claude/skills/openapi-spec/scripts/generate-spec.sh + ``` + +2. **Validate** the full spec: + ```bash + oastools validate .ai/tmp/openapi_public.yaml + ``` + +3. **Inspect** the target operation — use exact path and method: + ```bash + oastools walk parameters -detail -format json -method get -path "/v2/" .ai/tmp/openapi_public.yaml | jq 'del(.path)' + oastools walk responses -detail -format json -status 200 -method get -path "/v2/" .ai/tmp/openapi_public.yaml | jq 'del(.path)' + ``` + +4. **Run tests** to verify response schemas match the view output (use the `run-tests` skill). + +## Spec-wide audits + +Single-endpoint queries above answer "did I declare this right?" For "does the whole spec still follow our conventions?", use `references/oastools-audit-recipes.md`. Minimum sweep after any schema-touching change: recipe A (additionalProperties), B (422 coverage), F (base_params), I (tag casing). + +Always regenerate before auditing — the generated spec is cache-like, and a stale YAML produces false positives. diff --git a/.agents/skills/openapi-spec/scripts/generate-spec.sh b/.agents/skills/openapi-spec/scripts/generate-spec.sh new file mode 100755 index 000000000000..b7c5ec54623b --- /dev/null +++ b/.agents/skills/openapi-spec/scripts/generate-spec.sh @@ -0,0 +1,121 @@ +#!/usr/bin/env bash +# Generate the public OpenAPI spec YAML from Blockscout's OpenApiSpex annotations. +# +# Environment-aware: if mix is not found on the host, automatically +# re-invokes itself inside the project's devcontainer via exec.sh. +# +# Usage: generate-spec.sh [--chain ] [--output ] +# --chain Set CHAIN_TYPE for chain-specific endpoints (optional). +# --output Output file path (default: .ai/tmp/openapi_public.yaml, +# or .ai/tmp/openapi_public_.yaml when --chain is set). +# +# Exit codes: +# 0 spec generated successfully +# 1 script error (bad arguments, missing dependencies) +# 2 spec generation failed + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)" + +SPEC_MODULE="BlockScoutWeb.Specs.Public" + +# --- Parse flags --- +CHAIN_TYPE="${CHAIN_TYPE:-}" +OUTPUT_PATH="" + +while [ "$#" -gt 0 ]; do + case "$1" in + --chain) + [ "$#" -ge 2 ] || { echo "Error: --chain requires a value" >&2; exit 1; } + CHAIN_TYPE="$2" + shift 2 + ;; + --output) + [ "$#" -ge 2 ] || { echo "Error: --output requires a value" >&2; exit 1; } + OUTPUT_PATH="$2" + shift 2 + ;; + *) + echo "Error: unknown argument: $1" >&2 + echo "Usage: generate-spec.sh [--chain ] [--output ]" >&2 + exit 1 + ;; + esac +done + +# --- Compute default output path --- +if [ -z "$OUTPUT_PATH" ]; then + if [ -n "$CHAIN_TYPE" ]; then + OUTPUT_PATH=".ai/tmp/openapi_public_${CHAIN_TYPE}.yaml" + else + OUTPUT_PATH=".ai/tmp/openapi_public.yaml" + fi +fi + +# --- Export CHAIN_TYPE if set --- +if [ -n "$CHAIN_TYPE" ]; then + export CHAIN_TYPE +fi + +# --- If mix is not available, re-invoke inside the devcontainer --- +if ! command -v mix &>/dev/null; then + # Locate _find-devcontainer-exec.sh + FIND_EXEC="" + for agents_dir in "$PROJECT_ROOT/.agents/agents/scripts" "$PROJECT_ROOT/.claude/agents/scripts"; do + if [ -x "$agents_dir/_find-devcontainer-exec.sh" ]; then + FIND_EXEC="$agents_dir/_find-devcontainer-exec.sh" + break + fi + done + if [ -z "$FIND_EXEC" ]; then + echo "Error: _find-devcontainer-exec.sh not found in .agents/agents/scripts or .claude/agents/scripts" >&2 + exit 1 + fi + + EXEC_SH="$("$FIND_EXEC")" || exit 1 + + EXEC_ENV_ARGS=() + if [ -n "$CHAIN_TYPE" ]; then + EXEC_ENV_ARGS+=(-e "CHAIN_TYPE=$CHAIN_TYPE") + fi + + exec "$EXEC_SH" ${EXEC_ENV_ARGS[@]+"${EXEC_ENV_ARGS[@]}"} \ + bash .agents/skills/openapi-spec/scripts/generate-spec.sh \ + ${CHAIN_TYPE:+--chain "$CHAIN_TYPE"} --output "$OUTPUT_PATH" +fi + +# --- Ensure output directory exists --- +mkdir -p "$PROJECT_ROOT/.ai/tmp" + +# --- Run spec generation --- +cd "$PROJECT_ROOT" + +CAPTURE_FILE="$PROJECT_ROOT/.ai/tmp/.generate-spec-output-$$.log" +cleanup() { rm -f "$CAPTURE_FILE"; } +trap cleanup EXIT + +RESULT=0 +mix openapi.spec.yaml --spec "$SPEC_MODULE" "$OUTPUT_PATH" --start-app=false \ + >"$CAPTURE_FILE" 2>&1 || RESULT=$? + +echo "=== SPEC_RESULTS ===" +if [ -n "$CHAIN_TYPE" ]; then + echo "Chain: $CHAIN_TYPE" +else + echo "Chain: default" +fi + +if [ "$RESULT" -eq 0 ]; then + echo "Output: $OUTPUT_PATH" + echo "---" + echo "SPEC_OK" + exit 0 +else + echo "---" + cat "$CAPTURE_FILE" + echo "---" + echo "SPEC_FAIL" + exit 2 +fi diff --git a/.agents/skills/update-common-blockscout-env/SKILL.md b/.agents/skills/update-common-blockscout-env/SKILL.md new file mode 100644 index 000000000000..d1e6ba460fb4 --- /dev/null +++ b/.agents/skills/update-common-blockscout-env/SKILL.md @@ -0,0 +1,42 @@ +--- +name: update-common-blockscout-env +description: Ensure every newly introduced environment variable is also added to docker-compose/envs/common-blockscout.env so local Docker setups stay aligned with runtime configuration. +--- + +## Overview + +This skill keeps environment-variable documentation and defaults in sync for Docker users. + +When adding or changing runtime env vars (for example in config/runtime.exs), also update docker-compose/envs/common-blockscout.env in the same task. + +## Mandatory Rule + +- Every new env variable introduced in code/config must be added to docker-compose/envs/common-blockscout.env. +- Do not postpone this to a follow-up task. + +## How To Apply + +1. Identify newly added env vars in changed files (typically config/runtime.exs, config/*.exs, or modules reading System.get_env/1-2). +2. Add each variable to docker-compose/envs/common-blockscout.env. +3. Place it in the most relevant section (for example API flags near other API_* variables). +4. Prefer non-breaking defaults: + - Use a commented example line for optional flags (for example # MY_FLAG=false). + - Use an uncommented value only when the project convention requires a default to be active. +5. Keep naming and formatting consistent with existing entries. + +## Checklist + +- New env var exists in code. +- Matching entry exists in docker-compose/envs/common-blockscout.env. +- Placement is logical and discoverable. +- Default value does not change behavior unexpectedly. + +## Example + +If code adds: + +- DISABLE_TRANSACTIONS_BENS_PRELOAD + +Then docker-compose/envs/common-blockscout.env should include: + +- # DISABLE_TRANSACTIONS_BENS_PRELOAD=false diff --git a/.agents/skills/with-to-case-refactor/SKILL.md b/.agents/skills/with-to-case-refactor/SKILL.md new file mode 100644 index 000000000000..77e42fb1c52c --- /dev/null +++ b/.agents/skills/with-to-case-refactor/SKILL.md @@ -0,0 +1,131 @@ +--- +name: with-to-case-refactor +description: Replace `with` expressions that contain only a single `<-` clause and an `else` branch with a `case` expression. This addresses the Credo warning "with contains only one <- clause and an else branch, consider using case instead" and produces cleaner, more idiomatic Elixir code. +--- + +## Overview + +Elixir's `with` construct is designed for chaining multiple pattern-matching steps. When only one `<-` clause is present alongside an `else` branch, `with` adds no value over a plain `case`. Credo flags this as: + +``` +[R] → `with` contains only one <- clause and an `else` branch, consider using `case` instead +``` + +Always prefer `case` in this situation. + +## When to Use + +- When a `with` expression has exactly one `<-` clause and one or more `else` arms. +- When refactoring code to address the Credo `Credo.Check.Refactor.WithClauses` warning. + +## Anti-Pattern (Avoid) + +```elixir +# ❌ BAD: single-clause with/else — should be a case +with {:ok, response} <- json_rpc(params, opts) do + process(response) +else + {:error, reason} -> + Logger.error("RPC failed: #{inspect(reason)}") + :error +end +``` + +```elixir +# ❌ BAD: single-clause with/else wrapping a nested case +with {:ok, response} <- json_rpc(params, opts) do + case parse(response) do + {:ok, value} -> value + _ -> :error + end +else + {:error, reason} -> + Logger.error("RPC failed: #{inspect(reason)}") + :error +end +``` + +## Best Practice (Use Instead) + +```elixir +# ✅ GOOD: flat case replaces with/else +case json_rpc(params, opts) do + {:ok, response} -> + process(response) + + {:error, reason} -> + Logger.error("RPC failed: #{inspect(reason)}") + :error +end +``` + +```elixir +# ✅ GOOD: nested case is fine when the outer with is replaced +case json_rpc(params, opts) do + {:ok, response} -> + case parse(response) do + {:ok, value} -> value + _ -> :error + end + + {:error, reason} -> + Logger.error("RPC failed: #{inspect(reason)}") + :error +end +``` + +## Transformation Rules + +1. Move the expression on the right-hand side of `<-` to become the subject of `case`. +2. Turn the left-hand side of `<-` into the matching branch of `case`. +3. Move the body of the `with` block as the body of that `case` branch. +4. Move each arm of the `else` block as additional `case` branches. +5. Remove the `with`/`else`/`end` wrapper. + +## Real-World Example (from this codebase) + +### Before + +```elixir +with {:ok, response} <- + params + |> Map.merge(%{id: 0}) + |> Nonce.request() + |> json_rpc(json_rpc_named_arguments) do + case Nonce.from_response(%{id: 0, result: response}, id_to_params) do + {:ok, %{nonce: 0}} -> handle_zero_nonce(...) + {:ok, %{nonce: nonce}} when nonce > 0 -> handle_nonzero_nonce(...) + _ -> retry(...) + end +else + {:error, reason} -> + Logger.error("Error: #{inspect(reason)}") + retry(...) +end +``` + +### After + +```elixir +case params + |> Map.merge(%{id: 0}) + |> Nonce.request() + |> json_rpc(json_rpc_named_arguments) do + {:ok, response} -> + case Nonce.from_response(%{id: 0, result: response}, id_to_params) do + {:ok, %{nonce: 0}} -> handle_zero_nonce(...) + {:ok, %{nonce: nonce}} when nonce > 0 -> handle_nonzero_nonce(...) + _ -> retry(...) + end + + {:error, reason} -> + Logger.error("Error: #{inspect(reason)}") + retry(...) +end +``` + +## Notes + +- If the `with` has **two or more** `<-` clauses, keep it as `with`; this refactor only applies to the single-clause case. +- If there is no `else` branch at all, `with` is also acceptable for a single clause — but a `case` is still clearer and preferred. +- After refactoring, run `mix format` to ensure correct indentation. diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 3fa213982b9f..000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,627 +0,0 @@ -version: 2 -jobs: - build: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3-node-browsers - environment: - MIX_ENV: test - # match POSTGRES_PASSWORD for postgres image below - PGPASSWORD: postgres - # match POSTGRES_USER for postgres image below - PGUSER: postgres - - working_directory: ~/app - - steps: - - run: sudo apt-get update; sudo apt-get -y install autoconf build-essential libgmp3-dev libtool - - - checkout - - run: - command: ./bin/install_chrome_headless.sh - no_output_timeout: 2400 - - - run: mix local.hex --force - - run: mix local.rebar --force - - - run: - name: "ELIXIR_VERSION.lock" - command: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock - - run: - name: "OTP_VERSION.lock" - command: echo "${OTP_VERSION}" > OTP_VERSION.lock - - - restore_cache: - keys: - - v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }} - - v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }} - - v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }} - - - run: mix deps.get - - - restore_cache: - keys: - - v8-npm-install-{{ .Branch }}-{{ checksum "apps/block_scout_web/assets/package-lock.json" }} - - v8-npm-install-{{ .Branch }} - - v8-npm-install - - - run: - command: npm install - working_directory: "apps/explorer" - - - save_cache: - key: v3-npm-install-{{ .Branch }}-{{ checksum "apps/explorer/package-lock.json" }} - paths: "apps/explorer/node_modules" - - save_cache: - key: v3-npm-install-{{ .Branch }} - paths: "apps/explorer/node_modules" - - save_cache: - key: v3-npm-install - paths: "apps/explorer/node_modules" - - - run: - command: npm install - working_directory: "apps/block_scout_web/assets" - - - save_cache: - key: v8-npm-install-{{ .Branch }}-{{ checksum "apps/block_scout_web/assets/package-lock.json" }} - paths: "apps/block_scout_web/assets/node_modules" - - save_cache: - key: v8-npm-install-{{ .Branch }} - paths: "apps/block_scout_web/assets/node_modules" - - save_cache: - key: v8-npm-install - paths: "apps/block_scout_web/assets/node_modules" - - - run: mix compile - - # Ensure NIF is compiled for libsecp256k1 - - run: - command: make - working_directory: "deps/libsecp256k1" - - # `deps` needs to be cached with `_build` because `_build` will symlink into `deps` - - - save_cache: - key: v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }} - paths: - - deps - - _build - - save_cache: - key: v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }} - paths: - - deps - - _build - - save_cache: - key: v8-mix-compile-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }} - paths: - - deps - - _build - - - run: - name: Build assets - command: node node_modules/webpack/bin/webpack.js --mode development - working_directory: "apps/block_scout_web/assets" - - - persist_to_workspace: - root: . - paths: - - .circleci - - .credo.exs - - .dialyzer-ignore - - .formatter.exs - - .git - - .gitignore - - ELIXIR_VERSION.lock - - Gemfile - - Gemfile.lock - - OTP_VERSION.lock - - _build - - apps - - bin - - config - - deps - - doc - - mix.exs - - mix.lock - - appspec.yml - - rel - check_formatted: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: test - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: mix format --check-formatted - credo: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: test - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: mix local.hex --force - - - run: mix credo - deploy_aws: - docker: - # Ensure .tool-versions matches - - image: circleci/python:2.7-stretch - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - add_ssh_keys: - fingerprints: - - "c4:fd:a8:f8:48:a8:09:e5:3e:be:30:62:4d:6f:6f:36" - - - run: - name: Deploy to AWS - command: bin/deploy - dialyzer: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: test - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: mix local.hex --force - - - restore_cache: - keys: - - v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }} - - v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }} - - v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }} - - - run: - name: Unpack PLT cache - command: | - mkdir -p _build/test - cp plts/dialyxir*.plt _build/test/ || true - mkdir -p ~/.mix - cp plts/dialyxir*.plt ~/.mix/ || true - - - run: mix dialyzer --plt - - - run: - name: Pack PLT cache - command: | - mkdir -p plts - cp _build/test/dialyxir*.plt plts/ - cp ~/.mix/dialyxir*.plt plts/ - - - save_cache: - key: v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.lock" }} - paths: - - plts - - save_cache: - key: v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }}-{{ checksum "mix.exs" }} - paths: - - plts - - save_cache: - key: v8-mix-dialyzer-{{ checksum "OTP_VERSION.lock" }}-{{ checksum "ELIXIR_VERSION.lock" }} - paths: - - plts - - - run: mix dialyzer --halt-exit-status - eslint: - docker: - # Ensure .tool-versions matches - - image: circleci/node:12.18.2-browsers-legacy - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: - name: ESLint - command: ./node_modules/.bin/eslint --format=junit --output-file="test/eslint/junit.xml" js/** - working_directory: apps/block_scout_web/assets - - - store_test_results: - path: apps/block_scout_web/assets/test - gettext: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: test - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: mix local.hex --force - - - run: - name: Check for missed translations - command: | - mix gettext.extract --merge | tee stdout.txt - ! grep "Wrote " stdout.txt - working_directory: "apps/block_scout_web" - - - store_artifacts: - path: apps/block_scout_web/priv/gettext - jest: - docker: - # Ensure .tool-versions matches - - image: circleci/node:12.18.2-browsers-legacy - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: - name: Jest - command: ./node_modules/.bin/jest - working_directory: apps/block_scout_web/assets - release: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: prod - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: mix local.hex --force - - run: mix local.rebar --force - - run: MIX_ENV=prod mix release - - run: - name: Collecting artifacts - command: | - find -name 'blockscout.tar.gz' -exec sh -c 'mkdir -p ci_artifact && cp "$@" ci_artifact/ci_artifact_blockscout.tar.gz' _ {} + - when: always - - - store_artifacts: - name: Uploading CI artifacts - path: ci_artifact/ci_artifact_blockscout.tar.gz - destination: ci_artifact_blockscout.tar.gz - sobelow: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: test - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: mix local.hex --force - - - run: - name: Scan explorer for vulnerabilities - command: mix sobelow --config - working_directory: "apps/explorer" - - - run: - name: Scan block_scout_web for vulnerabilities - command: mix sobelow --config - working_directory: "apps/block_scout_web" - # test_geth_http_websocket: - # docker: - # # Ensure .tool-versions matches - # - image: circleci/elixir:1.10.3-node-browsers - # environment: - # MIX_ENV: test - # # match POSTGRES_PASSWORD for postgres image below - # PGPASSWORD: postgres - # # match POSTGRES_USER for postgres image below - # PGUSER: postgres - # ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Geth.HTTPWebSocket" - # ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Geth" - # - image: circleci/postgres:10.10-alpine - # environment: - # # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - # POSTGRES_DB: explorer_test - # # match PGPASSWORD for elixir image above - # POSTGRES_PASSWORD: postgres - # # match PGUSER for elixir image above - # POSTGRES_USER: postgres - - # working_directory: ~/app - - # steps: - # - attach_workspace: - # at: . - - # - run: - # command: ./bin/install_chrome_headless.sh - # no_output_timeout: 2400 - - # - run: mix local.hex --force - # - run: mix local.rebar --force - - # - run: - # name: Wait for DB - # command: dockerize -wait tcp://localhost:5432 -timeout 1m - - # - run: - # name: mix test --exclude no_geth - # command: | - # # Don't submit coverage report for forks, but let the build succeed - # if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then - # mix coveralls.html --exclude no_geth --parallel --umbrella - # else - # mix coveralls.circle --exclude no_geth --parallel --umbrella || - # # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status - # (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval) - # fi - - # - store_artifacts: - # path: cover/excoveralls.html - # - store_test_results: - # path: _build/test/junit - # test_geth_mox: - # docker: - # # Ensure .tool-versions matches - # - image: circleci/elixir:1.10.3-node-browsers - # environment: - # MIX_ENV: test - # # match POSTGRES_PASSWORD for postgres image below - # PGPASSWORD: postgres - # # match POSTGRES_USER for postgres image below - # PGUSER: postgres - # ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Geth.Mox" - # ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - # - image: circleci/postgres:10.10-alpine - # environment: - # # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - # POSTGRES_DB: explorer_test - # # match PGPASSWORD for elixir image above - # POSTGRES_PASSWORD: postgres - # # match PGUSER for elixir image above - # POSTGRES_USER: postgres - - # working_directory: ~/app - - # steps: - # - attach_workspace: - # at: . - - # - run: - # command: ./bin/install_chrome_headless.sh - # no_output_timeout: 2400 - - # - run: mix local.hex --force - # - run: mix local.rebar --force - - # - run: - # name: Wait for DB - # command: dockerize -wait tcp://localhost:5432 -timeout 1m - - # - run: - # name: mix test --exclude no_geth - # command: | - # # Don't submit coverage report for forks, but let the build succeed - # if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then - # mix coveralls.html --exclude no_geth --parallel --umbrella - # else - # mix coveralls.circle --exclude no_geth --parallel --umbrella || - # # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status - # (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval) - # fi - - # - store_artifacts: - # path: cover/excoveralls.html - # - store_test_results: - # path: _build/test/junit - # test_parity_http_websocket: - # docker: - # # Ensure .tool-versions matches - # - image: circleci/elixir:1.10.3-node-browsers - # environment: - # MIX_ENV: test - # # match POSTGRES_PASSWORD for postgres image below - # PGPASSWORD: postgres - # # match POSTGRES_USER for postgres image below - # PGUSER: postgres - # ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.HTTPWebSocket" - # ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Parity" - # - image: circleci/postgres:10.10-alpine - # environment: - # # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - # POSTGRES_DB: explorer_test - # # match PGPASSWORD for elixir image above - # POSTGRES_PASSWORD: postgres - # # match PGUSER for elixir image above - # POSTGRES_USER: postgres - - # working_directory: ~/app - - # steps: - # - attach_workspace: - # at: . - - # - run: - # command: ./bin/install_chrome_headless.sh - # no_output_timeout: 2400 - - # - run: mix local.hex --force - # - run: mix local.rebar --force - - # - run: - # name: Wait for DB - # command: dockerize -wait tcp://localhost:5432 -timeout 1m - - # - run: - # name: mix test --exclude no_parity - # command: | - # # Don't submit coverage report for forks, but let the build succeed - # if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then - # mix coveralls.html --exclude no_parity --parallel --umbrella - # else - # mix coveralls.circle --exclude no_parity --parallel --umbrella || - # # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status - # (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval) - # fi - - # - store_artifacts: - # path: cover/excoveralls.html - # - store_test_results: - # path: _build/test/junit - test_parity_mox: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3-node-browsers - environment: - MIX_ENV: test - # match POSTGRES_PASSWORD for postgres image below - PGPASSWORD: postgres - # match POSTGRES_USER for postgres image below - PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.Mox" - ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - - image: circleci/postgres:10.10-alpine - environment: - # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database - POSTGRES_DB: explorer_test - # match PGPASSWORD for elixir image above - POSTGRES_PASSWORD: postgres - # match PGUSER for elixir image above - POSTGRES_USER: postgres - - working_directory: ~/app - - steps: - - attach_workspace: - at: . - - - run: - command: ./bin/install_chrome_headless.sh - no_output_timeout: 2400 - - - run: mix local.hex --force - - run: mix local.rebar --force - - - run: - name: Wait for DB - command: dockerize -wait tcp://localhost:5432 -timeout 1m - - - run: - name: mix test --exclude no_parity - command: | - # Don't submit coverage report for forks, but let the build succeed - if [[ -z "$COVERALLS_REPO_TOKEN" ]]; then - mix coveralls.html --exclude no_parity --parallel --umbrella - else - mix coveralls.circle --exclude no_parity --parallel --umbrella || - # if mix failed, then coveralls_merge won't run, so signal done here and return original exit status - (retval=$? && curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" && return $retval) - fi - - - store_artifacts: - path: cover/excoveralls.html - - store_test_results: - path: _build/test/junit - coveralls_merge: - docker: - # Ensure .tool-versions matches - - image: circleci/elixir:1.10.3 - environment: - MIX_ENV: test - - steps: - - run: - name: Tell coveralls.io build is done - command: curl -k https://coveralls.io/webhook?repo_token=$COVERALLS_REPO_TOKEN -d "payload[build_num]=$CIRCLE_WORKFLOW_WORKSPACE_ID&payload[status]=done" -workflows: - version: 2 - primary: - jobs: - - build - - check_formatted: - requires: - - build - # This unfortunately will only fire if all the tests pass because of how `requires` works - - coveralls_merge: - requires: - # - test_parity_http_websocket - - test_parity_mox - # - test_geth_http_websocket - # - test_geth_mox - - credo: - requires: - - build - - deploy_aws: - filters: - branches: - only: - - production - - staging - - /deploy-[A-Za-z0-9]+$/ - requires: - - check_formatted - - credo - - eslint - - jest - - sobelow - # - test_parity_http_websocket - - test_parity_mox - # - test_geth_http_websocket - # - test_geth_mox - - dialyzer: - requires: - - build - - eslint: - requires: - - build - - gettext: - requires: - - build - - jest: - requires: - - build - - release: - requires: - - build - - sobelow: - requires: - - build - # - test_parity_http_websocket: - # requires: - # - build - - test_parity_mox: - requires: - - build - # - test_geth_http_websocket: - # requires: - # - build - # - test_geth_mox: - # requires: - # - build diff --git a/.credo.exs b/.credo.exs index ba4d7feb49e1..2649b6cafc4a 100644 --- a/.credo.exs +++ b/.credo.exs @@ -30,16 +30,24 @@ ] }, # + # Load and configure plugins here: + # + plugins: [], + # # If you create your own checks, you must specify the source files for # them here, so they can be loaded by Credo before running the analysis. # - requires: [], + requires: ["apps/utils/lib/credo/**/*.ex"], # # If you want to enforce a style guide and need a more traditional linting # experience, you can change `strict` to `true` below: # strict: true, # + # To modify the timeout for parsing files, change this value: + # + parse_timeout: 5000, + # # If you want to use uncolored output by default, you can change `color` # to `false` below: # @@ -52,99 +60,166 @@ # # {Credo.Check.Design.DuplicatedCode, false} # - checks: [ - # outdated by formatter in Elixir 1.6. See https://github.com/rrrene/credo/issues/505 - {Credo.Check.Consistency.LineEndings, false}, - {Credo.Check.Consistency.SpaceAroundOperators, false}, - {Credo.Check.Consistency.SpaceInParentheses, false}, - {Credo.Check.Consistency.TabsOrSpaces, false}, - {Credo.Check.Readability.LargeNumbers, false}, - {Credo.Check.Readability.MaxLineLength, false}, - {Credo.Check.Readability.ParenthesesInCondition, false}, - {Credo.Check.Readability.RedundantBlankLines, false}, - {Credo.Check.Readability.Semicolons, false}, - {Credo.Check.Readability.SpaceAfterCommas, false}, - {Credo.Check.Readability.TrailingBlankLine, false}, - {Credo.Check.Readability.TrailingWhiteSpace, false}, + checks: %{ + enabled: [ + # + ## Consistency Checks + # + {Credo.Check.Consistency.ExceptionNames, []}, + {Credo.Check.Consistency.ParameterPatternMatching, []}, - # outdated by lazy Logger in Elixir 1.7. See https://elixir-lang.org/blog/2018/07/25/elixir-v1-7-0-released/ - {Credo.Check.Warning.LazyLogging, false}, + # + ## Design Checks + # + # You can customize the priority of any check + # Priority values are: `low, normal, high, higher` + # + {Credo.Check.Design.AliasUsage, + [ + excluded_namespaces: ~w(Block Blocks Import Runner Socket SpandexDatadog Task Schemas), + excluded_lastnames: + ~w(Address DateTime Exporter Fetcher Full Instrumenter Logger Monitor Name Number Repo Spec Time Unit), + priority: :low, + if_nested_deeper_than: 2, + if_called_more_often_than: 0 + ]}, + {Credo.Check.Design.DuplicatedCode, excluded_macros: [], mass_threshold: 800}, + {Credo.Check.Design.TagFIXME, []}, + # You can also customize the exit_status of each check. + # If you don't want TODO comments to cause `mix credo` to fail, just + # set this value to 0 (zero). + # + {Credo.Check.Design.TagTODO, [exit_status: 0]}, - # not handled by formatter - {Credo.Check.Consistency.ExceptionNames}, - {Credo.Check.Consistency.ParameterPatternMatching}, + # + ## Readability Checks + # + {Credo.Check.Readability.AliasOrder, []}, + {Credo.Check.Readability.FunctionNames, []}, + {Credo.Check.Readability.ModuleAttributeNames, []}, + {Credo.Check.Readability.ModuleDoc, []}, + {Credo.Check.Readability.ModuleNames, []}, + {Credo.Check.Readability.ParenthesesOnZeroArityDefs, []}, + {Credo.Check.Readability.PipeIntoAnonymousFunctions, []}, + {Credo.Check.Readability.PredicateFunctionNames, []}, + {Credo.Check.Readability.PreferImplicitTry, []}, + {Credo.Check.Readability.StringSigils, []}, + {Credo.Check.Readability.UnnecessaryAliasExpansion, []}, + {Credo.Check.Readability.VariableNames, []}, + {Credo.Check.Readability.WithSingleClause, []}, - # You can customize the priority of any check - # Priority values are: `low, normal, high, higher` - # - {Credo.Check.Design.AliasUsage, - excluded_namespaces: ~w(Block Blocks Import Runner Socket SpandexDatadog Task), - excluded_lastnames: - ~w(Address DateTime Exporter Fetcher Full Instrumenter Logger Monitor Name Number Repo Spec Time Unit), - priority: :low}, + # + ## Refactoring Opportunities + # + {Credo.Check.Refactor.Apply, []}, + {Credo.Check.Refactor.CondStatements, []}, + {Credo.Check.Refactor.CyclomaticComplexity, []}, + {Credo.Check.Refactor.FilterCount, []}, + {Credo.Check.Refactor.FilterFilter, []}, + {Credo.Check.Refactor.FunctionArity, []}, + {Credo.Check.Refactor.LongQuoteBlocks, []}, + {Credo.Check.Refactor.MapJoin, []}, + {Credo.Check.Refactor.MatchInCondition, []}, + {Credo.Check.Refactor.NegatedConditionsInUnless, []}, + {Credo.Check.Refactor.NegatedConditionsWithElse, []}, + {Credo.Check.Refactor.Nesting, []}, + {Credo.Check.Refactor.RedundantWithClauseResult, []}, + {Credo.Check.Refactor.RejectReject, []}, + {Credo.Check.Refactor.UnlessWithElse, []}, + {Credo.Check.Refactor.WithClauses, []}, - # For some checks, you can also set other parameters - # - # If you don't want the `setup` and `test` macro calls in ExUnit tests - # or the `schema` macro in Ecto schemas to trigger DuplicatedCode, just - # set the `excluded_macros` parameter to `[:schema, :setup, :test]`. - # - {Credo.Check.Design.DuplicatedCode, excluded_macros: [], mass_threshold: 80}, + # + ## Warnings + # + {Credo.Check.Warning.ApplicationConfigInModuleAttribute, []}, + {Credo.Check.Warning.BoolOperationOnSameValues, []}, + {Credo.Check.Warning.Dbg, []}, + {Credo.Check.Warning.ExpensiveEmptyEnumCheck, []}, + {Credo.Check.Warning.IExPry, []}, + {Credo.Check.Warning.IoInspect, []}, + {Credo.Check.Warning.MissedMetadataKeyInLoggerConfig, []}, + {Credo.Check.Warning.OperationOnSameValues, []}, + {Credo.Check.Warning.OperationWithConstantResult, []}, + {Credo.Check.Warning.RaiseInsideRescue, []}, + {Credo.Check.Warning.SpecWithStruct, []}, + {Credo.Check.Warning.StructFieldAmount, []}, + {Credo.Check.Warning.UnsafeExec, []}, + {Credo.Check.Warning.UnusedEnumOperation, []}, + {Credo.Check.Warning.UnusedFileOperation, []}, + {Credo.Check.Warning.UnusedKeywordOperation, []}, + {Credo.Check.Warning.UnusedListOperation, []}, + {Credo.Check.Warning.UnusedMapOperation, []}, + {Credo.Check.Warning.UnusedPathOperation, []}, + {Credo.Check.Warning.UnusedRegexOperation, []}, + {Credo.Check.Warning.UnusedStringOperation, []}, + {Credo.Check.Warning.UnusedTupleOperation, []}, + {Credo.Check.Warning.WrongTestFilename, []}, + {Utils.Credo.Checks.CompileEnvUsage} + ], + disabled: [ + # + # Checks scheduled for next check update (opt-in for now) + {Credo.Check.Refactor.UtcNowTruncate, []}, - # You can also customize the exit_status of each check. - # If you don't want TODO comments to cause `mix credo` to fail, just - # set this value to 0 (zero). - # - {Credo.Check.Design.TagTODO, exit_status: 0}, - {Credo.Check.Design.TagFIXME}, - {Credo.Check.Readability.FunctionNames}, - {Credo.Check.Readability.ModuleAttributeNames}, - {Credo.Check.Readability.ModuleDoc}, - {Credo.Check.Readability.ModuleNames}, - {Credo.Check.Readability.ParenthesesOnZeroArityDefs}, - {Credo.Check.Readability.PredicateFunctionNames}, - {Credo.Check.Readability.PreferImplicitTry}, - {Credo.Check.Readability.StringSigils}, - {Credo.Check.Readability.VariableNames}, - {Credo.Check.Refactor.DoubleBooleanNegation}, - {Credo.Check.Refactor.CondStatements}, - {Credo.Check.Refactor.CyclomaticComplexity}, - {Credo.Check.Refactor.FunctionArity}, - {Credo.Check.Refactor.LongQuoteBlocks}, - {Credo.Check.Refactor.MatchInCondition}, - {Credo.Check.Refactor.NegatedConditionsInUnless}, - {Credo.Check.Refactor.NegatedConditionsWithElse}, - {Credo.Check.Refactor.Nesting}, - {Credo.Check.Refactor.PipeChainStart}, - {Credo.Check.Refactor.UnlessWithElse}, - {Credo.Check.Warning.BoolOperationOnSameValues}, - {Credo.Check.Warning.ExpensiveEmptyEnumCheck}, - {Credo.Check.Warning.IExPry}, - {Credo.Check.Warning.IoInspect}, - {Credo.Check.Warning.OperationOnSameValues}, - {Credo.Check.Warning.OperationWithConstantResult}, - {Credo.Check.Warning.UnusedEnumOperation}, - {Credo.Check.Warning.UnusedFileOperation}, - {Credo.Check.Warning.UnusedKeywordOperation}, - {Credo.Check.Warning.UnusedListOperation}, - {Credo.Check.Warning.UnusedPathOperation}, - {Credo.Check.Warning.UnusedRegexOperation}, - {Credo.Check.Warning.UnusedStringOperation}, - {Credo.Check.Warning.UnusedTupleOperation}, - {Credo.Check.Warning.RaiseInsideRescue, false}, + # + # Controversial and experimental checks (opt-in, just move the check to `:enabled` + # and be sure to use `mix credo --strict` to see low priority checks) + # + {Credo.Check.Consistency.LineEndings, []}, + {Credo.Check.Consistency.MultiAliasImportRequireUse, []}, + {Credo.Check.Consistency.SpaceAroundOperators, []}, + {Credo.Check.Consistency.SpaceInParentheses, []}, + {Credo.Check.Consistency.TabsOrSpaces, []}, + {Credo.Check.Consistency.UnusedVariableNames, []}, + {Credo.Check.Design.SkipTestWithoutComment, []}, + {Credo.Check.Readability.AliasAs, []}, + {Credo.Check.Readability.BlockPipe, []}, + {Credo.Check.Readability.ImplTrue, []}, + {Credo.Check.Readability.LargeNumbers, []}, + {Credo.Check.Readability.MaxLineLength, [priority: :low, max_length: 120]}, + {Credo.Check.Readability.MultiAlias, []}, + {Credo.Check.Readability.NestedFunctionCalls, []}, + {Credo.Check.Readability.OneArityFunctionInPipe, []}, + {Credo.Check.Readability.OnePipePerLine, []}, + {Credo.Check.Readability.ParenthesesInCondition, []}, + {Credo.Check.Readability.RedundantBlankLines, []}, + {Credo.Check.Readability.Semicolons, []}, + {Credo.Check.Readability.SeparateAliasRequire, []}, + {Credo.Check.Readability.SingleFunctionToBlockPipe, []}, + {Credo.Check.Readability.SinglePipe, []}, + {Credo.Check.Readability.SpaceAfterCommas, []}, + {Credo.Check.Readability.Specs, []}, + {Credo.Check.Readability.StrictModuleLayout, []}, + {Credo.Check.Readability.TrailingBlankLine, []}, + {Credo.Check.Readability.TrailingWhiteSpace, []}, + {Credo.Check.Readability.WithCustomTaggedTuple, []}, + {Credo.Check.Refactor.ABCSize, []}, + {Credo.Check.Refactor.AppendSingleItem, []}, + {Credo.Check.Refactor.CondInsteadOfIfElse, []}, + {Credo.Check.Refactor.DoubleBooleanNegation, []}, + {Credo.Check.Refactor.FilterReject, []}, + {Credo.Check.Refactor.IoPuts, []}, + {Credo.Check.Refactor.MapMap, []}, + {Credo.Check.Refactor.ModuleDependencies, []}, + {Credo.Check.Refactor.NegatedIsNil, []}, + {Credo.Check.Refactor.PassAsyncInTestCases, []}, + {Credo.Check.Refactor.PipeChainStart, []}, + {Credo.Check.Refactor.RejectFilter, []}, + {Credo.Check.Refactor.VariableRebinding, []}, + {Credo.Check.Warning.LazyLogging, []}, + {Credo.Check.Warning.LeakyEnvironment, []}, + {Credo.Check.Warning.MapGetUnsafePass, []}, + {Credo.Check.Warning.MixEnv, []}, + {Credo.Check.Warning.UnsafeToAtom, []} + # {Credo.Check.Warning.UnusedOperation, [{MyMagicModule, [:fun1, :fun2]}]} - # Controversial and experimental checks (opt-in, just remove `, false`) - # - # TODO reenable before merging optimized-indexer branch - {Credo.Check.Refactor.ABCSize, false}, - {Credo.Check.Refactor.AppendSingleItem}, - {Credo.Check.Refactor.VariableRebinding}, - {Credo.Check.Warning.MapGetUnsafePass}, - {Credo.Check.Consistency.MultiAliasImportRequireUse} + # {Credo.Check.Refactor.MapInto, []}, - # Custom checks can be created using `mix credo.gen.check`. - # - ] + # + # Custom checks can be created using `mix credo.gen.check`. + # + ] + } } ] } diff --git a/.devcontainer/.blockscout_config.example b/.devcontainer/.blockscout_config.example new file mode 100644 index 000000000000..209cb7db8592 --- /dev/null +++ b/.devcontainer/.blockscout_config.example @@ -0,0 +1,61 @@ +CHAIN_TYPE=ethereum + +ETHEREUM_JSONRPC_VARIANT=geth +ETHEREUM_JSONRPC_TRACE_URL="" + +API_RATE_LIMIT=100 +HEART_BEAT_TIMEOUT=30 +TXS_STATS_DAYS_TO_COMPILE_AT_INIT=2 +INDEXER_MEMORY_LIMIT=6 + +POOL_SIZE=50 +POOL_SIZE_API=50 +ACCOUNT_POOL_SIZE=10 + +INDEXER_DISABLE_EMPTY_BLOCKS_SANITIZER='true' +INDEXER_DISABLE_PENDING_TRANSACTIONS_FETCHER='true' +INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER='true' +INDEXER_DISABLE_BLOCK_REWARD_FETCHER='true' +INDEXER_DISABLE_ADDRESS_COIN_BALANCE_FETCHER='true' +INDEXER_DISABLE_CATALOGED_TOKEN_UPDATER_FETCHER='true' +ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES='true' +INDEXER_DISABLE_TOKEN_INSTANCE_RETRY_FETCHER='true' +INDEXER_DISABLE_TOKEN_INSTANCE_REALTIME_FETCHER='true' +INDEXER_DISABLE_TOKEN_INSTANCE_SANITIZE_FETCHER='true' +INDEXER_DISABLE_WITHDRAWALS_FETCHER='true' + +INDEXER_CATCHUP_BLOCKS_BATCH_SIZE=5 +INDEXER_COIN_BALANCES_BATCH_SIZE=1 +INDEXER_EMPTY_BLOCKS_SANITIZER_BATCH_SIZE=1 +INDEXER_BLOCK_REWARD_BATCH_SIZE=1 +INDEXER_RECEIPTS_BATCH_SIZE=10 +INDEXER_COIN_BALANCES_BATCH_SIZE=1 +INDEXER_ARCHIVAL_TOKEN_BALANCES_BATCH_SIZE=1 + +INDEXER_CATCHUP_BLOCKS_CONCURRENCY=1 +MIGRATION_TOKEN_INSTANCE_OWNER_BATCH_SIZE=1 +MIGRATION_TOKEN_INSTANCE_OWNER_CONCURRENCY=1 +INDEXER_BLOCK_REWARD_CONCURRENCY=1 +INDEXER_RECEIPTS_CONCURRENCY=1 +INDEXER_COIN_BALANCES_CONCURRENCY=1 +INDEXER_TOKEN_CONCURRENCY=1 +INDEXER_ARCHIVAL_TOKEN_BALANCES_CONCURRENCY=1 +INDEXER_TOKEN_INSTANCE_RETRY_CONCURRENCY=1 +INDEXER_TOKEN_INSTANCE_REALTIME_CONCURRENCY=1 +INDEXER_TOKEN_INSTANCE_SANITIZE_CONCURRENCY=1 +INDEXER_TOKEN_INSTANCE_RETRY_BATCH_SIZE=1 +INDEXER_TOKEN_INSTANCE_REALTIME_BATCH_SIZE=1 +INDEXER_TOKEN_INSTANCE_SANITIZE_BATCH_SIZE=1 + +INDEXER_TOKEN_BALANCES_FETCHER_INIT_QUERY_LIMIT=2 +INDEXER_COIN_BALANCES_FETCHER_INIT_QUERY_LIMIT=2 + +DISABLE_MARKET='true' +SOURCIFY_INTEGRATION_ENABLED='false' + +API_V2_ENABLED=true + +DISABLE_CATCHUP_INDEXER='false' +INDEXER_CATCHUP_BLOCKS_BATCH_SIZE=10 +INDEXER_CATCHUP_BLOCKS_CONCURRENCY=10 +ETHEREUM_JSONRPC_HTTP_URL="https://ethereum-sepolia-rpc.publicnode.com" diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000000..324a6d2eb818 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,50 @@ +# Since this is a copy of https://github.com/blockscout/devcontainer-elixir/blob/main/Dockerfile +# So after successful testing this file, the original one must be updated as well. +ARG VARIANT="1.19.4-erlang-27.3.4.6-debian-bookworm-20251117" +FROM hexpm/elixir:${VARIANT} + +# ARGs declared before FROM are not persisted beyond the FROM instruction. +# They must be redeclared here to be available in the rest of the Dockerfile. +ARG PHOENIX_VERSION="1.7.10" +ARG NODE_VERSION="20" + +# This Dockerfile adds a non-root user with sudo access. Update the “remoteUser” property in +# devcontainer.json to use it. More info: https://aka.ms/vscode-remote/containers/non-root-user. +ARG USERNAME=vscode +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Options for common package install script +ARG INSTALL_ZSH="true" +ARG UPGRADE_PACKAGES="true" +ARG COMMON_SCRIPT_SOURCE="https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/common-debian.sh" + +# Options for setup nodejs +ARG NODE_SCRIPT_SOURCE="https://raw.githubusercontent.com/microsoft/vscode-dev-containers/main/script-library/node-debian.sh" +ENV NVM_DIR=/usr/local/share/nvm +ENV NVM_SYMLINK_CURRENT=true +ENV PATH=${NVM_DIR}/current/bin:${PATH} + +# Install needed packages and setup non-root user. Use a separate RUN statement to add your own dependencies. +RUN apt-get update \ + && export DEBIAN_FRONTEND=noninteractive \ + && apt-get -y install --no-install-recommends curl ca-certificates 2>&1 \ + && curl -sSL ${COMMON_SCRIPT_SOURCE} -o /tmp/common-setup.sh \ + && /bin/bash /tmp/common-setup.sh "${INSTALL_ZSH}" "${USERNAME}" "${USER_UID}" "${USER_GID}" "${UPGRADE_PACKAGES}" \ + # + # Install Node.js for use with web applications + && curl -sSL ${NODE_SCRIPT_SOURCE} -o /tmp/node-setup.sh \ + && /bin/bash /tmp/node-setup.sh "${NVM_DIR}" "${NODE_VERSION}" "${USERNAME}" \ + && npm install -g cspell@latest \ + # + # Install dependencies + && apt-get install -y build-essential inotify-tools \ + # + # Clean up + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* /tmp/common-setup.sh /tmp/node-setup.sh + +RUN su ${USERNAME} -c "mix local.hex --force \ + && mix local.rebar --force \ + && mix archive.install --force hex phx_new ${PHOENIX_VERSION}" diff --git a/.devcontainer/README.md b/.devcontainer/README.md new file mode 100644 index 000000000000..a589b1d46bc6 --- /dev/null +++ b/.devcontainer/README.md @@ -0,0 +1,200 @@ +# Blockscout Backend Development with VSCode Devcontainers and GitHub Codespaces + +## Table of Contents +1. [Motivation](#motivation) +2. [Setting Up VSCode Devcontainer Locally](#setting-up-vscode-devcontainer-locally) +3. [Using GitHub Codespaces in the Browser](#using-github-codespaces-in-the-browser) +4. [Configuring Postgres DB Access](#configuring-postgres-db-access) +5. [Developing Blockscout Backend](#developing-blockscout-backend) +6. [Upgrading Elixir Version](#upgrading-elixir-version) +7. [Contributing](#contributing) + +## Motivation + +Setting up a local development environment for Blockscout can be time-consuming and error-prone. This devcontainer setup streamlines the process by providing a pre-configured environment with all necessary dependencies. It ensures consistency across development environments, reduces setup time, and allows developers to focus on coding rather than configuration. + +Key benefits include: +- Pre-configured environment with Elixir, Phoenix, and Node.js +- Integrated PostgreSQL database +- Essential VS Code extensions pre-installed +- Simplified database management +- Consistent development environment across team members + +## Setting Up VSCode Devcontainer Locally + +1. Clone the Blockscout repository: + ``` + git clone https://github.com/blockscout/blockscout.git + cd blockscout + ``` + +2. Open the project in VS Code: + ``` + code . + ``` + +3. Before re-opening in the container, you may find it useful to configure SSH authorization. To do this: + + a. Ensure you have SSH access to GitHub configured on your local machine. + + b. Open `.devcontainer/devcontainer.json`. + + c. Uncomment the `mounts` section: + ```json + "mounts": [ + "source=${localEnv:HOME}/.ssh/config,target=/home/vscode/.ssh/config,type=bind,consistency=cached", + "source=${localEnv:HOME}/.ssh/id_rsa,target=/home/vscode/.ssh/id_rsa,type=bind,consistency=cached" + ], + ``` + + d. Adjust the paths if your SSH keys are stored in a different location. + + e. Use `git update-index --assume-unchanged .devcontainer/devcontainer.json` to prevent the changes to `devcontainer.json` from appearing in `git status` and VS Code's Source Control. To undo the changes, use `git update-index --no-assume-unchanged .devcontainer/devcontainer.json`. + +4. When prompted, click "Reopen in Container". If not prompted, press `F1`, type "Remote-Containers: Reopen in Container", and press Enter. + +5. VS Code will build the devcontainer. This process includes: + - Pulling the base Docker image + - Installing specified VS Code extensions + - Setting up the PostgreSQL database + - Installing project dependencies + + This may take several minutes the first time. + +6. Once the devcontainer is built, you'll be working inside the containerized environment. + +7. If you modified the `devcontainer.json` file in step 3, you may want to execute `git update-index --assume-unchanged .devcontainer/devcontainer.json` in a terminal within your devcontainer to prevent the changes to `devcontainer.json` from appearing in `git status` and VS Code's Source Control. + +### Additional Setup for Cursor.ai Users + +If you're using Cursor.ai instead of VSCode, you may need to perform some additional setup steps. Please note that these changes will not persist after reloading the devcontainer, so you may need to repeat these steps each time you start a new session. + +1. **Git Configuration**: You may encounter issues when trying to perform Git operations from the terminal or the "Source Control" tab. To resolve this, set up your Git configuration inside the devcontainer: + + a. Open a terminal in your devcontainer. + b. Set your Git username: + ``` + git config --global user.name "Your Name" + ``` + c. Set your Git email: + ``` + git config --global user.email "your.email@example.com" + ``` + + Replace "Your Name" and "your.email@example.com" with your actual name and email associated with your GitHub account. + +2. **ElixirLS: Elixir support and debugger** (JakeBecker.elixir-ls): This extension may not be automatically installed in Cursor.ai, even though it's specified in the devcontainer configuration. To install it manually: + + a. Open the Extensions tab. + b. Search for "JakeBecker.elixir-ls". + c. Look for the extension "ElixirLS: Elixir support and debugger" by JakeBecker and click "Install". + +Remember, you may need to repeat these steps each time you start a new Cursor.ai session with the devcontainer. + +### Signing in to GitHub for Pull Request Extension + +1. In the devcontainer, click on the GitHub icon in the Primary sidebar. +2. Click on "Sign in to GitHub" and follow the prompts to authenticate. + +## Using GitHub Codespaces in the Browser + +To open the project in GitHub Codespaces: + +1. Navigate to the Blockscout repository on GitHub. +2. Switch to the branch you want to work on. +3. Click the "Code" button. +4. Instead of clicking "Create codespace on [branch]" (which would use the default machine type that may not be sufficient for this Elixir-based project), click on the three dots (...) next to it. +5. Select "New with options". +6. Choose the "4-core/16GB RAM" machine type for optimal performance. +7. Click "Create codespace". + +This will create a new Codespace with the specified resources, ensuring adequate performance for the Elixir-based project. + +Note: After the container opens, you may see an error about the inability to use "GitHub Copilot Chat". This Copilot functionality will not be accessible in the Codespace environment. + +## Configuring Postgres DB Access + +To configure access to the PostgreSQL database using the VS Code extension: + +1. Click on the PostgreSQL icon in the Primary sidebar. +2. Click "+" (Add Connection) in the PostgreSQL explorer. +3. Use the following details: + - Host: `db` + - User: `postgres` + - Password: `postgres` + - Port: `5432` + - Use an ssl connection: "Standard connection" + - Database: `app` + - The display name: "" + +These credentials are derived from the `DATABASE_URL` in the `bs` script. + +## Developing Blockscout Backend + +### Configuration + +Before running the Blockscout server, you need to set up the configuration: + +1. Copy the `.devcontainer/.blockscout_config.example` file to `.devcontainer/.blockscout_config`. +2. Adjust the settings in `.devcontainer/.blockscout_config` as needed for your development environment. + +For a comprehensive list of environment variables that can be set in this configuration file, refer to the [Blockscout documentation](https://docs.blockscout.com/setup/env-variables). + +### Using the `bs` Script + +The `bs` script in `.devcontainer/bin/` helps orchestrate common development tasks. Here are some key commands: + +- Initialize the project: `bs --init` +- Initialize or re-initialize the database: `bs --db-init` (This will remove all data and tables from the DB and re-create the tables) +- Run the server: `bs` +- Run the server without syncing: `bs --no-sync` +- Recompile the project: `bs --recompile` (Use this when new dependencies arrive after a merge or when switching to another `CHAIN_TYPE`) +- Run various checks: `bs --spellcheck`, `bs --dialyzer`, `bs --credo`, `bs --format` + +For a full list of options, run `bs --help`. + +### Interacting with the Blockscout API + +For local devcontainer setups (not applicable to GitHub Codespaces), you can use API testing tools like Postman or Insomnia on your host machine to interact with the Blockscout API running in the container: + +1. Ensure the Blockscout server is running in the devcontainer. +2. In the API testing tool on your host machine, use `http://127.0.0.1:4000` as the base URL. +3. Example endpoint: `GET http://127.0.0.1:4000/api/v2/blocks` + +This allows testing API endpoints directly from your host machine while the server runs in the container. + +### Troubleshooting + +If you face issues with dependency compilation or dialyzer after container creation: + +1. Check for untracked files: `git ls-files --others` +2. Remove compilation artifacts or generated files if present. +3. For persistent issues, consider cleaning all untracked files (use with caution): + ``` + git clean -fdX + bs --recompile + ``` + +This ensures a clean compilation environment within the container. + +## Upgrading Elixir Version + +To upgrade the Elixir version: + +1. Open `.devcontainer/Dockerfile`. +2. Update the `VARIANT` argument with the desired Elixir version. +3. Rebuild the devcontainer. + +Note: Ensure that the version you choose is compatible with the project dependencies. + +After testing the new Elixir version, propagate the corresponding changes in the Dockerfile to the repo https://github.com/blockscout/devcontainer-elixir. Once a new release tag is published there and a new docker image `ghcr.io/blockscout/devcontainer-elixir` appears in the GitHub registry, modify the `docker-compose.yml` file in the `.devcontainer` directory to reflect the proper docker image tag. + +## Contributing + +When contributing changes that require additional checks for specific blockchain types: + +1. Open `.devcontainer/bin/chain-specific-checks`. +2. Add your checks under the appropriate `CHAIN_TYPE` case. +3. Ensure your checks exit with a non-zero code if unsuccessful. + +Remember to document any new checks or configuration options in this README. \ No newline at end of file diff --git a/.devcontainer/bin/bs b/.devcontainer/bin/bs new file mode 100755 index 000000000000..145c152531dc --- /dev/null +++ b/.devcontainer/bin/bs @@ -0,0 +1,320 @@ +#!/bin/bash + +# Blockscout Development Helper Script +# +# This script provides a unified interface for common development tasks when working +# with the Blockscout backend server. It handles environment configuration, project +# initialization, and various development workflows. +# +# Main usage scenarios: +# 1. Project Setup +# - Initialize project directory: bs --init +# - Setup/reset database: bs --db-init +# +# 2. Development Tasks +# - Run backend server: bs +# - Run server (API only): bs --no-sync +# - Compile/recompile changes: bs --compile +# - Recompile dependencies: bs --recompile +# +# 3. Code Quality +# - Run formatter: bs --format +# - Run static analysis: bs --dialyzer +# - Run code style checks: bs --credo +# - Run spell checker: bs --spellcheck +# +# 4. Documentation +# - Generate project docs: bs --docs +# - Show usage help: bs --help +# +# Environment: +# - Loads configuration from .devcontainer/.blockscout_config if present +# - Uses default DATABASE_URL if not specified +# - Supports chain-specific configurations via CHAIN_TYPE + +source $(dirname $0)/utils + +# Source and export environment variables related to the backend configuration +BLOCKSCOUT_CONFIG_FILE=".devcontainer/.blockscout_config" +if [ -f "./${BLOCKSCOUT_CONFIG_FILE}" ]; then + set -a # Automatically export all variables + source ./${BLOCKSCOUT_CONFIG_FILE} + set +a # Disable automatic export +else + echo "Warning: ${BLOCKSCOUT_CONFIG_FILE} file not found. Skipping configuration loading." +fi + +if [ "${DATABASE_URL}" == "" ]; then + export DATABASE_URL="postgresql://postgres:postgres@db:5432/app" +fi + +# Initialize variables +INIT=false +NO_SYNC=false +DB_INIT=false +COMPILE=false +RECOMPILE=false +SPELLCHECK=false +DIALYZER=false +CREDO=false +FORMAT=false +DOCS=false +HELP=false + +# Define the help function +show_help() { + echo "Usage: bs [OPTION]" + echo "Orchestrate typical tasks when developing Blockscout backend server" + echo + echo "Options:" + echo " --help Show this help message and exit" + echo " --init Initialize the project directory" + echo " --format Run code formatter" + echo " --spellcheck Run spellcheck" + echo " --dialyzer Run dialyzer" + echo " --credo Run credo" + echo " --docs Generate documentation" + echo " --compile Compile/recompile changes" + echo " --recompile Re-fetch dependencies and recompile" + echo " --db-init (Re)initialize the database" + echo " --no-sync Run the server with disabled indexer, so only the API is available" + echo + echo "If no option is provided, the script will run the backend server." +} + +# Define valid arguments +VALID_ARGS=( + "--help" + "--init" + "--no-sync" + "--db-init" + "--compile" + "--recompile" + "--spellcheck" + "--dialyzer" + "--credo" + "--format" + "--docs" +) + +# Validate arguments +for arg in "$@" +do + if [[ ! " ${VALID_ARGS[@]} " =~ " ${arg} " ]]; then + echo "Error: Unknown argument '${arg}'" + echo + show_help + exit 1 + fi +done + +# Parse command line arguments +for arg in "$@" +do + case $arg in + --help) + HELP=true + shift # Remove --help from processing + ;; + --init) + INIT=true + shift # Remove --init from processing + ;; + --no-sync) + NO_SYNC=true + shift # Remove --no-sync from processing + ;; + --db-init) + DB_INIT=true + shift # Remove --db-init from processing + ;; + --compile) + COMPILE=true + shift # Remove --compile from processing + ;; + --recompile) + RECOMPILE=true + shift # Remove --recompile from processing + ;; + --spellcheck) + SPELLCHECK=true + shift # Remove --spellcheck from processing + ;; + --dialyzer) + DIALYZER=true + shift # Remove --dialyzer from processing + ;; + --credo) + CREDO=true + shift # Remove --credo from processing + ;; + --format) + FORMAT=true + shift # Remove --format from processing + ;; + --docs) + DOCS=true + shift # Remove --docs from processing + ;; + esac +done + +# If --help argument is passed, show help and exit +if [ "$HELP" = true ]; then + show_help + exit 0 +fi + +# Define the project directory initialization subroutine +initialize_project() { + if [ ! -d "apps/block_scout_web/priv/cert" ]; then + mix local.rebar --force + mix deps.compile + mix compile + + # cd apps/block_scout_web/assets + # npm install && node_modules/webpack/bin/webpack.js --mode production + # cd - + # cd apps/explorer + # npm install + # cd - + + cd apps/block_scout_web + mix phx.gen.cert blockscout blockscout.local + cd - + else + echo "Looks like the project directory is already initialized" + fi +} + +# Define the initialization subroutine +initialize_db() { + echo "Initializing database. Step 1 of 2: Dropping database" + if OUTPUT=$(mix ecto.drop 2>&1); then + echo "Initializing database. Step 2 of 2: Creating database" + mix do ecto.create, ecto.migrate | grep Runn + else + echo "Failed to drop database. Initialization aborted." + echo "Error output:" + echo "$OUTPUT" + return 1 + fi +} + +# Define the compile subroutine +compile() { + mix compile +} + +# Define the recompile subroutine +recompile() { + FALLBACK_APPS="block_scout_web ethereum_jsonrpc explorer indexer utils nft_media_handler" + APPS=$($(dirname $0)/extract_apps.exs) || APPS="$FALLBACK_APPS" + [ -z "$APPS" ] && APPS="$FALLBACK_APPS" + mix deps.clean $APPS + mix deps.get + mix deps.compile --force +} + +# Define the spellcheck subroutine +spellcheck() { + cspell | less +} + +# Define the dialyzer subroutine +dialyzer() { + if ! mix dialyzer; then + echo -e "\nDepending on the error you see, try either:" + echo " rm -rf 'priv/plts'" + echo " MIX_ENV=test bs --recompile" + return 1 + fi +} + +# Define the credo subroutine +credo() { + mix credo +} + +# Define the format subroutine +format() { + mix format +} + +# Define the generate_docs subroutine +generate_docs() { + mix docs +} + +# If --init argument is passed, run the project dir initialization subroutine and exit +if [ "$INIT" = true ]; then + initialize_project + exit 0 +fi + +# If --db-init argument is passed, run the database initialization subroutine and exit +if [ "$DB_INIT" = true ]; then + initialize_db + exit 0 +fi + +# If --compile argument is passed, run the compile subroutine and exit +if [ "$COMPILE" = true ]; then + compile + exit 0 +fi + +# If --recompile argument is passed, run the recompile subroutine and exit +if [ "$RECOMPILE" = true ]; then + recompile + exit 0 +fi + +# If --spellcheck argument is passed, run the spellcheck subroutine and exit +if [ "$SPELLCHECK" = true ]; then + spellcheck + exit 0 +fi + +# If --dialyzer argument is passed, run the dialyzer subroutine and exit +if [ "$DIALYZER" = true ]; then + dialyzer + exit 0 +fi + +# If --credo argument is passed, run the credo subroutine and exit +if [ "$CREDO" = true ]; then + credo + exit 0 +fi + +# If --format argument is passed, run the format subroutine and exit +if [ "$FORMAT" = true ]; then + format + exit 0 +fi + +# If --doc argument is passed, run the format subroutine and exit +if [ "$DOCS" = true ]; then + generate_docs + exit 0 +fi + +if [ "${ETHEREUM_JSONRPC_HTTP_URL}" != "" ]; then + check_server_availability ${ETHEREUM_JSONRPC_HTTP_URL} + check_server_accessibility ${ETHEREUM_JSONRPC_HTTP_URL} +fi + +if [ "${CHAIN_TYPE}" != "" -o "${CHAIN_TYPE}" != "ethereum" -o "${CHAIN_TYPE}" != "default" ]; then + source $(dirname $0)/chain-specific-checks +fi + +if [ ! -d "apps/block_scout_web/priv/cert" ]; then + echo "Project directory is not initialized" + echo "Run 'bs --init' to initialize the project directory" + exit 1 +fi + +export DISABLE_INDEXER=${NO_SYNC} + +mix phx.server diff --git a/.devcontainer/bin/chain-specific-checks b/.devcontainer/bin/chain-specific-checks new file mode 100644 index 000000000000..c6129f26b09a --- /dev/null +++ b/.devcontainer/bin/chain-specific-checks @@ -0,0 +1,17 @@ +# The script is sourced from the main script, so the unsuccessful check must exit +# with non-zero code to terminate the main script. + +source $(dirname $0)/utils + +# Run the appropriate checks based on CHAIN_TYPE +case "${CHAIN_TYPE}" in + "arbitrum") + echo "Arbitrum sepcific checks" + # if the check is not successful, exit with code 1 + check_server_availability ${INDEXER_ARBITRUM_L1_RPC} + check_server_accessibility ${INDEXER_ARBITRUM_L1_RPC} + ;; + *) + echo "No special checks for CHAIN_TYPE: $CHAIN_TYPE" + ;; +esac diff --git a/.devcontainer/bin/extract_apps.exs b/.devcontainer/bin/extract_apps.exs new file mode 100755 index 000000000000..a82f87c95d67 --- /dev/null +++ b/.devcontainer/bin/extract_apps.exs @@ -0,0 +1,45 @@ +#!/usr/bin/env elixir + +defmodule LocalHelper do + # Helper function to safely get configuration values + def get_config_value(config, key, name) do + case Keyword.get(config, key) do + nil -> {:error, name} + value -> {:ok, value} + end + end +end + +# Start Mix application +Mix.start() + +# Set the Mix environment to dev (or whatever environment you need) +Mix.env(:dev) + +# Read and evaluate the mix.exs file +Code.require_file("mix.exs") + +# Get the applications from the project configuration +apps = + try do + project = BlockScout.Mixfile.project() + + with {:ok, releases} <- LocalHelper.get_config_value(project, :releases, "releases"), + {:ok, blockscout} <- LocalHelper.get_config_value(releases, :blockscout, "blockscout release"), + {:ok, applications} <- LocalHelper.get_config_value(blockscout, :applications, "applications") do + applications + |> Keyword.keys() + |> Enum.join("\n") + else + {:error, message} -> + IO.puts(:stderr, "Error: #{message} not found in mix.exs configuration") + System.halt(1) + end + rescue + error -> + IO.puts(:stderr, "Error: Failed to read mix.exs configuration - #{Exception.message(error)}") + System.halt(1) + end + +# Print the applications to stdout +IO.puts(apps) diff --git a/.devcontainer/bin/utils b/.devcontainer/bin/utils new file mode 100644 index 000000000000..bd86034b8e5e --- /dev/null +++ b/.devcontainer/bin/utils @@ -0,0 +1,22 @@ +# Function to check server availability +check_server_availability() { + local url=$1 + + curl --connect-timeout 3 --silent ${url} 1>/dev/null + if [ $? -ne 0 ]; then + echo "VPN must be enabled to connect to ${url}" + exit 1 + fi +} + +# Function to check server accessibility with a POST request +check_server_accessibility() { + local url=$1 + local payload='[{"id":0,"params":["latest",false],"method":"eth_getBlockByNumber","jsonrpc":"2.0"}]' + + http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST ${url} -H "Content-Type: application/json" -d "${payload}") + if [ "$http_code" -ne 200 ]; then + echo "VPN must be enabled to access ${url} (HTTP status code: ${http_code})" + exit 1 + fi +} diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000000..54eed1903062 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,47 @@ +{ + "name": "Blockscout Elixir", + "dockerComposeFile": "docker-compose.yml", + "service": "elixir", + "workspaceFolder": "/workspace", + "postCreateCommand": { + "safe-directory": "git config --global --add safe.directory ${containerWorkspaceFolder}", + "deps": "mix deps.get", + "known_hosts": "sudo chown vscode:vscode /home/vscode/.ssh && ssh-keyscan github.com > /home/vscode/.ssh/known_hosts" + }, + "remoteEnv": { + "PATH": "${containerEnv:PATH}:${containerWorkspaceFolder}/.devcontainer/bin" + }, + // Configure tool-specific properties. + "customizations": { + // Configure properties specific to VS Code. + "vscode": { + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "JakeBecker.elixir-ls", + "ckolkman.vscode-postgres", + "GitHub.copilot", + "GitHub.copilot-chat", + "GitHub.vscode-pull-request-github" + ] + } + }, + "features": { + "ghcr.io/stuartleeks/dev-container-features/shell-history:0": {} + }, + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // This can be used to network with other containers or with the host. + "forwardPorts": [ + 4000, + 4001, + 5432 + ], + // Uncomment and adjust the private key path to the one you use to authenticate on GitHub + // if you want to have ability to push to GitHub from the container. + // "mounts": [ + // "source=${localEnv:HOME}/.ssh/config,target=/home/vscode/.ssh/config,type=bind,consistency=cached", + // // Make sure that the private key can be used to authenticate on GitHub + // "source=${localEnv:HOME}/.ssh/id_rsa,target=/home/vscode/.ssh/id_rsa,type=bind,consistency=cached" + // ], + // Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 000000000000..b0126db4cc9d --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,30 @@ +services: + elixir: + image: ghcr.io/blockscout/devcontainer-elixir:1.19.4-erlang-27.3.4.6 + + # Uncomment next lines to use test Dockerfile with new Elixir version + # build: + # context: . + # dockerfile: Dockerfile + + volumes: + - ..:/workspace:cached + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + db: + image: postgres:17 + command: postgres -c 'max_connections=250' + restart: unless-stopped + volumes: + - postgres-data:/var/lib/postgresql/data + environment: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: app + +volumes: + postgres-data: diff --git a/.dialyzer-ignore b/.dialyzer-ignore deleted file mode 100644 index ec75e5e7ddb8..000000000000 --- a/.dialyzer-ignore +++ /dev/null @@ -1,37 +0,0 @@ -:0: Unknown function 'Elixir.ExUnit.Callbacks':'__merge__'/3 -:0: Unknown function 'Elixir.ExUnit.CaseTemplate':'__proxy__'/2 -:0: Unknown type 'Elixir.Map':t/0 -:0: Unknown type 'Elixir.Hash':t/0 -:0: Unknown type 'Elixir.Address':t/0 -apps/ethereum_jsonrpc/lib/ethereum_jsonrpc.ex:400: Function timestamp_to_datetime/1 has no local return -lib/ethereum_jsonrpc/rolling_window.ex:173 -lib/explorer/repo/prometheus_logger.ex:8 -lib/explorer/smart_contract/solidity/publisher_worker.ex:1 -lib/explorer/smart_contract/vyper/publisher_worker.ex:1 -lib/explorer/smart_contract/solidity/publisher_worker.ex:6 -lib/explorer/smart_contract/vyper/publisher_worker.ex:6 -apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: Function microseconds_time/1 has no local return -apps/explorer/lib/explorer/repo/prometheus_logger.ex:8: The call 'Elixir.System':convert_time_unit(__@1::any(),'native','microseconds') breaks the contract (integer(),time_unit() | 'native',time_unit() | 'native') -> integer() -lib/block_scout_web/router.ex:1 -lib/block_scout_web/schema/types.ex:31 -lib/phoenix/router.ex:324 -lib/phoenix/router.ex:402 -lib/block_scout_web/views/layout_view.ex:145: The call 'Elixir.Poison.Parser':'parse!' -lib/block_scout_web/views/layout_view.ex:237: The call 'Elixir.Poison.Parser':'parse!' -lib/explorer/smart_contract/reader.ex:435 -lib/indexer/fetcher/token_total_supply_on_demand.ex:16 -lib/explorer/exchange_rates/source.ex:110 -lib/explorer/exchange_rates/source.ex:113 -lib/explorer/smart_contract/solidity/verifier.ex:162 -lib/block_scout_web/templates/address_contract/index.html.eex:162 -lib/block_scout_web/templates/address_contract/index.html.eex:199 -lib/explorer/staking/stake_snapshotting.ex:15: Function do_snapshotting/7 has no local return -lib/explorer/staking/stake_snapshotting.ex:147 -lib/explorer/third_party_integrations/sourcify.ex:70 -lib/explorer/third_party_integrations/sourcify.ex:73 -lib/block_scout_web/views/transaction_view.ex:137 -lib/block_scout_web/views/transaction_view.ex:152 -lib/block_scout_web/views/transaction_view.ex:197 -lib/indexer/buffered_task.ex:402 -lib/indexer/buffered_task.ex:451 -lib/indexer/memory/monitor.ex:160 diff --git a/.dialyzer_ignore.exs b/.dialyzer_ignore.exs new file mode 100644 index 000000000000..170fe3dbb0f2 --- /dev/null +++ b/.dialyzer_ignore.exs @@ -0,0 +1,13 @@ +[ + {"lib/ethereum_jsonrpc/rolling_window.ex", :improper_list_constr}, + {"lib/explorer/smart_contract/solidity/publisher_worker.ex", :pattern_match, 1}, + {"lib/explorer/smart_contract/solidity/publisher_worker.ex", :exact_eq, 9}, + {"lib/explorer/smart_contract/solidity/publisher_worker.ex", :pattern_match, 9}, + {"lib/explorer/smart_contract/vyper/publisher_worker.ex", :pattern_match, 1}, + {"lib/explorer/smart_contract/vyper/publisher_worker.ex", :exact_eq, 9}, + {"lib/explorer/smart_contract/vyper/publisher_worker.ex", :pattern_match, 9}, + {"lib/explorer/smart_contract/stylus/publisher_worker.ex", :pattern_match, 1}, + {"lib/explorer/smart_contract/stylus/publisher_worker.ex", :exact_eq, 15}, + {"lib/explorer/smart_contract/stylus/publisher_worker.ex", :pattern_match, 15}, + ~r/lib\/phoenix\/router.ex/ +] diff --git a/.dockerignore b/.dockerignore index b52edd4f4769..86f0f1d690d0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,5 +5,9 @@ apps/explorer/node_modules test .git .circleci +.vscode +.elixir_ls +erl_crash.dump logs apps/*/test +.devcontainer \ No newline at end of file diff --git a/.formatter.exs b/.formatter.exs index 69ae0d25d2c6..563ddfd8e03a 100644 --- a/.formatter.exs +++ b/.formatter.exs @@ -7,5 +7,6 @@ "mix.exs", "{config}/**/*.{ex,exs}" ], - line_length: 120 + line_length: 120, + import_deps: [:open_api_spex] ] diff --git a/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md similarity index 97% rename from CODE_OF_CONDUCT.md rename to .github/CODE_OF_CONDUCT.md index bfc85b0255bb..7507d6224673 100644 --- a/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -3,7 +3,7 @@ ## Our Pledge In the interest of fostering an open and welcoming environment, we as -contributors and maintainers pledge to making participation in our project and +contributors and maintainers pledge to make participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 000000000000..86a77646193b --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,261 @@ +# Contribution Guidelines: What We Are Looking For + +We welcome contributions that enhance the project and improve the overall quality of our codebase. While we appreciate the effort that goes into making contributions, we kindly ask that contributors focus on the following types of changes: +- Feature Enhancements: Substantial improvements or new features that add significant value to the project. +- Bug Fixes: Fixes for known bugs or issues that impact functionality. +- Documentation Improvements: Comprehensive updates to documentation that clarify usage, installation, or project structure. +- Performance Improvements: Changes that enhance the performance or efficiency of the application. + +# Contributing + +1. Fork it ( ) +2. Create your feature branch (`git checkout -b my-new-feature`) +3. Write tests that cover your work +4. Commit your changes (`git commit -am 'Add some feature'`) +5. Push to the branch (`git push origin my-new-feature`) +6. Create a new Pull Request targeting the `dev` branch. The title of Pull Request should follow [Conventional Commits specification](https://www.conventionalcommits.org/en/v1.0.0/) and should start with `feat:`, `fix:`, `chore:`, `doc:`, `perf:`, `refactor:` prefix. + +## General + +* Keep `.dialyzer-ignore` as small as possible. Only add entries to suppress false positives that cannot be resolved by fixing the underlying type issue. Every new suppression should include a comment explaining why it is necessary and cannot be fixed properly. +* Commits should be one logical change that still allows all tests to pass. Prefer smaller commits if there could be two levels of logic grouping. The goal is to allow contributors in the future (including your own future self) to determine your reasoning for making changes and to allow them to cherry-pick, patch or port those changes in isolation to other branches or forks. +* If during your PR you reveal a pre-existing bug: + 1. Try to isolate the bug and fix it on an independent branch and PR it first. + 2. Try to fix the bug in a separate commit from other changes: + 1. Commit the code in the broken state that revealed the bug originally + 2. Commit the fix for the bug. + 3. Continue original PR work. + +## Enhancements + +Enhancements cover all changes that make users lives better: + +* [feature requests filed as issues](https://github.com/blockscout/blockscout/labels/enhancement) that impact end-user [contributors](https://github.com/blockscout/blockscout/labels/contributor) and [developers](https://github.com/blockscout/blockscout/labels/developer) +* changes to the [architecture](https://github.com/blockscout/blockscout/labels/architecture) that make it easier for contributors (in the GitHub sense), dev-ops, and deployers to maintain and run blockscout + +## Bug Fixes + +For bug fixes, whenever possible, there should be at least 2 commits: + +1. A regression test commit that contains tests that demonstrate the bug and show as failing. +2. The bug fix commit that shows the regression test now passing. + +This format ensures that we can run the test to reproduce the original bug without depending on the new code in the fix, which could lead to the test falsely passing. + +## Incompatible Changes + +Incompatible changes can arise as a side-effect of either Enhancements or Bug Fixes. During Enhancements, incompatible changes can occur because, as an example, in order to support showing end-users new data, the database schema may need to be changed and the index rebuilt from scratch. During bug fixes, incompatible changes can occur because in order to fix a bug, the schema had to change, or how certain internal APIs are called changed. + +* Incompatible changes should be called out explicitly, with any steps the various user roles need to do to upgrade. +* If a schema change occurs that requires a re-index add the following to the Pull Request description: + + ```markdown + **NOTE**: A database reset and re-index is required + ``` + +## Pull Request + +There is a [PULL_REQUEST_TEMPLATE.md](PULL_REQUEST_TEMPLATE.md) for this repository, but since it can't fill in the title for you, please follow the following steps when opening a Pull Request before filling in the template: + +* [ ] Title + * [ ] Prefix labels if you don't have permissions to set labels in the GitHub interface. + * (bug) for [bug](https://github.com/blockscout/blockscout/labels/bug) fixes + * (enhancement) for [enhancement](https://github.com/blockscout/blockscout/labels/enhancement)s + * (incompatible changes) for [incompatible changes](https://github.com/blockscout/blockscout/labels/incompatible%20changes), such a refactor that removes functionality, changes arguments, or makes something required that wasn't previously. + * [ ] Single sentence summary of change + * What was fixed for bugs + * What was added for enhancements + * What was changed for incompatible changes + +See [#255](https://github.com/blockscout/blockscout/pull/255) as an example PR that uses GitHub keywords and a Changelog to explain multiple changes. + +## Basic Naming Convention + +When contributing to the codebase, please adhere to the following naming conventions to ensure clarity and consistency: + +- Use full names for entities. Avoid abbreviations or shorthand. + - Instead of "tx" or "txn", use "transaction". + - Instead of "txs", use "transactions". + - Instead of "tx_hash" or "txn_hash", use "transaction_hash". + - Instead of "address", use "address_hash". + - Instead of "block_num", use "block_number". +- Ensure that variable names are descriptive and convey the purpose or content clearly. +- Consistent naming helps in maintaining readability and understanding of the code, especially for new contributors. + +By following these conventions, we can maintain a clean and understandable codebase. + +### API V2 Naming Convention + +When contributing to the API v2, please adhere to the following naming conventions for response fields to ensure clarity and consistency: + +- The block number should be returned as a number in the property with the name which ends with `block_number`. +- All hashes (transaction, block address etc.) should be returned as a hex string in the property which ends with `_hash`. +- Property name for aggregations like counts and sums should contain plural form of entity and `_count`, `_sum` suffix respecively, e.g. `transactions_count`, `blocks_count`, `withdrawals_sum`. +- All fields that contain the "index" suffix should be returned as numbers. + +## Environment Configuration Best Practices + +### Runtime vs. Compile-time Configuration + +We strongly favor **runtime configuration** over compile-time configuration +whenever possible. This approach: + +- Reduces the number of Docker images needed +- Increases deployment flexibility +- Simplifies maintenance and testing + +When **adding** new configuration options, chain types, or **refactoring** +existing ones, please follow the decision tree below to determine the +appropriate approach: + +```mermaid +flowchart TD + A[Add/Modify Configuration Option or Chain Type] --> B{Is it feature-specific behavior of a function?} + B -->|Yes| C[Use RuntimeEnvHelper or Application.get_env/3 and pattern matching] + B -->|No| D{Does it need new database tables?} + D -->|Yes| E[Create new Ecto.Repo and handle it at runtime in config_helper.ex] + D -->|No| F{Is it an API endpoint?} + F -->|Yes| G[Use chain_scope macro or CheckFeature plug] + F -->|No| H{Does it modify existing database schema?} + H -->|Yes| I[Use Compile-time configuration] + H -->|No| J[Contact us to discuss this case further] + I -->|Future Work| O[Refactor toward Runtime configuration] +``` + +#### Use runtime configuration and pattern matching + +Anti-pattern: + +```elixir +# AVOID THIS +use Utils.CompileTimeEnvHelper, + chain_type: [:explorer, :chain_type] + +if @chain_type == :optimism do + def foo, do: :bar +else + def foo, do: :baz +end +``` + +Better approach: + +```elixir +# DO THIS INSTEAD +use Utils.RuntimeEnvHelper, + chain_type: [:explorer, :chain_type] + +def foo, do: chain_type() |> do_foo() + +defp do_foo(:optimism), do: :bar +defp do_foo(_), do: :baz +``` + +#### New database tables + +If your feature or chain-specific functionality requires new database tables: + +1. Define a new repository module in `apps/explorer/lib/explorer/repo.ex`. +2. Add the repository to `config/config_helper.exs` in the `repos/0` function. +3. Include a runtime check to load this repo conditionally: + +```elixir +# In config_helper.ex +ext_repos = [ + {parse_bool_env_var("MY_FEATURE_ENABLED"), Explorer.Repo.MyFeature}, + # other feature repos... +] +|> Enum.filter(&elem(&1, 0)) +|> Enum.map(&elem(&1, 1)) +``` + +This approach ensures migrations are automatically detected and applied at +runtime without requiring recompilation. + +#### API endpoints + +For feature-specific or chain-specific API endpoints, use one of the following +runtime approaches: + +1. **For chain-specific routes**, use the `chain_scope` macro in your router: + +```elixir +scope "/v2", as: :api_v2 do + chain_scope :zksync do + get("/zksync-batch/:batch_number", V2.TransactionController, :zksync_batch) + end +end +``` + +2. **For feature-toggle endpoints**, use `CheckFeature` plug in pipelines: + +```elixir +pipeline :my_feature do + plug(BlockScoutWeb.Plug.CheckFeature, feature_check: &my_feature_enabled?/0) +end + +scope "/my-feature" do + pipe_through(:my_feature) + + get "/data", MyFeatureController, :index +end +``` + +Both approaches return appropriate 404 responses when the feature is disabled or +chain type doesn't match. + +#### Modifying existing database schema + +If your functionality requires modifying existing database schema structures +(adding columns to shared tables, changing constraints, etc.), you currently +must use compile-time configuration. This is the **only case** where +compile-time configuration is still recommended. + +```elixir +# Current approach for schema modifications +use Utils.CompileTimeEnvHelper, + chain_type: [:explorer, :chain_type] + +if @chain_type == :optimism do + # Schema modifications specific to Optimism +end +``` + +To prepare for future runtime refactoring, isolate these schema-specific changes +as much as possible. + +This limitation stems from Ecto schemas being defined at compile-time. When +different chain types need variations in shared tables (additional fields, +different constraints), these schema differences cannot be modified at runtime. +We're currently researching approaches for dynamic schema adjustment based on +runtime configuration. + +For reference on which chain types still require compile-time configuration, see +the [Chain-Specific Environment +Variables](https://docs.blockscout.com/setup/env-variables/backend-envs-chain-specific) +documentation. + +### Compile time Environment Variables + +Before using compile-time configuration, ensure you've exhausted all runtime +alternatives by following the decision tree above. If after careful +consideration you still need to work with compile-time environment variables, +follow these guidelines: + +- Always use the `Utils.CompileTimeEnvHelper` module instead of direct + `Application.compile_env/2` calls: + +```elixir +# DO use this approach +use Utils.CompileTimeEnvHelper, + attribute_name: [:app, :test] + +# Access the value using the module attribute +@attribute_name + +# DON'T use this approach +Application.compile_env(:app, :test) # avoid direct compile_env calls +``` + +This approach provides faster compilation time and simplifies development and +maintenance. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000000..5fa188d46862 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,100 @@ +name: Bug Report +description: File a bug report +labels: [ "triage" ] +body: + - type: markdown + attributes: + value: | + Thanks for reporting a bug 🐛! + + Please search open/closed issues before submitting. Someone might have had the similar problem before 😉! + + - type: textarea + id: description + attributes: + label: Description + description: A brief description of the issue. + validations: + required: true + + - type: dropdown + id: installation-type + attributes: + label: Type of the installation + description: How the application has been deployed. + options: + - Docker-compose + - Helm charts (k8s) + - Manual from the source code + - Docker + validations: + required: true + + - type: input + id: archive-node-type + attributes: + label: Type of the JSON RPC archive node + description: Which type of archive node is used. + placeholder: "Erigon/Geth/Nethermind/Reth/PolygonEdge/Besu/OpenEthereum/..." + validations: + required: true + + - type: input + id: chain-type + attributes: + label: Type of the chain + description: Type of the chain. + placeholder: L1/L2/... + + - type: input + id: link + attributes: + label: Link to the page + description: The link to the page where the issue occurs. + placeholder: https://eth.blockscout.com + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: | + Explain how to reproduce the issue in the development environment. + + - type: input + id: backend-version + attributes: + label: Backend version + description: The release version of the backend or branch/commit. + placeholder: v6.1.0 + validations: + required: true + + - type: input + id: frontend-version + attributes: + label: Frontend version + description: The release version of the frontend or branch/commit. + placeholder: v1.11.1 + + - type: input + id: elixir-version + attributes: + label: Elixir & Erlang/OTP versions + description: Elixir & Erlang/OTP versions. + placeholder: Elixir 1.17.3 (compiled with Erlang/OTP 27) + validations: + required: true + + - type: input + id: os-version + attributes: + label: Operating system + description: The operating system this issue occurred with. + placeholder: Linux/macOS/Windows + + - type: textarea + id: additional-information + attributes: + label: Additional information + description: | + Use this section to provide any additional information you might have (e.g screenshots or screencasts). \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000000..439bca677db3 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Feature Request + url: https://blockscout.canny.io/feature-requests + about: Request a feature or enhancement + - name: Ask a question + url: https://github.com/orgs/blockscout/discussions + about: Ask questions and discuss topics with other community members + - name: Join our Discord Server + url: https://discord.gg/blockscout + about: The official Blockscout Discord community \ No newline at end of file diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000000..15ab63d31d24 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,36 @@ +_[GitHub keywords to close any associated issues](https://docs.github.com/en/issues/tracking-your-work-with-issues/closing-issues-using-keywords)_ + +## Motivation + +_Why we should merge these changes. If using GitHub keywords to close [issues](https://github.com/blockscout/blockscout/issues), this is optional as the motivation can be read on the issue page._ + +## Changelog + +### Enhancements + +_Things you added that don't break anything. Regression tests for Bug Fixes count as Enhancements._ + +### Bug Fixes + +_Things you changed that fix bugs. If it fixes a bug but, in so doing, adds a new requirement, removes code, or requires a database reset and reindex, the breaking part of the change should also be added to "Incompatible Changes" below._ + +### Incompatible Changes + +_Things you broke while doing Enhancements and Bug Fixes. Breaking changes include (1) adding new requirements and (2) removing code. Renaming counts as (2) because a rename is a removal followed by an add._ + +## Upgrading + +_If you have any Incompatible Changes in the above Changelog, outline how users of prior versions can upgrade once this PR lands or when reviewers are testing locally. A common upgrading step is "Database reset and re-index required"._ + +## Checklist for your Pull Request (PR) + +- [ ] I verified this PR does not break any public APIs, contracts, or interfaces that external consumers depend on. +- [ ] If I added new functionality, I added tests covering it. +- [ ] If I fixed a bug, I added a regression test to prevent the bug from silently reappearing again. +- [ ] I updated documentation if needed: + - [ ] General docs: submitted PR to [docs repository](https://github.com/blockscout/docs). + - [ ] ENV vars: updated [env vars list](https://github.com/blockscout/docs/tree/main/setup/env-variables) and set version parameter to `master`. + - [ ] Deprecated vars: added to [deprecated env vars list](https://github.com/blockscout/docs/tree/main/setup/env-variables/deprecated-env-variables). +- [ ] If I modified API endpoints, I updated the Swagger/OpenAPI schemas accordingly and checked that schemas are asserted in tests, and highlighted the change in the PR description. +- [ ] If I added new DB indices, I checked, that they are not redundant, with PGHero or other tools. +- [ ] If I added/removed chain type, I modified the Github CI matrix and PR labels accordingly. diff --git a/.github/actions/setup-repo/action.yml b/.github/actions/setup-repo/action.yml new file mode 100644 index 000000000000..ac52f13172d1 --- /dev/null +++ b/.github/actions/setup-repo/action.yml @@ -0,0 +1,86 @@ +name: 'Setup repo' +description: 'Setup repo: checkout/login/extract metadata, Set up Docker Buildx' +inputs: + github-token: + description: 'GitHub token for ghcr.io authentication' + required: true + docker-remote-multi-platform: + description: 'Docker remote multi-platform builder' + required: true + default: 'false' + docker-arm-host: + description: 'Docker remote arm builder' + required: false + docker-arm-host-key: + description: 'Docker remote arm builder ssh private key' + required: false + docker-image: + description: 'Docker image' + required: true + default: ghcr.io/blockscout/blockscout +outputs: + docker-builder: + description: 'Docker builder' + value: ${{ steps.builder_local.outputs.name || steps.builder_multi.outputs.name }} + docker-tags: + description: 'Docker metadata tags' + value: ${{ steps.meta.outputs.tags }} + docker-labels: + description: 'Docker metadata labels' + value: ${{ steps.meta.outputs.labels }} + docker-platforms: + description: 'Docker build platforms' + value: ${{ steps.builder_local.outputs.platforms || steps.builder_multi.outputs.platforms }} +runs: + using: "composite" + steps: + - name: Set up SSH key + shell: bash + run: | + mkdir -p ~/.ssh + echo "${{ inputs.docker-arm-host-key }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + - name: Find builder + if: ${{ inputs.docker-remote-multi-platform }} + shell: bash + run: echo "BUILDER_IP=$(./.github/scripts/select-builder.sh ${{ inputs.docker-arm-host }} root ~/.ssh/id_rsa)" >> $GITHUB_ENV + - name: Set up SSH + if: ${{ inputs.docker-remote-multi-platform }} + uses: MrSquaare/ssh-setup-action@523473d91581ccbf89565e12b40faba93f2708bd # v1.1.0 + with: + host: ${{ env.BUILDER_IP }} + private-key: ${{ inputs.docker-arm-host-key }} + + - name: Set up Docker Buildx + if: ${{ !inputs.docker-remote-multi-platform }} + uses: docker/setup-buildx-action@v3 + id: builder_local + with: + platforms: linux/amd64 + + - name: Set up Multi-platform Docker Buildx + if: ${{ inputs.docker-remote-multi-platform }} + uses: docker/setup-buildx-action@v3 + id: builder_multi + with: + platforms: linux/amd64 + append: | + - endpoint: ssh://root@${{ env.BUILDER_IP }} + platforms: linux/arm64/v8 + + - name: Log in to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ inputs.github-token }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ inputs.docker-image }} + + - name: Add SHORT_SHA env property with commit short sha + shell: bash + run: echo "SHORT_SHA=`echo ${GITHUB_SHA} | cut -c1-8`" >> $GITHUB_ENV diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000000..90b61deae2b8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,23 @@ +version: 2 +updates: + - package-ecosystem: "mix" + directory: "/" + open-pull-requests-limit: 20 + schedule: + interval: "weekly" + + # - package-ecosystem: "npm" + # directory: "/apps/block_scout_web/assets" + # open-pull-requests-limit: 10 + # schedule: + # interval: "monthly" + # ignore: + # - dependency-name: "bootstrap" + # - dependency-name: "web3" + # versions: ["4.x"] + + # - package-ecosystem: "npm" + # directory: "/apps/explorer" + # open-pull-requests-limit: 10 + # schedule: + # interval: "monthly" diff --git a/.github/scripts/select-builder.sh b/.github/scripts/select-builder.sh new file mode 100755 index 000000000000..e785109cf559 --- /dev/null +++ b/.github/scripts/select-builder.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +# Check if a domain is provided as an argument +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +DOMAIN=$1 +SSH_USER=$2 +SSH_KEY=$3 + +# Resolve A records +IP_LIST=$(dig +short A $DOMAIN) +if [ -z "$IP_LIST" ]; then + echo "No IPs found for domain $DOMAIN" + exit 1 +fi + +MIN_LA=1000000 +BEST_BUILDER="" + +for IP in $IP_LIST; do + # Check if the host is reachable via SSH + ssh -o StrictHostKeychecking=no -o ConnectTimeout=5 -o BatchMode=yes -i $SSH_KEY $SSH_USER@$IP "exit" 2>/dev/null + if [ $? -eq 0 ]; then + # Get the load average + LA=$(ssh -o StrictHostKeychecking=no -i $SSH_KEY $SSH_USER@$IP "uptime | awk -F'load average:' '{ print \$2 }' | cut -d, -f1" 2>/dev/null) + if [ $? -eq 0 ]; then + # Compare and find the minimum load average + LA=$(echo $LA | xargs) # Trim whitespace + if (( $(echo "$LA < $MIN_LA" | bc -l) )); then + MIN_LA=$LA + BEST_BUILDER=$IP + fi + fi + fi +done + +if [ -n "$BEST_BUILDER" ]; then + echo "$BEST_BUILDER" | tr -d '[:space:]' +else + echo "No reachable hosts found." +fi diff --git a/.github/workflows/antiscam.yml b/.github/workflows/antiscam.yml new file mode 100644 index 000000000000..2da1a0519264 --- /dev/null +++ b/.github/workflows/antiscam.yml @@ -0,0 +1,29 @@ +name: antiscam + +on: + issue_comment: + types: + - created + - edited + + discussion_comment: + types: + - created + - edited + +permissions: + pull-requests: write + issues: write + +jobs: + build: + if: ${{ !github.event.issue.pull_request }} + name: Antiscam + runs-on: ubuntu-latest + + steps: + - uses: vbaranov/antiscam-action@main + with: + token: ${{ github.token }} + env: + SCAM_ACTION_WHITELISTED_LOGINS: ${{ vars.SCAM_ACTION_WHITELISTED_LOGINS }} \ No newline at end of file diff --git a/.github/workflows/antispam.yml b/.github/workflows/antispam.yml new file mode 100644 index 000000000000..b7c6b02d914b --- /dev/null +++ b/.github/workflows/antispam.yml @@ -0,0 +1,24 @@ +name: antispam + +on: + issues: + types: + - opened + - edited + - reopened + +permissions: + pull-requests: write + issues: write + +jobs: + build: + name: Antispam + runs-on: ubuntu-latest + + steps: + - uses: vbaranov/antispam-action@main + with: + token: ${{ github.token }} + env: + SCAM_ACTION_WHITELISTED_LOGINS: ${{ vars.SCAM_ACTION_WHITELISTED_LOGINS }} diff --git a/.github/workflows/close-issues-on-dev-merge.yml b/.github/workflows/close-issues-on-dev-merge.yml new file mode 100644 index 000000000000..4124c3a92c3e --- /dev/null +++ b/.github/workflows/close-issues-on-dev-merge.yml @@ -0,0 +1,145 @@ +name: Close issues on dev merge + +on: + pull_request: + types: [closed] + branches: [dev] + +permissions: + issues: write + pull-requests: read + +jobs: + close-linked-issues: + if: github.event.pull_request.merged == true + runs-on: ubuntu-latest + steps: + - name: Close issues linked via closing keywords + uses: actions/github-script@v7 + with: + script: | + const SINGLE_ISSUE_REF = + "(?:[\\w.-]+\\/[\\w.-]+)?#\\d+" + + "|https?:\\/\\/github\\.com\\/[\\w.-]+\\/[\\w.-]+\\/issues\\/\\d+"; + + const ISSUE_REF_PATTERN = new RegExp( + `(?:^|[\\s(])(?:close|closes|closed|fix|fixes|fixed|resolve|resolves|resolved)\\s+((?:${SINGLE_ISSUE_REF})(?:\\s*(?:,\\s*|\\s+and\\s+)(?:${SINGLE_ISSUE_REF}))*)`, + "gi" + ); + + const HASH_REF_PATTERN = /(?:(?[\w.-]+\/[\w.-]+))?#(?\d+)/g; + const URL_REF_PATTERN = + /https?:\/\/github\.com\/(?[\w.-]+)\/(?[\w.-]+)\/issues\/(?\d+)/gi; + + const addIssueFromRef = (issueNumbers, { refRepo, number }, { owner, repo }) => { + if (refRepo && refRepo.toLowerCase() !== `${owner}/${repo}`.toLowerCase()) { + return; + } + + issueNumbers.add(Number(number)); + }; + + const parseIssueNumbers = (text, { owner, repo }) => { + if (!text) return []; + + const issueNumbers = new Set(); + let match; + + ISSUE_REF_PATTERN.lastIndex = 0; + + while ((match = ISSUE_REF_PATTERN.exec(text)) !== null) { + const refs = match[1]; + let refMatch; + + HASH_REF_PATTERN.lastIndex = 0; + + while ((refMatch = HASH_REF_PATTERN.exec(refs)) !== null) { + addIssueFromRef(issueNumbers, refMatch.groups, { owner, repo }); + } + + URL_REF_PATTERN.lastIndex = 0; + + while ((refMatch = URL_REF_PATTERN.exec(refs)) !== null) { + const { owner: refOwner, repoName, number } = refMatch.groups; + const refRepo = `${refOwner}/${repoName}`; + + addIssueFromRef(issueNumbers, { refRepo, number }, { owner, repo }); + } + } + + return [...issueNumbers]; + }; + + const { owner, repo } = context.repo; + const pull_number = context.payload.pull_request.number; + const pr = context.payload.pull_request; + + const commits = await github.paginate( + github.rest.pulls.listCommits, + { owner, repo, pull_number } + ); + + const commitMessages = commits + .map((commit) => commit.commit.message) + .join("\n"); + + const texts = [pr.title, pr.body, commitMessages].filter(Boolean); + const repoContext = { owner, repo }; + const issueNumbers = [ + ...new Set( + texts.flatMap((text) => parseIssueNumbers(text, repoContext)) + ), + ]; + + if (issueNumbers.length === 0) { + core.info("No issues to close (no closing keywords found)."); + return; + } + + core.info(`Closing issues: ${issueNumbers.join(", ")}`); + + for (const issue_number of issueNumbers) { + try { + const { data: issue } = await github.rest.issues.get({ + owner, + repo, + issue_number, + }); + + if (issue.state === "closed") { + core.info(`Issue #${issue_number} is already closed.`); + continue; + } + + if (issue.pull_request) { + core.info(`Skipping #${issue_number}: not an issue.`); + continue; + } + + await github.rest.issues.update({ + owner, + repo, + issue_number, + state: "closed", + state_reason: "completed", + }); + + await github.rest.issues.createComment({ + owner, + repo, + issue_number, + body: + `Closed by merge of #${pull_number} into \`dev\`.\n\n` + + `GitHub closes linked issues automatically only when merging into the default branch. ` + + `This comment was added by the [\`close-issues-on-dev-merge\`](${context.serverUrl}/${owner}/${repo}/actions/workflows/close-issues-on-dev-merge.yml) workflow.`, + }); + + core.info(`Closed issue #${issue_number}.`); + } catch (error) { + if (error.status === 404) { + core.warning(`Issue #${issue_number} not found in ${owner}/${repo}.`); + } else { + core.setFailed(`Failed to close issue #${issue_number}: ${error.message}`); + } + } + } diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 000000000000..c437d1dcdf2f --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,72 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "master" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "master" ] + schedule: + - cron: '45 11 * * 5' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v5 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/config.yml b/.github/workflows/config.yml index 67abe0e88316..68ed91347de1 100644 --- a/.github/workflows/config.yml +++ b/.github/workflows/config.yml @@ -1,29 +1,114 @@ -name: Blockscout +name: Blockscout main CI on: push: branches: - master + - dev + paths-ignore: + - "CHANGELOG.md" + - "**/README.md" + - "docker/*" + - "docker-compose/*" + workflow_dispatch: pull_request: + types: [opened, synchronize, reopened, labeled] branches: - master - - staking + - dev env: MIX_ENV: test - OTP_VERSION: '24.3.3' - ELIXIR_VERSION: '1.13.4' + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + ACCOUNT_AUTH0_DOMAIN: "blockscoutcom.us.auth0.com" jobs: + matrix-builder: + name: Build matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - id: set-matrix + run: | + echo "matrix=$(node -e ' + + const defaultChainTypes = ["default"]; + + // Add/remove CI matrix chain types here + const chainTypes = [ + "default", + "arbitrum", + "arc", + "blackfort", + "eden", + "ethereum", + "filecoin", + "optimism", + "optimism-celo", + "rsk", + "scroll", + "shibarium", + "stability", + "zetachain", + "zilliqa", + "zksync", + "neon" + ]; + + // Add/remove CI matrix chain types for "ci:core" label here + const coreChainTypes = [ + "default", + "ethereum", + "optimism", + "optimism-celo" + ]; + + const labels = ${{ github.event_name == 'pull_request' && toJson(github.event.pull_request.labels.*.name) || '[]' }}; + const ciLabels = labels.filter(label => label.startsWith("ci:")); + const labeledChainTypes = chainTypes.filter(chainType => + ciLabels.includes("ci:all") || + ciLabels.includes("ci:core") && coreChainTypes.includes(chainType) || + ciLabels.includes("ci:" + chainType) + ); + + // Chain type matrix we use in PRs to master/dev branches + const ciChainTypes = labeledChainTypes.length > 0 ? labeledChainTypes : defaultChainTypes; + + // Check for bridged tokens label + const hasBridgedTokensLabel = ciLabels.includes("ci:bridged-tokens"); + + // Create matrix combinations + const targetChainTypes = ${{ github.event_name == 'pull_request' && 'ciChainTypes' || 'chainTypes' }}; + const bridgedTokensConfigs = hasBridgedTokensLabel ? [false, true] : [false]; + + const matrixIncludes = []; + for (const chainType of targetChainTypes) { + for (const bridgedTokens of bridgedTokensConfigs) { + matrixIncludes.push({ + "chain-type": chainType, + "bridged-tokens": bridgedTokens + }); + } + } + + const matrix = { "include": matrixIncludes }; + console.log(JSON.stringify(matrix)); + ')" >> $GITHUB_OUTPUT + build-and-cache: name: Build and Cache deps - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: "ELIXIR_VERSION.lock" run: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock @@ -32,28 +117,27 @@ jobs: run: echo "${OTP_VERSION}" > OTP_VERSION.lock - name: Restore Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps- + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Conditionally build Mix deps cache if: steps.deps-cache.outputs.cache-hit != 'true' run: | mix local.hex --force mix local.rebar --force + mix deps.clean --all mix deps.get - mix deps.compile - cd deps/libsecp256k1 - make + mix deps.compile --skip-umbrella-children - name: Restore Explorer NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: explorer-npm-cache with: path: apps/explorer/node_modules @@ -67,7 +151,7 @@ jobs: working-directory: apps/explorer - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: blockscoutweb-npm-cache with: path: apps/block_scout_web/assets/node_modules @@ -82,138 +166,166 @@ jobs: credo: name: Credo - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: build-and-cache steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} - + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex + - name: Restore Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - run: mix credo check_formatted: name: Code formatting checks - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: build-and-cache steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Restore Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - run: mix format --check-formatted + dialyzer: + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }} name: Dialyzer static analysis - runs-on: ubuntu-18.04 - needs: build-and-cache + runs-on: ubuntu-latest + needs: + - build-and-cache + - matrix-builder steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Restore Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Restore Dialyzer Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: dialyzer-cache with: path: priv/plts - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-${{ matrix.chain-type }}-${{ matrix.bridged-tokens }}-dialyzer-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-dialyzer-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-${{ matrix.chain-type }}-${{ matrix.bridged-tokens }}-dialyzer-mixlockhash- - name: Conditionally build Dialyzer Cache if: steps.dialyzer-cache.output.cache-hit != 'true' run: | mkdir -p priv/plts mix dialyzer --plt + env: + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + BRIDGED_TOKENS_ENABLED: ${{ matrix.bridged-tokens }} - - run: mix dialyzer --halt-exit-status - name: Run Dialyzer + - name: Run Dialyzer + run: mix dialyzer --halt-exit-status + env: + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + BRIDGED_TOKENS_ENABLED: ${{ matrix.bridged-tokens }} gettext: name: Missing translation keys check - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: build-and-cache steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Restore Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - run: | mix gettext.extract --merge | tee stdout.txt - ! grep "Wrote " stdout.txt + grep "Wrote priv/gettext/en/LC_MESSAGES/default.po (0 new messages, 0 removed, " stdout.txt working-directory: "apps/block_scout_web" + sobelow: name: Sobelow security analysis - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: build-and-cache steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Scan explorer for vulnerabilities run: mix sobelow --config @@ -221,30 +333,83 @@ jobs: - name: Scan block_scout_web for vulnerabilities run: mix sobelow --config working-directory: "apps/block_scout_web" + + cspell: + name: Check spelling + runs-on: ubuntu-latest + needs: build-and-cache + steps: + - uses: actions/checkout@v5 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex + + - name: Mix Deps Cache + uses: actions/cache/restore@v4 + id: deps-cache + with: + path: | + deps + _build + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- + + - name: Restore Explorer NPM Cache + uses: actions/cache@v4 + id: explorer-npm-cache + with: + path: apps/explorer/node_modules + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm-${{ hashFiles('apps/explorer/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm- + + - name: Restore Blockscout Web NPM Cache + uses: actions/cache@v4 + id: blockscoutweb-npm-cache + with: + path: apps/block_scout_web/assets/node_modules + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm-${{ hashFiles('apps/block_scout_web/assets/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-blockscoutweb-npm- + + - name: Run cspell + uses: streetsidesoftware/cspell-action@v6 + with: + use_cspell_files: true + incremental_files_only: false + eslint: name: ESLint - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: build-and-cache steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Restore Explorer NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: explorer-npm-cache with: path: apps/explorer/node_modules @@ -253,7 +418,7 @@ jobs: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm- - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: blockscoutweb-npm-cache with: path: apps/block_scout_web/assets/node_modules @@ -267,30 +432,34 @@ jobs: - run: ./node_modules/.bin/eslint --format=junit --output-file="test/eslint/junit.xml" js/** working-directory: apps/block_scout_web/assets + jest: name: JS Tests - runs-on: ubuntu-18.04 + runs-on: ubuntu-latest needs: build-and-cache steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: blockscoutweb-npm-cache with: path: apps/block_scout_web/assets/node_modules @@ -305,13 +474,46 @@ jobs: - run: ./node_modules/.bin/jest working-directory: apps/block_scout_web/assets - test_parity_mox_ethereum_jsonrpc: - name: EthereumJSONRPC Tests - runs-on: ubuntu-18.04 + test_utils: + name: Utils Tests + runs-on: ubuntu-latest needs: build-and-cache + steps: + - uses: actions/checkout@v5 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex + + - name: Restore Mix Deps Cache + uses: actions/cache/restore@v4 + id: deps-cache + with: + path: | + deps + _build + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- + + - working-directory: apps/utils + run: mix test + + test_nethermind_mox_ethereum_jsonrpc: + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }} + name: EthereumJSONRPC Tests + runs-on: ubuntu-latest + needs: + - build-and-cache + - matrix-builder services: postgres: - image: postgres + image: postgres:17 env: # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database POSTGRES_DB: explorer_test @@ -329,45 +531,54 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - run: ./bin/install_chrome_headless.sh - - name: mix test --exclude no_parity + - name: mix test --exclude no_nethermind run: | cd apps/ethereum_jsonrpc mix compile - mix test --no-start --exclude no_parity + mix test --no-start --exclude no_nethermind env: # match POSTGRES_PASSWORD for postgres image below PGPASSWORD: postgres # match POSTGRES_USER for postgres image below PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.Mox" + ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - test_parity_mox_explorer: + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + BRIDGED_TOKENS_ENABLED: ${{ matrix.bridged-tokens }} + + test_nethermind_mox_explorer: + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }} name: Explorer Tests - runs-on: ubuntu-18.04 - needs: build-and-cache + runs-on: ubuntu-latest + needs: + - build-and-cache + - matrix-builder services: postgres: - image: postgres + image: postgres:17 env: # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database POSTGRES_DB: explorer_test @@ -385,27 +596,28 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Restore Explorer NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: explorer-npm-cache with: path: apps/explorer/node_modules @@ -414,27 +626,36 @@ jobs: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm - run: ./bin/install_chrome_headless.sh - - name: mix test --exclude no_parity + - name: mix test --exclude no_nethermind run: | mix ecto.create --quiet mix ecto.migrate cd apps/explorer mix compile - mix test --no-start --exclude no_parity + mix test --no-start --exclude no_nethermind env: # match POSTGRES_PASSWORD for postgres image below PGPASSWORD: postgres # match POSTGRES_USER for postgres image below PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.Mox" + ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - test_parity_mox_indexer: + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + WETH_TOKEN_TRANSFERS_FILTERING_ENABLED: "true" + BRIDGED_TOKENS_ENABLED: ${{ matrix.bridged-tokens }} + + test_nethermind_mox_indexer: + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }} name: Indexer Tests - runs-on: ubuntu-18.04 - needs: build-and-cache + runs-on: ubuntu-latest + needs: + - build-and-cache + - matrix-builder services: postgres: - image: postgres + image: postgres:17 env: # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database POSTGRES_DB: explorer_test @@ -452,50 +673,63 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - run: ./bin/install_chrome_headless.sh - - name: mix test --exclude no_parity + - name: mix test --exclude no_nethermind run: | mix ecto.create --quiet mix ecto.migrate cd apps/indexer mix compile - mix test --no-start --exclude no_parity + mix test --no-start --exclude no_nethermind env: # match POSTGRES_PASSWORD for postgres image below PGPASSWORD: postgres # match POSTGRES_USER for postgres image below PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.Mox" + ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - - test_parity_mox_block_scout_web: + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + WETH_TOKEN_TRANSFERS_FILTERING_ENABLED: "true" + BRIDGED_TOKENS_ENABLED: ${{ matrix.bridged-tokens }} + + test_nethermind_mox_block_scout_web: + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }} name: Blockscout Web Tests - runs-on: ubuntu-18.04 - needs: build-and-cache + runs-on: ubuntu-latest + needs: + - build-and-cache + - matrix-builder services: + redis-db: + image: "redis:alpine" + ports: + - 6379:6379 + postgres: - image: postgres + image: postgres:17 env: # Match apps/explorer/config/test.exs config :explorer, Explorer.Repo, database POSTGRES_DB: explorer_test @@ -513,28 +747,28 @@ jobs: # Maps tcp port 5432 on service container to the host - 5432:5432 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v5 - uses: erlef/setup-beam@v1 with: otp-version: ${{ env.OTP_VERSION }} elixir-version: ${{ env.ELIXIR_VERSION }} - - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - run: echo 'export PATH=~/.cargo/bin/:$PATH' >> $GITHUB_ENV + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex - name: Mix Deps Cache - uses: actions/cache@v2 + uses: actions/cache/restore@v4 id: deps-cache with: - path: | + path: | deps _build - key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash_11-${{ hashFiles('mix.lock') }} + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} restore-keys: | - ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-" - + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- - name: Restore Explorer NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: explorer-npm-cache with: path: apps/explorer/node_modules @@ -543,7 +777,7 @@ jobs: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-explorer-npm- - name: Restore Blockscout Web NPM Cache - uses: actions/cache@v2 + uses: actions/cache@v4 id: blockscoutweb-npm-cache with: path: apps/block_scout_web/assets/node_modules @@ -557,19 +791,28 @@ jobs: - run: ./bin/install_chrome_headless.sh - - name: mix test --exclude no_parity + - name: mix test --exclude no_nethermind run: | mix ecto.create --quiet mix ecto.migrate cd apps/block_scout_web mix compile - mix test --no-start --exclude no_parity + mix test --no-start --exclude no_nethermind env: # match POSTGRES_PASSWORD for postgres image below PGPASSWORD: postgres # match POSTGRES_USER for postgres image below PGUSER: postgres - ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Parity.Mox" + ETHEREUM_JSONRPC_CASE: "EthereumJSONRPC.Case.Nethermind.Mox" ETHEREUM_JSONRPC_WEB_SOCKET_CASE: "EthereumJSONRPC.WebSocket.Case.Mox" - CHAIN_ID: "77" - ADMIN_PANEL_ENABLED: "true" \ No newline at end of file + CHAIN_ID: "10200" + API_RATE_LIMIT_DISABLED: "true" + API_GRAPHQL_RATE_LIMIT_DISABLED: "true" + ADMIN_PANEL_ENABLED: "true" + ACCOUNT_ENABLED: "true" + ACCOUNT_REDIS_URL: "redis://localhost:6379" + SOURCIFY_INTEGRATION_ENABLED: "true" + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + WETH_TOKEN_TRANSFERS_FILTERING_ENABLED: "true" + BRIDGED_TOKENS_ENABLED: ${{ matrix.bridged-tokens }} + DISABLE_WEBAPP: "false" diff --git a/.github/workflows/generate-swagger.yml b/.github/workflows/generate-swagger.yml new file mode 100644 index 000000000000..02661c1fc277 --- /dev/null +++ b/.github/workflows/generate-swagger.yml @@ -0,0 +1,292 @@ +name: Generate OpenAPI Specs + +on: + push: + branches: + - master + - dev + paths-ignore: + - "CHANGELOG.md" + - "**/README.md" + - "docker/*" + - "docker-compose/*" + workflow_dispatch: + release: + types: [published] + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + RELEASE_VERSION: 11.2.7 + +jobs: + matrix-builder: + name: Build matrix + runs-on: ubuntu-latest + outputs: + matrix: ${{ steps.set-matrix.outputs.matrix }} + steps: + - id: set-matrix + run: | + echo "matrix=$(node -e ' + + // Add/remove CI matrix chain types here + const chainTypes = [ + "default", + "arbitrum", + "arc", + "blackfort", + "eden", + "ethereum", + "filecoin", + "neon", + "optimism", + "optimism-celo", + "rsk", + "scroll", + "shibarium", + "stability", + "suave", + "zetachain", + "zilliqa", + "zksync" + ]; + + const matrix = { "chain-type": ${{ 'chainTypes' }} }; + console.log(JSON.stringify(matrix)); + ')" >> $GITHUB_OUTPUT + + build-and-cache: + name: Build and Cache deps + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex + + - name: "ELIXIR_VERSION.lock" + run: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock + + - name: "OTP_VERSION.lock" + run: echo "${OTP_VERSION}" > OTP_VERSION.lock + + - name: Restore Mix Deps Cache + uses: actions/cache@v4 + id: deps-cache + with: + path: | + deps + _build + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- + + - name: Conditionally build Mix deps cache + if: steps.deps-cache.outputs.cache-hit != 'true' + run: | + mix local.hex --force + mix local.rebar --force + mix deps.get + mix deps.compile --skip-umbrella-children + + generate-swagger: + strategy: + fail-fast: false + matrix: ${{ fromJson(needs.matrix-builder.outputs.matrix) }} + name: Generate Open API spec + runs-on: ubuntu-latest + needs: + - build-and-cache + - matrix-builder + steps: + - uses: actions/checkout@v5 + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex + + - name: Mix Deps Cache + uses: actions/cache/restore@v4 + id: deps-cache + with: + path: | + deps + _build + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- + + - name: mix openapi.spec.yaml + run: | + mix openapi.spec.yaml --spec BlockScoutWeb.Specs.Public openapi.${{ matrix.chain-type }}.yaml --start-app=false + env: + CHAIN_TYPE: ${{ matrix.chain-type != 'default' && matrix.chain-type || '' }} + MUD_INDEXER_ENABLED: false + + - name: Generate MUD-enabled spec for Optimism + if: matrix.chain-type == 'optimism' + run: | + mix openapi.spec.yaml --spec BlockScoutWeb.Specs.Public openapi.mud.yaml --start-app=false + env: + CHAIN_TYPE: optimism + MUD_INDEXER_ENABLED: true + + - name: Upload OpenAPI spec + uses: actions/upload-artifact@v4 + with: + name: openapi-spec-${{ matrix.chain-type }} + path: openapi.${{ matrix.chain-type }}.yaml + retention-days: 1 + + - name: Upload MUD-enabled spec + if: matrix.chain-type == 'optimism' + uses: actions/upload-artifact@v4 + with: + name: openapi-spec-mud + path: openapi.mud.yaml + retention-days: 1 + + push-specs: + needs: + - generate-swagger + - matrix-builder + runs-on: ubuntu-latest + name: Push all OpenAPI specs + steps: + - name: Validate required secrets + run: | + if [ -z "${{ secrets.API_SPECS_PAT }}" ]; then + echo "Error: API_SPECS_PAT secret is not set" + exit 1 + fi + + - name: Checkout specs repository + uses: actions/checkout@v5 + with: + repository: ${{ vars.API_SPECS_REPOSITORY }} + token: ${{ secrets.API_SPECS_PAT }} + path: api-specs + + - name: Download all swagger specs + uses: actions/download-artifact@v5 + with: + pattern: openapi-spec-* + merge-multiple: true + path: temp-specs + + - name: Merge all OpenAPI specs into all-in-one spec + run: | + npm install js-yaml + cat > merge-specs.js << 'SCRIPT_EOF' + const fs = require('fs'); + const path = require('path'); + const yaml = require('js-yaml'); + + const specDir = './temp-specs'; + const outputFile = path.join(specDir, 'openapi.all.yaml'); + + const files = fs.readdirSync(specDir) + .filter(f => f.endsWith('.yaml')) + .sort(); + + let merged = null; + + for (const file of files) { + const content = yaml.load(fs.readFileSync(path.join(specDir, file), 'utf8')); + if (!merged) { + merged = JSON.parse(JSON.stringify(content)); + continue; + } + // Union merge paths (first definition wins for duplicates) + if (content.paths) { + merged.paths = merged.paths || {}; + for (const [p, def] of Object.entries(content.paths)) { + if (!merged.paths[p]) { + merged.paths[p] = def; + } + } + } + // Union merge components (first definition wins for duplicates) + if (content.components) { + merged.components = merged.components || {}; + for (const [section, defs] of Object.entries(content.components)) { + if (!merged.components[section]) { + merged.components[section] = defs; + } else { + for (const [name, def] of Object.entries(defs)) { + if (!merged.components[section][name]) { + merged.components[section][name] = def; + } + } + } + } + } + // Union merge tags (by name) + if (content.tags) { + merged.tags = merged.tags || []; + const existingTagNames = new Set(merged.tags.map(t => t.name)); + for (const tag of content.tags) { + if (!existingTagNames.has(tag.name)) { + merged.tags.push(tag); + existingTagNames.add(tag.name); + } + } + } + } + + fs.writeFileSync(outputFile, yaml.dump(merged, { lineWidth: -1 })); + console.log(`Merged ${files.length} specs into ${outputFile}`); + SCRIPT_EOF + node merge-specs.js + + - name: Create specs directory structure + run: | + VERSION=${{ github.event_name == 'release' && env.RELEASE_VERSION || (github.ref_name == 'dev' && 'dev' || 'master') }} + + for SPEC_FILE in temp-specs/*; do + if [ -f "$SPEC_FILE" ]; then + FILENAME=$(basename "$SPEC_FILE") + + # Handle MUD spec specially + if [ "$FILENAME" = "openapi.mud.yaml" ]; then + mkdir -p "api-specs/blockscout/${VERSION}/mud" + cp "$SPEC_FILE" "api-specs/blockscout/${VERSION}/mud/swagger.yaml" + else + # Extract chain type from filename (openapi.CHAINTYPE.yaml) + CHAIN_TYPE=$(echo "$FILENAME" | sed 's/openapi\.\(.*\)\.yaml/\1/') + mkdir -p "api-specs/blockscout/${VERSION}/${CHAIN_TYPE}" + cp "$SPEC_FILE" "api-specs/blockscout/${VERSION}/${CHAIN_TYPE}/swagger.yaml" + fi + fi + done + + + - name: Commit and push changes + working-directory: api-specs + run: | + git config --local user.email "github-actions[bot]@users.noreply.github.com" + git config --local user.name "github-actions[bot]" + + git add . + + # Only commit if there are changes + if git diff --staged --quiet; then + echo "No changes to commit" + else + git commit -m "[SKIP-GH-PAGES] create OpenAPI specs for Blockscout ${{ github.event_name == 'release' && env.RELEASE_VERSION || github.sha }}" + git push + fi + + - name: Clean up + if: always() + run: | + rm -rf temp-specs + rm -rf api-specs diff --git a/.github/workflows/pr-title-check.yml b/.github/workflows/pr-title-check.yml new file mode 100644 index 000000000000..06362683d3a7 --- /dev/null +++ b/.github/workflows/pr-title-check.yml @@ -0,0 +1,15 @@ +name: PR Conventional Commit Validation + +on: + pull_request: + types: [opened, synchronize, reopened, edited] + +jobs: + validate-pr-title: + runs-on: ubuntu-latest + steps: + - name: PR Conventional Commit Validation + uses: ytanikin/pr-conventional-commits@b72758283dcbee706975950e96bc4bf323a8d8c0 + with: + task_types: '["feat","fix","chore","perf","refactor","docs","doc"]' + add_label: 'false' diff --git a/.github/workflows/pre-release-arbitrum.yml b/.github/workflows/pre-release-arbitrum.yml new file mode 100644 index 000000000000..ae3925928580 --- /dev/null +++ b/.github/workflows/pre-release-arbitrum.yml @@ -0,0 +1,67 @@ +name: Pre-release for Arbitrum + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Arbitrum (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-arbitrum-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=arbitrum + + - name: Build and push Docker image for Arbitrum (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-arbitrum-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=arbitrum diff --git a/.github/workflows/pre-release-celo.yml b/.github/workflows/pre-release-celo.yml new file mode 100644 index 000000000000..34e069b4c8fe --- /dev/null +++ b/.github/workflows/pre-release-celo.yml @@ -0,0 +1,68 @@ +name: Pre-release for CELO + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + API_GRAPHQL_MAX_COMPLEXITY: 10400 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for CELO (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-celo-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism-celo + + - name: Build and push Docker image for CELO (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-celo-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism-celo diff --git a/.github/workflows/pre-release-eden.yml b/.github/workflows/pre-release-eden.yml new file mode 100644 index 000000000000..5bb08e1e587f --- /dev/null +++ b/.github/workflows/pre-release-eden.yml @@ -0,0 +1,67 @@ +name: Pre-release for Eden + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-eden-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=eden + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-eden-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=eden diff --git a/.github/workflows/pre-release-eth.yml b/.github/workflows/pre-release-eth.yml new file mode 100644 index 000000000000..7bc322a63ed3 --- /dev/null +++ b/.github/workflows/pre-release-eth.yml @@ -0,0 +1,67 @@ +name: Pre-release for Ethereum + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Ethereum (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-ethereum-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum + + - name: Build and push Docker image for Ethereum (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-ethereum-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum diff --git a/.github/workflows/pre-release-filecoin.yml b/.github/workflows/pre-release-filecoin.yml new file mode 100644 index 000000000000..3fd0f7da2441 --- /dev/null +++ b/.github/workflows/pre-release-filecoin.yml @@ -0,0 +1,67 @@ +name: Pre-release for Filecoin + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Filecoin (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-filecoin-private:latest, ghcr.io/blockscout/blockscout-filecoin-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=filecoin + + - name: Build and push Docker image for Filecoin (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-filecoin-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=filecoin diff --git a/.github/workflows/pre-release-fuse.yml b/.github/workflows/pre-release-fuse.yml new file mode 100644 index 000000000000..c147575e6c7b --- /dev/null +++ b/.github/workflows/pre-release-fuse.yml @@ -0,0 +1,67 @@ +name: Pre-release for Fuse + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Fuse (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-fuse-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true + + - name: Build and push Docker image for Fuse (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-fuse-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true diff --git a/.github/workflows/pre-release-gnosis.yml b/.github/workflows/pre-release-gnosis.yml new file mode 100644 index 000000000000..5ea8c66333af --- /dev/null +++ b/.github/workflows/pre-release-gnosis.yml @@ -0,0 +1,69 @@ +name: Pre-release for Gnosis Chain + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Gnosis Chain (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-xdai-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true + CHAIN_TYPE=ethereum + + - name: Build and push Docker image for Gnosis Chain (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-xdai-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true + CHAIN_TYPE=ethereum diff --git a/.github/workflows/pre-release-optimism.yml b/.github/workflows/pre-release-optimism.yml new file mode 100644 index 000000000000..a369b6892c55 --- /dev/null +++ b/.github/workflows/pre-release-optimism.yml @@ -0,0 +1,67 @@ +name: Pre-release for Optimism + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Optimism (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-optimism-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism + + - name: Build and push Docker image for Optimism (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-optimism-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism diff --git a/.github/workflows/pre-release-rootstock.yml b/.github/workflows/pre-release-rootstock.yml new file mode 100644 index 000000000000..dc0199f8e0de --- /dev/null +++ b/.github/workflows/pre-release-rootstock.yml @@ -0,0 +1,67 @@ +name: Pre-release for Rootstock + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Rootstock (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-rsk-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=rsk + + - name: Build and push Docker image for Rootstock (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-rsk-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=rsk diff --git a/.github/workflows/pre-release-scroll.yml b/.github/workflows/pre-release-scroll.yml new file mode 100644 index 000000000000..1023db455128 --- /dev/null +++ b/.github/workflows/pre-release-scroll.yml @@ -0,0 +1,67 @@ +name: Pre-release for Scroll + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Scroll (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-scroll-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=scroll + + - name: Build and push Docker image for Scroll (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-scroll-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=scroll diff --git a/.github/workflows/pre-release-zilliqa.yml b/.github/workflows/pre-release-zilliqa.yml new file mode 100644 index 000000000000..3983e8dc1a26 --- /dev/null +++ b/.github/workflows/pre-release-zilliqa.yml @@ -0,0 +1,67 @@ +name: Pre-release for Zilliqa + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zilliqa-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zilliqa + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zilliqa-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zilliqa diff --git a/.github/workflows/pre-release-zksync.yml b/.github/workflows/pre-release-zksync.yml new file mode 100644 index 000000000000..568109ec61be --- /dev/null +++ b/.github/workflows/pre-release-zksync.yml @@ -0,0 +1,67 @@ +name: Pre-release for ZkSync + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for ZkSync (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zksync-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zksync + + - name: Build and push Docker image for ZkSync (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zksync-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zksync diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml new file mode 100644 index 000000000000..409e788bb055 --- /dev/null +++ b/.github/workflows/pre-release.yml @@ -0,0 +1,79 @@ +name: Pre-release + +on: + workflow_dispatch: + inputs: + number: + type: number + description: Number of pre-release alpha iteration + required: true + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build & Push Core Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout-private:master, ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + - name: Build & Push Core Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}-alpha.${{ inputs.number }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} diff --git a/.github/workflows/public-release.yml b/.github/workflows/public-release.yml new file mode 100644 index 000000000000..3c17e6372306 --- /dev/null +++ b/.github/workflows/public-release.yml @@ -0,0 +1,112 @@ +name: Public release publishing + +on: + workflow_dispatch: + inputs: + release_number: + description: 'Release number (e.g., v9.1.0)' + required: true + type: string + +jobs: + copy-bundle: + runs-on: build + permissions: + contents: read + packages: write + + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Set source and target tags + run: | + RELEASE_NUMBER="${{ github.event.inputs.release_number }}" + SOURCE_TAG="${RELEASE_NUMBER}" + TARGET_TAG="${RELEASE_NUMBER}" + echo "SOURCE_TAG=${SOURCE_TAG}" >> $GITHUB_ENV + echo "TARGET_TAG=${TARGET_TAG}" >> $GITHUB_ENV + + - name: Copy chain-specific images from private to public repositories + run: | + RELEASE_NUMBER="${{ github.event.inputs.release_number }}" + + # Array of chain-specific repositories + CHAINS=( + "blockscout" + "blockscout-arbitrum" + "blockscout-celo" + "blockscout-eden" + "blockscout-ethereum" + "blockscout-filecoin" + "blockscout-fuse" + "blockscout-xdai" + "blockscout-optimism" + "blockscout-zkevm" + "blockscout-rsk" + "blockscout-scroll" + "blockscout-zetachain" + "blockscout-zilliqa" + "blockscout-zksync" + ) + + # Copy each chain-specific image + for CHAIN in "${CHAINS[@]}"; do + echo "Copying ${CHAIN}..." + + # Copy with the specific release number tag + docker buildx imagetools create \ + --tag ghcr.io/blockscout/${CHAIN}:${RELEASE_NUMBER} \ + ghcr.io/blockscout/${CHAIN}-private:${RELEASE_NUMBER} + + # Also copy with latest tag + docker buildx imagetools create \ + --tag ghcr.io/blockscout/${CHAIN}:latest \ + ghcr.io/blockscout/${CHAIN}-private:latest + + echo "✅ Completed copying ${CHAIN}" + done + + - name: Verify deployment + run: | + RELEASE_NUMBER="${{ github.event.inputs.release_number }}" + echo "🎉 All bundles successfully copied from private to public repositories" + echo "" + echo "🔗 All repositories copied:" + + CHAINS=( + "blockscout" + "blockscout-arbitrum" + "blockscout-celo" + "blockscout-eden" + "blockscout-ethereum" + "blockscout-filecoin" + "blockscout-fuse" + "blockscout-xdai" + "blockscout-optimism" + "blockscout-zkevm" + "blockscout-rsk" + "blockscout-scroll" + "blockscout-zetachain" + "blockscout-zilliqa" + "blockscout-zksync" + ) + + for CHAIN in "${CHAINS[@]}"; do + echo " ✅ ${CHAIN}-private -> ${CHAIN} (tags: ${RELEASE_NUMBER}, latest)" + done + + echo "" + echo "🔍 Inspecting main repository images:" + docker buildx imagetools inspect ghcr.io/blockscout/blockscout:${TARGET_TAG} + docker buildx imagetools inspect ghcr.io/blockscout/blockscout:latest diff --git a/.github/workflows/publish-api-types-npm-dev.yml b/.github/workflows/publish-api-types-npm-dev.yml new file mode 100644 index 000000000000..d4303c592a1d --- /dev/null +++ b/.github/workflows/publish-api-types-npm-dev.yml @@ -0,0 +1,25 @@ +name: Publish @blockscout/api-types to npm (dev) +# This workflow is used to publish the dev version (before release) of the @blockscout/api-types package to npm. + +on: + workflow_dispatch: + +jobs: + version: + name: Resolve dev package version + runs-on: ubuntu-latest + outputs: + package_version: ${{ steps.set.outputs.package_version }} + steps: + - name: Set version from commit SHA + id: set + run: echo "package_version=v0.0.1-beta.${GITHUB_SHA::7}" >> "$GITHUB_OUTPUT" + + publish: + name: Build and publish + needs: version + uses: ./.github/workflows/publish-api-types-npm.yml + with: + package_version: ${{ needs.version.outputs.package_version }} + secrets: + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish-api-types-npm.yml b/.github/workflows/publish-api-types-npm.yml new file mode 100644 index 000000000000..86f818b20878 --- /dev/null +++ b/.github/workflows/publish-api-types-npm.yml @@ -0,0 +1,149 @@ +name: Publish @blockscout/api-types to npm + +on: + workflow_dispatch: + inputs: + package_version: + description: "Package version (semver or Git tag, e.g. 1.0.0 or v1.0.0-beta.1)" + required: true + type: string + # todo: re-enable once all fixes to OpenApi schemas will be made + # release: + # types: [published] + workflow_call: + inputs: + package_version: + description: "Package version (semver or Git tag, e.g. 1.0.0 or v1.0.0-beta.1)" + required: true + type: string + secrets: + NPM_TOKEN: + required: true + +env: + OTP_VERSION: "27.3.4.6" + ELIXIR_VERSION: "1.19.4" + NODE_VERSION: "22" + +permissions: + id-token: write + contents: read + +jobs: + publish: + name: Build and publish + # Skip GitHub pre-releases; manual dispatch and workflow_call are unaffected. + if: github.event_name != 'release' || github.event.release.prerelease == false + runs-on: ubuntu-latest + permissions: + id-token: write + contents: read + + steps: + - name: Resolve package version and npm dist-tag + env: + EVENT_NAME: ${{ github.event_name }} + RELEASE_TAG: ${{ github.event.release.tag_name }} + INPUT_VERSION: ${{ inputs.package_version }} + run: | + case "$EVENT_NAME" in + release) + raw="$RELEASE_TAG" + ;; + *) + raw="$INPUT_VERSION" + ;; + esac + + version="${raw#[vV]}" + + if [ "$EVENT_NAME" = "release" ] && [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+- ]]; then + echo "Skipping npm publish: release tag '$raw' is not a final version" >&2 + exit 1 + fi + + if ! [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?(\+[0-9A-Za-z.-]+)?$ ]]; then + echo "Invalid semver (optional leading v/V): $raw" >&2 + exit 1 + fi + + if [[ "$version" =~ ^[0-9]+\.[0-9]+\.[0-9]+- ]]; then + dist_tag=beta + else + dist_tag=latest + fi + + echo "NPM_VERSION=$version" >> "$GITHUB_ENV" + echo "NPM_DIST_TAG=$dist_tag" >> "$GITHUB_ENV" + echo "Publishing @blockscout/api-types@$version with dist-tag '$dist_tag' (input: $raw)" + + - uses: actions/checkout@v5 + with: + ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + + - uses: erlef/setup-beam@v1 + with: + otp-version: ${{ env.OTP_VERSION }} + elixir-version: ${{ env.ELIXIR_VERSION }} + hexpm-mirrors: | + https://builds.hex.pm + https://cdn.jsdelivr.net/hex + + - name: ELIXIR_VERSION.lock + run: echo "${ELIXIR_VERSION}" > ELIXIR_VERSION.lock + + - name: OTP_VERSION.lock + run: echo "${OTP_VERSION}" > OTP_VERSION.lock + + - name: Restore Mix deps cache + uses: actions/cache/restore@v4 + id: deps-cache + with: + path: | + deps + _build + key: ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash-${{ hashFiles('mix.lock') }} + restore-keys: | + ${{ runner.os }}-${{ env.ELIXIR_VERSION }}-${{ env.OTP_VERSION }}-${{ env.MIX_ENV }}-deps-mixlockhash- + + - name: Build Mix deps + if: steps.deps-cache.outputs.cache-hit != 'true' + run: | + mix local.hex --force + mix local.rebar --force + mix deps.get + mix deps.compile --skip-umbrella-children + + - uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: npm + cache-dependency-path: types-package/package-lock.json + registry-url: https://registry.npmjs.org + scope: "@blockscout" + + - name: Install npm dependencies + working-directory: types-package + run: npm ci + + - name: Build OpenAPI specs and TypeScript types + working-directory: types-package + run: npm run build + + - name: Typecheck + working-directory: types-package + run: npm run typecheck + + - name: Set package version + working-directory: types-package + run: npm version "$NPM_VERSION" --no-git-tag-version + + - name: Prepare package for publish + working-directory: types-package + run: npm pkg delete private + + - name: Publish to npm + working-directory: types-package + run: npm publish --access public --tag "$NPM_DIST_TAG" + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/publish-docker-image-custom-build.yml b/.github/workflows/publish-docker-image-custom-build.yml new file mode 100644 index 000000000000..1c57a408310a --- /dev/null +++ b/.github/workflows/publish-docker-image-custom-build.yml @@ -0,0 +1,58 @@ +name: Publish Custom Base Docker image (master + some commit(s)) + +on: + workflow_dispatch: + push: + branches: + - custom-build +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}-postrelease-custom-build-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}-postrelease-custom-build-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} diff --git a/.github/workflows/publish-docker-image-every-push.yml b/.github/workflows/publish-docker-image-every-push.yml new file mode 100644 index 000000000000..a8019a3d4df5 --- /dev/null +++ b/.github/workflows/publish-docker-image-every-push.yml @@ -0,0 +1,121 @@ +name: Publish Docker image on every push to master/dev branches + +on: + push: + branches: + - master + - dev + paths-ignore: + - 'CHANGELOG.md' + - '**/README.md' + - 'docker-compose/*' +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + RELEASE_VERSION: 11.2.7 + +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout-private:${{ github.ref_name }}, ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}.commit.${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}.commit.${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + - name: Build and push Docker image for frontend + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + tags: ghcr.io/blockscout/blockscout-private:frontend-main + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + SESSION_COOKIE_DOMAIN=k8s-dev.blockscout.com + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + deploy_e2e: + needs: push_to_registry + runs-on: ubuntu-latest + permissions: write-all + steps: + - name: Get Vault credentials + id: retrieve-vault-secrets + uses: hashicorp/vault-action@v2.4.1 + with: + url: https://vault.k8s.blockscout.com + role: ci-dev + path: github-jwt + method: jwt + tlsSkipVerify: false + exportToken: true + secrets: | + ci/data/dev/github token | WORKFLOW_TRIGGER_TOKEN ; + - name: Trigger deploy + uses: convictional/trigger-workflow-and-wait@v1.6.1 + with: + owner: blockscout + repo: deployment-values + github_token: ${{env.WORKFLOW_TRIGGER_TOKEN}} + workflow_file_name: deploy_blockscout.yaml + ref: main + wait_interval: 30 + client_payload: '{ "instance": "dev", "globalEnv": "e2e"}' diff --git a/.github/workflows/publish-docker-image-for-arbitrum.yml b/.github/workflows/publish-docker-image-for-arbitrum.yml new file mode 100644 index 000000000000..0bb488771eb8 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-arbitrum.yml @@ -0,0 +1,61 @@ +name: Arbitrum Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-arbitrum +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: arbitrum + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=arbitrum + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=arbitrum diff --git a/.github/workflows/publish-docker-image-for-celo.yml b/.github/workflows/publish-docker-image-for-celo.yml new file mode 100644 index 000000000000..9b446db1b43c --- /dev/null +++ b/.github/workflows/publish-docker-image-for-celo.yml @@ -0,0 +1,65 @@ +name: Celo Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-celo +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: celo + CHAIN_TYPE: optimism-celo + API_GRAPHQL_MAX_COMPLEXITY: 10400 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for CELO (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + API_GRAPHQL_MAX_COMPLEXITY=${{ env.API_GRAPHQL_MAX_COMPLEXITY }} + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.CHAIN_TYPE }} + + - name: Build and push Docker image for CELO (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + API_GRAPHQL_MAX_COMPLEXITY=${{ env.API_GRAPHQL_MAX_COMPLEXITY }} + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.CHAIN_TYPE }} diff --git a/.github/workflows/publish-docker-image-for-eden.yml b/.github/workflows/publish-docker-image-for-eden.yml new file mode 100644 index 000000000000..b57ac97332ba --- /dev/null +++ b/.github/workflows/publish-docker-image-for-eden.yml @@ -0,0 +1,61 @@ +name: Eden publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-eden +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: eden + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} diff --git a/.github/workflows/publish-docker-image-for-eth-sepolia.yml b/.github/workflows/publish-docker-image-for-eth-sepolia.yml new file mode 100644 index 000000000000..ea9561ea7177 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-eth-sepolia.yml @@ -0,0 +1,61 @@ +name: ETH Sepolia Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-eth-sepolia +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: eth-sepolia + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:latest, ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum diff --git a/.github/workflows/publish-docker-image-for-eth.yml b/.github/workflows/publish-docker-image-for-eth.yml new file mode 100644 index 000000000000..b29691400b5f --- /dev/null +++ b/.github/workflows/publish-docker-image-for-eth.yml @@ -0,0 +1,61 @@ +name: ETH Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-eth +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: ethereum + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum diff --git a/.github/workflows/publish-docker-image-for-filecoin.yml b/.github/workflows/publish-docker-image-for-filecoin.yml new file mode 100644 index 000000000000..bb84b762e06c --- /dev/null +++ b/.github/workflows/publish-docker-image-for-filecoin.yml @@ -0,0 +1,60 @@ +name: Publish Docker image for specific chain branches + +on: + push: + branches: + - production-filecoin +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: filecoin + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Filecoin (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} + + - name: Build and push Docker image for Filecoin (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} diff --git a/.github/workflows/publish-docker-image-for-fuse.yml b/.github/workflows/publish-docker-image-for-fuse.yml new file mode 100644 index 000000000000..1f044222c6e5 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-fuse.yml @@ -0,0 +1,44 @@ +name: Fuse Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-fuse +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: fuse + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BRIDGED_TOKENS_ENABLED=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} diff --git a/.github/workflows/publish-docker-image-for-gnosis-chain.yml b/.github/workflows/publish-docker-image-for-gnosis-chain.yml new file mode 100644 index 000000000000..0b297caabadc --- /dev/null +++ b/.github/workflows/publish-docker-image-for-gnosis-chain.yml @@ -0,0 +1,63 @@ +name: Gnosis Chain Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-xdai +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: xdai + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BRIDGED_TOKENS_ENABLED=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BRIDGED_TOKENS_ENABLED=true + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum diff --git a/.github/workflows/publish-docker-image-for-optimism-exeperimental.yml b/.github/workflows/publish-docker-image-for-optimism-exeperimental.yml new file mode 100644 index 000000000000..77e1fe3369bb --- /dev/null +++ b/.github/workflows/publish-docker-image-for-optimism-exeperimental.yml @@ -0,0 +1,61 @@ +name: Optimism Publish experimental Docker image + +on: + workflow_dispatch: + push: + branches: + - production-optimism-experimental +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: optimism + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-experimental-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-experimental-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism diff --git a/.github/workflows/publish-docker-image-for-optimism.yml b/.github/workflows/publish-docker-image-for-optimism.yml new file mode 100644 index 000000000000..07acf64c37c6 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-optimism.yml @@ -0,0 +1,61 @@ +name: Optimism Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-optimism +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: optimism + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism diff --git a/.github/workflows/publish-docker-image-for-rootstock.yml b/.github/workflows/publish-docker-image-for-rootstock.yml new file mode 100644 index 000000000000..dfc276fe0695 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-rootstock.yml @@ -0,0 +1,44 @@ +name: Rootstock Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-rsk +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: rsk + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=rsk diff --git a/.github/workflows/publish-docker-image-for-scroll.yml b/.github/workflows/publish-docker-image-for-scroll.yml new file mode 100644 index 000000000000..5e758bcc8035 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-scroll.yml @@ -0,0 +1,61 @@ +name: Scroll Publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-scroll +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: scroll + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=scroll + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=scroll diff --git a/.github/workflows/publish-docker-image-for-zetachain.yml b/.github/workflows/publish-docker-image-for-zetachain.yml new file mode 100644 index 000000000000..bc4cfe7d9d0b --- /dev/null +++ b/.github/workflows/publish-docker-image-for-zetachain.yml @@ -0,0 +1,44 @@ +name: Zetachain publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-zetachain +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: zetachain + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zetachain diff --git a/.github/workflows/publish-docker-image-for-zilliqa.yml b/.github/workflows/publish-docker-image-for-zilliqa.yml new file mode 100644 index 000000000000..097f7e3c6ca1 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-zilliqa.yml @@ -0,0 +1,61 @@ +name: Zilliqa publish Docker image + +on: + workflow_dispatch: + push: + branches: + - production-zilliqa +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: zilliqa + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=${{ env.DOCKER_CHAIN_NAME }} diff --git a/.github/workflows/publish-docker-image-for-zksync.yml b/.github/workflows/publish-docker-image-for-zksync.yml new file mode 100644 index 000000000000..662d1f979496 --- /dev/null +++ b/.github/workflows/publish-docker-image-for-zksync.yml @@ -0,0 +1,60 @@ +name: Zksync publish Docker image + +on: + push: + branches: + - production-zksync +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + DOCKER_CHAIN_NAME: zksync + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zksync + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-${{ env.DOCKER_CHAIN_NAME }}-private:${{ env.RELEASE_VERSION }}-postrelease-${{ env.SHORT_SHA }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }}.+commit.${{ env.SHORT_SHA }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zksync diff --git a/.github/workflows/publish-docker-image-old-ui.yml b/.github/workflows/publish-docker-image-old-ui.yml new file mode 100644 index 000000000000..ebc007c2d3bb --- /dev/null +++ b/.github/workflows/publish-docker-image-old-ui.yml @@ -0,0 +1,51 @@ +name: Publish Docker image with an old UI + +on: + workflow_dispatch: + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +permissions: + contents: read + packages: write + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build & Push Docker image with an old UI (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/oldUI.Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout:${{ env.RELEASE_VERSION }}-with-old-ui-postrelease-${{ env.SHORT_SHA }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} diff --git a/.github/workflows/publish-docker-image.yml b/.github/workflows/publish-docker-image.yml deleted file mode 100644 index f0effec8398e..000000000000 --- a/.github/workflows/publish-docker-image.yml +++ /dev/null @@ -1,40 +0,0 @@ -# This workflow uses actions that are not certified by GitHub. -# They are provided by a third-party and are governed by -# separate terms of service, privacy policy, and support -# documentation. - -name: Publish Docker image - -on: - release: - types: [published] - -jobs: - push_to_registry: - name: Push Docker image to Docker Hub - runs-on: ubuntu-latest - env: - RELEASE_VERSION: 4.1.3 - steps: - - name: Check out the repo - uses: actions/checkout@v2 - - - name: Log in to Docker Hub - uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 - with: - username: ${{ secrets.DOCKER_USERNAME }} - password: ${{ secrets.DOCKER_PASSWORD }} - - - name: Extract metadata (tags, labels) for Docker - id: meta - uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 - with: - images: blockscout/blockscout - - - name: Build and push Docker image - uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc - with: - context: . - file: ./docker/Dockerfile - push: true - tags: blockscout/blockscout:latest, blockscout/blockscout:${{ env.RELEASE_VERSION }} \ No newline at end of file diff --git a/.github/workflows/release-arbitrum.yml b/.github/workflows/release-arbitrum.yml new file mode 100644 index 000000000000..d515aa9d6b9c --- /dev/null +++ b/.github/workflows/release-arbitrum.yml @@ -0,0 +1,64 @@ +name: Release for Arbitrum + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Arbitrum (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-arbitrum-private:latest, ghcr.io/blockscout/blockscout-arbitrum-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=arbitrum + + - name: Build and push Docker image for Arbitrum (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-arbitrum-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=arbitrum diff --git a/.github/workflows/release-celo.yml b/.github/workflows/release-celo.yml new file mode 100644 index 000000000000..972243dabd75 --- /dev/null +++ b/.github/workflows/release-celo.yml @@ -0,0 +1,67 @@ +name: Release for Celo + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + API_GRAPHQL_MAX_COMPLEXITY: 10400 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for CELO (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-celo-private:latest, ghcr.io/blockscout/blockscout-celo-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + API_GRAPHQL_MAX_COMPLEXITY=${{ env.API_GRAPHQL_MAX_COMPLEXITY }} + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism-celo + + - name: Build and push Docker image for CELO (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-celo-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + API_GRAPHQL_MAX_COMPLEXITY=${{ env.API_GRAPHQL_MAX_COMPLEXITY }} + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism-celo diff --git a/.github/workflows/release-default.yml b/.github/workflows/release-default.yml new file mode 100644 index 000000000000..8a4d55c2c864 --- /dev/null +++ b/.github/workflows/release-default.yml @@ -0,0 +1,153 @@ +name: Release + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build & Push Core Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout-private:latest, ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + - name: Build & Push Core Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + + - name: Build & Push Docker image with an old UI (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/oldUI.Dockerfile + push: true + cache-from: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache + cache-to: type=registry,ref=ghcr.io/blockscout/blockscout-private:buildcache,mode=max + tags: ghcr.io/blockscout/blockscout-private:${{ env.RELEASE_VERSION }}-with-old-ui + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DECODE_NOT_A_CONTRACT_CALLS=false + MIXPANEL_URL= + MIXPANEL_TOKEN= + AMPLITUDE_URL= + AMPLITUDE_API_KEY= + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + + # - name: Send release announcement to Slack workflow + # id: slack + # uses: slackapi/slack-github-action@v1.24.0 + # with: + # payload: | + # { + # "release-version": "${{ env.RELEASE_VERSION }}", + # "release-link": "https://github.com/blockscout/blockscout/releases/tag/v${{ env.RELEASE_VERSION }}" + # } + # env: + # SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} + + # merge-master-after-release: + # name: Merge 'master' to specific branch after release + # runs-on: ubuntu-latest + # env: + # BRANCHES: | + # production-core + # production-sokol + # production-eth-experimental + # production-eth-goerli + # production-lukso + # production-xdai + # production-polygon-supernets + # production-rsk + # production-immutable + # steps: + # - uses: actions/checkout@v5 + # - name: Set Git config + # run: | + # git config --local user.email "actions@github.com" + # git config --local user.name "Github Actions" + # - name: Merge master back after release + # run: | + # git fetch --unshallow + # touch errors.txt + # for branch in $BRANCHES; + # do + # git reset --merge + # git checkout master + # git fetch origin + # echo $branch + # git ls-remote --exit-code --heads origin $branch || { echo $branch >> errors.txt; continue; } + # echo "Merge 'master' to $branch" + # git checkout $branch + # git pull || { echo $branch >> errors.txt; continue; } + # git merge --no-ff master -m "Auto-merge master back to $branch" || { echo $branch >> errors.txt; continue; } + # git push || { echo $branch >> errors.txt; continue; } + # git checkout master; + # done + # [ -s errors.txt ] && echo "There are problems with merging 'master' to branches:" || echo "Errors file is empty" + # cat errors.txt + # [ ! -s errors.txt ] diff --git a/.github/workflows/release-eden.yml b/.github/workflows/release-eden.yml new file mode 100644 index 000000000000..dd18b2c1d5d1 --- /dev/null +++ b/.github/workflows/release-eden.yml @@ -0,0 +1,64 @@ +name: Release for Eden + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-eden-private:latest, ghcr.io/blockscout/blockscout-eden-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=eden + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-eden-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=eden diff --git a/.github/workflows/release-eth.yml b/.github/workflows/release-eth.yml new file mode 100644 index 000000000000..a86060de68b7 --- /dev/null +++ b/.github/workflows/release-eth.yml @@ -0,0 +1,64 @@ +name: Release for Ethereum + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Ethereum (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-ethereum-private:latest, ghcr.io/blockscout/blockscout-ethereum-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum + + - name: Build and push Docker image for Ethereum (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-ethereum-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=ethereum diff --git a/.github/workflows/release-filecoin.yml b/.github/workflows/release-filecoin.yml new file mode 100644 index 000000000000..8bc6ddfa8038 --- /dev/null +++ b/.github/workflows/release-filecoin.yml @@ -0,0 +1,64 @@ +name: Release for Filecoin + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Filecoin (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-filecoin-private:latest, ghcr.io/blockscout/blockscout-filecoin-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=filecoin + + - name: Build and push Docker image for Filecoin (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-filecoin-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=filecoin diff --git a/.github/workflows/release-fuse.yml b/.github/workflows/release-fuse.yml new file mode 100644 index 000000000000..cf2b09ca064d --- /dev/null +++ b/.github/workflows/release-fuse.yml @@ -0,0 +1,64 @@ +name: Release for Fuse + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Fuse (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-fuse-private:latest, ghcr.io/blockscout/blockscout-fuse-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true + + - name: Build and push Docker image for Fuse (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-fuse-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true diff --git a/.github/workflows/release-gnosis.yml b/.github/workflows/release-gnosis.yml new file mode 100644 index 000000000000..6a724e83c7e1 --- /dev/null +++ b/.github/workflows/release-gnosis.yml @@ -0,0 +1,66 @@ +name: Release for Gnosis Chain + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Gnosis chain (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-xdai-private:latest, ghcr.io/blockscout/blockscout-xdai-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true + CHAIN_TYPE=ethereum + + - name: Build and push Docker image for Gnosis chain (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-xdai-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + BRIDGED_TOKENS_ENABLED=true + CHAIN_TYPE=ethereum diff --git a/.github/workflows/release-optimism.yml b/.github/workflows/release-optimism.yml new file mode 100644 index 000000000000..5698ed3acdb7 --- /dev/null +++ b/.github/workflows/release-optimism.yml @@ -0,0 +1,64 @@ +name: Release for Optimism + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Optimism (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-optimism-private:latest, ghcr.io/blockscout/blockscout-optimism-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism + + - name: Build and push Docker image for Optimism (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-optimism-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=optimism diff --git a/.github/workflows/release-rootstock.yml b/.github/workflows/release-rootstock.yml new file mode 100644 index 000000000000..0da07d47a205 --- /dev/null +++ b/.github/workflows/release-rootstock.yml @@ -0,0 +1,64 @@ +name: Release for Rootstock + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Rootstock (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-rsk-private:latest, ghcr.io/blockscout/blockscout-rsk-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=rsk + + - name: Build and push Docker image for Rootstock (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-rsk-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=rsk diff --git a/.github/workflows/release-scroll.yml b/.github/workflows/release-scroll.yml new file mode 100644 index 000000000000..fd77fa5fc3ba --- /dev/null +++ b/.github/workflows/release-scroll.yml @@ -0,0 +1,64 @@ +name: Release for Scroll + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Scroll (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-scroll-private:latest, ghcr.io/blockscout/blockscout-scroll-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=scroll + + - name: Build and push Docker image for Scroll (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-scroll-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=scroll diff --git a/.github/workflows/release-zetachain.yml b/.github/workflows/release-zetachain.yml new file mode 100644 index 000000000000..5e327852df48 --- /dev/null +++ b/.github/workflows/release-zetachain.yml @@ -0,0 +1,64 @@ +name: Release for Zetachain + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for Zetachain (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zetachain-private:latest, ghcr.io/blockscout/blockscout-zetachain-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zetachain + + - name: Build and push Docker image for Zetachain (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zetachain-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zetachain diff --git a/.github/workflows/release-zilliqa.yml b/.github/workflows/release-zilliqa.yml new file mode 100644 index 000000000000..29804321a110 --- /dev/null +++ b/.github/workflows/release-zilliqa.yml @@ -0,0 +1,64 @@ +name: Release for Zilliqa + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zilliqa-private:latest, ghcr.io/blockscout/blockscout-zilliqa-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zilliqa + + - name: Build and push Docker image (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zilliqa-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zilliqa diff --git a/.github/workflows/release-zksync.yml b/.github/workflows/release-zksync.yml new file mode 100644 index 000000000000..b97c860dca51 --- /dev/null +++ b/.github/workflows/release-zksync.yml @@ -0,0 +1,64 @@ +name: Release for ZkSync + +on: + workflow_dispatch: + release: + types: [published] + +permissions: + contents: read + packages: write + +env: + OTP_VERSION: '27.3.4.6' + ELIXIR_VERSION: '1.19.4' + +jobs: + push_to_registry: + name: Push Docker image to GitHub Container Registry + runs-on: build + env: + RELEASE_VERSION: 11.2.7 + steps: + - uses: actions/checkout@v5 + - name: Setup repo + uses: ./.github/actions/setup-repo + id: setup + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + docker-remote-multi-platform: true + docker-arm-host: ${{ secrets.ARM_RUNNER_HOSTNAME }} + docker-arm-host-key: ${{ secrets.ARM_RUNNER_KEY }} + + - name: Build and push Docker image for ZkSync (indexer + API) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zksync-private:latest, ghcr.io/blockscout/blockscout-zksync-private:${{ env.RELEASE_VERSION }} + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zksync + + - name: Build and push Docker image for ZkSync (indexer) + uses: docker/build-push-action@v6 + with: + context: . + file: ./docker/Dockerfile + push: true + tags: ghcr.io/blockscout/blockscout-zksync-private:${{ env.RELEASE_VERSION }}-indexer + labels: ${{ steps.setup.outputs.docker-labels }} + platforms: | + linux/amd64 + linux/arm64/v8 + build-args: | + DISABLE_API=true + BLOCKSCOUT_VERSION=v${{ env.RELEASE_VERSION }} + RELEASE_VERSION=${{ env.RELEASE_VERSION }} + CHAIN_TYPE=zksync diff --git a/.gitignore b/.gitignore index 480f7002b984..d4ba21b88b12 100644 --- a/.gitignore +++ b/.gitignore @@ -9,8 +9,12 @@ /*.ez /logs +# mix dialyzer artifacts +/priv/plts + # Generated on crash by the VM erl_crash.dump +dump.rdb # Generated on crash by NPM npm-debug.log @@ -37,11 +41,40 @@ screenshots/ # Sobelow .sobelow -# osx +# osx .DS_Store +dump.rdb # mix phx.gen.cert self-signed certs for dev /apps/block_scout_web/priv/cert -/docker-compose/postgres-data +/docker-compose/services/blockscout-db-data +/docker-compose/services/stats-db-data +/docker-compose/services/redis-data +/docker-compose/services/logs /docker-compose/tmp + +.idea/ +*.iml + +.vscode +.cursorignore +.cursorrules +.elixir_ls +.claude/settings.local.json + +**.dec** + +*.env.example +*.env.local +*.env.staging +.devcontainer/.blockscout_config* + +# dets tables +queue_storage +tasks_in_progress +/dets + +/temp + +openapi.yaml diff --git a/.pairs b/.pairs deleted file mode 100644 index e40bd6ebc940..000000000000 --- a/.pairs +++ /dev/null @@ -1,13 +0,0 @@ -pairs: - cj: CJ Bryan; cj - dr: Doc Ritezel; doc - mo: Matt Olenick; matto - db: Derek Barnes; dgb - rdwb: Desmond Bowe; des - -email: - prefix: pair - domain: ministryofvelocity.com - no_solo_prefix: true - -global: true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 000000000000..505db0421db5 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,5 @@ +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.17.0 + hooks: + - id: gitleaks \ No newline at end of file diff --git a/.tool-versions b/.tool-versions index 5c22166c4061..45ce6d515c65 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1,3 +1,3 @@ -elixir 1.13.4-otp-24 -erlang 24.3.3 -nodejs 16.14.2 +elixir 1.19.4-otp-27 +erlang 27.3.4.6 +nodejs 20.17.0 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000000..85f793c624ac --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,65 @@ +# Agent Guidelines for Blockscout + +## Separate API / Indexer Mode Architecture + +Blockscout supports running as a single combined application or as separate API and indexer instances via the `APPLICATION_MODE` environment variable. + +### Mode Configuration + +`APPLICATION_MODE` environment variable (defined in `config/config_helper.exs`): +- `all` (default) — both API and indexer run together +- `api` — API-only instance, no indexing +- `indexer` — indexer-only instance, no API serving + +The current mode is accessible via `Explorer.mode()` (defined in `apps/explorer/lib/explorer.ex`), which returns `:all`, `:api`, `:indexer`, or `:media_worker`. + +`:media_worker` is a special standalone mode for NFT media processing. It is not set via `APPLICATION_MODE` — it activates when `nft_media_handler[:standalone_media_worker?]` is true, overriding the configured mode. In this mode, `Explorer.Application` starts only libcluster — no base_children or configurable_children. The process mode filtering rules below do not apply to `:media_worker`. + +Related environment variables: +- `DISABLE_INDEXER` — forces indexer off (auto-set when `APPLICATION_MODE=api`) +- `DISABLE_API` — forces API off (compile-time, controls `BlockScoutWeb.Endpoint`) + +### Rules for Assigning Processes to Modes + +When adding or modifying processes started by `Explorer.Application`, `Indexer.Application`, or `BlockScoutWeb.Application`, follow these rules: + +**Start in `:indexer` mode only:** +- Active periodic updaters — GenServers that periodically query the DB and write results to `last_fetched_counters` table (e.g., `ContractsCount`, `NewPendingTransactionsCount`, `Transactions24hCount`). The API side reads directly from the DB table without needing a local process. +- Data migrators (`Explorer.Migrator.*`) — one-time or ongoing data transformations. +- Catalogers and tag importers (`AddressTag.Cataloger`, `CertifiedSmartContractCataloger`). +- Block gap scanning (`MinMissingBlockNumber`). +- Indexer-specific caches that are written and read by indexer only (`LatestL1BlockNumber`). + +**Start in `:api` mode only:** +- Passive on-demand ETS/in-memory caches — GenServers that manage an ETS table and populate it on API request (e.g., `AddressTransactionsCount`, `TokenHoldersCount`, `BlockBurntFeeCount`, `AverageBlockTime`). ETS is local to the process, so these must run on the instance serving requests. +- On-demand fetchers triggered by API requests (`CheckBytecodeMatchingOnDemand`, `FetchValidatorInfoOnDemand`, `LookUpSmartContractSourcesOnDemand`). +- API access control (`AddressesBlacklist`). +- Contract verification tooling (`SolcDownloader`, `VyperDownloader`). +- Read-only DB replicas (`Explorer.Repo.Replica1`). +- API-only caches (`OptimismFinalizationPeriod`, `CeloEpochs`, `Rootstock.LockedBTCCount`). + +**Start in both modes (`:all`, `:api`, `:indexer`):** +- Core infrastructure: main `Explorer.Repo`, `Explorer.Vault`, `Registry.ChainEvents`, `Redix`. +- Event system: `Explorer.Chain.Events.Listener` (mode-controlled via its own `:enabled` config). +- Cluster discovery (`libcluster`) — needed for node communication in separate mode. + +### Helper Functions in Explorer.Application + +- `configure(process)` — starts if `Application.get_env(:explorer, process)[:enabled] == true`. No mode check. +- `configure_mode_dependent_process(process, mode)` — starts if `:enabled` is true AND `Explorer.mode()` matches. Use for processes that have `:enabled` config in `runtime.exs`. +- `only_in_mode(process, mode)` — starts if `Explorer.mode()` matches. No `:enabled` check. Use for processes without `:enabled` config (e.g., repos, downloaders, unconditional entries). +- `configure_chain_type_dependent_process(process, chain_type)` — starts if chain type matches. Can be piped with mode filters. + +Piping pattern for combined restrictions: +```elixir +SomeProcess +|> configure_mode_dependent_process(:indexer) +|> configure_chain_type_dependent_process(:optimism) +``` + +### Cache Pattern Reference + +How to distinguish active updaters from passive caches when deciding the mode: +- **Active periodic updater**: has `schedule_next_consolidation()`, `handle_info(:consolidate)`, writes to `last_fetched_counters` via `LastFetchedCounter.upsert()` -> `:indexer` +- **Passive on-demand ETS cache**: has `fetch()` with cache expiry check, stores in ETS via `Helper.put_into_ets_cache()`, may update model columns -> `:api` +- **MapCache (ConCache)**: uses `use Explorer.Chain.MapCache`, implements `handle_fallback` -> `:api` diff --git a/CHANGELOG.md b/CHANGELOG.md index c4de62255400..f3d2817e91d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,4694 @@ -## Current +# Changelog + +## 11.2.7 + +### 🚀 Features + +- Add /api/v2/transactions/{hash}/preview endpoint ([#14638](https://github.com/blockscout/blockscout/issues/14638), [#14703](https://github.com/blockscout/blockscout/issues/14703), [#14704](https://github.com/blockscout/blockscout/issues/14704)) + +### 🐛 Bug Fixes + +- Fix state changes for sponsored transactions ([#14702](https://github.com/blockscout/blockscout/issues/14702)) + +### ⚡ Performance + +- Reduce query count and payload in transaction API endpoint ([#14705](https://github.com/blockscout/blockscout/issues/14705)) +- Cache empty implementations of verified contracts longer ([#14696](https://github.com/blockscout/blockscout/issues/14696)) +- Fetch address existence checks in a single query ([#14694](https://github.com/blockscout/blockscout/issues/14694)) +- Reuse HTTP connections and parallelize microservice preloads ([#14689](https://github.com/blockscout/blockscout/issues/14689), [#14707](https://github.com/blockscout/blockscout/issues/14707)) +- Fix transform addresses tests for zksync ([#14717](https://github.com/blockscout/blockscout/pull/14717)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `CONTRACT_PROXY_EMPTY_IMPLEMENTATION_DATA_CACHE_TTL` | Empty probe results ("not a proxy") of smart-contracts verified on the address itself are refreshed with a dedicated, much longer TTL. Unverified contracts, bytecode twins, and real proxies keep the existing TTL behavior. [Time format](/setup/env-variables/backend-env-variables#time-format). Implemented in [#14689](https://github.com/blockscout/blockscout/pull/14689). | Version: v11.2.7+
Default: `1d`
Applications: API | +| `MICROSERVICE_HTTP_POOL_SIZE` | Total size of the keep-alive connection pools used by `Explorer.MicroserviceInterfaces.HttpClient` for BENS and Metadata requests. This total is split across multiple pools controlled by `MICROSERVICE_HTTP_POOL_COUNT`. Each individual pool size is calculated as `MICROSERVICE_HTTP_POOL_SIZE / MICROSERVICE_HTTP_POOL_COUNT`. Two logical pools are used: `:microservices` for short requests on the critical path and `:microservices_proxy` for requests proxied to a microservice on behalf of an API caller, so a handful of long-running proxied requests can no longer starve the preloads. Both pools are supervised from `Explorer.Application`. Implemented in [#14689](https://github.com/blockscout/blockscout/pull/14689) | Version: v11.2.7+
Default: `1000`
Applications: API | +| `MICROSERVICE_HTTP_POOL_COUNT` | Number of individual connection pools to split `MICROSERVICE_HTTP_POOL_SIZE` across. Pool splitting allows traffic to spread across multiple processes, reducing contention. Each pool size is calculated as `MICROSERVICE_HTTP_POOL_SIZE / MICROSERVICE_HTTP_POOL_COUNT`. Implemented in [#14707](https://github.com/blockscout/blockscout/pull/14707) | Version: v11.2.7+
Default: `4`
Applications: API, Indexer | + + +## 11.2.6 + +### 🐛 Bug Fixes + +- Fix current token balances fetcher result ([#14677](https://github.com/blockscout/blockscout/issues/14677)) + + +## 11.2.5 + +### 🚀 Features + +- Add average_block_time Prometheus metric ([#14673](https://github.com/blockscout/blockscout/issues/14673)) +- Add json_rpc_calls_count metric for per-method request counts ([#14668](https://github.com/blockscout/blockscout/issues/14668)) +- Add env to disable OnDemand.TokenBalance fetcher ([#14666](https://github.com/blockscout/blockscout/issues/14666)) +- Track eth_call requests by method id in L1/L2 metrics ([#14665](https://github.com/blockscout/blockscout/issues/14665)) +- Track L1 JSON RPC requests from rollups in separate metrics ([#14663](https://github.com/blockscout/blockscout/issues/14663)) + +### 🐛 Bug Fixes + +- Handle Solidity function type in decoded ABI values ([#14672](https://github.com/blockscout/blockscout/issues/14672)) +- Prevent Memory.Monitor crash on restarting OnDemand fetchers ([#14670](https://github.com/blockscout/blockscout/issues/14670)) +- Ignore traces of duplicated transactions ([#14669](https://github.com/blockscout/blockscout/issues/14669)) + +### ⚙️ Miscellaneous Tasks + +- Bump ex_abi lib version ([#14671](https://github.com/blockscout/blockscout/issues/14671)) + + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `INDEXER_DISABLE_TOKEN_BALANCE_ON_DEMAND_FETCHER` | If `true`, `Indexer.Fetcher.OnDemand.TokenBalance` fetcher is disabled at runtime. | Version: v11.2.5\+
Default: `false`
Applications: Indexer | + + +## 11.2.4 + +### 🚀 Features + +- Add eden chain_type with sponsored transaction support ([#14643](https://github.com/blockscout/blockscout/issues/14643)) + +### 🐛 Bug Fixes + +- Enqueue transactions and addresses to multichain queue on block full refetch ([#14652](https://github.com/blockscout/blockscout/issues/14652)) +- Fix OnDemand.TokenBalance import matching ([#14649](https://github.com/blockscout/blockscout/issues/14649)) +- Let INDEXER_OPTIMISM_L1_BATCH_INBOX/SUBMITTER override SystemConfig ([#14645](https://github.com/blockscout/blockscout/issues/14645)) +- Sort data before inserting to export queues ([#14642](https://github.com/blockscout/blockscout/issues/14642)) +- Add missing action_fallback to SolidityScanController ([#14635](https://github.com/blockscout/blockscout/issues/14635)) +- Fix InternalTransaction fetcher test ([#14634](https://github.com/blockscout/blockscout/issues/14634)) +- Handle not-loaded gas_token associations in Celo transaction view ([#14633](https://github.com/blockscout/blockscout/issues/14633)) + +### ⚙️ Miscellaneous Tasks + +- Optimize fetch_coin_balance query ([#14648](https://github.com/blockscout/blockscout/issues/14648)) +- Return proper status codes and string-typed block numbers in b… ([#14646](https://github.com/blockscout/blockscout/issues/14646)) +- Optimize transactions event notifying ([#14637](https://github.com/blockscout/blockscout/issues/14637)) +- Add deposits and withdrawals health metrics for rollups and ETH ([#14632](https://github.com/blockscout/blockscout/issues/14632)) +- Optimize realtime events processing ([#14625](https://github.com/blockscout/blockscout/issues/14625)) +- Add refetch_needed_blocks_count indexer metric ([#14630](https://github.com/blockscout/blockscout/issues/14630)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `HEALTH_MONITOR_DEPOSITS_PERIOD` | New deposits indexed max delay in /health API endpoint. [Time format](/setup/env-variables/backend-env-variables#time-format). Implemented in [#14632](https://github.com/blockscout/blockscout/pull/14632). | Version: v11.2.4\+
Default: `4h`
Applications: API, Indexer | +| `HEALTH_MONITOR_WITHDRAWALS_PERIOD` | New withdrawals indexed max delay in /health API endpoint. [Time format](/setup/env-variables/backend-env-variables#time-format). Implemented in [#14632](https://github.com/blockscout/blockscout/pull/14632). | Version: v11.2.4\+
Default: `4h`
Applications: API, Indexer | +| `DB_EVENTS_LISTENER_BATCH_SIZE` | Max events in one batch to be processed by DB events listener. Implemented in [#14625](https://github.com/blockscout/blockscout/pull/14625). | Version: v11.2.4\+
Default: `100`
Applications: API | +| `REALTIME_EVENT_HANDLERS_BATCH_SIZE` | Max events in one batch to be processed by each realtime event handler. Implemented in [#14625](https://github.com/blockscout/blockscout/pull/14625). | Version: v11.2.4\+
Default: `100`
Applications: API | + + +## 11.2.3 + +### 🚀 Features + +- Make ReplacedTransaction fetcher batch/concurrency configurable and auto-disable it when pending transactions fetcher is off ([#14576](https://github.com/blockscout/blockscout/issues/14576)) +- Report per-process memory in memory_consumed metric ([#14572](https://github.com/blockscout/blockscout/issues/14572)) + +### 🐛 Bug Fixes + +- Disable ETH bytecode DB sources fetching for minimal proxies ([#14622](https://github.com/blockscout/blockscout/issues/14622)) +- Reconcile stuck pending smart_contract_verification_statuses ([#14616](https://github.com/blockscout/blockscout/issues/14616)) +- Eliminate n+1 on historic exchange rate fetching ([#14615](https://github.com/blockscout/blockscout/issues/14615)) +- Prevent stuck pending_block_operations from zero-value internal transactions ([#14613](https://github.com/blockscout/blockscout/issues/14613)) +- Fix 422 in /api/v2/blocks/:block_number/countdown ([#14612](https://github.com/blockscout/blockscout/issues/14612)) +- Extend exception timeout definition ([#14610](https://github.com/blockscout/blockscout/issues/14610)) +- Prevent decoded_input_data crash on partial to_address map ([#14608](https://github.com/blockscout/blockscout/issues/14608)) +- Fix tuple json encoding error ([#14606](https://github.com/blockscout/blockscout/issues/14606)) +- Inherit timeout for update_token_instances_owner ([#14599](https://github.com/blockscout/blockscout/issues/14599)) +- Add missing preload_contract_creation_internal_transaction condition ([#14604](https://github.com/blockscout/blockscout/issues/14604)) +- Eliminate mostly Logger.configure; Make debug logging on failed tx decoding ([#14601](https://github.com/blockscout/blockscout/issues/14601)) +- Handle incorrect number of top-level calls ([#14600](https://github.com/blockscout/blockscout/issues/14600)) +- Re-run handle_partially_imported_blocks on error ([#14597](https://github.com/blockscout/blockscout/issues/14597)) +- Apply ZRC-2 token_type condition only for zilliqa ([#14585](https://github.com/blockscout/blockscout/issues/14585)) +- Use struct field access for token balance broadcast filter ([#14568](https://github.com/blockscout/blockscout/issues/14568)) +- Adapt uncataloged_token_transfer_block_numbers for arc ([#14564](https://github.com/blockscout/blockscout/issues/14564)) + +### 📚 Documentation + +- Update CONTRIBUTING.md: target PRs at dev branch ([#14549](https://github.com/blockscout/blockscout/issues/14549)) + +### ⚡ Performance + +- Optimize transaction to internal transaction preload ([#14596](https://github.com/blockscout/blockscout/issues/14596)) +- Use equality and UNION ALL instead of = ANY for topic filters in Etherscan getLogs ([#14595](https://github.com/blockscout/blockscout/issues/14595)) +- Push token balance staleness filter into SQL and add supporting index ([#14592](https://github.com/blockscout/blockscout/issues/14592)) +- Optimize topic-only getLogs ordering and add supporting logs index ([#14593](https://github.com/blockscout/blockscout/issues/14593)) +- Order getLogs by log.block_number to enable early LIMIT ([#14588](https://github.com/blockscout/blockscout/issues/14588)) + +### ⚙️ Miscellaneous Tasks + +- Add api-v2-temp-token-ttl ([#14620](https://github.com/blockscout/blockscout/issues/14620)) +- Demote some logs to debug ([#14611](https://github.com/blockscout/blockscout/issues/14611)) +- Make async logger call on API response ([#14609](https://github.com/blockscout/blockscout/issues/14609)) +- Hibernate BufferedTask on empty queue ([#14607](https://github.com/blockscout/blockscout/issues/14607)) +- Increase logger params ([#14603](https://github.com/blockscout/blockscout/issues/14603)) +- Use Repo.replica as a default repo for transaction preload ([#14591](https://github.com/blockscout/blockscout/issues/14591)) +- Differentiate blocks count event by type ([#14573](https://github.com/blockscout/blockscout/issues/14573)) +- Add availability to broadcast blocks count instead of full block ([#14571](https://github.com/blockscout/blockscout/issues/14571)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `INDEXER_REPLACED_TRANSACTIONS_BATCH_SIZE` | Batch size for replaced transactions fetcher. Implemented in [#14576](https://github.com/blockscout/blockscout/pull/14576). | Version: v11.2.3\+
Default: `10`
Applications: Indexer | +| `INDEXER_REPLACED_TRANSACTIONS_CONCURRENCY` | Concurrency for replaced transactions fetcher. Implemented in [#14576](https://github.com/blockscout/blockscout/pull/14576). | Version: v11.2.3\+
Default: `4`
Applications: Indexer | +| `BLOCK_BROADCAST_TYPE` | Type of data sent in new block socket events. May be `block` for full block data or `count` for new blocks count. Implemented in [#14571](https://github.com/blockscout/blockscout/pull/14571). | Version: v11.2.3\+
Default: `block`
Applications: API | +| `INDEXER_HANDLE_PARTIALLY_IMPORTED_BLOCK_INTERVAL` | Interval between retrying to set `refetch_needed=true` for blocks whose import failed on some stage in cases when setting `refetch_needed` fails itself. Implemented in [#14597](https://github.com/blockscout/blockscout/pull/14597). | Version: v11.2.3\+
Default: `1s`
Applications: Indexer | + + +## 11.2.2 + +### 🚀 Features + +- Add realtime ERC-20 token balance and block indexing delay metrics ([#14531](https://github.com/blockscout/blockscout/issues/14531)) + +### 🐛 Bug Fixes + +- Fix import result merging for chunked data ([#14528](https://github.com/blockscout/blockscout/issues/14528)) +- Add missing async importers for token balances and instances ([#14534](https://github.com/blockscout/blockscout/pull/14534)) +- Log error instead of silent empty map on CBOR decode failure ([#14510](https://github.com/blockscout/blockscout/issues/14510)) +- Log warning when bytecode metadata hex parsing fails ([#14511](https://github.com/blockscout/blockscout/issues/14511)) + + +## 11.2.1 + +### 🐛 Bug Fixes + +- Don't call InternalTransaction.async_fetch from ContractCreator ([#14482](https://github.com/blockscout/blockscout/issues/14482)) + + +## 11.2.0 + +### 🚀 Features + +- Support for EIP-7708 on arc ([#14336](https://github.com/blockscout/blockscout/pull/14336)) +- Preload only listened entities before broadcast ([#14430](https://github.com/blockscout/blockscout/issues/14430)) +- Add hot smart contracts caching ([#14320](https://github.com/blockscout/blockscout/issues/14320)) +- Add MinimalProxy detection for mid-bytecode EIP-1167-like pattern ([#14426](https://github.com/blockscout/blockscout/issues/14426)) +- Mark instance unhealthy when cache block lags DB ([#14449](https://github.com/blockscout/blockscout/pull/14449)) + +### 🐛 Bug Fixes + +- Don't start health monitor in tests ([#14481](https://github.com/blockscout/blockscout/pull/14481)) +- Improve BlockNumber cache ([#14453](https://github.com/blockscout/blockscout/pull/14453)) +- Fix revert reason for nethermind ([#14442](https://github.com/blockscout/blockscout/pull/14442)) +- Fix token import on Celo ([#14435](https://github.com/blockscout/blockscout/issues/14435)) +- Scope missing_current_token_balances_count indexer metric to configured block ranges ([#14423](https://github.com/blockscout/blockscout/issues/14423)) +- Restrict minimal proxy detection to bytecode ≤ 100 bytes ([#14427](https://github.com/blockscout/blockscout/issues/14427)) +- Add required fields to SmartContract schema ([#14437](https://github.com/blockscout/blockscout/issues/14437)) +- Fix traceable_blocks_dynamic_query ([#14436](https://github.com/blockscout/blockscout/issues/14436)) + +### ⚙️ Miscellaneous Tasks + +- Optimize deriving current token balances ([#14450](https://github.com/blockscout/blockscout/pull/14450), [#14479](https://github.com/blockscout/blockscout/pull/14479)) +- Limit max node requests in one batch ([#14319](https://github.com/blockscout/blockscout/issues/14319)) +- Log block fetch errors in catchup fetcher ([#14318](https://github.com/blockscout/blockscout/issues/14318)) +- Reset skip metadata flag for NFTs ([#14337](https://github.com/blockscout/blockscout/issues/14337)) +- Enhance missing current token balances metric ([#14438](https://github.com/blockscout/blockscout/issues/14438)) +- Perceive "out of gas" error as contract failure ([#14417](https://github.com/blockscout/blockscout/issues/14417)) +- Add PG statement_timeout for import transactions ([#14414](https://github.com/blockscout/blockscout/issues/14414)) +- Comment out direct Sourcify tests ([#8168](https://github.com/blockscout/blockscout/issues/8168)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `ETHEREUM_JSONRPC_HTTP_BATCH_SIZE` | Max http requests count in one batch. Implemented in [#14319](https://github.com/blockscout/blockscout/pull/14319). | Version: v11.2.0\+
Default: `500`
Applications: API, Indexer | +| `CACHE_HOT_SMART_CONTRACTS_5M_PERIOD` | TTL for ConCache entries serving `GET /api/v2/stats/hot-smart-contracts` with `scale=5m`. Controls how long paginated rankings over the last 5 minutes of contract activity are reused before recomputing from the database. [Time format](/setup/env-variables/backend-env-variables#time-format). Shorter TTL = fresher data, more DB load. Longer TTL = less load, staler rankings. | Version: v11.2.0\+
Default: `30s`
Applications: API | +| `CACHE_HOT_SMART_CONTRACTS_1H_PERIOD` | TTL for ConCache entries serving `GET /api/v2/stats/hot-smart-contracts` with `scale=1h`. Controls how long paginated rankings over the last 1 hour of contract activity are reused before recomputing from the database. [Time format](/setup/env-variables/backend-env-variables#time-format). | Version: v11.2.0\+
Default: `6m`
Applications: API | +| `CACHE_HOT_SMART_CONTRACTS_3H_PERIOD` | TTL for ConCache entries serving `GET /api/v2/stats/hot-smart-contracts` with `scale=3h`. Controls how long paginated rankings over the last 3 hours of contract activity are reused before recomputing from the database. [Time format](/setup/env-variables/backend-env-variables#time-format). | Version: v11.2.0\+
Default: `18m`
Applications: API | + + +## 11.1.3 + +### 🐛 Bug Fixes + +- Run background migrations immediately on green install ([#14424](https://github.com/blockscout/blockscout/issues/14424)) +- Adapt maybe_reject_zero_value for pre-changeset values ([#14425](https://github.com/blockscout/blockscout/issues/14425)) + +### ⚙️ Miscellaneous Tasks + +- Distributed MapCache ([#14411](https://github.com/blockscout/blockscout/pull/14411)) + +## 11.1.2 + +### 🐛 Bug Fixes + +- Fix VersionUpgrade check for empty previous version ([#14410](https://github.com/blockscout/blockscout/issues/14410)) + +## 11.1.1 + +### 🐛 Bug Fixes + +- Declare missing OpenAPI params for advanced-filters endpoint ([#14401](https://github.com/blockscout/blockscout/pull/14401), [#14399](https://github.com/blockscout/blockscout/issues/14399)) + +## 11.1.0 + +### 🚀 Features + +- Forward new BENS fields to search ([#14389](https://github.com/blockscout/blockscout/pull/14389)) +- Fetch token circulating supply along with circulating market cap ([#11969](https://github.com/blockscout/blockscout/issues/11969)) +- Support token lists import ([#11801](https://github.com/blockscout/blockscout/issues/11801)) +- transform ECTO_USE_SSL to sslmode param ([#8818](https://github.com/blockscout/blockscout/issues/8818)) + +### 🐛 Bug Fixes + +- Properly start VersionUpgrade on application launch ([#14396](https://github.com/blockscout/blockscout/pull/14396)) +- MissingBalanceOfToken fixes ([#14267](https://github.com/blockscout/blockscout/pull/14267)) +- Improvements of OpenAPI specification for `/v2/blocks` ([#14251](https://github.com/blockscout/blockscout/issues/14251)) +- Normalize Tesla timeout middleware exceptions ([#14059](https://github.com/blockscout/blockscout/issues/14059)) + +### 🚜 Refactor + +- Change multichain_search_db_export_token_info_queue.address_hash field type from :binary to Hash.Address ([#12894](https://github.com/blockscout/blockscout/issues/12894)) +- Refactor json rpc response parsers to ignore unknown fields ([#10334](https://github.com/blockscout/blockscout/issues/10334)) + +### 📚 Documentation + +- Add verification websocket subscription guide ([#14259](https://github.com/blockscout/blockscout/issues/14259)) + +### ⚙️ Miscellaneous Tasks + +- Add SPDX license identifier to Elixir source and test files ([#14393](https://github.com/blockscout/blockscout/pull/14393)) +- Publish OpenAPI specs on dev branch pushes ([#14391](https://github.com/blockscout/blockscout/pull/14391)) +- Add MIGRATION_FILL_INTERNAL_TRANSACTIONS_ADDRESS_IDS_CONCURRENCY ([#14390](https://github.com/blockscout/blockscout/pull/14390)) +- Close linked issues when PRs merge into dev ([#14384](https://github.com/blockscout/blockscout/pull/14384), [#14385](https://github.com/blockscout/blockscout/pull/14385)) +- Add SPDX attribution ([#14360](https://github.com/blockscout/blockscout/issues/14360)) +- Eliminate horizontal scroll in the main LICENSE file ([#14359](https://github.com/blockscout/blockscout/issues/14359)) +- Partial async import ([#14277](https://github.com/blockscout/blockscout/issues/14277)) +- OpenAPI specifications for all `/api/v2/advanced-filters` endpoints ([#14227](https://github.com/blockscout/blockscout/issues/14227)) +- OpenAPI spec for Arbitrum-related endpoints ([#14169](https://github.com/blockscout/blockscout/issues/14169)) +- Audit mode dependent processes ([#13925](https://github.com/blockscout/blockscout/issues/13925), [#14383](https://github.com/blockscout/blockscout/pull/14383)) +- Delete fiat_value for token if it disappears in coingecko ([#8932](https://github.com/blockscout/blockscout/issues/8932)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `TOKEN_LIST_URL` | URL for token list standard https://tokenlists.org/. Implemented in [#14206](https://github.com/blockscout/blockscout/pull/14206). | Version: v11.1.0\+
Default: (empty)
Applications: Indexer | +| `TOKEN_LIST_REFETCH_INTERVAL` | Interval to update data from token list. Implemented in [#14206](https://github.com/blockscout/blockscout/pull/14206). | Version: v11.1.0\+
Default: (empty)
Applications: Indexer | +| `ECTO_SSL_MODE` | SSL mode for Ecto DB connections. Supported values: `disable`, `allow`, `prefer`, `require`, `verify-ca`, `verify-full`. Resolution order: `ECTO_SSL_MODE` has highest priority, then `sslmode` in `DATABASE_URL`, otherwise defaults to `require`. | Version: v11.1.0\++
Default: `require`
Applications: API, Indexer | +| `INDEXER_ENABLE_PARTIAL_ASYNC_IMPORT` | If `true`, addresses, current token balances, tokens and token instances are imported asynchronously. Implemented in [#14277](https://github.com/blockscout/blockscout/pull/14277). | Version: v11.1.0\+
Default: `false`
Applications: Indexer | +| `MIGRATION_FILL_INTERNAL_TRANSACTIONS_ADDRESS_IDS_CONCURRENCY` | Number of parallel processes filling internal transactions address ids. Implemented in [#14390](https://github.com/blockscout/blockscout/pull/14390). | Version: v11.1.0\+
Default: `10`
Applications: Indexer | + +### Deprecated ENV variables + +| Variable | Description | Default | Version | Need recompile | Deprecated in Version | +| -------- | ----------- | ------- | ------- | -------------- | --------------------- | +| Deprecated `ECTO_USE_SSL` | Boolean SSL toggle for Ecto DB connections. Replaced with `ECTO_SSL_MODE`. | `TRUE` | All | | v11.1.0+ | + +## 11.0.3 + +### 🐛 Bug Fixes + +- Insert AddressIdToAddressHash via safe_insert_all ([#14333](https://github.com/blockscout/blockscout/pull/14333)) +- Force search for contract creator if internal transactions module is disabled ([#14324](https://github.com/blockscout/blockscout/issues/14324)) +- Add transactions uniqueness before insert ([#14329](https://github.com/blockscout/blockscout/issues/14329)) + +### ⚙️ Miscellaneous Tasks + +- Don't lock tables if foreign keys are already dropped ([#14321](https://github.com/blockscout/blockscout/issues/14321)) +- Dev branch + CI, remove obsolete GA workflows ([#14317](https://github.com/blockscout/blockscout/issues/14317)) + + +## 11.0.2 + +### 🐛 Bug Fixes + +- Process empty list of changes on fetching contract codes ([#14312](https://github.com/blockscout/blockscout/pull/14312)) +- Add fallback for empty "to" in Geth selfdestruct ([#14256](https://github.com/blockscout/blockscout/issues/14256)) +- Trim contractaddresses in getcontractcreation ([#14306](https://github.com/blockscout/blockscout/issues/14306)) +- Adapt maybe_reject_zero_value for empty blocks ([#14309](https://github.com/blockscout/blockscout/issues/14309)) +- Add missing internal transactions address preload ([#14308](https://github.com/blockscout/blockscout/issues/14308)) +- Fix some web tests ([#14310](https://github.com/blockscout/blockscout/pull/14310)) + +### ⚙️ Miscellaneous Tasks + +- Disable on-demand IT fetcher test for rsk and filecoin ([#14314](https://github.com/blockscout/blockscout/pull/14314)) +- Disable flaky contract code compiler doctest ([#14313](https://github.com/blockscout/blockscout/pull/14313)) +- Add coverage for core API v2 views ([#14254](https://github.com/blockscout/blockscout/issues/14254)) + + +## 11.0.1 + +### 🐛 Bug Fixes + +- Update OnDemand.InternalTransaction etherscan fields ([#14297](https://github.com/blockscout/blockscout/pull/14297)) +- Use inner join for verified contract addresses instead of lateral join ([#14294](https://github.com/blockscout/blockscout/pull/14294)) +- Disable on-demand internal tx fetch when corresponding flag is provided ([#14289](https://github.com/blockscout/blockscout/pull/14289)) +- Add fill IT addresses dependency into drop index migrations ([#14280](https://github.com/blockscout/blockscout/issues/14280)) +- Fix incorrect batch size in Indexer.Fetcher.OnDemand.TokenBalance ([#14265](https://github.com/blockscout/blockscout/issues/14265)) +- Prevent ETS crash in ContractCreator on GenServer restart ([#14221](https://github.com/blockscout/blockscout/issues/14221)) +- Fix internal transactions address dynamic condition ([#14278](https://github.com/blockscout/blockscout/issues/14278)) +- Remove addresses preload in celo parse_internal_transactions ([#14272](https://github.com/blockscout/blockscout/issues/14272)) +- Parse celo reward cursor params for address pagination ([#14275](https://github.com/blockscout/blockscout/issues/14275)) +- Map optimism-celo to celo OpenAPI folder ([#14274](https://github.com/blockscout/blockscout/issues/14274)) +- Make "sort_param" description endpoint-agnostic in OpenAPI spec ([#14270](https://github.com/blockscout/blockscout/issues/14270)) +- Fix Celo epochs list pagination ([#14269](https://github.com/blockscout/blockscout/issues/14269)) + +### 🚜 Refactor + +- Move preload contract creation internal transaction under runtime toggle ([#14279](https://github.com/blockscout/blockscout/issues/14279), ([#14287](https://github.com/blockscout/blockscout/pull/14287))) + +### ⚙️ Miscellaneous Tasks + +- Cover all RPC API stats endpoints and stabilize flaky specs ([#14299](https://github.com/blockscout/blockscout/pull/14299)) +- Change "coinsupply" RPC API response to fit JSON RPC requirements ([#14298](https://github.com/blockscout/blockscout/pull/14298)) +- Optimize internal transactions address_match_dynamic ([#14293](https://github.com/blockscout/blockscout/pull/14293)) +- Add window_size for PendingTransactionsSanitizer ([#14292](https://github.com/blockscout/blockscout/pull/14292)) +- Make pending operations helper batching configurable ([#14273](https://github.com/blockscout/blockscout/issues/14273)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `INDEXER_PENDING_TRANSACTIONS_WINDOW_SIZE` | Time offset for pending transactions sanitizer. Implemented in [#14292](https://github.com/blockscout/blockscout/pull/14292). | Version: v11.0.1\+
Default: `1d`
Applications: Indexer | +| `TOKEN_BALANCE_ON_DEMAND_FETCHER_BATCH_SIZE` | Batch size for Indexer.Fetcher.OnDemand.TokenBalance. Introduced in [#14265](https://github.com/poanetwork/blockscout/pull/14265) | Version: v11.0.1\+
Default: `500`
Applications: API, Indexer | +| `TOKEN_BALANCE_ON_DEMAND_FETCHER_CONCURRENCY` | Concurrency for Indexer.Fetcher.OnDemand.TokenBalance. Introduced in [#14265](https://github.com/poanetwork/blockscout/pull/14265) | Version: v11.0.1\+
Default: `4`
Applications: API, Indexer | +| `TOKEN_BALANCE_ON_DEMAND_FETCHER_ADDRESS_QUEUE_FLUSH_INTERVAL` | How often the on-demand token balance address queue is flushed to processing. Use a shorter interval for lower latency, or a longer interval to accumulate larger batches and reduce query frequency. Introduced in [#14265](https://github.com/poanetwork/blockscout/pull/14265) | Version: v11.0.1\+
Default: `1s`
Applications: API, Indexer | +| `TOKEN_BALANCE_ON_DEMAND_FETCHER_ADDRESS_QUEUE_BATCH_SIZE` | Batch size for on-demand token balance address queue. Introduced in [#14265](https://github.com/poanetwork/blockscout/pull/14265) | Version: v11.0.1\+
Default: `50`
Applications: API, Indexer | +| `PENDING_OPERATIONS_HELPER_TRANSACTIONS_BATCH_SIZE` | Batch size for transactions when processing pending operations. Implemented in [#14273](https://github.com/blockscout/blockscout/pull/14273). | Version: v11.0.1\+
Default: `1000`
Applications: Indexer | +| `PENDING_OPERATIONS_HELPER_BLOCKS_BATCH_SIZE` | Batch size for blocks when processing pending operations. Implemented in [#14273](https://github.com/blockscout/blockscout/pull/14273). | Version: v11.0.1\+
Default: `10`
Applications: Indexer | + + + +## 11.0.0 + +### 🚀 Features + +- Async CSV export ([#14028](https://github.com/blockscout/blockscout/issues/14028)) +- FHE operations and tags ([#13742](https://github.com/blockscout/blockscout/issues/13742)) +- Restore BENS preloads on the main page under toggle and add blocks BENS preload toggle ([#14262](https://github.com/blockscout/blockscout/pull/14262)) +- /api/legacy/* wrappers for three ES-compatible RPC endpoints ([#14239](https://github.com/blockscout/blockscout/pull/14239)) +- Make token balances import chunk size configurable ([#14250](https://github.com/blockscout/blockscout/pull/14250)) +- Add toggle to disable transactions / token transfers BENS preload ([#14159](https://github.com/blockscout/blockscout/issues/14159)) +- Add ENS and metadata preloading in block channel ([#12074](https://github.com/blockscout/blockscout/issues/12074)) +- Add validation for IPFS links before sending requests to gateway ([#14131](https://github.com/blockscout/blockscout/issues/14131)) +- Add search by token address hash in /api/v2/tokens ([#14102](https://github.com/blockscout/blockscout/issues/14102)) +- Add :rename heavy index db operation type and implement zero-downtime index replacement for transactions table ([#14052](https://github.com/blockscout/blockscout/issues/14052)) +- Use libraries field from eth bytecode db response ([#13948](https://github.com/blockscout/blockscout/issues/13948)) + +### 🐛 Bug Fixes + +- Fix filecoin view error ([#14255](https://github.com/blockscout/blockscout/pull/14255)) +- Internal transactions on-demand fetcher: check existence of deleted internal transactions address placeholders ([#14249](https://github.com/blockscout/blockscout/pull/14249)) +- Fix OnDemand.InternalTransaction fetcher ([#14242](https://github.com/blockscout/blockscout/pull/14242)) +- Guard missing ETS table in contract creator fetcher ([#14241](https://github.com/blockscout/blockscout/pull/14241)) +- Address ids usage improvements ([#14240](https://github.com/blockscout/blockscout/pull/14240)) +- Fix timeouts for API v1 tokentx endpoint ([#14185](https://github.com/blockscout/blockscout/issues/14185)) +- Remove internal transaction error field references ([#14213](https://github.com/blockscout/blockscout/pull/14213)) +- Handle partial errors in ContractCode fetch_codes ([#14211](https://github.com/blockscout/blockscout/pull/14211)) +- Include bridged token query params in OpenAPI spec ([#14209](https://github.com/blockscout/blockscout/pull/14209)) +- Update changed constraint name in shrink IT migration ([#14205](https://github.com/blockscout/blockscout/pull/14205)) +- Fix contract internal transactions preload ([#14203](https://github.com/blockscout/blockscout/issues/14203)) +- Handle RPC errors in ContractCreator, limit retries to 5 ([#14136](https://github.com/blockscout/blockscout/issues/14136)) +- Prevent duplicate missing block range inserts ([#14138](https://github.com/blockscout/blockscout/issues/14138)) +- Implementation address hash retrieval logic in the old UI ([#14192](https://github.com/blockscout/blockscout/issues/14192)) +- Keycloak address displaying ([#14155](https://github.com/blockscout/blockscout/issues/14155)) +- Celo election rewards csv export ([#14160](https://github.com/blockscout/blockscout/issues/14160)) +- Sync GraphQL language enum with SmartContract schema ([#14109](https://github.com/blockscout/blockscout/issues/14109)) +- Don't insert PTO for non-traceable transactions ([#14133](https://github.com/blockscout/blockscout/issues/14133)) +- Fix pending ops migration overflow by adaptive batching and chunked inserts ([#14135](https://github.com/blockscout/blockscout/issues/14135)) +- State changes use token transfer type ([#14073](https://github.com/blockscout/blockscout/issues/14073)) +- Fix 500 error when apikey provided with disabled account ([#14064](https://github.com/blockscout/blockscout/issues/14064)) +- Fix ArgumentError in BlockScoutWeb.NFTHelper.get_media_src/2 ([#14051](https://github.com/blockscout/blockscout/issues/14051)) + +### 🚜 Refactor + +- Refactor RollupReorgMonitorQueue ([#14196](https://github.com/blockscout/blockscout/issues/14196)) +- Deduplicate json_rpc_named_arguments ([#14194](https://github.com/blockscout/blockscout/issues/14194)) +- Fully migrate to `language` enum field in `smart_contracts` table ([#14049](https://github.com/blockscout/blockscout/issues/14049)) +- Migrate address_names to composite primary key on (address_hash, name) ([#14078](https://github.com/blockscout/blockscout/issues/14078)) + +### 📚 Documentation + +- Add .dialyzer-ignore hygiene guideline to CONTRIBUTING ([#14199](https://github.com/blockscout/blockscout/issues/14199)) + +### ⚡ Performance + +- Optimize token1155tx API v1 endpoint ([#14202](https://github.com/blockscout/blockscout/issues/14202)) +- Optimize optional address preloads across tx endpoints ([#14165](https://github.com/blockscout/blockscout/pull/14165)) +- Optimize on demand hot contracts performance ([#14150](https://github.com/blockscout/blockscout/issues/14150)) +- Remove join to "blocks" in api/v2/blocks/:block_number/transactions API endpoint ([#14162](https://github.com/blockscout/blockscout/issues/14162)) +- Improve performance of /api/v2/tokens API endpoint ([#14158](https://github.com/blockscout/blockscout/issues/14158)) + +### ⚙️ Miscellaneous Tasks + +- Update LICENCE ([#14201](https://github.com/blockscout/blockscout/pull/14201)) +- Remove "transaction_hash", "block_hash" and "block_index" from internal transactions, migrate Address Hashes to Address IDs ([#14099](https://github.com/blockscout/blockscout/issues/14099)) +- Remove timeout for test for FillInternalTransactionsAddressIds ([#14266](https://github.com/blockscout/blockscout/pull/14266)) +- Increase default timeout for FillInternalTransactionsAddressIds ([#14264](https://github.com/blockscout/blockscout/pull/14264)) +- Expand action of API_DISABLE_CONTRACT_CREATION_INTERNAL_TRANSACTION_ASSOCIATION flag to preload smart-contract associations ((#14257)[https://github.com/blockscout/blockscout/pull/14257]) +- Add Autoscout promo in the logs ([#14234](https://github.com/blockscout/blockscout/pull/14234)) +- Improve internal transactions migrations ([#14233](https://github.com/blockscout/blockscout/pull/14233)) +- Remove unused Explorer.Chain.Address.find_contract_addresses/2 function ([#14220](https://github.com/blockscout/blockscout/pull/14220)) +- Prevent deadlocks in IT fields removing migration ([#14215](https://github.com/blockscout/blockscout/pull/14215)) +- Filter blocks by BLOCK_RANGES in add_ranges_by_block_numbers ([#13875](https://github.com/blockscout/blockscout/pull/13875)) +- FillInternalTransactionsAddressIds improvements ([#14208](https://github.com/blockscout/blockscout/pull/14208)) +- Remove timeout between successful migrations ([#14198](https://github.com/blockscout/blockscout/issues/14198)) +- Add batch size env for FillInternalTransactionsAddressIds migration ([#14204](https://github.com/blockscout/blockscout/issues/14204)) +- Add Celo OpenAPI specs ([#14197](https://github.com/blockscout/blockscout/issues/14197), [#14229](https://github.com/blockscout/blockscout/pull/14229)) +- Cover counters to multichain export with unit tests ([#14193](https://github.com/blockscout/blockscout/issues/14193)) +- Update credo config ([#14147](https://github.com/blockscout/blockscout/issues/14147)) +- Remove Polygon zkEVM support ([#14188](https://github.com/blockscout/blockscout/issues/14188)) +- Add Block.full_refetch ([#14180](https://github.com/blockscout/blockscout/issues/14180)) +- Remove deprecated files from the root folder ([#14186](https://github.com/blockscout/blockscout/issues/14186)) +- Remove deprecated "transaction actions" indexer ([#14183](https://github.com/blockscout/blockscout/issues/14183)) +- Stabilize various flaky tests ([#14149](https://github.com/blockscout/blockscout/issues/14149)) +- Return automatic chromedriver version definition ([#14108](https://github.com/blockscout/blockscout/issues/14108)) +- Move agents skills to .agents/skills folder ([#14081](https://github.com/blockscout/blockscout/issues/14081)) +- Put in order background db migrations on the "transactions" table ([#14077](https://github.com/blockscout/blockscout/issues/14077)) +- Drop `transactions_operator_fee_constant_index` ([#14066](https://github.com/blockscout/blockscout/issues/14066)) +- Unescape ampersand in token's metadata ([#14055](https://github.com/blockscout/blockscout/issues/14055)) +- Treat blocks with huge amount of transactions as massive ([#13994](https://github.com/blockscout/blockscout/issues/13994)) +- Add OpenAPI docs for Scroll and Zilliqa endpoints ([#13972](https://github.com/blockscout/blockscout/issues/13972)) +- Add all-in-one open API spec file ([#14050](https://github.com/blockscout/blockscout/issues/14050)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `DISABLE_BLOCK_BROADCAST_ENRICHMENT` | If `true`, disables ENS and metadata enrichment for `new_block` WebSocket broadcasts. Implemented in [#12074](https://github.com/blockscout/blockscout/pull/12074). | Version: v11.0.0\+
Default: (empty)
Applications: API | +| `INDEXER_MASSIVE_BLOCK_THRESHOLD` | Max transactions count in a single block after which the block is treated as massive. Implemented in [#13994](https://github.com/blockscout/blockscout/pull/13994). | Version: v11.0.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_CURRENT_TOKEN_BALANCES_IMPORT_CHUNK_SIZE` | Number of CurrentTokenBalances items processed per chunk in token balances import. Default is 50; effective minimum is 1. Implemented in [#14250](https://github.com/blockscout/blockscout/pull/14250). | Version: v11.0.0\+
Default: `50`
Applications: Indexer | +| `INDEXER_FHE_OPERATIONS_ENABLED` | Flag to enable parsing of Fully Homomorphic Encryption (FHE) operations from transactions. Implemented in [#13742](https://github.com/blockscout/blockscout/pull/13742). | Version: v11.0.0\+
Default: `false`
Applications: Indexer | +| `MIGRATION_FILL_INTERNAL_TRANSACTIONS_ADDRESS_IDS_BATCH_SIZE` | Number of internal transactions to fill their address ids in the batch. Implemented in [#14204](https://github.com/blockscout/blockscout/pull/14204). | Version: v11.0.0\+
Default: `30`
Applications: Indexer | +| `MIGRATION_FILL_INTERNAL_TRANSACTIONS_ADDRESS_IDS_TIMEOUT` | Timeout between filling internal transactions address ids batches processing. Implemented in [#14208](https://github.com/blockscout/blockscout/pull/14208). | Version: v11.0.0\+
Default: `5s`
Applications: Indexer | +| `DISABLE_BLOCKS_BENS_PRELOAD` | If `true`, skips ENS name preloading in responses for block list endpoints: `/api/v2/blocks`, `/api/v2/main-page/blocks`, `/api/v2/blocks/optimism-batch/:batch_number`, `/api/v2/blocks/scroll-batch/:batch_number`. | Version: v11.0.0+
Default: `false`
Applications: API | +| `DISABLE_TRANSACTIONS_BENS_PRELOAD` | If `true`, skips ENS name preloading in responses for transaction list endpoints: `/api/v2/transactions`, `/api/v2/transactions/watchlist`, `/api/v2/main-page/transactions`, `/api/v2/main-page/transactions/watchlist`, `/api/v2/addresses/:hash/transactions`, `/api/v2/blocks/:hash/transactions`. | Version: v11.0.0+
Default: `false`
Applications: API | +| `DISABLE_TOKEN_TRANSFERS_BENS_PRELOAD` | If `true`, skips ENS name preloading in responses for token transfer list endpoints: `/api/v2/token-transfers`, `/api/v2/addresses/:hash/token-transfers`, `/api/v2/tokens/:address_hash_param/transfers`. | Version: v11.0.0+
Default: `false`
Applications: API | +| `CSV_EXPORT_ASYNC_ENABLED` | Enables async CSV export for supported endpoints. When enabled, the API returns `202 Accepted` with a `request_id` and processes exports through Oban instead of streaming them directly. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `false`
Applications: API | +| `CSV_EXPORT_ASYNC_OBAN_CONCURRENCY` | Sets Oban concurrency for the `csv_export` queue used by async CSV exports. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `10`
Applications: API | +| `CSV_EXPORT_ASYNC_GOKAPI_URL` | Base URL of the Gokapi instance used to store completed async CSV exports. Trailing slash is stripped during validation. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: Yes, if async export is enabled
Default: (empty)
Applications: API | +| `CSV_EXPORT_ASYNC_GOKAPI_API_KEY` | API key sent to Gokapi in the `apikey` header for async CSV export uploads. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: Yes, if async export is enabled
Default: (empty)
Applications: API | +| `CSV_EXPORT_ASYNC_MAX_PENDING_TASKS_PER_IP` | Maximum number of pending async CSV export requests allowed per client IP at once. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `3`
Applications: API | +| `CSV_EXPORT_ASYNC_UPLOAD_CHUNK_SIZE` | Chunk size in bytes for reading the generated CSV file and uploading it to Gokapi. Should be synchronized with Gokapi settings. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `47185920`
Applications: API | +| `CSV_EXPORT_DB_TIMEOUT` | Timeout for CSV export database work. Follows the [time format](/setup/env-variables/backend-env-variables#time-format). Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `1h` if async export is enabled, otherwise `5m`
Applications: API | +| `CSV_EXPORT_ASYNC_TMP_DIR` | Directory used for in-progress async CSV export files before they are uploaded to Gokapi. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `/tmp/csv_export`
Applications: API | +| `CSV_EXPORT_ASYNC_GOKAPI_TIMEOUT` | HTTP timeout and `recv_timeout` used for Gokapi requests during async CSV export. Follows the [time format](/setup/env-variables/backend-env-variables#time-format). Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `60s`
Applications: API | +| `CSV_EXPORT_ASYNC_GOKAPI_UPLOAD_EXPIRY_DAYS` | Sets Gokapi `expiryDays` for completed async CSV export uploads. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `1`
Applications: API | +| `CSV_EXPORT_ASYNC_GOKAPI_UPLOAD_ALLOWED_DOWNLOADS` | Sets Gokapi `allowedDownloads` for completed async CSV export uploads. Implemented in [#14028](https://github.com/blockscout/blockscout/pull/14028) | Version: v11.0.0\+ Required: No
Default: `1`
Applications: API | + +### Deprecated ENV variables + +| Variable | Description | Default | Version | Need recompile | Deprecated in Version | +| -------- | ----------- | ------- | ------- | -------------- | --------------------- | +| Deprecated `INDEXER_POLYGON_ZKEVM_BATCHES_ENABLED` | Enables Polygon zkEVM batches fetcher. Implemented in [#7584](https://github.com/blockscout/blockscout/pull/7584). | `false` | v5.3.1+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_BATCHES_CHUNK_SIZE` | The number of Polygon zkEVM batches in one chunk when reading them from RPC. Implemented in [#7584](https://github.com/blockscout/blockscout/pull/7584). | `20` | v5.3.1+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_BATCHES_RECHECK_INTERVAL` | The latest batch rechecking interval, seconds. Implemented in [#7584](https://github.com/blockscout/blockscout/pull/7584). | `60` | v5.3.1+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_BATCHES_IGNORE` | Comma-separated list of batch numbers that should be ignored by the fetcher. Implemented in [#12387](https://github.com/blockscout/blockscout/pull/12387). | (empty) | v9.0.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_RPC` | The RPC endpoint for L1 used to fetch Deposit or Withdrawal bridge events. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | (empty) | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_START_BLOCK` | The number of a start block on L1 to index L1 bridge events. If the table of bridge operations is not empty, the process will continue indexing from the last indexed L1 event. If empty or not defined, the L1 events are not handled. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | (empty) | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_CONTRACT` | The address of PolygonZkEVMBridgeV2 contract on L1 used to fetch L1 bridge events. Required for L1 bridge events indexing. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | (empty) | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_NETWORK_ID` | L1 Network ID in terms of Polygon zkEVM bridge (0 = Ethereum Mainnet, 1 = Polygon zkEVM, 2 = Astar zkEVM, etc.). Required if `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_START_BLOCK` or `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_START_BLOCK` is defined. Implemented in [#9637](https://github.com/blockscout/blockscout/pull/9637). | (empty) | v6.4.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_ROLLUP_INDEX` | L1 Rollup index in terms of Polygon zkEVM bridge (0 = Polygon zkEVM, 1 = Astar zkEVM, etc.). Not defined if L1 is Ethereum Mainnet. Required if L1 is not Ethereum Mainnet and `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_START_BLOCK` or `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_START_BLOCK` is defined. Implemented in [#9637](https://github.com/blockscout/blockscout/pull/9637). | (empty) | v6.4.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_NATIVE_SYMBOL` | The symbol of the native coin on L1 to display it in the table of the bridge Deposits and Withdrawals on UI. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | `ETH` | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_NATIVE_DECIMALS` | The number of decimals to correctly display an amount of native coins for some Deposit or Withdrawal bridge operations on UI. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | `18` | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_START_BLOCK` | The number of a start block on L2 to index L2 bridge events. If the table of bridge operations is not empty, the process will continue indexing from the last indexed L2 event. If empty or not defined, the L2 events are not handled. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | (empty) | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_CONTRACT` | The address of PolygonZkEVMBridgeV2 contract on L2 used to fetch L2 bridge events. Required for L2 bridge events indexing. Implemented in [#9098](https://github.com/blockscout/blockscout/pull/9098). | (empty) | v6.2.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_NETWORK_ID` | L2 Network ID in terms of Polygon zkEVM bridge (1 = Polygon zkEVM, 2 = Astar zkEVM, etc.). Required if `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_START_BLOCK` or `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_START_BLOCK` is defined. Implemented in [#9637](https://github.com/blockscout/blockscout/pull/9637). | (empty) | v6.4.0+ | | v11.0.0+ | +| Deprecated `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_ROLLUP_INDEX` | L2 Rollup index in terms of Polygon zkEVM bridge (0 = Polygon zkEVM, 1 = Astar zkEVM, etc.). Required if `INDEXER_POLYGON_ZKEVM_L1_BRIDGE_START_BLOCK` or `INDEXER_POLYGON_ZKEVM_L2_BRIDGE_START_BLOCK` is defined. Implemented in [#9637](https://github.com/blockscout/blockscout/pull/9637). | (empty) | v6.4.0+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_AAVE_V3_POOL_CONTRACT` | Pool contract address for Aave v3 protocol. If not defined, Aave transaction actions are ignored by the indexer. Implemented in [#7185](https://github.com/blockscout/blockscout/pull/7185). | (empty) | v5.1.3+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_ENABLE` | If `true`, transaction action indexer is active. Implemented in [#6582](https://github.com/blockscout/blockscout/pull/6582). | `false` | v5.1.0+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_MAX_TOKEN_CACHE_SIZE` | Maximum number of items in an internal cache of tx actions indexing process (to limit memory consumption). Implemented in [#6582](https://github.com/blockscout/blockscout/pull/6582). | `100000` | v5.1.0+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_REINDEX_FIRST_BLOCK` | The first block of a block range for historical indexing or reindexing of tx actions. Implemented in [#6582](https://github.com/blockscout/blockscout/pull/6582). | (empty) | v5.1.0+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_REINDEX_LAST_BLOCK` | The last block of a block range for historical indexing or reindexing of tx actions. Implemented in [#6582](https://github.com/blockscout/blockscout/pull/6582). | (empty) | v5.1.0+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_REINDEX_PROTOCOLS` | Comma-separated names of protocols which should be indexed or reindexed on historical blocks defined by the range. Example: `uniswap_v3,zkbob` - only these protocols will be indexed or reindexed for the defined block range. If the value is empty string (or not defined), all supported protocols will be indexed/reindexed. This option is not applicable to `realtime` and `catchup` fetchers (it always indexes all supported protocols). Implemented in [#6582](https://github.com/blockscout/blockscout/pull/6582). | (empty) | v5.1.0+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_UNISWAP_V3_FACTORY_CONTRACT` | UniswapV3Factory contract address. Implemented in [#7312](https://github.com/blockscout/blockscout/pull/7312). | `0x1F98431c8aD98523631AE4a59f267346ea31F984` | v5.1.4+ | | v11.0.0+ | +| Deprecated `INDEXER_TX_ACTIONS_UNISWAP_V3_NFT_POSITION_MANAGER_CONTRACT` | NonfungiblePositionManager contract address for Uniswap v3. Implemented in [#7312](https://github.com/blockscout/blockscout/pull/7312). | `0xC36442b4a4522E871399CD717aBDD847Ab11FE88` | v5.1.4+ | | v11.0.0+ | +| Deprecated `MIGRATION_REINDEX_DUPLICATED_INTERNAL_TRANSACTIONS_BATCH_SIZE` | Number of internal transactions to reindex in the batch. Implemented in [#12394](https://github.com/blockscout/blockscout/pull/12394). | `100` | v8.1.0+ | | v11.0.0+ | +| Deprecated `MIGRATION_REINDEX_DUPLICATED_INTERNAL_TRANSACTIONS_CONCURRENCY` | Number of parallel reindexing internal transaction batches processing. Implemented in [#12394](https://github.com/blockscout/blockscout/pull/12394). | `1` | v8.1.0+ | | v11.0.0+ | +| Deprecated `MIGRATION_REINDEX_DUPLICATED_INTERNAL_TRANSACTIONS_TIMEOUT` | Timeout between reindexing internal transaction batches processing. Implemented in [#12394](https://github.com/blockscout/blockscout/pull/12394). | `0` | v8.1.0+ | | v11.0.0+ | + + +## 10.2.6 + +### 🐛 Bug Fixes + +- Fix PendingTransactionsSanitizer ([#14235](https://github.com/blockscout/blockscout/issues/14235)) + + +## 10.2.5 + +### 🐛 Bug Fixes + +- Update changed constraint name in shrink IT migration ([#14205](https://github.com/blockscout/blockscout/issues/14205)) + + +## 10.2.4 + +### ⚡ Performance + +- Use tuple-based comparison to utilize index ([#14178](https://github.com/blockscout/blockscout/pull/14178)) + +### 🐛 Bug Fixes + +- Update transaction from receipt in PendingTransactionsSanitizer ([#14182](https://github.com/blockscout/blockscout/issues/14182)) + +### ⚙️ Miscellaneous Tasks + +- Add swagger generation for Arc and Suave chain types ([#14181](https://github.com/blockscout/blockscout/issues/14181)) + + +## 10.2.3 + +### 🐛 Bug Fixes + +- Allow fetching of stale token balances ([#14154](https://github.com/blockscout/blockscout/issues/14154)) + + +## 10.2.2 + +### 🐛 Bug Fixes + +- Fix token transfers block_consensus setting ([#14005](https://github.com/blockscout/blockscout/issues/14005)) +- OP Withdrawals indexer enhancement ([#13436](https://github.com/blockscout/blockscout/issues/13436)) + +### ⚙️ Miscellaneous Tasks + +- Add token transfer consensus sanitizer ([#14144](https://github.com/blockscout/blockscout/issues/14144)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `INDEXER_TOKEN_TRANSFER_BLOCK_CONSENSUS_SANITIZER_INTERVAL` | Interval for token transfer block consensus sanitizer. [Time format](/setup/env-variables/backend-env-variables#time-format). Implemented in [#14144](https://github.com/blockscout/blockscout/pull/14144). | Version: v10.2.2\+
Default: `20m`
Applications: Indexer | + + +## 10.2.1 + +### 🐛 Bug Fixes + +- Notify.check_auth0 for Keycloak and Dynamic ([#14146](https://github.com/blockscout/blockscout/issues/14146)) + +## 10.2.0 + +### 🚀 Features + +- Fetch transaction receipts by block ([#14046](https://github.com/blockscout/blockscout/issues/14046)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `ETHEREUM_JSONRPC_RECEIPTS_BY_BLOCK` | If `true`, block fetchers will fetch transaction receipts by block instead of per transaction. Implemented in [#14046](https://github.com/blockscout/blockscout/pull/14046) | Version: v10.2.0\+
Default: `false`
Applications: API, Indexer | +| `ETHEREUM_JSONRPC_MAX_RECEIPTS_BY_BLOCK` | Max number of transactions in block for which receipts will be fetched by block. If block has more transactions, receipts will be fetched per transaction in purpose of reducing response body size. Implemented in [#14046](https://github.com/blockscout/blockscout/pull/14046) | Version: v10.2.0\+
Default: `1000`
Applications: API, Indexer | + + +## 10.1.1 + +### 🐛 Bug Fixes + +- Authentication provider token redis key ([#14137](https://github.com/blockscout/blockscout/issues/14137)) + + +## 10.1.0 + +### 🚀 Features + +- KeyCloak integration ([#14068](https://github.com/blockscout/blockscout/issues/14068)) + +### New ENV variables + +| Variable | Description | Parameters | +|-----------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `ACCOUNT_SENDGRID_OTP_TEMPLATE` | Sendgrid email OTP template for login with email functionality. Implemented in [#14068](https://github.com/blockscout/blockscout/pull/14068). | Version: v9.4.0\+
Default: (empty)
Applications: API | +| `ACCOUNT_KEYCLOAK_DOMAIN` | Domain for [Keycloak](https://www.keycloak.org/). Implemented in [#14068](https://github.com/blockscout/blockscout/pull/14068). | Version: v9.4.0\+
Default: (empty)
Applications: API | +| `ACCOUNT_KEYCLOAK_REALM` | Realm for [Keycloak](https://www.keycloak.org/). Implemented in [#14068](https://github.com/blockscout/blockscout/pull/14068). | Version: v9.4.0\+
Default: (empty)
Applications: API | +| `ACCOUNT_KEYCLOAK_CLIENT_ID` | [Keycloak](https://www.keycloak.org/) client ID. Implemented in [#14068](https://github.com/blockscout/blockscout/pull/14068). | Version: v9.4.0\+
Default: (empty)
Applications: API | +| `ACCOUNT_KEYCLOAK_CLIENT_SECRET` | [Keycloak](https://www.keycloak.org/) client secret. Implemented in [#14068](https://github.com/blockscout/blockscout/pull/14068). | Version: v9.4.0\+
Default: (empty)
Applications: API | +| `ACCOUNT_KEYCLOAK_EMAIL_WEBHOOK_URL` | URL address where new email users are reported. Implemented in [#14068](https://github.com/blockscout/blockscout/pull/14068). | Version: v9.4.0\+
Default: (empty)
Applications: API | + + +## 10.0.8 + +### 🐛 Bug Fixes + +- Zetachain internal txs fetching error ([#14122](https://github.com/blockscout/blockscout/issues/14122)) + + +## 10.0.7 + +### 🐛 Bug Fixes + +- Add missing DenormalizationHelper alias in state changes ([#14119](https://github.com/blockscout/blockscout/issues/14119)) + + +## 10.0.6 + +### 🐛 Bug Fixes + +- Add dependency between heavy internal transactions migrations ([#14107](https://github.com/blockscout/blockscout/issues/14107)) + + +## 10.0.5 + +### 🐛 Bug Fixes + +- Add missing query params in user ops swagger spec ([#14104](https://github.com/blockscout/blockscout/issues/14104)) +- State changes handle ERC-7984; nil tx.value ([#14101](https://github.com/blockscout/blockscout/issues/14101)) + + +## 10.0.4 + +### 🐛 Bug Fixes + +- `confirm_otp` after `OpenApiSpex` integration ([#14098](https://github.com/blockscout/blockscout/issues/14098)) + + +## 10.0.3 + +### ⚙️ Miscellaneous Tasks + +- Allow disabling contract creation internal transaction association ([#14090](https://github.com/blockscout/blockscout/issues/14090), [#14097](https://github.com/blockscout/blockscout/pull/14097)) + + +## 10.0.2 + +### ⚙️ Miscellaneous Tasks + +- Add missing TokenBalance.Current launch in tests ([#14076](https://github.com/blockscout/blockscout/issues/14076)) +- Put backend versions into constants on launch ([#14072](https://github.com/blockscout/blockscout/issues/14072)) + + +## 10.0.1 + +### ⚡ Performance + +- Fix /advanced-filters timeout when scam filtering enabled ([#14047](https://github.com/blockscout/blockscout/issues/14047)) + +## 10.0.0 + +### 🚀 Features + +- ERC-7984 Confidential Tokens ([#13593](https://github.com/blockscout/blockscout/pull/13593), [#14019](https://github.com/blockscout/blockscout/pull/14019), [#14022](https://github.com/blockscout/blockscout/pull/14022), [#14023](https://github.com/blockscout/blockscout/pull/14023)) +- Move current token balances into a separate fetcher ([#13923](https://github.com/blockscout/blockscout/issues/13923)) +- Re-architect internal transaction format with call-type enum, error dictionary, and normalization ([#13893](https://github.com/blockscout/blockscout/issues/13893), [#14042](https://github.com/blockscout/blockscout/pull/14042), [#14043](https://github.com/blockscout/blockscout/pull/14043)) +- Add audit-reports import endpoint ([#13884](https://github.com/blockscout/blockscout/issues/13884)) +- Solady smart-contract proxy with immutable arguments support ([#13794](https://github.com/blockscout/blockscout/issues/13794)) +- Optionally accrue burnt fees to the block miner ([#13894](https://github.com/blockscout/blockscout/issues/13894)) +- Allow adding EOA with code to watchlist ([#13885](https://github.com/blockscout/blockscout/issues/13885)) +- Add Dynamic provider for account ([#13786](https://github.com/blockscout/blockscout/issues/13786)) +- Distributed cache ([#13698](https://github.com/blockscout/blockscout/issues/13698)) +- Return timestamps in the event logs list API endpoints ([#13779](https://github.com/blockscout/blockscout/issues/13779)) +- Support EigenDA blobs by Optimism batch indexer ([#13709](https://github.com/blockscout/blockscout/issues/13709)) +- `txlistinternal` API endpoint pending item status ([#13758](https://github.com/blockscout/blockscout/issues/13758)) +- Setup universal proxy config from the JSON content in ENV variable ([#13787](https://github.com/blockscout/blockscout/issues/13787)) +- Missed L1-to-L2 messages catchup on Arbitrum rollups ([#13792](https://github.com/blockscout/blockscout/issues/13792)) +- Expose CHAIN_TYPE in the REST API ([#13805](https://github.com/blockscout/blockscout/issues/13805)) +- REST API endpoint to list uncompleted DB migrations ([#13835](https://github.com/blockscout/blockscout/issues/13835)) +- Show ENS domains without resolved address in search ([#13638](https://github.com/blockscout/blockscout/issues/13638)) +- Mark contract addresses in search results ([#13636](https://github.com/blockscout/blockscout/issues/13636)) + +### 🐛 Bug Fixes + +- Handle nil coin balance in "broadcast_address_coin_balance/1" function ([#14044](https://github.com/blockscout/blockscout/pull/14044)) +- Fix duplicating paging params ([#14010](https://github.com/blockscout/blockscout/pull/14010)) +- Handle maybe_reject_zero_value for missing value ([#13990](https://github.com/blockscout/blockscout/pull/13990)) +- Handle internal transactions nil value([#13974](https://github.com/blockscout/blockscout/pull/13974)) +- `HttpClient.get` usage in genesis data module ([#13945](https://github.com/blockscout/blockscout/pull/13945)) +- Multichain counter starting time and small fixes ([#13920](https://github.com/blockscout/blockscout/pull/13920)) +- Fix 500 on empty ens domain search ([#13928](https://github.com/blockscout/blockscout/pull/13928)) +- Limit `getlogs` after filtering consensus ([#13934](https://github.com/blockscout/blockscout/pull/13934)) +- Handle nil in update_transactions_cache/2 ([#13911](https://github.com/blockscout/blockscout/pull/13911)) +- Fix token balances broadcasting function ([#13902](https://github.com/blockscout/blockscout/issues/13902)) +- Wrong `next_page_params` in OP Deposits ([#13870](https://github.com/blockscout/blockscout/issues/13870)) +- Fix error on loading thumbnails when public_r2_url is missed ([#13895](https://github.com/blockscout/blockscout/issues/13895)) +- Check token presence in address current token balance ([#13892](https://github.com/blockscout/blockscout/issues/13892)) +- Fix swagger generation for Mud chain +- Fix error in Indexer.Fetcher.OnDemand.TokenBalance module ([#13890](https://github.com/blockscout/blockscout/issues/13890)) +- Actualize indexer tests ([#13887](https://github.com/blockscout/blockscout/issues/13887)) +- Clear bytecode for smart-contracts self destructed in a separate transaction ([#13834](https://github.com/blockscout/blockscout/issues/13834)) +- Skip hot contracts fetching if last 30 days not indexed ([#13873](https://github.com/blockscout/blockscout/issues/13873)) +- Add block range filtering to TokenBalance fetcher ([#13874](https://github.com/blockscout/blockscout/issues/13874)) +- Filter traceable data in InternalTransaction.async_fetch ([#13872](https://github.com/blockscout/blockscout/issues/13872)) +- Take into account empty arrays in Explorer.Migrator.SanitizeIncorrectNFTTokenTransfers ([#13852](https://github.com/blockscout/blockscout/issues/13852)) +- Fix search for ERC-1155 with null symbol ([#13632](https://github.com/blockscout/blockscout/issues/13632)) +- Return date to logs ([#13858](https://github.com/blockscout/blockscout/issues/13858)) +- Convert token id to string from refetch metadata in the socket ([#13762](https://github.com/blockscout/blockscout/issues/13762)) +- Prevent DeleteZeroValueInternalTransactions from running while ShrinkInternalTransactions is in progress ([#13847](https://github.com/blockscout/blockscout/issues/13847)) +- Remove contract code and verified data on lose consensus ([#13829](https://github.com/blockscout/blockscout/issues/13829), [#13905](https://github.com/blockscout/blockscout/pull/13905)) +- Exclude 0 index internal transactions from /api/v2/internal-transactions endpoint ([#13841](https://github.com/blockscout/blockscout/issues/13841)) +- Fix NaN gas limit for `selfdestruct` internal transaction in the REST API ([#13827](https://github.com/blockscout/blockscout/issues/13827)) +- Handle normal termination of Indexer.Fetcher.OnDemand.ContractCode process ([#13828](https://github.com/blockscout/blockscout/issues/13828)) +- Validate block number in the api/v2/blocks/:block_number API endpoint ([#13795](https://github.com/blockscout/blockscout/issues/13795)) +- Fix methodId detection ([#13811](https://github.com/blockscout/blockscout/issues/13811)) +- Improve Arbitrum L1->L2 message discovery for reorg and RPC consistency ([#13770](https://github.com/blockscout/blockscout/issues/13770)) + +### 🚜 Refactor + +- Improve error handling in `EthereumJSONRPC.execute_contract_function/3` ([#13764](https://github.com/blockscout/blockscout/issues/13764)) + +### ⚙️ Miscellaneous Tasks + +- Claim storage space from multichain - related queues tables ([#14025](https://github.com/blockscout/blockscout/pull/14025)) +- Improve pending block operations count metric ([#14024](https://github.com/blockscout/blockscout/pull/14024)) +- Add initial_stream delay to BufferedTask ([#14018](https://github.com/blockscout/blockscout/pull/14018), [#14020](https://github.com/blockscout/blockscout/pull/14020)) +- Adjust query for "missing_current_token_balances_count" indexer metric ([#14009](https://github.com/blockscout/blockscout/pull/14009)) +- Add support for new BENS api ([#13992](https://github.com/blockscout/blockscout/pull/13992)) +- Add internal transactions not null constraints ([#13976](https://github.com/blockscout/blockscout/pull/13976), [#13995](https://github.com/blockscout/blockscout/pull/13995)) +- Change 429 error text ([#13989](https://github.com/blockscout/blockscout/pull/13989)) +- Enhance indexer metrics calculation ([#13985](https://github.com/blockscout/blockscout/pull/13985)) +- Don't send historic rate for recent txs ([#13960](https://github.com/blockscout/blockscout/pull/13960)) +- Increase default for MIGRATION_EMPTY_INTERNAL_TRANSACTIONS_DATA_BATCH_SIZE to 1000 ([#13953](https://github.com/blockscout/blockscout/pull/13953)) +- Improve EmptyInternalTransactionsData migration ([#13918](https://github.com/blockscout/blockscout/pull/13918)) +- Disable Auth0 when Dynamic enabled ([#13912](https://github.com/blockscout/blockscout/pull/13912)) +- Add swagger spec for account abstraction endpoints ([#13897](https://github.com/blockscout/blockscout/issues/13897)) +- Clear token "skip_metadata" property ([#13891](https://github.com/blockscout/blockscout/issues/13891)) +- Refactor internal transaction logic from "block_index" to "transaction_index" and "index" ([#12474](https://github.com/blockscout/blockscout/issues/12474), [#14029](https://github.com/blockscout/blockscout/pull/14029)) +- Cover Optimism API endpoints with swagger docs ([#13672](https://github.com/blockscout/blockscout/issues/13672)) +- Duplicate internal transaction created_contract_address_hash to to_address_hash ([#13846](https://github.com/blockscout/blockscout/issues/13846), [#14039](https://github.com/blockscout/blockscout/pull/14039), [#14040](https://github.com/blockscout/blockscout/pull/14040)) +- Add "openapi_spec_folder_name" to the response of api/v2/config/backend endpoint ([#13845](https://github.com/blockscout/blockscout/issues/13845)) +- Re-use parse_url_env_var/3 function for all *_URL env variables ([#13800](https://github.com/blockscout/blockscout/issues/13800)) +- Add swagger spec for MUD endpoints ([#13793](https://github.com/blockscout/blockscout/issues/13793)) +- Set unique block numbers in handle_partially_imported_blocks/1 ([#13657](https://github.com/blockscout/blockscout/issues/13657)) +- Disband 37% of Explorer.Chain module ([#13755](https://github.com/blockscout/blockscout/issues/13755)) +- Disable MissingRangesManipulator ([#13359](https://github.com/blockscout/blockscout/issues/13359)) +- Improve replica usage ([#13344](https://github.com/blockscout/blockscout/issues/13344)) +- Make "jsonrpc" field in response optional ([#13724](https://github.com/blockscout/blockscout/issues/13724)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `BLOCK_MINER_GETS_BURNT_FEES` | If `true`, the Burnt fees are added to block miner profit and displayed in UI as zero. Implemented in [#13894](https://github.com/blockscout/blockscout/pull/13894). | Version: v10.0.0\+
Default: `false`
Applications: API | +| `UNIVERSAL_PROXY_CONFIG` | JSON-encoded configuration string used to define settings for the universal proxy. Implemented in [#13787](https://github.com/blockscout/blockscout/pull/13787). | Version: v10.0.0\+
Default: (empty)
Applications: API | +| `MIGRATION_EMPTY_INTERNAL_TRANSACTIONS_DATA_BATCH_SIZE` | Number of internal transactions to clear their data in the batch. Implemented in [#13893](https://github.com/blockscout/blockscout/pull/13893). | Version: v10.0.0\+
Default: `1000`
Applications: Indexer | +| `MIGRATION_EMPTY_INTERNAL_TRANSACTIONS_DATA_CONCURRENCY` | Number of parallel clearing internal transaction data batches processing. Implemented in [#13893](https://github.com/blockscout/blockscout/pull/13893). | Version: v10.0.0\+
Default: `1`
Applications: Indexer | +| `MIGRATION_EMPTY_INTERNAL_TRANSACTIONS_DATA_TIMEOUT` | Timeout between clearing internal transaction data batches processing. Implemented in [#13893](https://github.com/blockscout/blockscout/pull/13893). | Version: v10.0.0\+
Default: `0`
Applications: Indexer | +| `CACHE_PENDING_OPERATIONS_COUNT_PERIOD` | Time interval to restart the task which calculates the total pending operations count. Introduced in [#12474](https://github.com/blockscout/blockscout/pull/12474). | Version: v10.0.0\+
Default: `5m`
Applications: API, Indexer | +| `ACCOUNT_DYNAMIC_ENV_ID` | Dynamic Environment ID, can be found here https://app.dynamic.xyz/dashboard/developer/api. Implemented in [#13786](https://github.com/blockscout/blockscout/pull/13786). | Version: v10.0.0\+
Default: (empty)
Applications: API | +| `INDEXER_OPTIMISM_L1_BATCH_EIGENDA_BLOBS_API_URL` | Defines a URL to DA indexer supporting EigenDA layer to retrieve L1 blobs from that. Example: `https://da-indexer-dev.k8s-prod-3.blockscout.com/api/v1/eigenda/v2/blobs`. Implemented in [#13709](https://github.com/blockscout/blockscout/pull/13709). | Version: v10.0.0+
Default: (empty)
Applications: Indexer | +| `INDEXER_OPTIMISM_L1_BATCH_EIGENDA_PROXY_BASE_URL` | Defines a URL to EigenDA proxy node which is used by the DA indexer (planned to be optional in the future). Example for MegaETH: `http://megaeth-eigenda-proxy.node.blockscout.com:3100`. Implemented in [#13709](https://github.com/blockscout/blockscout/pull/13709). | Version: v10.0.0+
Default: (empty)
Applications: Indexer | +| `INDEXER_ARBITRUM_MESSAGES_TRACKING_FAILURE_THRESHOLD` | The time threshold for L1 message tracking tasks. If a task has not run successfully within this threshold, it is marked as failed and enters a cooldown period before retrying. Implemented in [#13792](https://github.com/blockscout/blockscout/pull/13792). | Version: v10.0.0+
Default: `10m`
Applications: Indexer | +| `INDEXER_ARBITRUM_MISSED_MESSAGE_IDS_RANGE` | Size of each message ID range inspected when discovering L1-to-L2 messages with missing L1 origination information. Implemented in [#13792](https://github.com/blockscout/blockscout/pull/13792). | Version: v10.0.0+
Default: `10000`
Applications: Indexer | +| `INDEXER_CURRENT_TOKEN_BALANCES_BATCH_SIZE` | Batch size for current token balances fetcher. Implemented in [#13923](https://github.com/blockscout/blockscout/pull/13923). | Version: v10.0.0+
Default: `100`
Applications: Indexer | +| `INDEXER_CURRENT_TOKEN_BALANCES_CONCURRENCY` | Concurrency for current token balances fetcher. Implemented in [#13923](https://github.com/blockscout/blockscout/pull/13923). | Version: v10.0.0+
Default: `10`
Applications: Indexer | + + +### Deprecated ENV variables + +| Variable | Description | Default | Version | Deprecated in Version | +| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------------- | --------------------- | +| `CACHE_PBO_COUNT_PERIOD` | Time interval to restart the task which calculates the total pending_block_operations count. | `20m` | v5.2.0+ | | v10.0.0 | + + +## 9.3.7 + +### ⚙️ Miscellaneous Tasks + +- Allow disabling contract creation internal transaction association ([#14090](https://github.com/blockscout/blockscout/issues/14090), [#14097](https://github.com/blockscout/blockscout/pull/14097)) + + +## 9.3.6 + +### ⚡ Performance + +- Fix /advanced-filters timeout when scam filtering enabled ([#14047](https://github.com/blockscout/blockscout/pull/14047)) + + +## 9.3.5 + +### 🐛 Bug Fixes + +- Fix block reindex condition in ContractCreator on-demand ([#13831](https://github.com/blockscout/blockscout/issues/13831)) + + +## 9.3.4 + +### ⚡ Performance + +- Fix /token-transfers timeout when filtering scam tokens enabled ([#13973](https://github.com/blockscout/blockscout/pull/13973)) + + +## 9.3.3 + +### ⚙️ Miscellaneous Tasks + +- Replace ZeroValueDeleteQueue with filtering on import ([#13921](https://github.com/blockscout/blockscout/pull/13921), [#13947](https://github.com/blockscout/blockscout/pull/13947)) +- Allow to set IT storage period not only in days ([#13932](https://github.com/blockscout/blockscout/pull/13932)) + +### New ENV variables + +| Variable | Description | Parameters | +|---------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| +| `MIGRATION_DELETE_ZERO_VALUE_INTERNAL_TRANSACTIONS_STORAGE_PERIOD` | Specifies the period for which recent zero-value calls won't be deleted in delete zero-value calls migration. Implemented in [#13932](https://github.com/blockscout/blockscout/pull/13932). | Version: v9.3.3\+
Default: `30d`
Applications: Indexer | + +### Deprecated ENV variables + +| Variable | Description | Default | Version | Deprecated in Version | +|--------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|---------|-----------|-----------------------| +| `MIGRATION_DELETE_ZERO_VALUE_INTERNAL_TRANSACTIONS_STORAGE_PERIOD_DAYS` | Specifies the period for which recent zero-value calls won't be deleted in delete zero-value calls migration. | `30` | v9.3.0+ | v9.3.3 | + + +## 9.3.2 + +### 🐛 Bug Fixes + +- Handle_continue bad return value ([#13769](https://github.com/blockscout/blockscout/issues/13769)) +- Make `find_history_and_token_fetchers` public ([#13768](https://github.com/blockscout/blockscout/issues/13768)) +- Resolve TLS version issue on application startup ([#13767](https://github.com/blockscout/blockscout/issues/13767)) + +## 9.3.1 + +### 🐛 Bug Fixes + +- Fix blob transactions list API endpoint ([#13756](https://github.com/blockscout/blockscout/issues/13756)) + +## 9.3.0 + +### 🚀 Features + +- Update InternalTransactionsAddressPlaceholder upserts ([#13696](https://github.com/blockscout/blockscout/pull/13696)) +- Internal transactions on demand fetcher ([#13604](https://github.com/blockscout/blockscout/pull/13604)) +- Indexer config API endpoint ([#13679](https://github.com/blockscout/blockscout/pull/13679)) +- Add DIA market source ([#12678](https://github.com/blockscout/blockscout/issues/12678)) +- Add metadata to eth bytecode DB lookup request ([#13625](https://github.com/blockscout/blockscout/issues/13625)) +- Support ZRC-2 tokens for `zilliqa` chain type ([#13443](https://github.com/blockscout/blockscout/issues/13443)) +- Indexer monitor Prometheus metrics ([#13539](https://github.com/blockscout/blockscout/issues/13539), [#13668](https://github.com/blockscout/blockscout/pull/13668), [#13670](https://github.com/blockscout/blockscout/pull/13670)) +- Hot smart-contracts ([#13471](https://github.com/blockscout/blockscout/issues/13471), [#13669](https://github.com/blockscout/blockscout/pull/13669)) +- Support OP Jovian upgrade, other enhancements ([#13538](https://github.com/blockscout/blockscout/issues/13538)) +- Scope celo under optimism chain type ([#13375](https://github.com/blockscout/blockscout/issues/13375)) + +### 🐛 Bug Fixes + +- Fix tests for on-demand internal transaction fetcher ([#13744](https://github.com/blockscout/blockscout/pull/13744)) +- `batch_number` input param is now integer for OP and Scroll API endpoints ([#13727](https://github.com/blockscout/blockscout/pull/13727)) +- Set timeout: :infinity for delete zero value migration ([#13708](https://github.com/blockscout/blockscout/pull/13708)) +- Limit batch size for placeholders insertion ([#13699](https://github.com/blockscout/blockscout/pull/13699)) +- Add missed reputation fetch ([#13695](https://github.com/blockscout/blockscout/pull/13695)) +- Fix NFTMediaHandler postgres parameters overflow error ([#13694](https://github.com/blockscout/blockscout/pull/13694)) +- Add smart contract preload to hot contracts query ([#13691](https://github.com/blockscout/blockscout/pull/13691)) +- Restore fetcher name to dev console output ([#13681](https://github.com/blockscout/blockscout/pull/13681)) +- JSON RPC encoding for signed authorizations ([#13678](https://github.com/blockscout/blockscout/pull/13678)) +- Fix 500 for pending tx in tokentx RPC API endpoint ([#13666](https://github.com/blockscout/blockscout/pull/13666)) +- Fix 500 for pending tx in gettxinfo RPC API endpoint([#13665](https://github.com/blockscout/blockscout/pull/13665)) +- `Mix.env()` in `runtime.exs` ([#13641](https://github.com/blockscout/blockscout/issues/13641)) +- Celo aggregated election rewards migrator test ([#13639](https://github.com/blockscout/blockscout/issues/13639)) +- Fix filecoin web tests ([#13634](https://github.com/blockscout/blockscout/issues/13634)) +- Fix dialyzer test for filecoin chain type ([#13623](https://github.com/blockscout/blockscout/issues/13623)) +- Handle deposit status statement too complex ([#13588](https://github.com/blockscout/blockscout/issues/13588)) +- Beacon deposits: fallback to node ([#13425](https://github.com/blockscout/blockscout/issues/13425), [#13656](https://github.com/blockscout/blockscout/pull/13656)) +- Fix logic of disable token exchange rate ([#13414](https://github.com/blockscout/blockscout/issues/13414)) +- Null-checks for distribution field in celo epochs api ([#13457](https://github.com/blockscout/blockscout/issues/13457)) +- Reset ResetSanitizeDuplicatedLogsMigration status ([#13556](https://github.com/blockscout/blockscout/issues/13556)) +- Duplicated block numbers in int txs queue ([#13554](https://github.com/blockscout/blockscout/issues/13554)) +- Fix coin balance history - related normalize_balances_by_day/2 function ([#13515](https://github.com/blockscout/blockscout/issues/13515)) + +### 📚 Documentation + +- Update API endpoints descriptions in OpenAPI ([#13647](https://github.com/blockscout/blockscout/issues/13647)) + +### ⚡ Performance + +- Improve performance of api/v2/main-page/indexing-status endpoint ([#13730](https://github.com/blockscout/blockscout/pull/13730)) +- Implement celo aggregated election rewards ([#13418](https://github.com/blockscout/blockscout/issues/13418)) + +### ⚙️ Miscellaneous Tasks + +- GitHub Actions workflows: stop using ELIXIR_VERSION & OTP_VERSION from org/repo variables ([#13718](https://github.com/blockscout/blockscout/pull/13718)) +- Refactoring of the application mode config ([#13715](https://github.com/blockscout/blockscout/pull/13715)) +- Eliminate warnings in the Swagger file ([#13714](https://github.com/blockscout/blockscout/pull/13714)) +- Change URL to Solidity binaries list ([#13711](https://github.com/blockscout/blockscout/pull/13711)) +- Add osaka to the default list of supported EVM versions ([#13680](https://github.com/blockscout/blockscout/pull/13680)) +- Filter out empty addresses from multichain export ([#13674](https://github.com/blockscout/blockscout/pull/13674)) +- Validate NFT_MEDIA_HANDLER_BUCKET_FOLDER env ([#13671](https://github.com/blockscout/blockscout/pull/13671)) +- Enhance RPC API errors logging ([#13664](https://github.com/blockscout/blockscout/pull/13664)) +- Use chain id `31337` for `anvil` ([#13644](https://github.com/blockscout/blockscout/issues/13644)) +- Update devcontainer image to use Elixir 1.19.4 ([#13645](https://github.com/blockscout/blockscout/issues/13645)) +- Elixir 1.19.3 -> 1.19.4 ([#13643](https://github.com/blockscout/blockscout/issues/13643)) +- Update devcontainer image to use Elixir 1.19 ([#13637](https://github.com/blockscout/blockscout/issues/13637)) +- Internal transaction, Token transfer, Withdrawal, Smart-contracts, Main Page, Stats, Config and Search controllers OpenAPI specs ([#13557](https://github.com/blockscout/blockscout/issues/13557)) +- Using own runner for build ([#13624](https://github.com/blockscout/blockscout/issues/13624)) +- Drop token_instances_token_id_index index ([#13598](https://github.com/blockscout/blockscout/issues/13598)) +- Add migration to drop unique tokens_contract_address_hash_index index ([#13596](https://github.com/blockscout/blockscout/issues/13596), [#13655](https://github.com/blockscout/blockscout/pull/13655)) +- Elixir 1.17 -> 1.19 ([#13566](https://github.com/blockscout/blockscout/issues/13566)) +- Handle `NativeCoin*ed` events on Arc chain to make dual token balances synced ([#13452](https://github.com/blockscout/blockscout/issues/13452)) +- Improve DeleteZeroValueInternalTransactions migration ([#13569](https://github.com/blockscout/blockscout/issues/13569)) +- Remove address-related props from sending to multichain service ([#13584](https://github.com/blockscout/blockscout/issues/13584)) +- Move not auth cookies to headers ([#13478](https://github.com/blockscout/blockscout/issues/13478)) +- Transaction controller OpenAPI spec ([#13419](https://github.com/blockscout/blockscout/issues/13419)) +- Increase genesis file content fetch timeout ([#13527](https://github.com/blockscout/blockscout/issues/13527)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `INDEXER_DISABLE_HOT_SMART_CONTRACTS_FETCHER` | If `true`, `Indexer.Fetcher.Stats.HotSmartContracts` won't be started. Implemented in [#13471](https://github.com/blockscout/blockscout/pull/13471). | Version: v9.3.0\+
Default: `false`
Applications: Indexer | +| `MIGRATION_DELETE_ZERO_VALUE_INTERNAL_TRANSACTIONS_ENABLED` | Enable of delete zero-value calls migration. Implemented in [#13305](https://github.com/blockscout/blockscout/pull/13305). | Version: v9.3.0\+
Default: `false`
Applications: Indexer | +| `MIGRATION_DELETE_ZERO_VALUE_INTERNAL_TRANSACTIONS_BATCH_SIZE` | Specifies the block batch size selected for the delete zero-value calls migration. Implemented in [#13305](https://github.com/blockscout/blockscout/pull/13305). | Version: v9.3.0\+
Default: `100`
Applications: Indexer | +| `MIGRATION_DELETE_ZERO_VALUE_INTERNAL_TRANSACTIONS_STORAGE_PERIOD_DAYS` | Specifies the period for which recent zero-value calls won't be deleted in delete zero-value calls migration. Implemented in [#13305](https://github.com/blockscout/blockscout/pull/13305). | Version: v9.3.0\+
Default: `30`
Applications: Indexer | +| `MIGRATION_DELETE_ZERO_VALUE_INTERNAL_TRANSACTIONS_CHECK_INTERVAL` | Specifies the interval between checking of new zero-value calls to be deleted in delete zero-value calls migration. Implemented in [#13305](https://github.com/blockscout/blockscout/pull/13305). | Version: v9.3.0\+
Default: `1m`
Applications: Indexer | +| `MARKET_DIA_BLOCKCHAIN` | Sets DIA platform from https://www.diadata.org/docs/reference/apis/token-prices/api-endpoints/blockchains. Implemented in [#12678](https://github.com/blockscout/blockscout/pull/12678). | Version: v9.3.0\+
Default: (empty)
Applications: Indexer | +| `MARKET_DIA_BASE_URL` | If set, overrides the DIA API url. Implemented in [#12678](https://github.com/blockscout/blockscout/pull/12678). | Version: v9.3.0\+
Default: `https://api.diadata.org/v1`
Applications: API, Indexer | +| `MARKET_DIA_COIN_ADDRESS_HASH` | Sets address hash for native coin in DIA. Implemented in [#12678](https://github.com/blockscout/blockscout/pull/12678). | Version: v9.3.0\+
Default: (empty)
Applications: API | +| `MARKET_DIA_SECONDARY_COIN_ADDRESS_HASH` | Sets address hash for secondary coin in DIA. Implemented in [#12678](https://github.com/blockscout/blockscout/pull/12678). | Version: v9.3.0\+
Default: (empty)
Applications: API | +| `INDEXER_METRICS_ENABLED` | Flag to enable base indexer metrics. Implemented in [#13539](https://github.com/blockscout/blockscout/pull/13539). | Version: v9.3.0\+
Default: true
Applications: Indexer | +| `INDEXER_METRICS_ENABLED_TOKEN_INSTANCES_NOT_UPLOADED_TO_CDN_COUNT` | Flag to enable indexer metric: the count of token instances not uploaded to CDN. Implemented in [#13539](https://github.com/blockscout/blockscout/pull/13539). | Version: v9.3.0\+
Default: false
Applications: Indexer | +| `INDEXER_METRICS_ENABLED_FAILED_TOKEN_INSTANCES_METADATA_COUNT` | Flag to enable indexer metric: the count of token instances with failed metadata fetches. Implemented in [#13539](https://github.com/blockscout/blockscout/pull/13539). | Version: v9.3.0\+
Default: true
Applications: Indexer | +| `INDEXER_METRICS_ENABLED_UNFETCHED_TOKEN_INSTANCES_COUNT` | Flag to enable indexer metric: the count of token instances pending to fetch. Implemented in [#13539](https://github.com/blockscout/blockscout/pull/13539). | Version: v9.3.0\+
Default: true
Applications: Indexer | +| `INDEXER_METRICS_ENABLED_MISSING_CURRENT_TOKEN_BALANCES_COUNT` | Flag to enable indexer metric: the count of current token balances with missing values. Implemented in [#13539](https://github.com/blockscout/blockscout/pull/13539). | Version: v9.3.0\+
Default: true
Applications: Indexer | +| `INDEXER_METRICS_ENABLED_MISSING_ARCHIVAL_TOKEN_BALANCES_COUNT` | Flag to enable indexer metric: the count of archival token balances with missing values. Implemented in [#13539](https://github.com/blockscout/blockscout/pull/13539). | Version: v9.3.0\+
Default: true
Applications: Indexer | +| `INDEXER_OPTIMISM_L2_JOVIAN_TIMESTAMP` | Jovian upgrade L2 block timestamp. If set to `0`, the Jovian is assumed to be active from genesis block. Implemented in [#13538](https://github.com/blockscout/blockscout/pull/13538). | Version: v9.3.0+
Default: (empty)
Applications: API, Indexer | +| `INDEXER_ARC_NATIVE_TOKEN_DECIMALS` | Defines the number of decimals for Arc chain native token (e.g. USDC). Implemented in [#13452](https://github.com/blockscout/blockscout/pull/13452). | Version: v9.3.0+
Default: `6`
Applications: Indexer | +| `INDEXER_ARC_NATIVE_TOKEN_CONTRACT` | Arc chain native token contract address. Implemented in [#13452](https://github.com/blockscout/blockscout/pull/13452). | Version: v9.3.0+
Default: `0x3600000000000000000000000000000000000000`
Applications: Indexer | +| `INDEXER_ARC_NATIVE_TOKEN_SYSTEM_CONTRACT` | Arc chain system contract address emitting `NativeCoinTransferred` event. Implemented in [#13452](https://github.com/blockscout/blockscout/pull/13452). | Version: v9.3.0+
Default: `0x1800000000000000000000000000000000000000`
Applications: Indexer | + + +## 9.2.2 + +### 🐛 Bug Fixes + +- Fix next page params for tokens list API endpoint ([#13520](https://github.com/blockscout/blockscout/issues/13520)) + +## 9.2.1 + +### 🐛 Bug Fixes + +- Fix REST API token holders pagination ([#13500](https://github.com/blockscout/blockscout/issues/13500)) +- Add missing query binding to txlistinternal query ([#13479](https://github.com/blockscout/blockscout/issues/13479)) +- API v2 errors logging to the proper log file ([#13133](https://github.com/blockscout/blockscout/issues/13133)) + +### ⚙️ Miscellaneous Tasks + +- Silence multiple cspell complaints ([#13424](https://github.com/blockscout/blockscout/issues/13424)) + + +## 9.2.0 + +### 🚀 Features + +- distributed elixir runtime ([#13080](https://github.com/blockscout/blockscout/pull/13080)) +- Delete internal transactions on reorgs ([#13121](https://github.com/blockscout/blockscout/issues/13121)) +- Implement websocket endpoints support in the Universal Proxy config ([#13167](https://github.com/blockscout/blockscout/issues/13167)) +- Celo accounts api ([#12982](https://github.com/blockscout/blockscout/issues/12982)) +- Celo accounts indexing ([#12893](https://github.com/blockscout/blockscout/issues/12893)) +- OP operator fee indexing ([#13139](https://github.com/blockscout/blockscout/issues/13139)) +- Fields for OP Withdrawal Claim button ([#13272](https://github.com/blockscout/blockscout/issues/13272)) +- OP Alt-DA support for batch indexer ([#13179](https://github.com/blockscout/blockscout/issues/13179)) +- Add ci:core label ([#13249](https://github.com/blockscout/blockscout/issues/13249)) +- Initial support of indexing EigenDA-grounded Arbitrum batches ([#12915](https://github.com/blockscout/blockscout/issues/12915)) + +### 🐛 Bug Fixes + +- Fix token holders CSV export ([#13485](https://github.com/blockscout/blockscout/pull/13485)) +- ERC-1155 value in advanced filters csv ([#13474](https://github.com/blockscout/blockscout/pull/13474)) +- Fix /api/v2/tokens endpoints: allow back limit param ([#13473](https://github.com/blockscout/blockscout/pull/13473)) +- Incorrect average block time for sub-second blocks ([#13469](https://github.com/blockscout/blockscout/issues/13469)) +- Remove transaction_has_multiple_internal_transactions filter ([#13453](https://github.com/blockscout/blockscout/pull/13453)) +- celo accounts transformer ([#13423](https://github.com/blockscout/blockscout/pull/13423)) +- Fix broken txn batch blocks API endpoint ([#13438](https://github.com/blockscout/blockscout/pull/13438), [#13483](https://github.com/blockscout/blockscout/pull/13483)) +- Set timeout: :infinity for DeleteZeroValueInternalTransactions ([#13434](https://github.com/blockscout/blockscout/pull/13434)) +- Fix DeleteZeroValueInternalTransactions state keys ([#13431](https://github.com/blockscout/blockscout/pull/13431)) +- dump block_hash to binary when querying celo epoch distributions ([#13410](https://github.com/blockscout/blockscout/pull/13410)) +- Fix flaky indexer, web tests, refactoring ([#13392](https://github.com/blockscout/blockscout/issues/13392)) +- Advanced filters: ERC-20 value in CSV ([#13326](https://github.com/blockscout/blockscout/issues/13326)) +- Ignore old reorgs in beacon deposits fetcher ([#13372](https://github.com/blockscout/blockscout/issues/13372)) +- Update FUNDING.json ([#13399](https://github.com/blockscout/blockscout/issues/13399)) +- Add `log_index` field to celo validator group votes table ([#13391](https://github.com/blockscout/blockscout/issues/13391)) +- Add fallback to cached token counters in corresponding async tasks ([#13348](https://github.com/blockscout/blockscout/issues/13348)) +- Sanitize internal transaction error before insertion ([#13362](https://github.com/blockscout/blockscout/issues/13362)) +- Set skip metadata only on contract errors ([#12858](https://github.com/blockscout/blockscout/issues/12858)) +- Check if CoinBalance Realtime fetcher is disabled ([#13223](https://github.com/blockscout/blockscout/issues/13223)) +- Improve timeout exception definition ([#13286](https://github.com/blockscout/blockscout/issues/13286)) +- Enforce legacy query usage when sort by id ([#13323](https://github.com/blockscout/blockscout/issues/13323)) +- Fix web tests after hiding compile-time chain types routes ([#13324](https://github.com/blockscout/blockscout/issues/13324)) +- Hide compile-time chain type API routes in other chain type swaggers ([#13309](https://github.com/blockscout/blockscout/issues/13309)) +- Fix SanitizeDuplicatedLogIndexLogs migration completion check ([#13308](https://github.com/blockscout/blockscout/issues/13308)) + +### ⚡ Performance + +- Remove BENS preload from the main page API endpoints ([#13442](https://github.com/blockscout/blockscout/pull/13442), [#13449](https://github.com/blockscout/blockscout/pull/13449)) +- Batch preload token transfers in `/api/v2/celo/epochs` ([#13398](https://github.com/blockscout/blockscout/issues/13398)) +- Optimize token balance synchronous import steps ([#13217](https://github.com/blockscout/blockscout/issues/13217)) +- Optimize `EmptyBlocksSanitizer` queries ([#13132](https://github.com/blockscout/blockscout/issues/13132)) + +### ⚙️ Miscellaneous Tasks + +- add `CACHE_AVERAGE_BLOCK_TIME_WINDOW` ([#13470](https://github.com/blockscout/blockscout/pull/13470)) +- Improve DeleteZeroValueInternalTransactions future updating ([#13437](https://github.com/blockscout/blockscout/pull/13437)) +- advanced filters improvements ([#11909](https://github.com/blockscout/blockscout/pull/11909)) +- Allow api_key in the query string for api/v2/tokens/:address_hash/instances/refetch-metadata endpoint ([#13412](https://github.com/blockscout/blockscout/pull/13412)) +- *(ReindexDuplicatedInternalTransactions)* Optimize migration performance ([#13363](https://github.com/blockscout/blockscout/issues/13363)) +- OpenAPI spec for the REST API endpoints in token and CSV export controllers ([#13311](https://github.com/blockscout/blockscout/issues/13311)) +- Edited the broken Discord badge ([#13115](https://github.com/blockscout/blockscout/issues/13115)) +- OpenAPI spec for the REST API block controller ([#13274](https://github.com/blockscout/blockscout/issues/13274)) +- Add PR title conventional commit check workflow ([#13238](https://github.com/blockscout/blockscout/issues/13238)) +- Add label for running tests with enabled bridged tokens ([#13263](https://github.com/blockscout/blockscout/issues/13263)) +- Phoenix update ([#13147](https://github.com/blockscout/blockscout/issues/13147)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `INDEXER_EMPTY_BLOCKS_SANITIZER_HEAD_OFFSET` | Minimal age for block to be processed by empty block sanitizer. Implemented in [#13132](https://github.com/blockscout/blockscout/pull/13132) | Version: v9.2.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_INTERNAL_TRANSACTIONS_DELETE_QUEUE_BATCH_SIZE` | Batch size for internal transactions delete queue handler. Implemented in [#13121](https://github.com/blockscout/blockscout/pull/13121). | Version: v9.2.0\+
Default: `100`
Applications: Indexer | +| `INDEXER_INTERNAL_TRANSACTIONS_DELETE_QUEUE_CONCURRENCY` | Concurrency for internal transactions delete queue handler. Implemented in [#13121](https://github.com/blockscout/blockscout/pull/13121). | Version: v9.2.0\+
Default: `1`
Applications: Indexer | +| `INDEXER_INTERNAL_TRANSACTIONS_DELETE_QUEUE_THRESHOLD` | Threshold for internal transactions delete queue handler. Implemented in [#13121](https://github.com/blockscout/blockscout/pull/13121). | Version: v9.2.0\+
Default: `10m`
Applications: Indexer | +| `INDEXER_OPTIMISM_L1_BATCH_ALT_DA_SERVER_URL` | Defines a URL to Alt-DA server to retrieve L1 data from that. Example for Redstone: `https://da.redstonechain.com/get`. Implemented in [#13179](https://github.com/blockscout/blockscout/pull/13179). | Version: v9.2.0+
Default: (empty)
Applications: Indexer | +| `INDEXER_OPTIMISM_L2_ISTHMUS_TIMESTAMP` | Isthmus upgrade L2 block timestamp. Needed for operator fee determining. If set to `0`, the Isthmus is assumed to be active from genesis block. Implemented in [#13139](https://github.com/blockscout/blockscout/pull/13139). | Version: v9.2.0+
Default: (empty)
Applications: API, Indexer | +| `INDEXER_OPTIMISM_OPERATOR_FEE_QUEUE_BATCH_SIZE` | Batch size for OP operator fee fetcher. Defines max number of transactions handled per batch. Implemented in [#13139](https://github.com/blockscout/blockscout/pull/13139). | Version: v9.2.0\+
Default: `100`
Applications: Indexer | +| `INDEXER_OPTIMISM_OPERATOR_FEE_QUEUE_CONCURRENCY` | Concurrency for OP operator fee fetcher. Implemented in [#13139](https://github.com/blockscout/blockscout/pull/13139). | Version: v9.2.0\+
Default: `3`
Applications: Indexer | +| `INDEXER_OPTIMISM_OPERATOR_FEE_QUEUE_ENQUEUE_BUSY_WAITING_TIMEOUT` | Timeout before new attempt to append item to OP operator fee fetcher queue if it's full. [Time format](backend-env-variables.md#time-format). Implemented in [#13139](https://github.com/blockscout/blockscout/pull/13139). | Version: v9.2.0\+
Default: `1s`
Applications: Indexer | +| `INDEXER_OPTIMISM_OPERATOR_FEE_QUEUE_MAX_QUEUE_SIZE` | Maximum size of OP operator fee fetcher queue. Implemented in [#13139](https://github.com/blockscout/blockscout/pull/13139). | Version: v9.2.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_OPTIMISM_OPERATOR_FEE_QUEUE_INIT_QUERY_LIMIT` | Limit of the init query for processing the OP operator fee fetcher queue. Implemented in [#13139](https://github.com/blockscout/blockscout/pull/13139). | Version: v9.2.0\+
Default: `1000`
Applications: Indexer | +| `CELO_LOCKED_GOLD_CONTRACT` | The address of the `LockedGold` core contract. Implemented in [#12893](https://github.com/blockscout/blockscout/pull/12893). | Version: v9.2.0+
Default: (empty)
Applications: Indexer | +| `CELO_ACCOUNTS_CONTRACT` | The address of the `Accounts` core contract. Implemented in [#12893](https://github.com/blockscout/blockscout/pull/12893). | Version: v9.2.0+
Default: (empty)
Applications: Indexer | +| `INDEXER_CELO_ACCOUNTS_CONCURRENCY` | Sets the maximum number of concurrent requests for fetching Celo accounts. | Version: v9.2.0+
Default: `1`
Applications: Indexer | +| `INDEXER_CELO_ACCOUNTS_BATCH_SIZE` | Specifies the number of account addresses processed per batch during fetching. | Version: v9.2.0+
Default: `100`
Applications: Indexer | +| `K8S_SERVICE` | Kubernetes service name for Elixir nodes clusterization, more info on how to configure it can be found here https://hexdocs.pm/libcluster/Cluster.Strategy.Kubernetes.DNS.html. Implemented in [#13080](https://github.com/blockscout/blockscout/pull/13080). | Version: v9.2.0\+
Default: (empty)
Applications: API, Indexer | +| `CACHE_AVERAGE_BLOCK_TIME_WINDOW` | The number of blocks to be taken into account in the calculations. Introduced in [#13470](https://github.com/blockscout/blockscout/pull/13470). | Version: v9.2.0\+
Default: `100`
Applications: API, Indexer | + +### Deprecated ENV variables + +| Variable | Description | Default | Version | Deprecated in Version | +| ----------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------------- | --------------------- | +| `NFT_MEDIA_HANDLER_NODES_MAP` | String in json map format, where key is erlang node and value is folder in R2/S3 bucket, example: `"{\"producer@172.18.0.4\": \"/folder_1\"}"`. If nft_media_handler runs in one pod with indexer, map should contain `self` key | | v6.10.0+ | v9.2.0+ | + + +## 9.1.1 + +### 🚀 Features + +- Auto assert_schema in tests ([#13029](https://github.com/blockscout/blockscout/issues/13029)) + +### 🐛 Bug Fixes + +- Fix token transfer test for celo ([#13250](https://github.com/blockscout/blockscout/pull/13250)) +- Add reputation preload to celo base fee ([#13248](https://github.com/blockscout/blockscout/pull/13248)) +- Add reputation preload for user op body for transaction interpreter ([#13241](https://github.com/blockscout/blockscout/pull/13241)) +- Fix condition in Indexer.Fetcher.OnDemand.TokenTotalSupply fetcher ([#13240](https://github.com/blockscout/blockscout/pull/13240)) +- Add reputation preload to state changes and bridged tokens ([#13235](https://github.com/blockscout/blockscout/pull/13235)) +- Soften deposits deletion condition ([#13234](https://github.com/blockscout/blockscout/pull/13234)) +- Fix logic of checking finishing of heavy DB index operation ([#13231](https://github.com/blockscout/blockscout/pull/13231)) +- some flapping explorer/indexer tests ([#13230](https://github.com/blockscout/blockscout/pull/13230)) +- Remove requirement for beacon deposit indexes to be sequential ([#13228](https://github.com/blockscout/blockscout/pull/13228)) + +### ⚡ Performance + +- Improve perf of internal transactions retrieval from the DB ([#13232](https://github.com/blockscout/blockscout/pull/13232)) + +### ⚙️ Miscellaneous Tasks + +- Fix tests ([#13244](https://github.com/blockscout/blockscout/pull/13244)) +- Do not modify deposit indexer state on reorgs ([#13236](https://github.com/blockscout/blockscout/pull/13236)) +- Refactoring reputation ([#13221](https://github.com/blockscout/blockscout/issues/13221)) + +## 9.1.0 + +### 🚀 Features + +- beacon deposits ([#12985](https://github.com/blockscout/blockscout/pull/12985)) +- on-demand bytecode fetching on smart contract verification requests ([#10724](https://github.com/blockscout/blockscout/issues/10724)) +- Improved proxy detection ([#12846](https://github.com/blockscout/blockscout/issues/12846)) +- Add `reputation` property where applicable ([#13070](https://github.com/blockscout/blockscout/issues/13070)) +- Add envs to configure RemoteIp lib usage ([#13082](https://github.com/blockscout/blockscout/issues/13082)) +- Add possibility to forward event notification to another DB ([#13064](https://github.com/blockscout/blockscout/issues/13064)) +- Add x-api-key header ([#13076](https://github.com/blockscout/blockscout/issues/13076)) +- Add token_type to token transfer API response ([#13038](https://github.com/blockscout/blockscout/issues/13038)) +- Export main page counters to Multichain service ([#13007](https://github.com/blockscout/blockscout/issues/13007)) +- Add methodId to txlist rpc method ([#13043](https://github.com/blockscout/blockscout/issues/13043)) +- Runtime config option to disable file logging ([#12805](https://github.com/blockscout/blockscout/issues/12805)) +- Add celo-specific APIv1 `getepoch` action ([#12853](https://github.com/blockscout/blockscout/issues/12853)) + +### 🐛 Bug Fixes + +- Fix errors in celo epochs endpoints([#13201](https://github.com/blockscout/blockscout/pull/13201)) +- Fix api/v2/addresses/{hash}/celo/election-rewards pagination ([#13215](https://github.com/blockscout/blockscout/pull/13215)) +- Add reputation preload for celo gas_token ([#13200](https://github.com/blockscout/blockscout/pull/13200)) +- Mark completed deposits in batches ([#13210](https://github.com/blockscout/blockscout/pull/13210)) +- Adjustments in address nft and collections endpoints ([#13192](https://github.com/blockscout/blockscout/pull/13192)) +- Fix batch's number processing from the socket event ([#13181](https://github.com/blockscout/blockscout/pull/13181)) +- Delete PTOs for forked transactions ([#13145](https://github.com/blockscout/blockscout/pull/13145)) +- Pagination and filtering issues in `/addresses/:hash/nft` ([#13175](https://github.com/blockscout/blockscout/pull/13175)) +- Fix reputation preload for ERC-404 collections ([#13174](https://github.com/blockscout/blockscout/pull/13174)) +- Add reputation to token, rework reputation preload ([#13149](https://github.com/blockscout/blockscout/pull/13149)) +- Replace get_constant_by_key with get_constant_value in get_last_processed_token_address_hash ([#13118](https://github.com/blockscout/blockscout/issues/13118)) +- Duplicates of smart contracts additional sources ([#13018](https://github.com/blockscout/blockscout/issues/13018)) +- Set for read ops in NFT backfillers ([#13116](https://github.com/blockscout/blockscout/issues/13116)) +- Return internal transactions for consensus blocks only in /api/v2/internal-transactions ([#13041](https://github.com/blockscout/blockscout/issues/13041)) +- Fix recv timeout option in Universal proxy config ([#13046](https://github.com/blockscout/blockscout/issues/13046)) +- Fix failing ETH RPC tests ([#13099](https://github.com/blockscout/blockscout/issues/13099)) +- Escape only significant characters in tokens ([#13078](https://github.com/blockscout/blockscout/issues/13078)) +- `/api/v2/addresses/:hash/token-transfers` returns 500 on celo ([#13050](https://github.com/blockscout/blockscout/issues/13050)) +- RuntimeEnvHelper usage in Auth0.Migrated ([#13075](https://github.com/blockscout/blockscout/issues/13075)) +- Fix no function clause matching in Explorer.Chain.Transaction.decoded_input_data/5 ([#13055](https://github.com/blockscout/blockscout/issues/13055)) +- Fix Postgres errors in Explorer.Migrator.BackfillMetadataURL ([#13063](https://github.com/blockscout/blockscout/issues/13063)) +- Fix multichain search queue export bug processing ([#13049](https://github.com/blockscout/blockscout/issues/13049)) +- Csv export for celo l2 epoch rewards on address ([#12815](https://github.com/blockscout/blockscout/issues/12815)) +- Change signed_authorizations chain_id type to numeric ([#13042](https://github.com/blockscout/blockscout/issues/13042)) +- Address api spec for `filecoin` and `zilliqa` chain types ([#12996](https://github.com/blockscout/blockscout/issues/12996)) +- Token type filtering to support multiple types with OR logic ([#13008](https://github.com/blockscout/blockscout/issues/13008)) +- Don't validate address hash for common blocks channels ([#13020](https://github.com/blockscout/blockscout/issues/13020)) +- Fix matching in current token balances import filter ([#12930](https://github.com/blockscout/blockscout/issues/12930)) +- Expand indexer timeout exception definition ([#12748](https://github.com/blockscout/blockscout/issues/12748)) + +### 🚜 Refactor + +- Remove public tags request functionality ([#13006](https://github.com/blockscout/blockscout/issues/13006)) + +### ⚡ Performance + +- Optimize maybe_hide_scam_addresses/3 query ([#12927](https://github.com/blockscout/blockscout/issues/12927)) +- Fix perf of finding non pending block in internal transactions related queries ([#13189](https://github.com/blockscout/blockscout/pull/13189)) +- Internal transactions REST API endpoint perf tradeoff ([#13191](https://github.com/blockscout/blockscout/pull/13191)) + +### ⚙️ Miscellaneous Tasks + +- Remove quantile_estimator dep ([#13190](https://github.com/blockscout/blockscout/pull/13190)) +- Add support of Scroll codecv8 ([#13090](https://github.com/blockscout/blockscout/pull/13090)) +- Change release workflow ([#13087](https://github.com/blockscout/blockscout/issues/13087)) +- Add INDEXER_DISABLE_OPTIMISM_INTEROP_MULTICHAIN_EXPORT env variable ([#13051](https://github.com/blockscout/blockscout/pull/13051)) +- Update and format pull request template ([#13028](https://github.com/blockscout/blockscout/issues/13028)) +- Add final check for ReindexDuplicatedInternalTransactions ([#13091](https://github.com/blockscout/blockscout/issues/13091)) +- Remove obsolete circleci config ([#13097](https://github.com/blockscout/blockscout/issues/13097)) +- Replace ReindexDuplicatedInternalTransactions grouping field ([#13084](https://github.com/blockscout/blockscout/issues/13084)) +- Bump default rps to 5 ([#13089](https://github.com/blockscout/blockscout/issues/13089)) +- Add `is_pending_update` flag to block and transaction API endpoints ([#13013](https://github.com/blockscout/blockscout/issues/13013)) +- Bump actions major versions ([#13077](https://github.com/blockscout/blockscout/issues/13077)) +- Move token transfers to a separate event handler ([#13068](https://github.com/blockscout/blockscout/issues/13068)) +- Remove Polygon Edge modules and chain type ([#13056](https://github.com/blockscout/blockscout/issues/13056)) +- Cover token info export to Multichain service by unit tests ([#12899](https://github.com/blockscout/blockscout/issues/12899)) +- Route left API DB requests from master to read DB replica ([#12896](https://github.com/blockscout/blockscout/issues/12896)) +- Refactor usage of delete_parameters_from_next_page_params/1 ([#13005](https://github.com/blockscout/blockscout/issues/13005)) +- Move address nonce updating to a separate process ([#12941](https://github.com/blockscout/blockscout/issues/12941)) +- Catchup fetcher various improvements ([#12866](https://github.com/blockscout/blockscout/issues/12866)) +- Add disconnect_on_error_codes param to repo config ([#12800](https://github.com/blockscout/blockscout/issues/12800)) +- Move addresses to a separate import stage ([#12857](https://github.com/blockscout/blockscout/issues/12857)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `DISABLE_FILE_LOGGING` | Disables file-based logging when set to `true`. When enabled, application logs will only be written to stdout/stderr. | Version: v9.1.0\+
Default: `false`
Applications: API, Indexer | +| `API_RATE_LIMIT_REMOTE_IP_HEADERS` | Comma separated list of HTTP headers to extract the real client IP address when Blockscout is behind a proxy for rate limiting purposes. Implemented in [#12386](https://github.com/blockscout/blockscout/pull/13082) | Version: v9.1.0\+
Default: `x-forwarded-for`
Applications: API | +| `API_RATE_LIMIT_REMOTE_IP_KNOWN_PROXIES` | Comma separated list of trusted proxy IP addresses or CIDR ranges that are allowed to set the client IP headers for rate limiting. Implemented in [#12386](https://github.com/blockscout/blockscout/pull/13082) | Version: v9.1.0\+
Default: `(empty)`
Applications: API | +| `INDEXER_DISABLE_OPTIMISM_INTEROP_MULTICHAIN_EXPORT` | Disables exporting of interop messages to Multichain service. Implemented in [#13051](https://github.com/blockscout/blockscout/pull/13051). | Version: v9.1.0\+
Default: `true`
Applications: Indexer | +| `MICROSERVICE_MULTICHAIN_SEARCH_COUNTERS_CHUNK_SIZE` | Chunk size of counters while exporting to Multichain Search DB. Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_DISABLE_MULTICHAIN_SEARCH_DB_EXPORT_COUNTERS_QUEUE_FETCHER` | If `true`, multichain DB counters export fetcher doesn't run. Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `false`
Applications: Indexer | +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_COUNTERS_QUEUE_BATCH_SIZE` | Batch size for multichain DB counters export fetcher. Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_COUNTERS_QUEUE_CONCURRENCY` | Concurrency for multichain DB counters export fetcher. Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `10`
Applications: Indexer | +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_COUNTERS_QUEUE_ENQUEUE_BUSY_WAITING_TIMEOUT` | Timeout before new attempt to append item to multichain DB counters export queue if it's full. [Time format](backend-env-variables.md#time-format). Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `1s`
Applications: Indexer | +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_COUNTERS_QUEUE_MAX_QUEUE_SIZE` | Maximum size of multichain DB counters export queue. Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_COUNTERS_QUEUE_INIT_QUERY_LIMIT` | Limit of the init query for processing the counters export queue to the Multichain DB. Implemented in [#13007](https://github.com/blockscout/blockscout/pull/13007). | Version: v9.1.0\+
Default: `1000`
Applications: Indexer | +| `INDEXER_DISABLE_BEACON_DEPOSIT_FETCHER` | If `true`, the Beacon deposit fetcher won't be started. Implemented in [#12985](https://github.com/blockscout/blockscout/pull/12985). | Version: v9.1.0+
Default: `false`
Applications: Indexer | +| `INDEXER_BEACON_DEPOSIT_FETCHER_INTERVAL` | The interval indicating how often deposit events should be queried. [Time format](/setup/env-variables/backend-envs-chain-specific#time-format). Implemented in [#12985](https://github.com/blockscout/blockscout/pull/12985). | Version: v9.1.0+
Default: `6s`
Applications: Indexer | +| `INDEXER_BEACON_DEPOSIT_FETCHER_BATCH_SIZE` | The batch size specifies how many events are retrieved in a single database query. Implemented in [#12985](https://github.com/blockscout/blockscout/pull/12985). | Version: v9.1.0+
Default: `1000`
Applications: Indexer | +| `INDEXER_DISABLE_BEACON_DEPOSIT_STATUS_FETCHER` | If `true`, the Beacon deposit status fetcher won't be started. Implemented in [#12985](https://github.com/blockscout/blockscout/pull/12985). | Version: v9.1.0+
Default: `false`
Applications: Indexer | +| `INDEXER_BEACON_DEPOSIT_STATUS_FETCHER_EPOCH_DURATION` | Epoch duration in the Beacon chain in seconds. Implemented in [#12985](https://github.com/blockscout/blockscout/pull/12985). | Version: v9.1.0+
Default: `384`
Applications: Indexer | +| `INDEXER_BEACON_DEPOSIT_STATUS_FETCHER_REFERENCE_TIMESTAMP` | Any past finalized Beacon Chain epoch UTC timestamp. Used as reference for status fetcher scheduling. Implemented in [#12985](https://github.com/blockscout/blockscout/pull/12985). | Version: v9.1.0+
Default: `1722024023`
Applications: Indexer | + + +### Deprecated ENV variables + +| Variable | Required | Description | Default | Version | Need recompile | Deprecated in Version | +| ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | -------------- | --------------------- | +| `INDEXER_POLYGON_EDGE_L1_RPC` | The RPC endpoint for L1 used to fetch deposit or withdrawal events. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L1_EXIT_HELPER_CONTRACT` | The address of ExitHelper contract on L1 (root chain) used to fetch withdrawal exits. Required for withdrawal events indexing. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L1_WITHDRAWALS_START_BLOCK` | The number of start block on L1 (root chain) to index withdrawal exits. If the table of withdrawal exits is not empty, the process will continue indexing from the last indexed message. If empty or not defined, the withdrawal exits are not indexed. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L1_STATE_SENDER_CONTRACT` | The address of StateSender contract on L1 (root chain) used to fetch deposits. Required for deposit events indexing. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L1_DEPOSITS_START_BLOCK` | The number of start block on L1 (root chain) to index deposits. If the table of deposits is not empty, the process will continue indexing from the last indexed message. If empty or not defined, the deposits are not indexed. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L2_STATE_SENDER_CONTRACT` | The address of L2StateSender contract on L2 (child chain) used to fetch withdrawals. Required for withdrawal events indexing. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L2_WITHDRAWALS_START_BLOCK` | The number of start block on L2 (child chain) to index withdrawals. If the table of withdrawals is not empty, the process will fill gaps and then continue indexing from the last indexed message. If empty or not defined, the withdrawals are not indexed. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L2_STATE_RECEIVER_CONTRACT` | The address of StateReceiver contract on L2 (child chain) used to fetch deposit executes. Required for deposit events indexing. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_L2_DEPOSITS_START_BLOCK` | The number of start block on L2 (child chain) to index deposit executes. If the table of deposit executes is not empty, the process will fill gaps and then continue indexing from the last indexed message. If empty or not defined, the deposit executes are not indexed. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `INDEXER_POLYGON_EDGE_ETH_GET_LOGS_RANGE_SIZE` | Block range size for eth\_getLogs request in Polygon Edge indexer modules. Implemented in [#8180](https://github.com/blockscout/blockscout/pull/8180). | | v5.3.0+ | | v9.1.0 | +| `ACCOUNT_PUBLIC_TAGS_AIRTABLE_URL` | Airtable URL for public tag requests functionality | | v5.0.0+ | | v9.1.0 | +| `ACCOUNT_PUBLIC_TAGS_AIRTABLE_API_KEY` | Airtable API key for public tag requests functionality | | v5.0.0+ | | v9.1.0 | + + +## 9.0.2 + +### 🐛 Bug Fixes + +- atoms in token_transfers_next_page_params ([#12992](https://github.com/blockscout/blockscout/pull/12992)) +- Fix Mud worlds API endpoint ([#12991](https://github.com/blockscout/blockscout/pull/12991)) +- Set 5 RPS for api/health/* ([#12990]https://github.com/blockscout/blockscout/pull/12990) +- Pagination with atoms in paging_params ([#12986](https://github.com/blockscout/blockscout/issues/12986)) +- Fix RangesHelper.sanitize_ranges for empty list ([#12946](https://github.com/blockscout/blockscout/issues/12946)) +- Remove apikey from next_page_params ([#12972](https://github.com/blockscout/blockscout/issues/12972)) + +## 9.0.1 + +### ⚙️ Miscellaneous Tasks + +- Restore `getblocknobytime` response format to use `blockNumber` key ([#12955](https://github.com/blockscout/blockscout/issues/12955)) + +## 9.0.0 + +### 🚀 Features + +- Export token info to Multichain service ([#12867](https://github.com/blockscout/blockscout/pull/12867)) +- Export balances to Multichain DB([#12726](https://github.com/blockscout/blockscout/pull/12726)) +- Add eip7702 authorization status fetcher ([#12451](https://github.com/blockscout/blockscout/issues/12451)) +- Add token1155tx token404tx api v1 endpoints ([#12720](https://github.com/blockscout/blockscout/issues/12720)) +- Async multichain data export ([#12490](https://github.com/blockscout/blockscout/issues/12490)) +- Rate limits refactoring ([#12386](https://github.com/blockscout/blockscout/issues/12386)) +- Integrate Open API Spex lib ([#11886](https://github.com/blockscout/blockscout/issues/11886)) +- Update CodeQL action to v3 ([#12697](https://github.com/blockscout/blockscout/issues/12697)) ([#12703](https://github.com/blockscout/blockscout/issues/12703)) +- Support merged tenants ([#12109](https://github.com/blockscout/blockscout/issues/12109)) +- Support ethereum pre-deploy contracts ([#12579](https://github.com/blockscout/blockscout/issues/12579)) +- Add `creation_status` field to address response ([#12660](https://github.com/blockscout/blockscout/issues/12660)) +- Decode OP interop message payload, store cross-chain transfer data, display message page, send messages to Multichain ([#12387](https://github.com/blockscout/blockscout/issues/12387)) +- Celo l2 epochs ([#12373](https://github.com/blockscout/blockscout/issues/12373)) +- Add `/api/v2/config/celo` convenience endpoint ([#12238](https://github.com/blockscout/blockscout/issues/12238)) + +### 🐛 Bug Fixes + +- Ignore rate limit for api/v2/import/token-info and api/v2/import/smart-contracts/:param ([#12917](https://github.com/blockscout/blockscout/pull/12917)) +- Mitigate deadlocks while exporting balances and the main queue to the Multichain DB ([#12898](https://github.com/blockscout/blockscout/pull/12898), [#12928](https://github.com/blockscout/blockscout/pull/12928)) +- Balances export queue: replace replace_all with replace only value and updated_at ([#12892](https://github.com/blockscout/blockscout/pull/12892)) +- Fix naming for apikey param in OpenAPI spec ([#12891](https://github.com/blockscout/blockscout/pull/12891)) +- Don't send coin balances with zero delta via ws ([#12890](https://github.com/blockscout/blockscout/pull/12890)) +- Balances export queue to multichain replace do_nothing with replace_all on insertion to the queue ([#12888](https://github.com/blockscout/blockscout/pull/12888)) +- Allow using temporary token for api/account/v2 by default ([#12869](https://github.com/blockscout/blockscout/pull/12869)) +- Fix increment of retries_number in exporting data to Multichain DB ([#12847](https://github.com/blockscout/blockscout/pull/12847)) +- Fix various errors on export of balances to Multichain DB ([#12837](https://github.com/blockscout/blockscout/pull/12837)) +- Reject empty token_id and value in export of token balances to the Multichain DB ([#12829](https://github.com/blockscout/blockscout/pull/12829)) +- Fix multichain export queues processing ([#12822](https://github.com/blockscout/blockscout/pull/12822)) +- Remove token_id parameter from coin balance payload to Multichain service API endpoint ([#12817](https://github.com/blockscout/blockscout/pull/12817)) +- Sanitize empty block_ranges payload before sending HTTP request to Multichain service([#12816](https://github.com/blockscout/blockscout/pull/12816)) +- Disable Indexer.Fetcher.Optimism.Interop.MultichainExport for non-OP chains ([#12814](https://github.com/blockscout/blockscout/pull/12814)) +- Fix flaky test for exporting balances to Multichain DB ([#12813](https://github.com/blockscout/blockscout/pull/12813)) +- Filter out creation internal transaction with `index == 0` ([#12777](https://github.com/blockscout/blockscout/issues/12777)) +- Filter out scilla transactions in internal transactions fetcher ([#12793](https://github.com/blockscout/blockscout/issues/12793)) +- Change default ordering in `/api/v2/smart-contracts` ([#12767](https://github.com/blockscout/blockscout/issues/12767)) +- Filter scilla transactions by status ([#12756](https://github.com/blockscout/blockscout/issues/12756)) +- Fix timeout on cache update ([#12773](https://github.com/blockscout/blockscout/issues/12773)) +- Error on too big block numbers in APIv1 `txlist` method ([#12727](https://github.com/blockscout/blockscout/issues/12727)) +- Fix CSV export tests ([#12744](https://github.com/blockscout/blockscout/issues/12744)) +- Fix race condition for EventNotification ([#12738](https://github.com/blockscout/blockscout/issues/12738)) +- Multichain retry hex decoding ([#12742](https://github.com/blockscout/blockscout/issues/12742)) +- Internal transactions balance extraction ([#12654](https://github.com/blockscout/blockscout/issues/12654)) +- Multichain search export: retry only on failed chunks ([#12459](https://github.com/blockscout/blockscout/issues/12459)) +- Display correct OP Deposit origin address ([#12672](https://github.com/blockscout/blockscout/issues/12672)) +- Store blocks_validated in DB for Stability Validators ([#12540](https://github.com/blockscout/blockscout/issues/12540)) +- `MarketHistory` on conflict clause ([#12541](https://github.com/blockscout/blockscout/issues/12541)) +- Flaky 404 in `/api/v2/internal-transactions` ([#12701](https://github.com/blockscout/blockscout/issues/12701)) +- CryptoRank integration ([#12523](https://github.com/blockscout/blockscout/issues/12523)) +- Fix timeout on fetching address internal transactions ([#12570](https://github.com/blockscout/blockscout/issues/12570)) +- Coin balance history with internal tx changes ([#12631](https://github.com/blockscout/blockscout/issues/12631)) +- Update all block fields on conflict ([#12418](https://github.com/blockscout/blockscout/issues/12418)) +- Fix pending transactions sanitizer ([#12559](https://github.com/blockscout/blockscout/issues/12559)) +- Don't send logs without topic to sig provider ([#12620](https://github.com/blockscout/blockscout/issues/12620)) +- Add missing fields to Celo Epochs-related endpoints ([#12589](https://github.com/blockscout/blockscout/issues/12589)) +- Correctly use Geth importer for Besu genesis file. ([#12466](https://github.com/blockscout/blockscout/issues/12466)) ([#12686](https://github.com/blockscout/blockscout/issues/12686)) +- Ignore unknown type txs in gas price oracle ([#12613](https://github.com/blockscout/blockscout/issues/12613)) +- Resolve timeouts on Celo epoch reward contract reads ([#12229](https://github.com/blockscout/blockscout/issues/12229)) +- Prevent constant refetching of celo epoch blocks ([#12498](https://github.com/blockscout/blockscout/issues/12498)) +- Fix typo in ondemand token balance request ([#12495](https://github.com/blockscout/blockscout/issues/12495)) +- Fix for `add_0x_prefix` function ([#12514](https://github.com/blockscout/blockscout/issues/12514)) + +### ⚡ Performance + +- Api v1 `txlist`& `txlistinternal` endpoints ([#12774](https://github.com/blockscout/blockscout/issues/12774)) +- Optimize Explorer.Chain.Cache.Blocks ([#12402](https://github.com/blockscout/blockscout/issues/12402)) + +### ⚙️ Miscellaneous Tasks + +- Remove obsolete API response props ([#12931](https://github.com/blockscout/blockscout/pull/12931)) +- Balances Multichain export: Refactor rows acquisition for deletion query ([#12839](https://github.com/blockscout/blockscout/pull/12839)) +- Change name of Swagger generation workflow ([#12840](https://github.com/blockscout/blockscout/pull/12840)) +- migrate Auth0 to mint as well ([#12807](https://github.com/blockscout/blockscout/pull/12807)) +- Migrate from HTTPoison to Tesla.Mint ([#12699](https://github.com/blockscout/blockscout/pull/12699)) +- Merge adjacent missing block ranges ([#12778](https://github.com/blockscout/blockscout/issues/12778)) +- Optimize missing block ranges operations ([#12705](https://github.com/blockscout/blockscout/issues/12705)) +- Hold parity with Etherscan APIv1 for `getcontractcreation` and `getblocknobytime` endpoints ([#12721](https://github.com/blockscout/blockscout/issues/12721)) +- Allow resending reindexed OP interop messages to Multichain service ([#12626](https://github.com/blockscout/blockscout/issues/12626)) +- Duplicate block countdown endpoint in API v2 ([#12704](https://github.com/blockscout/blockscout/issues/12704)) +- Revise Explorer.Helper.add_0x_prefix usage ([#12543](https://github.com/blockscout/blockscout/issues/12543)) +- New tac microservice endpoint for search ([#12448](https://github.com/blockscout/blockscout/issues/12448)) +- Add filter for value > 0 to txlistinternal ([#12679](https://github.com/blockscout/blockscout/issues/12679)) +- Optimize realtime events notifier ([#12494](https://github.com/blockscout/blockscout/issues/12494)) +- Drop address_coin_balances value_fetched_at index ([#12598](https://github.com/blockscout/blockscout/issues/12598)) +- Update deprecated address to address_hash in tx summary response ([#12617](https://github.com/blockscout/blockscout/issues/12617)) +- Remove redundant word in comment ([#12603](https://github.com/blockscout/blockscout/issues/12603)) +- Move background migrations under indexer mode ([#12480](https://github.com/blockscout/blockscout/issues/12480)) +- Support multiple interop messages view on transaction page ([#12455](https://github.com/blockscout/blockscout/issues/12455)) +- Remove `is_self_destructed` field in `/api/v2/smart-contracts/{address_hash}` response ([#12239](https://github.com/blockscout/blockscout/issues/12239)) +- Set home directory for blockscout user ([#12337](https://github.com/blockscout/blockscout/issues/12337)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `INDEXER_DB_EVENT_NOTIFICATIONS_CLEANUP_ENABLED` | If `true`, `Indexer.Utils.EventNotificationsCleaner` process starts. Implemented in [#12738](https://github.com/blockscout/blockscout/pull/12738) |

Version: v9.0.0+
Default: true
Applications: Indexer

| +| `INDEXER_DB_EVENT_NOTIFICATIONS_CLEANUP_INTERVAL` | Interval between DB event notifications cleanup. [Time format](backend-env-variables.md#time-format). Implemented in [#12738](https://github.com/blockscout/blockscout/pull/12738) |

Version: v9.0.0+
Default: 2m
Applications: Indexer

| +| `INDEXER_DB_EVENT_NOTIFICATIONS_CLEANUP_MAX_AGE` | Max age of DB event notifications before they are cleaned up. [Time format](backend-env-variables.md#time-format). Implemented in [#12738](https://github.com/blockscout/blockscout/pull/12738) |

Version: v9.0.0+
Default: 5m
Applications: Indexer

| +| `INDEXER_SIGNED_AUTHORIZATION_STATUS_BATCH_SIZE` | Batch size (number of blocks) for EIP7702 authorizations status fetcher. Implemented in [#12451](https://github.com/blockscout/blockscout/pull/12451). |

Version: v9.0.0+
Default: 10
Applications: Indexer

| +| `MIGRATION_REINDEX_BLOCKS_WITH_MISSING_TRANSACTIONS_BATCH_SIZE` | Number of blocks to reindex in the batch. Implemented in [#12559](https://github.com/blockscout/blockscout/pull/12559). |

Version: v9.0.0+
Default: 10
Applications: Indexer

| +| `MIGRATION_REINDEX_BLOCKS_WITH_MISSING_TRANSACTIONS_CONCURRENCY` | Number of parallel reindexing block batches processing. Implemented in [#12559](https://github.com/blockscout/blockscout/pull/12559). |

Version: v9.0.0+
Default: 1
Applications: Indexer

| +| `MIGRATION_REINDEX_BLOCKS_WITH_MISSING_TRANSACTIONS_TIMEOUT` | Timeout between reindexing block batches processing. Implemented in [#12559](https://github.com/blockscout/blockscout/pull/12559). |

Version: v9.0.0+
Default: 0
Applications: Indexer

| +| `MIGRATION_REINDEX_BLOCKS_WITH_MISSING_TRANSACTIONS_ENABLED` | Enable reindex blocks with missing transactions migration. Implemented in [#12559](https://github.com/blockscout/blockscout/pull/12559). |

Version: v9.0.0+
Default: false
Applications: Indexer

| +| `MIGRATION_MERGE_ADJACENT_MISSING_BLOCK_RANGES_BATCH_SIZE` | Specifies the missing block range batch size selected for the merge migration. Implemented in [#12778](https://github.com/blockscout/blockscout/pull/12778). |

Version: v9.0.0+
Default: 100
Applications: Indexer

| +| `API_RATE_LIMIT_CONFIG_URL` | URL to fetch API rate limit configuration from external source. Implemented in [#12386](https://github.com/blockscout/blockscout/pull/12386) |

Version: v9.0.0+
Default: (empty)
Applications: API

| +| `API_RATE_LIMIT_BY_KEY_TIME_INTERVAL` | Time interval for API rate limit by key. [Time format](backend-env-variables.md#time-format). Implemented in [#12386](https://github.com/blockscout/blockscout/pull/12386) |

Version: v9.0.0+
Default: 1s
Applications: API

| +| `API_RATE_LIMIT_BY_WHITELISTED_IP_TIME_INTERVAL` | Time interval for API rate limit by whitelisted IP. [Time format](backend-env-variables.md#time-format). Implemented in [#12386](https://github.com/blockscout/blockscout/pull/12386) |

Version: v9.0.0+
Default: 1s
Applications: API

| +| `API_RATE_LIMIT_UI_V2_WITH_TOKEN_TIME_INTERVAL` | Time interval for API rate limit for UI v2 with token. [Time format](backend-env-variables.md#time-format). Implemented in [#12386](https://github.com/blockscout/blockscout/pull/12386) |

Version: v9.0.0+
Default: 1s
Applications: API

| +| `API_RATE_LIMIT_BY_ACCOUNT_API_KEY_TIME_INTERVAL` | Time interval for API rate limit by account API key. [Time format](backend-env-variables.md#time-format). Implemented in [#12386](https://github.com/blockscout/blockscout/pull/12386) |

Version: v9.0.0+
Default: 1s
Applications: API

| +| `INDEXER_DISABLE_MULTICHAIN_SEARCH_DB_EXPORT_MAIN_QUEUE_FETCHER` | If `true`, multichain DB main (blocks, transactions, addresses) export fetcher doesn't run. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v9.0.0+
Default: false
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_MAIN_QUEUE_BATCH_SIZE` | Batch size for multichain DB main (blocks, transactions, addresses) export fetcher. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v9.0.0+
Default: 1000
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_MAIN_QUEUE_CONCURRENCY` | Concurrency for multichain DB main (blocks, transactions, addresses) export fetcher. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v9.0.0+
Default: 10
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_MAIN_QUEUE_ENQUEUE_BUSY_WAITING_TIMEOUT` | Timeout before new attempt to append item to multichain DB main (blocks, transactions, addresses) export queue if it's full. [Time format](backend-env-variables.md#time-format). Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v9.0.0+
Default: 1s
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_MAIN_QUEUE_MAX_QUEUE_SIZE` | Maximum size of multichain DB main (blocks, transactions, addresses) export queue. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v9.0.0+
Default: 1000
Applications: Indexer

| +| `INDEXER_DISABLE_MULTICHAIN_SEARCH_DB_EXPORT_BALANCES_QUEUE_FETCHER` | If `true`, multichain DB balances export fetcher doesn't run. Implemented in [#12580](https://github.com/blockscout/blockscout/pull/12580). |

Version: v9.0.0+
Default: false
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_BALANCES_QUEUE_BATCH_SIZE` | Batch size for multichain DB balances export fetcher. Implemented in [#12580](https://github.com/blockscout/blockscout/pull/12580). |

Version: v9.0.0+
Default: 1000
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_BALANCES_QUEUE_CONCURRENCY` | Concurrency for multichain DB balances export fetcher. Implemented in [#12580](https://github.com/blockscout/blockscout/pull/12580). |

Version: v9.0.0+
Default: 10
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_BALANCES_QUEUE_ENQUEUE_BUSY_WAITING_TIMEOUT` | Timeout before new attempt to append item to multichain DB balances export queue if it's full. [Time format](backend-env-variables.md#time-format). Implemented in [#12580](https://github.com/blockscout/blockscout/pull/12580). |

Version: v9.0.0+
Default: 1s
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_BALANCES_QUEUE_MAX_QUEUE_SIZE` | Maximum size of multichain DB balances export queue. Implemented in [#12580](https://github.com/blockscout/blockscout/pull/12580). |

Version: v9.0.0+
Default: 1000
Applications: Indexer

| +| `INDEXER_POLYGON_ZKEVM_BATCHES_IGNORE` | Comma-separated list of batch numbers that should be ignored by the fetcher. Implemented in [#12387](https://github.com/blockscout/blockscout/pull/12387). |

Version: v9.0.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_OPTIMISM_MULTICHAIN_BATCH_SIZE` | Max number of items sent to the Multichain service in one batch. Implemented in [#12387](https://github.com/blockscout/blockscout/pull/12387). |

Version: v9.0.0+
Default: 100
Applications: Indexer

| +| `CELO_UNRELEASED_TREASURY_CONTRACT` | The address[^1] of the `CeloUnreleasedTreasury` core contract. Implemented in [#12373](https://github.com/blockscout/blockscout/pull/12373). |

Version: v9.0.0+
Default: (empty)
Applications: Indexer

| +| `CELO_VALIDATORS_CONTRACT` | The address[^1] of the `Validators` core contract. Implemented in [#12373](https://github.com/blockscout/blockscout/pull/12373). |

Version: v9.0.0+
Default: (empty)
Applications: Indexer

| +| `CELO_EPOCH_MANAGER_CONTRACT` | The address[^1] of the `EpochManager` core contract. Implemented in [#12373](https://github.com/blockscout/blockscout/pull/12373). |

Version: v9.0.0+
Default: (empty)
Applications: Indexer

| + +## 8.1.2 + +### ⚙️ Miscellaneous Tasks + +- Parsing L2 block number of OP Dispute Game on BOB chain ([#12831](https://github.com/blockscout/blockscout/pull/12831)) + +## 8.1.1 + +### 🐛 Bug Fixes + +- Add missing preload for logs in /api/v2/transactions/:transaction_hash_param/summary ([#12491](https://github.com/blockscout/blockscout/issues/12491)) + +## 8.1.0 + +### 🚀 Features + +- Add lower bound for base fee ([#12370](https://github.com/blockscout/blockscout/pull/12370)) +- Multichain Search DB export retry queue ([#12377](https://github.com/blockscout/blockscout/issues/12377)) +- Add TAC operation search ([#12367](https://github.com/blockscout/blockscout/issues/12367)) +- Add `internal_transactions_count` prop in api/v2/blocks/:block endpoint ([#12405](https://github.com/blockscout/blockscout/issues/12405)) + +### 🐛 Bug Fixes + +- Handle mismatched 0x prefixed bytes ([#12453](https://github.com/blockscout/blockscout/pull/12453)) +- Fix logs decoding issue for proxies ([#12414](https://github.com/blockscout/blockscout/issues/12414)) +- Refactor TokenInstanceMetadataRefetch on demand fetcher ([#12419](https://github.com/blockscout/blockscout/issues/12419)) +- Fix for type output in ETH RPC API transaction by hash endpoint +- Frozen confirmations discovery on Arbitrum Nova ([#12385](https://github.com/blockscout/blockscout/issues/12385)) +- Add prague Solidity EVM version ([#12115](https://github.com/blockscout/blockscout/issues/12115)) +- Fix :checkout_timeout error ([#12406](https://github.com/blockscout/blockscout/issues/12406)) +- Force index usage on select current token balances ([#12390](https://github.com/blockscout/blockscout/issues/12390)) +- Fix retrieving max block number in MissingRangesCollector ([#12333](https://github.com/blockscout/blockscout/issues/12333)) +- Start PubSub before Endpoint ([#12274](https://github.com/blockscout/blockscout/issues/12274)) +- Fix FunctionClauseError on internal transactions indexing ([#12246](https://github.com/blockscout/blockscout/issues/12246)) +- Support updated zkSync calldata format in batch proof tracking ([#12234](https://github.com/blockscout/blockscout/issues/12234)) +- On demand bytecode fetcher for eip7702 addresses ([#12330](https://github.com/blockscout/blockscout/issues/12330)) +- Handle pending operations for empty blocks as well ([#12349](https://github.com/blockscout/blockscout/issues/12349)) + +### 🚜 Refactor + +- Eliminate join with internal_transactions table to get list logs in API v1 ([#12352](https://github.com/blockscout/blockscout/issues/12352)) +- Define pending block operations by set of block hashes query ([#12375](https://github.com/blockscout/blockscout/issues/12375)) +- Move `address_to_internal_transactions/2` to `Explorer.Chain.InternalTransaction` module ([#12346](https://github.com/blockscout/blockscout/issues/12346)) +- Single definition of smart-contract internal creation transaction query ([#12335](https://github.com/blockscout/blockscout/issues/12335)) + +### ⚡ Performance + +- Force index usage in `api/v2/addresses/:hash/transactions` ([#12415](https://github.com/blockscout/blockscout/issues/12415)) + +### ⚙️ Miscellaneous Tasks + +- Add updated-gas-oracle to Access-Control-Allow-Headers ([#12473](https://github.com/blockscout/blockscout/pull/12473)) +- Add additional test for Universal proxy, duplicate all proxy endpoints at /3rdparty ([#12442](https://github.com/blockscout/blockscout/pull/12442)) +- Improve logic behind emerging of custom fields in the response of `eth_getTransactionByHash` ETH RPC API endpoint ([#12416](https://github.com/blockscout/blockscout/issues/12416)) +- Internal transactions unique index ([#12394](https://github.com/blockscout/blockscout/issues/12394)) +- Update blocks consensus in case of import failure ([#12243](https://github.com/blockscout/blockscout/issues/12243)) +- Sanitize ERC-1155 token balances without token ids ([#12305](https://github.com/blockscout/blockscout/issues/12305)) +- Support Celestia Alt-DA in OP batches indexer and Super Roots in OP withdrawals indexer ([#12332](https://github.com/blockscout/blockscout/issues/12332)) +- Send DB read queries to replica in on-demand fetchers ([#12383](https://github.com/blockscout/blockscout/issues/12383)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `HACKNEY_DEFAULT_POOL_SIZE` | Size of `default` hackney pool. Implemented in [#12406](https://github.com/blockscout/blockscout/pull/12406). |

Version: v8.1.0+
Default: 1000
Applications: API, Indexer

| +| `MIGRATION_REINDEX_DUPLICATED_INTERNAL_TRANSACTIONS_BATCH_SIZE` | Number of internal transactions to reindex in the batch. Implemented in [#12394](https://github.com/blockscout/blockscout/pull/12394). |

Version: v8.1.0+
Default: 100
Applications: Indexer

| +| `MIGRATION_REINDEX_DUPLICATED_INTERNAL_TRANSACTIONS_CONCURRENCY` | Number of parallel reindexing internal transaction batches processing. Implemented in [#12394](https://github.com/blockscout/blockscout/pull/12394). |

Version: v8.1.0+
Default: 1
Applications: Indexer

| +| `MIGRATION_REINDEX_DUPLICATED_INTERNAL_TRANSACTIONS_TIMEOUT` | Timeout between reindexing internal transaction batches processing. Implemented in [#12394](https://github.com/blockscout/blockscout/pull/12394). |

Version: v8.1.0+
Default: 0
Applications: Indexer

| +| `INDEXER_SCROLL_L1_BATCH_BLOCKSCOUT_BLOBS_API_URL` | Defines a URL to Blockscout Blobs API to retrieve L1 blobs from that. Example for Sepolia: `https://eth-sepolia.blockscout.com/api/v2/blobs`. Implemented in [#12294](https://github.com/blockscout/blockscout/pull/12294). |

Version: v8.1.0+
Default: (empty)
Applications: Indexer

| +| `MICROSERVICE_MULTICHAIN_SEARCH_ADDRESSES_CHUNK_SIZE` | Chunk size of addresses while exporting to Multichain Search DB. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377) |

Version: v8.1.0+
Default: (empty)
Applications: API, Indexer

| +| `INDEXER_DISABLE_MULTICHAIN_SEARCH_DB_EXPORT_RETRY_FETCHER` | If `true`, `retry` multichain search export fetcher doesn't run. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v8.1.0+
Default: false
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_RETRY_BATCH_SIZE` | Batch size for `retry` multichain search export fetcher. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v8.1.0+
Default: 10
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_RETRY_CONCURRENCY` | Concurrency for `retry` multichain search export fetcher. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v8.1.0+
Default: 10
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_RETRY_ENQUEUE_BUSY_WAITING_TIMEOUT` | Timeout before new attempt to append item to `retry` multichain search export queue if it's full. [Time format](backend-env-variables.md#time-format). Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v8.1.0+
Default: 1s
Applications: Indexer

| +| `INDEXER_MULTICHAIN_SEARCH_DB_EXPORT_RETRY_MAX_QUEUE_SIZE` | Maximum size of `retry` multichain search export queue. Implemented in [#12377](https://github.com/blockscout/blockscout/pull/12377). |

Version: v8.1.0+
Default: 1000
Applications: Indexer

| + + +## 8.0.2 + +### 🚀 Features + +- Rate limiter for on-demand fetchers ([#12218](https://github.com/blockscout/blockscout/issues/12218)) +- Add average batch time (L2) to prometheus metrics ([#12217](https://github.com/blockscout/blockscout/issues/12217)) +- Contract creation tx block number binary search ([#10530](https://github.com/blockscout/blockscout/issues/10530)) +- Enhance health endpoint logic: track L2-rollup batches health ([#11888](https://github.com/blockscout/blockscout/issues/11888)) +- Universal API Proxy ([#12119](https://github.com/blockscout/blockscout/issues/12119)) +- Add sorting by tx count and balance to `/api/v2/addresses` ([#12168](https://github.com/blockscout/blockscout/issues/12168)) +- Support OP interop messages ([#11903](https://github.com/blockscout/blockscout/issues/11903)) +- Store and validate metadata_url ([#12102](https://github.com/blockscout/blockscout/issues/12102)) +- Captcha scoped bypass token for token instance metadata refetch ([#12147](https://github.com/blockscout/blockscout/issues/12147)) +- Add filter by `type` and `call_type` to `/api/v2/blocks/{:block_hash}/internal-transactions` ([#11968](https://github.com/blockscout/blockscout/issues/11968)) +- ERC-7760 proxy type support ([#12057](https://github.com/blockscout/blockscout/issues/12057)) +- Extend scam tokens feature on other endpoints ([#11975](https://github.com/blockscout/blockscout/issues/11975)) +- JSON RPC metrics ([#12070](https://github.com/blockscout/blockscout/issues/12070)) +- Add search by transaction hash capability at api/v2/internal-transactions endpoint ([#12025](https://github.com/blockscout/blockscout/issues/12025)) +- Add ENS and metadata preload to /api/v2/proxy/metadata/addresses ([#11962](https://github.com/blockscout/blockscout/issues/11962)) +- Zilliqa stakers API ([#11615](https://github.com/blockscout/blockscout/issues/11615)) +- Refine setting of certified flag on smart-contracts ([#11855](https://github.com/blockscout/blockscout/issues/11855)) +- Add PendingTransactionOperation ([#11157](https://github.com/blockscout/blockscout/issues/11157)) +- Allow from_period and to_period to be timestamps in CSV export functionality ([#11862](https://github.com/blockscout/blockscout/issues/11862)) +- Add support of ResolvedDelegateProxy proxy pattern ([#11720](https://github.com/blockscout/blockscout/issues/11720)) + +### 🐛 Bug Fixes + +- Fix Indexer.Helper.http_get_request function ([#12317](https://github.com/blockscout/blockscout/pull/12317)) +- Rename left props in API v2 with new naming convention ([#12314](https://github.com/blockscout/blockscout/issues/12314)) +- Temporary disable PendingTransactionOperation ([#12312](https://github.com/blockscout/blockscout/issues/12312)) +- Add `bash` to `builder-deps` build stage ([#12316](https://github.com/blockscout/blockscout/issues/12316)) +- Build on macos ([#12308](https://github.com/blockscout/blockscout/issues/12308)) +- Fix MissingBlockRange.fill_ranges_between/3 for empty range ([#12319](https://github.com/blockscout/blockscout/pull/12319)) +- Fix CSV export "to" range to include the whole day in all cases ([#12286](https://github.com/blockscout/blockscout/pull/12286)) +- Return compatibility with previous version of health endpoint([#12280](https://github.com/blockscout/blockscout/pull/12280)) +- Unbind import from compile-time chain_type ([#12277](https://github.com/blockscout/blockscout/pull/12277)) +- Read `CHAIN_TYPE` and `MUD_INDEXER_ENABLED` envs in runtime config ([#12270](https://github.com/blockscout/blockscout/issues/12270)) +- Limit max import concurrency ([#12261](https://github.com/blockscout/blockscout/pull/12261)) +- CSV export: download items for the given day if from / to period are equal ([#12260](https://github.com/blockscout/blockscout/pull/12260)) +- Upgrade missing balanceOf token condition ([#12254](https://github.com/blockscout/blockscout/pull/12254)) +- Add missing load of health_latest_batch_average_time_from_db ([#12240](https://github.com/blockscout/blockscout/pull/12240)) +- Handle unconfigured coin fetcher ETS access ([#12228](https://github.com/blockscout/blockscout/pull/12228)) +- Negate condition for language check in solidityscan controller ([#12222](https://github.com/blockscout/blockscout/pull/12222)) +- Look up sources for partially verified smart contracts ([#12221](https://github.com/blockscout/blockscout/pull/12221)) +- BufferedTask-based approach for fetching Arbitrum-specific settlement info ([#12192](https://github.com/blockscout/blockscout/pull/12192)) +- Contract creation transaction associations and bytecode twin detection ([#12086](https://github.com/blockscout/blockscout/issues/12086)) +- Improve background migrations + new `Indexer.Migrator.RecoveryWETHTokenTransfers` ([#12065](https://github.com/blockscout/blockscout/issues/12065)) +- Update docker cache references to use ghcr.io ([#12178](https://github.com/blockscout/blockscout/issues/12178)) +- Add blob and authorization list info to ETH RPC API ([#12150](https://github.com/blockscout/blockscout/issues/12150)) +- Fix Stability web test ([#12171](https://github.com/blockscout/blockscout/issues/12171)) +- Fix Rootstock failed tests ([#12169](https://github.com/blockscout/blockscout/issues/12169)) +- Unify Block Range Collector behavior for undefined and single range ([#12153](https://github.com/blockscout/blockscout/issues/12153)) +- Signed_authorizations table migrate nonce to numeric(20,0) ([#12157](https://github.com/blockscout/blockscout/issues/12157)) +- Refactor smart-contract API v2 endpoint output ([#12076](https://github.com/blockscout/blockscout/issues/12076)) +- Managing gas usage sum cache and address count cache ([#12149](https://github.com/blockscout/blockscout/issues/12149)) +- Web3 wallet login on Rootstock ([#12121](https://github.com/blockscout/blockscout/issues/12121)) +- Refactor a query to get missing confirmation for Arbitrum blocks ([#11914](https://github.com/blockscout/blockscout/issues/11914)) +- Fix error in old UI ([#12112](https://github.com/blockscout/blockscout/issues/12112)) +- OnDemand fetchers memory consumption for api mode ([#12082](https://github.com/blockscout/blockscout/issues/12082)) +- Implement DA record deduplication for Arbitrum batch processing ([#12095](https://github.com/blockscout/blockscout/issues/12095)) +- Empty contract code addresses ([#12023](https://github.com/blockscout/blockscout/issues/12023)) +- Unify response for single and batch 1155 transfer in RPC API ([#12083](https://github.com/blockscout/blockscout/issues/12083)) +- Is_verified for verified eip7702 proxies ([#12033](https://github.com/blockscout/blockscout/issues/12033)) +- Recovered functionality of Arbitrum batch fetcher ([#12059](https://github.com/blockscout/blockscout/issues/12059)) +- Fix flaking test ([#12013](https://github.com/blockscout/blockscout/issues/12013)) +- Confirmations of Arbitrum blocks near genesis ([#11790](https://github.com/blockscout/blockscout/issues/11790)) +- Fix finding of first block to index ([#11875](https://github.com/blockscout/blockscout/issues/11875)) +- Async fetch internal transactions from reindex migration ([#11959](https://github.com/blockscout/blockscout/issues/11959)) +- Fix Indexer.Fetcher.ContractCode unhandled error ([#11873](https://github.com/blockscout/blockscout/issues/11873)) + +### 🚜 Refactor + +- Consistency with the core application in properties namings in rollups-related API endpoints ([#12055](https://github.com/blockscout/blockscout/issues/12055)) +- Refactor market related code ([#11844](https://github.com/blockscout/blockscout/pull/11844)) + +### ⚡ Performance + +- Optimize watchlist query ([#12264](https://github.com/blockscout/blockscout/pull/12264)) +- Add index for slow `/api/v2/addresses?sort=transactions_count&order=asc` ([#12230](https://github.com/blockscout/blockscout/pull/12230)) +- `/api/v2/smart-contracts` endpoint ([#12060](https://github.com/blockscout/blockscout/issues/12060)) +- Optimize query for user token transfers list filtered by token ([#12039](https://github.com/blockscout/blockscout/issues/12039)) +- Improve watchlist rendering performance ([#11999](https://github.com/blockscout/blockscout/issues/11999)) + +### ⚙️ Miscellaneous Tasks + +- Add Scroll Euclid upgrade support ([#12294](https://github.com/blockscout/blockscout/issues/12294)) +- Decrease PBO to PTO migration batch size ([#12279](https://github.com/blockscout/blockscout/pull/12279)) +- Decrease PendingOperationsHelper blocks_batch_size ([#12276](https://github.com/blockscout/blockscout/pull/12276)) +- Update docker compose to use ghcr.io images ([#12177](https://github.com/blockscout/blockscout/issues/12177)) +- Add typed_ecto_schema to release ([#12255](https://github.com/blockscout/blockscout/pull/12255)) +- Suppress logging for expected 404 errors in account abstraction ([#12242](https://github.com/blockscout/blockscout/pull/12242)) +- Upgrade on demand balances fetchers ([#12104](https://github.com/blockscout/blockscout/pull/12104)) +- Migrate images to ghcr.io ([#12128](https://github.com/blockscout/blockscout/issues/12128)) +- Don't send transaction interpretation request for failed tx ([#12164](https://github.com/blockscout/blockscout/issues/12164)) +- Move `redstone` chain type to runtime ([#12124](https://github.com/blockscout/blockscout/issues/12124)) +- Move `DISABLE_INDEXER` option to runtime ([#12139](https://github.com/blockscout/blockscout/issues/12139)) +- Drop transactions index duplicates ([#12144](https://github.com/blockscout/blockscout/issues/12144)) +- CDN improvement: batch DB upsert ([#11918](https://github.com/blockscout/blockscout/issues/11918)) +- Partially move chain types to runtime ([#12114](https://github.com/blockscout/blockscout/issues/12114)) +- Chain counters refactoring and setup persistency for global counters in the DB ([#11849](https://github.com/blockscout/blockscout/issues/11849)) +- Remove legacy decompiled contracts API ([#11998](https://github.com/blockscout/blockscout/issues/11998)) +- Eliminate intercept for V2 socket channels ([#12003](https://github.com/blockscout/blockscout/issues/12003)) +- Treat `SHRINK_INTERNAL_TRANSACTIONS_ENABLED` as runtime env ([#12110](https://github.com/blockscout/blockscout/issues/12110)) +- Docker compose reduce env output ([#12111](https://github.com/blockscout/blockscout/issues/12111)) +- Replaced the link to the blockscout badge ([#12106](https://github.com/blockscout/blockscout/issues/12106)) +- Remove default JSON RPC endpoint ([#12071](https://github.com/blockscout/blockscout/issues/12071)) +- Remove token object from API v2 api/v2/tokens/:hash/holders endpoint ([#12022](https://github.com/blockscout/blockscout/issues/12022)) +- Remove Read/Write smart-contract API v2 endpoints ([#12026](https://github.com/blockscout/blockscout/issues/12026)) +- Use DB replica, if it's enabled, for proxy-related queries ([#12020](https://github.com/blockscout/blockscout/issues/12020)) +- Ganache -> Anvil JSON RPC Variant ([#12066](https://github.com/blockscout/blockscout/issues/12066)) +- Remove `is_vyper_contract` from the `/api/v2/smart-contracts/{address_hash}` endpoint response ([#11823](https://github.com/blockscout/blockscout/issues/11823)) +- Eliminate warnings in `epoch_logs.ex` ([#12027](https://github.com/blockscout/blockscout/issues/12027)) +- Migrate to `language` enum field in `smart_contracts` table ([#11813](https://github.com/blockscout/blockscout/issues/11813)) +- Fetch epoch logs and rewards until `CELO_L2_MIGRATION_BLOCK` ([#11949](https://github.com/blockscout/blockscout/issues/11949)) +- GraphQL introspection plug ([#11843](https://github.com/blockscout/blockscout/issues/11843)) +- Remove duplicate endpoints for 3d party proxies ([#11940](https://github.com/blockscout/blockscout/issues/11940)) +- Limit number of implementations proxy before insertion into the DB ([#11882](https://github.com/blockscout/blockscout/issues/11882)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `HEALTH_MONITOR_CHECK_INTERVAL` | Interval between health stats collection. [Time format](backend-env-variables.md#time-format). Implemented in [#11888](https://github.com/blockscout/blockscout/pull/11888/) |

Version: v8.0.0+
Default: 1m
Applications: API, Indexer

| +| `HEALTH_MONITOR_BLOCKS_PERIOD` | New blocks indexed max delay in /health API endpoint. [Time format](backend-env-variables.md#time-format). Implemented in [#11888](https://github.com/blockscout/blockscout/pull/11888/) |

Version: v8.0.0+
Default: 5m
Applications: API, Indexer

| +| `HEALTH_MONITOR_BATCHES_PERIOD` | New batches indexed max delay in /health API endpoint. [Time format](backend-env-variables.md#time-format). Implemented in [#11888](https://github.com/blockscout/blockscout/pull/11888/) |

Version: v8.0.0+
Default: 4h
Applications: API, Indexer

| +| `INDEXER_TOKEN_INSTANCE_CIDR_BLACKLIST` | List of IP addresses in CIDR format to block when fetching token instance metadata. Example: `"0.0.0.0/32,192.168.0.0/16"`. Implemented in [#12102](https://github.com/blockscout/blockscout/pull/12102). |

Version: v8.0.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_TOKEN_INSTANCE_HOST_FILTERING_ENABLED` | If `false`, the URL from which metadata is fetched will not be resolved to an IP address, and the IP address will not be checked against the blacklist. Implemented in [#12102](https://github.com/blockscout/blockscout/pull/12102). |

Version: v8.0.0+
Default: true
Applications: Indexer

| +| `INDEXER_TOKEN_INSTANCE_ALLOWED_URI_PROTOCOLS` | List of allowed URI protocols (schemes) for requests when fetching token instance metadata. Implemented in [#12102](https://github.com/blockscout/blockscout/pull/12102). |

Version: v8.0.0+
Default: http,https
Applications: Indexer

| +| `MIGRATION_SMART_CONTRACT_LANGUAGE_DISABLED` | If set to `true`, the migration to the `language` field in the `smart_contracts` table will not start. If set to `false`, the migration proceeds as normal. Implemented in [#11813](https://github.com/blockscout/blockscout/pull/11813). |

Version: v8.0.0+
Default: false
Applications: Indexer

| +| `MIGRATION_SMART_CONTRACT_LANGUAGE_BATCH_SIZE` | Defines the number of records to be processed in each batch when migrating the `language` field in the `smart_contracts` table. Implemented in [#11813](https://github.com/blockscout/blockscout/pull/11813). |

Version: v8.0.0+
Default: 100
Applications: Indexer

| +| `MIGRATION_SMART_CONTRACT_LANGUAGE_CONCURRENCY` | Specifies how many concurrent processes can handle the `language` field migration. Implemented in [#11813](https://github.com/blockscout/blockscout/pull/11813). |

Version: v8.0.0+
Default: 1
Applications: Indexer

| +| `MIGRATION_BACKFILL_METADATA_URL_DISABLED` | If set to `true`, the backfiller of `metadata_url` field in the `token_instances` table will not start. If set to `false`, the migration proceeds as normal. Implemented in [#12102](https://github.com/blockscout/blockscout/pull/12102). |

Version: v8.0.0+
Default: false
Applications: Indexer

| +| `MIGRATION_BACKFILL_METADATA_URL_BATCH_SIZE` | Defines the number of records to be processed in each batch when backfilling the `metadata_url` field in the `token_instances` table. Implemented in [#12102](https://github.com/blockscout/blockscout/pull/12102). |

Version: v8.0.0+
Default: 100
Applications: Indexer

| +| `MIGRATION_BACKFILL_METADATA_URL_CONCURRENCY` | Specifies how many concurrent processes can handle the `metadata_url` field backfilling. Implemented in [#12102](https://github.com/blockscout/blockscout/pull/12102). |

Version: v8.0.0+
Default: 5
Applications: Indexer

| +| `MIGRATION_RECOVERY_WETH_TOKEN_TRANSFERS_CONCURRENCY` | Specifies how many concurrent processes can handle the recovery WETH token transfers migration. Implemented in [#12065](https://github.com/blockscout/blockscout/pull/12065). |

Version: v8.0.0+
Default: 5
Applications: Indexer

| +| `MIGRATION_RECOVERY_WETH_TOKEN_TRANSFERS_BATCH_SIZE` | Defines the number of records to be processed in each batch when recovery WETH token transfers. Implemented in [#12065](https://github.com/blockscout/blockscout/pull/12065). |

Version: v8.0.0+
Default: 50
Applications: Indexer

| +| `MIGRATION_RECOVERY_WETH_TOKEN_TRANSFERS_TIMEOUT` | Defines the timeout between processing each batch (`batch_size` * `concurrency`) in the recovery WETH token transfers migration. Follows the [time format](backend-env-variables.md#time-format). Implemented in [#12065](https://github.com/blockscout/blockscout/pull/12065). |

Version: v8.0.0+
Default: 0s
Applications: Indexer

| +| `MIGRATION_RECOVERY_WETH_TOKEN_TRANSFERS_BLOCKS_BATCH_SIZE` | Specifies the block range size selected for the recovery of WETH token transfer migration. Implemented in [#12065](https://github.com/blockscout/blockscout/pull/12065). |

Version: v8.0.0+
Default: 100000
Applications: Indexer

| +| `MIGRATION_RECOVERY_WETH_TOKEN_TRANSFERS_HIGH_VERBOSITY` | If set to `true`, enables high verbosity logging (logs each transaction hash, where missed transfers were restored) during the recovery of WETH token transfer migration. Implemented in [#12065](https://github.com/blockscout/blockscout/pull/12065). |

Version: v8.0.0+
Default: true
Applications: Indexer

| +| `CACHE_ADDRESS_COUNT_PERIOD` | Interval for restarting the task that calculates the total number of addresses. |

Version: v8.0.0+
Default: 30m
Applications: API, Indexer

| +| `RE_CAPTCHA_TOKEN_INSTANCE_REFETCH_METADATA_SCOPED_BYPASS_TOKEN` | API key that allows to skip reCAPTCHA check for requests to `/api/v2/tokens/{token_hash}/instances/{token_id}/refetch-metadata` endpoint. Implemented in [#12147](https://github.com/blockscout/blockscout/pull/12147) |

Version: v8.0.0+
Default: (empty)
Applications: API

| +| `INDEXER_ARBITRUM_BATCHES_TRACKING_FAILURE_THRESHOLD` | The time threshold for transaction batch monitoring tasks. If a task has not run successfully within this threshold, it is marked as failed and enters a cooldown period before retrying. Implemented in [#12192](https://github.com/blockscout/blockscout/pull/12192). |

Version: v8.0.0+
Default: 10m
Applications: Indexer

| +| `RATE_LIMITER_REDIS_URL` | Redis DB URL for rate limiter. Implemented in [#12218](https://github.com/blockscout/blockscout/pull/12218) |

Version: v8.0.0+
Default: (empty)
Applications: API

| +| `RATE_LIMITER_ON_DEMAND_TIME_INTERVAL` | Time interval of rate limit for on-demand fetchers. Implemented in [#12218](https://github.com/blockscout/blockscout/pull/12218) |

Version: v8.0.0+
Default: 5s
Applications: API

| +| `RATE_LIMITER_ON_DEMAND_LIMIT_BY_IP` | Rate limit for an IP address for on-demand fetcher call. Implemented in [#12218](https://github.com/blockscout/blockscout/pull/12218) |

Version: v8.0.0+
Default: 100
Applications: API

| +| `RATE_LIMITER_ON_DEMAND_EXPONENTIAL_TIMEOUT_COEFF` | Coefficient to calculate exponential timeout for on-demand rate limit. Implemented in [#12218](https://github.com/blockscout/blockscout/pull/12218) |

Version: v8.0.0+
Default: 100
Applications: API

| +| `RATE_LIMITER_ON_DEMAND_MAX_BAN_INTERVAL` | Max time an IP address can be banned from on-demand fetcher calls. Implemented in [#12218](https://github.com/blockscout/blockscout/pull/12218) |

Version: v8.0.0+
Default: 1h
Applications: API

| +| `RATE_LIMITER_ON_DEMAND_LIMITATION_PERIOD` | Time after which the number of bans for the IP address will be reset. Implemented in [#12218](https://github.com/blockscout/blockscout/pull/12218) |

Version: v8.0.0+
Default: 1h
Applications: API

| +| `DISABLE_MARKET` | Disables all fetchers and any market data displaying. Setting this to `true` will disable all market-related functionality. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: false
Applications: API, Indexer

| +| `MARKET_NATIVE_COIN_SOURCE` | Source for realtime native coin price fetching. Possible values are: `coin_gecko`, `coin_market_cap`, `crypto_rank`, or `mobula`. Useful when multiple coin IDs are configured and you want to explicitly select the source. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: coin_gecko
Applications: API

| +| `MARKET_SECONDARY_COIN_SOURCE` | Source for realtime secondary coin fetching. Possible values are: `coin_gecko`, `coin_market_cap`, `crypto_rank`, or `mobula`. Useful when multiple secondary coin IDs are configured. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: coin_gecko
Applications: API

| +| `MARKET_TOKENS_SOURCE` | Sets the source for tokens price fetching. Available values are `coin_gecko`, `crypto_rank`, `mobula`. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: coin_gecko
Applications: Indexer

| +| `MARKET_NATIVE_COIN_HISTORY_SOURCE` | Sets the source for price history fetching. Available values are `crypto_compare`, `coin_gecko`, `mobula`, `coin_market_cap` and `crypto_rank`. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: crypto_compare
Applications: Indexer

| +| `MARKET_SECONDARY_COIN_HISTORY_SOURCE` | Sets the source for secondary coin price history fetching. Available values are `crypto_compare`, `coin_gecko`, `mobula`, `coin_market_cap` and `crypto_rank`. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: crypto_compare
Applications: Indexer

| +| `MARKET_MARKET_CAP_HISTORY_SOURCE` | Sets the source for market cap history fetching. Available values are `coin_gecko` and `coin_market_cap`. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: coin_gecko
Applications: Indexer

| +| `MARKET_TVL_HISTORY_SOURCE` | Sets the source for TVL history fetching. Available value is `defillama`. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: defillama
Applications: Indexer

| +| `MARKET_COINGECKO_PLATFORM_ID` | [CoinGecko](https://www.coingecko.com/) platform id for which token prices are fetched, see full list in [`/asset_platforms`](https://api.coingecko.com/api/v3/asset_platforms) endpoint. Examples: "ethereum", "optimistic-ethereum". Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: ethereum
Applications: Indexer

| +| `MARKET_COINGECKO_BASE_URL` | If set, overrides the Coingecko base URL. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: https://api.coingecko.com/api/v3
Applications: API, Indexer

| +| `MARKET_COINGECKO_BASE_PRO_URL` | If set, overrides the Coingecko Pro base URL. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: https://pro-api.coingecko.com/api/v3
Applications: API, Indexer

| +| `MARKET_COINGECKO_API_KEY` | CoinGecko API key. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_COINGECKO_COIN_ID` | Sets CoinGecko coin ID. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_COINGECKO_SECONDARY_COIN_ID` | Sets CoinGecko coin ID for secondary coin market chart. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_COINMARKETCAP_BASE_URL` | If set, overrides the CoinMarketCap base URL (Free and Pro). Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: https://pro-api.coinmarketcap.com/v2
Applications: API, Indexer

| +| `MARKET_COINMARKETCAP_API_KEY` | CoinMarketCap API key. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_COINMARKETCAP_COIN_ID` | CoinMarketCap coin id. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_COINMARKETCAP_SECONDARY_COIN_ID` | CoinMarketCap coin id for secondary coin. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_CRYPTOCOMPARE_BASE_URL` | If set, overrides the CryptoCompare base URL. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: https://min-api.cryptocompare.com
Applications: API, Indexer

| +| `MARKET_CRYPTOCOMPARE_COIN_SYMBOL` | CryptoCompare coin symbol for native coin (e.g., "OP" for Optimism). CryptoCompare uses symbols instead of IDs. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: Indexer

| +| `MARKET_CRYPTOCOMPARE_SECONDARY_COIN_SYMBOL`| CryptoCompare coin symbol for secondary coin market chart. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: Indexer

| +| `MARKET_CRYPTORANK_PLATFORM_ID` | Sets Cryptorank platform ID. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: Indexer

| +| `MARKET_CRYPTORANK_BASE_URL` | If set, overrides the Cryptorank API url. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: https://api.cryptorank.io/v1/
Applications: API, Indexer

| +| `MARKET_CRYPTORANK_API_KEY` | Cryptorank API key. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_CRYPTORANK_COIN_ID` | Sets Cryptorank coin ID. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_CRYPTORANK_SECONDARY_COIN_ID` | Sets Cryptorank coin ID for secondary coin. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_DEFILLAMA_COIN_ID` | DefiLlama coin id. Use the `name` field from the `/v2/chains` endpoint response (e.g., "OP Mainnet" for Optimism). Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: Indexer

| +| `MARKET_MOBULA_PLATFORM_ID` | Mobula platform ID. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: Indexer

| +| `MARKET_MOBULA_BASE_URL` | If set, overrides the Mobula API base URL. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: https://api.mobula.io/api/1
Applications: API, Indexer

| +| `MARKET_MOBULA_API_KEY` | Mobula API key. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_MOBULA_COIN_ID` | Set Mobula coin ID. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_MOBULA_SECONDARY_COIN_ID` | Set Mobula coin ID for secondary coin. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: (empty)
Applications: API, Indexer

| +| `MARKET_COIN_FETCHER_ENABLED` | If `false` disables fetching of realtime native coin price. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: true
Applications: API

| +| `MARKET_COIN_CACHE_PERIOD` | Cache period for coin exchange rates. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: 10m
Applications: API

| +| `MARKET_TOKENS_FETCHER_ENABLED` | If `false` disables fetching of token prices. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: true
Applications: Indexer

| +| `MARKET_TOKENS_INTERVAL` | Interval between batch requests of token prices. Can be decreased in order to fetch prices faster if you have pro rate limit. [Time format](backend-env-variables.md#time-format). Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: 10s
Applications: Indexer

| +| `MARKET_TOKENS_REFETCH_INTERVAL` | Interval between refetching token prices, responsible for the relevance of prices. [Time format](backend-env-variables.md#time-format). Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: 1h
Applications: Indexer

| +| `MARKET_TOKENS_MAX_BATCH_SIZE` | Batch size of a single token price request. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: 500
Applications: Indexer

| +| `MARKET_HISTORY_FETCHER_ENABLED` | If `false` disables fetching of marked data history. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: true
Applications: Indexer

| +| `MARKET_HISTORY_FIRST_FETCH_DAY_COUNT` | Initial number of days to fetch for market history. Implemented in [#11844](https://github.com/blockscout/blockscout/pull/11844). |

Version: v8.0.0+
Default: 365
Applications: Indexer

| + +### Deprecated ENV variables + +| Variable | Required | Description | Default | Version | Need recompile | Deprecated in Version | +| ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | -------------- | --------------------- | +| `CACHE_ADDRESS_WITH_BALANCES_UPDATE_INTERVAL` | | Interval to restart the task which calculates addresses with balances. | 30m | v4.1.3+ | | v8.0.0 +| `HEALTHY_BLOCKS_PERIOD` | | New blocks indexed max delay in /health API endpoint. [Time format](env-variables.md#time-format). Implemented in [#2294](https://github.com/blockscout/blockscout/pull/2294/) | 5m | v2.0.2+ | | v8.0.0 | + +## 7.0.2 + +### ⚡ Performance + +- Logs list decoding: Accumulate ABI for unique address hashes ([#11967](https://github.com/blockscout/blockscout/pull/11967)) +- Logs list decoding: Use Sig provider microservice batched request ([#11956](https://github.com/blockscout/blockscout/issues/11956), [#11963](https://github.com/blockscout/blockscout/issues/11963)) +- Transactions list: Don't fetch revert reason for txs list ([#11935](https://github.com/blockscout/blockscout/issues/11935)) + +## 7.0.1 + +### 🐛 Bug Fixes + +- Show scam ENS in search ([#11933](https://github.com/blockscout/blockscout/issues/11933)) +- Show scam EOA in search ([#11932](https://github.com/blockscout/blockscout/issues/11932)) +- Replace unique filecoin addresses indexes with not unique ([#11905](https://github.com/blockscout/blockscout/issues/11905)) +- Render token transfers from celo epoch logs ([#11915](https://github.com/blockscout/blockscout/issues/11915)) + +## 7.0.0 + +### 🚀 Features + +- NFT collection trigger refetch Admin API endpoint ([#10263](https://github.com/blockscout/blockscout/issues/10263)) +- Improve NFT sanitizers ([#11543](https://github.com/blockscout/blockscout/issues/11543)) +- Add new endpoint /api/v2/proxy/account-abstraction/status ([#11784](https://github.com/blockscout/blockscout/issues/11784)) +- Adds support for NeonVM linked Solana transactions ([#11667](https://github.com/blockscout/blockscout/issues/11667)) ([#11736](https://github.com/blockscout/blockscout/issues/11736)) +- Enable /api/v2/internal-transactions endpoint ([#11792](https://github.com/blockscout/blockscout/issues/11792)) +- Integrate metadata tags to search ([#11719](https://github.com/blockscout/blockscout/issues/11719)) +- Add Arweave NFT image link parsing support ([#11565](https://github.com/blockscout/blockscout/issues/11565)) +- Disable re-verification from partial to partial match by default ([#11737](https://github.com/blockscout/blockscout/issues/11737)) +- DB Index heavy operations processing module ([#11604](https://github.com/blockscout/blockscout/issues/11604)) +- Multiple strategies for filecoin address info fetching ([#11412](https://github.com/blockscout/blockscout/issues/11412)) +- Preload NFT to token transfers ([#11756](https://github.com/blockscout/blockscout/issues/11756)) +- Add show_scam_tokens cookie ([#11747](https://github.com/blockscout/blockscout/issues/11747)) +- Add ENS and metadata preload to /api/v2/tokens/{hash}/instances ([#11760](https://github.com/blockscout/blockscout/issues/11760)) +- Return 200 on addresses which are not present in DB ([#11506](https://github.com/blockscout/blockscout/issues/11506)) +- Enhance txlistinternal API v1: make transaction hash and address hash not mandatory ([#11717](https://github.com/blockscout/blockscout/issues/11717)) +- Backfill for Arbitrum-specific information in blocks and transactions ([#11163](https://github.com/blockscout/blockscout/issues/11163)) +- Ignore events older than 24 hours in Explorer.Account.Notifier.… ([#11654](https://github.com/blockscout/blockscout/issues/11654)) +- Add timeout env for proxy metadata requests ([#11656](https://github.com/blockscout/blockscout/issues/11656)) +- Support filecoin addresses in search ([#11499](https://github.com/blockscout/blockscout/issues/11499)) +- Return error on verification if address is not a smart contract ([#11504](https://github.com/blockscout/blockscout/issues/11504)) + +### 🐛 Bug Fixes + +- Add BRIDGED_TOKENS_ENABLED to custom Gnosis chain docker images ([#11895](https://github.com/blockscout/blockscout/pull/11895)) +- Fix /verified-contracts in old UI ([#11854](https://github.com/blockscout/blockscout/pull/11854)) +- Cleanup token instance metadata on nft collection metadata refetch ([#11848](https://github.com/blockscout/blockscout/pull/11848)) +- Allow skip fiat_value in /api/v2/addresses/{hash}/tokens endpoint ([#11837](https://github.com/blockscout/blockscout/pull/11837)) +- Handle invalid BLACKFORT_VALIDATOR_API_URL ([#11812](https://github.com/blockscout/blockscout/issues/11812)) +- Fix scam addresses ban in quick search ([#11810](https://github.com/blockscout/blockscout/issues/11810)) +- Handle case when `epoch_distribution` is `nil` ([#11807](https://github.com/blockscout/blockscout/issues/11807)) +- Strict mode for timestamp to block number conversion ([#11633](https://github.com/blockscout/blockscout/issues/11633)) +- Don't store ipfs gateway in metadata ([#11673](https://github.com/blockscout/blockscout/issues/11673)) +- Use 0 as a default for v field in transactions ([#11800](https://github.com/blockscout/blockscout/issues/11800)) +- Fix tests ([#11805](https://github.com/blockscout/blockscout/issues/11805)) +- Use safe field access in CurrentTokenBalances.should_update?/2 ([#11804](https://github.com/blockscout/blockscout/issues/11804)) +- Run Neon tests on neon chain type only ([#11802](https://github.com/blockscout/blockscout/issues/11802)) +- Sanitize addresses of smart contracts having `verified` set to `false` ([#11727](https://github.com/blockscout/blockscout/issues/11727)) +- Celestia info parsing ([#11678](https://github.com/blockscout/blockscout/issues/11678)) +- `EIP1559ConfigUpdate` and `Indexer.Block.Realtime.Fetcher` fetchers were unstable for L2 reorgs, `brotli` lib was replaced ([#11714](https://github.com/blockscout/blockscout/issues/11714)) +- Add traceable blocks filtering to contract code fetcher ([#11700](https://github.com/blockscout/blockscout/issues/11700)) +- Improve token metadata update process ([#11710](https://github.com/blockscout/blockscout/issues/11710)) +- Add typeless handler for call_tracer ([#11766](https://github.com/blockscout/blockscout/issues/11766)) +- Add consensus filter to reindex internal transactions migration ([#11732](https://github.com/blockscout/blockscout/issues/11732)) +- Add error handling to chunked json rpc decode json ([#11734](https://github.com/blockscout/blockscout/issues/11734)) +- New methods submitting Arbitrum batches supported ([#11731](https://github.com/blockscout/blockscout/issues/11731)) +- Don't fail on pending transactions in Explorer.Account.Notifier.Notify ([#11724](https://github.com/blockscout/blockscout/issues/11724)) +- Add flat value to BoundInterval increase/decrease ([#11708](https://github.com/blockscout/blockscout/issues/11708)) +- Add missing condition to reindex internal transactions migration ([#11709](https://github.com/blockscout/blockscout/issues/11709)) +- Add 'yParity' alias ([#11642](https://github.com/blockscout/blockscout/issues/11642)) +- Fix address coin balances transformer ([#11627](https://github.com/blockscout/blockscout/issues/11627)) +- Improve session handling in account v2 ([#11420](https://github.com/blockscout/blockscout/issues/11420)) +- Add /metrics handler for indexer mode ([#11672](https://github.com/blockscout/blockscout/issues/11672)) +- Ease SQL query for EIP1559ConfigUpdate fetcher ([#11659](https://github.com/blockscout/blockscout/issues/11659)) +- Fix enoent in Indexer.NFTMediaHandler.Queue ([#11653](https://github.com/blockscout/blockscout/issues/11653)) +- Add function clause for wrong first trace result format ([#11655](https://github.com/blockscout/blockscout/issues/11655)) +- Intercept error during DB drop ([#11618](https://github.com/blockscout/blockscout/issues/11618)) +- Update EmptyBlocksSanitizer logic due to refetch_needed field ([#11660](https://github.com/blockscout/blockscout/issues/11660)) + +### 🚜 Refactor + +- All env variables related to DB migration processes now have "MIGRATION_" prefix ([#11798](https://github.com/blockscout/blockscout/issues/11798)) + +### ⚡ Performance + +- Smart contracts list query ([#11733](https://github.com/blockscout/blockscout/issues/11733)) + +### ⚙️ Miscellaneous Tasks + +- Runtime variable to manage chain spec processing delay ([#11874](https://github.com/blockscout/blockscout/pull/11874)) +- Replace composite id types usage ([#11861](https://github.com/blockscout/blockscout/pull/11861)) +- Correct the docker compose command for running an external frontend in README.md ([#11838](https://github.com/blockscout/blockscout/pull/11838)) +- Update link to the list of chains in README.md ([#11829](https://github.com/blockscout/blockscout/pull/11829)) +- Create /api/v2/proxy/3dparty/ root path for 3dparty proxy API endpoints ([#11808](https://github.com/blockscout/blockscout/issues/11808)) +- Mention WC Project ID in common-frontend.env ([#11799](https://github.com/blockscout/blockscout/issues/11799)) +- Remove api v1 health endpoints ([#11573](https://github.com/blockscout/blockscout/issues/11573)) +- Add env var for realtime fetcher polling period ([#11783](https://github.com/blockscout/blockscout/issues/11783)) +- Refactor composite keys filtering ([#11473](https://github.com/blockscout/blockscout/issues/11473)) +- Upsert token instances by batches ([#11685](https://github.com/blockscout/blockscout/issues/11685)) +- Fix spelling in some modules ([#11791](https://github.com/blockscout/blockscout/issues/11791)) +- Update Twitter URL to x.com format ([#11761](https://github.com/blockscout/blockscout/issues/11761)) +- Reduce the number of queries for token type ([#11674](https://github.com/blockscout/blockscout/issues/11674)) +- Increase verbosity of error logs in TokenInstanceMetadataRefetch ([#11758](https://github.com/blockscout/blockscout/issues/11758)) +- Support snake case in ImportController ([#11501](https://github.com/blockscout/blockscout/issues/11501)) +- Pass chain id to Transaction Interpretation service ([#11745](https://github.com/blockscout/blockscout/issues/11745)) +- Deprecating of CHECKSUM_FUNCTION variable ([#10480](https://github.com/blockscout/blockscout/issues/10480)) +- Arbitrum claiming enhancements ([#11552](https://github.com/blockscout/blockscout/issues/11552)) +- Fix text in the template and update localization files ([#11715](https://github.com/blockscout/blockscout/issues/11715)) +- Decrease catchup interval ([#11626](https://github.com/blockscout/blockscout/issues/11626)) + +### New ENV variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `INDEXER_DISABLE_TOKEN_INSTANCE_REFETCH_FETCHER` | If `true`, the Token instance fetcher, which re-fetches NFT collections marked to refetch, doesn't run. Implemented in [#10263](https://github.com/blockscout/blockscout/pull/10263). |

Version: v7.0.0+
Default: false
Applications: Indexer

| +| `INDEXER_REALTIME_FETCHER_POLLING_PERIOD` | Period between polling the `latest` block in realtime fetcher. [Time format](backend-env-variables.md#time-format). Implemented in [#11783](https://github.com/blockscout/blockscout/pull/11783) |

Version: v7.0.0+
Default: (empty)
Applications: Indexer

| +| `MIGRATION_SHRINK_INTERNAL_TRANSACTIONS_BATCH_SIZE` | Batch size of the shrink internal transactions migration. _Note_: before release "v6.8.0", the default value was 1000. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567), changed default value in [#10689](https://github.com/blockscout/blockscout/pull/10689). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 100
Applications: API, Indexer

| +| `MIGRATION_SHRINK_INTERNAL_TRANSACTIONS_CONCURRENCY` | Concurrency of the shrink internal transactions migration. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 10
Applications: API, Indexer

| +| `MIGRATION_TOKEN_INSTANCE_OWNER_CONCURRENCY` | Concurrency of new fields backfiller implemented in [#8386](https://github.com/blockscout/blockscout/pull/8386). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 5
Applications: API, Indexer

| +| `MIGRATION_TOKEN_INSTANCE_OWNER_BATCH_SIZE` | Batch size of new fields backfiller implemented in [#8386](https://github.com/blockscout/blockscout/pull/8386). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 50
Applications: API, Indexer

| +| `MIGRATION_TOKEN_INSTANCE_OWNER_ENABLED` | Enable of backfiller from [#8386](https://github.com/blockscout/blockscout/pull/8386) implemented in [#8752](https://github.com/blockscout/blockscout/pull/8752). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: false
Applications: API, Indexer

| +| `MIGRATION_TRANSACTIONS_TABLE_DENORMALIZATION_BATCH_SIZE` | Number of transactions to denormalize (add block timestamp and consensus) in the batch. Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 500
Applications: API, Indexer

| +| `MIGRATION_TRANSACTIONS_TABLE_DENORMALIZATION_CONCURRENCY` | Number of parallel denormalization transaction batches processing. Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 10
Applications: API, Indexer

| +| `MIGRATION_TOKEN_TRANSFER_TOKEN_TYPE_BATCH_SIZE` | Number of token transfers to denormalize (add token\_type) in the batch. Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 100
Applications: API, Indexer

| +| `MIGRATION_TOKEN_TRANSFER_TOKEN_TYPE_CONCURRENCY` | Number of parallel denormalization token transfer batches processing. Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 1
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_INCORRECT_NFT_BATCH_SIZE` | Number of token transfers to sanitize in the batch. Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 100
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_INCORRECT_NFT_CONCURRENCY` | Number of parallel sanitizing token transfer batches processing. Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 1
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_INCORRECT_NFT_TIMEOUT` | Timeout between sanitizing token transfer batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 0
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_INCORRECT_WETH_BATCH_SIZE` | Number of token transfers to sanitize in the batch. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 100
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_INCORRECT_WETH_CONCURRENCY` | Number of parallel sanitizing token transfer batches processing. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 1
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_INCORRECT_WETH_TIMEOUT` | Timeout between sanitizing token transfer batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 0
Applications: API, Indexer

| +| `MIGRATION_REINDEX_INTERNAL_TRANSACTIONS_STATUS_BATCH_SIZE` | Number of internal transactions to reindex in the batch. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 100
Applications: API, Indexer

| +| `MIGRATION_REINDEX_INTERNAL_TRANSACTIONS_STATUS_CONCURRENCY` | Number of parallel reindexing internal transaction batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 1
Applications: API, Indexer

| +| `MIGRATION_REINDEX_INTERNAL_TRANSACTIONS_STATUS_TIMEOUT` | Timeout between reindexing internal transaction batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358). Renamed in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 0
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_VERIFIED_ADDRESSES_DISABLED` | Concurrency of the sanitize verified addresses migration. Implemented in [#11727](https://github.com/blockscout/blockscout/pull/11727). |

Version: v7.0.0+
Default: false
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_VERIFIED_ADDRESSES_BATCH_SIZE` | Concurrency of the sanitize verified addresses migration. Implemented in [#11727](https://github.com/blockscout/blockscout/pull/11727). |

Version: v7.0.0+
Default: 500
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_VERIFIED_ADDRESSES_CONCURRENCY` | Concurrency of the sanitize verified addresses migration. Implemented in [#11727](https://github.com/blockscout/blockscout/pull/11727). |

Version: v7.0.0+
Default: 1
Applications: API, Indexer

| +| `MIGRATION_SANITIZE_VERIFIED_ADDRESSES_TIMEOUT` | Timeout between batches processing in sanitize verified addresses migration. [Time format](backend-env-variables.md#time-format). Implemented in [#11727](https://github.com/blockscout/blockscout/pull/11727). |

Version: v7.0.0+
Default: 0s
Applications: API, Indexer

| +| `MIGRATION_HEAVY_INDEX_OPERATIONS_CHECK_INTERVAL` | Interval between status checks of heavy db operation like index creation or dropping. [Time format](backend-env-variables.md#time-format). Implemented in [#11604](https://github.com/blockscout/blockscout/pull/11604) |

Version: v7.0.0+
Default: 10m
Applications: API, Indexer

| +| `MIGRATION_TOKEN_INSTANCE_ERC_1155_SANITIZE_CONCURRENCY` | Concurrency for `erc-1155-sanitize` token instance fetcher. Implemented in [#9226](https://github.com/blockscout/blockscout/pull/9226). Default value and name changed in [#11543](https://github.com/blockscout/blockscout/pull/11543) |

Version: v7.0.0+
Default: 1
Applications: Indexer

| +| `MIGRATION_TOKEN_INSTANCE_ERC_721_SANITIZE_CONCURRENCY` | Concurrency for `erc-721-sanitize` token instance fetcher. Implemented in [#9226](https://github.com/blockscout/blockscout/pull/9226). Name changed in [#11543](https://github.com/blockscout/blockscout/pull/11543) |

Version: v7.0.0+
Default: 2
Applications: Indexer

| +| `MIGRATION_TOKEN_INSTANCE_ERC_1155_SANITIZE_BATCH_SIZE` | Batch size for `erc-1155-sanitize` token instance fetcher. Implemented in [#9226](https://github.com/blockscout/blockscout/pull/9226). Default value and name changed in [#11543](https://github.com/blockscout/blockscout/pull/11543) |

Version: v7.0.0+
Default: 500
Applications: Indexer

| +| `MIGRATION_TOKEN_INSTANCE_ERC_721_SANITIZE_BATCH_SIZE` | Batch size for `erc-721-sanitize` token instance fetcher. Implemented in [#9226](https://github.com/blockscout/blockscout/pull/9226). Default value and name changed in [#11543](https://github.com/blockscout/blockscout/pull/11543) |

Version: v7.0.0+
Default: 50
Applications: Indexer

| +| `MIGRATION_TOKEN_INSTANCE_ERC_721_SANITIZE_TOKENS_BATCH_SIZE`| Tokens batch size for `erc-721-sanitize` token instance fetcher. Implemented in [#9226](https://github.com/blockscout/blockscout/pull/9226). Name changed in [#11543](https://github.com/blockscout/blockscout/pull/11543) |

Version: v7.0.0+
Default: 100
Applications: Indexer

| +| `CONTRACT_ENABLE_PARTIAL_REVERIFICATION` | Toggle for enabling re-verification from partial to partial match. Implemented in [#11737](https://github.com/blockscout/blockscout/pull/11737) |

Version: v7.0.0+
Default: false
Applications: API

| +| `INDEXER_ARBITRUM_DATA_BACKFILL_ENABLED` | Enables a process to backfill the blocks and transaction with Arbitrum specific data. This should only be enabled for Arbitrum chains where blocks were indexed before upgrading to a version that includes Arbitrum-specific data indexing features. Implemented in [#11163](https://github.com/blockscout/blockscout/pull/11163). |

Version: v7.0.0+
Default: false
Applications: Indexer

| +| `INDEXER_ARBITRUM_DATA_BACKFILL_UNINDEXED_BLOCKS_RECHECK_INTERVAL` | The number of L2 blocks to look back in one iteration of the backfill process. Implemented in [#11163](https://github.com/blockscout/blockscout/pull/11163). |

Version: v7.0.0+
Default: 120s
Applications: Indexer

| +| `INDEXER_ARBITRUM_DATA_BACKFILL_BLOCKS_DEPTH` | Interval to retry the backfill task for unindexed blocks. Implemented in [#11163](https://github.com/blockscout/blockscout/pull/11163). |

Version: v7.0.0+
Default: 500
Applications: Indexer

| +| `MIGRATION_ARBITRUM_DA_RECORDS_NORMALIZATION_BATCH_SIZE` | Specifies the number of address records processed per batch during normalization of batch-to-blob associations by moving them from arbitrum_da_multi_purpose to a dedicated arbitrum_batches_to_da_blobs table. Implemented in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 500
Applications: Indexer

| +| `MIGRATION_ARBITRUM_DA_RECORDS_NORMALIZATION_CONCURRENCY` | Specifies the number of concurrent processes used during normalization of batch-to-blob associations by moving them from arbitrum_da_multi_purpose to a dedicated arbitrum_batches_to_da_blobs table. Implemented in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 1
Applications: Indexer

| +| `FILFOX_API_BASE_URL` | [Filfox API](https://filfox.info/api/v1/docs/static/index.html) base URL. Implemented in [#11412](https://github.com/blockscout/blockscout/pull/11412). |

Version: v7.0.0+
Default: https://filfox.info/api/v1
Applications: Indexer

| +| `MIGRATION_FILECOIN_PENDING_ADDRESS_OPERATIONS_BATCH_SIZE` | Specifies the number of address records processed per batch during the backfill of pending address fetch operations. Implemented in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 100
Applications: Indexer

| +| `MIGRATION_FILECOIN_PENDING_ADDRESS_OPERATIONS_CONCURRENCY` | Specifies the number of concurrent processes used during the backfill of pending address fetch operations. Implemented in [#11798](https://github.com/blockscout/blockscout/pull/11798). |

Version: v7.0.0+
Default: 1
Applications: Indexer

| +| `MICROSERVICE_METADATA_PROXY_REQUESTS_TIMEOUT` | Timeout for request forwarding from `/api/v2/proxy/metadata/`. Implemented in [#11656](https://github.com/blockscout/blockscout/pull/11656) |

Version: v7.0.0+
Default: 30s
Applications: API

| +| `CHAIN_SPEC_PROCESSING_DELAY` | Chain specification path processing delay. [Time format](backend-env-variables.md#time-format). Implemented in [#11874](https://github.com/blockscout/blockscout/pull/11874). |

Version: v7.0.0+
Default: 15s
Applications: API, Indexer

| + +### Deprecated ENV variables + +| Variable | Required | Description | Default | Version | Need recompile | Deprecated in Version | +| ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | -------------- | --------------------- | +| `CHECKSUM_FUNCTION` | | Defines checksum address function. 2 available values: `rsk`, `eth` | `eth` | v2.0.1+ | | v7.0.0 | +| `TOKEN_ID_MIGRATION_FIRST_BLOCK` | | Bottom block for token id migration. Implemented in [#6391](https://github.com/blockscout/blockscout/pull/6391) | 0 | v5.0.0+ | | v7.0.0 +| `TOKEN_ID_MIGRATION_CONCURRENCY` | | Number of workers performing the token id migration. Implemented in [#6391](https://github.com/blockscout/blockscout/pull/6391) | 1 | v5.0.0+ | | v7.0.0 +| `TOKEN_ID_MIGRATION_BATCH_SIZE` | | Interval of token transfer block numbers processed by a token id migration worker at a time. Implemented in [#6391](https://github.com/blockscout/blockscout/pull/6391) | 500 | v5.0.0+ | | v7.0.0 +| `SHRINK_INTERNAL_TRANSACTIONS_BATCH_SIZE` | | Batch size of the shrink internal transactions migration. _Note_: before release "v6.8.0", the default value was 1000. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567), changed default value in [#10689](https://github.com/blockscout/blockscout/pull/10689). | 100 | v6.8.0+ | | v7.0.0 +| `SHRINK_INTERNAL_TRANSACTIONS_CONCURRENCY` | | Concurrency of the shrink internal transactions migration. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567). | 10 | v6.8.0+ | | v7.0.0 +| `TOKEN_INSTANCE_OWNER_MIGRATION_CONCURRENCY` | | Concurrency of new fields backfiller implemented in [#8386](https://github.com/blockscout/blockscout/pull/8386) | 5 | v5.3.0+ | | v7.0.0 +| `TOKEN_INSTANCE_OWNER_MIGRATION_BATCH_SIZE` | | Batch size of new fields backfiller implemented in [#8386](https://github.com/blockscout/blockscout/pull/8386) | 50 | v5.3.0+ | | v7.0.0 +| `TOKEN_INSTANCE_OWNER_MIGRATION_ENABLED` | | Enable of backfiller from [#8386](https://github.com/blockscout/blockscout/pull/8386) implemented in [#8752](https://github.com/blockscout/blockscout/pull/8752) | false | v5.3.2+ | | v7.0.0 +| `DENORMALIZATION_MIGRATION_BATCH_SIZE` | | Number of transactions to denormalize (add block timestamp and consensus) in the batch. | 500 | v6.0.0+ | | v7.0.0 +| `DENORMALIZATION_MIGRATION_CONCURRENCY` | | Number of parallel denormalization transaction batches processing. | 10 | v6.0.0+ | | v7.0.0 +| `TOKEN_TRANSFER_TOKEN_TYPE_MIGRATION_BATCH_SIZE` | | Number of token transfers to denormalize (add token\_type) in the batch. | 100 | v6.3.0+ | | v7.0.0 +| `TOKEN_TRANSFER_TOKEN_TYPE_MIGRATION_CONCURRENCY` | | Number of parallel denormalization token transfer batches processing. | 1 | v6.3.0+ | | v7.0.0 +| `SANITIZE_INCORRECT_NFT_BATCH_SIZE` | | Number of token transfers to sanitize in the batch. | 100 | v6.3.0+ | | v7.0.0 +| `SANITIZE_INCORRECT_NFT_CONCURRENCY` | | Number of parallel sanitizing token transfer batches processing. | 1 | v6.3.0+ | | v7.0.0 +| `SANITIZE_INCORRECT_NFT_TIMEOUT` | | Timeout between sanitizing token transfer batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) | 0 | v6.10.0+ | | v7.0.0 +| `SANITIZE_INCORRECT_WETH_BATCH_SIZE` | | Number of token transfers to sanitize in the batch. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) | 100 | v6.8.0+ | | v7.0.0 +| `SANITIZE_INCORRECT_WETH_CONCURRENCY` | | Number of parallel sanitizing token transfer batches processing. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) | 1 | v6.8.0+ | | v7.0.0 +| `SANITIZE_INCORRECT_WETH_TIMEOUT` | | Timeout between sanitizing token transfer batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) | 0 | v6.10.0+ | | v7.0.0 +| `REINDEX_INTERNAL_TRANSACTIONS_STATUS_BATCH_SIZE` | | Number of internal transactions to reindex in the batch. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) | 100 | v6.10.0+ | | v7.0.0 +| `REINDEX_INTERNAL_TRANSACTIONS_STATUS_CONCURRENCY` | | Number of parallel reindexing internal transaction batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) | 1 | v6.10.0+ | | v7.0.0 +| `REINDEX_INTERNAL_TRANSACTIONS_STATUS_TIMEOUT` | | Timeout between reindexing internal transaction batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) | 0 | v6.10.0+ | | v7.0.0 +| `FILECOIN_PENDING_ADDRESS_OPERATIONS_MIGRATION_BATCH_SIZE` | | Specifies the number of address records processed per batch during the backfill of pending address fetch operations. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). | 100 | v6.9.0+ | | v7.0.0 +| `FILECOIN_PENDING_ADDRESS_OPERATIONS_MIGRATION_CONCURRENCY` | | Specifies the number of concurrent processes used during the backfill of pending address fetch operations. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). | 1 | v6.9.0+ | | v7.0.0 +| `ARBITRUM_DA_RECORDS_NORMALIZATION_MIGRATION_BATCH_SIZE` | | Specifies the number of address records processed per batch during normalization of batch-to-blob associations by moving them from arbitrum_da_multi_purpose to a dedicated arbitrum_batches_to_da_blobs table. Implemented in [#11798](https://github.com/blockscout/blockscout/pull/11798). | 500 | v6.10.1+ | | v7.0.0 +| `ARBITRUM_DA_RECORDS_NORMALIZATION_MIGRATION_CONCURRENCY` | | Specifies the number of concurrent processes used during normalization of batch-to-blob associations by moving them from arbitrum_da_multi_purpose to a dedicated arbitrum_batches_to_da_blobs table. Implemented in [#11798](https://github.com/blockscout/blockscout/pull/11798). | 1 | v6.10.1+ | | v7.0.0 + + +## 6.10.2 + +### ⚙️ Miscellaneous Tasks + +- Add captcha to account wallet login as well ([#11682](https://github.com/blockscout/blockscout/issues/11682)) + +### New ENV Variables + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `RE_CAPTCHA_BYPASS_TOKEN` | Bypass token that allows to skip reCAPTCHA check. Implemented in [#11682](https://github.com/blockscout/blockscout/pull/11682) |

Version: v6.10.2+
Default: (empty)
Applications: API

+ +## 6.10.1 + +### 🚀 Features + +- Support OP Holocene upgrade ([#11355](https://github.com/blockscout/blockscout/issues/11355)) +- Add active DB connections metric ([#11321](https://github.com/blockscout/blockscout/issues/11321)) +- Add protocol icon to the search result ([#11478](https://github.com/blockscout/blockscout/issues/11478)) + +### 🐛 Bug Fixes + +- Remove unnecessary internal transactions preload ([#11643](https://github.com/blockscout/blockscout/issues/11643)) +- Fix bug in Indexer.Fetcher.EmptyBlocksSanitizer module ([#11636](https://github.com/blockscout/blockscout/pull/11636)) +- Multichain search: process address in chunks ([#11632](https://github.com/blockscout/blockscout/issues/11632)) +- Fix transactions deadlock ([#11623](https://github.com/blockscout/blockscout/issues/11623)) +- Fix tokens and transactions deadlocks ([#11620](https://github.com/blockscout/blockscout/issues/11620)) +- Order address names to return the latest non-primary ([#11612](https://github.com/blockscout/blockscout/issues/11612)) +- Rename tx_burnt_fee prop in API v2 endpoint ([#11563](https://github.com/blockscout/blockscout/issues/11563)) +- Celo fee handler ([#11387](https://github.com/blockscout/blockscout/issues/11387)) +- Fix addresses deadlock ([#11616](https://github.com/blockscout/blockscout/issues/11616)) +- Besu raw trace ([#11413](https://github.com/blockscout/blockscout/issues/11413)) +- Fix tokens deadlock ([#11603](https://github.com/blockscout/blockscout/issues/11603)) +- Set timeout: :infinity for PendingTransactionsSanitizer delete ([#11600](https://github.com/blockscout/blockscout/issues/11600)) +- Fixed Missing Closing Quotation Marks in sed Expressions Update version_bump.sh ([#11574](https://github.com/blockscout/blockscout/issues/11574)) +- The same DA blobs for different Arbitrum batches ([#11485](https://github.com/blockscout/blockscout/issues/11485)) +- Extended list of apps in the devcontainer helper script ([#11396](https://github.com/blockscout/blockscout/issues/11396)) +- Fix MarketHistory test ([#11547](https://github.com/blockscout/blockscout/issues/11547)) +- Advanced-filters csv format ([#11494](https://github.com/blockscout/blockscout/issues/11494)) +- Fix verifyproxycontract endpoint ([#11523](https://github.com/blockscout/blockscout/issues/11523)) +- Fix minor grammatical issue Update README.md ([#11544](https://github.com/blockscout/blockscout/issues/11544)) + +### 📚 Documentation + +- Typo fix Update README.md ([#11595](https://github.com/blockscout/blockscout/issues/11595)) +- Typo fix Update CODE_OF_CONDUCT.md ([#11572](https://github.com/blockscout/blockscout/issues/11572)) +- Fix minor grammar and phrasing inconsistencies Update README.md ([#11548](https://github.com/blockscout/blockscout/issues/11548)) +- Fixed incorrect usage of -d flag in stop containers command Update README.md ([#11522](https://github.com/blockscout/blockscout/issues/11522)) + +### ⚡ Performance + +- Implement batched requests and DB upsert operations Indexer.Fetcher.EmptyBlocksSanitizer module ([#11555](https://github.com/blockscout/blockscout/issues/11555)) + +### ⚙️ Miscellaneous Tasks + +- Remove unused Explorer.Token.InstanceOwnerReader module ([#11570](https://github.com/blockscout/blockscout/issues/11570)) +- Optimize coin balances deriving ([#11613](https://github.com/blockscout/blockscout/issues/11613)) +- Fix typo Update CHANGELOG.md ([#11607](https://github.com/blockscout/blockscout/issues/11607)) +- Add env variable for PendingTransactionsSanitizer interval ([#11601](https://github.com/blockscout/blockscout/issues/11601)) +- Documentation for Explorer.Chain.Transaction.History.Historian ([#11397](https://github.com/blockscout/blockscout/issues/11397)) +- Extend error message on updating token balance with token id ([#11524](https://github.com/blockscout/blockscout/issues/11524)) + +### New ENV Variables + +| Variable | Description | Parameters | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `INDEXER_PENDING_TRANSACTIONS_SANITIZER_INTERVAL` | Interval between pending transactions sanitizing. Implemented in [#11601](https://github.com/blockscout/blockscout/pull/11601). |

Version: v6.10.1
Default: 1h
Applications: Indexer

| + +## 6.10.0 + +### 🚀 Features + +- Addresses blacklist support ([#11417](https://github.com/blockscout/blockscout/issues/11417)) +- Multichain search DB filling ([#11139](https://github.com/blockscout/blockscout/issues/11139)) +- Zilliqa scilla transactions and smart contracts ([#11069](https://github.com/blockscout/blockscout/issues/11069)) +- CDN ([#10675](https://github.com/blockscout/blockscout/issues/10675)) +- Arbitrum L2->L1 message claiming ([#10804](https://github.com/blockscout/blockscout/issues/10804)) +- Add is_banned to token_instances table ([#11235](https://github.com/blockscout/blockscout/issues/11235)) +- Add CSV export of epoch transactions for address ([#11195](https://github.com/blockscout/blockscout/issues/11195)) +- Add request to /cache/{tx_hash} of transaction interpreter ([#11279](https://github.com/blockscout/blockscout/issues/11279)) +- Switch DB requests from replica to master in case of replica inaccessibility ([#11020](https://github.com/blockscout/blockscout/issues/11020)) +- Add gzip encoding option ([#11292](https://github.com/blockscout/blockscout/issues/11292)) +- Add Stylus verification support ([#11183](https://github.com/blockscout/blockscout/issues/11183)) +- Multiple json rpc urls ([#10934](https://github.com/blockscout/blockscout/issues/10934)) +- Gas prices with base fee if no transactions ([#11132](https://github.com/blockscout/blockscout/issues/11132)) +- Zilliqa consensus data related to block ([#10699](https://github.com/blockscout/blockscout/issues/10699)) +- Add filecoin robust addresses to proxy implementations ([#11102](https://github.com/blockscout/blockscout/issues/11102)) + +### 🐛 Bug Fixes + +- Limit max decimals value ([#11493](https://github.com/blockscout/blockscout/issues/11493)) +- Ignore unknown transaction receipt fields ([#11492](https://github.com/blockscout/blockscout/issues/11492)) +- Fixed issue in db request (l2_to_l1_message_by_id/2) ([#11481](https://github.com/blockscout/blockscout/issues/11481)) +- Handle float time in compose_gas_price/5 ([#11476](https://github.com/blockscout/blockscout/issues/11476)) +- Fix 500 on disabled metadata service ([#11443](https://github.com/blockscout/blockscout/issues/11443)) +- Fix get_media_url_from_metadata_for_nft_media_handler/1 ([#11437](https://github.com/blockscout/blockscout/issues/11437)) +- Fix check-redirect for ENS ([#11435](https://github.com/blockscout/blockscout/issues/11435)) +- Refactor CDN upload functions, prevent saving partially uploaded thumbnails ([#11400](https://github.com/blockscout/blockscout/issues/11400)) +- Take into account several proofs in OP Withdrawals ([#11399](https://github.com/blockscout/blockscout/issues/11399)) +- Handle "null" in paging options ([#11388](https://github.com/blockscout/blockscout/issues/11388)) +- Fix search timeout ([#11277](https://github.com/blockscout/blockscout/issues/11277)) +- Fix Noves.fi endpoints for bulk transactions ([#11375](https://github.com/blockscout/blockscout/issues/11375)) +- Fix docker container build after adding NFT media handler ([#11373](https://github.com/blockscout/blockscout/issues/11373)) +- Handle simultaneous account entities creation ([#11341](https://github.com/blockscout/blockscout/issues/11341)) +- Websocket configuration ([#11357](https://github.com/blockscout/blockscout/issues/11357)) +- 403 instead of 404 on wrong captcha in api/v1 ([#11348](https://github.com/blockscout/blockscout/issues/11348)) +- Upgrade fallback urls propagation ([#11331](https://github.com/blockscout/blockscout/issues/11331)) +- Add utils to dockerfile ([#11345](https://github.com/blockscout/blockscout/issues/11345)) +- Fix log decoding bug ([#11266](https://github.com/blockscout/blockscout/issues/11266)) +- Return 404 instead of 200 for nonexistent NFT ([#11280](https://github.com/blockscout/blockscout/issues/11280)) +- Fix metrics modules warnings ([#11340](https://github.com/blockscout/blockscout/issues/11340)) +- Handle entries with not specified `retries_count` ([#11206](https://github.com/blockscout/blockscout/issues/11206)) +- Get rid of scientific notation in CSV token holders export ([#11281](https://github.com/blockscout/blockscout/issues/11281)) +- Wrong usage of env in TokenInstanceMetadataRefetch ([#11317](https://github.com/blockscout/blockscout/issues/11317)) +- Rework initialization of the `RollupL1ReorgMonitor` and fix `read_system_config` for fallback cases ([#11275](https://github.com/blockscout/blockscout/issues/11275)) +- Eth_getLogs paging ([#11248](https://github.com/blockscout/blockscout/issues/11248)) +- Handle excessive otp confirmations ([#11244](https://github.com/blockscout/blockscout/issues/11244)) +- Check if flash is fetched before getting it in app.html ([#11270](https://github.com/blockscout/blockscout/issues/11270)) +- Multiple json rpc urls fixes ([#11264](https://github.com/blockscout/blockscout/issues/11264)) +- Handle eth rpc request without params ([#11269](https://github.com/blockscout/blockscout/issues/11269)) +- Fixate 6.9.2 as the latest release ([#11265](https://github.com/blockscout/blockscout/issues/11265)) +- Fix ETH JSON RPC deriving for Stylus verification ([#11247](https://github.com/blockscout/blockscout/issues/11247)) +- Fix fake json_rpc_named_arguments for multiple urls usage ([#11243](https://github.com/blockscout/blockscout/issues/11243)) +- Handle simultaneous api key creation ([#11233](https://github.com/blockscout/blockscout/issues/11233)) +- Fixate 6.9.1 as the latest release in master branch +- Invalid metadata requests ([#11210](https://github.com/blockscout/blockscout/issues/11210)) +- *(nginx-conf)* Redirect `/api-docs` to frontend. ([#11202](https://github.com/blockscout/blockscout/issues/11202)) +- Fix failed filecoin tests ([#11187](https://github.com/blockscout/blockscout/issues/11187)) +- Fix missing `signers` field in nested quorum certificate ([#11185](https://github.com/blockscout/blockscout/issues/11185)) +- Return `l1_tx_hashes` in the response of /batches/da/celestia/... API endpoint ([#11184](https://github.com/blockscout/blockscout/issues/11184)) +- Omit pbo for blocks lower than trace first block for indexing status ([#11053](https://github.com/blockscout/blockscout/issues/11053)) +- Update overview.html.eex ([#11094](https://github.com/blockscout/blockscout/issues/11094)) +- Fix sitemap timeout; optimize OrderedCache preloads ([#11131](https://github.com/blockscout/blockscout/issues/11131)) + +### 🚜 Refactor + +- Cspell configuration ([#11146](https://github.com/blockscout/blockscout/issues/11146)) + +### ⚡ Performance + +- Advanced filters optimization ([#11186](https://github.com/blockscout/blockscout/issues/11186)) + +### ⚙️ Miscellaneous Tasks + +- Return old response format in /api/v1/health endpoint ([#11511](https://github.com/blockscout/blockscout/issues/11511)) +- Rename blob_tx_count per naming conventions ([#11438](https://github.com/blockscout/blockscout/issues/11438)) +- Follow updated response schema in interpreter microservice ([#11402](https://github.com/blockscout/blockscout/issues/11402)) +- Remove raise in case if ETHEREUM_JSONRPC_HTTP_URL is not provided ([#11392](https://github.com/blockscout/blockscout/issues/11392)) +- Optimize tokens import ([#11389](https://github.com/blockscout/blockscout/issues/11389)) +- Remove beta suffix from releases ([#11376](https://github.com/blockscout/blockscout/issues/11376)) +- Background migrations timeout ([#11358](https://github.com/blockscout/blockscout/issues/11358)) +- Remove obsolete compile-time vars ([#11336](https://github.com/blockscout/blockscout/issues/11336)) +- Fixate Postgres 17 version in Docker compose and Github Actions workflows ([#11334](https://github.com/blockscout/blockscout/issues/11334)) +- Remove shorthands-duplicates from API responses ([#11319](https://github.com/blockscout/blockscout/issues/11319)) +- Refactor compile time envs usage ([#11148](https://github.com/blockscout/blockscout/issues/11148)) +- Refactor Dockerfile ([#11130](https://github.com/blockscout/blockscout/issues/11130)) +- Refactor import stages ([#11013](https://github.com/blockscout/blockscout/issues/11013)) +- Optimize CurrentTokenBalances import runner ([#11191](https://github.com/blockscout/blockscout/issues/11191)) +- Fix watchlist address flaking test ([#11242](https://github.com/blockscout/blockscout/issues/11242)) +- OP modules improvements ([#11073](https://github.com/blockscout/blockscout/issues/11073)) +- Invalid association `token_transfers` ([#11204](https://github.com/blockscout/blockscout/issues/11204)) +- Update Github Actions packages versions ([#11144](https://github.com/blockscout/blockscout/issues/11144)) +- Convenient way to manage known_hosts within devcontainer ([#11091](https://github.com/blockscout/blockscout/issues/11091)) +- Add docker compose file without microservices ([#11097](https://github.com/blockscout/blockscout/issues/11097)) + +### New ENV Variables + +| Variable | Description | Parameters | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `ETHEREUM_JSONRPC_HTTP_URLS` | Analogue of `ETHEREUM_JSONRPC_HTTP_URL` for multiple values. Implemented in [#10934](https://github.com/blockscout/blockscout/pull/10934) |

Version: v6.10.0+
Default: (empty)
Applications: API, Indexer

| +| `ETHEREUM_JSONRPC_FALLBACK_HTTP_URLS` | Analogue of `ETHEREUM_JSONRPC_FALLBACK_HTTP_URL` for multiple values. Implemented in [#10934](https://github.com/blockscout/blockscout/pull/10934) |

Version: v6.10.0+
Default: (empty)
Applications: API, Indexer

| +| `ETHEREUM_JSONRPC_TRACE_URLS` | Analogue of `ETHEREUM_JSONRPC_TRACE_URL` for multiple values. Implemented in [#10934](https://github.com/blockscout/blockscout/pull/10934) |

Version: v6.10.0+
Default: (empty)
Applications: API, Indexer

| +| `ETHEREUM_JSONRPC_FALLBACK_TRACE_URLS` | Analogue of `ETHEREUM_JSONRPC_FALLBACK_TRACE_URL` for multiple values. Implemented in [#10934](https://github.com/blockscout/blockscout/pull/10934) |

Version: v6.10.0+
Default: (empty)
Applications: API, Indexer

| +| `ETHEREUM_JSONRPC_ETH_CALL_URLS` | Analogue of `ETHEREUM_JSONRPC_ETH_CALL_URL` for multiple values. Implemented in [#10934](https://github.com/blockscout/blockscout/pull/10934) |

Version: v6.10.0+
Default: (empty)
Applications: API, Indexer

| +| `ETHEREUM_JSONRPC_FALLBACK_ETH_CALL_URLS` | Analogue of `ETHEREUM_JSONRPC_FALLBACK_ETH_CALL_URL` for multiple values. Implemented in [#10934](https://github.com/blockscout/blockscout/pull/10934) |

Version: v6.10.0+
Default: (empty)
Applications: API, Indexer

| +| `ETHEREUM_JSONRPC_HTTP_GZIP_ENABLED` | If `true`, then send gzip encoding header and expect encoding in response. Implemented in [#11292](https://github.com/blockscout/blockscout/pull/11292). |

Version: v6.10.0+
Default: false
Applications: API, Indexer

| +| `REPLICA_MAX_LAG` | Defines the max lag for read-only replica. If the actual lag is higher than this, replica is considered unavailable and all requests to it are redirected to main DB. Implemented in [#11020](https://github.com/blockscout/blockscout/pull/11020) |

Version: v6.10.0+
Default: 5m
Applications: API

| +| `SANITIZE_INCORRECT_NFT_TIMEOUT` | Timeout between sanitizing token transfer batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) |

Version: v6.10.0+
Default: 0
Applications: API, Indexer

| +| `SANITIZE_INCORRECT_WETH_TIMEOUT` | Timeout between sanitizing token transfer batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) |

Version: v6.10.0+
Default: 0
Applications: API, Indexer

| +| `REINDEX_INTERNAL_TRANSACTIONS_STATUS_BATCH_SIZE` | Number of internal transactions to reindex in the batch. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) |

Version: v6.10.0+
Default: 100
Applications: API, Indexer

| +| `REINDEX_INTERNAL_TRANSACTIONS_STATUS_CONCURRENCY` | Number of parallel reindexing internal transaction batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) |

Version: v6.10.0+
Default: 1
Applications: API, Indexer

| +| `REINDEX_INTERNAL_TRANSACTIONS_STATUS_TIMEOUT` | Timeout between reindexing internal transaction batches processing. Implemented in [#11358](https://github.com/blockscout/blockscout/pull/11358) |

Version: v6.10.0+
Default: 0
Applications: API, Indexer

| +| `NFT_MEDIA_HANDLER_AWS_ACCESS_KEY_ID` | S3 API Access Key ID |

Version: v6.10.0+
Default: (empty)
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_AWS_SECRET_ACCESS_KEY` | S3 API Secret Access Key |

Version: v6.10.0+
Default: (empty)
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_AWS_BUCKET_HOST` | S3 API URL |

Version: v6.10.0+
Default: (empty)
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_AWS_BUCKET_NAME` | S3 bucket name |

Version: v6.10.0+
Default: (empty)
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_AWS_PUBLIC_BUCKET_URL` | Public S3 bucket URL |

Version: v6.10.0+
Default: (empty)
Applications: API

| +| `NFT_MEDIA_HANDLER_ENABLED` | if `true`, CDN feature enabled |

Version: v6.10.0+
Default: false
Applications: Indexer, NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_REMOTE_DISPATCHER_NODE_MODE_ENABLED` | if `true`, nft media handler is supposed to run separately. |

Version: v6.10.0+
Default: false
Applications: Indexer, NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_IS_WORKER` | if `true`, and `NFT_MEDIA_HANDLER_REMOTE_DISPATCHER_NODE_MODE_ENABLED=true` will be started only nft_media_handler app |

Version: v6.10.0+
Default: false
Applications: Indexer, NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_NODES_MAP` | String in json map format, where key is erlang node and value is folder in R2/S3 bucket, example: `"{\"producer@172.18.0.4\": \"/folder_1\"}"`. If nft_media_handler runs in one pod with indexer, map should contain `self` key |

Version: v6.10.0+
Default: (empty)
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_WORKER_CONCURRENCY` | Concurrency of media handling (resizing/uploading) |

Version: v6.10.0+
Default: 10
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_WORKER_BATCH_SIZE` | Number of url processed by one async task |

Version: v6.10.0+
Default: 10
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_WORKER_SPAWN_TASKS_TIMEOUT` | Timeout before spawn new task |

Version: v6.10.0+
Default: 100ms
Applications: NFT_MEDIA_HANDLER

| +| `NFT_MEDIA_HANDLER_BACKFILL_ENABLED` | If `true`, unprocessed token instances from DB will be processed via nft_media_handler |

Version: v6.10.0+
Default: false
Applications: Indexer

| +| `NFT_MEDIA_HANDLER_BACKFILL_QUEUE_SIZE` | Max size of backfill queue |

Version: v6.10.0+
Default: 1000
Applications: Indexer

| +| `NFT_MEDIA_HANDLER_BACKFILL_ENQUEUE_BUSY_WAITING_TIMEOUT` | Timeout before new attempt to append item to backfill queue if it's full |

Version: v6.10.0+
Default: 1s
Applications: Indexer

| +| `NFT_MEDIA_HANDLER_CACHE_UNIQUENESS_MAX_SIZE` | Max size of cache, where stored already uploaded token instances media |

Version: v6.10.0+
Default: 100_000
Applications: Indexer

| +| `ADDRESSES_BLACKLIST` | A comma-separated list of addresses to enable restricted access to them. |

Version: v6.10.0+
Default: (empty)
Applications: API

| +| `ADDRESSES_BLACKLIST_KEY` | A key to access blacklisted addresses (either by `ADDRESSES_BLACKLIST` or by blacklist provider). Can be passed via query param to the page's URL: `?key=...` |

Version: v6.10.0+
Default: (empty)
Applications: API

| +| `ADDRESSES_BLACKLIST_PROVIDER` | Blacklist provider type, available options: `blockaid` |

Version: v6.10.0+
Default: blockaid
Applications: API

| +| `ADDRESSES_BLACKLIST_URL` | URL to fetch blacklist from |

Version: v6.10.0+
Default: (empty)
Applications: API

| +| `ADDRESSES_BLACKLIST_UPDATE_INTERVAL` | Interval between scheduled updates of blacklist |

Version: v6.10.0+
Default: 15m
Applications: API

| +| `ADDRESSES_BLACKLIST_RETRY_INTERVAL` | Time to wait before new attempt of blacklist fetching, after abnormal termination of fetching task |

Version: v6.10.0+
Default: 5s
Applications: API

| +| `MICROSERVICE_MULTICHAIN_SEARCH_URL` | Multichain Search Service API URL. Integration is enabled, if this variable value contains valid URL. Implemented in [#11139](https://github.com/blockscout/blockscout/pull/11139) |

Version: master
Default: (empty)
Applications: API, Indexer

| +| `MICROSERVICE_MULTICHAIN_SEARCH_API_KEY` | Multichain Search Service API key. Implemented in [#11139](https://github.com/blockscout/blockscout/pull/11139) |

Version: master
Default: (empty)
Applications: API, Indexer

| +| `MIGRATION_BACKFILL_MULTICHAIN_SEARCH_BATCH_SIZE` | Batch size of backfilling Multichain Search Service DB. Implemented in [#11139](https://github.com/blockscout/blockscout/pull/11139) |

Version: master
Default: (empty)
Applications: Indexer

| + +### Deprecated ENV Variables + + +| Variable | Required | Description | Default | Version | Need recompile | Deprecated in Version | +| ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | -------------- | --------------------- | +| `RESTRICTED_LIST` | | A comma-separated list of addresses to enable restricted access to them. | (empty) | v3.3.3+ | | v6.10.0 | +| `RESTRICTED_LIST_KEY` | | A key to access addresses listed in`RESTRICTED_LIST` variable. Can be passed via query param to the page's URL: `?key=...` | (empty) | v3.3.3+ | | v6.10.0 | + +## 6.9.2 + +### 🚀 Features + +- Xname app proxy ([#11010](https://github.com/blockscout/blockscout/issues/11010)) + +| Variable | Description | Parameters | +| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | +| `XNAME_BASE_API_URL` | [Xname API](https://xname.app/) base URL. Implemented in [#11010](https://github.com/blockscout/blockscout/pull/11010). |

Version: v6.9.2+
Default: https://gateway.xname.app
Applications: API

| +| `XNAME_API_TOKEN` | [Xname API](https://xname.app/) token. Implemented in [#11010](https://github.com/blockscout/blockscout/pull/11010). |

Version: v6.9.2+
Default: (empty)
Applications: API

+ +## 6.9.1 + +### 🐛 Bug Fixes + +- Add `auth0-forwarded-for` header in auth0 ([#11178](https://github.com/blockscout/blockscout/issues/11178)) + +### ⚙️ Miscellaneous Tasks + +- Extend recaptcha logging ([#11182](https://github.com/blockscout/blockscout/issues/11182)) + + +| Variable | Description | Parameters | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `RE_CAPTCHA_SCORE_THRESHOLD`| Changes reCAPTCHA score threshold. Implemented in [#11182](https://github.com/blockscout/blockscout/pull/11182) |

Version: v6.9.1+
Default: 0.5
Applications: API

| + +## 6.9.0 + +### 🚀 Features + +- Support zksync foundry verification ([#11037](https://github.com/blockscout/blockscout/issues/11037)) +- Address transactions block number sorting ([#11035](https://github.com/blockscout/blockscout/issues/11035)) +- Scroll rollup: L1 fee parameters in API, `queueIndex` for L2 transactions, and L1 <->L2 messages ([#10484](https://github.com/blockscout/blockscout/issues/10484)) +- Account V2 ([#10706](https://github.com/blockscout/blockscout/issues/10706)) +- Allow to provide DB schema other than public ([#10946](https://github.com/blockscout/blockscout/issues/10946)) +- Add missing filecoin robust addresses ([#10935](https://github.com/blockscout/blockscout/issues/10935)) +- EIP-7702 support ([#10870](https://github.com/blockscout/blockscout/issues/10870)) +- Open access to re-fetch metadata button for token instances without metadata initially fetched ([#10878](https://github.com/blockscout/blockscout/issues/10878)) +- Support snake_case in metadata service ([#10722](https://github.com/blockscout/blockscout/issues/10722)) +- Token transfers list API v2 endpoint ([#10801](https://github.com/blockscout/blockscout/issues/10801)) +- Send archive balances requests to trace url ([#10820](https://github.com/blockscout/blockscout/issues/10820)) +- Add metadata info to tx interpreter request ([#10823](https://github.com/blockscout/blockscout/issues/10823)) +- Api for querying mud systems abi ([#10829](https://github.com/blockscout/blockscout/issues/10829)) +- Arbitrum L1-to-L2 messages with hashed message id ([#10751](https://github.com/blockscout/blockscout/issues/10751)) +- Support CoinMarketCap format in token supply stats ([#10853](https://github.com/blockscout/blockscout/issues/10853)) +- Address scam badge flag ([#10763](https://github.com/blockscout/blockscout/issues/10763)) +- Add verbosity to GraphQL token transfers query ([#10770](https://github.com/blockscout/blockscout/issues/10770)) +- (celo) include token information in API response for address epoch rewards ([#10831](https://github.com/blockscout/blockscout/issues/10831)) +- Add Blackfort validators ([#10744](https://github.com/blockscout/blockscout/issues/10744)) +- Retry ERC-1155 token instance metadata fetch from baseURI + tokenID ([#10766](https://github.com/blockscout/blockscout/issues/10766)) + +### 🐛 Bug Fixes + +- Fix tokennfttx API v1 endpoint ([#11083](https://github.com/blockscout/blockscout/issues/11083)) +- Fix contract codes fetching for zksync chain type ([#11055](https://github.com/blockscout/blockscout/issues/11055)) +- Filter non-traceable blocks before inserting them to internal txs fetcher queue ([#11074](https://github.com/blockscout/blockscout/issues/11074)) +- Import blocks before coin balances ([#11049](https://github.com/blockscout/blockscout/issues/11049)) +- Abi cache for non-proxied addresses ([#11065](https://github.com/blockscout/blockscout/issues/11065)) +- Celo collated gas price issue ([#11067](https://github.com/blockscout/blockscout/issues/11067)) +- Indexer memory limit for api instance ([#11066](https://github.com/blockscout/blockscout/issues/11066)) +- Fix scam badge value in some API endpoints ([#11054](https://github.com/blockscout/blockscout/issues/11054)) +- Divide by `10^decimals` when calculating token supply in CMC format ([#11036](https://github.com/blockscout/blockscout/issues/11036)) +- Rename zksync l1/l2 _tx_count columns ([#11051](https://github.com/blockscout/blockscout/issues/11051)) +- Bugs introduced in calldata decoding optimizations ([#11025](https://github.com/blockscout/blockscout/issues/11025)) +- Handle stalled async task in MapCache ([#11015](https://github.com/blockscout/blockscout/issues/11015)) +- Add tx_count, tx_types props in the response of address API v2 endpoints for compatibility with current version of the frontend ([#11012](https://github.com/blockscout/blockscout/issues/11012)) +- Chart API: add compatibility with the current frontend ([#11008](https://github.com/blockscout/blockscout/issues/11008)) +- Fix failed tests ([#11000](https://github.com/blockscout/blockscout/issues/11000)) +- Add compatibility with current frontend for some public props ([#10998](https://github.com/blockscout/blockscout/issues/10998)) +- Process foreign key violation in scam addresses assigning functionality ([#10977](https://github.com/blockscout/blockscout/issues/10977)) +- Handle import exceptions in MassiveBlocksFetcher ([#10993](https://github.com/blockscout/blockscout/issues/10993)) +- Workaround for repeating logIndex ([#10880](https://github.com/blockscout/blockscout/issues/10880)) +- Filter out nil implementations from combine_proxy_implementation_addresses_map function result ([#10943](https://github.com/blockscout/blockscout/issues/10943)) +- Delete incorrect coin balances on reorg ([#10879](https://github.com/blockscout/blockscout/issues/10879)) +- Handle delegatecall in state changes ([#10906](https://github.com/blockscout/blockscout/issues/10906)) +- Fix env. variables link in README.md ([#10898](https://github.com/blockscout/blockscout/issues/10898)) +- Add missing block timestamp in election rewards for address response ([#10907](https://github.com/blockscout/blockscout/issues/10907)) +- Add missing build arg to celo workflow ([#10895](https://github.com/blockscout/blockscout/issues/10895)) +- Do not include unrelated token transfers in `tokenTransferTxs` ([#10889](https://github.com/blockscout/blockscout/issues/10889)) +- Fix get current user in app template ([#10844](https://github.com/blockscout/blockscout/issues/10844)) +- Set `API_GRAPHQL_MAX_COMPLEXITY` in build action ([#10843](https://github.com/blockscout/blockscout/issues/10843)) +- Disable archive balances only if latest block is available ([#10851](https://github.com/blockscout/blockscout/issues/10851)) +- Dialyzer warning ([#10845](https://github.com/blockscout/blockscout/issues/10845)) +- Decode revert reason by decoding candidates from the DB ([#10827](https://github.com/blockscout/blockscout/issues/10827)) +- Filecoin stuck pending address operations ([#10832](https://github.com/blockscout/blockscout/issues/10832)) +- Sanitize replaced transactions migration ([#10784](https://github.com/blockscout/blockscout/issues/10784)) +- Repair /metrics endpoint ([#10813](https://github.com/blockscout/blockscout/issues/10813)) +- Revert the deletion of deriving current token balances ([#10811](https://github.com/blockscout/blockscout/issues/10811)) +- Clear null round blocks from missing block ranges ([#10805](https://github.com/blockscout/blockscout/issues/10805)) +- Decode addresses as checksummed ([#10777](https://github.com/blockscout/blockscout/issues/10777)) +- Preload additional sources for bytecode twin smart-contract ([#10692](https://github.com/blockscout/blockscout/issues/10692)) +- Set min query length in the search API endpoints ([#10698](https://github.com/blockscout/blockscout/issues/10698)) +- Proper handling of old batches on Arbitrum Nova ([#10786](https://github.com/blockscout/blockscout/issues/10786)) +- Get rid of heavy DB query to start Arbitrum missed messages discovery process ([#10767](https://github.com/blockscout/blockscout/issues/10767)) +- Revisited approach to choose L1 blocks to discover missing Arbitrum batches ([#10757](https://github.com/blockscout/blockscout/issues/10757)) +- Fix account db repo definition ([#10714](https://github.com/blockscout/blockscout/issues/10714)) +- Allow string IDs in JSON RPC requests ([#10759](https://github.com/blockscout/blockscout/issues/10759)) +- Filter out tokens with skip_metadata: true from token fetcher ([#10736](https://github.com/blockscout/blockscout/issues/10736)) + +### 🚜 Refactor + +- Fixate naming convention for "transaction" and "block number" entities ([#10913](https://github.com/blockscout/blockscout/issues/10913)) +- Use middleware to check if GraphQL API is enabled ([#10772](https://github.com/blockscout/blockscout/issues/10772)) + +### ⚡ Performance + +- Fix performance of Explorer.Counters.Transactions24hStats.consolidate/0 function ([#11082](https://github.com/blockscout/blockscout/issues/11082)) +- Optimize advanced filters ([#10463](https://github.com/blockscout/blockscout/issues/10463)) +- Refactor tx data decoding with fewer DB queries ([#10842](https://github.com/blockscout/blockscout/issues/10842)) + +### ⚙️ Miscellaneous Tasks + +- Update version bump script +- Remove deprecated single implementation property of the smart-contract from the API response ([#10715](https://github.com/blockscout/blockscout/issues/10715)) +- Set indexer memory limit based on system info as a fallback ([#10697](https://github.com/blockscout/blockscout/issues/10697)) +- Set user agent to metadata requests ([#10834](https://github.com/blockscout/blockscout/issues/10834)) +- Reverse internal transactions fetching order ([#10912](https://github.com/blockscout/blockscout/issues/10912)) +- Remove unused fetch_and_lock_by_hashes/1 public function +- Add shrink int txs docker image build for Celo chain type ([#10894](https://github.com/blockscout/blockscout/issues/10894)) +- Ability to work with Blockscout code base within a VSCode devcontainer ([#10838](https://github.com/blockscout/blockscout/issues/10838)) +- Add version bump script ([#10871](https://github.com/blockscout/blockscout/issues/10871)) +- Bump elixir to 1.17.3 and Erlang OTP to 27.1 ([#10284](https://github.com/blockscout/blockscout/issues/10284)) +- Reindex incorrect internal transactions migration ([#10654](https://github.com/blockscout/blockscout/issues/10654)) +- Remove old UI from base Docker image ([#10828](https://github.com/blockscout/blockscout/issues/10828)) +- Add primary key to address_tags table ([#10818](https://github.com/blockscout/blockscout/issues/10818)) +- Refactor OrderedCache preloads ([#10803](https://github.com/blockscout/blockscout/issues/10803)) +- Support non-unique log index for rsk chain type ([#10807](https://github.com/blockscout/blockscout/issues/10807)) +- Add missing symbols ([#10749](https://github.com/blockscout/blockscout/issues/10749)) + +### New ENV Variables + +| Variable | Description | Parameters | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `INDEXER_SYSTEM_MEMORY_PERCENTAGE` | Percentage of total memory available to the VM that an application can use if `INDEXER_MEMORY_LIMIT` is not set. Implemented in [#10697](https://github.com/blockscout/blockscout/pull/10697). |

Version: v6.9.0+
Default: 60
Applications: Indexer

| +| `INDEXER_TOKEN_BALANCES_EXPONENTIAL_TIMEOUT_COEFF` | Coefficient to calculate exponential timeout. Implemented in [#10694](https://github.com/blockscout/blockscout/pull/10694). |

Version: v6.9.0+
Default: 100
Applications: Indexer

| +| `INDEXER_INTERNAL_TRANSACTIONS_FETCH_ORDER` | Order of fetching internal transactions from node. Possible values: `asc`, `desc`. Implemented in [#10912](https://github.com/blockscout/blockscout/pull/10912) |

Version: v6.9.0+
Default: asc
Applications: Indexer

| +| `HIDE_SCAM_ADDRESSES` | Hides address of EOA/smart-contract/token from search results if the value is `true` and "scam" badge is assigned to that address. Implemented in [#10763](https://github.com/blockscout/blockscout/pull/10763) |

Version: v6.9.0+
Default: (empty)
Applications: API

| +| `RE_CAPTCHA_CHECK_HOSTNAME` | Disable reCAPTCHA hostname check. More details on [reCaptcha docs](https://developers.google.com/recaptcha/docs/domain\_validation). Implemented in [#10706](https://github.com/blockscout/blockscout/pull/10706) |

Version: v6.9.0+
Default: false
Applications: API

| +| `ACCOUNT_OTP_RESEND_INTERVAL` | Time before resending otp email. Implemented in [#10706](https://github.com/blockscout/blockscout/pull/10706). |

Version: v6.9.0+
Default: 1m
Applications: API

| +| `INDEXER_SCROLL_L1_RPC` | The RPC endpoint for L1 used to fetch Deposit and Withdrawal messages. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L1_CHAIN_CONTRACT` | The address of ScrollChain contract on L1. Used to fetch batch and bundle events. Implemented in [#10819](https://github.com/blockscout/blockscout/pull/10819). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L1_BATCH_START_BLOCK` | The number of a start block on L1 to index L1 batches and bundles. If the table of batches is not empty, the process will continue indexing from the last indexed batch. Implemented in [#10819](https://github.com/blockscout/blockscout/pull/10819). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L1_MESSENGER_CONTRACT` | The address of L1 Scroll Messenger contract on L1 used to fetch Deposit and Withdrawal messages. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L1_MESSENGER_START_BLOCK` | The number of a start block on L1 to index L1 bridge messages. If the table of bridge operations is not empty, the process will continue indexing from the last indexed L1 message. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L2_MESSENGER_CONTRACT` | The address of L2 Scroll Messenger contract on L2 used to fetch Deposit and Withdrawal messages. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L2_MESSENGER_START_BLOCK` | The number of a start block on L2 to index L2 bridge messages. If the table of bridge operations is not empty, the process will continue indexing from the last indexed L2 message. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `FIRST_BLOCK`
Applications: Indexer

| +| `INDEXER_SCROLL_L2_GAS_ORACLE_CONTRACT` | The address of L1 Gas Oracle contract on L2. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `INDEXER_SCROLL_L1_ETH_GET_LOGS_RANGE_SIZE` | Block range size for eth\_getLogs request in Scroll indexer modules for Layer 1. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `250`
Applications: Indexer

| +| `INDEXER_SCROLL_L2_ETH_GET_LOGS_RANGE_SIZE` | Block range size for eth\_getLogs request in Scroll indexer modules for Layer 2. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `1000`
Applications: Indexer

| +| `SCROLL_L2_CURIE_UPGRADE_BLOCK` | L2 block number of the Curie upgrade. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `SCROLL_L1_SCALAR_INIT` | Initial value for `scalar` parameter. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `SCROLL_L1_OVERHEAD_INIT` | Initial value for `overhead` parameter. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `SCROLL_L1_COMMIT_SCALAR_INIT` | Initial value for `commit_scalar` parameter. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `SCROLL_L1_BLOB_SCALAR_INIT` | Initial value for `blob_scalar` parameter. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `SCROLL_L1_BASE_FEE_INIT` | Initial value for `l1_base_fee` parameter. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `SCROLL_L1_BLOB_BASE_FEE_INIT` | Initial value for `l1_blob_base_fee` parameter. Implemented in [#10484](https://github.com/blockscout/blockscout/pull/10484). |

Version: v6.9.0+
Default: `0`
Applications: API

| +| `INDEXER_OPTIMISM_L1_DEPOSITS_TRANSACTION_TYPE` | Defines OP Deposit transaction type (numeric value) which is needed for correct L2 transaction hash calculation by the Deposits indexing module. Implemented in [#10674](https://github.com/blockscout/blockscout/pull/10674). |

Version: v6.9.0+
Default: 126
Applications: Indexer

| +| `INDEXER_DISABLE_CELO_VALIDATOR_GROUP_VOTES_FETCHER` | If set to `true`, the validator group votes fetcher will not be started. Implemented in [#10673](https://github.com/blockscout/blockscout/pull/10673). |

Version: v6.9.0+
Default: false
Applications: Indexer

| +| `FILECOIN_NETWORK_PREFIX` | Specifies the expected network prefix for Filecoin addresses. For more details, refer to the [Filecoin Spec](https://spec.filecoin.io/appendix/address/#section-appendix.address.network-prefix). Available values: `f` (for the mainnet), `t` (for testnets). Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Version: v6.9.0+
Default: f
Applications: API, Indexer

| +| `BERYX_API_TOKEN` | [Beryx API](https://docs.zondax.ch/beryx-api) token, used for retrieving Filecoin native addressing information. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Required: ✅
Version: v6.9.0+
Default: (empty)
Applications: Indexer

| +| `BERYX_API_BASE_URL` | [Beryx API](https://docs.zondax.ch/beryx-api) base URL. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Version: v6.9.0+
Default: https://api.zondax.ch/fil/data/v3/mainnet
Applications: Indexer

| +| `INDEXER_DISABLE_FILECOIN_ADDRESS_INFO_FETCHER` | When set to `true`, Filecoin native addressing information will not be fetched, but addresses pending fetch will still be recorded in the database. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Version: v6.9.0+
Default: false
Applications: Indexer

| +| `INDEXER_FILECOIN_ADDRESS_INFO_CONCURRENCY` | Sets the maximum number of concurrent requests made to fetch Filecoin native addressing information. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Version: v6.9.0+
Default: 1
Applications: Indexer

| +| `FILECOIN_PENDING_ADDRESS_OPERATIONS_MIGRATION_BATCH_SIZE` | Specifies the number of address records processed per batch during the backfill of pending address fetch operations. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Version: v6.9.0+
Default: 100
Applications: Indexer

| +| `FILECOIN_PENDING_ADDRESS_OPERATIONS_MIGRATION_CONCURRENCY` | Specifies the number of concurrent processes used during the backfill of pending address fetch operations. Implemented in [#10468](https://github.com/blockscout/blockscout/pull/10468). |

Version: v6.9.0+
Default: 1
Applications: Indexer

| +| `BLACKFORT_VALIDATOR_API_URL` | Variable to define the URL of the Blackfort Validator API. Implemented in [#10744](https://github.com/blockscout/blockscout/pull/10744). |

Version: v6.9.0+
Default: (empty)
Applications: API, Indexer

| + +## 6.8.1 + +### 🚀 Features + +- Add `INDEXER_OPTIMISM_L1_DEPOSITS_TRANSACTION_TYPE` env variable ([#10674](https://github.com/blockscout/blockscout/issues/10674)) +- Support for filecoin native addresses ([#10468](https://github.com/blockscout/blockscout/issues/10468)) + +### 🐛 Bug Fixes + +- Decoding of zero fields in mud ([#10764](https://github.com/blockscout/blockscout/issues/10764)) +- Insert coin balances placeholders in internal transactions fetcher ([#10603](https://github.com/blockscout/blockscout/issues/10603)) +- Avoid key violation error in `Indexer.Fetcher.Optimism.TxnBatch` ([#10752](https://github.com/blockscout/blockscout/issues/10752)) +- Fix empty current token balances ([#10745](https://github.com/blockscout/blockscout/issues/10745)) +- Allow disabling group votes fetcher independently of epoch block fetcher ([#10673](https://github.com/blockscout/blockscout/issues/10673)) +- Fix gettext usage warning ([#10693](https://github.com/blockscout/blockscout/issues/10693)) +- Truncate token symbol in Explorer.Chain.PolygonZkevm.BridgeL1Token ([#10688](https://github.com/blockscout/blockscout/issues/10688)) + +### ⚡ Performance + +- Improve performance of transactions list page ([#10734](https://github.com/blockscout/blockscout/issues/10734)) + +### ⚙️ Miscellaneous Tasks + +- Add meta to migrations_status ([#10678](https://github.com/blockscout/blockscout/issues/10678)) +- Token balances fetcher slow queue ([#10694](https://github.com/blockscout/blockscout/issues/10694)) +- Shrink sample response for the trace in Filecoin chain type +- Extend missing balanceOf function with :unable_to_decode error ([#10713](https://github.com/blockscout/blockscout/issues/10713)) +- Fix flaking explorer tests ([#10676](https://github.com/blockscout/blockscout/issues/10676)) +- Change shrink internal transactions migration default batch_size ([#10689](https://github.com/blockscout/blockscout/issues/10689)) + +## 6.8.0 + +### 🚀 Features + +- Detect Diamond proxy pattern on unverified proxy smart-contract ([#10665](https://github.com/blockscout/blockscout/pull/10665)) +- Support smart-contract verification in zkSync ([#10500](https://github.com/blockscout/blockscout/issues/10500)) +- Add icon for secondary coin ([#10241](https://github.com/blockscout/blockscout/issues/10241)) +- Integrate Cryptorank API ([#10550](https://github.com/blockscout/blockscout/issues/10550)) +- Enhance /api/v2/smart-contracts/:hash API endpoint ([#10558](https://github.com/blockscout/blockscout/issues/10558)) +- Add method name to transactions CSV export ([#10579](https://github.com/blockscout/blockscout/issues/10579)) +- Add /api/v2/proxy/metadata/addresses endpoint ([#10585](https://github.com/blockscout/blockscout/issues/10585)) +- More descriptive status for Arbitrum message for the transaction view ([#10593](https://github.com/blockscout/blockscout/issues/10593)) +- Add internal_transactions to Tx interpreter request ([#10347](https://github.com/blockscout/blockscout/issues/10347)) +- Add token decimals to token transfers CSV export ([#10589](https://github.com/blockscout/blockscout/issues/10589)) +- Add DELETE /api/v2/import/token-info method ([#10580](https://github.com/blockscout/blockscout/issues/10580)) +- Add block number to token transfer object in API v2 endpoint ([#10591](https://github.com/blockscout/blockscout/issues/10591)) +- L1 tx associated with Arbitrum message in /api/v2/transactions/{txHash} ([#10590](https://github.com/blockscout/blockscout/issues/10590)) +- No rate limit API key ([#10515](https://github.com/blockscout/blockscout/issues/10515)) +- Support for `:celo` chain type ([#10564](https://github.com/blockscout/blockscout/issues/10564)) +- Public IPFS gateway URL ([#10511](https://github.com/blockscout/blockscout/issues/10511)) +- Add CSV_EXPORT_LIMIT env ([#10497](https://github.com/blockscout/blockscout/issues/10497)) +- Backfiller for omitted WETH transfers ([#10466](https://github.com/blockscout/blockscout/issues/10466)) +- Add INDEXER_DISABLE_REPLACED_TRANSACTION_FETCHER env ([#10485](https://github.com/blockscout/blockscout/issues/10485)) +- Revisited approach to catchup missed Arbitrum messages ([#10374](https://github.com/blockscout/blockscout/issues/10374)) +- Missing Arbitrum batches re-discovery ([#10446](https://github.com/blockscout/blockscout/issues/10446)) +- Add memory metrics for OnDemand fetchers ([#10425](https://github.com/blockscout/blockscout/issues/10425)) +- Add Celestia blobs support to Optimism batches fetcher ([#10199](https://github.com/blockscout/blockscout/issues/10199)) +- AnyTrust and Celestia support as DA for Arbitrum batches ([#10144](https://github.com/blockscout/blockscout/issues/10144)) +- Broadcast updates about new Arbitrum batches and L1-L2 messages through WebSocket ([#10272](https://github.com/blockscout/blockscout/issues/10272)) + +### 🐛 Bug Fixes + +- Logs list serialization ([#10565](https://github.com/blockscout/blockscout/issues/10565)) +- nil in OrderedCache ([#10647](https://github.com/blockscout/blockscout/pull/10647)) +- Fix for metadata detection at ipfs protocol([#10646](https://github.com/blockscout/blockscout/pull/10646)) +- Fix bug in update_replaced_transactions query ([#10634](https://github.com/blockscout/blockscout/issues/10634)) +- Fix mode dependent processes starting ([#10641](https://github.com/blockscout/blockscout/issues/10641)) +- Better detection IPFS links in NFT metadata fetcher ([#10638](https://github.com/blockscout/blockscout/issues/10638)) +- Change mode env name ([#10636](https://github.com/blockscout/blockscout/issues/10636)) +- Proper default value of gas used for dropped Arbitrum transactions ([#10619](https://github.com/blockscout/blockscout/issues/10619)) +- Fix fetch_first_trace tests ([#10618](https://github.com/blockscout/blockscout/issues/10618)) +- Add SHRINK_INTERNAL_TRANSACTIONS_ENABLED arg to Dockerfile ([#10616](https://github.com/blockscout/blockscout/issues/10616)) +- Fix raw-trace test ([#10606](https://github.com/blockscout/blockscout/issues/10606)) +- Fix internal transaction validation ([#10443](https://github.com/blockscout/blockscout/issues/10443)) +- Fix internal transactions runner test for zetachain ([#10576](https://github.com/blockscout/blockscout/issues/10576)) +- Filter out incorrect L1-to-L2 Arbitrum messages ([#10570](https://github.com/blockscout/blockscout/issues/10570)) +- Fetch contract methods decoding candidates sorted by inserted_at ([#10529](https://github.com/blockscout/blockscout/issues/10529)) +- Sanitize topic value before making db query ([#10481](https://github.com/blockscout/blockscout/issues/10481)) +- Fix :checkout_timeout error on NFT fetching ([#10429](https://github.com/blockscout/blockscout/issues/10429)) +- Proper handling confirmations for Arbitrum rollup block in the middle of a batch ([#10482](https://github.com/blockscout/blockscout/issues/10482)) +- Sanitize contractURI response ([#10479](https://github.com/blockscout/blockscout/issues/10479)) +- Use token_type from tt instead of token ([#10555](https://github.com/blockscout/blockscout/issues/10555)) +- Non-consensus logs in JSON RPC and ETH RPC APIs ([#10545](https://github.com/blockscout/blockscout/issues/10545)) +- Fix address_to_logs consensus filtering ([#10528](https://github.com/blockscout/blockscout/issues/10528)) +- Error on internal transactions CSV export ([#10495](https://github.com/blockscout/blockscout/issues/10495)) +- Extend block search range for `getblocknobytime` method ([#10475](https://github.com/blockscout/blockscout/issues/10475)) +- Move recon dep to explorer mix.exs ([#10487](https://github.com/blockscout/blockscout/issues/10487)) +- Add missing condition to fetch_min_missing_block_cache ([#10478](https://github.com/blockscout/blockscout/issues/10478)) +- Mud api format fixes ([#10362](https://github.com/blockscout/blockscout/issues/10362)) +- Add no overlapping constraint to missing_block_ranges ([#10449](https://github.com/blockscout/blockscout/issues/10449)) +- Avoid infinite loop during batch block range binary search ([#10436](https://github.com/blockscout/blockscout/issues/10436)) +- Fix "key :bytes not found in: nil" issue ([#10435](https://github.com/blockscout/blockscout/issues/10435)) +- Missing clauses in MetadataPreloader functions ([#10439](https://github.com/blockscout/blockscout/issues/10439)) +- Code compiler test ([#10454](https://github.com/blockscout/blockscout/issues/10454)) +- Include internal transactions in state change ([#10210](https://github.com/blockscout/blockscout/issues/10210)) +- Race condition in cache tests ([#10441](https://github.com/blockscout/blockscout/issues/10441)) +- Fix on-demand fetchers metrics ([#10431](https://github.com/blockscout/blockscout/issues/10431)) +- Transactions and token transfers block_consensus ([#10285](https://github.com/blockscout/blockscout/issues/10285)) +- Allow fetching image from properties -> image prop in token instance metadata ([#10380](https://github.com/blockscout/blockscout/issues/10380)) +- Filter out internal transactions belonging to reorg ([#10330](https://github.com/blockscout/blockscout/issues/10330)) +- Fix logs sorting in API v1 ([#10405](https://github.com/blockscout/blockscout/issues/10405)) +- Fix flickering transaction_estimated_count/1 test ([#10403](https://github.com/blockscout/blockscout/issues/10403)) +- Fix flickering "updates cache if initial value is zero" tests ([#10402](https://github.com/blockscout/blockscout/issues/10402)) +- /addresses empty list flickering test fix ([#10400](https://github.com/blockscout/blockscout/issues/10400)) +- Fix missing expectation in mock_beacon_storage_pointer_request ([#10399](https://github.com/blockscout/blockscout/issues/10399)) +- Fix /stats/charts/market test ([#10392](https://github.com/blockscout/blockscout/issues/10392)) +- Alternative way to detect blocks range for ArbitrumOne batches ([#10295](https://github.com/blockscout/blockscout/issues/10295)) +- Fix exchange rate flickering test ([#10383](https://github.com/blockscout/blockscout/issues/10383)) +- Fix gas price oracle flickering test ([#10381](https://github.com/blockscout/blockscout/issues/10381)) +- Fix address controller flickering test ([#10382](https://github.com/blockscout/blockscout/issues/10382)) +- Empty revert reasons in geth variant ([#10243](https://github.com/blockscout/blockscout/issues/10243)) +- Proper handling for re-discovered Arbitrum batches ([#10326](https://github.com/blockscout/blockscout/issues/10326)) +- Proper lookup of confirmed Arbitrum cross-chain messages ([#10322](https://github.com/blockscout/blockscout/issues/10322)) +- Indexer first block usage to halt Arbitrum missed messages discovery ([#10280](https://github.com/blockscout/blockscout/issues/10280)) + +### 📚 Documentation + +- Refine PR template +- Move note in README.md higher for visibility ([#10450](https://github.com/blockscout/blockscout/issues/10450)) + +### ⚡ Performance + +- Speed up worlds list query ([#10556](https://github.com/blockscout/blockscout/issues/10556)) +- Reduce LookUpSmartContractSourcesOnDemand fetcher footprint ([#10457](https://github.com/blockscout/blockscout/issues/10457)) + +### ⚙️ Miscellaneous Tasks + +- Make Dockerfile use specified user with uid/gid ([#10070](https://github.com/blockscout/blockscout/pull/10070)) +- Run shrink internal transactions migration for indexer instance only ([#10631](https://github.com/blockscout/blockscout/issues/10631)) +- Shrink internal transactions ([#10567](https://github.com/blockscout/blockscout/issues/10567)) +- Upgrade WS client ([#10407](https://github.com/blockscout/blockscout/issues/10407)) +- Add API endpoint for OP batch blocks ([#10566](https://github.com/blockscout/blockscout/issues/10566)) +- Public metrics config API endpoint ([#10568](https://github.com/blockscout/blockscout/issues/10568)) +- Add workflow to generate separate pre-release indexer/API images for Arbitrum +- Fix some comments ([#10519](https://github.com/blockscout/blockscout/issues/10519)) +- Set Geth as default JSON RPC Variant ([#10509](https://github.com/blockscout/blockscout/issues/10509)) +- Return ex_abi core lib dependency ([#10470](https://github.com/blockscout/blockscout/issues/10470)) +- Add recon dependency ([#10486](https://github.com/blockscout/blockscout/issues/10486)) +- Manage Solidityscan platform id via runtime variable ([#10473](https://github.com/blockscout/blockscout/issues/10473)) +- Add test for broadcasting fetched_bytecode message ([#10244](https://github.com/blockscout/blockscout/issues/10244)) +- Disable public metrics by default, set 1 day as default period of update ([#10469](https://github.com/blockscout/blockscout/issues/10469)) +- Move eth_bytecode_db_lookup_started event to smart contract related event handler ([#10462](https://github.com/blockscout/blockscout/issues/10462)) +- Token transfers broadcast optimization ([#10465](https://github.com/blockscout/blockscout/issues/10465)) +- Remove catchup sequence logic ([#10415](https://github.com/blockscout/blockscout/issues/10415)) +- Remove single implementation name, address from API v2 response ([#10390](https://github.com/blockscout/blockscout/issues/10390)) +- Refactor init functions to use continue if needed ([#10300](https://github.com/blockscout/blockscout/issues/10300)) +- Update buildkit builders ([#10377](https://github.com/blockscout/blockscout/issues/10377)) + +### New ENV Variables + +| Variable | Description | Parameters | +| ------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- | +| `ETHEREUM_JSONRPC_FALLBACK_WS_URL` | The fallback WebSockets RPC endpoint used to subscribe to the `newHeads` subscription alerting the indexer to fetch new blocks. Implemented in [#10407](https://github.com/blockscout/blockscout/pull/10407). |

Version: v6.8.0+
Default: (empty)
Applications: Indexer

| +| `ETHEREUM_JSONRPC_WS_RETRY_INTERVAL` | The interval between retries of connecting to WebSocket RPC endpoint after the previous attempt is failed. Implemented in [#10407](https://github.com/blockscout/blockscout/pull/10407). |

Version: v6.8.0+
Default: 1m
Applications: Indexer

| +| `DATABASE_EVENT_URL` | Variable to define the Postgres Database endpoint that will be used by event listener process. Applicable for separate indexer and API setup. More info in related PR. Implemented in [#10164](https://github.com/blockscout/blockscout/pull/10164). |

Version: v6.8.0+
Default: (empty)
Applications: API

| +| `PUBLIC_METRICS_ENABLED` | Variable to enable running queries at /public-metrics endpoint. Implemented in [#10469](https://github.com/blockscout/blockscout/pull/10469). |

Version: v6.8.0+
Default: false
Applications: API

| +| `PUBLIC_METRICS_UPDATE_PERIOD_HOURS` | Public metrics update period in hours at /public-metrics endpoint. Implemented in [#10469](https://github.com/blockscout/blockscout/pull/10469). |

Version: v6.8.0+
Default: 24
Applications: API

| +| `SHRINK_INTERNAL_TRANSACTIONS_ENABLED` | Variable to enable internal transactions shrinking logic. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567). |

Version: v6.8.0+
Default: false
Applications: API, Indexer

| +| `SHRINK_INTERNAL_TRANSACTIONS_BATCH_SIZE` | Batch size of the shrink internal transactions migration. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567). |

Version: v6.8.0+
Default: 1000
Applications: API, Indexer

| +| `SHRINK_INTERNAL_TRANSACTIONS_CONCURRENCY` | Concurrency of the shrink internal transactions migration. Implemented in [#10567](https://github.com/blockscout/blockscout/pull/10567). |

Version: v6.8.0+
Default: 1
Applications: API, Indexer

| +| `IPFS_PUBLIC_GATEWAY_URL` | IPFS public gateway url which is used by frontend to display IPFS resources such as token instance image. |

Version: v6.8.0+
Default: https://ipfs.io/ipfs
Applications: API

| +| `INDEXER_TOKEN_INSTANCE_RETRY_MAX_REFETCH_INTERVAL` | Maximum interval between attempts to fetch token instance metadata. [Time format](backend-env-variables.md#time-format). Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). |

Version: v6.8.0+
Default: 168h
Applications: Indexer

| +| `INDEXER_TOKEN_INSTANCE_RETRY_EXPONENTIAL_TIMEOUT_BASE` | Base to calculate exponential timeout. Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). |

Version: v6.8.0+
Default: 2
Applications: Indexer

| +| `INDEXER_TOKEN_INSTANCE_RETRY_EXPONENTIAL_TIMEOUT_COEFF` | Coefficient to calculate exponential timeout. Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). |

Version: v6.8.0+
Default: 100
Applications: Indexer

| +| `MISSING_BALANCE_OF_TOKENS_WINDOW_SIZE` | Minimal blocks count until the next token balance request will be executed for tokens that doesn't implement `balanceOf` function. Implemented in [#10142](https://github.com/blockscout/blockscout/pull/10142) |

Version: v6.8.0+
Default: 100
Applications: Indexer

| +| `ETHEREUM_JSONRPC_GETH_ALLOW_EMPTY_TRACES` | Allow transactions to not have internal transactions. Implemented in [#10200](https://github.com/blockscout/blockscout/pull/10200) |

Version: v6.8.0+
Default: false
Applications: Indexer

| +| `INDEXER_DISABLE_REPLACED_TRANSACTION_FETCHER` | If `true`, `Indexer.Fetcher.ReplacedTransaction` fetcher doesn't run |

Version: v6.8.0+
Default: false
Applications: Indexer

| +| `SANITIZE_INCORRECT_WETH_BATCH_SIZE` | Number of token transfers to sanitize in the batch. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) |

Version: v6.8.0+
Default: 100
Applications: API, Indexer

| +| `SANITIZE_INCORRECT_WETH_CONCURRENCY` | Number of parallel sanitizing token transfer batches processing. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) |

Version: v6.8.0+
Default: 1
Applications: API, Indexer

| +| `MIGRATION_RESTORE_OMITTED_WETH_TOKEN_TRANSFERS_BATCH_SIZE` | Number of logs to process in the batch. Implemented in [#10466](https://github.com/blockscout/blockscout/pull/10466) |

Version: v6.8.0+
Default: 50
Applications: API, Indexer

| +| `MIGRATION_RESTORE_OMITTED_WETH_TOKEN_TRANSFERS_CONCURRENCY`| Number of parallel logs batches processing. Implemented in [#10466](https://github.com/blockscout/blockscout/pull/10466) |

Version: v6.8.0+
Default: 5
Applications: API, Indexer

| +| `MIGRATION_RESTORE_OMITTED_WETH_TOKEN_TRANSFERS_TIMEOUT` | Time interval between checks if queue is not empty. The same timeout multiplied by 2 used between checks if queue is not full. Implemented in [#10466](https://github.com/blockscout/blockscout/pull/10466) |

Version: v6.8.0+
Default: 250ms
Applications: API, Indexer

| +| `EXCHANGE_RATES_SOURCE` | Source for native coin and tokens price fetching. Possible values are: `coin_gecko`, `coin_market_cap` or `mobula`. |

Version: v6.8.0+
Default: coin_gecko
Applications: API, Indexer

| +| `EXCHANGE_RATES_SECONDARY_COIN_SOURCE` | Source for secondary coin fetching. Possible values are: `coin_gecko`, `coin_market_cap` or `mobula`. |

Version: v6.8.0+
Default: coin_gecko
Applications: API, Indexer

| +| `TOKEN_EXCHANGE_RATES_SOURCE` | Sets the source for tokens price fetching. Available values are `coin_gecko`, `cryptorank`. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: coin_gecko
Applications: API, Indexer

| +| `EXCHANGE_RATES_CRYPTORANK_SECONDARY_COIN_ID` | Sets Cryptorank coin ID for secondary coin market chart. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: (empty)
Applications: API, Indexer

| +| `EXCHANGE_RATES_CRYPTORANK_PLATFORM_ID` | Sets Cryptorank platform ID. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: (empty)
Applications: API, Indexer

| +| `EXCHANGE_RATES_CRYPTORANK_BASE_URL` | If set, overrides the Cryptorank API url. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: https://api.cryptorank.io/v1/
Applications: API, Indexer

| +| `EXCHANGE_RATES_CRYPTORANK_API_KEY` | Cryptorank API key. Current implementation uses dedicated beta Cryptorank API endpoint. If you want to integrate Cryptorank price fetching you should contact Cryptorank to receive an API key. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: (empty)
Applications: API, Indexer

| +| `EXCHANGE_RATES_CRYPTORANK_COIN_ID` | Sets Cryptorank coin ID. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: (empty)
Applications: API, Indexer

| +| `EXCHANGE_RATES_CRYPTORANK_LIMIT` | Sets the maximum number of token prices returned in a single request. Implemented in [#10550](https://github.com/blockscout/blockscout/pull/10550). |

Version: v6.8.0+
Default: 1000
Applications: API, Indexer

| +| `WHITELISTED_WETH_CONTRACTS` | Comma-separated list of smart-contract address hashes of WETH-like tokens which deposit and withdrawal events you'd like to index. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) |

Version: v6.8.0+
Default: (empty)
Applications: API, Indexer

| +| `API_NO_RATE_LIMIT_API_KEY` | API key with no rate limit. Implemented in [#10515](https://github.com/blockscout/blockscout/pull/10515) |

Version: v6.8.0+
Default: (empty)
Applications: API

| + +## 6.7.2 + +### 🐛 Bug Fixes + +- Apply Ecto set explicit ssl_opts: [verify: :verify_none] to all prod repos ([#10369](https://github.com/blockscout/blockscout/issues/10369)) +- Fix slow internal transactions query ([#10346](https://github.com/blockscout/blockscout/issues/10346)) +- Don't execute update query for empty list ([#10344](https://github.com/blockscout/blockscout/issues/10344)) +- Add rescue on tx revert reason fetching ([#10366](https://github.com/blockscout/blockscout/issues/10366)) +- Reth compatibility ([#10335](https://github.com/blockscout/blockscout/issues/10335)) +- Public metrics enabling ([#10365](https://github.com/blockscout/blockscout/issues/10365)) +- Flaky market test ([#10262](https://github.com/blockscout/blockscout/issues/10262)) + +### ⚙️ Miscellaneous Tasks + +- Bump elixir to 1.16.3 and Erlang OTP to 26.2.5.1 ([#9256](https://github.com/blockscout/blockscout/issues/9256)) + +## 6.7.1 + +### 🐛 Bug Fixes + +- Fix to_string error ([#10319](https://github.com/blockscout/blockscout/issues/10319)) +- Fix bridged tokens ([#10318](https://github.com/blockscout/blockscout/issues/10318)) +- Missing onlyTopCall option on some geth networks ([#10309](https://github.com/blockscout/blockscout/issues/10309)) + +## 6.7.0 + +### 🚀 Features + +- Public metrics toggler ([#10279](https://github.com/blockscout/blockscout/issues/10279)) +- Chain & explorer Prometheus metrics ([#10063](https://github.com/blockscout/blockscout/issues/10063)) +- API endpoint to re-fetch token instance metadata ([#10097](https://github.com/blockscout/blockscout/issues/10097)) +- *(ci)* Use remote arm64 builder ([#9468](https://github.com/blockscout/blockscout/issues/9468)) +- Adding Mobula price source ([#9971](https://github.com/blockscout/blockscout/issues/9971)) +- Get ERC-1155 token name from contractURI getter fallback ([#10187](https://github.com/blockscout/blockscout/issues/10187)) +- Push relevant entries to the front of bound queue ([#10193](https://github.com/blockscout/blockscout/issues/10193)) +- Add feature toggle for WETH filtering ([#10208](https://github.com/blockscout/blockscout/issues/10208)) +- Batch read methods requests ([#10192](https://github.com/blockscout/blockscout/issues/10192)) +- Set dynamic ttl of cache modules derived from MapCache ([#10109](https://github.com/blockscout/blockscout/issues/10109)) +- Add Fee column to Internal transactions CSV export ([#10204](https://github.com/blockscout/blockscout/issues/10204)) +- Add window between balance fetch retries for missing balanceOf tokens ([#10142](https://github.com/blockscout/blockscout/issues/10142)) +- Indexer for cross level messages on Arbitrum ([#9312](https://github.com/blockscout/blockscout/issues/9312)) + +### 🐛 Bug Fixes + +- Add token instances preloads ([#10288](https://github.com/blockscout/blockscout/issues/10288)) +- Set timeout in seconds ([#10283](https://github.com/blockscout/blockscout/issues/10283)) +- Fix ci setup repo error ([#10277](https://github.com/blockscout/blockscout/issues/10277)) +- `getsourcecode` in API v1 for verified proxy ([#10273](https://github.com/blockscout/blockscout/issues/10273)) +- Add preloads for tx summary endpoint ([#10261](https://github.com/blockscout/blockscout/issues/10261)) +- Add preloads to summary and tokens endpoints ([#10259](https://github.com/blockscout/blockscout/issues/10259)) +- Advanced filter contract creation transaction ([#10257](https://github.com/blockscout/blockscout/issues/10257)) +- Proper hex-encoded transaction hash recognition in ZkSync batches status checker ([#10255](https://github.com/blockscout/blockscout/issues/10255)) +- Pipe through api_v2_no_forgery_protect POST requests in SmartContractsApiV2Router +- Fix possible unknown UID bug ([#10240](https://github.com/blockscout/blockscout/issues/10240)) +- Batch transactions view recovered and support of proofs through ZkSync Hyperchain ([#10234](https://github.com/blockscout/blockscout/issues/10234)) +- Fix nil abi issue in get_naive_implementation_abi and get_master_copy_pattern methods ([#10239](https://github.com/blockscout/blockscout/issues/10239)) +- Add smart contracts preloads to from_address ([#10236](https://github.com/blockscout/blockscout/issues/10236)) +- Add proxy_implementations preloads ([#10225](https://github.com/blockscout/blockscout/issues/10225)) +- Cannot truncate chardata ([#10227](https://github.com/blockscout/blockscout/issues/10227)) +- ERC-1155 tokens metadata retrieve ([#10231](https://github.com/blockscout/blockscout/issues/10231)) +- Replace empty arg names with argN ([#9748](https://github.com/blockscout/blockscout/issues/9748)) +- Fix unknown UID bug ([#10226](https://github.com/blockscout/blockscout/issues/10226)) +- Fixed the field name ([#10216](https://github.com/blockscout/blockscout/issues/10216)) +- Excessive logging for Arbitrum batches confirmations ([#10205](https://github.com/blockscout/blockscout/issues/10205)) +- Filter WETH transfers in indexer + migration to delete historical incorrect WETH transfers ([#10134](https://github.com/blockscout/blockscout/issues/10134)) +- Fix flaky test +- Resolve flaky address_controller test for web +- Add the ability to allow empty traces ([#10200](https://github.com/blockscout/blockscout/issues/10200)) +- Move auth routes to general router ([#10153](https://github.com/blockscout/blockscout/issues/10153)) +- Add a separate db url for events listener ([#10164](https://github.com/blockscout/blockscout/issues/10164)) +- Fix Retry NFT fetcher ([#10146](https://github.com/blockscout/blockscout/issues/10146)) +- Add missing preloads to tokens endpoints ([#10072](https://github.com/blockscout/blockscout/issues/10072)) +- Missing nil case for revert reason ([#10136](https://github.com/blockscout/blockscout/issues/10136)) +- Hotfix for Indexer.Fetcher.Optimism.WithdrawalEvent and EthereumJSONRPC.Receipt ([#10130](https://github.com/blockscout/blockscout/issues/10130)) + +### 🚜 Refactor + +- Remove hardcoded numResults from fetch_pending_transactions_besu ([#10117](https://github.com/blockscout/blockscout/issues/10117)) + +### ⚡ Performance + +- Replace individual queries with ecto preload ([#10203](https://github.com/blockscout/blockscout/issues/10203)) + +### ⚙️ Miscellaneous Tasks + +- Refactor PendingTransactionsSanitizer to use batched requests ([#10101](https://github.com/blockscout/blockscout/issues/10101)) +- Exclude write methods from read tabs ([#10111](https://github.com/blockscout/blockscout/issues/10111)) +- Return is verified=true for verified minimal proxy pattern ([#10132](https://github.com/blockscout/blockscout/issues/10132)) +- Bump ecto_sql from 3.11.1 to 3.11.2 + +### New ENV Variables + +| Variable | Required | Description | Default | Version | Need recompile | Application | +| -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------- | -------------- | --- | +| `DATABASE_EVENT_URL` | | Variable to define the Postgres Database endpoint that will be used by event listener process. Applicable for separate indexer and API setup. More info in related PR. Implemented in [#10164](https://github.com/blockscout/blockscout/pull/10164). | (empty) | v6.7.0+ | | API | +| `INDEXER_TOKEN_INSTANCE_RETRY_MAX_REFETCH_INTERVAL` | | Maximum interval between attempts to fetch token instance metadata. [Time format](env-variables.md#time-format). Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). | `168h` | v6.7.0+ | | Indexer | +| `INDEXER_TOKEN_INSTANCE_RETRY_EXPONENTIAL_TIMEOUT_BASE` | | Base to calculate exponential timeout. Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). | `2` | v6.7.0+ | | Indexer | +| `INDEXER_TOKEN_INSTANCE_RETRY_EXPONENTIAL_TIMEOUT_COEFF` | | Coefficient to calculate exponential timeout. Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). | `100` | v6.7.0+ | | Indexer | +| `MISSING_BALANCE_OF_TOKENS_WINDOW_SIZE` | | Minimal blocks count until the next token balance request will be executed for tokens that doesn't implement `balanceOf` function. Implemented in [#10142](https://github.com/blockscout/blockscout/pull/10142) | 100 | v6.7.0+ | | Indexer | +| `ETHEREUM_JSONRPC_GETH_ALLOW_EMPTY_TRACES` | | Allow transactions to not have internal transactions. Implemented in [#10200](https://github.com/blockscout/blockscout/pull/10200) | `false` | v6.7.0+ | | Indexer | +| `SANITIZE_INCORRECT_WETH_BATCH_SIZE` | | Number of token transfers to sanitize in the batch. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) | 100 | v6.7.0+ | | API, Indexer | +| `SANITIZE_INCORRECT_WETH_CONCURRENCY` | | Number of parallel sanitizing token transfer batches processing. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) | 1 | v6.7.0+ | | API, Indexer | +| `EXCHANGE_RATES_MOBULA_SECONDARY_COIN_ID` | | Explicitly set Mobula coin ID for secondary coin market chart. | (empty) | v6.7.0+ | | API, Indexer | +| `EXCHANGE_RATES_MOBULA_API_KEY` | | Mobula API key. | (empty) | v6.7.0+ | | API, Indexer | +| `EXCHANGE_RATES_MOBULA_CHAIN_ID` | | [Mobula](https://www.mobula.io/) chain id for which token prices are fetched, see full list in the [`Documentation`](https://docs.mobula.io/blockchains/intro-blockchains). | ethereum | v6.7.0+ | | API, Indexer | +| `TOKEN_INSTANCE_METADATA_REFETCH_ON_DEMAND_FETCHER_THRESHOLD` | | An initial threshold (for exponential backoff) to re-fetch token instance's metadata on-demand. [Time format](env-variables.md#time-format). Implemented in [#10097](https://github.com/blockscout/blockscout/pull/10097). | 5s | v6.7.0+ | | API, Indexer | +| `WHITELISTED_WETH_CONTRACTS` | | Comma-separated list of smart-contract addresses hashes of WETH-like tokens which deposit and withdrawal events you'd like to index. Implemented in [#10134](https://github.com/blockscout/blockscout/pull/10134) | (empty) | v6.7.0+ | | API, Indexer| +| `WETH_TOKEN_TRANSFERS_FILTERING_ENABLED` | | Toggle for WETH token transfers filtering which was introduced in [#10134](https://github.com/blockscout/blockscout/pull/10134). Implemented in [#10208](https://github.com/blockscout/blockscout/pull/10208) | false | v6.7.0+ | | API, Indexer| + +## 6.6.0 + +### 🚀 Features + +- Implement fetch_first_trace for Geth ([#10087](https://github.com/blockscout/blockscout/issues/10087)) +- Add optional retry of NFT metadata fetch in Indexer.Fetcher.Tok… ([#10036](https://github.com/blockscout/blockscout/issues/10036)) +- Blueprint contracts support ([#10058](https://github.com/blockscout/blockscout/issues/10058)) +- Clone with immutable arguments proxy pattern ([#10039](https://github.com/blockscout/blockscout/issues/10039)) +- Improve retry NFT fetcher ([#10027](https://github.com/blockscout/blockscout/issues/10027)) +- MUD API support ([#9869](https://github.com/blockscout/blockscout/issues/9869)) +- Diamond proxy (EIP-2535) support ([#10034](https://github.com/blockscout/blockscout/issues/10034)) +- Add user ops indexer to docker compose configs ([#10010](https://github.com/blockscout/blockscout/issues/10010)) +- Save smart-contract proxy type in the DB ([#10033](https://github.com/blockscout/blockscout/issues/10033)) +- Detect EIP-1967 proxy pattern on unverified smart-contracts ([#9864](https://github.com/blockscout/blockscout/issues/9864)) +- Omit balanceOf requests for tokens that doesn't support it ([#10018](https://github.com/blockscout/blockscout/issues/10018)) +- Precompiled contracts ABI import ([#9899](https://github.com/blockscout/blockscout/issues/9899)) +- Add ENS category to search result; Add ENS to check-redirect ([#9779](https://github.com/blockscout/blockscout/issues/9779)) + +### 🐛 Bug Fixes + +- Fix certified flag in the search API v2 endpoint ([#10094](https://github.com/blockscout/blockscout/issues/10094)) +- Update Vyper inner compilers list to support all compilers ([#10091](https://github.com/blockscout/blockscout/issues/10091)) +- Add healthcheck endpoints for indexer-only setup ([#10076](https://github.com/blockscout/blockscout/issues/10076)) +- Rework revert_reason ([#9212](https://github.com/blockscout/blockscout/issues/9212)) +- Eliminate from_address_hash == #{address_hash} clause for transactions query in case of smart-contracts ([#9469](https://github.com/blockscout/blockscout/issues/9469)) +- Separate indexer setup ([#10032](https://github.com/blockscout/blockscout/issues/10032)) +- Disallow batched queries in GraphQL endpoint ([#10050](https://github.com/blockscout/blockscout/issues/10050)) +- Vyper contracts re-verification ([#10053](https://github.com/blockscout/blockscout/issues/10053)) +- Fix Unknown UID bug at smart-contract verification ([#9986](https://github.com/blockscout/blockscout/issues/9986)) +- Search for long integers ([#9651](https://github.com/blockscout/blockscout/issues/9651)) +- Don't put error to NFT metadata ([#9940](https://github.com/blockscout/blockscout/issues/9940)) +- Handle DB unavailability by PolygonZkevm.TransactionBatch fetcher ([#10031](https://github.com/blockscout/blockscout/issues/10031)) +- Fix WebSocketClient reconnect ([#9937](https://github.com/blockscout/blockscout/issues/9937)) +- Fix incorrect image_url parsing from NFT meta ([#9956](https://github.com/blockscout/blockscout/issues/9956)) + +### 🚜 Refactor + +- Improve response of address API to return multiple implementations for Diamond proxy ([#10113](https://github.com/blockscout/blockscout/pull/10113)) +- Refactor get_additional_sources/4 -> get_additional_sources/3 ([#10046](https://github.com/blockscout/blockscout/issues/10046)) +- Test database config ([#9662](https://github.com/blockscout/blockscout/issues/9662)) + +### ⚙️ Miscellaneous Tasks + +- Update hackney pool size: add new fetchers accounting ([#9941](https://github.com/blockscout/blockscout/issues/9941)) +- Bump credo from 1.7.5 to 1.7.6 ([#10060](https://github.com/blockscout/blockscout/issues/10060)) +- Bump redix from 1.5.0 to 1.5.1 ([#10059](https://github.com/blockscout/blockscout/issues/10059)) +- Bump ex_doc from 0.32.1 to 0.32.2 ([#10061](https://github.com/blockscout/blockscout/issues/10061)) +- Remove `has_methods` from `/addresses` ([#10051](https://github.com/blockscout/blockscout/issues/10051)) +- Add support of Blast-specific L1 OP withdrawal events ([#10049](https://github.com/blockscout/blockscout/issues/10049)) +- Update outdated links to ETH JSON RPC Specification in docstrings ([#10041](https://github.com/blockscout/blockscout/issues/10041)) +- Migrate to GET variant of {{metadata_url}}/api/v1/metadata ([#9994](https://github.com/blockscout/blockscout/issues/9994)) +- Bump ex_cldr_numbers from 2.32.4 to 2.33.1 ([#9978](https://github.com/blockscout/blockscout/issues/9978)) +- Bump ex_cldr from 2.38.0 to 2.38.1 ([#10009](https://github.com/blockscout/blockscout/issues/10009)) +- Bump ex_cldr_units from 3.16.5 to 3.17.0 ([#9931](https://github.com/blockscout/blockscout/issues/9931)) +- Bump style-loader in /apps/block_scout_web/assets ([#9995](https://github.com/blockscout/blockscout/issues/9995)) +- Bump mini-css-extract-plugin in /apps/block_scout_web/assets ([#9997](https://github.com/blockscout/blockscout/issues/9997)) +- Bump @babel/preset-env in /apps/block_scout_web/assets ([#9999](https://github.com/blockscout/blockscout/issues/9999)) +- Bump @amplitude/analytics-browser in /apps/block_scout_web/assets ([#10001](https://github.com/blockscout/blockscout/issues/10001)) +- Bump css-loader in /apps/block_scout_web/assets ([#10003](https://github.com/blockscout/blockscout/issues/10003)) +- Bump sweetalert2 in /apps/block_scout_web/assets ([#9998](https://github.com/blockscout/blockscout/issues/9998)) +- Bump mixpanel-browser in /apps/block_scout_web/assets ([#10000](https://github.com/blockscout/blockscout/issues/10000)) +- Bump @fortawesome/fontawesome-free ([#10002](https://github.com/blockscout/blockscout/issues/10002)) +- Bump @babel/core in /apps/block_scout_web/assets ([#9996](https://github.com/blockscout/blockscout/issues/9996)) +- Enhance indexer memory metrics ([#9984](https://github.com/blockscout/blockscout/issues/9984)) +- Bump redix from 1.4.1 to 1.5.0 ([#9977](https://github.com/blockscout/blockscout/issues/9977)) +- Bump floki from 0.36.1 to 0.36.2 ([#9979](https://github.com/blockscout/blockscout/issues/9979)) +- (old UI) Replace old Twitter icon with new 'X' ([#9641](https://github.com/blockscout/blockscout/issues/9641)) + +### New ENV Variables + +| Variable | Required | Description | Default | Version | Need recompile | +| -------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ------- | -------------- | +| `DISABLE_API` | | If `true`, endpoint is not started. Set this if you want to use an indexer-only setup. Implemented in [#10032](https://github.com/blockscout/blockscout/pull/10032) | `false` | v6.6.0+ | | +| `INDEXER_TOKEN_INSTANCE_RETRY_MAX_REFETCH_INTERVAL` | | Maximum interval between attempts to fetch token instance metadata. [Time format](env-variables.md#time-format). Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). | `168h` | v6.6.0+ | +| `INDEXER_TOKEN_INSTANCE_RETRY_EXPONENTIAL_TIMEOUT_BASE` | | Base to calculate exponential timeout. Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). | `2` | v6.6.0+ | +| `INDEXER_TOKEN_INSTANCE_RETRY_EXPONENTIAL_TIMEOUT_COEFF` | | Coefficient to calculate exponential timeout. Implemented in [#10027](https://github.com/blockscout/blockscout/pull/10027). | `100` | v6.6.0+ | +| `INDEXER_TOKEN_INSTANCE_REALTIME_RETRY_ENABLED` | | If `true`, `realtime` token instance fetcher will retry once on 404 and 500 error. Implemented in [#10036](https://github.com/blockscout/blockscout/pull/10036). | `false` | v6.6.0+ | +| `INDEXER_TOKEN_INSTANCE_REALTIME_RETRY_TIMEOUT` | | Timeout for retry set by `INDEXER_TOKEN_INSTANCE_REALTIME_RETRY_ENABLED`. [Time format](env-variables.md#time-format). Implemented in [#10036](https://github.com/blockscout/blockscout/pull/10036). | `5s` | v6.6.0+ | +| `TEST_DATABASE_URL` | | Variable to define the endpoint of the Postgres Database that is used during testing. Implemented in [#9662](https://github.com/blockscout/blockscout/pull/9662). | (empty) | v6.6.0+ | | +| `TEST_DATABASE_READ_ONLY_API_URL` | | Variable to define the endpoint of the Postgres Database read-only replica that is used during testing. If it is provided, most of the read queries from API v2 and UI would go through this endpoint. Implemented in [#9662](https://github.com/blockscout/blockscout/pull/9662). | (empty) | v6.6.0+ | | +| `MUD_INDEXER_ENABLED` | | If `true`, integration with [MUD](https://mud.dev/services/indexer#schemaless-indexing-with-postgresql-via-docker) is enabled. Implemented in [#9869](https://github.com/blockscout/blockscout/pull/9869) | (empty) | v6.6.0+ | | +| `MUD_DATABASE_URL` | | MUD indexer DB connection URL. | value from `DATABASE_URL` | v6.6.0+ | | +| `MUD_POOL_SIZE` | | MUD indexer DB `pool_size` | 50 | v6.6.0+ | | + +### Deprecated ENV Variables + +| Variable | Required | Description | Default | Version | Need recompile | Deprecated in Version | +| ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | -------------- | --------------------- | +| `INDEXER_TOKEN_INSTANCE_RETRY_REFETCH_INTERVAL` | | Interval between attempts to fetch token instance metadata. [Time format](env-variables.md#time-format). Implemented in [#7286](https://github.com/blockscout/blockscout/pull/7286). | `24h` | v5.1.4+ | | v6.6.0 | +| `INDEXER_INTERNAL_TRANSACTIONS_INDEXING_FINISHED_THRESHOLD` | | In the case when the 1st tx in the chain already has internal transactions, If the number of blocks in pending\_block\_operations is less than the value in this env var, Blockscout will consider, that indexing of internal transactions finished, otherwise, it will consider, that indexing is still taking place and the indexing banner will appear at the top. Implemented in [#7576](https://github.com/blockscout/blockscout/pull/7576). | 1000 | v5.2.0+ | | v6.6.0 | + +## 6.5.0 + +### 🚀 Features + +- Certified smart contracts ([#9910](https://github.com/blockscout/blockscout/issues/9910)) +- Exit on provided invalid CHAIN_TYPE ([#9904](https://github.com/blockscout/blockscout/issues/9904)) +- IPFS gateway URL extra params ([#9898](https://github.com/blockscout/blockscout/issues/9898)) +- Zerion API proxy ([#9896](https://github.com/blockscout/blockscout/issues/9896)) +- Support Optimism Fault Proofs ([#9892](https://github.com/blockscout/blockscout/issues/9892)) +- Return number of days in address's coin-balance-history-by-day API v2 endpoint ([#9806](https://github.com/blockscout/blockscout/issues/9806)) +- Allow the use of Coingecko demo account ([#9835](https://github.com/blockscout/blockscout/issues/9835)) + +### 🐛 Bug Fixes + +- Set refetch_needed: false on block import ([#9953](https://github.com/blockscout/blockscout/issues/9953)) +- `GAS_PRICE_ORACLE_NUM_OF_BLOCKS` calculation ([#9943](https://github.com/blockscout/blockscout/issues/9943)) +- Handle "null" filter in api/v1/logs-csv ([#9933](https://github.com/blockscout/blockscout/issues/9933)) +- Fix metadata preload ([#9925](https://github.com/blockscout/blockscout/issues/9925)) +- `coin_price_change_percentage` calculation ([#9774](https://github.com/blockscout/blockscout/issues/9774)) +- Remove backend dependency in microservices.yml ([#9905](https://github.com/blockscout/blockscout/issues/9905)) +- Expand memory only if it was shrunk ([#9907](https://github.com/blockscout/blockscout/issues/9907)) +- Coin balances fetcher error logging ([#9902](https://github.com/blockscout/blockscout/issues/9902)) +- Refactor catchup rudimentaries + fix graceful shutdown ([#9729](https://github.com/blockscout/blockscout/issues/9729)) +- Handle transactions with `gas_price` set to `nil` in `transaction_revert_reason/2` ([#9647](https://github.com/blockscout/blockscout/issues/9647)) +- Correct processing of sized array to view in API v2 ([#9854](https://github.com/blockscout/blockscout/issues/9854)) +- Broadcast realtime coin balances ([#9804](https://github.com/blockscout/blockscout/issues/9804)) +- Disable BlockReward fetcher for unsupported variants ([#9859](https://github.com/blockscout/blockscout/issues/9859)) +- Add non-unique log_index support in update_token_instances_owner ([#9862](https://github.com/blockscout/blockscout/issues/9862)) + +### ⚡ Performance + +- Paging function edge cases fix ([#9820](https://github.com/blockscout/blockscout/issues/9820)) +- Adjust unfetched_address_token_balances_index to fit all bound query conditions ([#9912](https://github.com/blockscout/blockscout/issues/9912)) +- Enhance index for token holders list ([#9816](https://github.com/blockscout/blockscout/issues/9816)) +- Improve performance of token page transfers tab ([#9809](https://github.com/blockscout/blockscout/issues/9809)) + +### ⚙️ Miscellaneous Tasks + +- Fix some typos in comments ([#9900](https://github.com/blockscout/blockscout/issues/9900)) +- Add queue expanding logic to memory monitor ([#9870](https://github.com/blockscout/blockscout/issues/9870)) +- Bump ex_doc from 0.31.2 to 0.32.1 ([#9889](https://github.com/blockscout/blockscout/issues/9889)) +- Separate reorgs from blocks that just need refetch ([#9674](https://github.com/blockscout/blockscout/issues/9674)) +- Unknown token in email template ([#9883](https://github.com/blockscout/blockscout/issues/9883)) +- Bump tesla from 1.8.0 to 1.9.0 ([#9886](https://github.com/blockscout/blockscout/issues/9886)) +- Bump logger_file_backend from 0.0.13 to 0.0.14 ([#9885](https://github.com/blockscout/blockscout/issues/9885)) +- Bump cloak_ecto from 1.2.0 to 1.3.0 ([#9890](https://github.com/blockscout/blockscout/issues/9890)) +- Bump ex_secp256k1 from 0.7.2 to 0.7.3 ([#9888](https://github.com/blockscout/blockscout/issues/9888)) +- Bump ex_cldr_units from 3.16.4 to 3.16.5 ([#9884](https://github.com/blockscout/blockscout/issues/9884)) +- Move `has_methods_*` fields to `/smart-contracts` endpoint response ([#9599](https://github.com/blockscout/blockscout/issues/9599)) +- Add metrics for realtime event handlers queue length ([#9822](https://github.com/blockscout/blockscout/issues/9822)) +- Increase MissingRangesCollector past check interval after the first cycle ([#9872](https://github.com/blockscout/blockscout/issues/9872)) +- Reduce number of warnings in web tests ([#9851](https://github.com/blockscout/blockscout/issues/9851)) +- Fix some typos in comments ([#9838](https://github.com/blockscout/blockscout/issues/9838)) +- Bump ex_abi from 0.7.1 to 0.7.2 ([#9841](https://github.com/blockscout/blockscout/issues/9841)) +- Remove /config/json-rpc-url API endpoint ([#9798](https://github.com/blockscout/blockscout/issues/9798)) +- Bump junit_formatter from 3.3.1 to 3.4.0 ([#9842](https://github.com/blockscout/blockscout/issues/9842)) +- Bump number from 1.0.4 to 1.0.5 ([#9843](https://github.com/blockscout/blockscout/issues/9843)) +- Bump absinthe_phoenix from 2.0.2 to 2.0.3 ([#9840](https://github.com/blockscout/blockscout/issues/9840)) +- Bump plug_cowboy from 2.7.0 to 2.7.1 ([#9844](https://github.com/blockscout/blockscout/issues/9844)) + +## 6.4.0 + +### 🚀 Features + +- Secondary coin price in `api/v2/stats` ([#9777](https://github.com/blockscout/blockscout/issues/9777)) +- Add /api/v2/blocks/{hash_or_number}/internal-transactions endpoint ([#9668](https://github.com/blockscout/blockscout/issues/9668)) +- Integrate Metadata microservice ([#9706](https://github.com/blockscout/blockscout/issues/9706)) +- Support verifier alliance and eth-bytecode-db v1.7.0 changes ([#9724](https://github.com/blockscout/blockscout/issues/9724)) +- Add rate limits to graphQL API ([#9771](https://github.com/blockscout/blockscout/issues/9771)) +- Support for internal user operation calldata decoded by microservice ([#9776](https://github.com/blockscout/blockscout/issues/9776)) +- Internal txs fetching for Arbitrum ([#9737](https://github.com/blockscout/blockscout/issues/9737)) +- Allow for custom base_url for fetching prices ([#9679](https://github.com/blockscout/blockscout/issues/9679)) +- Contract code on-demand fetcher ([#9708](https://github.com/blockscout/blockscout/issues/9708)) +- Add /api/v2/tokens/:address_hash_param/holders/csv endpoint ([#9722](https://github.com/blockscout/blockscout/issues/9722)) +- Support the 2nd version of L2<->L1 Polygon zkEVM Bridge ([#9637](https://github.com/blockscout/blockscout/issues/9637)) +- GraphQL management env vars ([#9751](https://github.com/blockscout/blockscout/issues/9751)) +- Improvements in zksync batch related transactions requests ([#9680](https://github.com/blockscout/blockscout/issues/9680)) +- Add trying to decode internal calldata for user ops ([#9675](https://github.com/blockscout/blockscout/issues/9675)) + +### 🐛 Bug Fixes + +- Apply quantity_to_integer/1 to effectiveGasPrice ([#9812](https://github.com/blockscout/blockscout/issues/9812)) +- Replace tx gas_price with effectiveGasPrice from receipt ([#9733](https://github.com/blockscout/blockscout/issues/9733)) +- Fetching GraphQL schema by GraphiQL IDE ([#9630](https://github.com/blockscout/blockscout/issues/9630)) +- Add block range check into OP Withdrawals fetcher ([#9770](https://github.com/blockscout/blockscout/issues/9770)) +- Update token's holder_count in the db from ETS module ([#9623](https://github.com/blockscout/blockscout/issues/9623)) +- Fix UTF-8 json handling in NFT metadata fetching ([#9707](https://github.com/blockscout/blockscout/issues/9707)) +- Separate ZkSync and ZkEvm readers in API controller ([#9749](https://github.com/blockscout/blockscout/issues/9749)) +- Add missing preloads ([#9520](https://github.com/blockscout/blockscout/issues/9520)) +- Change CoinGecko token image attribute priority ([#9671](https://github.com/blockscout/blockscout/issues/9671)) +- Fix Geth block tracing errors handling ([#9672](https://github.com/blockscout/blockscout/issues/9672)) +- Erc-404 token transfers null value ([#9698](https://github.com/blockscout/blockscout/issues/9698)) +- Erc-404 type stored in token balances tables ([#9700](https://github.com/blockscout/blockscout/issues/9700)) + +### 🚜 Refactor + +- `Enum.count` to `Enum.empty?` ([#9666](https://github.com/blockscout/blockscout/issues/9666)) + +### ⚡ Performance + +- Add EIP4844 blob transactions index ([#9661](https://github.com/blockscout/blockscout/issues/9661)) + +### ⚙️ Miscellaneous Tasks + +- Rework chain type matrix in CI runs ([#9704](https://github.com/blockscout/blockscout/issues/9704)) +- Exclude latest tag update from alpha releases ([#9800](https://github.com/blockscout/blockscout/issues/9800)) +- Reduce default API v1 limit by key 50 -> 10 ([#9799](https://github.com/blockscout/blockscout/issues/9799)) +- Bump autoprefixer in /apps/block_scout_web/assets ([#9786](https://github.com/blockscout/blockscout/issues/9786)) +- Remove /api/account/v1 path ([#9660](https://github.com/blockscout/blockscout/issues/9660)) +- Bump sass from 1.71.1 to 1.72.0 in /apps/block_scout_web/assets ([#9780](https://github.com/blockscout/blockscout/issues/9780)) +- Bump @babel/core in /apps/block_scout_web/assets ([#9782](https://github.com/blockscout/blockscout/issues/9782)) +- Bump webpack in /apps/block_scout_web/assets ([#9787](https://github.com/blockscout/blockscout/issues/9787)) +- Bump postcss in /apps/block_scout_web/assets ([#9785](https://github.com/blockscout/blockscout/issues/9785)) +- Bump @amplitude/analytics-browser in /apps/block_scout_web/assets ([#9788](https://github.com/blockscout/blockscout/issues/9788)) +- Bump solc from 0.8.24 to 0.8.25 in /apps/explorer ([#9789](https://github.com/blockscout/blockscout/issues/9789)) +- Bump sweetalert2 in /apps/block_scout_web/assets ([#9783](https://github.com/blockscout/blockscout/issues/9783)) +- Bump @babel/preset-env in /apps/block_scout_web/assets ([#9784](https://github.com/blockscout/blockscout/issues/9784)) +- Bump core-js in /apps/block_scout_web/assets ([#9781](https://github.com/blockscout/blockscout/issues/9781)) +- Enable Rust sc-verifier microservice by default ([#9752](https://github.com/blockscout/blockscout/issues/9752)) +- Temporarily ignore OP batches written to Celestia ([#9734](https://github.com/blockscout/blockscout/issues/9734)) +- Bump cldr_utils from 2.24.2 to 2.25.0 ([#9723](https://github.com/blockscout/blockscout/issues/9723)) +- Bump express in /apps/block_scout_web/assets ([#9725](https://github.com/blockscout/blockscout/issues/9725)) +- Bump bureaucrat from 0.2.9 to 0.2.10 ([#9669](https://github.com/blockscout/blockscout/issues/9669)) +- Fix typos ([#9693](https://github.com/blockscout/blockscout/issues/9693)) +- Bump follow-redirects from 1.15.4 to 1.15.6 in /apps/explorer ([#9648](https://github.com/blockscout/blockscout/issues/9648)) +- Bump floki from 0.36.0 to 0.36.1 ([#9670](https://github.com/blockscout/blockscout/issues/9670)) +- Use git-cliff changelog generator ([#9687](https://github.com/blockscout/blockscout/issues/9687)) + +## 6.3.0 + +### Features + +- [#9631](https://github.com/blockscout/blockscout/pull/9631) - Initial support of zksync chain type +- [#9532](https://github.com/blockscout/blockscout/pull/9532) - Add last output root size counter +- [#9511](https://github.com/blockscout/blockscout/pull/9511) - Separate errors by type in EndpointAvailabilityObserver +- [#9490](https://github.com/blockscout/blockscout/pull/9490), [#9644](https://github.com/blockscout/blockscout/pull/9644) - Add blob transaction counter and filter in block view +- [#9486](https://github.com/blockscout/blockscout/pull/9486) - Massive blocks fetcher +- [#9483](https://github.com/blockscout/blockscout/pull/9483) - Add secondary coin and transaction stats +- [#9473](https://github.com/blockscout/blockscout/pull/9473) - Add user_op interpretation +- [#9461](https://github.com/blockscout/blockscout/pull/9461) - Fetch blocks without internal transactions backwards +- [#9460](https://github.com/blockscout/blockscout/pull/9460) - Optimism chain type +- [#9409](https://github.com/blockscout/blockscout/pull/9409) - ETH JSON RPC extension +- [#9390](https://github.com/blockscout/blockscout/pull/9390) - Add stability validators +- [#8702](https://github.com/blockscout/blockscout/pull/8702) - Add OP withdrawal status to transaction page in API +- [#7200](https://github.com/blockscout/blockscout/pull/7200) - Add Optimism BedRock Deposits to the main page in API +- [#6980](https://github.com/blockscout/blockscout/pull/6980) - Add Optimism BedRock support (Txn Batches, Output Roots, Deposits, Withdrawals) + +### Fixes + +- [#9654](https://github.com/blockscout/blockscout/pull/9654) - Send timeout param in debug_traceBlockByNumber request +- [#9653](https://github.com/blockscout/blockscout/pull/9653) - Tokens import improvements +- [#9652](https://github.com/blockscout/blockscout/pull/9652) - Remove duplicated tx hashes while indexing OP batches +- [#9646](https://github.com/blockscout/blockscout/pull/9646) - Hotfix for Optimism Ecotone batch blobs indexing +- [#9640](https://github.com/blockscout/blockscout/pull/9640) - Fix no function clause matching in `BENS.item_to_address_hash_strings/1` +- [#9638](https://github.com/blockscout/blockscout/pull/9638) - Do not broadcast coin balance changes with empty value/delta +- [#9635](https://github.com/blockscout/blockscout/pull/9635) - Reset missing ranges collector to max number after the cycle is done +- [#9629](https://github.com/blockscout/blockscout/pull/9629) - Don't insert pbo for not inserted blocks +- [#9620](https://github.com/blockscout/blockscout/pull/9620) - Fix infinite retries for orphaned blobs +- [#9601](https://github.com/blockscout/blockscout/pull/9601) - Fix token instance transform for some unconventional tokens +- [#9597](https://github.com/blockscout/blockscout/pull/9597) - Update token transfers block_consensus by block_number +- [#9596](https://github.com/blockscout/blockscout/pull/9596) - Fix logging +- [#9585](https://github.com/blockscout/blockscout/pull/9585) - Fix Geth block internal transactions fetching +- [#9576](https://github.com/blockscout/blockscout/pull/9576) - Rewrite query for token transfers on address to eliminate "or" +- [#9572](https://github.com/blockscout/blockscout/pull/9572) - Fix Shibarium L1 fetcher +- [#9563](https://github.com/blockscout/blockscout/pull/9563) - Fix timestamp handler for unfinalized zkEVM batches +- [#9560](https://github.com/blockscout/blockscout/pull/9560) - Fix fetch pending transaction for hyperledger besu client +- [#9555](https://github.com/blockscout/blockscout/pull/9555) - Fix EIP-1967 beacon proxy pattern detection +- [#9529](https://github.com/blockscout/blockscout/pull/9529) - Fix `MAX_SAFE_INTEGER` frontend bug +- [#9518](https://github.com/blockscout/blockscout/pull/9518), [#9628](https://github.com/blockscout/blockscout/pull/9628) - Fix MultipleResultsError in `smart_contract_creation_tx_bytecode/1` +- [#9514](https://github.com/blockscout/blockscout/pull/9514) - Fix missing `0x` prefix for `blockNumber`, `logIndex`, `transactionIndex` and remove `transactionLogIndex` in `eth_getLogs` response. +- [#9510](https://github.com/blockscout/blockscout/pull/9510) - Fix WS false 0 token balances +- [#9512](https://github.com/blockscout/blockscout/pull/9512) - Docker-compose 2.24.6 compatibility +- [#9407](https://github.com/blockscout/blockscout/pull/9407) - ERC-404 basic support +- [#9262](https://github.com/blockscout/blockscout/pull/9262) - Fix withdrawal status +- [#9123](https://github.com/blockscout/blockscout/pull/9123) - Fixes in Optimism due to changed log topics type +- [#8831](https://github.com/blockscout/blockscout/pull/8831) - Return all OP Withdrawals bound to L2 transaction +- [#8822](https://github.com/blockscout/blockscout/pull/8822) - Hotfix for optimism_withdrawal_transaction_status function +- [#8811](https://github.com/blockscout/blockscout/pull/8811) - Consider consensus block only when retrieving OP withdrawal transaction status +- [#8364](https://github.com/blockscout/blockscout/pull/8364) - Fix API v2 for OP Withdrawals +- [#8229](https://github.com/blockscout/blockscout/pull/8229) - Fix Indexer.Fetcher.OptimismTxnBatch +- [#8208](https://github.com/blockscout/blockscout/pull/8208) - Ignore invalid frame by OP transaction batches module +- [#8122](https://github.com/blockscout/blockscout/pull/8122) - Ignore previously handled frame by OP transaction batches module +- [#7827](https://github.com/blockscout/blockscout/pull/7827) - Fix transaction batches module for L2 OP stack +- [#7776](https://github.com/blockscout/blockscout/pull/7776) - Fix transactions ordering in Indexer.Fetcher.OptimismTxnBatch +- [#7219](https://github.com/blockscout/blockscout/pull/7219) - Output L1 fields in API v2 for transaction page and fix transaction fee calculation +- [#6699](https://github.com/blockscout/blockscout/pull/6699) - L1 tx fields fix for Goerli Optimism BedRock update + +### Chore + +- [#9622](https://github.com/blockscout/blockscout/pull/9622) - Add alternative `hex.pm` mirrors +- [#9571](https://github.com/blockscout/blockscout/pull/9571) - Support Optimism Ecotone upgrade by Indexer.Fetcher.Optimism.TxnBatch module +- [#9562](https://github.com/blockscout/blockscout/pull/9562) - Add cancun evm version +- [#9506](https://github.com/blockscout/blockscout/pull/9506) - API v1 bridgedtokenlist endpoint +- [#9260](https://github.com/blockscout/blockscout/pull/9260) - Optimism Delta upgrade support by Indexer.Fetcher.OptimismTxnBatch module +- [#8740](https://github.com/blockscout/blockscout/pull/8740) - Add delay to Indexer.Fetcher.OptimismTxnBatch module initialization + +
+ Dependencies version bumps + +- [#9544](https://github.com/blockscout/blockscout/pull/9544) - Bump @babel/core from 7.23.9 to 7.24.0 in /apps/block_scout_web/assets +- [#9537](https://github.com/blockscout/blockscout/pull/9537) - Bump logger_json from 5.1.3 to 5.1.4 +- [#9550](https://github.com/blockscout/blockscout/pull/9550) - Bump xss from 1.0.14 to 1.0.15 in /apps/block_scout_web/assets +- [#9539](https://github.com/blockscout/blockscout/pull/9539) - Bump floki from 0.35.4 to 0.36.0 +- [#9551](https://github.com/blockscout/blockscout/pull/9551) - Bump @amplitude/analytics-browser from 2.5.1 to 2.5.2 in /apps/block_scout_web/assets +- [#9547](https://github.com/blockscout/blockscout/pull/9547) - Bump @babel/preset-env from 7.23.9 to 7.24.0 in /apps/block_scout_web/assets +- [#9549](https://github.com/blockscout/blockscout/pull/9549) - Bump postcss-loader from 8.1.0 to 8.1.1 in /apps/block_scout_web/assets +- [#9542](https://github.com/blockscout/blockscout/pull/9542) - Bump phoenix_ecto from 4.4.3 to 4.5.0 +- [#9546](https://github.com/blockscout/blockscout/pull/9546) - https://github.com/blockscout/blockscout/pull/9546 +- [#9545](https://github.com/blockscout/blockscout/pull/9545) - Bump chart.js from 4.4.1 to 4.4.2 in /apps/block_scout_web/assets +- [#9540](https://github.com/blockscout/blockscout/pull/9540) - Bump postgrex from 0.17.4 to 0.17.5 +- [#9543](https://github.com/blockscout/blockscout/pull/9543) - Bump ueberauth from 0.10.7 to 0.10.8 +- [#9538](https://github.com/blockscout/blockscout/pull/9538) - Bump credo from 1.7.4 to 1.7.5 +- [#9607](https://github.com/blockscout/blockscout/pull/9607) - Bump redix from 1.3.0 to 1.4.1 +- [#9606](https://github.com/blockscout/blockscout/pull/9606) - Bump ecto from 3.11.1 to 3.11.2 +- [#9605](https://github.com/blockscout/blockscout/pull/9605) - Bump ex_doc from 0.31.1 to 0.31.2 +- [#9604](https://github.com/blockscout/blockscout/pull/9604) - Bump phoenix_ecto from 4.5.0 to 4.5.1 + +
+ +## 6.2.2 + +### Features + +### Fixes + +- [#9505](https://github.com/blockscout/blockscout/pull/9505) - Add env vars for NFT sanitize migration + +### Chore + +- [#9487](https://github.com/blockscout/blockscout/pull/9487) - Add tsvector index on smart_contracts.name + +
+ Dependencies version bumps + +
+ +## 6.2.1 + +### Features + +### Fixes + +- [#9591](https://github.com/blockscout/blockscout/pull/9591) - Fix duplicated results in `methods-read` endpoint +- [#9502](https://github.com/blockscout/blockscout/pull/9502) - Add batch_size and concurrency envs for tt token type migration +- [#9493](https://github.com/blockscout/blockscout/pull/9493) - Fix API response for unknown blob hashes +- [#9484](https://github.com/blockscout/blockscout/pull/9484) - Fix read contract error +- [#9426](https://github.com/blockscout/blockscout/pull/9426) - Fix tabs counter cache bug + +### Chore + +
+ Dependencies version bumps + +- [#9478](https://github.com/blockscout/blockscout/pull/9478) - Bump floki from 0.35.3 to 0.35.4 +- [#9477](https://github.com/blockscout/blockscout/pull/9477) - Bump hammer from 6.2.0 to 6.2.1 +- [#9476](https://github.com/blockscout/blockscout/pull/9476) - Bump eslint from 8.56.0 to 8.57.0 in /apps/block_scout_web/assets +- [#9475](https://github.com/blockscout/blockscout/pull/9475) - Bump @amplitude/analytics-browser from 2.4.1 to 2.5.1 in /apps/block_scout_web/assets +- [#9474](https://github.com/blockscout/blockscout/pull/9474) - Bump sass from 1.71.0 to 1.71.1 in /apps/block_scout_web/assets +- [#9492](https://github.com/blockscout/blockscout/pull/9492) - Bump es5-ext from 0.10.62 to 0.10.64 in /apps/block_scout_web/assets + +
+ +## 6.2.0 + +### Features + +- [#9441](https://github.com/blockscout/blockscout/pull/9441) - Update BENS integration: change endpoint for resolving address in search +- [#9437](https://github.com/blockscout/blockscout/pull/9437) - Add Enum.uniq before sanitizing token transfers +- [#9403](https://github.com/blockscout/blockscout/pull/9403) - Null round handling +- [#9401](https://github.com/blockscout/blockscout/pull/9401) - Eliminate incorrect token transfers with empty token_ids +- [#9396](https://github.com/blockscout/blockscout/pull/9396) - More-Minimal Proxy support +- [#9386](https://github.com/blockscout/blockscout/pull/9386) - Filecoin JSON RPC variant +- [#9379](https://github.com/blockscout/blockscout/pull/9379) - Filter non-traceable transactions for zetachain +- [#9364](https://github.com/blockscout/blockscout/pull/9364) - Fix using of startblock/endblock in API v1 list endpoints: txlist, txlistinternal, tokentx +- [#9360](https://github.com/blockscout/blockscout/pull/9360) - Move missing ranges sanitize to a separate background migration +- [#9351](https://github.com/blockscout/blockscout/pull/9351) - Noves.fi: add proxy endpoint for describeTxs endpoint +- [#9282](https://github.com/blockscout/blockscout/pull/9282) - Add `license_type` to smart contracts +- [#9202](https://github.com/blockscout/blockscout/pull/9202) - Add base and priority fee to gas oracle response +- [#9182](https://github.com/blockscout/blockscout/pull/9182) - Fetch coin balances in async mode in realtime fetcher +- [#9168](https://github.com/blockscout/blockscout/pull/9168) - Support EIP4844 blobs indexing & API +- [#9098](https://github.com/blockscout/blockscout/pull/9098) - Polygon zkEVM Bridge indexer and API v2 extension + +### Fixes + +- [#9444](https://github.com/blockscout/blockscout/pull/9444) - Fix quick search bug +- [#9440](https://github.com/blockscout/blockscout/pull/9440) - Add `debug_traceBlockByNumber` to `method_to_url` +- [#9387](https://github.com/blockscout/blockscout/pull/9387) - Filter out Vyper contracts in Solidityscan API endpoint +- [#9377](https://github.com/blockscout/blockscout/pull/9377) - Speed up account abstraction proxy +- [#9371](https://github.com/blockscout/blockscout/pull/9371) - Filter empty values before token update +- [#9356](https://github.com/blockscout/blockscout/pull/9356) - Remove ERC-1155 logs params from coin balances params +- [#9346](https://github.com/blockscout/blockscout/pull/9346) - Process integer balance in genesis.json +- [#9317](https://github.com/blockscout/blockscout/pull/9317) - Include null gas price txs in fee calculations +- [#9315](https://github.com/blockscout/blockscout/pull/9315) - Fix manual uncle reward calculation +- [#9306](https://github.com/blockscout/blockscout/pull/9306) - Improve marking of failed internal transactions +- [#9305](https://github.com/blockscout/blockscout/pull/9305) - Add effective gas price calculation as fallback +- [#9300](https://github.com/blockscout/blockscout/pull/9300) - Fix read contract bug +- [#9226](https://github.com/blockscout/blockscout/pull/9226) - Split Indexer.Fetcher.TokenInstance.LegacySanitize + +### Chore + +- [#9439](https://github.com/blockscout/blockscout/pull/9439) - Solidityscan integration enhancements +- [#9398](https://github.com/blockscout/blockscout/pull/9398) - Improve elixir dependencies caching in CI +- [#9393](https://github.com/blockscout/blockscout/pull/9393) - Bump actions/cache to v4 +- [#9389](https://github.com/blockscout/blockscout/pull/9389) - Output user address as an object in API v2 for Shibarium +- [#9361](https://github.com/blockscout/blockscout/pull/9361) - Define BRIDGED_TOKENS_ENABLED env in Dockerfile +- [#9257](https://github.com/blockscout/blockscout/pull/9257) - Retry token instance metadata fetch from baseURI + tokenID +- [#8851](https://github.com/blockscout/blockscout/pull/8851) - Fix dialyzer and add TypedEctoSchema + +
+ Dependencies version bumps + +- [#9335](https://github.com/blockscout/blockscout/pull/9335) - Bump mini-css-extract-plugin from 2.7.7 to 2.8.0 in /apps/block_scout_web/assets +- [#9333](https://github.com/blockscout/blockscout/pull/9333) - Bump sweetalert2 from 11.10.3 to 11.10.5 in /apps/block_scout_web/assets +- [#9288](https://github.com/blockscout/blockscout/pull/9288) - Bump solc from 0.8.23 to 0.8.24 in /apps/explorer +- [#9287](https://github.com/blockscout/blockscout/pull/9287) - Bump @babel/preset-env from 7.23.8 to 7.23.9 in /apps/block_scout_web/assets +- [#9331](https://github.com/blockscout/blockscout/pull/9331) - Bump logger_json from 5.1.2 to 5.1.3 +- [#9330](https://github.com/blockscout/blockscout/pull/9330) - Bump hammer from 6.1.0 to 6.2.0 +- [#9294](https://github.com/blockscout/blockscout/pull/9294) - Bump exvcr from 0.15.0 to 0.15.1 +- [#9293](https://github.com/blockscout/blockscout/pull/9293) - Bump floki from 0.35.2 to 0.35.3 +- [#9338](https://github.com/blockscout/blockscout/pull/9338) - Bump postcss-loader from 8.0.0 to 8.1.0 in /apps/block_scout_web/assets +- [#9336](https://github.com/blockscout/blockscout/pull/9336) - Bump web3 from 1.10.3 to 1.10.4 in /apps/block_scout_web/assets +- [#9290](https://github.com/blockscout/blockscout/pull/9290) - Bump ex_doc from 0.31.0 to 0.31.1 +- [#9285](https://github.com/blockscout/blockscout/pull/9285) - Bump @amplitude/analytics-browser from 2.3.8 to 2.4.0 in /apps/block_scout_web/assets +- [#9283](https://github.com/blockscout/blockscout/pull/9283) - Bump @babel/core from 7.23.7 to 7.23.9 in /apps/block_scout_web/assets +- [#9337](https://github.com/blockscout/blockscout/pull/9337) - Bump css-loader from 6.9.1 to 6.10.0 in /apps/block_scout_web/assets +- [#9334](https://github.com/blockscout/blockscout/pull/9334) - Bump sass-loader from 14.0.0 to 14.1.0 in /apps/block_scout_web/assets +- [#9339](https://github.com/blockscout/blockscout/pull/9339) - Bump webpack from 5.89.0 to 5.90.1 in /apps/block_scout_web/assets +- [#9383](https://github.com/blockscout/blockscout/pull/9383) - Bump credo from 1.7.3 to 1.7.4 +- [#9384](https://github.com/blockscout/blockscout/pull/9384) - Bump postcss from 8.4.33 to 8.4.35 in /apps/block_scout_web/assets +- [#9385](https://github.com/blockscout/blockscout/pull/9385) - Bump mixpanel-browser from 2.48.1 to 2.49.0 in /apps/block_scout_web/assets +- [#9423](https://github.com/blockscout/blockscout/pull/9423) - Bump @amplitude/analytics-browser from 2.4.0 to 2.4.1 in /apps/block_scout_web/assets +- [#9422](https://github.com/blockscout/blockscout/pull/9422) - Bump core-js from 3.35.1 to 3.36.0 in /apps/block_scout_web/assets +- [#9424](https://github.com/blockscout/blockscout/pull/9424) - Bump webpack from 5.90.1 to 5.90.3 in /apps/block_scout_web/assets +- [#9425](https://github.com/blockscout/blockscout/pull/9425) - Bump sass-loader from 14.1.0 to 14.1.1 in /apps/block_scout_web/assets +- [#9421](https://github.com/blockscout/blockscout/pull/9421) - Bump sass from 1.70.0 to 1.71.0 in /apps/block_scout_web/assets + +
+ +## 6.1.0 + +### Features + +- [#9189](https://github.com/blockscout/blockscout/pull/9189) - User operations in the search +- [#9169](https://github.com/blockscout/blockscout/pull/9169) - Add bridged tokens functionality to master branch +- [#9158](https://github.com/blockscout/blockscout/pull/9158) - Increase shared memory for PostgreSQL containers +- [#9155](https://github.com/blockscout/blockscout/pull/9155) - Allow bypassing avg block time in proxy implementation re-fetch ttl calculation +- [#9148](https://github.com/blockscout/blockscout/pull/9148) - Add `/api/v2/utils/decode-calldata` +- [#9145](https://github.com/blockscout/blockscout/pull/9145), [#9309](https://github.com/blockscout/blockscout/pull/9309) - Proxy for Account abstraction microservice +- [#9132](https://github.com/blockscout/blockscout/pull/9132) - Fetch token image from CoinGecko +- [#9131](https://github.com/blockscout/blockscout/pull/9131) - Merge addresses stage with address referencing +- [#9120](https://github.com/blockscout/blockscout/pull/9120) - Add GET and POST `/api/v2/smart-contracts/:address_hash/audit-reports` +- [#9072](https://github.com/blockscout/blockscout/pull/9072) - Add tracing by block logic for geth +- [#9185](https://github.com/blockscout/blockscout/pull/9185), [#9068](https://github.com/blockscout/blockscout/pull/9068) - New RPC API v1 endpoints +- [#9056](https://github.com/blockscout/blockscout/pull/9056) - Noves.fi API proxy + +### Fixes + +- [#9275](https://github.com/blockscout/blockscout/pull/9275) - Tx summary endpoint fixes +- [#9261](https://github.com/blockscout/blockscout/pull/9261) - Fix pending transactions sanitizer +- [#9253](https://github.com/blockscout/blockscout/pull/9253) - Don't fetch first trace for pending transactions +- [#9241](https://github.com/blockscout/blockscout/pull/9241) - Fix log decoding bug +- [#9234](https://github.com/blockscout/blockscout/pull/9234) - Add missing filters by non-pending transactions +- [#9229](https://github.com/blockscout/blockscout/pull/9229) - Add missing filter to txlist query +- [#9195](https://github.com/blockscout/blockscout/pull/9195) - API v1 allow multiple slashes in the path before "api" +- [#9187](https://github.com/blockscout/blockscout/pull/9187) - Fix Internal Server Error on request for nonexistent token instance +- [#9178](https://github.com/blockscout/blockscout/pull/9178) - Change internal txs tracer type to opcode for Hardhat node +- [#9173](https://github.com/blockscout/blockscout/pull/9173) - Exclude genesis block from average block time calculation +- [#9143](https://github.com/blockscout/blockscout/pull/9143) - Handle nil token_ids in token transfers on render +- [#9139](https://github.com/blockscout/blockscout/pull/9139) - TokenBalanceOnDemand fixes +- [#9125](https://github.com/blockscout/blockscout/pull/9125) - Fix Explorer.Chain.Cache.GasPriceOracle.merge_fees +- [#9124](https://github.com/blockscout/blockscout/pull/9124) - EIP-1167 display multiple sources of implementation +- [#9110](https://github.com/blockscout/blockscout/pull/9110) - Improve update_in in gas tracker +- [#9109](https://github.com/blockscout/blockscout/pull/9109) - Return current exchange rate in api/v2/stats +- [#9102](https://github.com/blockscout/blockscout/pull/9102) - Fix some log topics for Suave and Polygon Edge +- [#9075](https://github.com/blockscout/blockscout/pull/9075) - Fix fetching contract codes +- [#9073](https://github.com/blockscout/blockscout/pull/9073) - Allow payable function with output appear in the Read tab +- [#9069](https://github.com/blockscout/blockscout/pull/9069) - Fetch realtime coin balances only for addresses for which it has changed + +### Chore + +- [#9323](https://github.com/blockscout/blockscout/pull/9323) - Change index creation to concurrent +- [#9322](https://github.com/blockscout/blockscout/pull/9322) - Create repo setup actions +- [#9303](https://github.com/blockscout/blockscout/pull/9303) - Add workflow for Shibarium +- [#9233](https://github.com/blockscout/blockscout/pull/9233) - "cataloged" index on tokens table +- [#9198](https://github.com/blockscout/blockscout/pull/9198) - Make Postgres@15 default option +- [#9197](https://github.com/blockscout/blockscout/pull/9197) - Add `MARKET_HISTORY_FETCH_INTERVAL` env +- [#9196](https://github.com/blockscout/blockscout/pull/9196) - Compatibility with docker-compose 2.24 +- [#9193](https://github.com/blockscout/blockscout/pull/9193) - Equalize elixir stack versions +- [#9153](https://github.com/blockscout/blockscout/pull/9153) - Enhanced unfetched token balances index + +
+ Dependencies version bumps + +- [#9119](https://github.com/blockscout/blockscout/pull/9119) - Bump sass from 1.69.6 to 1.69.7 in /apps/block_scout_web/assets +- [#9126](https://github.com/blockscout/blockscout/pull/9126) - Bump follow-redirects from 1.14.8 to 1.15.4 in /apps/explorer +- [#9116](https://github.com/blockscout/blockscout/pull/9116) - Bump ueberauth from 0.10.5 to 0.10.7 +- [#9118](https://github.com/blockscout/blockscout/pull/9118) - Bump postcss from 8.4.32 to 8.4.33 in /apps/block_scout_web/assets +- [#9161](https://github.com/blockscout/blockscout/pull/9161) - Bump sass-loader from 13.3.3 to 14.0.0 in /apps/block_scout_web/assets +- [#9160](https://github.com/blockscout/blockscout/pull/9160) - Bump copy-webpack-plugin from 11.0.0 to 12.0.1 in /apps/block_scout_web/assets +- [#9165](https://github.com/blockscout/blockscout/pull/9165) - Bump sweetalert2 from 11.10.2 to 11.10.3 in /apps/block_scout_web/assets +- [#9163](https://github.com/blockscout/blockscout/pull/9163) - Bump mini-css-extract-plugin from 2.7.6 to 2.7.7 in /apps/block_scout_web/assets +- [#9159](https://github.com/blockscout/blockscout/pull/9159) - Bump @babel/preset-env from 7.23.7 to 7.23.8 in /apps/block_scout_web/assets +- [#9162](https://github.com/blockscout/blockscout/pull/9162) - Bump style-loader from 3.3.3 to 3.3.4 in /apps/block_scout_web/assets +- [#9164](https://github.com/blockscout/blockscout/pull/9164) - Bump css-loader from 6.8.1 to 6.9.0 in /apps/block_scout_web/assets +- [#8686](https://github.com/blockscout/blockscout/pull/8686) - Bump dialyxir from 1.4.1 to 1.4.2 +- [#8861](https://github.com/blockscout/blockscout/pull/8861) - Bump briefly from 51dfe7f to 4836ba3 +- [#9117](https://github.com/blockscout/blockscout/pull/9117) - Bump credo from 1.7.1 to 1.7.3 +- [#9222](https://github.com/blockscout/blockscout/pull/9222) - Bump dialyxir from 1.4.2 to 1.4.3 +- [#9219](https://github.com/blockscout/blockscout/pull/9219) - Bump sass from 1.69.7 to 1.70.0 in /apps/block_scout_web/assets +- [#9224](https://github.com/blockscout/blockscout/pull/9224) - Bump ex_cldr_numbers from 2.32.3 to 2.32.4 +- [#9220](https://github.com/blockscout/blockscout/pull/9220) - Bump copy-webpack-plugin from 12.0.1 to 12.0.2 in /apps/block_scout_web/assets +- [#9216](https://github.com/blockscout/blockscout/pull/9216) - Bump core-js from 3.35.0 to 3.35.1 in /apps/block_scout_web/assets +- [#9218](https://github.com/blockscout/blockscout/pull/9218) - Bump postcss-loader from 7.3.4 to 8.0.0 in /apps/block_scout_web/assets +- [#9223](https://github.com/blockscout/blockscout/pull/9223) - Bump plug_cowboy from 2.6.1 to 2.6.2 +- [#9217](https://github.com/blockscout/blockscout/pull/9217) - Bump css-loader from 6.9.0 to 6.9.1 in /apps/block_scout_web/assets +- [#9215](https://github.com/blockscout/blockscout/pull/9215) - Bump css-minimizer-webpack-plugin from 5.0.1 to 6.0.0 in /apps/block_scout_web/assets +- [#9221](https://github.com/blockscout/blockscout/pull/9221) - Bump autoprefixer from 10.4.16 to 10.4.17 in /apps/block_scout_web/assets + +
+ +## 6.0.0 + +### Features + +- [#9112](https://github.com/blockscout/blockscout/pull/9112) - Add specific url for eth_call +- [#9044](https://github.com/blockscout/blockscout/pull/9044) - Expand gas price oracle functionality + +### Fixes + +- [#9113](https://github.com/blockscout/blockscout/pull/9113) - Fix migrators cache updating +- [#9101](https://github.com/blockscout/blockscout/pull/9101) - Fix migration_finished? logic +- [#9062](https://github.com/blockscout/blockscout/pull/9062) - Fix blockscout-ens integration +- [#9061](https://github.com/blockscout/blockscout/pull/9061) - Arbitrum allow tx receipt gasUsedForL1 field +- [#8812](https://github.com/blockscout/blockscout/pull/8812) - Update existing tokens type if got transfer with higher type priority + +### Chore + +- [#9055](https://github.com/blockscout/blockscout/pull/9055) - Add ASC indices for logs, token transfers, transactions +- [#9038](https://github.com/blockscout/blockscout/pull/9038) - Token type filling migrations +- [#9009](https://github.com/blockscout/blockscout/pull/9009) - Index for block refetch_needed +- [#9007](https://github.com/blockscout/blockscout/pull/9007) - Drop logs type index +- [#9006](https://github.com/blockscout/blockscout/pull/9006) - Drop unused indexes on address_current_token_balances table +- [#9005](https://github.com/blockscout/blockscout/pull/9005) - Drop unused token_id column from token_transfers table and indexes based on this column +- [#9000](https://github.com/blockscout/blockscout/pull/9000) - Change log topic type in the DB to bytea +- [#8996](https://github.com/blockscout/blockscout/pull/8996) - Refine token transfers token ids index +- [#8776](https://github.com/blockscout/blockscout/pull/8776) - DB denormalization: block consensus and timestamp in transaction table + +
+ Dependencies version bumps + +- [#9059](https://github.com/blockscout/blockscout/pull/9059) - Bump redux from 5.0.0 to 5.0.1 in /apps/block_scout_web/assets +- [#9057](https://github.com/blockscout/blockscout/pull/9057) - Bump benchee from 1.2.0 to 1.3.0 +- [#9060](https://github.com/blockscout/blockscout/pull/9060) - Bump @amplitude/analytics-browser from 2.3.7 to 2.3.8 in /apps/block_scout_web/assets +- [#9084](https://github.com/blockscout/blockscout/pull/9084) - Bump @babel/preset-env from 7.23.6 to 7.23.7 in /apps/block_scout_web/assets +- [#9083](https://github.com/blockscout/blockscout/pull/9083) - Bump @babel/core from 7.23.6 to 7.23.7 in /apps/block_scout_web/assets +- [#9086](https://github.com/blockscout/blockscout/pull/9086) - Bump core-js from 3.34.0 to 3.35.0 in /apps/block_scout_web/assets +- [#9081](https://github.com/blockscout/blockscout/pull/9081) - Bump sweetalert2 from 11.10.1 to 11.10.2 in /apps/block_scout_web/assets +- [#9085](https://github.com/blockscout/blockscout/pull/9085) - Bump moment from 2.29.4 to 2.30.1 in /apps/block_scout_web/assets +- [#9087](https://github.com/blockscout/blockscout/pull/9087) - Bump postcss-loader from 7.3.3 to 7.3.4 in /apps/block_scout_web/assets +- [#9082](https://github.com/blockscout/blockscout/pull/9082) - Bump sass-loader from 13.3.2 to 13.3.3 in /apps/block_scout_web/assets +- [#9088](https://github.com/blockscout/blockscout/pull/9088) - Bump sass from 1.69.5 to 1.69.6 in /apps/block_scout_web/assets + +
+ +## 5.4.0-beta + +### Features + +- [#9018](https://github.com/blockscout/blockscout/pull/9018) - Add SmartContractRealtimeEventHandler +- [#8997](https://github.com/blockscout/blockscout/pull/8997) - Isolate throttable error count by request method +- [#8975](https://github.com/blockscout/blockscout/pull/8975) - Add EIP-4844 compatibility (not full support yet) +- [#8972](https://github.com/blockscout/blockscout/pull/8972) - BENS integration +- [#8960](https://github.com/blockscout/blockscout/pull/8960) - TRACE_BLOCK_RANGES env var +- [#8957](https://github.com/blockscout/blockscout/pull/8957) - Add Tx Interpreter Service integration +- [#8929](https://github.com/blockscout/blockscout/pull/8929) - Shibarium Bridge indexer and API v2 extension + +### Fixes + +- [#9039](https://github.com/blockscout/blockscout/pull/9039) - Fix tx input decoding in tx summary microservice request +- [#9035](https://github.com/blockscout/blockscout/pull/9035) - Handle Postgrex errors on NFT import +- [#9015](https://github.com/blockscout/blockscout/pull/9015) - Optimize NFT owner preload +- [#9013](https://github.com/blockscout/blockscout/pull/9013) - Speed up `Indexer.Fetcher.TokenInstance.LegacySanitize` +- [#8969](https://github.com/blockscout/blockscout/pull/8969) - Support legacy paging options for address transaction endpoint +- [#8965](https://github.com/blockscout/blockscout/pull/8965) - Set poll: false for internal transactions fetcher +- [#8955](https://github.com/blockscout/blockscout/pull/8955) - Remove daily balances updating from BlockReward fetcher +- [#8846](https://github.com/blockscout/blockscout/pull/8846) - Handle nil gas_price at address view + +### Chore + +- [#9094](https://github.com/blockscout/blockscout/pull/9094) - Improve exchange rates logging +- [#9014](https://github.com/blockscout/blockscout/pull/9014) - Decrease amount of NFT in address collection: 15 -> 9 +- [#8994](https://github.com/blockscout/blockscout/pull/8994) - Refactor transactions event preloads +- [#8991](https://github.com/blockscout/blockscout/pull/8991) - Manage DB queue target via runtime env var + +
+ Dependencies version bumps + +- [#8986](https://github.com/blockscout/blockscout/pull/8986) - Bump chart.js from 4.4.0 to 4.4.1 in /apps/block_scout_web/assets +- [#8982](https://github.com/blockscout/blockscout/pull/8982) - Bump ex_doc from 0.30.9 to 0.31.0 +- [#8987](https://github.com/blockscout/blockscout/pull/8987) - Bump @babel/preset-env from 7.23.5 to 7.23.6 in /apps/block_scout_web/assets +- [#8984](https://github.com/blockscout/blockscout/pull/8984) - Bump ecto_sql from 3.11.0 to 3.11.1 +- [#8988](https://github.com/blockscout/blockscout/pull/8988) - Bump core-js from 3.33.3 to 3.34.0 in /apps/block_scout_web/assets +- [#8980](https://github.com/blockscout/blockscout/pull/8980) - Bump exvcr from 0.14.4 to 0.15.0 +- [#8985](https://github.com/blockscout/blockscout/pull/8985) - Bump @babel/core from 7.23.5 to 7.23.6 in /apps/block_scout_web/assets +- [#9020](https://github.com/blockscout/blockscout/pull/9020) - Bump eslint-plugin-import from 2.29.0 to 2.29.1 in /apps/block_scout_web/assets +- [#9021](https://github.com/blockscout/blockscout/pull/9021) - Bump eslint from 8.55.0 to 8.56.0 in /apps/block_scout_web/assets +- [#9019](https://github.com/blockscout/blockscout/pull/9019) - Bump @amplitude/analytics-browser from 2.3.6 to 2.3.7 in /apps/block_scout_web/assets + +
+ +## 5.3.3-beta + +### Features + +- [#8966](https://github.com/blockscout/blockscout/pull/8966) - Add `ACCOUNT_WATCHLIST_NOTIFICATIONS_LIMIT_FOR_30_DAYS` +- [#8908](https://github.com/blockscout/blockscout/pull/8908) - Solidityscan report API endpoint +- [#8900](https://github.com/blockscout/blockscout/pull/8900) - Add Compound proxy contract pattern +- [#8611](https://github.com/blockscout/blockscout/pull/8611) - Implement sorting of smart contracts, address transactions + +### Fixes + +- [#8959](https://github.com/blockscout/blockscout/pull/8959) - Skip failed instances in Token Instance Owner migrator +- [#8924](https://github.com/blockscout/blockscout/pull/8924) - Delete invalid current token balances in OnDemand fetcher +- [#8922](https://github.com/blockscout/blockscout/pull/8922) - Allow call type to be in lowercase +- [#8917](https://github.com/blockscout/blockscout/pull/8917) - Proxy detection hotfix in API v2 +- [#8915](https://github.com/blockscout/blockscout/pull/8915) - smart-contract: delete embeds_many relation on replace +- [#8906](https://github.com/blockscout/blockscout/pull/8906) - Fix abi encoded string argument +- [#8898](https://github.com/blockscout/blockscout/pull/8898) - Enhance method decoding by candidates from DB +- [#8882](https://github.com/blockscout/blockscout/pull/8882) - Change order of proxy contracts patterns detection: existing popular EIPs to the top of the list +- [#8707](https://github.com/blockscout/blockscout/pull/8707) - Fix native coin exchange rate with `EXCHANGE_RATES_COINGECKO_COIN_ID` + +### Chore + +- [#8956](https://github.com/blockscout/blockscout/pull/8956) - Refine docker-compose config structure +- [#8911](https://github.com/blockscout/blockscout/pull/8911) - Set client_connection_check_interval for main Postgres DB in docker-compose setup + +
+ Dependencies version bumps + +- [#8863](https://github.com/blockscout/blockscout/pull/8863) - Bump core-js from 3.33.2 to 3.33.3 in /apps/block_scout_web/assets +- [#8864](https://github.com/blockscout/blockscout/pull/8864) - Bump @amplitude/analytics-browser from 2.3.3 to 2.3.5 in /apps/block_scout_web/assets +- [#8860](https://github.com/blockscout/blockscout/pull/8860) - Bump ecto_sql from 3.10.2 to 3.11.0 +- [#8896](https://github.com/blockscout/blockscout/pull/8896) - Bump httpoison from 2.2.0 to 2.2.1 +- [#8867](https://github.com/blockscout/blockscout/pull/8867) - Bump mixpanel-browser from 2.47.0 to 2.48.1 in /apps/block_scout_web/assets +- [#8865](https://github.com/blockscout/blockscout/pull/8865) - Bump eslint from 8.53.0 to 8.54.0 in /apps/block_scout_web/assets +- [#8866](https://github.com/blockscout/blockscout/pull/8866) - Bump sweetalert2 from 11.9.0 to 11.10.1 in /apps/block_scout_web/assets +- [#8897](https://github.com/blockscout/blockscout/pull/8897) - Bump prometheus from 4.10.0 to 4.11.0 +- [#8859](https://github.com/blockscout/blockscout/pull/8859) - Bump absinthe from 1.7.5 to 1.7.6 +- [#8858](https://github.com/blockscout/blockscout/pull/8858) - Bump ex_json_schema from 0.10.1 to 0.10.2 +- [#8943](https://github.com/blockscout/blockscout/pull/8943) - Bump postgrex from 0.17.3 to 0.17.4 +- [#8939](https://github.com/blockscout/blockscout/pull/8939) - Bump @babel/core from 7.23.3 to 7.23.5 in /apps/block_scout_web/assets +- [#8936](https://github.com/blockscout/blockscout/pull/8936) - Bump eslint from 8.54.0 to 8.55.0 in /apps/block_scout_web/assets +- [#8940](https://github.com/blockscout/blockscout/pull/8940) - Bump photoswipe from 5.4.2 to 5.4.3 in /apps/block_scout_web/assets +- [#8938](https://github.com/blockscout/blockscout/pull/8938) - Bump @babel/preset-env from 7.23.3 to 7.23.5 in /apps/block_scout_web/assets +- [#8935](https://github.com/blockscout/blockscout/pull/8935) - Bump @amplitude/analytics-browser from 2.3.5 to 2.3.6 in /apps/block_scout_web/assets +- [#8937](https://github.com/blockscout/blockscout/pull/8937) - Bump redux from 4.2.1 to 5.0.0 in /apps/block_scout_web/assets +- [#8942](https://github.com/blockscout/blockscout/pull/8942) - Bump gettext from 0.23.1 to 0.24.0 +- [#8934](https://github.com/blockscout/blockscout/pull/8934) - Bump @fortawesome/fontawesome-free from 6.4.2 to 6.5.1 in /apps/block_scout_web/assets +- [#8933](https://github.com/blockscout/blockscout/pull/8933) - Bump postcss from 8.4.31 to 8.4.32 in /apps/block_scout_web/assets + +
+ +## 5.3.2-beta + +### Features + +- [#8848](https://github.com/blockscout/blockscout/pull/8848) - Add MainPageRealtimeEventHandler +- [#8821](https://github.com/blockscout/blockscout/pull/8821) - Add new events to addresses channel: `eth_bytecode_db_lookup_started` and `smart_contract_was_not_verified` +- [#8795](https://github.com/blockscout/blockscout/pull/8795) - Disable catchup indexer by env +- [#8768](https://github.com/blockscout/blockscout/pull/8768) - Add possibility to search tokens by address hash +- [#8750](https://github.com/blockscout/blockscout/pull/8750) - Support new eth-bytecode-db request metadata fields +- [#8634](https://github.com/blockscout/blockscout/pull/8634) - API v2: NFT for address +- [#8609](https://github.com/blockscout/blockscout/pull/8609) - Change logs format to JSON; Add endpoint url to the block_scout_web logging +- [#8558](https://github.com/blockscout/blockscout/pull/8558) - Add CoinBalanceDailyUpdater + +### Fixes + +- [#8891](https://github.com/blockscout/blockscout/pull/8891) - Fix average block time +- [#8869](https://github.com/blockscout/blockscout/pull/8869) - Limit TokenBalance fetcher timeout +- [#8855](https://github.com/blockscout/blockscout/pull/8855) - All transactions count at top addresses page +- [#8836](https://github.com/blockscout/blockscout/pull/8836) - Safe token update +- [#8814](https://github.com/blockscout/blockscout/pull/8814) - Improve performance for EOA addresses in `/api/v2/addresses/{address_hash}` +- [#8813](https://github.com/blockscout/blockscout/pull/8813) - Force verify twin contracts on `/api/v2/import/smart-contracts/{address_hash}` +- [#8784](https://github.com/blockscout/blockscout/pull/8784) - Fix Indexer.Transform.Addresses for non-Suave setup +- [#8770](https://github.com/blockscout/blockscout/pull/8770) - Fix for eth_getbalance API v1 endpoint when requesting latest tag +- [#8765](https://github.com/blockscout/blockscout/pull/8765) - Fix for tvl update in market history when row already exists +- [#8759](https://github.com/blockscout/blockscout/pull/8759) - Gnosis safe proxy via singleton input +- [#8752](https://github.com/blockscout/blockscout/pull/8752) - Add `TOKEN_INSTANCE_OWNER_MIGRATION_ENABLED` env +- [#8724](https://github.com/blockscout/blockscout/pull/8724) - Fix flaky account notifier test + +### Chore + +- [#8832](https://github.com/blockscout/blockscout/pull/8832) - Log more details in regards 413 error +- [#8807](https://github.com/blockscout/blockscout/pull/8807) - Smart-contract proxy detection refactoring +- [#8802](https://github.com/blockscout/blockscout/pull/8802) - Enable API v2 by default +- [#8742](https://github.com/blockscout/blockscout/pull/8742) - Merge rsk branch into the master branch +- [#8728](https://github.com/blockscout/blockscout/pull/8728) - Remove repos_list (default value for ecto repos) from Explorer.ReleaseTasks + +
+ Dependencies version bumps + +- [#8727](https://github.com/blockscout/blockscout/pull/8727) - Bump browserify-sign from 4.2.1 to 4.2.2 in /apps/block_scout_web/assets +- [#8748](https://github.com/blockscout/blockscout/pull/8748) - Bump sweetalert2 from 11.7.32 to 11.9.0 in /apps/block_scout_web/assets +- [#8747](https://github.com/blockscout/blockscout/pull/8747) - Bump core-js from 3.33.1 to 3.33.2 in /apps/block_scout_web/assets +- [#8743](https://github.com/blockscout/blockscout/pull/8743) - Bump solc from 0.8.21 to 0.8.22 in /apps/explorer +- [#8745](https://github.com/blockscout/blockscout/pull/8745) - Bump tesla from 1.7.0 to 1.8.0 +- [#8749](https://github.com/blockscout/blockscout/pull/8749) - Bump sass from 1.69.4 to 1.69.5 in /apps/block_scout_web/assets +- [#8744](https://github.com/blockscout/blockscout/pull/8744) - Bump phoenix_ecto from 4.4.2 to 4.4.3 +- [#8746](https://github.com/blockscout/blockscout/pull/8746) - Bump floki from 0.35.1 to 0.35.2 +- [#8793](https://github.com/blockscout/blockscout/pull/8793) - Bump eslint from 8.52.0 to 8.53.0 in /apps/block_scout_web/assets +- [#8792](https://github.com/blockscout/blockscout/pull/8792) - Bump cldr_utils from 2.24.1 to 2.24.2 +- [#8787](https://github.com/blockscout/blockscout/pull/8787) - Bump ex_cldr_numbers from 2.32.2 to 2.32.3 +- [#8790](https://github.com/blockscout/blockscout/pull/8790) - Bump ex_abi from 0.6.3 to 0.6.4 +- [#8788](https://github.com/blockscout/blockscout/pull/8788) - Bump ex_cldr_units from 3.16.3 to 3.16.4 +- [#8827](https://github.com/blockscout/blockscout/pull/8827) - Bump @babel/core from 7.23.2 to 7.23.3 in /apps/block_scout_web/assets +- [#8823](https://github.com/blockscout/blockscout/pull/8823) - Bump benchee from 1.1.0 to 1.2.0 +- [#8826](https://github.com/blockscout/blockscout/pull/8826) - Bump luxon from 3.4.3 to 3.4.4 in /apps/block_scout_web/assets +- [#8824](https://github.com/blockscout/blockscout/pull/8824) - Bump httpoison from 2.1.0 to 2.2.0 +- [#8828](https://github.com/blockscout/blockscout/pull/8828) - Bump @babel/preset-env from 7.23.2 to 7.23.3 in /apps/block_scout_web/assets +- [#8825](https://github.com/blockscout/blockscout/pull/8825) - Bump solc from 0.8.22 to 0.8.23 in /apps/explorer + +
+ +## 5.3.1-beta + +### Features + +- [#8717](https://github.com/blockscout/blockscout/pull/8717) - Save GasPriceOracle old prices as a fallback +- [#8696](https://github.com/blockscout/blockscout/pull/8696) - Support tokenSymbol and tokenName in `/api/v2/import/token-info` +- [#8673](https://github.com/blockscout/blockscout/pull/8673) - Add a window for balances fetching from non-archive node +- [#8651](https://github.com/blockscout/blockscout/pull/8651) - Add `stability_fee` for CHAIN_TYPE=stability +- [#8556](https://github.com/blockscout/blockscout/pull/8556) - Suave functional +- [#8528](https://github.com/blockscout/blockscout/pull/8528) - Account: add pagination + envs for limits +- [#7584](https://github.com/blockscout/blockscout/pull/7584) - Add Polygon zkEVM batches fetcher + +### Fixes + +- [#8714](https://github.com/blockscout/blockscout/pull/8714) - Fix sourcify check +- [#8708](https://github.com/blockscout/blockscout/pull/8708) - CoinBalanceHistory tab: show also tx with gasPrice & gasUsed > 0 +- [#8706](https://github.com/blockscout/blockscout/pull/8706) - Add address name updating on contract re-verification +- [#8705](https://github.com/blockscout/blockscout/pull/8705) - Fix sourcify enabled flag +- [#8695](https://github.com/blockscout/blockscout/pull/8695), [#8755](https://github.com/blockscout/blockscout/pull/8755) - Don't override internal transaction error if it's present already +- [#8685](https://github.com/blockscout/blockscout/pull/8685) - Fix db pool size exceeds Postgres max connections +- [#8678](https://github.com/blockscout/blockscout/pull/8678) - Fix `is_verified` for `/addresses` and `/smart-contracts` + +### Chore + +- [#8715](https://github.com/blockscout/blockscout/pull/8715) - Rename `wrapped` field to `requestRecord` for Suave + +
+ Dependencies version bumps + +- [#8683](https://github.com/blockscout/blockscout/pull/8683) - Bump eslint from 8.51.0 to 8.52.0 in /apps/block_scout_web/assets +- [#8689](https://github.com/blockscout/blockscout/pull/8689) - Bump ex_abi from 0.6.2 to 0.6.3 +- [#8682](https://github.com/blockscout/blockscout/pull/8682) - Bump core-js from 3.33.0 to 3.33.1 in /apps/block_scout_web/assets +- [#8680](https://github.com/blockscout/blockscout/pull/8680) - Bump web3 from 1.10.2 to 1.10.3 in /apps/block_scout_web/assets +- [#8681](https://github.com/blockscout/blockscout/pull/8681) - Bump eslint-plugin-import from 2.28.1 to 2.29.0 in /apps/block_scout_web/assets +- [#8684](https://github.com/blockscout/blockscout/pull/8684) - Bump @amplitude/analytics-browser from 2.3.2 to 2.3.3 in /apps/block_scout_web/assets +- [#8679](https://github.com/blockscout/blockscout/pull/8679) - Bump sass from 1.69.3 to 1.69.4 in /apps/block_scout_web/assets +- [#8687](https://github.com/blockscout/blockscout/pull/8687) - Bump floki from 0.35.0 to 0.35.1 +- [#8693](https://github.com/blockscout/blockscout/pull/8693) - Bump redix from 1.2.3 to 1.3.0 +- [#8688](https://github.com/blockscout/blockscout/pull/8688) - Bump ex_doc from 0.30.7 to 0.30.9 + +
+ +## 5.3.0-beta + +### Features + +- [#8512](https://github.com/blockscout/blockscout/pull/8512) - Add caching and improve `/tabs-counters` performance +- [#8472](https://github.com/blockscout/blockscout/pull/8472) - Integrate `/api/v2/bytecodes/sources:search-all` of `eth_bytecode_db` +- [#8589](https://github.com/blockscout/blockscout/pull/8589) - DefiLlama TVL source +- [#8544](https://github.com/blockscout/blockscout/pull/8544) - Fix `nil` `"structLogs"` +- [#8583](https://github.com/blockscout/blockscout/pull/8583) - Add stats widget for rootstock +- [#8542](https://github.com/blockscout/blockscout/pull/8542) - Add tracing for rootstock +- [#8561](https://github.com/blockscout/blockscout/pull/8561), [#8564](https://github.com/blockscout/blockscout/pull/8564) - Get historical market cap data from CoinGecko +- [#8543](https://github.com/blockscout/blockscout/pull/8543) - Fix polygon tracer +- [#8386](https://github.com/blockscout/blockscout/pull/8386) - Add `owner_address_hash` to the `token_instances` +- [#8530](https://github.com/blockscout/blockscout/pull/8530) - Add `block_type` to search results +- [#8180](https://github.com/blockscout/blockscout/pull/8180) - Deposits and Withdrawals for Polygon Edge +- [#7996](https://github.com/blockscout/blockscout/pull/7996) - Add CoinBalance fetcher init query limit +- [#8658](https://github.com/blockscout/blockscout/pull/8658) - Remove block consensus on import fail +- [#8575](https://github.com/blockscout/blockscout/pull/8575) - Filter token transfers on coin balances updates + +### Fixes + +- [#8661](https://github.com/blockscout/blockscout/pull/8661) - arm64-compatible docker image +- [#8649](https://github.com/blockscout/blockscout/pull/8649) - Set max 30sec JSON RPC poll frequency for realtime fetcher when WS is disabled +- [#8614](https://github.com/blockscout/blockscout/pull/8614) - Disable market history cataloger fetcher when exchange rates are disabled +- [#8613](https://github.com/blockscout/blockscout/pull/8613) - Refactor parsing of FIRST_BLOCK, LAST_BLOCK, TRACE_FIRST_BLOCK, TRACE_LAST_BLOCK env variables +- [#8572](https://github.com/blockscout/blockscout/pull/8572) - Refactor docker-compose config +- [#8552](https://github.com/blockscout/blockscout/pull/8552) - Add CHAIN_TYPE build arg to Dockerfile +- [#8550](https://github.com/blockscout/blockscout/pull/8550) - Sanitize paging params +- [#8515](https://github.com/blockscout/blockscout/pull/8515) - Fix `:error.types/0 is undefined` warning +- [#7959](https://github.com/blockscout/blockscout/pull/7959) - Fix empty batch transfers handling +- [#8513](https://github.com/blockscout/blockscout/pull/8513) - Don't override transaction status +- [#8620](https://github.com/blockscout/blockscout/pull/8620) - Fix the display of icons +- [#8594](https://github.com/blockscout/blockscout/pull/8594) - Fix TokenBalance fetcher retry logic + +### Chore + +- [#8584](https://github.com/blockscout/blockscout/pull/8584) - Store chain together with cookie hash in Redis +- [#8579](https://github.com/blockscout/blockscout/pull/8579), [#8590](https://github.com/blockscout/blockscout/pull/8590) - IPFS gateway URL runtime env variable +- [#8573](https://github.com/blockscout/blockscout/pull/8573) - Update Nginx to proxy all frontend paths +- [#8290](https://github.com/blockscout/blockscout/pull/8290) - Update Chromedriver version +- [#8536](https://github.com/blockscout/blockscout/pull/8536), [#8537](https://github.com/blockscout/blockscout/pull/8537), [#8540](https://github.com/blockscout/blockscout/pull/8540), [#8557](https://github.com/blockscout/blockscout/pull/8557) - New issue template +- [#8529](https://github.com/blockscout/blockscout/pull/8529) - Move PolygonEdge-related migration to the corresponding ecto repository +- [#8504](https://github.com/blockscout/blockscout/pull/8504) - Deploy new UI through Makefile +- [#8501](https://github.com/blockscout/blockscout/pull/8501) - Conceal secondary ports in docker compose setup + +
+ Dependencies version bumps + +- [#8508](https://github.com/blockscout/blockscout/pull/8508) - Bump sass from 1.67.0 to 1.68.0 in /apps/block_scout_web/assets +- [#8509](https://github.com/blockscout/blockscout/pull/8509) - Bump autoprefixer from 10.4.15 to 10.4.16 in /apps/block_scout_web/assets +- [#8511](https://github.com/blockscout/blockscout/pull/8511) - Bump mox from 1.0.2 to 1.1.0 +- [#8532](https://github.com/blockscout/blockscout/pull/8532) - Bump eslint from 8.49.0 to 8.50.0 in /apps/block_scout_web/assets +- [#8533](https://github.com/blockscout/blockscout/pull/8533) - Bump sweetalert2 from 11.7.28 to 11.7.29 in /apps/block_scout_web/assets +- [#8531](https://github.com/blockscout/blockscout/pull/8531) - Bump ex_cldr_units from 3.16.2 to 3.16.3 +- [#8534](https://github.com/blockscout/blockscout/pull/8534) - Bump @babel/core from 7.22.20 to 7.23.0 in /apps/block_scout_web/assets +- [#8546](https://github.com/blockscout/blockscout/pull/8546) - Bump sweetalert2 from 11.7.29 to 11.7.31 in /apps/block_scout_web/assets +- [#8553](https://github.com/blockscout/blockscout/pull/8553) - Bump @amplitude/analytics-browser from 2.3.1 to 2.3.2 in /apps/block_scout_web/assets +- [#8554](https://github.com/blockscout/blockscout/pull/8554) - https://github.com/blockscout/blockscout/pull/8554 +- [#8547](https://github.com/blockscout/blockscout/pull/8547) - Bump briefly from 678a376 to 51dfe7f +- [#8567](https://github.com/blockscout/blockscout/pull/8567) - Bump photoswipe from 5.4.1 to 5.4.2 in /apps/block_scout_web/assets +- [#8566](https://github.com/blockscout/blockscout/pull/8566) - Bump postcss from 8.4.30 to 8.4.31 in /apps/block_scout_web/assets +- [#7575](https://github.com/blockscout/blockscout/pull/7575) - Bump css-loader from 5.2.7 to 6.8.1 in /apps/block_scout_web/assets +- [#8569](https://github.com/blockscout/blockscout/pull/8569) - Bump web3 from 1.10.0 to 1.10.2 in /apps/block_scout_web/assets +- [#8570](https://github.com/blockscout/blockscout/pull/8570) - Bump core-js from 3.32.2 to 3.33.0 in /apps/block_scout_web/assets +- [#8581](https://github.com/blockscout/blockscout/pull/8581) - Bump credo from 1.7.0 to 1.7.1 +- [#8607](https://github.com/blockscout/blockscout/pull/8607) - Bump sass from 1.68.0 to 1.69.0 in /apps/block_scout_web/assets +- [#8606](https://github.com/blockscout/blockscout/pull/8606) - Bump highlight.js from 11.8.0 to 11.9.0 in /apps/block_scout_web/assets +- [#8605](https://github.com/blockscout/blockscout/pull/8605) - Bump eslint from 8.50.0 to 8.51.0 in /apps/block_scout_web/assets +- [#8608](https://github.com/blockscout/blockscout/pull/8608) - Bump sweetalert2 from 11.7.31 to 11.7.32 in /apps/block_scout_web/assets +- [#8510](https://github.com/blockscout/blockscout/pull/8510) - Bump hackney from 1.18.1 to 1.19.1 +- [#8637](https://github.com/blockscout/blockscout/pull/8637) - Bump @babel/preset-env from 7.22.20 to 7.23.2 in /apps/block_scout_web/assets +- [#8639](https://github.com/blockscout/blockscout/pull/8639) - Bump sass from 1.69.0 to 1.69.3 in /apps/block_scout_web/assets +- [#8643](https://github.com/blockscout/blockscout/pull/8643) - Bump floki from 0.34.3 to 0.35.0 +- [#8641](https://github.com/blockscout/blockscout/pull/8641) - Bump ex_cldr from 2.37.2 to 2.37.4 +- [#8646](https://github.com/blockscout/blockscout/pull/8646) - Bump @babel/traverse from 7.23.0 to 7.23.2 in /apps/block_scout_web/assets +- [#8636](https://github.com/blockscout/blockscout/pull/8636) - Bump @babel/core from 7.23.0 to 7.23.2 in /apps/block_scout_web/assets +- [#8645](https://github.com/blockscout/blockscout/pull/8645) - Bump ex_doc from 0.30.6 to 0.30.7 +- [#8638](https://github.com/blockscout/blockscout/pull/8638) - Bump webpack from 5.88.2 to 5.89.0 in /apps/block_scout_web/assets +- [#8640](https://github.com/blockscout/blockscout/pull/8640) - Bump hackney from 1.19.1 to 1.20.1 + +
+ +## 5.2.3-beta + +### Features + +- [#8382](https://github.com/blockscout/blockscout/pull/8382) - Add sitemap.xml +- [#8313](https://github.com/blockscout/blockscout/pull/8313) - Add batches to TokenInstance fetchers +- [#8285](https://github.com/blockscout/blockscout/pull/8285), [#8399](https://github.com/blockscout/blockscout/pull/8399) - Add CG/CMC coin price sources +- [#8181](https://github.com/blockscout/blockscout/pull/8181) - Insert current token balances placeholders along with historical +- [#8210](https://github.com/blockscout/blockscout/pull/8210) - Drop address foreign keys +- [#8292](https://github.com/blockscout/blockscout/pull/8292) - Add ETHEREUM_JSONRPC_WAIT_PER_TIMEOUT env var +- [#8269](https://github.com/blockscout/blockscout/pull/8269) - Don't push back to sequence on catchup exception +- [#8362](https://github.com/blockscout/blockscout/pull/8362), [#8398](https://github.com/blockscout/blockscout/pull/8398) - Drop token balances tokens foreign key + +### Fixes + +- [#8446](https://github.com/blockscout/blockscout/pull/8446) - Fix market cap calculation in case of CMC +- [#8431](https://github.com/blockscout/blockscout/pull/8431) - Fix contracts' output decoding +- [#8354](https://github.com/blockscout/blockscout/pull/8354) - Hotfix for proper addresses' tokens displaying +- [#8350](https://github.com/blockscout/blockscout/pull/8350) - Add Base Mainnet support for tx actions +- [#8282](https://github.com/blockscout/blockscout/pull/8282) - NFT fetcher improvements +- [#8287](https://github.com/blockscout/blockscout/pull/8287) - Add separate hackney pool for TokenInstance fetchers +- [#8293](https://github.com/blockscout/blockscout/pull/8293) - Add ETHEREUM_JSONRPC_TRACE_URL for Geth in docker-compose.yml +- [#8240](https://github.com/blockscout/blockscout/pull/8240) - Refactor and fix paging params in API v2 +- [#8242](https://github.com/blockscout/blockscout/pull/8242) - Fixing visualizer service CORS issue when running docker-compose +- [#8355](https://github.com/blockscout/blockscout/pull/8355) - Fix current token balances redefining +- [#8338](https://github.com/blockscout/blockscout/pull/8338) - Fix reorgs query +- [#8413](https://github.com/blockscout/blockscout/pull/8413) - Put error in last call for STOP opcode +- [#8447](https://github.com/blockscout/blockscout/pull/8447) - Fix reorg transactions + +### Chore + +- [#8494](https://github.com/blockscout/blockscout/pull/8494) - Add release announcement in Slack +- [#8493](https://github.com/blockscout/blockscout/pull/8493) - Fix arm docker image build +- [#8478](https://github.com/blockscout/blockscout/pull/8478) - Set integration with Blockscout's eth bytecode DB endpoint by default and other enhancements +- [#8442](https://github.com/blockscout/blockscout/pull/8442) - Unify burn address definition +- [#8321](https://github.com/blockscout/blockscout/pull/8321) - Add curl into resulting Docker image +- [#8319](https://github.com/blockscout/blockscout/pull/8319) - Add MIX_ENV: 'prod' to docker-compose +- [#8281](https://github.com/blockscout/blockscout/pull/8281) - Planned removal of duplicate API endpoints: for CSV export and GraphQL + +
+ Dependencies version bumps + +- [#8244](https://github.com/blockscout/blockscout/pull/8244) - Bump core-js from 3.32.0 to 3.32.1 in /apps/block_scout_web/assets +- [#8243](https://github.com/blockscout/blockscout/pull/8243) - Bump sass from 1.65.1 to 1.66.0 in /apps/block_scout_web/assets +- [#8259](https://github.com/blockscout/blockscout/pull/8259) - Bump sweetalert2 from 11.7.23 to 11.7.27 in /apps/block_scout_web/assets +- [#8258](https://github.com/blockscout/blockscout/pull/8258) - Bump sass from 1.66.0 to 1.66.1 in /apps/block_scout_web/assets +- [#8260](https://github.com/blockscout/blockscout/pull/8260) - Bump jest from 29.6.2 to 29.6.3 in /apps/block_scout_web/assets +- [#8261](https://github.com/blockscout/blockscout/pull/8261) - Bump eslint-plugin-import from 2.28.0 to 2.28.1 in /apps/block_scout_web/assets +- [#8262](https://github.com/blockscout/blockscout/pull/8262) - Bump jest-environment-jsdom from 29.6.2 to 29.6.3 in /apps/block_scout_web/assets +- [#8275](https://github.com/blockscout/blockscout/pull/8275) - Bump ecto_sql from 3.10.1 to 3.10.2 +- [#8284](https://github.com/blockscout/blockscout/pull/8284) - Bump luxon from 3.4.0 to 3.4.1 in /apps/block_scout_web/assets +- [#8294](https://github.com/blockscout/blockscout/pull/8294) - Bump chart.js from 4.3.3 to 4.4.0 in /apps/block_scout_web/assets +- [#8295](https://github.com/blockscout/blockscout/pull/8295) - Bump jest from 29.6.3 to 29.6.4 in /apps/block_scout_web/assets +- [#8296](https://github.com/blockscout/blockscout/pull/8296) - Bump jest-environment-jsdom from 29.6.3 to 29.6.4 in /apps/block_scout_web/assets +- [#8297](https://github.com/blockscout/blockscout/pull/8297) - Bump @babel/core from 7.22.10 to 7.22.11 in /apps/block_scout_web/assets +- [#8305](https://github.com/blockscout/blockscout/pull/8305) - Bump @amplitude/analytics-browser from 2.2.0 to 2.2.1 in /apps/block_scout_web/assets +- [#8342](https://github.com/blockscout/blockscout/pull/8342) - Bump postgrex from 0.17.2 to 0.17.3 +- [#8341](https://github.com/blockscout/blockscout/pull/8341) - Bump hackney from 1.18.1 to 1.18.2 +- [#8343](https://github.com/blockscout/blockscout/pull/8343) - Bump @amplitude/analytics-browser from 2.2.1 to 2.2.2 in /apps/block_scout_web/assets +- [#8344](https://github.com/blockscout/blockscout/pull/8344) - Bump postcss from 8.4.28 to 8.4.29 in /apps/block_scout_web/assets +- [#8330](https://github.com/blockscout/blockscout/pull/8330) - Bump bignumber.js from 9.1.1 to 9.1.2 in /apps/block_scout_web/assets +- [#8332](https://github.com/blockscout/blockscout/pull/8332) - Bump jquery from 3.7.0 to 3.7.1 in /apps/block_scout_web/assets +- [#8329](https://github.com/blockscout/blockscout/pull/8329) - Bump viewerjs from 1.11.4 to 1.11.5 in /apps/block_scout_web/assets +- [#8328](https://github.com/blockscout/blockscout/pull/8328) - Bump eslint from 8.47.0 to 8.48.0 in /apps/block_scout_web/assets +- [#8325](https://github.com/blockscout/blockscout/pull/8325) - Bump exvcr from 0.14.3 to 0.14.4 +- [#8323](https://github.com/blockscout/blockscout/pull/8323) - Bump ex_doc from 0.30.5 to 0.30.6 +- [#8322](https://github.com/blockscout/blockscout/pull/8322) - Bump dialyxir from 1.3.0 to 1.4.0 +- [#8326](https://github.com/blockscout/blockscout/pull/8326) - Bump comeonin from 5.3.3 to 5.4.0 +- [#8331](https://github.com/blockscout/blockscout/pull/8331) - Bump luxon from 3.4.1 to 3.4.2 in /apps/block_scout_web/assets +- [#8324](https://github.com/blockscout/blockscout/pull/8324) - Bump spandex_datadog from 1.3.0 to 1.4.0 +- [#8327](https://github.com/blockscout/blockscout/pull/8327) - Bump bcrypt_elixir from 3.0.1 to 3.1.0 +- [#8358](https://github.com/blockscout/blockscout/pull/8358) - Bump @babel/preset-env from 7.22.10 to 7.22.14 in /apps/block_scout_web/assets +- [#8365](https://github.com/blockscout/blockscout/pull/8365) - Bump dialyxir from 1.4.0 to 1.4.1 +- [#8374](https://github.com/blockscout/blockscout/pull/8374) - Bump @amplitude/analytics-browser from 2.2.2 to 2.2.3 in /apps/block_scout_web/assets +- [#8373](https://github.com/blockscout/blockscout/pull/8373) - Bump ex_secp256k1 from 0.7.0 to 0.7.1 +- [#8391](https://github.com/blockscout/blockscout/pull/8391) - Bump @babel/preset-env from 7.22.14 to 7.22.15 in /apps/block_scout_web/assets +- [#8390](https://github.com/blockscout/blockscout/pull/8390) - Bump photoswipe from 5.3.8 to 5.3.9 in /apps/block_scout_web/assets +- [#8389](https://github.com/blockscout/blockscout/pull/8389) - Bump @babel/core from 7.22.11 to 7.22.15 in /apps/block_scout_web/assets +- [#8392](https://github.com/blockscout/blockscout/pull/8392) - Bump ex_cldr_numbers from 2.31.3 to 2.32.0 +- [#8400](https://github.com/blockscout/blockscout/pull/8400) - Bump ex_secp256k1 from 0.7.1 to 0.7.2 +- [#8405](https://github.com/blockscout/blockscout/pull/8405) - Bump luxon from 3.4.2 to 3.4.3 in /apps/block_scout_web/assets +- [#8404](https://github.com/blockscout/blockscout/pull/8404) - Bump ex_abi from 0.6.0 to 0.6.1 +- [#8410](https://github.com/blockscout/blockscout/pull/8410) - Bump core-js from 3.32.1 to 3.32.2 in /apps/block_scout_web/assets +- [#8418](https://github.com/blockscout/blockscout/pull/8418) - Bump url from 0.11.1 to 0.11.2 in /apps/block_scout_web/assets +- [#8416](https://github.com/blockscout/blockscout/pull/8416) - Bump @babel/core from 7.22.15 to 7.22.17 in /apps/block_scout_web/assets +- [#8419](https://github.com/blockscout/blockscout/pull/8419) - Bump assert from 2.0.0 to 2.1.0 in /apps/block_scout_web/assets +- [#8417](https://github.com/blockscout/blockscout/pull/8417) - Bump photoswipe from 5.3.9 to 5.4.0 in /apps/block_scout_web/assets +- [#8441](https://github.com/blockscout/blockscout/pull/8441) - Bump eslint from 8.48.0 to 8.49.0 in /apps/block_scout_web/assets +- [#8439](https://github.com/blockscout/blockscout/pull/8439) - Bump ex_cldr_numbers from 2.32.0 to 2.32.1 +- [#8444](https://github.com/blockscout/blockscout/pull/8444) - Bump ex_cldr_numbers from 2.32.1 to 2.32.2 +- [#8445](https://github.com/blockscout/blockscout/pull/8445) - Bump ex_abi from 0.6.1 to 0.6.2 +- [#8450](https://github.com/blockscout/blockscout/pull/8450) - Bump jest-environment-jsdom from 29.6.4 to 29.7.0 in /apps/block_scout_web/assets +- [#8451](https://github.com/blockscout/blockscout/pull/8451) - Bump jest from 29.6.4 to 29.7.0 in /apps/block_scout_web/assets +- [#8463](https://github.com/blockscout/blockscout/pull/8463) - Bump sass from 1.66.1 to 1.67.0 in /apps/block_scout_web/assets +- [#8464](https://github.com/blockscout/blockscout/pull/8464) - Bump @babel/core from 7.22.17 to 7.22.19 in /apps/block_scout_web/assets +- [#8462](https://github.com/blockscout/blockscout/pull/8462) - Bump sweetalert2 from 11.7.27 to 11.7.28 in /apps/block_scout_web/assets +- [#8479](https://github.com/blockscout/blockscout/pull/8479) - Bump photoswipe from 5.4.0 to 5.4.1 in /apps/block_scout_web/assets +- [#8483](https://github.com/blockscout/blockscout/pull/8483) - Bump @amplitude/analytics-browser from 2.2.3 to 2.3.1 in /apps/block_scout_web/assets +- [#8481](https://github.com/blockscout/blockscout/pull/8481) - Bump @babel/preset-env from 7.22.15 to 7.22.20 in /apps/block_scout_web/assets +- [#8480](https://github.com/blockscout/blockscout/pull/8480) - Bump @babel/core from 7.22.19 to 7.22.20 in /apps/block_scout_web/assets +- [#8482](https://github.com/blockscout/blockscout/pull/8482) - Bump viewerjs from 1.11.5 to 1.11.6 in /apps/block_scout_web/assets +- [#8489](https://github.com/blockscout/blockscout/pull/8489) - Bump postcss from 8.4.29 to 8.4.30 in /apps/block_scout_web/assets + +
+ +## 5.2.2-beta + +### Features + +- [#8218](https://github.com/blockscout/blockscout/pull/8218) - Add `/api/v2/search/quick` method +- [#8202](https://github.com/blockscout/blockscout/pull/8202) - Add `/api/v2/addresses/:address_hash/tabs-counters` endpoint +- [#8156](https://github.com/blockscout/blockscout/pull/8156) - Add `is_verified_via_admin_panel` property to tokens table +- [#8165](https://github.com/blockscout/blockscout/pull/8165), [#8201](https://github.com/blockscout/blockscout/pull/8201) - Add broadcast of updated address_current_token_balances +- [#7952](https://github.com/blockscout/blockscout/pull/7952) - Add parsing constructor arguments for sourcify contracts +- [#6190](https://github.com/blockscout/blockscout/pull/6190) - Add EIP-1559 support to gas price oracle +- [#7977](https://github.com/blockscout/blockscout/pull/7977) - GraphQL: extend schema with new field for existing objects +- [#8158](https://github.com/blockscout/blockscout/pull/8158), [#8164](https://github.com/blockscout/blockscout/pull/8164) - Include unfetched balances in TokenBalanceOnDemand fetcher + +### Fixes + +- [#8233](https://github.com/blockscout/blockscout/pull/8233) - Fix API v2 broken tx response +- [#8147](https://github.com/blockscout/blockscout/pull/8147) - Switch sourcify tests from POA Sokol to Gnosis Chiado +- [#8145](https://github.com/blockscout/blockscout/pull/8145) - Handle negative holders count in API v2 +- [#8040](https://github.com/blockscout/blockscout/pull/8040) - Resolve issue with Docker image for Mac M1/M2 +- [#8060](https://github.com/blockscout/blockscout/pull/8060) - Fix eth_getLogs API endpoint +- [#8082](https://github.com/blockscout/blockscout/pull/8082), [#8088](https://github.com/blockscout/blockscout/pull/8088) - Fix Rootstock charts API +- [#7992](https://github.com/blockscout/blockscout/pull/7992) - Fix missing range insert +- [#8022](https://github.com/blockscout/blockscout/pull/8022) - Don't add reorg block number to missing blocks + +### Chore + +- [#8222](https://github.com/blockscout/blockscout/pull/8222) - docker-compose for new UI with external backend +- [#8177](https://github.com/blockscout/blockscout/pull/8177) - Refactor address counter functions +- [#8183](https://github.com/blockscout/blockscout/pull/8183) - Update frontend envs in order to pass their validation +- [#8167](https://github.com/blockscout/blockscout/pull/8167) - Manage concurrency for Token and TokenBalance fetcher +- [#8179](https://github.com/blockscout/blockscout/pull/8179) - Enhance nginx config +- [#8146](https://github.com/blockscout/blockscout/pull/8146) - Add method_id to write methods in API v2 response +- [#8105](https://github.com/blockscout/blockscout/pull/8105) - Extend API v1 with endpoints used by new UI +- [#8104](https://github.com/blockscout/blockscout/pull/8104) - remove "TODO" from API v2 response +- [#8100](https://github.com/blockscout/blockscout/pull/8100), [#8103](https://github.com/blockscout/blockscout/pull/8103) - Extend docker-compose configs with new config when front is running externally +- [#8012](https://github.com/blockscout/blockscout/pull/8012) - API v2 smart-contract verification extended logging + +
+ Dependencies version bumps + +- [#7980](https://github.com/blockscout/blockscout/pull/7980) - Bump solc from 0.8.20 to 0.8.21 in /apps/explorer +- [#7986](https://github.com/blockscout/blockscout/pull/7986) - Bump sass from 1.63.6 to 1.64.0 in /apps/block_scout_web/assets +- [#8030](https://github.com/blockscout/blockscout/pull/8030) - Bump sweetalert2 from 11.7.18 to 11.7.20 in /apps/block_scout_web/assets +- [#8029](https://github.com/blockscout/blockscout/pull/8029) - Bump viewerjs from 1.11.3 to 1.11.4 in /apps/block_scout_web/assets +- [#8028](https://github.com/blockscout/blockscout/pull/8028) - Bump sass from 1.64.0 to 1.64.1 in /apps/block_scout_web/assets +- [#8026](https://github.com/blockscout/blockscout/pull/8026) - Bump dataloader from 1.0.10 to 1.0.11 +- [#8036](https://github.com/blockscout/blockscout/pull/8036) - Bump ex_cldr_numbers from 2.31.1 to 2.31.3 +- [#8027](https://github.com/blockscout/blockscout/pull/8027) - Bump absinthe from 1.7.4 to 1.7.5 +- [#8035](https://github.com/blockscout/blockscout/pull/8035) - Bump wallaby from 0.30.4 to 0.30.5 +- [#8038](https://github.com/blockscout/blockscout/pull/8038) - Bump chart.js from 4.3.0 to 4.3.1 in /apps/block_scout_web/assets +- [#8047](https://github.com/blockscout/blockscout/pull/8047) - Bump chart.js from 4.3.1 to 4.3.2 in /apps/block_scout_web/assets +- [#8000](https://github.com/blockscout/blockscout/pull/8000) - Bump postcss from 8.4.26 to 8.4.27 in /apps/block_scout_web/assets +- [#8052](https://github.com/blockscout/blockscout/pull/8052) - Bump @amplitude/analytics-browser from 2.1.2 to 2.1.3 in /apps/block_scout_web/assets +- [#8054](https://github.com/blockscout/blockscout/pull/8054) - Bump jest-environment-jsdom from 29.6.1 to 29.6.2 in /apps/block_scout_web/assets +- [#8063](https://github.com/blockscout/blockscout/pull/8063) - Bump eslint from 8.45.0 to 8.46.0 in /apps/block_scout_web/assets +- [#8066](https://github.com/blockscout/blockscout/pull/8066) - Bump ex_json_schema from 0.9.3 to 0.10.1 +- [#8064](https://github.com/blockscout/blockscout/pull/8064) - Bump core-js from 3.31.1 to 3.32.0 in /apps/block_scout_web/assets +- [#8053](https://github.com/blockscout/blockscout/pull/8053) - Bump jest from 29.6.1 to 29.6.2 in /apps/block_scout_web/assets +- [#8065](https://github.com/blockscout/blockscout/pull/8065) - Bump eslint-plugin-import from 2.27.5 to 2.28.0 in /apps/block_scout_web/assets +- [#8092](https://github.com/blockscout/blockscout/pull/8092) - Bump exvcr from 0.14.1 to 0.14.2 +- [#8091](https://github.com/blockscout/blockscout/pull/8091) - Bump sass from 1.64.1 to 1.64.2 in /apps/block_scout_web/assets +- [#8114](https://github.com/blockscout/blockscout/pull/8114) - Bump ex_doc from 0.30.3 to 0.30.4 +- [#8115](https://github.com/blockscout/blockscout/pull/8115) - Bump chart.js from 4.3.2 to 4.3.3 in /apps/block_scout_web/assets +- [#8116](https://github.com/blockscout/blockscout/pull/8116) - Bump @fortawesome/fontawesome-free from 6.4.0 to 6.4.2 in /apps/block_scout_web/assets +- [#8142](https://github.com/blockscout/blockscout/pull/8142) - Bump sobelow from 0.12.2 to 0.13.0 +- [#8141](https://github.com/blockscout/blockscout/pull/8141) - Bump @babel/core from 7.22.9 to 7.22.10 in /apps/block_scout_web/assets +- [#8140](https://github.com/blockscout/blockscout/pull/8140) - Bump @babel/preset-env from 7.22.9 to 7.22.10 in /apps/block_scout_web/assets +- [#8160](https://github.com/blockscout/blockscout/pull/8160) - Bump exvcr from 0.14.2 to 0.14.3 +- [#8159](https://github.com/blockscout/blockscout/pull/8159) - Bump luxon from 3.3.0 to 3.4.0 in /apps/block_scout_web/assets +- [#8169](https://github.com/blockscout/blockscout/pull/8169) - Bump sass from 1.64.2 to 1.65.1 in /apps/block_scout_web/assets +- [#8170](https://github.com/blockscout/blockscout/pull/8170) - Bump sweetalert2 from 11.7.20 to 11.7.22 in /apps/block_scout_web/assets +- [#8188](https://github.com/blockscout/blockscout/pull/8188) - Bump eslint from 8.46.0 to 8.47.0 in /apps/block_scout_web/assets +- [#8204](https://github.com/blockscout/blockscout/pull/8204) - Bump ex_doc from 0.30.4 to 0.30.5 +- [#8207](https://github.com/blockscout/blockscout/pull/8207) - Bump wallaby from 0.30.5 to 0.30.6 +- [#8212](https://github.com/blockscout/blockscout/pull/8212) - Bump sweetalert2 from 11.7.22 to 11.7.23 in /apps/block_scout_web/assets +- [#8203](https://github.com/blockscout/blockscout/pull/8203) - Bump autoprefixer from 10.4.14 to 10.4.15 in /apps/block_scout_web/assets +- [#8214](https://github.com/blockscout/blockscout/pull/8214) - Bump @amplitude/analytics-browser from 2.1.3 to 2.2.0 in /apps/block_scout_web/assets +- [#8225](https://github.com/blockscout/blockscout/pull/8225) - Bump postcss from 8.4.27 to 8.4.28 in /apps/block_scout_web/assets +- [#8224](https://github.com/blockscout/blockscout/pull/8224) - Bump gettext from 0.22.3 to 0.23.1 + +
+ +## 5.2.1-beta + +### Features + +- [#7970](https://github.com/blockscout/blockscout/pull/7970) - Search improvements: add sorting +- [#7771](https://github.com/blockscout/blockscout/pull/7771) - CSV export: speed up +- [#7962](https://github.com/blockscout/blockscout/pull/7962) - Allow indicate CMC id of the coin through env var +- [#7946](https://github.com/blockscout/blockscout/pull/7946) - API v2 rate limit: Put token to cookies & change /api/v2/key method +- [#7888](https://github.com/blockscout/blockscout/pull/7888) - Add token balances info to watchlist address response +- [#7898](https://github.com/blockscout/blockscout/pull/7898) - Add possibility to add extra headers with JSON RPC URL +- [#7836](https://github.com/blockscout/blockscout/pull/7836) - Improve unverified email flow +- [#7784](https://github.com/blockscout/blockscout/pull/7784) - Search improvements: Add new fields, light refactoring +- [#7811](https://github.com/blockscout/blockscout/pull/7811) - Filter addresses before insertion +- [#7895](https://github.com/blockscout/blockscout/pull/7895) - API v2: Add sorting to tokens page +- [#7859](https://github.com/blockscout/blockscout/pull/7859) - Add TokenTotalSupplyUpdater +- [#7873](https://github.com/blockscout/blockscout/pull/7873) - Chunk realtime balances requests +- [#7927](https://github.com/blockscout/blockscout/pull/7927) - Delete token balances only for blocks that lost consensus +- [#7947](https://github.com/blockscout/blockscout/pull/7947) - Improve locks acquiring + +### Fixes + +- [#8187](https://github.com/blockscout/blockscout/pull/8187) - API v1 500 error convert to 404, if requested path is incorrect +- [#7852](https://github.com/blockscout/blockscout/pull/7852) - Token balances refactoring & fixes +- [#7872](https://github.com/blockscout/blockscout/pull/7872) - Fix pending gas price in pending tx +- [#7875](https://github.com/blockscout/blockscout/pull/7875) - Fix twin compiler version +- [#7825](https://github.com/blockscout/blockscout/pull/7825) - Fix nginx config for the new frontend websockets +- [#7772](https://github.com/blockscout/blockscout/pull/7772) - Fix parsing of database password period(s) +- [#7803](https://github.com/blockscout/blockscout/pull/7803) - Fix additional sources and interfaces, save names for vyper contracts +- [#7758](https://github.com/blockscout/blockscout/pull/7758) - Remove limit for configurable fetchers +- [#7764](https://github.com/blockscout/blockscout/pull/7764) - Fix missing ranges insertion and deletion logic +- [#7843](https://github.com/blockscout/blockscout/pull/7843) - Fix created_contract_code_indexed_at updating +- [#7855](https://github.com/blockscout/blockscout/pull/7855) - Handle internal transactions unique_violation +- [#7899](https://github.com/blockscout/blockscout/pull/7899) - Fix catchup numbers_to_ranges function +- [#7951](https://github.com/blockscout/blockscout/pull/7951) - Fix TX url in email notifications on mainnet + +### Chore + +- [#7963](https://github.com/blockscout/blockscout/pull/7963) - Op Stack: ignore depositNonce +- [#7954](https://github.com/blockscout/blockscout/pull/7954) - Enhance Account Explorer.Account.Notifier.Email module tests +- [#7950](https://github.com/blockscout/blockscout/pull/7950) - Add GA CI for Eth Goerli chain +- [#7934](https://github.com/blockscout/blockscout/pull/7934), [#7936](https://github.com/blockscout/blockscout/pull/7936) - Explicitly set consensus == true in queries (convenient for search), remove logger requirements, where it is not used anymore +- [#7901](https://github.com/blockscout/blockscout/pull/7901) - Fix Docker image build +- [#7890](https://github.com/blockscout/blockscout/pull/7890), [#7918](https://github.com/blockscout/blockscout/pull/7918) - Resolve warning: Application.get_env/2 is discouraged in the module body, use Application.compile_env/3 instead +- [#7863](https://github.com/blockscout/blockscout/pull/7863) - Add max_age for account sessions +- [#7841](https://github.com/blockscout/blockscout/pull/7841) - CORS setup for docker-compose config with new frontend +- [#7832](https://github.com/blockscout/blockscout/pull/7832), [#7891](https://github.com/blockscout/blockscout/pull/7891) - API v2: Add block_number, block_hash to logs +- [#7789](https://github.com/blockscout/blockscout/pull/7789) - Fix test warnings; Fix name of `MICROSERVICE_ETH_BYTECODE_DB_INTERVAL_BETWEEN_LOOKUPS` env variable +- [#7819](https://github.com/blockscout/blockscout/pull/7819) - Add logging for unknown error verification result +- [#7781](https://github.com/blockscout/blockscout/pull/7781) - Add `/api/v1/health/liveness` and `/api/v1/health/readiness` + +
+ Dependencies version bumps + +- [#7759](https://github.com/blockscout/blockscout/pull/7759) - Bump sass from 1.63.4 to 1.63.5 in /apps/block_scout_web/assets +- [#7760](https://github.com/blockscout/blockscout/pull/7760) - Bump @amplitude/analytics-browser from 2.0.0 to 2.0.1 in /apps/block_scout_web/assets +- [#7762](https://github.com/blockscout/blockscout/pull/7762) - Bump webpack from 5.87.0 to 5.88.0 in /apps/block_scout_web/assets +- [#7769](https://github.com/blockscout/blockscout/pull/7769) - Bump sass from 1.63.5 to 1.63.6 in /apps/block_scout_web/assets +- [#7805](https://github.com/blockscout/blockscout/pull/7805) - Bump ssl_verify_fun from 1.1.6 to 1.1.7 +- [#7812](https://github.com/blockscout/blockscout/pull/7812) - Bump webpack from 5.88.0 to 5.88.1 in /apps/block_scout_web/assets +- [#7770](https://github.com/blockscout/blockscout/pull/7770) - Bump @amplitude/analytics-browser from 2.0.1 to 2.1.0 in /apps/block_scout_web/assets +- [#7821](https://github.com/blockscout/blockscout/pull/7821) - Bump absinthe from 1.7.1 to 1.7.3 +- [#7823](https://github.com/blockscout/blockscout/pull/7823) - Bump @amplitude/analytics-browser from 2.1.0 to 2.1.1 in /apps/block_scout_web/assets +- [#7838](https://github.com/blockscout/blockscout/pull/7838) - Bump gettext from 0.22.2 to 0.22.3 +- [#7840](https://github.com/blockscout/blockscout/pull/7840) - Bump eslint from 8.43.0 to 8.44.0 in /apps/block_scout_web/assets +- [#7839](https://github.com/blockscout/blockscout/pull/7839) - Bump photoswipe from 5.3.7 to 5.3.8 in /apps/block_scout_web/assets +- [#7850](https://github.com/blockscout/blockscout/pull/7850) - Bump jest-environment-jsdom from 29.5.0 to 29.6.0 in /apps/block_scout_web/assets +- [#7848](https://github.com/blockscout/blockscout/pull/7848) - Bump @amplitude/analytics-browser from 2.1.1 to 2.1.2 in /apps/block_scout_web/assets +- [#7847](https://github.com/blockscout/blockscout/pull/7847) - Bump @babel/core from 7.22.5 to 7.22.6 in /apps/block_scout_web/assets +- [#7846](https://github.com/blockscout/blockscout/pull/7846) - Bump @babel/preset-env from 7.22.5 to 7.22.6 in /apps/block_scout_web/assets +- [#7856](https://github.com/blockscout/blockscout/pull/7856) - Bump ex_cldr from 2.37.1 to 2.37.2 +- [#7870](https://github.com/blockscout/blockscout/pull/7870) - Bump jest from 29.5.0 to 29.6.1 in /apps/block_scout_web/assets +- [#7867](https://github.com/blockscout/blockscout/pull/7867) - Bump postcss from 8.4.24 to 8.4.25 in /apps/block_scout_web/assets +- [#7871](https://github.com/blockscout/blockscout/pull/7871) - Bump @babel/core from 7.22.6 to 7.22.8 in /apps/block_scout_web/assets +- [#7868](https://github.com/blockscout/blockscout/pull/7868) - Bump jest-environment-jsdom from 29.6.0 to 29.6.1 in /apps/block_scout_web/assets +- [#7866](https://github.com/blockscout/blockscout/pull/7866) - Bump @babel/preset-env from 7.22.6 to 7.22.7 in /apps/block_scout_web/assets +- [#7869](https://github.com/blockscout/blockscout/pull/7869) - Bump core-js from 3.31.0 to 3.31.1 in /apps/block_scout_web/assets +- [#7884](https://github.com/blockscout/blockscout/pull/7884) - Bump ecto from 3.10.2 to 3.10.3 +- [#7882](https://github.com/blockscout/blockscout/pull/7882) - Bump jason from 1.4.0 to 1.4.1 +- [#7880](https://github.com/blockscout/blockscout/pull/7880) - Bump absinthe from 1.7.3 to 1.7.4 +- [#7879](https://github.com/blockscout/blockscout/pull/7879) - Bump babel-loader from 9.1.2 to 9.1.3 in /apps/block_scout_web/assets +- [#7881](https://github.com/blockscout/blockscout/pull/7881) - Bump ex_cldr_numbers from 2.31.1 to 2.31.2 +- [#7883](https://github.com/blockscout/blockscout/pull/7883) - Bump ex_doc from 0.29.4 to 0.30.1 +- [#7916](https://github.com/blockscout/blockscout/pull/7916) - Bump semver from 5.7.1 to 5.7.2 in /apps/explorer +- [#7912](https://github.com/blockscout/blockscout/pull/7912) - Bump sweetalert2 from 11.7.12 to 11.7.16 in /apps/block_scout_web/assets +- [#7913](https://github.com/blockscout/blockscout/pull/7913) - Bump ex_doc from 0.30.1 to 0.30.2 +- [#7923](https://github.com/blockscout/blockscout/pull/7923) - Bump postgrex from 0.17.1 to 0.17.2 +- [#7921](https://github.com/blockscout/blockscout/pull/7921) - Bump @babel/preset-env from 7.22.7 to 7.22.9 in /apps/block_scout_web/assets +- [#7922](https://github.com/blockscout/blockscout/pull/7922) - Bump @babel/core from 7.22.8 to 7.22.9 in /apps/block_scout_web/assets +- [#7931](https://github.com/blockscout/blockscout/pull/7931) - Bump wallaby from 0.30.3 to 0.30.4 +- [#7940](https://github.com/blockscout/blockscout/pull/7940) - Bump postcss from 8.4.25 to 8.4.26 in /apps/block_scout_web/assets +- [#7939](https://github.com/blockscout/blockscout/pull/7939) - Bump eslint from 8.44.0 to 8.45.0 in /apps/block_scout_web/assets +- [#7955](https://github.com/blockscout/blockscout/pull/7955) - Bump sweetalert2 from 11.7.16 to 11.7.18 in /apps/block_scout_web/assets +- [#7958](https://github.com/blockscout/blockscout/pull/7958) - Bump ex_doc from 0.30.2 to 0.30.3 +- [#7965](https://github.com/blockscout/blockscout/pull/7965) - Bump webpack from 5.88.1 to 5.88.2 in /apps/block_scout_web/assets +- [#7972](https://github.com/blockscout/blockscout/pull/7972) - Bump word-wrap from 1.2.3 to 1.2.4 in /apps/block_scout_web/assets + +
+ +## 5.2.0-beta + +### Features + +- [#7502](https://github.com/blockscout/blockscout/pull/7502) - Improve performance of some methods, endpoints and SQL queries +- [#7665](https://github.com/blockscout/blockscout/pull/7665) - Add standard-json vyper verification +- [#7685](https://github.com/blockscout/blockscout/pull/7685) - Add yul filter and "language" field for smart contracts +- [#7653](https://github.com/blockscout/blockscout/pull/7653) - Add support for DEPOSIT and WITHDRAW token transfer event in older contracts +- [#7628](https://github.com/blockscout/blockscout/pull/7628) - Support partially verified property from verifier MS; Add property to track contracts automatically verified via eth-bytecode-db +- [#7603](https://github.com/blockscout/blockscout/pull/7603) - Add Polygon Edge and optimism genesis files support +- [#7585](https://github.com/blockscout/blockscout/pull/7585) - Store and display native coin market cap from the DB +- [#7513](https://github.com/blockscout/blockscout/pull/7513) - Add Polygon Edge support +- [#7532](https://github.com/blockscout/blockscout/pull/7532) - Handle empty id in json rpc responses +- [#7544](https://github.com/blockscout/blockscout/pull/7544) - Add ERC-1155 signatures to uncataloged_token_transfer_block_numbers +- [#7363](https://github.com/blockscout/blockscout/pull/7363) - CSV export filters +- [#7697](https://github.com/blockscout/blockscout/pull/7697) - Limit fetchers init tasks + +### Fixes + +- [#7712](https://github.com/blockscout/blockscout/pull/7712) - Transaction actions import fix +- [#7709](https://github.com/blockscout/blockscout/pull/7709) - Contract args displaying bug +- [#7654](https://github.com/blockscout/blockscout/pull/7654) - Optimize exchange rates requests rate +- [#7636](https://github.com/blockscout/blockscout/pull/7636) - Remove receive from read methods +- [#7635](https://github.com/blockscout/blockscout/pull/7635) - Fix single 1155 transfer displaying +- [#7629](https://github.com/blockscout/blockscout/pull/7629) - Fix NFT fetcher +- [#7614](https://github.com/blockscout/blockscout/pull/7614) - API and smart-contracts fixes and improvements +- [#7611](https://github.com/blockscout/blockscout/pull/7611) - Fix tokens pagination +- [#7566](https://github.com/blockscout/blockscout/pull/7566) - Account: check composed email before sending +- [#7564](https://github.com/blockscout/blockscout/pull/7564) - Return contract type in address view +- [#7562](https://github.com/blockscout/blockscout/pull/7562) - Remove fallback from Read methods +- [#7537](https://github.com/blockscout/blockscout/pull/7537), [#7553](https://github.com/blockscout/blockscout/pull/7553) - Withdrawals fixes and improvements +- [#7546](https://github.com/blockscout/blockscout/pull/7546) - API v2: fix today coin price (use in-memory or cached in DB value) +- [#7545](https://github.com/blockscout/blockscout/pull/7545) - API v2: Check if cached exchange rate is empty before replacing DB value in stats API +- [#7516](https://github.com/blockscout/blockscout/pull/7516) - Fix shrinking logo in Safari +- [#7590](https://github.com/blockscout/blockscout/pull/7590) - Drop genesis block in internal transactions fetcher +- [#7639](https://github.com/blockscout/blockscout/pull/7639) - Fix contract creation transactions +- [#7724](https://github.com/blockscout/blockscout/pull/7724), [#7753](https://github.com/blockscout/blockscout/pull/7753) - Move MissingRangesCollector init logic to handle_continue +- [#7751](https://github.com/blockscout/blockscout/pull/7751) - Add missing method_to_url params for trace transactions + +### Chore + +- [#7699](https://github.com/blockscout/blockscout/pull/7699) - Add block_number index for address_coin_balances table +- [#7666](https://github.com/blockscout/blockscout/pull/7666), [#7740](https://github.com/blockscout/blockscout/pull/7740), [#7741](https://github.com/blockscout/blockscout/pull/7741) - Search label query +- [#7644](https://github.com/blockscout/blockscout/pull/7644) - Publish docker images CI for prod/staging branches +- [#7594](https://github.com/blockscout/blockscout/pull/7594) - Stats service support in docker-compose config with new frontend +- [#7576](https://github.com/blockscout/blockscout/pull/7576) - Check left blocks in pending block operations in order to decide, if we need to display indexing int tx banner at the top +- [#7543](https://github.com/blockscout/blockscout/pull/7543) - Allow hyphen in DB username + +
+ Dependencies version bumps + +- [#7518](https://github.com/blockscout/blockscout/pull/7518) - Bump mini-css-extract-plugin from 2.7.5 to 2.7.6 in /apps/block_scout_web/assets +- [#7519](https://github.com/blockscout/blockscout/pull/7519) - Bump style-loader from 3.3.2 to 3.3.3 in /apps/block_scout_web/assets +- [#7505](https://github.com/blockscout/blockscout/pull/7505) - Bump webpack from 5.83.0 to 5.83.1 in /apps/block_scout_web/assets +- [#7533](https://github.com/blockscout/blockscout/pull/7533) - Bump sass-loader from 13.2.2 to 13.3.0 in /apps/block_scout_web/assets +- [#7534](https://github.com/blockscout/blockscout/pull/7534) - Bump eslint from 8.40.0 to 8.41.0 in /apps/block_scout_web/assets +- [#7541](https://github.com/blockscout/blockscout/pull/7541) - Bump cldr_utils from 2.23.1 to 2.24.0 +- [#7542](https://github.com/blockscout/blockscout/pull/7542) - Bump ex_cldr_units from 3.16.0 to 3.16.1 +- [#7548](https://github.com/blockscout/blockscout/pull/7548) - Bump briefly from 20d1318 to 678a376 +- [#7547](https://github.com/blockscout/blockscout/pull/7547) - Bump webpack from 5.83.1 to 5.84.0 in /apps/block_scout_web/assets +- [#7554](https://github.com/blockscout/blockscout/pull/7554) - Bump webpack from 5.84.0 to 5.84.1 in /apps/block_scout_web/assets +- [#7568](https://github.com/blockscout/blockscout/pull/7568) - Bump @babel/core from 7.21.8 to 7.22.1 in /apps/block_scout_web/assets +- [#7569](https://github.com/blockscout/blockscout/pull/7569) - Bump postcss-loader from 7.3.0 to 7.3.1 in /apps/block_scout_web/assets +- [#7570](https://github.com/blockscout/blockscout/pull/7570) - Bump number from 1.0.3 to 1.0.4 +- [#7567](https://github.com/blockscout/blockscout/pull/7567) - Bump @babel/preset-env from 7.21.5 to 7.22.2 in /apps/block_scout_web/assets +- [#7582](https://github.com/blockscout/blockscout/pull/7582) - Bump eslint-config-standard from 17.0.0 to 17.1.0 in /apps/block_scout_web/assets +- [#7581](https://github.com/blockscout/blockscout/pull/7581) - Bump sass-loader from 13.3.0 to 13.3.1 in /apps/block_scout_web/assets +- [#7578](https://github.com/blockscout/blockscout/pull/7578) - Bump @babel/preset-env from 7.22.2 to 7.22.4 in /apps/block_scout_web/assets +- [#7577](https://github.com/blockscout/blockscout/pull/7577) - Bump postcss-loader from 7.3.1 to 7.3.2 in /apps/block_scout_web/assets +- [#7579](https://github.com/blockscout/blockscout/pull/7579) - Bump sweetalert2 from 11.7.5 to 11.7.8 in /apps/block_scout_web/assets +- [#7591](https://github.com/blockscout/blockscout/pull/7591) - Bump sweetalert2 from 11.7.8 to 11.7.9 in /apps/block_scout_web/assets +- [#7593](https://github.com/blockscout/blockscout/pull/7593) - Bump ex_json_schema from 0.9.2 to 0.9.3 +- [#7580](https://github.com/blockscout/blockscout/pull/7580) - Bump postcss from 8.4.23 to 8.4.24 in /apps/block_scout_web/assets +- [#7601](https://github.com/blockscout/blockscout/pull/7601) - Bump sweetalert2 from 11.7.9 to 11.7.10 in /apps/block_scout_web/assets +- [#7602](https://github.com/blockscout/blockscout/pull/7602) - Bump mime from 2.0.3 to 2.0.4 +- [#7618](https://github.com/blockscout/blockscout/pull/7618) - Bump gettext from 0.22.1 to 0.22.2 +- [#7617](https://github.com/blockscout/blockscout/pull/7617) - Bump @amplitude/analytics-browser from 1.10.3 to 1.10.4 in /apps/block_scout_web/assets +- [#7609](https://github.com/blockscout/blockscout/pull/7609) - Bump webpack from 5.84.1 to 5.85.0 in /apps/block_scout_web/assets +- [#7610](https://github.com/blockscout/blockscout/pull/7610) - Bump mime from 2.0.4 to 2.0.5 +- [#7634](https://github.com/blockscout/blockscout/pull/7634) - Bump eslint from 8.41.0 to 8.42.0 in /apps/block_scout_web/assets +- [#7633](https://github.com/blockscout/blockscout/pull/7633) - Bump floki from 0.34.2 to 0.34.3 +- [#7631](https://github.com/blockscout/blockscout/pull/7631) - Bump phoenix_ecto from 4.4.1 to 4.4.2 +- [#7630](https://github.com/blockscout/blockscout/pull/7630) - Bump webpack-cli from 5.1.1 to 5.1.3 in /apps/block_scout_web/assets +- [#7632](https://github.com/blockscout/blockscout/pull/7632) - Bump webpack from 5.85.0 to 5.85.1 in /apps/block_scout_web/assets +- [#7646](https://github.com/blockscout/blockscout/pull/7646) - Bump sweetalert2 from 11.7.10 to 11.7.11 in /apps/block_scout_web/assets +- [#7647](https://github.com/blockscout/blockscout/pull/7647) - Bump @amplitude/analytics-browser from 1.10.4 to 1.10.6 in /apps/block_scout_web/assets +- [#7659](https://github.com/blockscout/blockscout/pull/7659) - Bump webpack-cli from 5.1.3 to 5.1.4 in /apps/block_scout_web/assets +- [#7658](https://github.com/blockscout/blockscout/pull/7658) - Bump @amplitude/analytics-browser from 1.10.6 to 1.10.7 in /apps/block_scout_web/assets +- [#7657](https://github.com/blockscout/blockscout/pull/7657) - Bump webpack from 5.85.1 to 5.86.0 in /apps/block_scout_web/assets +- [#7672](https://github.com/blockscout/blockscout/pull/7672) - Bump @babel/preset-env from 7.22.4 to 7.22.5 in /apps/block_scout_web/assets +- [#7674](https://github.com/blockscout/blockscout/pull/7674) - Bump ecto from 3.10.1 to 3.10.2 +- [#7673](https://github.com/blockscout/blockscout/pull/7673) - Bump @babel/core from 7.22.1 to 7.22.5 in /apps/block_scout_web/assets +- [#7671](https://github.com/blockscout/blockscout/pull/7671) - Bump sass from 1.62.1 to 1.63.2 in /apps/block_scout_web/assets +- [#7681](https://github.com/blockscout/blockscout/pull/7681) - Bump sweetalert2 from 11.7.11 to 11.7.12 in /apps/block_scout_web/assets +- [#7679](https://github.com/blockscout/blockscout/pull/7679) - Bump @amplitude/analytics-browser from 1.10.7 to 1.10.8 in /apps/block_scout_web/assets +- [#7680](https://github.com/blockscout/blockscout/pull/7680) - Bump sass from 1.63.2 to 1.63.3 in /apps/block_scout_web/assets +- [#7693](https://github.com/blockscout/blockscout/pull/7693) - Bump sass-loader from 13.3.1 to 13.3.2 in /apps/block_scout_web/assets +- [#7692](https://github.com/blockscout/blockscout/pull/7692) - Bump postcss-loader from 7.3.2 to 7.3.3 in /apps/block_scout_web/assets +- [#7691](https://github.com/blockscout/blockscout/pull/7691) - Bump url from 0.11.0 to 0.11.1 in /apps/block_scout_web/assets +- [#7690](https://github.com/blockscout/blockscout/pull/7690) - Bump core-js from 3.30.2 to 3.31.0 in /apps/block_scout_web/assets +- [#7701](https://github.com/blockscout/blockscout/pull/7701) - Bump css-minimizer-webpack-plugin from 5.0.0 to 5.0.1 in /apps/block_scout_web/assets +- [#7702](https://github.com/blockscout/blockscout/pull/7702) - Bump @amplitude/analytics-browser from 1.10.8 to 1.11.0 in /apps/block_scout_web/assets +- [#7708](https://github.com/blockscout/blockscout/pull/7708) - Bump phoenix_pubsub from 2.1.2 to 2.1.3 +- [#7707](https://github.com/blockscout/blockscout/pull/7707) - Bump @amplitude/analytics-browser from 1.11.0 to 2.0.0 in /apps/block_scout_web/assets +- [#7706](https://github.com/blockscout/blockscout/pull/7706) - Bump webpack from 5.86.0 to 5.87.0 in /apps/block_scout_web/assets +- [#7705](https://github.com/blockscout/blockscout/pull/7705) - Bump sass from 1.63.3 to 1.63.4 in /apps/block_scout_web/assets +- [#7714](https://github.com/blockscout/blockscout/pull/7714) - Bump ex_cldr_units from 3.16.1 to 3.16.2 +- [#7748](https://github.com/blockscout/blockscout/pull/7748) - Bump mock from 0.3.7 to 0.3.8 +- [#7746](https://github.com/blockscout/blockscout/pull/7746) - Bump eslint from 8.42.0 to 8.43.0 in /apps/block_scout_web/assets +- [#7747](https://github.com/blockscout/blockscout/pull/7747) - Bump cldr_utils from 2.24.0 to 2.24.1 + +
+ +## 5.1.5-beta + +### Features + +- [#7439](https://github.com/blockscout/blockscout/pull/7439) - Define batch size for token balance fetcher via runtime env var +- [#7298](https://github.com/blockscout/blockscout/pull/7298) - Add changes to support force email verification +- [#7422](https://github.com/blockscout/blockscout/pull/7422) - Refactor state changes +- [#7416](https://github.com/blockscout/blockscout/pull/7416) - Add option to disable reCAPTCHA +- [#6694](https://github.com/blockscout/blockscout/pull/6694) - Add withdrawals support (EIP-4895) +- [#7355](https://github.com/blockscout/blockscout/pull/7355) - Add endpoint for token info import +- [#7393](https://github.com/blockscout/blockscout/pull/7393) - Realtime fetcher max gap +- [#7436](https://github.com/blockscout/blockscout/pull/7436) - TokenBalanceOnDemand ERC-1155 support +- [#7469](https://github.com/blockscout/blockscout/pull/7469), [#7485](https://github.com/blockscout/blockscout/pull/7485), [#7493](https://github.com/blockscout/blockscout/pull/7493) - Clear missing block ranges after every success import +- [#7489](https://github.com/blockscout/blockscout/pull/7489) - INDEXER_CATCHUP_BLOCK_INTERVAL env var + +### Fixes + +- [#7490](https://github.com/blockscout/blockscout/pull/7490) - Fix pending txs is not a map +- [#7474](https://github.com/blockscout/blockscout/pull/7474) - Websocket v2 improvements +- [#7472](https://github.com/blockscout/blockscout/pull/7472) - Fix RE_CAPTCHA_DISABLED variable parsing +- [#7391](https://github.com/blockscout/blockscout/pull/7391) - Fix: cannot read properties of null (reading 'value') +- [#7377](https://github.com/blockscout/blockscout/pull/7377), [#7454](https://github.com/blockscout/blockscout/pull/7454) - API v2 improvements + +### Chore + +- [#7496](https://github.com/blockscout/blockscout/pull/7496) - API v2: Pass backend version to the frontend +- [#7468](https://github.com/blockscout/blockscout/pull/7468) - Refactoring queries with blocks +- [#7435](https://github.com/blockscout/blockscout/pull/7435) - Add `.exs` and `.eex` checking in cspell +- [#7450](https://github.com/blockscout/blockscout/pull/7450) - Resolve unresponsive navbar in verification form page +- [#7449](https://github.com/blockscout/blockscout/pull/7449) - Actualize docker-compose readme and use latest tags instead main +- [#7417](https://github.com/blockscout/blockscout/pull/7417) - Docker compose for frontend +- [#7349](https://github.com/blockscout/blockscout/pull/7349) - Proxy pattern with getImplementation() +- [#7360](https://github.com/blockscout/blockscout/pull/7360) - Manage visibility of indexing progress alert + +
+ Dependencies version bumps + +- [#7351](https://github.com/blockscout/blockscout/pull/7351) - Bump decimal from 2.0.0 to 2.1.1 +- [#7356](https://github.com/blockscout/blockscout/pull/7356) - Bump @amplitude/analytics-browser from 1.10.0 to 1.10.1 in /apps/block_scout_web/assets +- [#7366](https://github.com/blockscout/blockscout/pull/7366) - Bump mixpanel-browser from 2.46.0 to 2.47.0 in /apps/block_scout_web/assets +- [#7365](https://github.com/blockscout/blockscout/pull/7365) - Bump @amplitude/analytics-browser from 1.10.1 to 1.10.2 in /apps/block_scout_web/assets +- [#7368](https://github.com/blockscout/blockscout/pull/7368) - Bump cowboy from 2.9.0 to 2.10.0 +- [#7370](https://github.com/blockscout/blockscout/pull/7370) - Bump ex_cldr_units from 3.15.0 to 3.16.0 +- [#7364](https://github.com/blockscout/blockscout/pull/7364) - Bump chart.js from 4.2.1 to 4.3.0 in /apps/block_scout_web/assets +- [#7382](https://github.com/blockscout/blockscout/pull/7382) - Bump @babel/preset-env from 7.21.4 to 7.21.5 in /apps/block_scout_web/assets +- [#7381](https://github.com/blockscout/blockscout/pull/7381) - Bump highlight.js from 11.7.0 to 11.8.0 in /apps/block_scout_web/assets +- [#7379](https://github.com/blockscout/blockscout/pull/7379) - Bump @babel/core from 7.21.4 to 7.21.5 in /apps/block_scout_web/assets +- [#7380](https://github.com/blockscout/blockscout/pull/7380) - Bump postcss-loader from 7.2.4 to 7.3.0 in /apps/block_scout_web/assets +- [#7395](https://github.com/blockscout/blockscout/pull/7395) - Bump @babel/core from 7.21.5 to 7.21.8 in /apps/block_scout_web/assets +- [#7402](https://github.com/blockscout/blockscout/pull/7402) - Bump webpack from 5.81.0 to 5.82.0 in /apps/block_scout_web/assets +- [#7411](https://github.com/blockscout/blockscout/pull/7411) - Bump cldr_utils from 2.22.0 to 2.23.1 +- [#7409](https://github.com/blockscout/blockscout/pull/7409) - Bump @amplitude/analytics-browser from 1.10.2 to 1.10.3 in /apps/block_scout_web/assets +- [#7410](https://github.com/blockscout/blockscout/pull/7410) - Bump sweetalert2 from 11.7.3 to 11.7.5 in /apps/block_scout_web/assets +- [#7434](https://github.com/blockscout/blockscout/pull/7434) - Bump ex_cldr from 2.37.0 to 2.37.1 +- [#7433](https://github.com/blockscout/blockscout/pull/7433) - Bump eslint from 8.39.0 to 8.40.0 in /apps/block_scout_web/assets +- [#7432](https://github.com/blockscout/blockscout/pull/7432) - Bump tesla from 1.6.0 to 1.6.1 +- [#7431](https://github.com/blockscout/blockscout/pull/7431) - Bump webpack-cli from 5.0.2 to 5.1.0 in /apps/block_scout_web/assets +- [#7430](https://github.com/blockscout/blockscout/pull/7430) - Bump core-js from 3.30.1 to 3.30.2 in /apps/block_scout_web/assets +- [#7443](https://github.com/blockscout/blockscout/pull/7443) - Bump webpack-cli from 5.1.0 to 5.1.1 in /apps/block_scout_web/assets +- [#7457](https://github.com/blockscout/blockscout/pull/7457) - Bump web3 from 1.9.0 to 1.10.0 in /apps/block_scout_web/assets +- [#7456](https://github.com/blockscout/blockscout/pull/7456) - Bump webpack from 5.82.0 to 5.82.1 in /apps/block_scout_web/assets +- [#7458](https://github.com/blockscout/blockscout/pull/7458) - Bump phoenix_ecto from 4.4.0 to 4.4.1 +- [#7455](https://github.com/blockscout/blockscout/pull/7455) - Bump solc from 0.8.19 to 0.8.20 in /apps/explorer +- [#7460](https://github.com/blockscout/blockscout/pull/7460) - Bump jquery from 3.6.4 to 3.7.0 in /apps/block_scout_web/assets +- [#7488](https://github.com/blockscout/blockscout/pull/7488) - Bump exvcr from 0.13.5 to 0.14.1 +- [#7486](https://github.com/blockscout/blockscout/pull/7486) - Bump redix from 1.2.2 to 1.2.3 +- [#7487](https://github.com/blockscout/blockscout/pull/7487) - Bump tesla from 1.6.1 to 1.7.0 +- [#7494](https://github.com/blockscout/blockscout/pull/7494) - Bump webpack from 5.82.1 to 5.83.0 in /apps/block_scout_web/assets +- [#7495](https://github.com/blockscout/blockscout/pull/7495) - Bump ex_cldr_numbers from 2.31.0 to 2.31.1 + +
+ +## 5.1.4-beta + +### Features + +- [#7273](https://github.com/blockscout/blockscout/pull/7273) - Support reCAPTCHA v3 in CSV export page +- [#7345](https://github.com/blockscout/blockscout/pull/7345) - Manage telegram link and its visibility in the footer +- [#7313](https://github.com/blockscout/blockscout/pull/7313) - API v2 new endpoints: watchlist transactions +- [#7286](https://github.com/blockscout/blockscout/pull/7286) - Split token instance fetcher +- [#7246](https://github.com/blockscout/blockscout/pull/7246) - Fallback JSON RPC option +- [#7329](https://github.com/blockscout/blockscout/pull/7329) - Delete pending block operations for empty blocks + +### Fixes + +- [#7317](https://github.com/blockscout/blockscout/pull/7317) - Fix tokensupply API v1 endpoint: handle nil total_supply +- [#7290](https://github.com/blockscout/blockscout/pull/7290) - Allow nil gas price for pending tx (Erigon node case) +- [#7288](https://github.com/blockscout/blockscout/pull/7288) - API v2 improvements: Fix tx type for pending contract creation; Remove owner for not unique ERC-1155 token instances +- [#7283](https://github.com/blockscout/blockscout/pull/7283) - Fix status for dropped/replaced tx +- [#7270](https://github.com/blockscout/blockscout/pull/7270) - Fix default `TOKEN_EXCHANGE_RATE_REFETCH_INTERVAL` +- [#7276](https://github.com/blockscout/blockscout/pull/7276) - Convert 99+% of int txs indexing into 100% in order to hide top indexing banner +- [#7282](https://github.com/blockscout/blockscout/pull/7282) - Add not found transaction error case +- [#7305](https://github.com/blockscout/blockscout/pull/7305) - Reset MissingRangesCollector min_fetched_block_number + +### Chore + +- [#7343](https://github.com/blockscout/blockscout/pull/7343) - Management flexibility of charts dashboard on the main page +- [#7337](https://github.com/blockscout/blockscout/pull/7337) - Account: derive Auth0 logout urls from existing envs +- [#7332](https://github.com/blockscout/blockscout/pull/7332) - Add volume for Postgres Docker containers DB +- [#7328](https://github.com/blockscout/blockscout/pull/7328) - Update Docker image tag latest with release only +- [#7312](https://github.com/blockscout/blockscout/pull/7312) - Add configs for Uniswap v3 transaction actions to index them on Base Goerli +- [#7310](https://github.com/blockscout/blockscout/pull/7310) - Reducing resource consumption on bs-indexer-eth-goerli environment +- [#7297](https://github.com/blockscout/blockscout/pull/7297) - Use tracing JSONRPC URL in case of debug_traceTransaction method +- [#7292](https://github.com/blockscout/blockscout/pull/7292) - Allow Node 16+ version + +
+ Dependencies version bumps + +- [#7257](https://github.com/blockscout/blockscout/pull/7257) - Bump ecto_sql from 3.10.0 to 3.10.1 +- [#7265](https://github.com/blockscout/blockscout/pull/7265) - Bump ecto from 3.10.0 to 3.10.1 +- [#7263](https://github.com/blockscout/blockscout/pull/7263) - Bump sass from 1.61.0 to 1.62.0 in /apps/block_scout_web/assets +- [#7264](https://github.com/blockscout/blockscout/pull/7264) - Bump webpack from 5.78.0 to 5.79.0 in /apps/block_scout_web/assets +- [#7274](https://github.com/blockscout/blockscout/pull/7274) - Bump postgrex from 0.17.0 to 0.17.1 +- [#7277](https://github.com/blockscout/blockscout/pull/7277) - Bump core-js from 3.30.0 to 3.30.1 in /apps/block_scout_web/assets +- [#7295](https://github.com/blockscout/blockscout/pull/7295) - Bump postcss from 8.4.21 to 8.4.22 in /apps/block_scout_web/assets +- [#7303](https://github.com/blockscout/blockscout/pull/7303) - Bump redix from 1.2.1 to 1.2.2 +- [#7302](https://github.com/blockscout/blockscout/pull/7302) - Bump webpack from 5.79.0 to 5.80.0 in /apps/block_scout_web/assets +- [#7307](https://github.com/blockscout/blockscout/pull/7307) - Bump postcss from 8.4.22 to 8.4.23 in /apps/block_scout_web/assets +- [#7321](https://github.com/blockscout/blockscout/pull/7321) - Bump webpack-cli from 5.0.1 to 5.0.2 in /apps/block_scout_web/assets +- [#7320](https://github.com/blockscout/blockscout/pull/7320) - Bump js-cookie from 3.0.1 to 3.0.4 in /apps/block_scout_web/assets +- [#7333](https://github.com/blockscout/blockscout/pull/7333) - Bump js-cookie from 3.0.4 to 3.0.5 in /apps/block_scout_web/assets +- [#7334](https://github.com/blockscout/blockscout/pull/7334) - Bump eslint from 8.38.0 to 8.39.0 in /apps/block_scout_web/assets +- [#7344](https://github.com/blockscout/blockscout/pull/7344) - Bump @amplitude/analytics-browser from 1.9.4 to 1.10.0 in /apps/block_scout_web/assets +- [#7347](https://github.com/blockscout/blockscout/pull/7347) - Bump webpack from 5.80.0 to 5.81.0 in /apps/block_scout_web/assets +- [#7348](https://github.com/blockscout/blockscout/pull/7348) - Bump sass from 1.62.0 to 1.62.1 in /apps/block_scout_web/assets + +
+ +## 5.1.3-beta + +### Features + +- [#7253](https://github.com/blockscout/blockscout/pull/7253) - Add `EIP_1559_ELASTICITY_MULTIPLIER` env variable +- [#7187](https://github.com/blockscout/blockscout/pull/7187) - Integrate [Eth Bytecode DB](https://github.com/blockscout/blockscout-rs/tree/main/eth-bytecode-db/eth-bytecode-db) +- [#7185](https://github.com/blockscout/blockscout/pull/7185) - Aave v3 transaction actions indexer +- [#7148](https://github.com/blockscout/blockscout/pull/7148), [#7244](https://github.com/blockscout/blockscout/pull/7244) - API v2 improvements: API rate limiting, `/tokens/{address_hash}/instances/{token_id}/holders` and other changes + +### Fixes + +- [#7242](https://github.com/blockscout/blockscout/pull/7242) - Fix daily txs chart +- [#7210](https://github.com/blockscout/blockscout/pull/7210) - Fix Makefile docker image build +- [#7203](https://github.com/blockscout/blockscout/pull/7203) - Fix write contract functionality for multidimensional arrays case +- [#7186](https://github.com/blockscout/blockscout/pull/7186) - Fix build from Dockerfile +- [#7255](https://github.com/blockscout/blockscout/pull/7255) - Fix MissingRangesCollector max block number fetching + +### Chore + +- [#7254](https://github.com/blockscout/blockscout/pull/7254) - Rename env vars related for the integration with microservices +- [#7107](https://github.com/blockscout/blockscout/pull/7107) - Tx actions: remove excess delete_all calls and remake a cache +- [#7201](https://github.com/blockscout/blockscout/pull/7201) - Remove rust, cargo from dependencies since the latest version of ex_keccak is using precompiled rust + +
+ Dependencies version bumps + +- [#7183](https://github.com/blockscout/blockscout/pull/7183) - Bump sobelow from 0.11.1 to 0.12.1 +- [#7188](https://github.com/blockscout/blockscout/pull/7188) - Bump @babel/preset-env from 7.20.2 to 7.21.4 in /apps/block_scout_web/assets +- [#7190](https://github.com/blockscout/blockscout/pull/7190) - Bump @amplitude/analytics-browser from 1.9.1 to 1.9.2 in /apps/block_scout_web/assets +- [#7189](https://github.com/blockscout/blockscout/pull/7189) - Bump @babel/core from 7.21.3 to 7.21.4 in /apps/block_scout_web/assets +- [#7206](https://github.com/blockscout/blockscout/pull/7206) - Bump tesla from 1.5.1 to 1.6.0 +- [#7207](https://github.com/blockscout/blockscout/pull/7207) - Bump sobelow from 0.12.1 to 0.12.2 +- [#7205](https://github.com/blockscout/blockscout/pull/7205) - Bump @amplitude/analytics-browser from 1.9.2 to 1.9.3 in /apps/block_scout_web/assets +- [#7204](https://github.com/blockscout/blockscout/pull/7204) - Bump postcss-loader from 7.1.0 to 7.2.1 in /apps/block_scout_web/assets +- [#7214](https://github.com/blockscout/blockscout/pull/7214) - Bump core-js from 3.29.1 to 3.30.0 in /apps/block_scout_web/assets +- [#7215](https://github.com/blockscout/blockscout/pull/7215) - Bump postcss-loader from 7.2.1 to 7.2.4 in /apps/block_scout_web/assets +- [#7220](https://github.com/blockscout/blockscout/pull/7220) - Bump wallaby from 0.30.2 to 0.30.3 +- [#7236](https://github.com/blockscout/blockscout/pull/7236) - Bump sass from 1.60.0 to 1.61.0 in /apps/block_scout_web/assets +- [#7235](https://github.com/blockscout/blockscout/pull/7235) - Bump @amplitude/analytics-browser from 1.9.3 to 1.9.4 in /apps/block_scout_web/assets +- [#7224](https://github.com/blockscout/blockscout/pull/7224) - Bump webpack from 5.77.0 to 5.78.0 in /apps/block_scout_web/assets +- [#7245](https://github.com/blockscout/blockscout/pull/7245) - Bump eslint from 8.37.0 to 8.38.0 in /apps/block_scout_web/assets +- [#7250](https://github.com/blockscout/blockscout/pull/7250) - Bump dialyxir from 1.2.0 to 1.3.0 + +
+ +## 5.1.2-beta + +### Features + +- [#6925](https://github.com/blockscout/blockscout/pull/6925) - Rework token price fetching mechanism and sort token balances by fiat value +- [#7068](https://github.com/blockscout/blockscout/pull/7068) - Add authenticate endpoint +- [#6990](https://github.com/blockscout/blockscout/pull/6990) - Improved http requests logging, batch transfers pagination; New API v2 endpoint `/smart-contracts/counters`; And some refactoring +- [#7089](https://github.com/blockscout/blockscout/pull/7089) - ETHEREUM_JSONRPC_HTTP_TIMEOUT env variable + +### Fixes + +- [#7243](https://github.com/blockscout/blockscout/pull/7243) - Fix Elixir tracer to work with polygon edge +- [#7162](https://github.com/blockscout/blockscout/pull/7162) - Hide indexing alert, if internal transactions indexer disabled +- [#7096](https://github.com/blockscout/blockscout/pull/7096) - Hide indexing alert, if indexer disabled +- [#7102](https://github.com/blockscout/blockscout/pull/7102) - Set infinity timeout timestamp_to_block_number query +- [#7091](https://github.com/blockscout/blockscout/pull/7091) - Fix custom ABI +- [#7087](https://github.com/blockscout/blockscout/pull/7087) - Allow URI special symbols in `DATABASE_URL` +- [#7062](https://github.com/blockscout/blockscout/pull/7062) - Save block count in the DB when calculated in Cache module +- [#7008](https://github.com/blockscout/blockscout/pull/7008) - Fetch image/video content from IPFS link +- [#7007](https://github.com/blockscout/blockscout/pull/7007), [#7031](https://github.com/blockscout/blockscout/pull/7031), [#7058](https://github.com/blockscout/blockscout/pull/7058), [#7061](https://github.com/blockscout/blockscout/pull/7061), [#7067](https://github.com/blockscout/blockscout/pull/7067) - Token instance fetcher fixes +- [#7009](https://github.com/blockscout/blockscout/pull/7009) - Fix updating coin balances with empty value +- [#7055](https://github.com/blockscout/blockscout/pull/7055) - Set updated_at on token update even if there are no changes +- [#7080](https://github.com/blockscout/blockscout/pull/7080) - Deduplicate second degree relations before insert +- [#7161](https://github.com/blockscout/blockscout/pull/7161) - Treat "" as empty value while parsing env vars +- [#7135](https://github.com/blockscout/blockscout/pull/7135) - Block reorg fixes + +### Chore + +- [#7147](https://github.com/blockscout/blockscout/pull/7147) - Add missing GAS_PRICE_ORACLE_ vars to Makefile +- [#7144](https://github.com/blockscout/blockscout/pull/7144) - Update Blockscout logo +- [#7136](https://github.com/blockscout/blockscout/pull/7136) - Add release link or commit hash to docker images +- [#7097](https://github.com/blockscout/blockscout/pull/7097) - Force display token instance page +- [#7119](https://github.com/blockscout/blockscout/pull/7119), [#7149](https://github.com/blockscout/blockscout/pull/7149) - Refactor runtime config +- [#7072](https://github.com/blockscout/blockscout/pull/7072) - Add a separate docker compose for geth with clique consensus +- [#7056](https://github.com/blockscout/blockscout/pull/7056) - Add path_helper in interact.js +- [#7040](https://github.com/blockscout/blockscout/pull/7040) - Use alias BlockScoutWeb.Cldr.Number +- [#7037](https://github.com/blockscout/blockscout/pull/7037) - Define common function for "reltuples" query +- [#7034](https://github.com/blockscout/blockscout/pull/7034) - Resolve "Unexpected var, use let or const instead" +- [#7014](https://github.com/blockscout/blockscout/pull/7014), [#7036](https://github.com/blockscout/blockscout/pull/7036), [7041](https://github.com/blockscout/blockscout/pull/7041) - Fix spell in namings, add spell checking in CI +- [#7012](https://github.com/blockscout/blockscout/pull/7012) - Refactor socket.js +- [#6960](https://github.com/blockscout/blockscout/pull/6960) - Add deploy + workflow for testing (bs-indexers-ethereum-goerli) +- [#6989](https://github.com/blockscout/blockscout/pull/6989) - Update bitwalker/alpine-elixir-phoenix: 1.13 -> 1.14 +- [#6987](https://github.com/blockscout/blockscout/pull/6987) - Change tx actions warning importance + +
+ Dependencies version bumps + +- [6997](https://github.com/blockscout/blockscout/pull/6997) - Bump sweetalert2 from 11.7.2 to 11.7.3 in /apps/block_scout_web/assets +- [6999](https://github.com/blockscout/blockscout/pull/6999) - Bump @amplitude/analytics-browser from 1.8.0 to 1.9.0 in /apps/block_scout_web/assets +- [7000](https://github.com/blockscout/blockscout/pull/7000) - Bump eslint from 8.34.0 to 8.35.0 in /apps/block_scout_web/assets +- [7001](https://github.com/blockscout/blockscout/pull/7001) - Bump core-js from 3.28.0 to 3.29.0 in /apps/block_scout_web/assets +- [7002](https://github.com/blockscout/blockscout/pull/7002) - Bump floki from 0.34.1 to 0.34.2 +- [7004](https://github.com/blockscout/blockscout/pull/7004) - Bump ex_cldr from 2.34.1 to 2.34.2 +- [7011](https://github.com/blockscout/blockscout/pull/7011) - Bump ex_doc from 0.29.1 to 0.29.2 +- [7026](https://github.com/blockscout/blockscout/pull/7026) - Bump @amplitude/analytics-browser from 1.9.0 to 1.9.1 in /apps/block_scout_web/assets +- [7029](https://github.com/blockscout/blockscout/pull/7029) - Bump jest from 29.4.3 to 29.5.0 in /apps/block_scout_web/assets +- [7028](https://github.com/blockscout/blockscout/pull/7028) - Bump luxon from 3.2.1 to 3.3.0 in /apps/block_scout_web/assets +- [7027](https://github.com/blockscout/blockscout/pull/7027) - Bump jest-environment-jsdom from 29.4.3 to 29.5.0 in /apps/block_scout_web/assets +- [7030](https://github.com/blockscout/blockscout/pull/7030) - Bump viewerjs from 1.11.2 to 1.11.3 in /apps/block_scout_web/assets +- [7042](https://github.com/blockscout/blockscout/pull/7042) - Bump ex_cldr_numbers from 2.29.0 to 2.30.0 +- [7048](https://github.com/blockscout/blockscout/pull/7048) - Bump webpack from 5.75.0 to 5.76.0 in /apps/block_scout_web/assets +- [7049](https://github.com/blockscout/blockscout/pull/7049) - Bump jquery from 3.6.3 to 3.6.4 in /apps/block_scout_web/assets +- [7050](https://github.com/blockscout/blockscout/pull/7050) - Bump mini-css-extract-plugin from 2.7.2 to 2.7.3 in /apps/block_scout_web/assets +- [7063](https://github.com/blockscout/blockscout/pull/7063) - Bump autoprefixer from 10.4.13 to 10.4.14 in /apps/block_scout_web/assets +- [7064](https://github.com/blockscout/blockscout/pull/7064) - Bump ueberauth from 0.10.3 to 0.10.5 +- [7074](https://github.com/blockscout/blockscout/pull/7074) - Bump core-js from 3.29.0 to 3.29.1 in /apps/block_scout_web/assets +- [7078](https://github.com/blockscout/blockscout/pull/7078) - Bump ex_cldr from 2.35.1 to 2.36.0 +- [7075](https://github.com/blockscout/blockscout/pull/7075) - Bump webpack from 5.76.0 to 5.76.1 in /apps/block_scout_web/assets +- [7077](https://github.com/blockscout/blockscout/pull/7077) - Bump wallaby from 0.30.1 to 0.30.2 +- [7073](https://github.com/blockscout/blockscout/pull/7073) - Bump sass from 1.58.3 to 1.59.2 in /apps/block_scout_web/assets +- [7076](https://github.com/blockscout/blockscout/pull/7076) - Bump eslint from 8.35.0 to 8.36.0 in /apps/block_scout_web/assets +- [7082](https://github.com/blockscout/blockscout/pull/7082) - Bump @babel/core from 7.21.0 to 7.21.3 in /apps/block_scout_web/assets +- [7083](https://github.com/blockscout/blockscout/pull/7083) - Bump style-loader from 3.3.1 to 3.3.2 in /apps/block_scout_web/assets +- [7086](https://github.com/blockscout/blockscout/pull/7086) - Bump sass from 1.59.2 to 1.59.3 in /apps/block_scout_web/assets +- [7092](https://github.com/blockscout/blockscout/pull/7092) - Bump mini-css-extract-plugin from 2.7.3 to 2.7.4 in /apps/block_scout_web/assets +- [7094](https://github.com/blockscout/blockscout/pull/7094) - Bump webpack from 5.76.1 to 5.76.2 in /apps/block_scout_web/assets +- [7095](https://github.com/blockscout/blockscout/pull/7095) - Bump plug_cowboy from 2.6.0 to 2.6.1 +- [7093](https://github.com/blockscout/blockscout/pull/7093) - Bump postcss-loader from 7.0.2 to 7.1.0 in /apps/block_scout_web/assets +- [7100](https://github.com/blockscout/blockscout/pull/7100) - Bump mini-css-extract-plugin from 2.7.4 to 2.7.5 in /apps/block_scout_web/assets +- [7101](https://github.com/blockscout/blockscout/pull/7101) - Bump ex_doc from 0.29.2 to 0.29.3 +- [7113](https://github.com/blockscout/blockscout/pull/7113) - Bump sass-loader from 13.2.0 to 13.2.1 in /apps/block_scout_web/assets +- [7114](https://github.com/blockscout/blockscout/pull/7114) - Bump web3 from 1.8.2 to 1.9.0 in /apps/block_scout_web/assets +- [7117](https://github.com/blockscout/blockscout/pull/7117) - Bump flow from 1.2.3 to 1.2.4 +- [7127](https://github.com/blockscout/blockscout/pull/7127) - Bump webpack from 5.76.2 to 5.76.3 in /apps/block_scout_web/assets +- [7128](https://github.com/blockscout/blockscout/pull/7128) - Bump ecto from 3.9.4 to 3.9.5 +- [7129](https://github.com/blockscout/blockscout/pull/7129) - Bump ex_abi from 0.5.16 to 0.6.0 +- [7118](https://github.com/blockscout/blockscout/pull/7118) - Bump credo from 1.6.7 to 1.7.0 +- [7151](https://github.com/blockscout/blockscout/pull/7151) - Bump mixpanel-browser from 2.45.0 to 2.46.0 in /apps/block_scout_web/assets +- [7156](https://github.com/blockscout/blockscout/pull/7156) - Bump cldr_utils from 2.21.0 to 2.22.0 +- [7155](https://github.com/blockscout/blockscout/pull/7155) - Bump timex from 3.7.9 to 3.7.11 +- [7154](https://github.com/blockscout/blockscout/pull/7154) - Bump sass-loader from 13.2.1 to 13.2.2 in /apps/block_scout_web/assets +- [7152](https://github.com/blockscout/blockscout/pull/7152) - Bump @fortawesome/fontawesome-free from 6.3.0 to 6.4.0 in /apps/block_scout_web/assets +- [7153](https://github.com/blockscout/blockscout/pull/7153) - Bump sass from 1.59.3 to 1.60.0 in /apps/block_scout_web/assets +- [7159](https://github.com/blockscout/blockscout/pull/7159) - Bump ex_cldr_numbers from 2.30.0 to 2.30.1 +- [7158](https://github.com/blockscout/blockscout/pull/7158) - Bump css-minimizer-webpack-plugin from 4.2.2 to 5.0.0 in /apps/block_scout_web/assets +- [7165](https://github.com/blockscout/blockscout/pull/7165) - Bump ex_doc from 0.29.3 to 0.29.4 +- [7164](https://github.com/blockscout/blockscout/pull/7164) - Bump photoswipe from 5.3.6 to 5.3.7 in /apps/block_scout_web/assets +- [7167](https://github.com/blockscout/blockscout/pull/7167) - Bump webpack from 5.76.3 to 5.77.0 in /apps/block_scout_web/assets +- [7166](https://github.com/blockscout/blockscout/pull/7166) - Bump eslint from 8.36.0 to 8.37.0 in /apps/block_scout_web/assets + +
+ +## 5.1.1-beta + +### Features + +- [#6973](https://github.com/blockscout/blockscout/pull/6973) - API v2: `/smart-contracts` and `/state-changes` endpoints +- [#6897](https://github.com/blockscout/blockscout/pull/6897) - Support basic auth in JSON RPC endpoint +- [#6908](https://github.com/blockscout/blockscout/pull/6908) - Allow disable API rate limit +- [#6951](https://github.com/blockscout/blockscout/pull/6951), [#6958](https://github.com/blockscout/blockscout/pull/6958), [#6991](https://github.com/blockscout/blockscout/pull/6991) - Set poll: true for TokenInstance fetcher +- [#5720](https://github.com/blockscout/blockscout/pull/5720) - Fetchers graceful shutdown + +### Fixes + +- [#6933](https://github.com/blockscout/blockscout/pull/6933) - Extract blocking UI requests to separate GenServers +- [#6953](https://github.com/blockscout/blockscout/pull/6953) - reCAPTCHA dark mode +- [#6940](https://github.com/blockscout/blockscout/pull/6940) - Reduce ttl_check_interval for cache module +- [#6941](https://github.com/blockscout/blockscout/pull/6941) - Sanitize search query before displaying +- [#6912](https://github.com/blockscout/blockscout/pull/6912) - Docker compose fix exposed ports +- [#6913](https://github.com/blockscout/blockscout/pull/6913) - Fix an error occurred when decoding base64 encoded json +- [#6911](https://github.com/blockscout/blockscout/pull/6911) - Fix bugs in verification API v2 +- [#6903](https://github.com/blockscout/blockscout/pull/6903), [#6937](https://github.com/blockscout/blockscout/pull/6937), [#6961](https://github.com/blockscout/blockscout/pull/6961) - Fix indexed blocks value in "Indexing tokens" banner +- [#6891](https://github.com/blockscout/blockscout/pull/6891) - Fix read contract for geth +- [#6889](https://github.com/blockscout/blockscout/pull/6889) - Fix Internal Server Error on tx input decoding +- [#6893](https://github.com/blockscout/blockscout/pull/6893) - Fix token type definition for multiple interface tokens +- [#6922](https://github.com/blockscout/blockscout/pull/6922) - Fix WebSocketClient +- [#6501](https://github.com/blockscout/blockscout/pull/6501) - Fix wss connect + +### Chore + +- [#6981](https://github.com/blockscout/blockscout/pull/6981) - Token instance fetcher batch size and concurrency env vars +- [#6954](https://github.com/blockscout/blockscout/pull/6954), [#6979](https://github.com/blockscout/blockscout/pull/6979) - Move some compile time vars to runtime +- [#6952](https://github.com/blockscout/blockscout/pull/6952) - Manage BlockReward fetcher params +- [#6929](https://github.com/blockscout/blockscout/pull/6929) - Extend `INDEXER_MEMORY_LIMIT` env parsing +- [#6902](https://github.com/blockscout/blockscout/pull/6902) - Increase verification timeout to 120 seconds for microservice verification + +
+ Dependencies version bumps + +- [#6882](https://github.com/blockscout/blockscout/pull/6882) - Bump exvcr from 0.13.4 to 0.13.5 +- [#6883](https://github.com/blockscout/blockscout/pull/6883) - Bump floki from 0.34.0 to 0.34.1 +- [#6884](https://github.com/blockscout/blockscout/pull/6884) - Bump eslint from 8.33.0 to 8.34.0 in /apps/block_scout_web/assets +- [#6894](https://github.com/blockscout/blockscout/pull/6894) - Bump core-js from 3.27.2 to 3.28.0 in /apps/block_scout_web/assets +- [#6895](https://github.com/blockscout/blockscout/pull/6895) - Bump sass from 1.58.0 to 1.58.1 in /apps/block_scout_web/assets +- [#6905](https://github.com/blockscout/blockscout/pull/6905) - Bump jest-environment-jsdom from 29.4.2 to 29.4.3 in /apps/block_scout_web/assets +- [#6907](https://github.com/blockscout/blockscout/pull/6907) - Bump cbor from 1.0.0 to 1.0.1 +- [#6906](https://github.com/blockscout/blockscout/pull/6906) - Bump jest from 29.4.2 to 29.4.3 in /apps/block_scout_web/assets +- [#6917](https://github.com/blockscout/blockscout/pull/6917) - Bump tesla from 1.5.0 to 1.5.1 +- [#6930](https://github.com/blockscout/blockscout/pull/6930) - Bump sweetalert2 from 11.7.1 to 11.7.2 in /apps/block_scout_web/assets +- [#6942](https://github.com/blockscout/blockscout/pull/6942) - Bump @babel/core from 7.20.12 to 7.21.0 in /apps/block_scout_web/assets +- [#6943](https://github.com/blockscout/blockscout/pull/6943) - Bump gettext from 0.22.0 to 0.22.1 +- [#6944](https://github.com/blockscout/blockscout/pull/6944) - Bump sass from 1.58.1 to 1.58.3 in /apps/block_scout_web/assets +- [#6966](https://github.com/blockscout/blockscout/pull/6966) - Bump solc from 0.8.18 to 0.8.19 in /apps/explorer +- [#6967](https://github.com/blockscout/blockscout/pull/6967) - Bump photoswipe from 5.3.5 to 5.3.6 in /apps/block_scout_web/assets +- [#6968](https://github.com/blockscout/blockscout/pull/6968) - Bump ex_rlp from 0.5.5 to 0.6.0 + +
+ +## 5.1.0-beta + +### Features + +- [#6871](https://github.com/blockscout/blockscout/pull/6871) - Integrate new smart contract verifier version +- [#6838](https://github.com/blockscout/blockscout/pull/6838) - Disable dark mode env var +- [#6843](https://github.com/blockscout/blockscout/pull/6843) - Add env variable to hide Add to MM button +- [#6744](https://github.com/blockscout/blockscout/pull/6744) - API v2: smart contracts verification +- [#6763](https://github.com/blockscout/blockscout/pull/6763) - Permanent UI dark mode +- [#6721](https://github.com/blockscout/blockscout/pull/6721) - Implement fetching internal transactions from callTracer +- [#6541](https://github.com/blockscout/blockscout/pull/6541) - Integrate sig provider +- [#6712](https://github.com/blockscout/blockscout/pull/6712), [#6798](https://github.com/blockscout/blockscout/pull/6798) - API v2 update +- [#6582](https://github.com/blockscout/blockscout/pull/6582) - Transaction actions indexer +- [#6863](https://github.com/blockscout/blockscout/pull/6863) - Move OnDemand fetchers from indexer supervisor + +### Fixes + +- [#6864](https://github.com/blockscout/blockscout/pull/6864) - Fix pool checker in tx actions fetcher +- [#6860](https://github.com/blockscout/blockscout/pull/6860) - JSON RPC to CSP header +- [#6859](https://github.com/blockscout/blockscout/pull/6859) - Fix task restart in transaction actions fetcher +- [#6840](https://github.com/blockscout/blockscout/pull/6840) - Fix realtime block fetcher +- [#6831](https://github.com/blockscout/blockscout/pull/6831) - Copy of [#6028](https://github.com/blockscout/blockscout/pull/6028) +- [#6832](https://github.com/blockscout/blockscout/pull/6832) - Transaction actions fix +- [#6827](https://github.com/blockscout/blockscout/pull/6827) - Fix handling unknown calls from `callTracer` +- [#6793](https://github.com/blockscout/blockscout/pull/6793) - Change sig-provider default image tag to main +- [#6777](https://github.com/blockscout/blockscout/pull/6777) - Fix -1 transaction counter +- [#6746](https://github.com/blockscout/blockscout/pull/6746) - Fix -1 address counter +- [#6736](https://github.com/blockscout/blockscout/pull/6736) - Fix `/tokens` in old UI +- [#6705](https://github.com/blockscout/blockscout/pull/6705) - Fix `/smart-contracts` bugs in API v2 +- [#6740](https://github.com/blockscout/blockscout/pull/6740) - Fix tokens deadlock +- [#6759](https://github.com/blockscout/blockscout/pull/6759) - Add `jq` in docker image +- [#6779](https://github.com/blockscout/blockscout/pull/6779) - Fix missing ranges bounds clearing +- [#6652](https://github.com/blockscout/blockscout/pull/6652) - Fix geth transaction tracer + +### Chore + +- [#6877](https://github.com/blockscout/blockscout/pull/6877) - Docker-compose: increase default max connections and db pool size +- [#6853](https://github.com/blockscout/blockscout/pull/6853) - Fix 503 page +- [#6845](https://github.com/blockscout/blockscout/pull/6845) - Extract Docker-compose services into separate files +- [#6839](https://github.com/blockscout/blockscout/pull/6839) - Add cache to transaction actions parser +- [#6834](https://github.com/blockscout/blockscout/pull/6834) - Take into account FIRST_BLOCK in "Total blocks" counter on the main page +- [#6340](https://github.com/blockscout/blockscout/pull/6340) - Rollback to websocket_client 1.3.0 +- [#6786](https://github.com/blockscout/blockscout/pull/6786) - Refactor `try rescue` statements to keep stacktrace +- [#6695](https://github.com/blockscout/blockscout/pull/6695) - Process errors and warnings with enables check-js feature in VS code + +
+ Dependencies version bumps + +- [#6703](https://github.com/blockscout/blockscout/pull/6703) - Bump @amplitude/analytics-browser from 1.6.7 to 1.6.8 in /apps/block_scout_web/assets +- [#6716](https://github.com/blockscout/blockscout/pull/6716) - Bump prometheus from 4.9.1 to 4.10.0 +- [#6717](https://github.com/blockscout/blockscout/pull/6717) - Bump briefly from 13a9790 to 20d1318 +- [#6715](https://github.com/blockscout/blockscout/pull/6715) - Bump eslint-plugin-import from 2.26.0 to 2.27.4 in /apps/block_scout_web/assets +- [#6702](https://github.com/blockscout/blockscout/pull/6702) - Bump sweetalert2 from 11.6.16 to 11.7.0 in /apps/block_scout_web/assets +- [#6722](https://github.com/blockscout/blockscout/pull/6722) - Bump eslint from 8.31.0 to 8.32.0 in /apps/block_scout_web/assets +- [#6727](https://github.com/blockscout/blockscout/pull/6727) - Bump eslint-plugin-import from 2.27.4 to 2.27.5 in /apps/block_scout_web/assets +- [#6728](https://github.com/blockscout/blockscout/pull/6728) - Bump ex_cldr_numbers from 2.28.0 to 2.29.0 +- [#6732](https://github.com/blockscout/blockscout/pull/6732) - Bump chart.js from 4.1.2 to 4.2.0 in /apps/block_scout_web/assets +- [#6739](https://github.com/blockscout/blockscout/pull/6739) - Bump core-js from 3.27.1 to 3.27.2 in /apps/block_scout_web/assets +- [#6753](https://github.com/blockscout/blockscout/pull/6753) - Bump gettext from 0.21.0 to 0.22.0 +- [#6754](https://github.com/blockscout/blockscout/pull/6754) - Bump cookiejar from 2.1.3 to 2.1.4 in /apps/block_scout_web/assets +- [#6756](https://github.com/blockscout/blockscout/pull/6756) - Bump jest from 29.3.1 to 29.4.0 in /apps/block_scout_web/assets +- [#6757](https://github.com/blockscout/blockscout/pull/6757) - Bump jest-environment-jsdom from 29.3.1 to 29.4.0 in /apps/block_scout_web/assets +- [#6764](https://github.com/blockscout/blockscout/pull/6764) - Bump sweetalert2 from 11.7.0 to 11.7.1 in /apps/block_scout_web/assets +- [#6770](https://github.com/blockscout/blockscout/pull/6770) - Bump jest-environment-jsdom from 29.4.0 to 29.4.1 in /apps/block_scout_web/assets +- [#6773](https://github.com/blockscout/blockscout/pull/6773) - Bump ex_cldr from 2.34.0 to 2.34.1 +- [#6772](https://github.com/blockscout/blockscout/pull/6772) - Bump jest from 29.4.0 to 29.4.1 in /apps/block_scout_web/assets +- [#6771](https://github.com/blockscout/blockscout/pull/6771) - Bump web3modal from 1.9.11 to 1.9.12 in /apps/block_scout_web/assets +- [#6781](https://github.com/blockscout/blockscout/pull/6781) - Bump cldr_utils from 2.19.2 to 2.20.0 +- [#6789](https://github.com/blockscout/blockscout/pull/6789) - Bump eslint from 8.32.0 to 8.33.0 in /apps/block_scout_web/assets +- [#6790](https://github.com/blockscout/blockscout/pull/6790) - Bump redux from 4.2.0 to 4.2.1 in /apps/block_scout_web/assets +- [#6792](https://github.com/blockscout/blockscout/pull/6792) - Bump cldr_utils from 2.20.0 to 2.21.0 +- [#6788](https://github.com/blockscout/blockscout/pull/6788) - Bump web3 from 1.8.1 to 1.8.2 in /apps/block_scout_web/assets +- [#6802](https://github.com/blockscout/blockscout/pull/6802) - Bump @amplitude/analytics-browser from 1.6.8 to 1.7.0 in /apps/block_scout_web/assets +- [#6803](https://github.com/blockscout/blockscout/pull/6803) - Bump photoswipe from 5.3.4 to 5.3.5 in /apps/block_scout_web/assets +- [#6804](https://github.com/blockscout/blockscout/pull/6804) - Bump sass from 1.57.1 to 1.58.0 in /apps/block_scout_web/assets +- [#6807](https://github.com/blockscout/blockscout/pull/6807) - Bump absinthe from 1.7.0 to 1.7.1 +- [#6806](https://github.com/blockscout/blockscout/pull/6806) - Bump solc from 0.8.16 to 0.8.18 in /apps/explorer +- [#6814](https://github.com/blockscout/blockscout/pull/6814) - Bump @amplitude/analytics-browser from 1.7.0 to 1.7.1 in /apps/block_scout_web/assets +- [#6813](https://github.com/blockscout/blockscout/pull/6813) - Bump chartjs-adapter-luxon from 1.3.0 to 1.3.1 in /apps/block_scout_web/assets +- [#6846](https://github.com/blockscout/blockscout/pull/6846) - Bump jest from 29.4.1 to 29.4.2 in /apps/block_scout_web/assets +- [#6850](https://github.com/blockscout/blockscout/pull/6850) - Bump redix from 1.2.0 to 1.2.1 +- [#6849](https://github.com/blockscout/blockscout/pull/6849) - Bump jest-environment-jsdom from 29.4.1 to 29.4.2 in /apps/block_scout_web/assets +- [#6857](https://github.com/blockscout/blockscout/pull/6857) - Bump @amplitude/analytics-browser from 1.7.1 to 1.8.0 in /apps/block_scout_web/assets +- [#6847](https://github.com/blockscout/blockscout/pull/6847) - Bump @fortawesome/fontawesome-free from 6.2.1 to 6.3.0 in /apps/block_scout_web/assets +- [#6866](https://github.com/blockscout/blockscout/pull/6866) - Bump chart.js from 4.2.0 to 4.2.1 in /apps/block_scout_web/assets + +
+ +## 5.0.0-beta + +### Features + +- [#6092](https://github.com/blockscout/blockscout/pull/6092) - Blockscout Account functionality +- [#6324](https://github.com/blockscout/blockscout/pull/6324) - Add verified contracts list page +- [#6316](https://github.com/blockscout/blockscout/pull/6316) - Public tags functionality +- [#6444](https://github.com/blockscout/blockscout/pull/6444) - Add support for yul verification via rust microservice +- [#6073](https://github.com/blockscout/blockscout/pull/6073) - Add vyper support for rust verifier microservice integration +- [#6401](https://github.com/blockscout/blockscout/pull/6401) - Add Sol2Uml contract visualization +- [#6583](https://github.com/blockscout/blockscout/pull/6583), [#6687](https://github.com/blockscout/blockscout/pull/6687) - Missing ranges collector +- [#6574](https://github.com/blockscout/blockscout/pull/6574), [#6601](https://github.com/blockscout/blockscout/pull/6601) - Allow and manage insecure HTTP connection to the archive node +- [#6433](https://github.com/blockscout/blockscout/pull/6433), [#6698](https://github.com/blockscout/blockscout/pull/6698) - Update error pages +- [#6544](https://github.com/blockscout/blockscout/pull/6544) - API improvements +- [#5561](https://github.com/blockscout/blockscout/pull/5561), [#6523](https://github.com/blockscout/blockscout/pull/6523), [#6549](https://github.com/blockscout/blockscout/pull/6549) - Improve working with contracts implementations +- [#6481](https://github.com/blockscout/blockscout/pull/6481) - Smart contract verification improvements +- [#6440](https://github.com/blockscout/blockscout/pull/6440) - Add support for base64 encoded NFT metadata +- [#6407](https://github.com/blockscout/blockscout/pull/6407) - Indexed ratio for int txs fetching stage +- [#6379](https://github.com/blockscout/blockscout/pull/6379), [#6429](https://github.com/blockscout/blockscout/pull/6429), [#6642](https://github.com/blockscout/blockscout/pull/6642), [#6677](https://github.com/blockscout/blockscout/pull/6677) - API v2 for frontend +- [#6351](https://github.com/blockscout/blockscout/pull/6351) - Enable forum link env var +- [#6196](https://github.com/blockscout/blockscout/pull/6196) - INDEXER_CATCHUP_BLOCKS_BATCH_SIZE and INDEXER_CATCHUP_BLOCKS_CONCURRENCY env variables +- [#6187](https://github.com/blockscout/blockscout/pull/6187) - Filter by created time of verified contracts in listcontracts API endpoint +- [#6111](https://github.com/blockscout/blockscout/pull/6111) - Add Prometheus metrics to indexer +- [#6168](https://github.com/blockscout/blockscout/pull/6168) - Token instance fetcher checks instance owner and updates current token balance +- [#6209](https://github.com/blockscout/blockscout/pull/6209) - Add metrics for block import stages, runners, steps +- [#6257](https://github.com/blockscout/blockscout/pull/6257), [#6276](https://github.com/blockscout/blockscout/pull/6276) - DISABLE_TOKEN_INSTANCE_FETCHER env variable +- [#6391](https://github.com/blockscout/blockscout/pull/6391), [#6427](https://github.com/blockscout/blockscout/pull/6427) - TokenTransfer token_id -> token_ids migration +- [#6443](https://github.com/blockscout/blockscout/pull/6443) - Drop internal transactions order index +- [#6450](https://github.com/blockscout/blockscout/pull/6450) - INDEXER_INTERNAL_TRANSACTIONS_BATCH_SIZE and INDEXER_INTERNAL_TRANSACTIONS_CONCURRENCY env variables +- [#6454](https://github.com/blockscout/blockscout/pull/6454) - INDEXER_RECEIPTS_BATCH_SIZE, INDEXER_RECEIPTS_CONCURRENCY, INDEXER_COIN_BALANCES_BATCH_SIZE, INDEXER_COIN_BALANCES_CONCURRENCY env variables +- [#6476](https://github.com/blockscout/blockscout/pull/6476), [#6484](https://github.com/blockscout/blockscout/pull/6484) - Update token balances indexes +- [#6510](https://github.com/blockscout/blockscout/pull/6510) - Set consensus: false for blocks on int transaction foreign_key_violation +- [#6565](https://github.com/blockscout/blockscout/pull/6565) - Set restart: :permanent for permanent fetchers +- [#6568](https://github.com/blockscout/blockscout/pull/6568) - Drop unfetched_token_balances index +- [#6647](https://github.com/blockscout/blockscout/pull/6647) - Pending block operations update +- [#6542](https://github.com/blockscout/blockscout/pull/6542) - Init mixpanel and amplitude analytics +- [#6713](https://github.com/blockscout/blockscout/pull/6713) - Remove internal transactions deletion + +### Fixes + +- [#6676](https://github.com/blockscout/blockscout/pull/6676) - Fix `/smart-contracts` bugs in API v2 +- [#6603](https://github.com/blockscout/blockscout/pull/6603) - Add to MM button explorer URL fix +- [#6512](https://github.com/blockscout/blockscout/pull/6512) - Allow gasUsed in failed internal txs; Leave error field for staticcall +- [#6532](https://github.com/blockscout/blockscout/pull/6532) - Fix index creation migration +- [#6473](https://github.com/blockscout/blockscout/pull/6473) - Fix state changes for contract creation transactions +- [#6475](https://github.com/blockscout/blockscout/pull/6475) - Fix token name with unicode graphemes shortening +- [#6420](https://github.com/blockscout/blockscout/pull/6420) - Fix address logs search +- [#6390](https://github.com/blockscout/blockscout/pull/6390), [#6502](https://github.com/blockscout/blockscout/pull/6502), [#6511](https://github.com/blockscout/blockscout/pull/6511) - Fix transactions responses in API v2 +- [#6357](https://github.com/blockscout/blockscout/pull/6357), [#6409](https://github.com/blockscout/blockscout/pull/6409), [#6428](https://github.com/blockscout/blockscout/pull/6428) - Fix definitions of NETWORK_PATH, API_PATH, SOCKET_ROOT: process trailing slash +- [#6338](https://github.com/blockscout/blockscout/pull/6338) - Fix token search with space +- [#6329](https://github.com/blockscout/blockscout/pull/6329) - Prevent logger from truncating response from rust verifier service in case of an error +- [#6309](https://github.com/blockscout/blockscout/pull/6309) - Fix read contract bug and change address tx count +- [#6303](https://github.com/blockscout/blockscout/pull/6303) - Fix some UI bugs +- [#6243](https://github.com/blockscout/blockscout/pull/6243) - Fix freezes on `/blocks` page +- [#6162](https://github.com/blockscout/blockscout/pull/6162) - Extend token symbol type varchar(255) -> text +- [#6158](https://github.com/blockscout/blockscout/pull/6158) - Add missing clause for merge_twin_vyper_contract_with_changeset function +- [#6090](https://github.com/blockscout/blockscout/pull/6090) - Fix metadata fetching for ERC-1155 tokens instances +- [#6091](https://github.com/blockscout/blockscout/pull/6091) - Improve fetching media type for NFT +- [#6094](https://github.com/blockscout/blockscout/pull/6094) - Fix inconsistent behavior of `getsourcecode` method +- [#6105](https://github.com/blockscout/blockscout/pull/6105) - Fix some token transfers broadcasting +- [#6106](https://github.com/blockscout/blockscout/pull/6106) - Fix 500 response on `/coin-balance` for empty address +- [#6118](https://github.com/blockscout/blockscout/pull/6118) - Fix unfetched token balances +- [#6163](https://github.com/blockscout/blockscout/pull/6163) - Fix rate limit logs +- [#6223](https://github.com/blockscout/blockscout/pull/6223) - Fix coin_id test +- [#6336](https://github.com/blockscout/blockscout/pull/6336) - Fix sending request on each key in token search +- [#6327](https://github.com/blockscout/blockscout/pull/6327) - Fix and refactor address logs page and search +- [#6449](https://github.com/blockscout/blockscout/pull/6449) - Search min_missing_block_number from zero +- [#6492](https://github.com/blockscout/blockscout/pull/6492) - Remove token instance owner fetching +- [#6536](https://github.com/blockscout/blockscout/pull/6536) - Fix internal transactions query +- [#6550](https://github.com/blockscout/blockscout/pull/6550) - Query token transfers before updating +- [#6599](https://github.com/blockscout/blockscout/pull/6599) - unhandled division by zero +- [#6590](https://github.com/blockscout/blockscout/pull/6590) - ignore some receipt fields for metis + +### Chore + +- [#6607](https://github.com/blockscout/blockscout/pull/6607) - Run e2e tests after PR review +- [#6606](https://github.com/blockscout/blockscout/pull/6606) - Add ARG SESSION_COOKIE_DOMAIN to Dockerfile +- [#6600](https://github.com/blockscout/blockscout/pull/6600) - Token stub icon +- [#6588](https://github.com/blockscout/blockscout/pull/6588) - Add latest image build for frontend-main with specific build-args +- [#6584](https://github.com/blockscout/blockscout/pull/6584) - Vacuum package-lock.json +- [#6581](https://github.com/blockscout/blockscout/pull/6581) - Dark mode switcher localStorage to cookie in order to support new UI +- [#6572](https://github.com/blockscout/blockscout/pull/6572) - pending_block_operations table: remove fetch_internal_transactions column +- [#6387](https://github.com/blockscout/blockscout/pull/6387) - Fix errors in docker-build and e2e-tests workflows +- [#6325](https://github.com/blockscout/blockscout/pull/6325) - Set http_only attribute of account authorization cookie to false +- [#6343](https://github.com/blockscout/blockscout/pull/6343) - Docker-compose persistent logs +- [#6240](https://github.com/blockscout/blockscout/pull/6240) - Elixir 1.14 support +- [#6204](https://github.com/blockscout/blockscout/pull/6204) - Refactor contract libs render, CONTRACT_VERIFICATION_MAX_LIBRARIES, refactor parsing integer env vars in config +- [#6195](https://github.com/blockscout/blockscout/pull/6195) - Docker compose configs improvements: Redis container name and persistent storage +- [#6192](https://github.com/blockscout/blockscout/pull/6192), [#6207](https://github.com/blockscout/blockscout/pull/6207) - Hide Indexing Internal Transactions message, if INDEXER_DISABLE_INTERNAL_TRANSACTIONS_FETCHER=true +- [#6183](https://github.com/blockscout/blockscout/pull/6183) - Transparent coin name definition +- [#6155](https://github.com/blockscout/blockscout/pull/6155), [#6189](https://github.com/blockscout/blockscout/pull/6189) - Refactor Ethereum JSON RPC variants +- [#6125](https://github.com/blockscout/blockscout/pull/6125) - Rename obsolete "parity" EthereumJSONRPC.Variant to "nethermind" +- [#6124](https://github.com/blockscout/blockscout/pull/6124) - Docker compose: add config for Erigon +- [#6061](https://github.com/blockscout/blockscout/pull/6061) - Discord badge and updated permalink + +
+ Dependencies version bumps + +- [#6585](https://github.com/blockscout/blockscout/pull/6585) - Bump jquery from 3.6.1 to 3.6.2 in /apps/block_scout_web/assets +- [#6610](https://github.com/blockscout/blockscout/pull/6610) - Bump tesla from 1.4.4 to 1.5.0 +- [#6611](https://github.com/blockscout/blockscout/pull/6611) - Bump chart.js from 4.0.1 to 4.1.0 in /apps/block_scout_web/assets +- [#6618](https://github.com/blockscout/blockscout/pull/6618) - Bump chart.js from 4.1.0 to 4.1.1 in /apps/block_scout_web/assets +- [#6619](https://github.com/blockscout/blockscout/pull/6619) - Bump eslint from 8.29.0 to 8.30.0 in /apps/block_scout_web/assets +- [#6620](https://github.com/blockscout/blockscout/pull/6620) - Bump sass from 1.56.2 to 1.57.0 in /apps/block_scout_web/assets +- [#6626](https://github.com/blockscout/blockscout/pull/6626) - Bump @amplitude/analytics-browser from 1.6.1 to 1.6.6 in /apps/block_scout_web/assets +- [#6627](https://github.com/blockscout/blockscout/pull/6627) - Bump sass from 1.57.0 to 1.57.1 in /apps/block_scout_web/assets +- [#6628](https://github.com/blockscout/blockscout/pull/6628) - Bump sweetalert2 from 11.6.15 to 11.6.16 in /apps/block_scout_web/assets +- [#6631](https://github.com/blockscout/blockscout/pull/6631) - Bump jquery from 3.6.2 to 3.6.3 in /apps/block_scout_web/assets +- [#6633](https://github.com/blockscout/blockscout/pull/6633) - Bump ecto_sql from 3.9.1 to 3.9.2 +- [#6636](https://github.com/blockscout/blockscout/pull/6636) - Bump ecto from 3.9.3 to 3.9.4 +- [#6639](https://github.com/blockscout/blockscout/pull/6639) - Bump @amplitude/analytics-browser from 1.6.6 to 1.6.7 in /apps/block_scout_web/assets +- [#6640](https://github.com/blockscout/blockscout/pull/6640) - Bump @babel/core from 7.20.5 to 7.20.7 in /apps/block_scout_web/assets +- [#6653](https://github.com/blockscout/blockscout/pull/6653) - Bump luxon from 3.1.1 to 3.2.0 in /apps/block_scout_web/assets +- [#6654](https://github.com/blockscout/blockscout/pull/6654) - Bump flow from 1.2.0 to 1.2.1 +- [#6669](https://github.com/blockscout/blockscout/pull/6669) - Bump @babel/core from 7.20.7 to 7.20.12 in /apps/block_scout_web/assets +- [#6663](https://github.com/blockscout/blockscout/pull/6663) - Bump eslint from 8.30.0 to 8.31.0 in /apps/block_scout_web/assets +- [#6662](https://github.com/blockscout/blockscout/pull/6662) - Bump viewerjs from 1.11.1 to 1.11.2 in /apps/block_scout_web/assets +- [#6668](https://github.com/blockscout/blockscout/pull/6668) - Bump babel-loader from 9.1.0 to 9.1.2 in /apps/block_scout_web/assets +- [#6670](https://github.com/blockscout/blockscout/pull/6670) - Bump json5 from 1.0.1 to 1.0.2 in /apps/block_scout_web/assets +- [#6673](https://github.com/blockscout/blockscout/pull/6673) - Bump chart.js from 4.1.1 to 4.1.2 in /apps/block_scout_web/assets +- [#6674](https://github.com/blockscout/blockscout/pull/6674) - Bump luxon from 3.2.0 to 3.2.1 in /apps/block_scout_web/assets +- [#6675](https://github.com/blockscout/blockscout/pull/6675) - Bump web3modal from 1.9.10 to 1.9.11 in /apps/block_scout_web/assets +- [#6679](https://github.com/blockscout/blockscout/pull/6679) - Bump gettext from 0.20.0 to 0.21.0 +- [#6680](https://github.com/blockscout/blockscout/pull/6680) - Bump flow from 1.2.1 to 1.2.2 +- [#6689](https://github.com/blockscout/blockscout/pull/6689) - Bump postcss from 8.4.20 to 8.4.21 in /apps/block_scout_web/assets +- [#6690](https://github.com/blockscout/blockscout/pull/6690) - Bump bamboo from 2.2.0 to 2.3.0 +- [#6691](https://github.com/blockscout/blockscout/pull/6691) - Bump flow from 1.2.2 to 1.2.3 +- [#6696](https://github.com/blockscout/blockscout/pull/6696) - Bump briefly from 1dd66ee to 13a9790 +- [#6697](https://github.com/blockscout/blockscout/pull/6697) - Bump mime from 1.6.0 to 2.0.3 +- [#6053](https://github.com/blockscout/blockscout/pull/6053) - Bump jest-environment-jsdom from 29.0.1 to 29.0.2 in /apps/block_scout_web/assets +- [#6055](https://github.com/blockscout/blockscout/pull/6055) - Bump @babel/core from 7.18.13 to 7.19.0 in /apps/block_scout_web/assets +- [#6054](https://github.com/blockscout/blockscout/pull/6054) - Bump jest from 29.0.1 to 29.0.2 in /apps/block_scout_web/assets +- [#6056](https://github.com/blockscout/blockscout/pull/6056) - Bump @babel/preset-env from 7.18.10 to 7.19.0 in /apps/block_scout_web/assets +- [#6064](https://github.com/blockscout/blockscout/pull/6064) - Bump sweetalert2 from 11.4.29 to 11.4.31 in /apps/block_scout_web/assets +- [#6075](https://github.com/blockscout/blockscout/pull/6075) - Bump sweetalert2 from 11.4.31 to 11.4.32 in /apps/block_scout_web/assets +- [#6082](https://github.com/blockscout/blockscout/pull/6082) - Bump core-js from 3.25.0 to 3.25.1 in /apps/block_scout_web/assets +- [#6083](https://github.com/blockscout/blockscout/pull/6083) - Bump sass from 1.54.8 to 1.54.9 in /apps/block_scout_web/assets +- [#6095](https://github.com/blockscout/blockscout/pull/6095) - Bump jest-environment-jsdom from 29.0.2 to 29.0.3 in /apps/block_scout_web/assets +- [#6096](https://github.com/blockscout/blockscout/pull/6096) - Bump exvcr from 0.13.3 to 0.13.4 +- [#6101](https://github.com/blockscout/blockscout/pull/6101) - Bump ueberauth from 0.10.1 to 0.10.2 +- [#6102](https://github.com/blockscout/blockscout/pull/6102) - Bump eslint from 8.23.0 to 8.23.1 in /apps/block_scout_web/assets +- [#6098](https://github.com/blockscout/blockscout/pull/6098) - Bump ex_json_schema from 0.9.1 to 0.9.2 +- [#6097](https://github.com/blockscout/blockscout/pull/6097) - Bump autoprefixer from 10.4.8 to 10.4.9 in /apps/block_scout_web/assets +- [#6099](https://github.com/blockscout/blockscout/pull/6099) - Bump jest from 29.0.2 to 29.0.3 in /apps/block_scout_web/assets +- [#6103](https://github.com/blockscout/blockscout/pull/6103) - Bump css-minimizer-webpack-plugin from 4.0.0 to 4.1.0 in /apps/block_scout_web/assets +- [#6108](https://github.com/blockscout/blockscout/pull/6108) - Bump autoprefixer from 10.4.9 to 10.4.10 in /apps/block_scout_web/assets +- [#6116](https://github.com/blockscout/blockscout/pull/6116) - Bump autoprefixer from 10.4.10 to 10.4.11 in /apps/block_scout_web/assets +- [#6114](https://github.com/blockscout/blockscout/pull/6114) - Bump @babel/core from 7.19.0 to 7.19.1 in /apps/block_scout_web/assets +- [#6113](https://github.com/blockscout/blockscout/pull/6113) - Bump ueberauth from 0.10.2 to 0.10.3 +- [#6112](https://github.com/blockscout/blockscout/pull/6112) - Bump @babel/preset-env from 7.19.0 to 7.19.1 in /apps/block_scout_web/assets +- [#6115](https://github.com/blockscout/blockscout/pull/6115) - Bump web3 from 1.7.5 to 1.8.0 in /apps/block_scout_web/assets +- [#6117](https://github.com/blockscout/blockscout/pull/6117) - Bump sweetalert2 from 11.4.32 to 11.4.33 in /apps/block_scout_web/assets +- [#6119](https://github.com/blockscout/blockscout/pull/6119) - Bump scss-tokenizer from 0.3.0 to 0.4.3 in /apps/block_scout_web/assets +- [#6138](https://github.com/blockscout/blockscout/pull/6138) - Bump core-js from 3.25.1 to 3.25.2 in /apps/block_scout_web/assets +- [#6147](https://github.com/blockscout/blockscout/pull/6147) - Bump autoprefixer from 10.4.11 to 10.4.12 in /apps/block_scout_web/assets +- [#6151](https://github.com/blockscout/blockscout/pull/6151) - Bump sass from 1.54.9 to 1.55.0 in /apps/block_scout_web/assets +- [#6173](https://github.com/blockscout/blockscout/pull/6173) - Bump core-js from 3.25.2 to 3.25.3 in /apps/block_scout_web/assets +- [#6174](https://github.com/blockscout/blockscout/pull/6174) - Bump sweetalert2 from 11.4.33 to 11.4.34 in /apps/block_scout_web/assets +- [#6175](https://github.com/blockscout/blockscout/pull/6175) - Bump luxon from 3.0.3 to 3.0.4 in /apps/block_scout_web/assets +- [#6176](https://github.com/blockscout/blockscout/pull/6176) - Bump @babel/preset-env from 7.19.1 to 7.19.3 in /apps/block_scout_web/assets +- [#6177](https://github.com/blockscout/blockscout/pull/6177) - Bump @babel/core from 7.19.1 to 7.19.3 in /apps/block_scout_web/assets +- [#6178](https://github.com/blockscout/blockscout/pull/6178) - Bump eslint from 8.23.1 to 8.24.0 in /apps/block_scout_web/assets +- [#6184](https://github.com/blockscout/blockscout/pull/6184) - Bump jest from 29.0.3 to 29.1.1 in /apps/block_scout_web/assets +- [#6186](https://github.com/blockscout/blockscout/pull/6186) - Bump jest-environment-jsdom from 29.0.3 to 29.1.1 in /apps/block_scout_web/assets +- [#6185](https://github.com/blockscout/blockscout/pull/6185) - Bump sweetalert2 from 11.4.34 to 11.4.35 in /apps/block_scout_web/assets +- [#6146](https://github.com/blockscout/blockscout/pull/6146) - Bump websocket_client from 1.3.0 to 1.5.0 +- [#6191](https://github.com/blockscout/blockscout/pull/6191) - Bump css-minimizer-webpack-plugin from 4.1.0 to 4.2.0 in /apps/block_scout_web/assets +- [#6199](https://github.com/blockscout/blockscout/pull/6199) - Bump redix from 1.1.5 to 1.2.0 +- [#6213](https://github.com/blockscout/blockscout/pull/6213) - Bump sweetalert2 from 11.4.35 to 11.4.37 in /apps/block_scout_web/assets +- [#6214](https://github.com/blockscout/blockscout/pull/6214) - Bump jest-environment-jsdom from 29.1.1 to 29.1.2 in /apps/block_scout_web/assets +- [#6215](https://github.com/blockscout/blockscout/pull/6215) - Bump postcss from 8.4.16 to 8.4.17 in /apps/block_scout_web/assets +- [#6216](https://github.com/blockscout/blockscout/pull/6216) - Bump core-js from 3.25.3 to 3.25.5 in /apps/block_scout_web/assets +- [#6217](https://github.com/blockscout/blockscout/pull/6217) - Bump jest from 29.1.1 to 29.1.2 in /apps/block_scout_web/assets +- [#6229](https://github.com/blockscout/blockscout/pull/6229) - Bump sweetalert2 from 11.4.37 to 11.4.38 in /apps/block_scout_web/assets +- [#6232](https://github.com/blockscout/blockscout/pull/6232) - Bump css-minimizer-webpack-plugin from 4.2.0 to 4.2.1 in /apps/block_scout_web/assets +- [#6230](https://github.com/blockscout/blockscout/pull/6230) - Bump sass-loader from 13.0.2 to 13.1.0 in /apps/block_scout_web/assets +- [#6251](https://github.com/blockscout/blockscout/pull/6251) - Bump sweetalert2 from 11.4.38 to 11.5.1 in /apps/block_scout_web/assets +- [#6246](https://github.com/blockscout/blockscout/pull/6246) - Bump @babel/preset-env from 7.19.3 to 7.19.4 in /apps/block_scout_web/assets +- [#6247](https://github.com/blockscout/blockscout/pull/6247) - Bump ex_abi from 0.5.14 to 0.5.15 +- [#6248](https://github.com/blockscout/blockscout/pull/6248) - Bump eslint from 8.24.0 to 8.25.0 in /apps/block_scout_web/assets +- [#6255](https://github.com/blockscout/blockscout/pull/6255) - Bump postcss from 8.4.17 to 8.4.18 in /apps/block_scout_web/assets +- [#6256](https://github.com/blockscout/blockscout/pull/6256) - Bump css-minimizer-webpack-plugin from 4.2.1 to 4.2.2 in /apps/block_scout_web/assets +- [#6258](https://github.com/blockscout/blockscout/pull/6258) - Bump jest from 29.1.2 to 29.2.0 in /apps/block_scout_web/assets +- [#6259](https://github.com/blockscout/blockscout/pull/6259) - Bump jest-environment-jsdom from 29.1.2 to 29.2.0 in /apps/block_scout_web/assets +- [#6253](https://github.com/blockscout/blockscout/pull/6253) - Bump eslint-plugin-promise from 6.0.1 to 6.1.0 in /apps/block_scout_web/assets +- [#6279](https://github.com/blockscout/blockscout/pull/6279) - Bump util from 0.12.4 to 0.12.5 in /apps/block_scout_web/assets +- [#6280](https://github.com/blockscout/blockscout/pull/6280) - Bump ex_rlp from 0.5.4 to 0.5.5 +- [#6281](https://github.com/blockscout/blockscout/pull/6281) - Bump ex_abi from 0.5.15 to 0.5.16 +- [#6283](https://github.com/blockscout/blockscout/pull/6283) - Bump spandex_datadog from 1.2.0 to 1.3.0 +- [#6282](https://github.com/blockscout/blockscout/pull/6282) - Bump sweetalert2 from 11.5.1 to 11.5.2 in /apps/block_scout_web/assets +- [#6284](https://github.com/blockscout/blockscout/pull/6284) - Bump spandex_phoenix from 1.0.6 to 1.1.0 +- [#6298](https://github.com/blockscout/blockscout/pull/6298) - Bump jest-environment-jsdom from 29.2.0 to 29.2.1 in /apps/block_scout_web/assets +- [#6297](https://github.com/blockscout/blockscout/pull/6297) - Bump jest from 29.2.0 to 29.2.1 in /apps/block_scout_web/assets +- [#6254](https://github.com/blockscout/blockscout/pull/6254) - Bump ex_doc from 0.28.5 to 0.28.6 +- [#6314](https://github.com/blockscout/blockscout/pull/6314) - Bump @babel/core from 7.19.3 to 7.19.6 in /apps/block_scout_web/assets +- [#6313](https://github.com/blockscout/blockscout/pull/6313) - Bump ex_doc from 0.28.6 to 0.29.0 +- [#6305](https://github.com/blockscout/blockscout/pull/6305) - Bump sweetalert2 from 11.5.2 to 11.6.0 in /apps/block_scout_web/assets +- [#6312](https://github.com/blockscout/blockscout/pull/6312) - Bump eslint-plugin-promise from 6.1.0 to 6.1.1 in /apps/block_scout_web/assets +- [#6318](https://github.com/blockscout/blockscout/pull/6318) - Bump spandex from 3.1.0 to 3.2.0 +- [#6335](https://github.com/blockscout/blockscout/pull/6335) - Bump eslint from 8.25.0 to 8.26.0 in /apps/block_scout_web/assets +- [#6334](https://github.com/blockscout/blockscout/pull/6334) - Bump ex_cldr_numbers from 2.27.3 to 2.28.0 +- [#6333](https://github.com/blockscout/blockscout/pull/6333) - Bump core-js from 3.25.5 to 3.26.0 in /apps/block_scout_web/assets +- [#6332](https://github.com/blockscout/blockscout/pull/6332) - Bump ex_cldr from 2.33.2 to 2.34.0 +- [#6339](https://github.com/blockscout/blockscout/pull/6339) - Bump sweetalert2 from 11.6.0 to 11.6.2 in /apps/block_scout_web/assets +- [#6330](https://github.com/blockscout/blockscout/pull/6330) - Bump ex_cldr_units from 3.14.0 to 3.15.0 +- [#6341](https://github.com/blockscout/blockscout/pull/6341) - Bump jest-environment-jsdom from 29.2.1 to 29.2.2 in /apps/block_scout_web/assets +- [#6342](https://github.com/blockscout/blockscout/pull/6342) - Bump jest from 29.2.1 to 29.2.2 in /apps/block_scout_web/assets +- [#6359](https://github.com/blockscout/blockscout/pull/6359) - Bump babel-loader from 8.2.5 to 9.0.0 in /apps/block_scout_web/assets +- [#6360](https://github.com/blockscout/blockscout/pull/6360) - Bump sweetalert2 from 11.6.2 to 11.6.4 in /apps/block_scout_web/assets +- [#6363](https://github.com/blockscout/blockscout/pull/6363) - Bump autoprefixer from 10.4.12 to 10.4.13 in /apps/block_scout_web/assets +- [#6364](https://github.com/blockscout/blockscout/pull/6364) - Bump ueberauth_auth0 from 2.0.0 to 2.1.0 +- [#6372](https://github.com/blockscout/blockscout/pull/6372) - Bump babel-loader from 9.0.0 to 9.0.1 in /apps/block_scout_web/assets +- [#6374](https://github.com/blockscout/blockscout/pull/6374) - Bump plug_cowboy from 2.5.2 to 2.6.0 +- [#6373](https://github.com/blockscout/blockscout/pull/6373) - Bump luxon from 3.0.4 to 3.1.0 in /apps/block_scout_web/assets +- [#6375](https://github.com/blockscout/blockscout/pull/6375) - Bump sweetalert2 from 11.6.4 to 11.6.5 in /apps/block_scout_web/assets +- [#6393](https://github.com/blockscout/blockscout/pull/6393) - Bump babel-loader from 9.0.1 to 9.1.0 in /apps/block_scout_web/assets +- [#6417](https://github.com/blockscout/blockscout/pull/6417) - Bump loader-utils from 2.0.2 to 2.0.3 in /apps/block_scout_web/assets +- [#6410](https://github.com/blockscout/blockscout/pull/6410) - Bump sweetalert2 from 11.6.5 to 11.6.7 in /apps/block_scout_web/assets +- [#6411](https://github.com/blockscout/blockscout/pull/6411) - Bump eslint from 8.26.0 to 8.27.0 in /apps/block_scout_web/assets +- [#6412](https://github.com/blockscout/blockscout/pull/6412) - Bump sass from 1.55.0 to 1.56.0 in /apps/block_scout_web/assets +- [#6413](https://github.com/blockscout/blockscout/pull/6413) - Bump jest-environment-jsdom from 29.2.2 to 29.3.0 in /apps/block_scout_web/assets +- [#6414](https://github.com/blockscout/blockscout/pull/6414) - Bump @babel/core from 7.19.6 to 7.20.2 in /apps/block_scout_web/assets +- [#6416](https://github.com/blockscout/blockscout/pull/6416) - Bump @babel/preset-env from 7.19.4 to 7.20.2 in /apps/block_scout_web/assets +- [#6419](https://github.com/blockscout/blockscout/pull/6419) - Bump jest from 29.2.2 to 29.3.1 in /apps/block_scout_web/assets +- [#6421](https://github.com/blockscout/blockscout/pull/6421) - Bump webpack from 5.74.0 to 5.75.0 in /apps/block_scout_web/assets +- [#6423](https://github.com/blockscout/blockscout/pull/6423) - Bump jest-environment-jsdom from 29.3.0 to 29.3.1 in /apps/block_scout_web/assets +- [#6424](https://github.com/blockscout/blockscout/pull/6424) - Bump floki from 0.33.1 to 0.34.0 +- [#6422](https://github.com/blockscout/blockscout/pull/6422) - Bump sass from 1.56.0 to 1.56.1 in /apps/block_scout_web/assets +- [#6430](https://github.com/blockscout/blockscout/pull/6430) - Bump web3 from 1.8.0 to 1.8.1 in /apps/block_scout_web/assets +- [#6431](https://github.com/blockscout/blockscout/pull/6431) - Bump sweetalert2 from 11.6.7 to 11.6.8 in /apps/block_scout_web/assets +- [#6432](https://github.com/blockscout/blockscout/pull/6432) - Bump sass-loader from 13.1.0 to 13.2.0 in /apps/block_scout_web/assets +- [#6445](https://github.com/blockscout/blockscout/pull/6445) - Bump postcss from 8.4.18 to 8.4.19 in /apps/block_scout_web/assets +- [#6446](https://github.com/blockscout/blockscout/pull/6446) - Bump core-js from 3.26.0 to 3.26.1 in /apps/block_scout_web/assets +- [#6452](https://github.com/blockscout/blockscout/pull/6452) - Bump @fortawesome/fontawesome-free from 6.2.0 to 6.2.1 in /apps/block_scout_web/assets +- [#6456](https://github.com/blockscout/blockscout/pull/6456) - Bump loader-utils from 2.0.3 to 2.0.4 in /apps/block_scout_web/assets +- [#6462](https://github.com/blockscout/blockscout/pull/6462) - Bump chartjs-adapter-luxon from 1.2.0 to 1.2.1 in /apps/block_scout_web/assets +- [#6469](https://github.com/blockscout/blockscout/pull/6469) - Bump sweetalert2 from 11.6.8 to 11.6.9 in /apps/block_scout_web/assets +- [#6471](https://github.com/blockscout/blockscout/pull/6471) - Bump mini-css-extract-plugin from 2.6.1 to 2.7.0 in /apps/block_scout_web/assets +- [#6470](https://github.com/blockscout/blockscout/pull/6470) - Bump chart.js from 3.9.1 to 4.0.1 in /apps/block_scout_web/assets +- [#6472](https://github.com/blockscout/blockscout/pull/6472) - Bump webpack-cli from 4.10.0 to 5.0.0 in /apps/block_scout_web/assets +- [#6487](https://github.com/blockscout/blockscout/pull/6487) - Bump eslint from 8.27.0 to 8.28.0 in /apps/block_scout_web/assets +- [#6488](https://github.com/blockscout/blockscout/pull/6488) - Bump ex_doc from 0.29.0 to 0.29.1 +- [#6491](https://github.com/blockscout/blockscout/pull/6491) - Bump minimatch from 3.0.4 to 3.0.8 in /apps/block_scout_web/assets +- [#6479](https://github.com/blockscout/blockscout/pull/6479) - Bump ecto_sql from 3.9.0 to 3.9.1 +- [#6486](https://github.com/blockscout/blockscout/pull/6486) - Bump sweetalert2 from 11.6.9 to 11.6.10 in /apps/block_scout_web/assets +- [#6498](https://github.com/blockscout/blockscout/pull/6498) - Bump sweetalert2 from 11.6.10 to 11.6.13 in /apps/block_scout_web/assets +- [#6506](https://github.com/blockscout/blockscout/pull/6506) - Bump web3modal from 1.9.9 to 1.9.10 in /apps/block_scout_web/assets +- [#6505](https://github.com/blockscout/blockscout/pull/6505) - Bump highlight.js from 11.6.0 to 11.7.0 in /apps/block_scout_web/assets +- [#6504](https://github.com/blockscout/blockscout/pull/6504) - Bump sweetalert2 from 11.6.13 to 11.6.14 in /apps/block_scout_web/assets +- [#6507](https://github.com/blockscout/blockscout/pull/6507) - Bump remote_ip from 1.0.0 to 1.1.0 +- [#6497](https://github.com/blockscout/blockscout/pull/6497) - Bump chartjs-adapter-luxon from 1.2.1 to 1.3.0 in /apps/block_scout_web/assets +- [#6519](https://github.com/blockscout/blockscout/pull/6519) - Bump photoswipe from 5.3.3 to 5.3.4 in /apps/block_scout_web/assets +- [#6520](https://github.com/blockscout/blockscout/pull/6520) - Bump @babel/core from 7.20.2 to 7.20.5 in /apps/block_scout_web/assets +- [#6527](https://github.com/blockscout/blockscout/pull/6527) - Bump luxon from 3.1.0 to 3.1.1 in /apps/block_scout_web/assets +- [#6526](https://github.com/blockscout/blockscout/pull/6526) - Bump mini-css-extract-plugin from 2.7.0 to 2.7.1 in /apps/block_scout_web/assets +- [#6533](https://github.com/blockscout/blockscout/pull/6533) - Bump postcss-loader from 7.0.1 to 7.0.2 in /apps/block_scout_web/assets +- [#6534](https://github.com/blockscout/blockscout/pull/6534) - Bump sweetalert2 from 11.6.14 to 11.6.15 in /apps/block_scout_web/assets +- [#6539](https://github.com/blockscout/blockscout/pull/6539) - Bump decode-uri-component from 0.2.0 to 0.2.2 in /apps/block_scout_web/assets +- [#6555](https://github.com/blockscout/blockscout/pull/6555) - Bump bignumber.js from 9.1.0 to 9.1.1 in /apps/block_scout_web/assets +- [#6557](https://github.com/blockscout/blockscout/pull/6557) - Bump webpack-cli from 5.0.0 to 5.0.1 in /apps/block_scout_web/assets +- [#6558](https://github.com/blockscout/blockscout/pull/6558) - Bump eslint from 8.28.0 to 8.29.0 in /apps/block_scout_web/assets +- [#6556](https://github.com/blockscout/blockscout/pull/6556) - Bump mini-css-extract-plugin from 2.7.1 to 2.7.2 in /apps/block_scout_web/assets +- [#6562](https://github.com/blockscout/blockscout/pull/6562) - Bump qs from 6.5.2 to 6.5.3 in /apps/block_scout_web/assets +- [#6577](https://github.com/blockscout/blockscout/pull/6577) - Bump postcss from 8.4.19 to 8.4.20 in /apps/block_scout_web/assets +- [#6578](https://github.com/blockscout/blockscout/pull/6578) - Bump sass from 1.56.1 to 1.56.2 in /apps/block_scout_web/assets + +
+ +## 4.1.8-beta + +### Features + +- [#5968](https://github.com/blockscout/blockscout/pull/5968) - Add call type in the response of txlistinternal API method +- [#5860](https://github.com/blockscout/blockscout/pull/5860) - Integrate rust verifier micro-service ([blockscout-rs/verifier](https://github.com/blockscout/blockscout-rs/tree/main/verification)) +- [#6001](https://github.com/blockscout/blockscout/pull/6001) - Add ETHEREUM_JSONRPC_DISABLE_ARCHIVE_BALANCES env var that filters requests and query node only if the block quantity is "latest" +- [#5944](https://github.com/blockscout/blockscout/pull/5944) - Add tab with state changes to transaction page + +### Fixes + +- [#6038](https://github.com/blockscout/blockscout/pull/6038) - Extend token name from string to text type +- [#6037](https://github.com/blockscout/blockscout/pull/6037) - Fix order of results in txlistinternal API endpoint +- [#6036](https://github.com/blockscout/blockscout/pull/6036) - Fix address checksum on transaction page +- [#6032](https://github.com/blockscout/blockscout/pull/6032) - Sort by address.hash column in accountlist API endpoint +- [#6017](https://github.com/blockscout/blockscout/pull/6017), [#6028](https://github.com/blockscout/blockscout/pull/6028) - Move "contract interaction" and "Add chain to MM" env vars to runtime +- [#6012](https://github.com/blockscout/blockscout/pull/6012) - Fix display of estimated addresses counter on the main page +- [#5978](https://github.com/blockscout/blockscout/pull/5978) - Allow timestamp param in the log of eth_getTransactionReceipt method +- [#5977](https://github.com/blockscout/blockscout/pull/5977) - Fix address overview.html.eex in case of nil implementation address hash +- [#5975](https://github.com/blockscout/blockscout/pull/5975) - Fix CSV export of internal transactions +- [#5957](https://github.com/blockscout/blockscout/pull/5957) - Server-side reCAPTCHA check for CSV export +- [#5954](https://github.com/blockscout/blockscout/pull/5954) - Fix ace editor appearance +- [#5942](https://github.com/blockscout/blockscout/pull/5942), [#5945](https://github.com/blockscout/blockscout/pull/5945) - Fix nightly solidity versions filtering UX +- [#5904](https://github.com/blockscout/blockscout/pull/5904) - Enhance health API endpoint: better parsing HEALTHY_BLOCKS_PERIOD and use it in the response +- [#5903](https://github.com/blockscout/blockscout/pull/5903) - Disable compile env validation +- [#5887](https://github.com/blockscout/blockscout/pull/5887) - Added missing environment variables to Makefile container params +- [#5850](https://github.com/blockscout/blockscout/pull/5850) - Fix too large postgres notifications +- [#5809](https://github.com/blockscout/blockscout/pull/5809) - Fix 404 on `/metadata` page +- [#5807](https://github.com/blockscout/blockscout/pull/5807) - Update Makefile migrate command due to release build +- [#5786](https://github.com/blockscout/blockscout/pull/5786) - Replace `current_path` with `Controller.current_full_path` in two controllers +- [#5948](https://github.com/blockscout/blockscout/pull/5948) - Fix unexpected messages in `CoinBalanceOnDemand` +- [#6013](https://github.com/blockscout/blockscout/pull/6013) - Fix ERC-1155 tokens fetching +- [#6043](https://github.com/blockscout/blockscout/pull/6043) - Fix token instance fetching +- [#6093](https://github.com/blockscout/blockscout/pull/6093) - Fix Indexer.Fetcher.TokenInstance for ERC-1155 tokens + +### Chore + +- [#5921](https://github.com/blockscout/blockscout/pull/5921) - Bump briefly from 25942fb to 1dd66ee +- [#6033](https://github.com/blockscout/blockscout/pull/6033) - Bump sass from 1.54.7 to 1.54.8 in /apps/block_scout_web/assets +- [#6046](https://github.com/blockscout/blockscout/pull/6046) - Bump credo from 1.6.6 to 1.6.7 +- [#6045](https://github.com/blockscout/blockscout/pull/6045) - Re-use _btn_copy.html for raw trace page +- [#6035](https://github.com/blockscout/blockscout/pull/6035) - Hide copy btn if no raw trace +- [#6034](https://github.com/blockscout/blockscout/pull/6034) - Suppress empty sections in supported chain dropdown +- [#5939](https://github.com/blockscout/blockscout/pull/5939) - Bump sweetalert2 from 11.4.26 to 11.4.27 in /apps/block_scout_web/assets +- [#5938](https://github.com/blockscout/blockscout/pull/5938) - Bump xss from 1.0.13 to 1.0.14 in /apps/block_scout_web/assets +- [#5743](https://github.com/blockscout/blockscout/pull/5743) - Fixing tracer not found #5729 +- [#5952](https://github.com/blockscout/blockscout/pull/5952) - Bump sweetalert2 from 11.4.27 to 11.4.28 in /apps/block_scout_web/assets +- [#5955](https://github.com/blockscout/blockscout/pull/5955) - Bump ex_doc from 0.28.4 to 0.28.5 +- [#5956](https://github.com/blockscout/blockscout/pull/5956) - Bump bcrypt_elixir from 2.3.1 to 3.0.1 +- [#5964](https://github.com/blockscout/blockscout/pull/5964) - Bump sweetalert2 from 11.4.28 to 11.4.29 in /apps/block_scout_web/assets +- [#5966](https://github.com/blockscout/blockscout/pull/5966) - Bump sass from 1.54.4 to 1.54.5 in /apps/block_scout_web/assets +- [#5967](https://github.com/blockscout/blockscout/pull/5967) - Bump @babel/core from 7.18.10 to 7.18.13 in /apps/block_scout_web/assets +- [#5973](https://github.com/blockscout/blockscout/pull/5973) - Bump prometheus from 4.9.0 to 4.9.1 +- [#5974](https://github.com/blockscout/blockscout/pull/5974) - Bump cldr_utils from 2.19.0 to 2.19.1 +- [#5884](https://github.com/blockscout/blockscout/pull/5884) - Bump nimble_csv from 1.1.0 to 1.2.0 +- [#5984](https://github.com/blockscout/blockscout/pull/5984) - Bump jest from 28.1.3 to 29.0.0 in /apps/block_scout_web/assets +- [#5983](https://github.com/blockscout/blockscout/pull/5983) - Bump core-js from 3.24.1 to 3.25.0 in /apps/block_scout_web/assets +- [#5981](https://github.com/blockscout/blockscout/pull/5981) - Bump eslint-plugin-promise from 6.0.0 to 6.0.1 in /apps/block_scout_web/assets +- [#5982](https://github.com/blockscout/blockscout/pull/5982) - Bump jest-environment-jsdom from 28.1.3 to 29.0.0 in /apps/block_scout_web/assets +- [#5987](https://github.com/blockscout/blockscout/pull/5987) - Bump jest from 29.0.0 to 29.0.1 in /apps/block_scout_web/assets +- [#5988](https://github.com/blockscout/blockscout/pull/5988) - Bump jest-environment-jsdom from 29.0.0 to 29.0.1 in /apps/block_scout_web/assets +- [#5989](https://github.com/blockscout/blockscout/pull/5989) - Bump jquery from 3.6.0 to 3.6.1 in /apps/block_scout_web/assets +- [#5990](https://github.com/blockscout/blockscout/pull/5990) - Bump web3modal from 1.9.8 to 1.9.9 in /apps/block_scout_web/assets +- [#6004](https://github.com/blockscout/blockscout/pull/6004) - Bump luxon from 3.0.1 to 3.0.3 in /apps/block_scout_web/assets +- [#6005](https://github.com/blockscout/blockscout/pull/6005) - Bump ex_cldr from 2.33.1 to 2.33.2 +- [#6006](https://github.com/blockscout/blockscout/pull/6006) - Bump eslint from 8.22.0 to 8.23.0 in /apps/block_scout_web/assets +- [#6015](https://github.com/blockscout/blockscout/pull/6015) - Bump @fortawesome/fontawesome-free from 6.1.2 to 6.2.0 in /apps/block_scout_web/assets +- [#6021](https://github.com/blockscout/blockscout/pull/6021) - Bump sass from 1.54.5 to 1.54.7 in /apps/block_scout_web/assets +- [#6018](https://github.com/blockscout/blockscout/pull/6018) - Update chromedriver version +- [#5836](https://github.com/blockscout/blockscout/pull/5836) - Bump comeonin from 4.1.2 to 5.3.3 +- [#5869](https://github.com/blockscout/blockscout/pull/5869) - Bump reduce-reducers from 0.4.3 to 1.0.4 in /apps/block_scout_web/assets +- [#5919](https://github.com/blockscout/blockscout/pull/5919) - Bump floki from 0.32.1 to 0.33.1 +- [#5930](https://github.com/blockscout/blockscout/pull/5930) - Bump eslint from 8.21.0 to 8.22.0 in /apps/block_scout_web/assets +- [#5845](https://github.com/blockscout/blockscout/pull/5845) - Bump autoprefixer from 10.4.2 to 10.4.8 in /apps/block_scout_web/assets +- [#5877](https://github.com/blockscout/blockscout/pull/5877) - Bump eslint from 8.17.0 to 8.21.0 in /apps/block_scout_web/assets +- [#5875](https://github.com/blockscout/blockscout/pull/5875) - Bump sass from 1.49.8 to 1.54.3 in /apps/block_scout_web/assets +- [#5873](https://github.com/blockscout/blockscout/pull/5873) - Bump highlight.js from 11.4.0 to 11.6.0 in /apps/block_scout_web/assets +- [#5870](https://github.com/blockscout/blockscout/pull/5870) - Bump spandex_ecto from 0.6.2 to 0.7.0 +- [#5867](https://github.com/blockscout/blockscout/pull/5867) - Bump @babel/preset-env from 7.16.11 to 7.18.10 in /apps/block_scout_web/assets +- [#5876](https://github.com/blockscout/blockscout/pull/5876) - Bump bignumber.js from 9.0.2 to 9.1.0 in /apps/block_scout_web/assets +- [#5871](https://github.com/blockscout/blockscout/pull/5871) - Bump redux from 4.1.2 to 4.2.0 in /apps/block_scout_web/assets +- [#5868](https://github.com/blockscout/blockscout/pull/5868) - Bump ex_rlp from 0.5.3 to 0.5.4 +- [#5874](https://github.com/blockscout/blockscout/pull/5874) - Bump core-js from 3.20.3 to 3.24.1 in /apps/block_scout_web/assets +- [#5882](https://github.com/blockscout/blockscout/pull/5882) - Bump math from 0.3.1 to 0.7.0 +- [#5878](https://github.com/blockscout/blockscout/pull/5878) - Bump css-minimizer-webpack-plugin from 3.4.1 to 4.0.0 in /apps/block_scout_web/assets +- [#5883](https://github.com/blockscout/blockscout/pull/5883) - Bump postgrex from 0.15.10 to 0.15.13 +- [#5885](https://github.com/blockscout/blockscout/pull/5885) - Bump hammer from 6.0.0 to 6.1.0 +- [#5893](https://github.com/blockscout/blockscout/pull/5893) - Bump prometheus from 4.8.1 to 4.9.0 +- [#5892](https://github.com/blockscout/blockscout/pull/5892) - Bump babel-loader from 8.2.3 to 8.2.5 in /apps/block_scout_web/assets +- [#5890](https://github.com/blockscout/blockscout/pull/5890) - Bump sweetalert2 from 11.3.10 to 11.4.26 in /apps/block_scout_web/assets +- [#5889](https://github.com/blockscout/blockscout/pull/5889) - Bump sass from 1.54.3 to 1.54.4 in /apps/block_scout_web/assets +- [#5894](https://github.com/blockscout/blockscout/pull/5894) - Bump jest from 27.4.7 to 28.1.3 in /apps/block_scout_web/assets +- [#5865](https://github.com/blockscout/blockscout/pull/5865) - Bump timex from 3.7.1 to 3.7.9 +- [#5872](https://github.com/blockscout/blockscout/pull/5872) - Bump benchee from 0.13.2 to 0.99.0 +- [#5895](https://github.com/blockscout/blockscout/pull/5895) - Bump wallaby from 0.29.1 to 0.30.1 +- [#5905](https://github.com/blockscout/blockscout/pull/5905) - Bump absinthe from 1.6.5 to 1.6.8 +- [#5881](https://github.com/blockscout/blockscout/pull/5881) - Bump dataloader from 1.0.9 to 1.0.10 +- [#5909](https://github.com/blockscout/blockscout/pull/5909) - Bump junit_formatter from 3.3.0 to 3.3.1 +- [#5912](https://github.com/blockscout/blockscout/pull/5912) - Bump credo from 1.6.4 to 1.6.6 +- [#5911](https://github.com/blockscout/blockscout/pull/5911) - Bump absinthe_relay from 1.5.1 to 1.5.2 +- [#5915](https://github.com/blockscout/blockscout/pull/5915) - Bump flow from 0.15.0 to 1.2.0 +- [#5916](https://github.com/blockscout/blockscout/pull/5916) - Bump dialyxir from 1.1.0 to 1.2.0 +- [#5910](https://github.com/blockscout/blockscout/pull/5910) - Bump benchee from 0.99.0 to 1.1.0 +- [#5917](https://github.com/blockscout/blockscout/pull/5917) - Bump bypass from 1.0.0 to 2.1.0 +- [#5920](https://github.com/blockscout/blockscout/pull/5920) - Bump spandex_datadog from 1.1.0 to 1.2.0 +- [#5918](https://github.com/blockscout/blockscout/pull/5918) - Bump logger_file_backend from 0.0.12 to 0.0.13 +- [#5863](https://github.com/blockscout/blockscout/pull/5863) - Update Poison hex package +- [#5861](https://github.com/blockscout/blockscout/pull/5861) - Add cache for docker build +- [#5859](https://github.com/blockscout/blockscout/pull/5859) - Update ex_cldr hex packages +- [#5858](https://github.com/blockscout/blockscout/pull/5858) - Update CHANGELOG; revert update of css-loader; rename fontawesome icons selectors +- [#5811](https://github.com/blockscout/blockscout/pull/5811) - Bump chartjs-adapter-luxon from 1.1.0 to 1.2.0 in /apps/block_scout_web/assets +- [#5814](https://github.com/blockscout/blockscout/pull/5814) - Bump webpack from 5.69.1 to 5.74.0 in /apps/block_scout_web/assets +- [#5812](https://github.com/blockscout/blockscout/pull/5812) - Bump mini-css-extract-plugin from 2.5.3 to 2.6.1 in /apps/block_scout_web/assets +- [#5819](https://github.com/blockscout/blockscout/pull/5819) - Bump xss from 1.0.10 to 1.0.13 in /apps/block_scout_web/assets +- [#5818](https://github.com/blockscout/blockscout/pull/5818) - Bump @fortawesome/fontawesome-free from 6.0.0-beta3 to 6.1.2 in /apps/block_scout_web/assets +- [#5821](https://github.com/blockscout/blockscout/pull/5821) - Bump spandex from 3.0.3 to 3.1.0 +- [#5830](https://github.com/blockscout/blockscout/pull/5830) - Bump spandex_phoenix from 1.0.5 to 1.0.6 +- [#5825](https://github.com/blockscout/blockscout/pull/5825) - Bump postcss from 8.4.6 to 8.4.16 in /apps/block_scout_web/assets +- [#5816](https://github.com/blockscout/blockscout/pull/5816) - Bump webpack-cli from 4.9.2 to 4.10.0 in /apps/block_scout_web/assets +- [#5822](https://github.com/blockscout/blockscout/pull/5822) - Bump chart.js from 3.7.0 to 3.9.1 in /apps/block_scout_web/assets +- [#5829](https://github.com/blockscout/blockscout/pull/5829) - Bump mox from 0.5.2 to 1.0.2 +- [#5823](https://github.com/blockscout/blockscout/pull/5823) - Bump luxon from 2.4.0 to 3.0.1 in /apps/block_scout_web/assets +- [#5837](https://github.com/blockscout/blockscout/pull/5837) - Bump @walletconnect/web3-provider from 1.7.8 to 1.8.0 in /apps/block_scout_web/assets +- [#5840](https://github.com/blockscout/blockscout/pull/5840) - Bump web3modal from 1.9.5 to 1.9.8 in /apps/block_scout_web/assets +- [#5842](https://github.com/blockscout/blockscout/pull/5842) - Bump copy-webpack-plugin from 10.2.1 to 11.0.0 in /apps/block_scout_web/assets +- [#5835](https://github.com/blockscout/blockscout/pull/5835) - Bump tesla from 1.3.3 to 1.4.4 +- [#5841](https://github.com/blockscout/blockscout/pull/5841) - Bump sass-loader from 12.6.0 to 13.0.2 in /apps/block_scout_web/assets +- [#5844](https://github.com/blockscout/blockscout/pull/5844) - Bump postcss-loader from 6.2.1 to 7.0.1 in /apps/block_scout_web/assets +- [#5838](https://github.com/blockscout/blockscout/pull/5838) - Bump path-parser from 4.2.0 to 6.1.0 in /apps/block_scout_web/assets +- [#5843](https://github.com/blockscout/blockscout/pull/5843) - Bump @tarekraafat/autocomplete.js from 10.2.6 to 10.2.7 in /apps/block_scout_web/assets +- [#5834](https://github.com/blockscout/blockscout/pull/5834) - Bump clipboard from 2.0.9 to 2.0.11 in /apps/block_scout_web/assets +- [#5827](https://github.com/blockscout/blockscout/pull/5827) - Bump @babel/core from 7.16.12 to 7.18.10 in /apps/block_scout_web/assets +- [#5851](https://github.com/blockscout/blockscout/pull/5851) - Bump exvcr from 0.13.2 to 0.13.3 +- [#5824](https://github.com/blockscout/blockscout/pull/5824) - Bump ex_json_schema from 0.6.2 to 0.9.1 +- [#5849](https://github.com/blockscout/blockscout/pull/5849) - Bump gettext 0.18.2 -> 0.20.0 +- [#5806](https://github.com/blockscout/blockscout/pull/5806) - Update target Postgres version in Docker: 13 -> 14 + +## 4.1.7-beta + +### Features + +- [#5783](https://github.com/blockscout/blockscout/pull/5783) - Allow to setup multiple ranges of blocks to index + +### Fixes + +- [#5799](https://github.com/blockscout/blockscout/pull/5799) - Fix address_tokens_usd_sum function +- [#5798](https://github.com/blockscout/blockscout/pull/5798) - Copy explorer node_modules to result image +- [#5797](https://github.com/blockscout/blockscout/pull/5797) - Fix flickering token tooltip + +### Chore + +- [#5796](https://github.com/blockscout/blockscout/pull/5796) - Add job for e2e tests on every push to master + fix job "Merge 'master' to specific branch after release" + +## 4.1.6-beta + +### Features + +- [#5739](https://github.com/blockscout/blockscout/pull/5739) - Erigon archive node support +- [#5732](https://github.com/blockscout/blockscout/pull/5732) - Manage testnet label (right to the navbar logo) +- [#5699](https://github.com/blockscout/blockscout/pull/5699) - Switch to basic (non-pro) API endpoint for Coingecko requests, if API key is not provided +- [#5542](https://github.com/blockscout/blockscout/pull/5542) - Add `jq` in docker image +- [#5345](https://github.com/blockscout/blockscout/pull/5345) - Graphql: add user-selected ordering to transactions for address query + +### Fixes + +- [#5768](https://github.com/blockscout/blockscout/pull/5768) - Outstanding rows limit for missing blocks query (catchup fetcher) +- [#5737](https://github.com/blockscout/blockscout/pull/5737), [#5772](https://github.com/blockscout/blockscout/pull/5772) - Fix double requests; Fix token balances dropdown view +- [#5723](https://github.com/blockscout/blockscout/pull/5723) - Add nil clause for Data.to_string/1 +- [#5714](https://github.com/blockscout/blockscout/pull/5714) - Add clause for EthereumJSONRPC.Transaction.elixir_to_params/1 when gas_price is missing in the response +- [#5697](https://github.com/blockscout/blockscout/pull/5697) - Gas price oracle: ignore gas price rounding for values less than 0.01 +- [#5690](https://github.com/blockscout/blockscout/pull/5690) - Allow special characters for password in DB URL parser +- [#5778](https://github.com/blockscout/blockscout/pull/5778) - Allow hyphen in database name + +### Chore + +- [#5787](https://github.com/blockscout/blockscout/pull/5787) - Add job for merging master to specific branch after release +- [#5788](https://github.com/blockscout/blockscout/pull/5788) - Update Docker image on every push to master branch +- [#5736](https://github.com/blockscout/blockscout/pull/5736) - Remove obsolete network selector +- [#5730](https://github.com/blockscout/blockscout/pull/5730) - Add primary keys for DB tables where they do not exist +- [#5703](https://github.com/blockscout/blockscout/pull/5703) - Remove bridged tokens functionality from Blockscout core +- [#5700](https://github.com/blockscout/blockscout/pull/5700) - Remove Staking dapp logic from Blockscout core +- [#5696](https://github.com/blockscout/blockscout/pull/5696) - Update .tool-versions +- [#5695](https://github.com/blockscout/blockscout/pull/5695) - Decimal hex package update 1.9 -> 2.0 +- [#5684](https://github.com/blockscout/blockscout/pull/5684) - Block import timings logs + +## 4.1.5-beta + +### Features + +- [#5667](https://github.com/blockscout/blockscout/pull/5667) - Address page: scroll to selected tab's data + +### Fixes + +- [#5680](https://github.com/blockscout/blockscout/pull/5680) - Fix broken token icons; Disable animation in lists; Fix doubled requests for some pages +- [#5671](https://github.com/blockscout/blockscout/pull/5671) - Fix double requests for token exchange rates; Disable fetching `btc_value` by default (add `EXCHANGE_RATES_FETCH_BTC_VALUE` env variable); Add `CACHE_EXCHANGE_RATES_PERIOD` env variable +- [#5676](https://github.com/blockscout/blockscout/pull/5676) - Fix wrong miner address shown for post EIP-1559 block for clique network + +### Chore + +- [#5679](https://github.com/blockscout/blockscout/pull/5679) - Optimize query in fetch_min_missing_block_cache function +- [#5674](https://github.com/blockscout/blockscout/pull/5674) - Disable token holder refreshing +- [#5661](https://github.com/blockscout/blockscout/pull/5661) - Fixes yaml syntax for boolean env variables in docker compose + +## 4.1.4-beta + +### Features + +- [#5656](https://github.com/blockscout/blockscout/pull/5656) - Gas price oracle +- [#5613](https://github.com/blockscout/blockscout/pull/5613) - Exchange rates CoinMarketCap source module +- [#5588](https://github.com/blockscout/blockscout/pull/5588) - Add broadcasting of coin balance +- [#5560](https://github.com/blockscout/blockscout/pull/5560) - Manual fetch beneficiaries +- [#5479](https://github.com/blockscout/blockscout/pull/5479) - Remake of solidity verifier module; Verification UX improvements +- [#5540](https://github.com/blockscout/blockscout/pull/5540) - Tx page: scroll to selected tab's data + +### Fixes + +- [#5647](https://github.com/blockscout/blockscout/pull/5647) - Add handling for invalid Sourcify response +- [#5635](https://github.com/blockscout/blockscout/pull/5635) - Set CoinGecko source in exchange_rates_source function fix in case of token_bridge +- [#5629](https://github.com/blockscout/blockscout/pull/5629) - Fix empty coin balance for empty address +- [#5612](https://github.com/blockscout/blockscout/pull/5612) - Fix token transfers order +- [#5626](https://github.com/blockscout/blockscout/pull/5626) - Fix vyper compiler versions order +- [#5603](https://github.com/blockscout/blockscout/pull/5603) - Fix failing verification attempts +- [#5598](https://github.com/blockscout/blockscout/pull/5598) - Fix token dropdown +- [#5592](https://github.com/blockscout/blockscout/pull/5592) - Burn fees for legacy transactions +- [#5568](https://github.com/blockscout/blockscout/pull/5568) - Add regexp for ipfs checking +- [#5567](https://github.com/blockscout/blockscout/pull/5567) - Sanitize token name and symbol before insert into DB, display in the application +- [#5564](https://github.com/blockscout/blockscout/pull/5564) - Add fallback clauses to `string_to_..._hash` functions +- [#5538](https://github.com/blockscout/blockscout/pull/5538) - Fix internal transaction's tile bug + +### Chore + +- [#5660](https://github.com/blockscout/blockscout/pull/5660) - Display txs count chart by default, disable price chart by default, add chart titles +- [#5659](https://github.com/blockscout/blockscout/pull/5659) - Use chartjs-adapter-luxon instead chartjs-adapter-moment for charts +- [#5651](https://github.com/blockscout/blockscout/pull/5651), [#5657](https://github.com/blockscout/blockscout/pull/5657) - Gnosis chain rebranded theme and generalization of chart legend colors definition +- [#5640](https://github.com/blockscout/blockscout/pull/5640) - Clean up and fix tests, reduce amount of warnings +- [#5625](https://github.com/blockscout/blockscout/pull/5625) - Get rid of some redirects to checksummed address url +- [#5623](https://github.com/blockscout/blockscout/pull/5623) - Allow hyphen in DB password +- [#5543](https://github.com/blockscout/blockscout/pull/5543) - Increase max_restarts to 1_000 (from 3 by default) for explorer, block_scout_web supervisors +- [#5536](https://github.com/blockscout/blockscout/pull/5536) - NPM audit fix + +## 4.1.3-beta ### Features + +- [#5515](https://github.com/blockscout/blockscout/pull/5515) - Integrate ace editor to display contract sources +- [#5505](https://github.com/blockscout/blockscout/pull/5505) - Manage debug_traceTransaction JSON RPC method timeout +- [#5491](https://github.com/blockscout/blockscout/pull/5491) - Sequential blocks broadcast on the main page - [#5312](https://github.com/blockscout/blockscout/pull/5312) - Add OpenZeppelin proxy storage slot - [#5302](https://github.com/blockscout/blockscout/pull/5302) - Add specific tx receipt fields for the GoQuorum client -- [#5268](https://github.com/blockscout/blockscout/pull/5268) - Contract names display improvement +- [#5268](https://github.com/blockscout/blockscout/pull/5268), [#5313](https://github.com/blockscout/blockscout/pull/5313) - Contract names display improvement ### Fixes + +- [#5528](https://github.com/blockscout/blockscout/pull/5528) - Token balances fetcher retry +- [#5524](https://github.com/blockscout/blockscout/pull/5524) - ContractState module resistance to unresponsive archive node +- [#5513](https://github.com/blockscout/blockscout/pull/5513) - Do not fill pending blocks ops with block numbers below TRACE_FIRST_BLOCK +- [#5508](https://github.com/blockscout/blockscout/pull/5508) - Hide indexing banner if we fetched internal transactions from TRACE_FIRST_BLOCK +- [#5504](https://github.com/blockscout/blockscout/pull/5504) - Extend TRACE_FIRST_BLOCK env var to geth variant +- [#5488](https://github.com/blockscout/blockscout/pull/5488) - Split long contract output to multiple lines +- [#5487](https://github.com/blockscout/blockscout/pull/5487) - Fix array displaying in decoded constructor args +- [#5482](https://github.com/blockscout/blockscout/pull/5482) - Fix for querying of the contract read functions +- [#5455](https://github.com/blockscout/blockscout/pull/5455) - Fix unverified_smart_contract function: add md5 of bytecode to the changeset +- [#5454](https://github.com/blockscout/blockscout/pull/5454) - Docker: Fix the qemu-x86_64 signal 11 error on Apple Silicon - [#5443](https://github.com/blockscout/blockscout/pull/5443) - Geth: display tx revert reason +- [#5420](https://github.com/blockscout/blockscout/pull/5420) - Deduplicate addresses and coin balances before inserting to the DB - [#5416](https://github.com/blockscout/blockscout/pull/5416) - Fix getsourcecode for EOA addresses +- [#5413](https://github.com/blockscout/blockscout/pull/5413) - Fix params encoding for read contracts methods - [#5411](https://github.com/blockscout/blockscout/pull/5411) - Fix character_not_in_repertoire error for tx revert reason - [#5410](https://github.com/blockscout/blockscout/pull/5410) - Handle exited realtime fetcher - [#5383](https://github.com/blockscout/blockscout/pull/5383) - Fix reload transactions button @@ -28,6 +4709,12 @@ - [#5239](https://github.com/blockscout/blockscout/pull/5239) - Add accounting for block rewards in `getblockreward` api method ### Chore + +- [#5506](https://github.com/blockscout/blockscout/pull/5506) - Refactor config files +- [#5480](https://github.com/blockscout/blockscout/pull/5480) - Remove duplicate of balances_params_to_address_params function +- [#5473](https://github.com/blockscout/blockscout/pull/5473) - Refactor daily coin balances fetcher +- [#5458](https://github.com/blockscout/blockscout/pull/5458) - Decrease min safe polling period for realtime fetcher +- [#5456](https://github.com/blockscout/blockscout/pull/5456) - Ignore arbitrary block details fields for custom Ethereum clients - [#5450](https://github.com/blockscout/blockscout/pull/5450) - Logging error in publishing of smart-contract - [#5433](https://github.com/blockscout/blockscout/pull/5433) - Caching modules refactoring - [#5419](https://github.com/blockscout/blockscout/pull/5419) - Add check if address exists for some api methods @@ -52,10 +4739,10 @@ - [#5260](https://github.com/blockscout/blockscout/pull/5260) - Makefile release task to prerelease and release task - [#5082](https://github.com/blockscout/blockscout/pull/5082) - Elixir 1.12 -> 1.13 - ## 4.1.2-beta ### Features + - [#5232](https://github.com/blockscout/blockscout/pull/5232) - Contract Read Page: Add functions overloading support - [#5220](https://github.com/blockscout/blockscout/pull/5220) - Add info about proxy contracts to api methods response - [#5200](https://github.com/blockscout/blockscout/pull/5200) - Docker-compose configuration @@ -64,6 +4751,7 @@ - [#4690](https://github.com/blockscout/blockscout/pull/4690) - Improve pagination: introduce pagination with random access to pages; Integrate it to the Transactions List page ### Fixes + - [#5248](https://github.com/blockscout/blockscout/pull/5248) - Speedup query for getting verified smart-contract bytecode twin - [#5241](https://github.com/blockscout/blockscout/pull/5241) - Fix DB hostname Regex pattern - [#5216](https://github.com/blockscout/blockscout/pull/5216) - Add token-transfers-toggle.js to the `block_transaction/index.html.eex` @@ -82,6 +4770,7 @@ - [#4862](https://github.com/blockscout/blockscout/pull/4862) - Fix internal transactions pagination ### Chore + - [#5230](https://github.com/blockscout/blockscout/pull/5230) - Contract verification forms refactoring - [#5227](https://github.com/blockscout/blockscout/pull/5227) - Major update of css-loader npm package - [#5226](https://github.com/blockscout/blockscout/pull/5226) - Update mini-css-extract-plugin, css-minimizer-webpack-plugin packages @@ -101,14 +4790,15 @@ - [#5119](https://github.com/blockscout/blockscout/pull/5119) - Inventory controller refactoring - [#5118](https://github.com/blockscout/blockscout/pull/5118) - Fix top navigation template - ## 4.1.1-beta ### Features + - [#5090](https://github.com/blockscout/blockscout/pull/5090) - Allotted rate limit by IP - [#5080](https://github.com/blockscout/blockscout/pull/5080) - Allotted rate limit by a global API key ### Fixes + - [#5085](https://github.com/blockscout/blockscout/pull/5085) - Fix wallet style - [#5088](https://github.com/blockscout/blockscout/pull/5088) - Store address transactions/token transfers in the DB - [#5071](https://github.com/blockscout/blockscout/pull/5071) - Fix write page contract tuple input @@ -118,27 +4808,29 @@ - [#5051](https://github.com/blockscout/blockscout/pull/5051) - Fix 500 response when ABI method was parsed as nil ### Chore + - [#5092](https://github.com/blockscout/blockscout/pull/5092) - Resolve vulnerable follow-redirects npm dep in ./apps/explorer - [#5091](https://github.com/blockscout/blockscout/pull/5091) - Refactor search page template - [#5081](https://github.com/blockscout/blockscout/pull/5081) - Add internal transactions fetcher disabled? config parameter - [#5063](https://github.com/blockscout/blockscout/pull/5063) - Resolve moderate NPM vulnerabilities with npm audit tool - [#5053](https://github.com/blockscout/blockscout/pull/5053) - Update ex_keccak lib - ## 4.1.0-beta ### Features + - [#5030](https://github.com/blockscout/blockscout/pull/5030) - API rate limiting -- [#4924](https://github.com/blockscout/blockscout/pull/4924) - Add daily bytecode verifcation to prevent metamorphic contracts vulnerablity +- [#4924](https://github.com/blockscout/blockscout/pull/4924) - Add daily bytecode verification to prevent metamorphic contracts vulnerability - [#4908](https://github.com/blockscout/blockscout/pull/4908) - Add verification via standard JSON input - [#5004](https://github.com/blockscout/blockscout/pull/5004) - Add ability to set up a separate DB endpoint for the API endpoints - [#4989](https://github.com/blockscout/blockscout/pull/4989), [#4991](https://github.com/blockscout/blockscout/pull/4991) - Bridged tokens list API endpoint - [#4931](https://github.com/blockscout/blockscout/pull/4931) - Web3 modal with Wallet Connect for Write contract page and Staking Dapp ### Fixes + - [#5045](https://github.com/blockscout/blockscout/pull/5045) - Contracts interaction improvements -- [#5032](https://github.com/blockscout/blockscout/pull/5032) - Fix token transfer csv export -- [#5020](https://github.com/blockscout/blockscout/pull/5020) - Token instance image display imrovement +- [#5032](https://github.com/blockscout/blockscout/pull/5032) - Fix token transfer csv export +- [#5020](https://github.com/blockscout/blockscout/pull/5020) - Token instance image display improvement - [#5019](https://github.com/blockscout/blockscout/pull/5019) - Fix fetch_last_token_balance function termination - [#5011](https://github.com/blockscout/blockscout/pull/5011) - Fix `0x0` implementation address - [#5008](https://github.com/blockscout/blockscout/pull/5008) - Extend decimals cap in format_according_to_decimals up to 24 @@ -152,9 +4844,10 @@ - [#4945](https://github.com/blockscout/blockscout/pull/4945) - Fix `Verify & Publish` button link - [#4938](https://github.com/blockscout/blockscout/pull/4938) - Fix displaying of nested arrays for contracts read - [#4888](https://github.com/blockscout/blockscout/pull/4888) - Fix fetch_top_tokens method: add nulls last for token holders desc order -- [#4867](https://github.com/blockscout/blockscout/pull/4867) - Fix bug in quering contracts method and improve contracts interactions +- [#4867](https://github.com/blockscout/blockscout/pull/4867) - Fix bug in querying contracts method and improve contracts interactions ### Chore + - [#5047](https://github.com/blockscout/blockscout/pull/5047) - At contract write use wei precision - [#5023](https://github.com/blockscout/blockscout/pull/5023) - Capability to leave an empty logo - [#5018](https://github.com/blockscout/blockscout/pull/5018) - Resolve npm vulnerabilities via npm audix fix @@ -163,10 +4856,10 @@ - [#4983](https://github.com/blockscout/blockscout/pull/4983), [#5038](https://github.com/blockscout/blockscout/pull/5038) - Fix contract verification tests - [#4861](https://github.com/blockscout/blockscout/pull/4861) - Add separate column for token icons - ## 4.0.0-beta ### Features + - [#4807](https://github.com/blockscout/blockscout/pull/4807) - Added support for BeaconProxy pattern - [#4777](https://github.com/blockscout/blockscout/pull/4777), [#4791](https://github.com/blockscout/blockscout/pull/4791), [#4799](https://github.com/blockscout/blockscout/pull/4799), [#4847](https://github.com/blockscout/blockscout/pull/4847) - Added decoding revert reason - [#4776](https://github.com/blockscout/blockscout/pull/4776) - Added view for unsuccessfully fetched values from read functions @@ -174,7 +4867,7 @@ - [#4739](https://github.com/blockscout/blockscout/pull/4739) - Improve logs and inputs decoding - [#4747](https://github.com/blockscout/blockscout/pull/4747) - Advanced CSV export - [#4745](https://github.com/blockscout/blockscout/pull/4745) - Vyper contracts verification -- [#4699](https://github.com/blockscout/blockscout/pull/4699), [#4793](https://github.com/blockscout/blockscout/pull/4793), [#4820](https://github.com/blockscout/blockscout/pull/4820), [#4827](https://github.com/blockscout/blockscout/pull/4827) - Address page facelifting +- [#4699](https://github.com/blockscout/blockscout/pull/4699), [#4793](https://github.com/blockscout/blockscout/pull/4793), [#4820](https://github.com/blockscout/blockscout/pull/4820), [#4827](https://github.com/blockscout/blockscout/pull/4827) - Address page face lifting - [#4667](https://github.com/blockscout/blockscout/pull/4667) - Transaction Page: Add expand/collapse button for long contract method data - [#4641](https://github.com/blockscout/blockscout/pull/4641), [#4733](https://github.com/blockscout/blockscout/pull/4733) - Improve Read Contract page logic - [#4660](https://github.com/blockscout/blockscout/pull/4660) - Save Sourcify path instead of filename @@ -190,6 +4883,7 @@ - [#4579](https://github.com/blockscout/blockscout/pull/4579) - Write contract page: Resize inputs; Improve multiplier selector ### Fixes + - [#4857](https://github.com/blockscout/blockscout/pull/4857) - Fix `tx/raw-trace` Internal Server Error - [#4854](https://github.com/blockscout/blockscout/pull/4854) - Fix infinite gas usage count loading - [#4853](https://github.com/blockscout/blockscout/pull/4853) - Allow custom optimizations runs for contract verifications via API @@ -233,6 +4927,7 @@ - [#4582](https://github.com/blockscout/blockscout/pull/4582) - Fix NaN input on write contract page ### Chore + - [#4876](https://github.com/blockscout/blockscout/pull/4876) - Add missing columns updates when INSERT ... ON CONFLICT DO UPDATE ... happens - [#4872](https://github.com/blockscout/blockscout/pull/4872) - Set explicit ascending order by hash in acquire transactions query of internal transactions import - [#4871](https://github.com/blockscout/blockscout/pull/4871) - Remove cumulative gas used update duplicate @@ -253,21 +4948,22 @@ - [#4646](https://github.com/blockscout/blockscout/pull/4646) - Transaction page: Rename burned to burnt - [#4611](https://github.com/blockscout/blockscout/pull/4611) - Ability to hide miner in block views - ## 3.7.3-beta ### Features + - [#4569](https://github.com/blockscout/blockscout/pull/4569) - Smart-Contract: remove comment with the submission date - [#4568](https://github.com/blockscout/blockscout/pull/4568) - TX page: Token transfer and minting section improvements -- [#4540](https://github.com/blockscout/blockscout/pull/4540) - Allign copy buttons for `Block Details` and `Transaction Details` pages +- [#4540](https://github.com/blockscout/blockscout/pull/4540) - Align copy buttons for `Block Details` and `Transaction Details` pages - [#4528](https://github.com/blockscout/blockscout/pull/4528) - Block Details page: rework view - [#4531](https://github.com/blockscout/blockscout/pull/4531) - Add Arbitrum support - [#4524](https://github.com/blockscout/blockscout/pull/4524) - Add index position of transaction in the block - [#4489](https://github.com/blockscout/blockscout/pull/4489) - Search results page -- [#4475](https://github.com/blockscout/blockscout/pull/4475) - Tx page facelifting -- [#4452](https://github.com/blockscout/blockscout/pull/4452) - Add names for smart-conrtact's function response +- [#4475](https://github.com/blockscout/blockscout/pull/4475) - Tx page face lifting +- [#4452](https://github.com/blockscout/blockscout/pull/4452) - Add names for smart-contract's function response ### Fixes + - [#4553](https://github.com/blockscout/blockscout/pull/4553) - Indexer performance update: skip genesis block in requesting of trace_block API endpoint - [#4544](https://github.com/blockscout/blockscout/pull/4544) - Indexer performance update: Add skip_metadata flag for token if indexer failed to get any of [name, symbol, decimals, totalSupply] - [#4542](https://github.com/blockscout/blockscout/pull/4542) - Indexer performance update: Deduplicate tokens in the indexer token transfers transformer @@ -280,30 +4976,32 @@ - [#4488](https://github.com/blockscout/blockscout/pull/4488) - Tx page: handle empty to_address - [#4483](https://github.com/blockscout/blockscout/pull/4483) - Fix copy-paste typo in `token_transfers_counter.ex` - [#4473](https://github.com/blockscout/blockscout/pull/4473), [#4481](https://github.com/blockscout/blockscout/pull/4481) - Search autocomplete: fix for address/block/tx hash -- [#4472](https://github.com/blockscout/blockscout/pull/4472) - Search autocomplete: fix Cannot read property toLowerCase of undefined +- [#4472](https://github.com/blockscout/blockscout/pull/4472) - Search autocomplete: fix Cannot read property toLowerCase of undefined - [#4456](https://github.com/blockscout/blockscout/pull/4456) - URL encoding for NFT media files URLs - [#4453](https://github.com/blockscout/blockscout/pull/4453) - Unescape characters for string output type in the contract response - [#4401](https://github.com/blockscout/blockscout/pull/4401) - Fix displaying of token holders with the same amount ### Chore + - [#4550](https://github.com/blockscout/blockscout/pull/4550) - Update con_cache package to 1.0 -- [#4523](https://github.com/blockscout/blockscout/pull/4523) - Change order of transations in block's view +- [#4523](https://github.com/blockscout/blockscout/pull/4523) - Change order of transactions in block's view - [#4521](https://github.com/blockscout/blockscout/pull/4521) - Rewrite transaction page tooltips - [#4516](https://github.com/blockscout/blockscout/pull/4516) - Add DB migrations step into Docker start script - [#4497](https://github.com/blockscout/blockscout/pull/4497) - Handle error in fetch_validators_list method - [#4444](https://github.com/blockscout/blockscout/pull/4444) - Main page performance cumulative update - [#4439](https://github.com/blockscout/blockscout/pull/4439), - [#4465](https://github.com/blockscout/blockscout/pull/4465) - Fix revert response in contract's output - ## 3.7.2-beta ### Features + - [#4424](https://github.com/blockscout/blockscout/pull/4424) - Display search results categories - [#4423](https://github.com/blockscout/blockscout/pull/4423) - Add creation time of contract in the results of the search - [#4391](https://github.com/blockscout/blockscout/pull/4391) - Add batched transactions on the `address/{addressHash}/transactions` page - [#4353](https://github.com/blockscout/blockscout/pull/4353) - Added live-reload on the token holders page ### Fixes + - [#4437](https://github.com/blockscout/blockscout/pull/4437) - Fix `PendingTransactionsSanitizer` for non-consensus blocks - [#4430](https://github.com/blockscout/blockscout/pull/4430) - Fix current token balance on-demand fetcher - [#4429](https://github.com/blockscout/blockscout/pull/4429), [#4431](https://github.com/blockscout/blockscout/pull/4431) - Fix 500 response on `/tokens/{addressHash}/token-holders?type=JSON` when total supply is zero @@ -311,10 +5009,11 @@ - [#4418](https://github.com/blockscout/blockscout/pull/4418) - Fix empty search results for the full-word search criteria - [#4406](https://github.com/blockscout/blockscout/pull/4406) - Fix internal server error on the validator's txs page - [#4360](https://github.com/blockscout/blockscout/pull/4360) - Fix false-pending transactions in reorg blocks -- [#4388](https://github.com/blockscout/blockscout/pull/4388) - Fix internal server error on contract page for insctances without sourcify envs +- [#4388](https://github.com/blockscout/blockscout/pull/4388) - Fix internal server error on contract page for instances without sourcify envs - [#4385](https://github.com/blockscout/blockscout/pull/4385) - Fix html template for transaction's input; Add copy text for tuples ### Chore + - [#4400](https://github.com/blockscout/blockscout/pull/4400) - Add "Token ID" label onto `tokens/.../instance/.../token-transfers` page - [#4398](https://github.com/blockscout/blockscout/pull/4398) - Speed up the transactions loading on the front-end - [#4384](https://github.com/blockscout/blockscout/pull/4384) - Fix Elixir version in `.tool-versions` @@ -322,27 +5021,28 @@ - [#4371](https://github.com/blockscout/blockscout/pull/4371) - Place search outside of burger in mobile view - [#4355](https://github.com/blockscout/blockscout/pull/4355) - Do not redirect to 404 page with empty string in the search field - ## 3.7.1-beta ### Features + - [#4331](https://github.com/blockscout/blockscout/pull/4331) - Added support for partially verified contracts via [Sourcify](https://sourcify.dev) - [#4323](https://github.com/blockscout/blockscout/pull/4323) - Renamed Contract Byte Code, add Contract Creation Code on contract's page - [#4312](https://github.com/blockscout/blockscout/pull/4312) - Display pending transactions on address page - [#4299](https://github.com/blockscout/blockscout/pull/4299) - Added [Sourcify](https://sourcify.dev) verification API endpoint - [#4267](https://github.com/blockscout/blockscout/pull/4267) - Extend verification through [Sourcify](https://sourcify.dev) smart-contract verification: fetch smart contract metadata from Sourcify repo if it has been already verified there - [#4241](https://github.com/blockscout/blockscout/pull/4241) - Reload transactions on the main page without reloading of the whole page -- [#4218](https://github.com/blockscout/blockscout/pull/4218) - Hide long arrays in smart-contracts +- [#4218](https://github.com/blockscout/blockscout/pull/4218) - Hide long arrays in smart-contracts - [#4205](https://github.com/blockscout/blockscout/pull/4205) - Total transactions fees per day API endpoint - [#4158](https://github.com/blockscout/blockscout/pull/4158) - Calculate total fee per day - [#4067](https://github.com/blockscout/blockscout/pull/4067) - Display LP tokens USD value and custom metadata in tokens dropdown at address page ### Fixes + - [#4351](https://github.com/blockscout/blockscout/pull/4351) - Support effectiveGasPrice property in tx receipt (Geth specific) - [#4346](https://github.com/blockscout/blockscout/pull/4346) - Fix internal server error on raw-trace transaction page - [#4345](https://github.com/blockscout/blockscout/pull/4345) - Fix bug on validator's address transactions page(Support effectiveGasPrice property in receipt (geth specific)) - [#4342](https://github.com/blockscout/blockscout/pull/4342) - Remove dropped/replaced txs from address transactions page -- [#4320](https://github.com/blockscout/blockscout/pull/4320) - Fix absence of imported smart-contracts' source code in `getsourcecode` API method +- [#4320](https://github.com/blockscout/blockscout/pull/4320) - Fix absence of imported smart-contracts' source code in `getsourcecode` API method - [#4274](https://github.com/blockscout/blockscout/pull/4302) - Fix search token-autocomplete - [#4316](https://github.com/blockscout/blockscout/pull/4316) - Fix `/decompiled-contracts` bug - [#4310](https://github.com/blockscout/blockscout/pull/4310) - Fix logo URL redirection, set font-family defaults for chart.js @@ -352,7 +5052,7 @@ - [#4295](https://github.com/blockscout/blockscout/pull/4295) - Mobile view fix: transaction tile tx hash overflow - [#4294](https://github.com/blockscout/blockscout/pull/4294) - User wont be able to open verification pages for verified smart-contract - [#4240](https://github.com/blockscout/blockscout/pull/4240) - `[]` is accepted in write contract page -- [#4236](https://github.com/blockscout/blockscout/pull/4236), [#4242](https://github.com/blockscout/blockscout/pull/4242) - Fix typo, constructor instead of contructor +- [#4236](https://github.com/blockscout/blockscout/pull/4236), [#4242](https://github.com/blockscout/blockscout/pull/4242) - Fix typo, constructor instead of constructor - [#4167](https://github.com/blockscout/blockscout/pull/4167) - Deduplicate block numbers in acquire_blocks function - [#4149](https://github.com/blockscout/blockscout/pull/4149) - Exclude smart_contract_additional_sources from JSON encoding in address schema - [#4137](https://github.com/blockscout/blockscout/pull/4137) - Get token balance query improvement @@ -363,6 +5063,7 @@ - [#3888](https://github.com/blockscout/blockscout/pull/3888) - EIP-1967 contract proxy pattern detection fix ### Chore + - [#4315](https://github.com/blockscout/blockscout/pull/4315) - Replace node_modules/ with ~ in app.scss - [#4314](https://github.com/blockscout/blockscout/pull/4314) - Set infinite timeout for fetch_min_missing_block_cache method DB query - [#4300](https://github.com/blockscout/blockscout/pull/4300) - Remove clear_build.sh script @@ -378,10 +5079,10 @@ - [#3893](https://github.com/blockscout/blockscout/pull/3893) - Add left/right paddings in tx tile - [#3870](https://github.com/blockscout/blockscout/pull/3870) - Manage token balance on-demand fetcher threshold via env var - ## 3.7.0-beta ### Features + - [#3858](https://github.com/blockscout/blockscout/pull/3858) - Integration with Sourcify - [#3834](https://github.com/blockscout/blockscout/pull/3834) - Method name in tx tile - [#3792](https://github.com/blockscout/blockscout/pull/3792) - Cancel pending transaction @@ -390,6 +5091,7 @@ - [#3750](https://github.com/blockscout/blockscout/pull/3750) - getblocknobytime block module API endpoint ### Fixes + - [#3835](https://github.com/blockscout/blockscout/pull/3835) - Fix getTokenHolders API endpoint pagination - [#3787](https://github.com/blockscout/blockscout/pull/3787) - Improve tokens list elements display - [#3785](https://github.com/blockscout/blockscout/pull/3785) - Fix for write contract functionality: false and 0 boolean inputs are parsed as true @@ -399,6 +5101,7 @@ - [#3748](https://github.com/blockscout/blockscout/pull/3748) - Skip null topics in eth_getLogs API endpoint ### Chore + - [#3831](https://github.com/blockscout/blockscout/pull/3831) - Process type field in eth_getTransactionReceipt response - [#3802](https://github.com/blockscout/blockscout/pull/3802) - Extend Become a Candidate popup in Staking DApp - [#3801](https://github.com/blockscout/blockscout/pull/3801) - Poison package update @@ -406,10 +5109,10 @@ - [#3789](https://github.com/blockscout/blockscout/pull/3789) - Update repo organization - [#3788](https://github.com/blockscout/blockscout/pull/3788) - Update fontawesome NPM package - ## 3.6.0-beta ### Features + - [#3743](https://github.com/blockscout/blockscout/pull/3743) - Minimal proxy pattern support (EIP-1167) - [#3722](https://github.com/blockscout/blockscout/pull/3722) - Allow double quotes for (u)int arrays inputs during contract interaction - [#3694](https://github.com/blockscout/blockscout/pull/3694) - LP tokens total liquidity @@ -424,6 +5127,7 @@ - [#3564](https://github.com/blockscout/blockscout/pull/3564) - Staking welcome message ### Fixes + - [#3742](https://github.com/blockscout/blockscout/pull/3742) - Fix Sushiswap LP tokens custom metadata fetcher: bytes(n) symbol and name support - [#3741](https://github.com/blockscout/blockscout/pull/3741) - Contract reader fix when there are multiple input params including an array type - [#3735](https://github.com/blockscout/blockscout/pull/3735) - Token balance on demand fetcher memory leak fix @@ -451,6 +5155,7 @@ - [#3577](https://github.com/blockscout/blockscout/pull/3577) - Eliminate GraphiQL page XSS attack ### Chore + - [#3745](https://github.com/blockscout/blockscout/pull/3745) - Refactor and optimize Staking DApp - [#3744](https://github.com/blockscout/blockscout/pull/3744) - Update Mix packages: timex, hackney, tzdata certifi - [#3736](https://github.com/blockscout/blockscout/pull/3736), [#3739](https://github.com/blockscout/blockscout/pull/3739) - Contract writer: Fix sending a transaction with tuple input type @@ -474,31 +5179,33 @@ - [#3618](https://github.com/blockscout/blockscout/pull/3618) - Contracts verification up to 10 libraries - [#3616](https://github.com/blockscout/blockscout/pull/3616) - POSDAO refactoring: use zero address instead of staker address for certain cases - [#3612](https://github.com/blockscout/blockscout/pull/3612) - POSDAO refactoring: use 'getDelegatorPools' getter instead of 'getStakerPools' in Staking DApp -- [#3585](https://github.com/blockscout/blockscout/pull/3585) - Add autoswitching from eth_subscribe to eth_blockNumber in Staking DApp +- [#3585](https://github.com/blockscout/blockscout/pull/3585) - Add auto switching from eth_subscribe to eth_blockNumber in Staking DApp - [#3574](https://github.com/blockscout/blockscout/pull/3574) - Correct UNI token price - [#3569](https://github.com/blockscout/blockscout/pull/3569) - Allow re-define cache period vars at runtime - [#3567](https://github.com/blockscout/blockscout/pull/3567) - Force to show filter at the page where filtered items list is empty - [#3565](https://github.com/blockscout/blockscout/pull/3565) - Staking dapp: unhealthy state alert message - ## 3.5.1-beta ### Features + - [#3558](https://github.com/blockscout/blockscout/pull/3558) - Focus to search field with a forward slash key -- [#3541](https://github.com/blockscout/blockscout/pull/3541) - Staking dapp stats: total number of delegators, total staked amount +- [#3541](https://github.com/blockscout/blockscout/pull/3541) - Staking dapp stats: total number of delegators, total staked amount - [#3540](https://github.com/blockscout/blockscout/pull/3540) - Apply DarkForest custom theme to NFT instances ### Fixes + - [#3551](https://github.com/blockscout/blockscout/pull/3551) - Fix contract's method's output of tuple type ### Chore + - [#3557](https://github.com/blockscout/blockscout/pull/3557) - Single Staking menu - [#3540](https://github.com/blockscout/blockscout/pull/3540), [#3545](https://github.com/blockscout/blockscout/pull/3545) - Support different versions of DarkForest (0.4 - 0.5) - ## 3.5.0-beta ### Features + - [#3536](https://github.com/blockscout/blockscout/pull/3536) - Revert reason in the result of contract's method call - [#3532](https://github.com/blockscout/blockscout/pull/3532) - Contract interaction: an easy setting of precision for integer input - [#3531](https://github.com/blockscout/blockscout/pull/3531) - Allow double quotes in input data of contract methods @@ -509,6 +5216,7 @@ - [#3462](https://github.com/blockscout/blockscout/pull/3462) - Display price for bridged tokens ### Fixes + - [#3535](https://github.com/blockscout/blockscout/pull/3535) - Improve speed of tokens dropdown loading at owner address page - [#3530](https://github.com/blockscout/blockscout/pull/3530) - Allow trailing/leading whitespaces for inputs for contract read methods - [#3526](https://github.com/blockscout/blockscout/pull/3526) - Order staking pools @@ -534,6 +5242,7 @@ - [#3457](https://github.com/blockscout/blockscout/pull/3457) - Fix doubled token transfer on block's page if block has reorg ### Chore + - [#3500](https://github.com/blockscout/blockscout/pull/3500) - Update solc version in explorer folder - [#3498](https://github.com/blockscout/blockscout/pull/3498) - Make Staking DApp work with transferAndCall function - [#3496](https://github.com/blockscout/blockscout/pull/3496) - Rollback websocket_client module to 1.3.0 @@ -546,10 +5255,10 @@ - [#3467](https://github.com/blockscout/blockscout/pull/3467) - NodeJS engine upgrade up to 14 - [#3460](https://github.com/blockscout/blockscout/pull/3460) - Update Staking DApp scripts due to MetaMask breaking changes - ## 3.4.0-beta ### Features + - [#3442](https://github.com/blockscout/blockscout/pull/3442) - Constructor arguments autodetection in API verify endpoint - [#3435](https://github.com/blockscout/blockscout/pull/3435) - Token transfers counter cache - [#3420](https://github.com/blockscout/blockscout/pull/3420) - Enable read/write proxy tabs for Gnosis safe proxy contract @@ -565,6 +5274,7 @@ - [#3330](https://github.com/blockscout/blockscout/pull/3330) - Caching of address transactions counter, remove query 10_000 rows limit ### Fixes + - [#3449](https://github.com/blockscout/blockscout/pull/3449) - Correct avg time calculation - [#3443](https://github.com/blockscout/blockscout/pull/3443) - Improve blocks handling in Staking DApp - [#3440](https://github.com/blockscout/blockscout/pull/3440) - Rewrite missing blocks range query @@ -599,6 +5309,7 @@ - [#3335](https://github.com/blockscout/blockscout/pull/3335) - MarketCap calculation: check that ETS tables exist before inserting new data or lookup from the table ### Chore + - [#5240](https://github.com/blockscout/blockscout/pull/5240) - Managing invalidation of address coin balance cache - [#3450](https://github.com/blockscout/blockscout/pull/3450) - Replace window.web3 with window.ethereum - [#3446](https://github.com/blockscout/blockscout/pull/3446), [#3448](https://github.com/blockscout/blockscout/pull/3448) - Set infinity timeout and increase cache invalidation period for counters @@ -615,10 +5326,10 @@ - [#3366](https://github.com/blockscout/blockscout/pull/3366) - Stabilize tests execution in Github Actions CI - [#3343](https://github.com/blockscout/blockscout/pull/3343) - Make (Bridged) Tokens' list page's header more compact - ## 3.3.3-beta ### Features + - [#3320](https://github.com/blockscout/blockscout/pull/3320) - Bridged tokens from AMB extensions support - [#3311](https://github.com/blockscout/blockscout/pull/3311) - List of addresses with restricted access option - [#3293](https://github.com/blockscout/blockscout/pull/3293) - Composite market cap for xDai: TokenBridge + OmniBridge @@ -631,6 +5342,7 @@ - [#3261](https://github.com/blockscout/blockscout/pull/3261) - Bridged tokens table ### Fixes + - [#3323](https://github.com/blockscout/blockscout/pull/3323) - Fix logs list API endpoint response - [#3319](https://github.com/blockscout/blockscout/pull/3319) - Eliminate horizontal scroll - [#3314](https://github.com/blockscout/blockscout/pull/3314) - Handle nil values from response of CoinGecko price API @@ -649,6 +5361,7 @@ - [#3256](https://github.com/blockscout/blockscout/pull/3256) - Fix for invisible validator address at block page and wrong alert text color at xDai ### Chore + - [#3327](https://github.com/blockscout/blockscout/pull/3327) - Handle various indexer fetchers errors in setup with non-archive node - [#3325](https://github.com/blockscout/blockscout/pull/3325) - Dark theme improvements - [#3316](https://github.com/blockscout/blockscout/pull/3316), [#3317](https://github.com/blockscout/blockscout/pull/3317) - xDai smile logo @@ -660,10 +5373,10 @@ - [#3260](https://github.com/blockscout/blockscout/pull/3260) - Update NPM dependencies to fix known vulnerabilities - [#3258](https://github.com/blockscout/blockscout/pull/3258) - Token transfer: check that block exists before retrieving timestamp - ## 3.3.2-beta ### Features + - [#3252](https://github.com/blockscout/blockscout/pull/3252) - Gas price at the main page - [#3239](https://github.com/blockscout/blockscout/pull/3239) - Hide address page tabs if no items - [#3236](https://github.com/blockscout/blockscout/pull/3236) - Easy verification of contracts which has verified twins (the same bytecode) @@ -671,10 +5384,11 @@ - [#3224](https://github.com/blockscout/blockscout/pull/3224) - Top tokens page ### Fixes + - [#3249](https://github.com/blockscout/blockscout/pull/3249) - Fix incorrect ABI decoding of address in tuple output - [#3237](https://github.com/blockscout/blockscout/pull/3237) - Refine contract method signature detection for read/write feature -- [#3235](https://github.com/blockscout/blockscout/pull/3235) - Fix coin supply api edpoint -- [#3233](https://github.com/blockscout/blockscout/pull/3233) - Fix for the contract verifiaction for solc 0.5 family with experimental features enabled +- [#3235](https://github.com/blockscout/blockscout/pull/3235) - Fix coin supply api endpoint +- [#3233](https://github.com/blockscout/blockscout/pull/3233) - Fix for the contract verification for solc 0.5 family with experimental features enabled - [#3231](https://github.com/blockscout/blockscout/pull/3231) - Improve search: unlimited number of searching results - [#3231](https://github.com/blockscout/blockscout/pull/3231) - Improve search: allow search with space - [#3231](https://github.com/blockscout/blockscout/pull/3231) - Improve search: order by token holders in descending order and token/contract name is ascending order @@ -682,15 +5396,16 @@ - [#3220](https://github.com/blockscout/blockscout/pull/3220) - Allow interaction with navbar menu at block-not-found page ### Chore + - [#3326](https://github.com/blockscout/blockscout/pull/3326) - Chart smooth lines - [#3250](https://github.com/blockscout/blockscout/pull/3250) - Eliminate occurrences of obsolete env variable ETHEREUM_JSONRPC_JSON_RPC_TRANSPORT -- [#3240](https://github.com/blockscout/blockscout/pull/3240), [#3251](https://github.com/blockscout/blockscout/pull/3251) - various CSS imroving +- [#3240](https://github.com/blockscout/blockscout/pull/3240), [#3251](https://github.com/blockscout/blockscout/pull/3251) - various CSS improving - [f3a720](https://github.com/blockscout/blockscout/commit/2dd909c10a79b0bf4b7541a486be114152f3a720) - Make wobserver optional - ## 3.3.1-beta ### Features + - [#3216](https://github.com/blockscout/blockscout/pull/3216) - Display new token transfers at token page and address page without refreshing the page - [#3199](https://github.com/blockscout/blockscout/pull/3199) - Show compilation error at contract verification - [#3193](https://github.com/blockscout/blockscout/pull/3193) - Raw trace copy button @@ -698,6 +5413,7 @@ - [#3145](https://github.com/blockscout/blockscout/pull/3145) - Pending txs per address API endpoint ### Fixes + - [#3219](https://github.com/blockscout/blockscout/pull/3219) - Fix revert reason message detection - [#3215](https://github.com/blockscout/blockscout/pull/3215) - Coveralls in CI through Github Actions - [#3214](https://github.com/blockscout/blockscout/pull/3214) - Fix current token balances fetcher @@ -715,6 +5431,7 @@ - [#3178](https://github.com/blockscout/blockscout/pull/3178) - Fix unavailable navbar menu when read/write proxy tab is active ### Chore + - [#3212](https://github.com/blockscout/blockscout/pull/3212) - GitHub actions CI config - [#3210](https://github.com/blockscout/blockscout/pull/3210) - Update Phoenix up to 1.4.17 - [#3206](https://github.com/blockscout/blockscout/pull/3206) - Update Elixir version: 1.10.2 -> 1.10.3 @@ -722,10 +5439,10 @@ - [#3180](https://github.com/blockscout/blockscout/pull/3180) - Return correct status in verify API endpoint if contract verified - [#3180](https://github.com/blockscout/blockscout/pull/3180) - Remove Kovan from the list of default chains - ## 3.3.0-beta ### Features + - [#3174](https://github.com/blockscout/blockscout/pull/3174) - EIP-1967 support: transparent proxy pattern - [#3173](https://github.com/blockscout/blockscout/pull/3173) - Display implementation address at read/write proxy tabs - [#3171](https://github.com/blockscout/blockscout/pull/3171) - Import accounts/contracts/balances from Geth genesis.json @@ -734,15 +5451,16 @@ - [#3157](https://github.com/blockscout/blockscout/pull/3157) - Read methods of implementation on proxy contract ### Fixes + - [#3168](https://github.com/blockscout/blockscout/pull/3168) - Eliminate internal server error at /accounts page with token-bridge type of supply and inexistent bridge contracts - [#3169](https://github.com/blockscout/blockscout/pull/3169) - Fix for verification of contracts defined in genesis block ### Chore - ## 3.2.0-beta ### Features + - [#3154](https://github.com/blockscout/blockscout/pull/3154) - Support of Hyperledger Besu client - [#3153](https://github.com/blockscout/blockscout/pull/3153) - Proxy contracts: logs decoding using implementation ABI - [#3153](https://github.com/blockscout/blockscout/pull/3153) - Proxy contracts: methods decoding using implementation ABI @@ -751,15 +5469,17 @@ ### Fixes ### Chore -- [#3152](https://github.com/blockscout/blockscout/pull/3152) - Fix contract compilation tests for old versions of compiler +- [#3152](https://github.com/blockscout/blockscout/pull/3152) - Fix contract compilation tests for old versions of compiler ## 3.1.3-beta ### Features + - [#3125](https://github.com/blockscout/blockscout/pull/3125) - Availability to configure a number of days to consider at coin balance history chart via environment variable ### Fixes + - [#3146](https://github.com/blockscout/blockscout/pull/3146) - Fix coin balance history page: order of items, fix if no balance changes - [#3142](https://github.com/blockscout/blockscout/pull/3142) - Speed-up last coin balance timestamp query (coin balance history page performance improvement) - [#3140](https://github.com/blockscout/blockscout/pull/3140) - Fix performance of the balance changing history list loading @@ -779,14 +5499,15 @@ - [#3106](https://github.com/blockscout/blockscout/pull/3106), [#3115](https://github.com/blockscout/blockscout/pull/3115) - Fix verification of contracts, created from factory (from internal transaction) ### Chore + - [#3137](https://github.com/blockscout/blockscout/pull/3137) - RSK Papyrus Release v2.0.1 hardfork: cumulativeDifficulty - [#3134](https://github.com/blockscout/blockscout/pull/3134) - Get last value of fetched coinsupply API endpoint from DB if cache is empty - [#3124](https://github.com/blockscout/blockscout/pull/3124) - Display upper border for tx speed if the value cannot be calculated - ## 3.1.2-beta ### Features + - [#3089](https://github.com/blockscout/blockscout/pull/3089) - CoinGecko API coin id environment variable - [#3069](https://github.com/blockscout/blockscout/pull/3069) - Make a link to address page on decoded constructor argument of address type - [#3067](https://github.com/blockscout/blockscout/pull/3067) - Show proper title of the tile or container for token burnings/mintings instead of "Token Transfer" @@ -794,6 +5515,7 @@ - [#3065](https://github.com/blockscout/blockscout/pull/3065) - Transactions history chart ### Fixes + - [#3097](https://github.com/blockscout/blockscout/pull/3097) - Fix contract reader decoding - [#3095](https://github.com/blockscout/blockscout/pull/3095) - Fix constructor arguments decoding - [#3092](https://github.com/blockscout/blockscout/pull/3092) - Contract verification: constructor arguments search search refinement @@ -806,35 +5528,38 @@ - [#2756](https://github.com/blockscout/blockscout/pull/2756) - Improve subquery joins ### Chore + - [#3100](https://github.com/blockscout/blockscout/pull/3100) - Update npm packages - [#3099](https://github.com/blockscout/blockscout/pull/3099) - Remove pending txs cache - [#3093](https://github.com/blockscout/blockscout/pull/3093) - Extend list of env vars for Docker setup - [#3084](https://github.com/blockscout/blockscout/pull/3084) - Bump Elixir version 1.10.2 - [#3079](https://github.com/blockscout/blockscout/pull/3079) - Extend optionality of websockets to Geth - ## 3.1.1-beta ### Features + - [#3058](https://github.com/blockscout/blockscout/pull/3058) - Searching by verified contract name ### Fixes + - [#3053](https://github.com/blockscout/blockscout/pull/3053) - Fix ABI decoding in contracts methods, logs (migrate to ex_abi 0.3.0) - [#3044](https://github.com/blockscout/blockscout/pull/3044) - Prevent division by zero on /accounts page - [#3043](https://github.com/blockscout/blockscout/pull/3043) - Extract host name for split couple of indexer and web app - [#3042](https://github.com/blockscout/blockscout/pull/3042) - Speedup pending txs list query - [#2944](https://github.com/blockscout/blockscout/pull/2944), [#3046](https://github.com/blockscout/blockscout/pull/3046) - Split js logic into multiple files - ## 3.1.0-beta ### Features + - [#3013](https://github.com/blockscout/blockscout/pull/3013), [#3026](https://github.com/blockscout/blockscout/pull/3026), [#3031](https://github.com/blockscout/blockscout/pull/3031) - Raw trace of transaction on-demand - [#3000](https://github.com/blockscout/blockscout/pull/3000) - Get rid of storing of first trace for all types of transactions for Parity variant - [#2875](https://github.com/blockscout/blockscout/pull/2875) - Save contract code from Parity genesis file - [#2834](https://github.com/blockscout/blockscout/pull/2834), [#3009](https://github.com/blockscout/blockscout/pull/3009), [#3014](https://github.com/blockscout/blockscout/pull/3014), [#3033](https://github.com/blockscout/blockscout/pull/3033) - always redirect to checksummed hash ### Fixes + - [#3037](https://github.com/blockscout/blockscout/pull/3037) - Make buttons color at verification page consistent - [#3034](https://github.com/blockscout/blockscout/pull/3034) - Support stateMutability=view to define reading functions in smart-contracts - [#3029](https://github.com/blockscout/blockscout/pull/3029) - Fix transactions and blocks appearance on the main page @@ -858,20 +5583,22 @@ - [#2883](https://github.com/blockscout/blockscout/pull/2883) - Fix long contracts names ### Chore + - [#3032](https://github.com/blockscout/blockscout/pull/3032) - Remove indexing status alert for Ganache variant - [#3030](https://github.com/blockscout/blockscout/pull/3030) - Remove default websockets URL from config - [#2995](https://github.com/blockscout/blockscout/pull/2995) - Support API_PATH env var in Docker file - ## 3.0.0-beta ### Features + - [#2835](https://github.com/blockscout/blockscout/pull/2835), [#2871](https://github.com/blockscout/blockscout/pull/2871), [#2872](https://github.com/blockscout/blockscout/pull/2872), [#2886](https://github.com/blockscout/blockscout/pull/2886), [#2925](https://github.com/blockscout/blockscout/pull/2925), [#2936](https://github.com/blockscout/blockscout/pull/2936), [#2949](https://github.com/blockscout/blockscout/pull/2949), [#2940](https://github.com/blockscout/blockscout/pull/2940), [#2958](https://github.com/blockscout/blockscout/pull/2958) - Add "block_hash" to logs, token_transfers and internal transactions and "pending blocks operations" approach - [#2975](https://github.com/blockscout/blockscout/pull/2975) - Refine UX of contracts verification - [#2926](https://github.com/blockscout/blockscout/pull/2926) - API endpoint: sum balances except burnt address - [#2918](https://github.com/blockscout/blockscout/pull/2918) - Add tokenID for tokentx API action explicitly ### Fixes + - [#2969](https://github.com/blockscout/blockscout/pull/2969) - Fix contract constructor require msg appearance in constructor arguments encoded view - [#2964](https://github.com/blockscout/blockscout/pull/2964) - Fix bug in skipping of constructor arguments in contract verification - [#2961](https://github.com/blockscout/blockscout/pull/2961) - Add a guard that addresses is enum in `values` function in `read contract` page @@ -895,6 +5622,7 @@ - [#2887](https://github.com/blockscout/blockscout/pull/2887) - increase chart loading speed ### Chore + - [#2959](https://github.com/blockscout/blockscout/pull/2959) - Remove logs from test folder too in the cleaning script - [#2954](https://github.com/blockscout/blockscout/pull/2954) - Upgrade absinthe and ecto deps - [#2947](https://github.com/blockscout/blockscout/pull/2947) - Upgrade Circle CI postgres Docker image @@ -903,10 +5631,10 @@ - [#2896](https://github.com/blockscout/blockscout/pull/2896) - Disable Parity websockets tests - [#2873](https://github.com/blockscout/blockscout/pull/2873) - bump elixir to 1.9.4 - ## 2.1.1-beta ### Features + - [#2862](https://github.com/blockscout/blockscout/pull/2862) - Coin total supply from DB API endpoint - [#2857](https://github.com/blockscout/blockscout/pull/2857) - Extend getsourcecode API view with new output fields - [#2822](https://github.com/blockscout/blockscout/pull/2822) - Estimated address count on the main page, if cache is empty @@ -917,6 +5645,7 @@ - [#2449](https://github.com/blockscout/blockscout/pull/2449) - add ability to send notification events through postgres notify ### Fixes + - [#2864](https://github.com/blockscout/blockscout/pull/2864) - add token instance metadata type check - [#2855](https://github.com/blockscout/blockscout/pull/2855) - Fix favicons load - [#2854](https://github.com/blockscout/blockscout/pull/2854) - Fix all npm vulnerabilities @@ -935,6 +5664,7 @@ - [#2690](https://github.com/blockscout/blockscout/pull/2690) - do not stich json rpc config into module for net version cache ### Chore + - [#2878](https://github.com/blockscout/blockscout/pull/2878) - Decrease loaders showing delay on the main page - [#2859](https://github.com/blockscout/blockscout/pull/2859) - Add eth_blockNumber API endpoint to eth_rpc section - [#2846](https://github.com/blockscout/blockscout/pull/2846) - Remove networks images preload @@ -948,10 +5678,10 @@ - [#2805](https://github.com/blockscout/blockscout/pull/2805) - Update supported chains default option - [#2801](https://github.com/blockscout/blockscout/pull/2801) - remove unused clause in address_to_unique_tokens query - ## 2.1.0-beta ### Features + - [#2776](https://github.com/blockscout/blockscout/pull/2776) - fetch token counters async - [#2772](https://github.com/blockscout/blockscout/pull/2772) - add token instance images to the token inventory tab - [#2733](https://github.com/blockscout/blockscout/pull/2733) - Add cache for first page of uncles @@ -970,6 +5700,7 @@ - [#2470](https://github.com/blockscout/blockscout/pull/2470) - Allow Realtime Fetcher to wait for small skips ### Fixes + - [#4325](https://github.com/blockscout/blockscout/pull/4325) - Fix search on `/tokens` page - [#2793](https://github.com/blockscout/blockscout/pull/2793) - Hide "We are indexing this chain right now. Some of the counts may be inaccurate" banner if no txs in blockchain - [#2779](https://github.com/blockscout/blockscout/pull/2779) - fix fetching `latin1` encoded data @@ -1011,6 +5742,7 @@ fixed menu hovers in dark mode desktop view - [#2738](https://github.com/blockscout/blockscout/pull/2738) - do not fail block `internal_transactions_indexed_at` field update ### Chore + - [#2797](https://github.com/blockscout/blockscout/pull/2797) - Return old style menu - [#2796](https://github.com/blockscout/blockscout/pull/2796) - Optimize all images with ImageOptim - [#2794](https://github.com/blockscout/blockscout/pull/2786) - update hosted versions in readme @@ -1024,21 +5756,22 @@ fixed menu hovers in dark mode desktop view - [#2723](https://github.com/blockscout/blockscout/pull/2723) - get rid of ex_json_schema warnings - [#2740](https://github.com/blockscout/blockscout/pull/2740) - add verify contract rpc doc - ## 2.0.4-beta ### Features + - [#2636](https://github.com/blockscout/blockscout/pull/2636) - Execute all address' transactions page queries in parallel - [#2596](https://github.com/blockscout/blockscout/pull/2596) - support AuRa's empty step reward type - [#2588](https://github.com/blockscout/blockscout/pull/2588) - add verification submission comment - [#2505](https://github.com/blockscout/blockscout/pull/2505) - support POA Network emission rewards -- [#2581](https://github.com/blockscout/blockscout/pull/2581) - Add generic Map-like Cache behaviour and implementation +- [#2581](https://github.com/blockscout/blockscout/pull/2581) - Add generic Map-like Cache behavior and implementation - [#2561](https://github.com/blockscout/blockscout/pull/2561) - Add token's type to the response of tokenlist method - [#2555](https://github.com/blockscout/blockscout/pull/2555) - find and show decoding candidates for logs - [#2499](https://github.com/blockscout/blockscout/pull/2499) - import emission reward ranges -- [#2497](https://github.com/blockscout/blockscout/pull/2497) - Add generic Ordered Cache behaviour and implementation +- [#2497](https://github.com/blockscout/blockscout/pull/2497) - Add generic Ordered Cache behavior and implementation ### Fixes + - [#2659](https://github.com/blockscout/blockscout/pull/2659) - Multipurpose front-end part update - [#2640](https://github.com/blockscout/blockscout/pull/2640) - SVG network icons - [#2635](https://github.com/blockscout/blockscout/pull/2635) - optimize ERC721 inventory query @@ -1060,21 +5793,22 @@ fixed menu hovers in dark mode desktop view - [#2468](https://github.com/blockscout/blockscout/pull/2468) - fix confirmations for non consensus blocks ### Chore + - [#2662](https://github.com/blockscout/blockscout/pull/2662) - fetch coin gecko id based on the coin symbol - [#2646](https://github.com/blockscout/blockscout/pull/2646) - Added Xerom to list of Additional Chains using BlockScout - [#2634](https://github.com/blockscout/blockscout/pull/2634) - add Lukso to networks dropdown - [#2617](https://github.com/blockscout/blockscout/pull/2617) - skip cache update if there are no blocks inserted - [#2611](https://github.com/blockscout/blockscout/pull/2611) - fix js dependency vulnerabilities - [#2594](https://github.com/blockscout/blockscout/pull/2594) - do not start genesis data fetching periodically -- [#2590](https://github.com/blockscout/blockscout/pull/2590) - restore backward compatablity with old releases +- [#2590](https://github.com/blockscout/blockscout/pull/2590) - restore backward compatibility with old releases - [#2577](https://github.com/blockscout/blockscout/pull/2577) - Need recompile column in the env vars table - [#2574](https://github.com/blockscout/blockscout/pull/2574) - limit request body in json rpc error - [#2566](https://github.com/blockscout/blockscout/pull/2566) - upgrade absinthe phoenix - ## 2.0.3-beta ### Features + - [#2433](https://github.com/blockscout/blockscout/pull/2433) - Add a functionality to try Eth RPC methods in the documentation - [#2529](https://github.com/blockscout/blockscout/pull/2529) - show both eth value and token transfers on transaction overview page - [#2376](https://github.com/blockscout/blockscout/pull/2376) - Split API and WebApp routes @@ -1084,12 +5818,13 @@ fixed menu hovers in dark mode desktop view - [#2403](https://github.com/blockscout/blockscout/pull/2403) - Return gasPrice field at the result of gettxinfo method ### Fixes + - [#2562](https://github.com/blockscout/blockscout/pull/2562) - Fix dark theme flickering - [#2560](https://github.com/blockscout/blockscout/pull/2560) - fix slash before not empty path in docs - [#2559](https://github.com/blockscout/blockscout/pull/2559) - fix rsk total supply for empty exchange rate - [#2553](https://github.com/blockscout/blockscout/pull/2553) - Dark theme import to the end of sass - [#2550](https://github.com/blockscout/blockscout/pull/2550) - correctly encode decimal values for frontend -- [#2549](https://github.com/blockscout/blockscout/pull/2549) - Fix wrong colour of tooltip +- [#2549](https://github.com/blockscout/blockscout/pull/2549) - Fix wrong color of tooltip - [#2548](https://github.com/blockscout/blockscout/pull/2548) - CSS preload support in Firefox - [#2547](https://github.com/blockscout/blockscout/pull/2547) - do not show eth value if it's zero on the transaction overview page - [#2543](https://github.com/blockscout/blockscout/pull/2543) - do not hide search input during logs search @@ -1117,6 +5852,7 @@ fixed menu hovers in dark mode desktop view - [#2551](https://github.com/blockscout/blockscout/pull/2551) - Correctly handle dynamically created Bootstrap tooltips ### Chore + - [#2554](https://github.com/blockscout/blockscout/pull/2554) - remove extra slash for endpoint url in docs - [#2552](https://github.com/blockscout/blockscout/pull/2552) - remove brackets for token holders percentage - [#2507](https://github.com/blockscout/blockscout/pull/2507) - update minor version of ecto, ex_machina, phoenix_live_reload @@ -1133,10 +5869,10 @@ fixed menu hovers in dark mode desktop view - [#2402](https://github.com/blockscout/blockscout/pull/2402) - bump otp version to 22.0 - [#2373](https://github.com/blockscout/blockscout/pull/2373) - Add script to validate internal_transactions constraint for large DBs - ## 2.0.2-beta ### Features + - [#2412](https://github.com/blockscout/blockscout/pull/2412) - dark theme - [#2399](https://github.com/blockscout/blockscout/pull/2399) - decode verified smart contract's logs - [#2391](https://github.com/blockscout/blockscout/pull/2391) - Controllers Improvements @@ -1149,6 +5885,7 @@ fixed menu hovers in dark mode desktop view - [#2324](https://github.com/blockscout/blockscout/pull/2324) - set timeout for loading message on the main page ### Fixes + - [#2421](https://github.com/blockscout/blockscout/pull/2421) - Fix hiding of loader for txs on the main page - [#2420](https://github.com/blockscout/blockscout/pull/2420) - fetch data from cache in healthy endpoint - [#2416](https://github.com/blockscout/blockscout/pull/2416) - Fix "page not found" handling in the router @@ -1176,6 +5913,7 @@ fixed menu hovers in dark mode desktop view - [#2326](https://github.com/blockscout/blockscout/pull/2326) - fix nested constructor arguments ### Chore + - [#2422](https://github.com/blockscout/blockscout/pull/2422) - check if address_id is binary in token_transfers_csv endpoint - [#2418](https://github.com/blockscout/blockscout/pull/2418) - Remove parentheses in market cap percentage - [#2401](https://github.com/blockscout/blockscout/pull/2401) - add ENV vars to manage updating period of average block time and market history cache @@ -1190,10 +5928,10 @@ fixed menu hovers in dark mode desktop view - [#2293](https://github.com/blockscout/blockscout/pull/2293) - remove request idle timeout configuration - [#2255](https://github.com/blockscout/blockscout/pull/2255) - bump elixir version to 1.9.0 - ## 2.0.1-beta ### Features + - [#2283](https://github.com/blockscout/blockscout/pull/2283) - Add transactions cache - [#2182](https://github.com/blockscout/blockscout/pull/2182) - add market history cache - [#2109](https://github.com/blockscout/blockscout/pull/2109) - use bigger updates instead of `Multi` transactions in BlocksTransactionsMismatch @@ -1208,6 +5946,7 @@ fixed menu hovers in dark mode desktop view - [#2266](https://github.com/blockscout/blockscout/pull/2266) - allow excluding uncles from average block time calculation ### Fixes + - [#2290](https://github.com/blockscout/blockscout/pull/2290) - Add eth_get_balance.json to AddressView's render - [#2286](https://github.com/blockscout/blockscout/pull/2286) - banner stats issues on sm resolutions, transactions title issue - [#2284](https://github.com/blockscout/blockscout/pull/2284) - add 404 status for not existing pages @@ -1273,15 +6012,16 @@ fixed menu hovers in dark mode desktop view - [#2276](https://github.com/blockscout/blockscout/pull/2276) - remove port in docs ### Chore -- [#2127](https://github.com/blockscout/blockscout/pull/2127) - use previouse chromedriver version + +- [#2127](https://github.com/blockscout/blockscout/pull/2127) - use previous chromedriver version - [#2118](https://github.com/blockscout/blockscout/pull/2118) - show only the last decompiled contract - [#2255](https://github.com/blockscout/blockscout/pull/2255) - upgrade elixir version to 1.9.0 - [#2256](https://github.com/blockscout/blockscout/pull/2256) - use the latest version of chromedriver - ## 2.0.0-beta ### Features + - [#2044](https://github.com/blockscout/blockscout/pull/2044) - New network selector. - [#2091](https://github.com/blockscout/blockscout/pull/2091) - Added "Question" modal. - [#1963](https://github.com/blockscout/blockscout/pull/1963), [#1959](https://github.com/blockscout/blockscout/pull/1959), [#1948](https://github.com/blockscout/blockscout/pull/1948), [#1936](https://github.com/blockscout/blockscout/pull/1936), [#1925](https://github.com/blockscout/blockscout/pull/1925), [#1922](https://github.com/blockscout/blockscout/pull/1922), [#1903](https://github.com/blockscout/blockscout/pull/1903), [#1874](https://github.com/blockscout/blockscout/pull/1874), [#1895](https://github.com/blockscout/blockscout/pull/1895), [#2031](https://github.com/blockscout/blockscout/pull/2031), [#2073](https://github.com/blockscout/blockscout/pull/2073), [#2074](https://github.com/blockscout/blockscout/pull/2074), - added new themes and logos for poa, eth, rinkeby, goerli, ropsten, kovan, sokol, xdai, etc, rsk and default theme @@ -1300,7 +6040,7 @@ fixed menu hovers in dark mode desktop view - [#2036](https://github.com/blockscout/blockscout/pull/2036) - New tables for staking pools and delegators - [#1974](https://github.com/blockscout/blockscout/pull/1974) - feat: previous page button logic - [#1999](https://github.com/blockscout/blockscout/pull/1999) - load data async on addresses page -- [#1807](https://github.com/blockscout/blockscout/pull/1807) - New theming capabilites. +- [#1807](https://github.com/blockscout/blockscout/pull/1807) - New theming capabilities. - [#2040](https://github.com/blockscout/blockscout/pull/2040) - Verification links to other explorers for ETH - [#2037](https://github.com/blockscout/blockscout/pull/2037) - add address logs search functionality - [#2012](https://github.com/blockscout/blockscout/pull/2012) - make all pages pagination async @@ -1308,6 +6048,7 @@ fixed menu hovers in dark mode desktop view - [#2100](https://github.com/blockscout/blockscout/pull/2100) - feat: eth_get_balance rpc endpoint ### Fixes + - [#2228](https://github.com/blockscout/blockscout/pull/2228) - favorites duplication issues, active radio issue - [#2207](https://github.com/blockscout/blockscout/pull/2207) - new 'download csv' button design - [#2206](https://github.com/blockscout/blockscout/pull/2206) - added styles for 'Download All Transactions as CSV' button @@ -1329,7 +6070,7 @@ fixed menu hovers in dark mode desktop view - [#1868](https://github.com/blockscout/blockscout/pull/1868) - fix: logs list endpoint performance - [#1822](https://github.com/blockscout/blockscout/pull/1822) - Fix style breaks in decompiled contract code view - [#1885](https://github.com/blockscout/blockscout/pull/1885) - highlight reserved words in decompiled code -- [#1896](https://github.com/blockscout/blockscout/pull/1896) - re-query tokens in top nav automplete +- [#1896](https://github.com/blockscout/blockscout/pull/1896) - re-query tokens in top nav autocomplete - [#1905](https://github.com/blockscout/blockscout/pull/1905) - fix reorgs, uncles pagination - [#1904](https://github.com/blockscout/blockscout/pull/1904) - fix `BLOCK_COUNT_CACHE_TTL` env var type - [#1915](https://github.com/blockscout/blockscout/pull/1915) - fallback to 2 latest evm versions @@ -1346,7 +6087,7 @@ fixed menu hovers in dark mode desktop view - [#2014](https://github.com/blockscout/blockscout/pull/2014) - fix: use better queries for listLogs endpoint - [#2027](https://github.com/blockscout/blockscout/pull/2027) - fix: `BlocksTransactionsMismatch` ignoring blocks without transactions - [#2070](https://github.com/blockscout/blockscout/pull/2070) - reduce `max_concurrency` of `BlocksTransactionsMismatch` fetcher -- [#2083](https://github.com/blockscout/blockscout/pull/2083) - allow total_difficuly to be nil +- [#2083](https://github.com/blockscout/blockscout/pull/2083) - allow total_difficulty to be nil - [#2086](https://github.com/blockscout/blockscout/pull/2086) - fix geth's staticcall without output ### Chore @@ -1361,7 +6102,6 @@ fixed menu hovers in dark mode desktop view - [#2055](https://github.com/blockscout/blockscout/pull/2055) - Increase timeout for geth indexers - [#2069](https://github.com/blockscout/blockscout/pull/2069) - Docsify integration: static docs page generation - ## 1.3.15-beta ### Features @@ -1376,7 +6116,6 @@ fixed menu hovers in dark mode desktop view - [#1992](https://github.com/blockscout/blockscout/pull/1992) - fix: support https for wobserver polling - [#2027](https://github.com/blockscout/blockscout/pull/2027) - fix: `BlocksTransactionsMismatch` ignoring blocks without transactions - ## 1.3.14-beta - [#1812](https://github.com/blockscout/blockscout/pull/1812) - add pagination to addresses page @@ -1391,7 +6130,6 @@ fixed menu hovers in dark mode desktop view - [#1892](https://github.com/blockscout/blockscout/pull/1892) - Remove temporary worker modules - ## 1.3.13-beta ### Features @@ -1404,12 +6142,10 @@ fixed menu hovers in dark mode desktop view - [#1881](https://github.com/blockscout/blockscout/pull/1881) - fix: store solc versions locally for performance - [#1898](https://github.com/blockscout/blockscout/pull/1898) - check if the constructor has arguments before verifying constructor arguments - ## 1.3.12-beta Reverting of synchronous block counter, implemented in #1848 - ## 1.3.11-beta ### Features @@ -1428,10 +6164,9 @@ Reverting of synchronous block counter, implemented in #1848 ### Chore -- [#1814](https://github.com/blockscout/blockscout/pull/1814) - Clear build artefacts script +- [#1814](https://github.com/blockscout/blockscout/pull/1814) - Clear build artifacts script - [#1837](https://github.com/blockscout/blockscout/pull/1837) - Add -f flag to clear_build.sh script delete static folder - ## 1.3.10-beta ### Features @@ -1446,165 +6181,162 @@ Reverting of synchronous block counter, implemented in #1848 ### Fixes - - [#1724](https://github.com/blockscout/blockscout/pull/1724) - Remove internal tx and token balance fetching from realtime fetcher - - [#1727](https://github.com/blockscout/blockscout/pull/1727) - add logs pagination in rpc api - - [#1740](https://github.com/blockscout/blockscout/pull/1740) - fix empty block time - - [#1743](https://github.com/blockscout/blockscout/pull/1743) - sort decompiled smart contracts in lexicographical order - - [#1756](https://github.com/blockscout/blockscout/pull/1756) - add today's token balance from the previous value - - [#1769](https://github.com/blockscout/blockscout/pull/1769) - add timestamp to block overview - - [#1768](https://github.com/blockscout/blockscout/pull/1768) - fix first block parameter - - [#1778](https://github.com/blockscout/blockscout/pull/1778) - Make websocket optional for realtime fetcher - - [#1790](https://github.com/blockscout/blockscout/pull/1790) - fix constructor arguments verification - - [#1793](https://github.com/blockscout/blockscout/pull/1793) - fix top nav autocomplete - - [#1795](https://github.com/blockscout/blockscout/pull/1795) - fix line numbers for decompiled contracts - - [#1803](https://github.com/blockscout/blockscout/pull/1803) - use coinmarketcap for total_supply by default - - [#1802](https://github.com/blockscout/blockscout/pull/1802) - make coinmarketcap's number of pages configurable - - [#1799](https://github.com/blockscout/blockscout/pull/1799) - Use eth_getUncleByBlockHashAndIndex for uncle block fetching - - [#1531](https://github.com/blockscout/blockscout/pull/1531) - docker: fix dockerFile for secp256k1 building - - [#1835](https://github.com/blockscout/blockscout/pull/1835) - fix: ignore `pong` messages without error +- [#1724](https://github.com/blockscout/blockscout/pull/1724) - Remove internal tx and token balance fetching from realtime fetcher +- [#1727](https://github.com/blockscout/blockscout/pull/1727) - add logs pagination in rpc api +- [#1740](https://github.com/blockscout/blockscout/pull/1740) - fix empty block time +- [#1743](https://github.com/blockscout/blockscout/pull/1743) - sort decompiled smart contracts in lexicographical order +- [#1756](https://github.com/blockscout/blockscout/pull/1756) - add today's token balance from the previous value +- [#1769](https://github.com/blockscout/blockscout/pull/1769) - add timestamp to block overview +- [#1768](https://github.com/blockscout/blockscout/pull/1768) - fix first block parameter +- [#1778](https://github.com/blockscout/blockscout/pull/1778) - Make websocket optional for realtime fetcher +- [#1790](https://github.com/blockscout/blockscout/pull/1790) - fix constructor arguments verification +- [#1793](https://github.com/blockscout/blockscout/pull/1793) - fix top nav autocomplete +- [#1795](https://github.com/blockscout/blockscout/pull/1795) - fix line numbers for decompiled contracts +- [#1803](https://github.com/blockscout/blockscout/pull/1803) - use coinmarketcap for total_supply by default +- [#1802](https://github.com/blockscout/blockscout/pull/1802) - make coinmarketcap's number of pages configurable +- [#1799](https://github.com/blockscout/blockscout/pull/1799) - Use eth_getUncleByBlockHashAndIndex for uncle block fetching +- [#1531](https://github.com/blockscout/blockscout/pull/1531) - docker: fix dockerFile for secp256k1 building +- [#1835](https://github.com/blockscout/blockscout/pull/1835) - fix: ignore `pong` messages without error ### Chore - - [#1804](https://github.com/blockscout/blockscout/pull/1804) - (Chore) Divide chains by Mainnet/Testnet in menu - - [#1783](https://github.com/blockscout/blockscout/pull/1783) - Update README with the chains that use Blockscout - - [#1780](https://github.com/blockscout/blockscout/pull/1780) - Update link to the Github repo in the footer - - [#1757](https://github.com/blockscout/blockscout/pull/1757) - Change twitter acc link to official Blockscout acc twitter - - [#1749](https://github.com/blockscout/blockscout/pull/1749) - Replace the link in the footer with the official POA announcements tg channel link - - [#1718](https://github.com/blockscout/blockscout/pull/1718) - Flatten indexer module hierarchy and supervisor tree - - [#1753](https://github.com/blockscout/blockscout/pull/1753) - Add a check mark to decompiled contract tab - - [#1744](https://github.com/blockscout/blockscout/pull/1744) - remove `0x0..0` from tests - - [#1763](https://github.com/blockscout/blockscout/pull/1763) - Describe indexer structure and list existing fetchers - - [#1800](https://github.com/blockscout/blockscout/pull/1800) - Disable lazy logging check in Credo - +- [#1804](https://github.com/blockscout/blockscout/pull/1804) - (Chore) Divide chains by Mainnet/Testnet in menu +- [#1783](https://github.com/blockscout/blockscout/pull/1783) - Update README with the chains that use Blockscout +- [#1780](https://github.com/blockscout/blockscout/pull/1780) - Update link to the Github repo in the footer +- [#1757](https://github.com/blockscout/blockscout/pull/1757) - Change twitter acc link to official Blockscout acc twitter +- [#1749](https://github.com/blockscout/blockscout/pull/1749) - Replace the link in the footer with the official POA announcements tg channel link +- [#1718](https://github.com/blockscout/blockscout/pull/1718) - Flatten indexer module hierarchy and supervisor tree +- [#1753](https://github.com/blockscout/blockscout/pull/1753) - Add a check mark to decompiled contract tab +- [#1744](https://github.com/blockscout/blockscout/pull/1744) - remove `0x0..0` from tests +- [#1763](https://github.com/blockscout/blockscout/pull/1763) - Describe indexer structure and list existing fetchers +- [#1800](https://github.com/blockscout/blockscout/pull/1800) - Disable lazy logging check in Credo ## 1.3.9-beta ### Features - - [#1662](https://github.com/blockscout/blockscout/pull/1662) - allow specifying number of optimization runs - - [#1654](https://github.com/blockscout/blockscout/pull/1654) - add decompiled code tab - - [#1661](https://github.com/blockscout/blockscout/pull/1661) - try to compile smart contract with the latest evm version - - [#1665](https://github.com/blockscout/blockscout/pull/1665) - Add contract verification RPC endpoint. - - [#1706](https://github.com/blockscout/blockscout/pull/1706) - allow setting update interval for addresses with b +- [#1662](https://github.com/blockscout/blockscout/pull/1662) - allow specifying number of optimization runs +- [#1654](https://github.com/blockscout/blockscout/pull/1654) - add decompiled code tab +- [#1661](https://github.com/blockscout/blockscout/pull/1661) - try to compile smart contract with the latest evm version +- [#1665](https://github.com/blockscout/blockscout/pull/1665) - Add contract verification RPC endpoint. +- [#1706](https://github.com/blockscout/blockscout/pull/1706) - allow setting update interval for addresses with b ### Fixes - - [#1669](https://github.com/blockscout/blockscout/pull/1669) - do not fail if multiple matching tokens are found - - [#1691](https://github.com/blockscout/blockscout/pull/1691) - decrease token metadata update interval - - [#1688](https://github.com/blockscout/blockscout/pull/1688) - do not fail if failure reason is atom - - [#1692](https://github.com/blockscout/blockscout/pull/1692) - exclude decompiled smart contract from encoding - - [#1684](https://github.com/blockscout/blockscout/pull/1684) - Discard child block with parent_hash not matching hash of imported block - - [#1699](https://github.com/blockscout/blockscout/pull/1699) - use seconds as transaction cache period measure - - [#1697](https://github.com/blockscout/blockscout/pull/1697) - fix failing in rpc if balance is empty - - [#1711](https://github.com/blockscout/blockscout/pull/1711) - rescue failing repo in block number cache update - - [#1712](https://github.com/blockscout/blockscout/pull/1712) - do not set contract code from transaction input - - [#1714](https://github.com/blockscout/blockscout/pull/1714) - fix average block time calculation +- [#1669](https://github.com/blockscout/blockscout/pull/1669) - do not fail if multiple matching tokens are found +- [#1691](https://github.com/blockscout/blockscout/pull/1691) - decrease token metadata update interval +- [#1688](https://github.com/blockscout/blockscout/pull/1688) - do not fail if failure reason is atom +- [#1692](https://github.com/blockscout/blockscout/pull/1692) - exclude decompiled smart contract from encoding +- [#1684](https://github.com/blockscout/blockscout/pull/1684) - Discard child block with parent_hash not matching hash of imported block +- [#1699](https://github.com/blockscout/blockscout/pull/1699) - use seconds as transaction cache period measure +- [#1697](https://github.com/blockscout/blockscout/pull/1697) - fix failing in rpc if balance is empty +- [#1711](https://github.com/blockscout/blockscout/pull/1711) - rescue failing repo in block number cache update +- [#1712](https://github.com/blockscout/blockscout/pull/1712) - do not set contract code from transaction input +- [#1714](https://github.com/blockscout/blockscout/pull/1714) - fix average block time calculation ### Chore - - [#1693](https://github.com/blockscout/blockscout/pull/1693) - Add a checklist to the PR template - +- [#1693](https://github.com/blockscout/blockscout/pull/1693) - Add a checklist to the PR template ## 1.3.8-beta ### Features - - [#1611](https://github.com/blockscout/blockscout/pull/1611) - allow setting the first indexing block - - [#1596](https://github.com/blockscout/blockscout/pull/1596) - add endpoint to create decompiled contracts - - [#1634](https://github.com/blockscout/blockscout/pull/1634) - add transaction count cache +- [#1611](https://github.com/blockscout/blockscout/pull/1611) - allow setting the first indexing block +- [#1596](https://github.com/blockscout/blockscout/pull/1596) - add endpoint to create decompiled contracts +- [#1634](https://github.com/blockscout/blockscout/pull/1634) - add transaction count cache ### Fixes - - [#1630](https://github.com/blockscout/blockscout/pull/1630) - (Fix) colour for release link in the footer - - [#1621](https://github.com/blockscout/blockscout/pull/1621) - Modify query to fetch failed contract creations - - [#1614](https://github.com/blockscout/blockscout/pull/1614) - Do not fetch burn address token balance - - [#1639](https://github.com/blockscout/blockscout/pull/1614) - Optimize token holder count updates when importing address current balances - - [#1643](https://github.com/blockscout/blockscout/pull/1643) - Set internal_transactions_indexed_at for empty blocks - - [#1647](https://github.com/blockscout/blockscout/pull/1647) - Fix typo in view - - [#1650](https://github.com/blockscout/blockscout/pull/1650) - Add petersburg evm version to smart contract verifier - - [#1657](https://github.com/blockscout/blockscout/pull/1657) - Force consensus loss for parent block if its hash mismatches parent_hash +- [#1630](https://github.com/blockscout/blockscout/pull/1630) - (Fix) color for release link in the footer +- [#1621](https://github.com/blockscout/blockscout/pull/1621) - Modify query to fetch failed contract creations +- [#1614](https://github.com/blockscout/blockscout/pull/1614) - Do not fetch burn address token balance +- [#1639](https://github.com/blockscout/blockscout/pull/1614) - Optimize token holder count updates when importing address current balances +- [#1643](https://github.com/blockscout/blockscout/pull/1643) - Set internal_transactions_indexed_at for empty blocks +- [#1647](https://github.com/blockscout/blockscout/pull/1647) - Fix typo in view +- [#1650](https://github.com/blockscout/blockscout/pull/1650) - Add petersburg evm version to smart contract verifier +- [#1657](https://github.com/blockscout/blockscout/pull/1657) - Force consensus loss for parent block if its hash mismatches parent_hash ### Chore - ## 1.3.7-beta ### Features ### Fixes - - [#1615](https://github.com/blockscout/blockscout/pull/1615) - Add more logging to code fixer process - - [#1613](https://github.com/blockscout/blockscout/pull/1613) - Fix USD fee value - - [#1577](https://github.com/blockscout/blockscout/pull/1577) - Add process to fix contract with code - - [#1583](https://github.com/blockscout/blockscout/pull/1583) - Chunk JSON-RPC batches in case connection times out +- [#1615](https://github.com/blockscout/blockscout/pull/1615) - Add more logging to code fixer process +- [#1613](https://github.com/blockscout/blockscout/pull/1613) - Fix USD fee value +- [#1577](https://github.com/blockscout/blockscout/pull/1577) - Add process to fix contract with code +- [#1583](https://github.com/blockscout/blockscout/pull/1583) - Chunk JSON-RPC batches in case connection times out ### Chore - - [#1610](https://github.com/blockscout/blockscout/pull/1610) - Add PIRL to Readme - +- [#1610](https://github.com/blockscout/blockscout/pull/1610) - Add PIRL to Readme ## 1.3.6-beta ### Features - - [#1589](https://github.com/blockscout/blockscout/pull/1589) - RPC endpoint to list addresses - - [#1567](https://github.com/blockscout/blockscout/pull/1567) - Allow setting different configuration just for realtime fetcher - - [#1562](https://github.com/blockscout/blockscout/pull/1562) - Add incoming transactions count to contract view - - [#1608](https://github.com/blockscout/blockscout/pull/1608) - Add listcontracts RPC Endpoint +- [#1589](https://github.com/blockscout/blockscout/pull/1589) - RPC endpoint to list addresses +- [#1567](https://github.com/blockscout/blockscout/pull/1567) - Allow setting different configuration just for realtime fetcher +- [#1562](https://github.com/blockscout/blockscout/pull/1562) - Add incoming transactions count to contract view +- [#1608](https://github.com/blockscout/blockscout/pull/1608) - Add listcontracts RPC Endpoint ### Fixes - - [#1595](https://github.com/blockscout/blockscout/pull/1595) - Reduce block_rewards in the catchup fetcher - - [#1590](https://github.com/blockscout/blockscout/pull/1590) - Added guard for fetching blocks with invalid number - - [#1588](https://github.com/blockscout/blockscout/pull/1588) - Fix usd value on address page - - [#1586](https://github.com/blockscout/blockscout/pull/1586) - Exact timestamp display - - [#1581](https://github.com/blockscout/blockscout/pull/1581) - Consider `creates` param when fetching transactions - - [#1559](https://github.com/blockscout/blockscout/pull/1559) - Change v column type for Transactions table +- [#1595](https://github.com/blockscout/blockscout/pull/1595) - Reduce block_rewards in the catchup fetcher +- [#1590](https://github.com/blockscout/blockscout/pull/1590) - Added guard for fetching blocks with invalid number +- [#1588](https://github.com/blockscout/blockscout/pull/1588) - Fix usd value on address page +- [#1586](https://github.com/blockscout/blockscout/pull/1586) - Exact timestamp display +- [#1581](https://github.com/blockscout/blockscout/pull/1581) - Consider `creates` param when fetching transactions +- [#1559](https://github.com/blockscout/blockscout/pull/1559) - Change v column type for Transactions table ### Chore - - [#1579](https://github.com/blockscout/blockscout/pull/1579) - Add SpringChain to the list of Additional Chains Utilizing BlockScout - - [#1578](https://github.com/blockscout/blockscout/pull/1578) - Refine contributing procedure - - [#1572](https://github.com/blockscout/blockscout/pull/1572) - Add option to disable block rewards in indexer config - +- [#1579](https://github.com/blockscout/blockscout/pull/1579) - Add SpringChain to the list of Additional Chains Utilizing BlockScout +- [#1578](https://github.com/blockscout/blockscout/pull/1578) - Refine contributing procedure +- [#1572](https://github.com/blockscout/blockscout/pull/1572) - Add option to disable block rewards in indexer config ## 1.3.5-beta ### Features - - [#1560](https://github.com/blockscout/blockscout/pull/1560) - Allow executing smart contract functions in arbitrarily sized batches - - [#1543](https://github.com/blockscout/blockscout/pull/1543) - Use trace_replayBlockTransactions API for faster tracing - - [#1558](https://github.com/blockscout/blockscout/pull/1558) - Allow searching by token symbol - - [#1551](https://github.com/blockscout/blockscout/pull/1551) Exact date and time for Transaction details page - - [#1547](https://github.com/blockscout/blockscout/pull/1547) - Verify smart contracts with evm versions - - [#1540](https://github.com/blockscout/blockscout/pull/1540) - Fetch ERC721 token balances if sender is '0x0..0' - - [#1539](https://github.com/blockscout/blockscout/pull/1539) - Add the link to release in the footer - - [#1519](https://github.com/blockscout/blockscout/pull/1519) - Create contract methods - - [#1496](https://github.com/blockscout/blockscout/pull/1496) - Remove dropped/replaced transactions in pending transactions list - - [#1492](https://github.com/blockscout/blockscout/pull/1492) - Disable usd value for an empty exchange rate - - [#1466](https://github.com/blockscout/blockscout/pull/1466) - Decoding candidates for unverified contracts - -### Fixes - - [#1545](https://github.com/blockscout/blockscout/pull/1545) - Fix scheduling of latest block polling in Realtime Fetcher - - [#1554](https://github.com/blockscout/blockscout/pull/1554) - Encode integer parameters when calling smart contract functions - - [#1537](https://github.com/blockscout/blockscout/pull/1537) - Fix test that depended on date - - [#1534](https://github.com/blockscout/blockscout/pull/1534) - Render a nicer error when creator cannot be determined - - [#1527](https://github.com/blockscout/blockscout/pull/1527) - Add index to value_fetched_at - - [#1518](https://github.com/blockscout/blockscout/pull/1518) - Select only distinct failed transactions - - [#1516](https://github.com/blockscout/blockscout/pull/1516) - Fix coin balance params reducer for pending transaction - - [#1511](https://github.com/blockscout/blockscout/pull/1511) - Set correct log level for production - - [#1510](https://github.com/blockscout/blockscout/pull/1510) - Fix test that fails every 1st day of the month - - [#1509](https://github.com/blockscout/blockscout/pull/1509) - Add index to blocks' consensus - - [#1508](https://github.com/blockscout/blockscout/pull/1508) - Remove duplicated indexes - - [#1505](https://github.com/blockscout/blockscout/pull/1505) - Use https instead of ssh for absinthe libs - - [#1501](https://github.com/blockscout/blockscout/pull/1501) - Constructor_arguments must be type `text` - - [#1498](https://github.com/blockscout/blockscout/pull/1498) - Add index for created_contract_address_hash in transactions - - [#1493](https://github.com/blockscout/blockscout/pull/1493) - Do not do work in process initialization - - [#1487](https://github.com/blockscout/blockscout/pull/1487) - Limit geth sync to 128 blocks - - [#1484](https://github.com/blockscout/blockscout/pull/1484) - Allow decoding input as utf-8 - - [#1479](https://github.com/blockscout/blockscout/pull/1479) - Remove smoothing from coin balance chart - -### Chore - - [https://github.com/blockscout/blockscout/pull/1532](https://github.com/blockscout/blockscout/pull/1532) - Upgrade elixir to 1.8.1 - - [https://github.com/blockscout/blockscout/pull/1553](https://github.com/blockscout/blockscout/pull/1553) - Dockerfile: remove 1.7.1 version pin FROM bitwalker/alpine-elixir-phoenix - - [https://github.com/blockscout/blockscout/pull/1465](https://github.com/blockscout/blockscout/pull/1465) - Resolve lodash security alert +- [#1560](https://github.com/blockscout/blockscout/pull/1560) - Allow executing smart contract functions in arbitrarily sized batches +- [#1543](https://github.com/blockscout/blockscout/pull/1543) - Use trace_replayBlockTransactions API for faster tracing +- [#1558](https://github.com/blockscout/blockscout/pull/1558) - Allow searching by token symbol +- [#1551](https://github.com/blockscout/blockscout/pull/1551) Exact date and time for Transaction details page +- [#1547](https://github.com/blockscout/blockscout/pull/1547) - Verify smart contracts with evm versions +- [#1540](https://github.com/blockscout/blockscout/pull/1540) - Fetch ERC721 token balances if sender is '0x0..0' +- [#1539](https://github.com/blockscout/blockscout/pull/1539) - Add the link to release in the footer +- [#1519](https://github.com/blockscout/blockscout/pull/1519) - Create contract methods +- [#1496](https://github.com/blockscout/blockscout/pull/1496) - Remove dropped/replaced transactions in pending transactions list +- [#1492](https://github.com/blockscout/blockscout/pull/1492) - Disable usd value for an empty exchange rate +- [#1466](https://github.com/blockscout/blockscout/pull/1466) - Decoding candidates for unverified contracts + +### Fixes + +- [#1545](https://github.com/blockscout/blockscout/pull/1545) - Fix scheduling of latest block polling in Realtime Fetcher +- [#1554](https://github.com/blockscout/blockscout/pull/1554) - Encode integer parameters when calling smart contract functions +- [#1537](https://github.com/blockscout/blockscout/pull/1537) - Fix test that depended on date +- [#1534](https://github.com/blockscout/blockscout/pull/1534) - Render a nicer error when creator cannot be determined +- [#1527](https://github.com/blockscout/blockscout/pull/1527) - Add index to value_fetched_at +- [#1518](https://github.com/blockscout/blockscout/pull/1518) - Select only distinct failed transactions +- [#1516](https://github.com/blockscout/blockscout/pull/1516) - Fix coin balance params reducer for pending transaction +- [#1511](https://github.com/blockscout/blockscout/pull/1511) - Set correct log level for production +- [#1510](https://github.com/blockscout/blockscout/pull/1510) - Fix test that fails every 1st day of the month +- [#1509](https://github.com/blockscout/blockscout/pull/1509) - Add index to blocks' consensus +- [#1508](https://github.com/blockscout/blockscout/pull/1508) - Remove duplicated indexes +- [#1505](https://github.com/blockscout/blockscout/pull/1505) - Use https instead of ssh for absinthe libs +- [#1501](https://github.com/blockscout/blockscout/pull/1501) - Constructor_arguments must be type `text` +- [#1498](https://github.com/blockscout/blockscout/pull/1498) - Add index for created_contract_address_hash in transactions +- [#1493](https://github.com/blockscout/blockscout/pull/1493) - Do not do work in process initialization +- [#1487](https://github.com/blockscout/blockscout/pull/1487) - Limit geth sync to 128 blocks +- [#1484](https://github.com/blockscout/blockscout/pull/1484) - Allow decoding input as utf-8 +- [#1479](https://github.com/blockscout/blockscout/pull/1479) - Remove smoothing from coin balance chart + +### Chore + +- [https://github.com/blockscout/blockscout/pull/1532](https://github.com/blockscout/blockscout/pull/1532) - Upgrade elixir to 1.8.1 +- [https://github.com/blockscout/blockscout/pull/1553](https://github.com/blockscout/blockscout/pull/1553) - Dockerfile: remove 1.7.1 version pin FROM bitwalker/alpine-elixir-phoenix +- [https://github.com/blockscout/blockscout/pull/1465](https://github.com/blockscout/blockscout/pull/1465) - Resolve lodash security alert diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000000..5e7a02004399 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +See AGENTS.md for Blockscout architecture guidance. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 79125b999467..000000000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,60 +0,0 @@ -## Contributing - -1. Fork it ( https://github.com/blockscout/blockscout/fork ) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Write tests that cover your work -4. Commit your changes (`git commit -am 'Add some feature'`) -5. Push to the branch (`git push origin my-new-feature`) -6. Create a new Pull Request -7. Update CHANGELOG.md with the link to PR and description of the changes - -### General - -* Commits should be one logical change that still allows all tests to pass. Prefer smaller commits if there could be two levels of logic grouping. The goal is to allow contributors in the future (including your own future self) to determine your reasoning for making changes and to allow them to cherry-pick, patch or port those changes in isolation to other branches or forks. -* If during your PR you reveal a pre-existing bug: - 1. Try to isolate the bug and fix it on an independent branch and PR it first. - 2. Try to fix the bug in a separate commit from other changes: - 1. Commit the code in the broken state that revealed the bug originally - 2. Commit the fix for the bug. - 3. Continue original PR work. - -### Enhancements - -Enhancements cover all changes that make users lives better: -* [feature requests filed as issues](https://github.com/blockscout/blockscout/labels/enhancement) that impact end-user [contributors](https://github.com/blockscout/blockscout/labels/contributor) and [developers](https://github.com/blockscout/blockscout/labels/developer) -* changes to the [architecture](https://github.com/blockscout/blockscout/labels/architecture) that make it easier for contributors (in the GitHub sense), dev-ops, and deployers to maintain and run blockscout - -### Bug Fixes - -For bug fixes, whenever possible, there should be at least 2 commits: - -1. A regression test commit that contains tests that demonstrate the bug and show as failing. -2. The bug fix commit that shows the regression test now passing. - -This format ensures that we can run the test to reproduce the original bug without depending on the new code in the fix, which could lead to the test falsely passing. - -### Incompatible Changes - -Incompatible changes can arise as a side-effect of either Enhancements or Bug Fixes. During Enhancements, incompatible changes can occur because, as an example, in order to support showing end-users new data, the database schema may need to be changed and the index rebuilt from scratch. During bug fixes, incompatible changes can occur because in order to fix a bug, the schema had to change, or how certain internal APIs are called changed. - -* Incompatible changes should be called out explicitly, with any steps the various user roles need to do to upgrade. -* If a schema change occurs that requires a re-index add the following to the Pull Request description: - ```markdown - **NOTE**: A database reset and re-index is required - ``` - -### Pull Request - -There is a [PULL_REQUEST_TEMPLATE.md](PULL_REQUEST_TEMPLATE.md) for this repository, but since it can't fill in the title for you, please follow the following steps when opening a Pull Request before filling in the template: - -- [ ] Title - - [ ] Prefix labels if you don't have permissions to set labels in the GitHub interface. - * (bug) for [bug](https://github.com/blockscout/blockscout/labels/bug) fixes - * (enhancement) for [enhancement](https://github.com/blockscout/blockscout/labels/enhancement)s - * (incompatible changes) for [incompatible changes](https://github.com/blockscout/blockscout/labels/incompatible%20changes), such a refactor that removes functionality, changes arguments, or makes something required that wasn't previously. - - [ ] Single sentence summary of change - * What was fixed for bugs - * What was added for enhancements - * What was changed for incompatible changes - -See [#255](https://github.com/blockscout/blockscout/pull/255) as an example PR that uses GitHub keywords and a Changelog to explain multiple changes. diff --git a/FUNDING.json b/FUNDING.json new file mode 100644 index 000000000000..6bc52bce679f --- /dev/null +++ b/FUNDING.json @@ -0,0 +1,10 @@ +{ + "drips": { + "filecoin": { + "ownedBy": "0x5C36Bd76a6c138187C43da92f66f37E23b4017fA" + }, + "opRetro": { + "projectId": "0x663e4d25ca3f327365240471b4831ea3c989cb132bbf6ae8f5c1e15268591795" + } + } +} diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md deleted file mode 100644 index 3075397e8ddb..000000000000 --- a/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,19 +0,0 @@ -*Describe your issue here.* - -### Environment - -* Elixir & Erlang/OTP versions (`elixir -version`): -* Operating System: -* Blockscout Version/branch: - -### Steps to reproduce - -*Tell us how to reproduce this issue. ❤️ if you can push up a branch to your fork with a regression test we can run to reproduce locally.* - -### Expected behaviour - -*Tell us what should happen.* - -### Actual behaviour - -*Tell us what happens instead.* diff --git a/LICENSE b/LICENSE index 94a9ed024d38..925326d4d936 100644 --- a/LICENSE +++ b/LICENSE @@ -1,674 +1,446 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. +SPDX-License-Identifier: LicenseRef-Blockscout + +Effective Date: 2026-04-22 +Version: 1.0 +Previous Version: N/A + +PLEASE READ THIS LICENCE CAREFULLY. BY DOWNLOADING, ACCESSING, COPYING, +MODIFYING, DISTRIBUTING, DEPLOYING, OR OTHERWISE USING THE SOFTWARE, YOU +CONFIRM THAT YOU HAVE READ, UNDERSTOOD, AND AGREE TO BE LEGALLY BOUND BY +THE TERMS OF THIS LICENCE IN FULL. IF YOU DO NOT AGREE TO THESE TERMS, +YOU MUST NOT DOWNLOAD, USE, COPY, MODIFY, OR DISTRIBUTE THE SOFTWARE. + +1. Definitions + +“Commercial Licence” means a separate written commercial licence +agreement entered into between you and the Licensor, which expressly +references this Licence and supplements its terms by granting additional +rights, or permitting uses, that are not granted or permitted under this +Licence. + +“Derivative Work” means any work, whether in source or object form, that +is based on or derived from the Software and in which any editorial +revisions, annotations, elaborations, additions, deletions, or other +modifications, taken as a whole, constitute an original work of +authorship. For the avoidance of doubt, Derivative Works do not include +works that remain separable from, or merely link to, the Software. + +“Feedback” means any comments, suggestions, recommendations, ideas, +proposals, or other feedback, whether oral or written, provided by you in +connection with or relating to the Software. + +“Group” means, in respect of an entity, that entity together with any +other entity that directly or indirectly controls, is controlled by, or +is under common control with, that entity. For the purposes of this +definition, “control” means the direct or indirect ownership of more than +fifty per cent (50%) of the voting securities or other ownership interest +of an entity, or the power to direct or cause the direction of the +management and policies of that entity (whether by ownership, contract, +or otherwise). + +“Licence” means this Blockscout Software Licence, as amended or updated +from time to time. + +“Licensor” means Blockscout Limited, an international business company +incorporated under the laws of the Republic of Seychelles. + +“Prior Software” means any prior version, release, build, or component of +the Software that was made available by or on behalf of the Licensor +before the Effective Date, and that is not distributed under this Licence. + +“Software” means the Blockscout blockchain explorer, a tool for +inspecting and analyzing blockchain networks, as made available by the +Licensor under this Licence, including the source code, object code, +executable files, configuration and deployment materials, documentation, +APIs/SDKs (if any), and any part or portion thereof. + +“You” or “your” means the individual who accepts this Licence. Where you +act on behalf of an entity, “you” shall refer to both: (i) you as an +individual exercising rights under this Licence; and (ii) the entity on +whose behalf you are acting. + +2. Licence and Attribution + + a. Licence. Subject to and conditional upon your compliance with this + Licence, the Licensor hereby grants you a temporary, worldwide, + non-exclusive, royalty-free, revocable, non-transferable, and + non-sublicensable licence to download, review, use, deploy, copy, + modify, and create Derivative Works of the Software. All rights not + expressly granted under this Licence are reserved by the Licensor. + + b. Branding and Attribution. You shall preserve all copyright, patent, + trademark, branding, and attribution notices included in or displayed + by the Software, and shall not remove, obscure, conceal, replace, + alter, disable, or otherwise interfere with the display or integrity of + such notices. + + c. Interface Attribution. Where the Software is used to power, enable, + or provide functionality for any user interface (including any website, + web application, mobile application, or other frontend), you shall + ensure that such interface includes clear and reasonably prominent + attribution to the Licensor at all times while you use the Software. + Such attribution shall (i) prominently identify the Licensor by the + brand name “Blockscout” (such as “Made with Blockscout” or “Powered by + Blockscout”), and (ii) include the respective attribution text, link + (or a hyperlink) to the website https://blockscout.com and any branding + or notices provided by the Licensor, in each case in the same form and + manner as displayed in the footer of the following website: + https://eth.blockscout.com. + + d. No Endorsement or Service Provision. Except as expressly agreed in + writing by the Licensor, the Licensor does not provide, and shall not + be deemed to provide, any product or service that you (or any third + party) offer, operate, or make available using the Software, and the + Licensor is not a party to, and has no responsibility or liability for, + any relationship, transaction or interaction between you and any end + user or other third party. The Licensor does not endorse, sponsor, + approve, or recommend you, your business, or any of your products or + services. Except as expressly agreed in writing by the Licensor, you + shall not (and shall not authorise or permit any third party to) state, + represent, imply, or otherwise hold out that: (i) the Licensor provides + any services to or for you; (ii) the Licensor acts on your behalf; + (iii) you are acting as an agent, representative, partner, or affiliate + of the Licensor; or (iv) the Licensor endorses, sponsors, approves, or + recommends you, your business, or any of your products or services. + +3. Scope and Updates + + a. Scope. Subject to Third-Party Licences clause, this Licence applies + solely to the version of the Software (and its components) with which + it is distributed by or on behalf of the Licensor. This Licence does + not apply to any Prior Software. + + + b. Software Changes. The Software is under active development and may + be modified, updated, improved, withdrawn, suspended, or discontinued + by the Licensor at any time, in whole or in part, with or without + notice. The Licensor does not warrant or guarantee that any particular + features, functionality, integrations, interfaces, or components of the + Software will remain available, unchanged, or compatible with any prior + or future versions. You acknowledge and agree that the Software may + change over time and that continued use of the Software is at your sole + risk. + + + c. Licence Updates. The Licensor may amend, replace, or update this + Licence at any time in its sole discretion, with or without notice. + Where you continue to access, use, deploy, copy, modify, or otherwise + use the Software after the effective date of an updated Licence, you + acknowledge and agree that your continued use constitutes acceptance + of, and you shall comply with, the updated Licence. For the avoidance + of doubt, an updated Licence may introduce additional restrictions or + permissions, including requiring a Commercial Licence for certain uses. + +4. Restricted Uses and Commercial Licence + + a. Restricted Commercial or Monetised Use (including SaaS and RaaS). + Unless and until you obtain a Commercial Licence, you shall not, and + shall not authorise or permit any third party to exercise any rights + granted under this Licence to (directly or indirectly) sell, license, + monetise, commercialise, or otherwise make available the Software or + its functionality to any third party in exchange for any fee or other + consideration (including without limitation fees for hosting, access, + subscriptions, support, consulting, implementation, customisation, + maintenance, managed services, or any other services), where such + product or service incorporates, uses, depends on, or is materially + enabled by the Software (including offering the Software or its + functionality on a hosted, “as-a-service”, or managed basis). + + b. Obtaining Commercial Licence. If you intend to exercise any rights + or engage in any uses of the Software that are prohibited, restricted, + or not granted under this Licence, you must, prior to such use, contact + the Licensor at https://eaas.blockscout.com/#contact to request a + Commercial Licence and applicable pricing and terms. Any such rights or + uses are unauthorised unless and until a Commercial Licence has been + expressly agreed in writing by the Licensor. Nothing in this Licence + obliges the Licensor to grant any Commercial Licence or to enter into + any agreement with you. + + c. Compliance Verification. Upon the Licensor’s reasonable request, you + shall promptly provide the Licensor with such information and + documentation as the Licensor may reasonably require to verify your + compliance with this Licence, including (without limitation) to confirm + whether your use of the Software requires a Commercial Licence. The + Licensor shall use any such information solely for compliance + verification purposes. + + d. Name and Branding Restrictions. You shall not distribute, market, or + otherwise make available the Software or any Derivative Works under any + name, designation, branding, or identifier that is identical or + confusingly similar to the Licensor’s product names, trademarks, + service marks, or trade names, or that is likely to cause confusion as + to the origin, sponsorship, affiliation, or endorsement by the Licensor. + +5. Derivative Works + + a. Permission. Subject to and conditional upon your compliance with + this Licence, you may create Derivative Works of the Software solely + for your internal use of the Software. + + b. Restrictions. You shall not distribute, sublicense, sell, license, + make available, or otherwise provide any Derivative Works, in whole or + in part, to any third party without first obtaining a Commercial + Licence. + + c. Ownership and Licence. Except as expressly provided in this Licence, + ownership of any Derivative Works shall remain with you. + Notwithstanding the foregoing, you hereby grant the Licensor a + perpetual, irrevocable, worldwide, royalty-free, non-exclusive, + transferable, and sublicensable licence to use, reproduce, modify, + adapt, incorporate, and otherwise exploit any Derivative Works for any + purpose, including to develop, improve, or distribute the Software. + + d. Tracking of Changes. Where you modify the Software or create any + Derivative Works, you shall ensure that any modified files carry + prominent notices stating that you have modified the Software and + indicating the date of such modification. Any such notices shall not be + construed as modifying, limiting, or otherwise affecting this Licence. + + e. Warranties. You represent and warrant that you own or otherwise have + all necessary rights to create and license any Derivative Works as + contemplated by this Licence, and that such Derivative Works do not + infringe any third-party intellectual property rights, violate this + Licence, or breach any applicable laws or regulations. + +6. Feedback + + a. Permission and Rights. You may, but are not obliged to, provide + Feedback. Where you provide any Feedback, you acknowledge and agree + that the Licensor may, in its sole discretion, use, reproduce, + disclose, make publicly available, and otherwise exploit such Feedback + for any purpose, commercial or otherwise, without restriction and + without any obligation to you, including without acknowledgment or + compensation. + + b. Licence. You hereby grant the Licensor a perpetual, irrevocable, + worldwide, royalty-free, transferable, and sublicensable licence to + use, reproduce, modify, adapt, publish, translate, distribute, publicly + perform, publicly display, and otherwise exploit the Feedback, in whole + or in part, in any manner and for any purpose. To the extent permitted + by applicable law, you waive, and agree not to assert, any moral rights + or similar rights you may have in the Feedback. + + c. Warranties. You represent and warrant that you own or otherwise have + all necessary rights to grant the licence set out in this clause, and + that the Feedback does not infringe any third-party rights or + applicable laws. + +7. Ownership + + a. Ownership. The Licensor is and shall remain the sole owner (or, + where applicable, the authorised licensor) of the Software. Nothing in + this Licence shall operate to assign, transfer, or otherwise convey to + you any right, title, or interest in or to the Software, save for the + limited licence expressly granted under this Licence and the Commercial + Licence, if applicable. All rights are licensed, not sold. You shall + not take, or assist others in taking, any action that may diminish the + Licensor's rights in the Software. + + b. Branding. Subject to your compliance with this Licence, the Licensor + hereby grants you a temporary, worldwide, non-exclusive, royalty-free, + revocable, non-transferable, and non-sublicensable licence to display + the Licensor’s trademarks, trade names, and logos as provided along + with the Software or as required under this Licence, solely for + attribution purposes as required under this Licence. Except for the + foregoing, no rights in any trademarks, trade names, or logos of the + Licensor or its affiliates are granted under this Licence. + + c. Third-Party Licences. While the Software is made available in its + entirety under this Licence, certain components of the Software may + incorporate or be derived from third-party open-source software + provided under permissive licences. Such specific third-party + open-source software components are distributed under the terms of the + applicable third-party licences. To the extent required by such + third-party licences, applicable copyright notices, licence texts, and + attribution requirements shall be preserved. Subject to the foregoing, + the Software as a whole, and all parts thereof, is licensed under this + Licence. + +8. Disclaimers + +To the maximum extent permitted by applicable law, the Software is +provided on an “AS IS” and “AS AVAILABLE” basis and is used at your sole +risk. The Licensor disclaims all warranties of any kind, whether express, +implied, statutory, or otherwise, including (without limitation) any +implied warranties of merchantability, satisfactory quality, fitness for +a particular purpose, non-infringement, and title, and any warranties +arising out of course of dealing, course of performance, or usage of +trade. Without limiting the foregoing, the Licensor makes no +representation or warranty that the Software will function as expected, +meet your requirements, operate in combination with any other software, +have any specific functionality, be uninterrupted, timely, secure, +accurate, complete, or error-free, or that any defects or errors will be +corrected. Nothing in this Licence excludes or limits any warranty, +liability, or other term to the extent it cannot be excluded or limited +under applicable law. The Software is provided for informational and +technical purposes only and does not constitute legal, financial, tax, +investment, or other professional advice. You are solely responsible for +determining whether use of the Software is appropriate for your purposes. + +9. Limitation of Liability + +Nothing in this Licence excludes or limits liability for: (i) death or +personal injury caused by negligence; (ii) fraud or fraudulent +misrepresentation; or (iii) any other liability which cannot be excluded +or limited under applicable law. Subject to the foregoing, to the maximum +extent permitted by applicable law, the Licensor shall not be liable to +you for any loss or damage whatsoever (whether direct, indirect, +incidental, special, punitive or consequential), or for any loss of +profits, revenue, business, business opportunity, anticipated savings, +goodwill or data, or for any business interruption, arising out of or in +connection with the use of, or inability to use, the Software, whether in +contract, tort (including negligence), misrepresentation, restitution, +breach of statutory duty, or otherwise, even if advised of the +possibility of such loss or damage. To the extent that the Licensor is +held liable notwithstanding the above, the total aggregate liability +arising out of or in connection with this Licence or the Software shall +not exceed the total amounts actually paid by you to the Licensor under +this Licence in the twelve (12) months preceding the event giving rise to +the claim (or, if no such amounts were paid, USD 100). + +10. Term and Termination + + a. Automatic Termination. This Licence shall automatically terminate, + without any further action by the Licensor, upon any breach by you of + its terms. + + b. Termination by the Licensor. The Licensor may terminate this Licence + at any time in its sole discretion. Where reasonably practicable, the + Licensor will use reasonable efforts to provide you with advance notice + of termination. + + c. Effect of Termination. Upon termination of this Licence for any + reason: (i) all rights granted to you under this Licence shall + immediately cease; (ii) all Commercial Licences executed with you shall + automatically terminate simultaneously with this Licence; (iii) you + shall immediately cease all access to and use of the Software and any + Derivative Works; (iv) you shall uninstall and delete the Software and + any Derivative Works from all systems under your control and destroy + all copies in your possession or control (in each case including any + copies held by your contractors or service providers), except to the + extent retention is required by applicable law; (v) you shall + immediately cease all distribution or making available of the Software + and any Derivative Works; and (vi) any provisions of this Licence which + by their nature are intended to survive termination shall survive, + including without limitation provisions relating to ownership, + trademarks, feedback, disclaimers, limitation of liability, and + governing law and jurisdiction. + +11. Governing Law and Arbitration + + a. Governing Law. This Licence and any dispute or claim (including + non-contractual disputes or claims) arising out of or in connection + with it or its subject matter or formation shall be governed by and + construed in accordance with the law of England and Wales, excluding + its conflict of law rules. For the avoidance of doubt, the provisions + of the United Nations Convention on the International Sale of Goods + shall not apply to this Licence. + + b. Dispute Resolution. The parties shall first attempt to resolve any + dispute arising out of or in connection with this Licence informally. + You may initiate such informal discussions by giving notice to the + Licensor by email at info@blockscout.com. If the dispute is not + resolved within thirty (30) days of such notice, the dispute shall be + referred to and finally resolved by arbitration under the LCIA Rules, + which Rules are deemed incorporated by reference into this clause. The + seat (legal place) of arbitration shall be London, United Kingdom. The + tribunal shall consist of one (1) arbitrator. The language of the + arbitration shall be English. The governing law of this arbitration + agreement shall be the laws of England and Wales. To the maximum extent + permitted by applicable law, you may bring claims against the Licensor + only in your individual capacity and not as a claimant or class member + in any purported class, collective, consolidated, or representative + proceeding. Any notices, requests, demands, or other communications + given in connection with the arbitration may be sent in electronic + form, including via email or any electronic filing system operated by + the LCIA, and shall be deemed received when successfully transmitted to + the recipient (as evidenced by no delivery failure notice). + +12. Miscellaneous + + a. Injunctive Relief. You acknowledge and agree that any breach of this + Licence (including any breach of the restrictions on use of the + Software) may cause the Licensor irreparable harm for which damages may + not be an adequate remedy. Accordingly, the Licensor shall be entitled + to seek injunctive relief, specific performance, and/or any other + equitable relief for any such breach, in addition to any other rights + or remedies available at law. + + b. Rights and Remedies. The rights and remedies provided under this + Licence are cumulative and are in addition to, and not exclusive of, + any rights or remedies provided by law. Any right or remedy may be + exercised as often as required. + + c. Assignment. Unless otherwise permitted under this Licence, you shall + not assign, transfer, charge, subcontract, declare a trust over, or + deal in any other manner with any of your rights or obligations under + this Licence without the prior written consent of the Licensor. The + Licensor may at any time assign, transfer, charge, subcontract, or + otherwise deal with any of its rights or obligations under this Licence + without your consent or notice to you. + + d. Severability. If any provision (or part of a provision) of this + Licence is found by any court or competent authority to be invalid, + illegal, or unenforceable, that provision (or part-provision) shall be + deemed modified to the minimum extent necessary to make it valid, + legal, and enforceable. If such modification is not possible, the + relevant provision (or part-provision) shall be deemed deleted. Any + modification to or deletion of a provision (or part-provision) under + this clause shall not affect the validity and enforceability of the + remainder of this Licence. + + e. Entire Agreement. This Licence (together with the Commercial + Licence, if any) constitutes the entire agreement between you and the + Licensor in relation to its subject matter and supersedes and + extinguishes all prior and contemporaneous agreements, understandings, + negotiations, representations, and arrangements between the parties, + whether written or oral. You acknowledge and agree that you shall have + no remedies in respect of any statement, representation, assurance, or + warranty (whether made innocently or negligently) that is not set out + in this Licence (or the Commercial Licence). + + f. Commercial Licence. If a Commercial Licence is in place, it forms an + integral part of this Licence. In the event of any conflict or + inconsistency between the terms of this Licence and the Commercial + Licence, the terms of the Commercial Licence shall prevail to the + extent of such conflict or inconsistency. + + g. Notices. Any notice or other communication given by the Licensor + under or in connection with this Licence may be given using any + available means reasonably selected by the Licensor, including (without + limitation) publication of notice in the Software repository, on the + Licensor’s website, or through any other communication channel + reasonably selected by the Licensor. Where you have a Commercial + Licence in force, any notice or other communication given by the + Licensor under or in connection with this Licence shall be in writing + and may be delivered by email to the email address(es) specified for + notices in the executed Commercial Licence. A notice sent by email + shall be deemed received: (i) if sent during normal business hours, at + the time of transmission; or (ii) if sent outside normal business + hours, at 9:00 a.m. on the next business day. Notices sent by email + shall be legally effective. + + h. Waiver. No failure or delay by the Licensor to exercise any right or + remedy under this Licence or by law shall constitute a waiver of that + or any other right or remedy, nor shall it prevent or restrict any + further exercise of that or any other right or remedy. No single or + partial exercise of any right or remedy shall prevent or restrict the + further exercise of that or any other right or remedy. + + i. Third Party Rights. Except as expressly provided in this clause, a + person who is not a party to this Licence shall not have any rights + under the Contracts (Rights of Third Parties) Act 1999 to enforce any + term of this Licence. Notwithstanding the foregoing, the Licensor’s + affiliates and the Licensor’s directors, officers, employees, + contractors, agents, representatives, and other personnel shall be + entitled, pursuant to the Contracts (Rights of Third Parties) Act 1999, + to enforce and rely on any provision of this Licence that limits or + excludes the liability of the Licensor (including any limitations and + exclusions of liability and any indemnities in favour of the Licensor) + as if they were parties to this Licence. This Licence may be amended, + varied, terminated, or rescinded (in whole or in part) without the + consent of any such person. + +END OF THE LICENCE + +Copyright © Blockscout Limited 2026 diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 001deecbdfeb..000000000000 --- a/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,29 +0,0 @@ -*[GitHub keywords to close any associated issues](https://blog.github.com/2013-05-14-closing-issues-via-pull-requests/)* - -## Motivation - -*Why we should merge these changes. If using GitHub keywords to close [issues](https://github.com/poanetwork/blockscout/issues), this is optional as the motivation can be read on the issue page.* - -## Changelog - -### Enhancements -*Things you added that don't break anything. Regression tests for Bug Fixes count as Enhancements.* - -### Bug Fixes -*Things you changed that fix bugs. If a fixes a bug, but in so doing adds a new requirement, removes code, or requires a database reset and reindex, the breaking part of the change should be added to Incompatible Changes below also.* - -### Incompatible Changes -*Things you broke while doing Enhancements and Bug Fixes. Breaking changes include (1) adding new requirements and (2) removing code. Renaming counts as (2) because a rename is a removal followed by an add.* - -## Upgrading - -*If you have any Incompatible Changes in the above Changelog, outline how users of prior versions can upgrade once this PR lands or when reviewers are testing locally. A common upgrading step is "Database reset and re-index required".* - -## Checklist for your Pull Request (PR) - - - [ ] I added an entry to `CHANGELOG.md` with this PR - - [ ] If I added new functionality, I added tests covering it. - - [ ] If I fixed a bug, I added a regression test to prevent the bug from silently reappearing again. - - [ ] I checked whether I should update the docs and did so by submitting a PR to https://github.com/blockscout/docs - - [ ] If I added/changed/removed ENV var, I submitted a PR to https://github.com/blockscout/docs to update the list of env vars at https://github.com/blockscout/docs/blob/master/for-developers/information-and-settings/env-variables.md and I updated the version to `master` in the Version column. Changes will be reflected in this table: https://docs.blockscout.com/for-developers/information-and-settings/env-variables. - - [ ] If I add new indices into DB, I checked, that they are not redundant with PGHero or other tools diff --git a/README.md b/README.md index 8aa45fdee253..578711d78c21 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,52 @@ -

BlockScout

+

Blockscout

Blockchain Explorer for inspecting and analyzing EVM Chains.

-[![Blockscout](https://github.com/blockscout/blockscout/workflows/Blockscout/badge.svg?branch=master)](https://github.com/blockscout/blockscout/actions) [![Join the chat at https://gitter.im/poanetwork/blockscout](https://badges.gitter.im/poanetwork/blockscout.svg)](https://gitter.im/poanetwork/blockscout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Discord](https://img.shields.io/badge/chat-Blockscout-green.svg)](https://discord.gg/blockscout)
-BlockScout provides a comprehensive, easy-to-use interface for users to view, confirm, and inspect transactions on EVM (Ethereum Virtual Machine) blockchains. This includes the POA Network, xDai Chain, Ethereum Classic and other **Ethereum testnets, private networks and sidechains**. -See our [project documentation](https://docs.blockscout.com/) for detailed information and setup instructions. +Blockscout provides a comprehensive, easy-to-use interface for users to view, confirm, and inspect transactions on EVM (Ethereum Virtual Machine) blockchains. This includes Ethereum Mainnet, Ethereum Classic, Optimism, Gnosis Chain and many other **Ethereum testnets, private networks, L2s and sidechains**. -Visit the [POA BlockScout forum](https://forum.poa.network/c/blockscout) for FAQs, troubleshooting, and other BlockScout related items. You can also post and answer questions here. +See our [project documentation](https://docs.blockscout.com/) for detailed information and setup instructions. -You can also access the dev chatroom on our [Gitter Channel](https://gitter.im/poanetwork/blockscout). +For questions, comments and feature requests see the [discussions section](https://github.com/blockscout/blockscout/discussions) or via [Discord](https://discord.com/invite/blockscout). -## About BlockScout +## About Blockscout -BlockScout is an Elixir application that allows users to search transactions, view accounts and balances, and verify smart contracts on the Ethereum network including all forks and sidechains. +Blockscout allows users to search transactions, view accounts and balances, verify and interact with smart contracts and view and interact with applications on the Ethereum network including many forks, sidechains, L2s and testnets. -Currently available full-featured block explorers (Etherscan, Etherchain, Blockchair) are closed systems which are not independently verifiable. As Ethereum sidechains continue to proliferate in both private and public settings, transparent, open-source tools are needed to analyze and validate transactions. +Blockscout is an open-source alternative to centralized, closed source block explorers such as Etherscan, Etherchain and others. As Ethereum sidechains and L2s continue to proliferate in both private and public settings, transparent, open-source tools are needed to analyze and validate all transactions. ## Supported Projects -BlockScout supports a number of projects. Hosted instances include POA Network, xDai Chain, Ethereum Classic, Sokol & Kovan testnets, and other EVM chains. - -- [List of hosted mainnets, testnets, and additional chains using BlockScout](https://docs.blockscout.com/for-projects/supported-projects) -- [Hosted instance versions](https://docs.blockscout.com/about/use-cases/hosted-blockscout) - +Blockscout currently supports several hundred chains and rollups throughout the greater blockchain ecosystem. Ethereum, Cosmos, Polkadot, Avalanche, Near and many others include Blockscout integrations. A comprehensive list is available at [chains.blockscout.com](https://chains.blockscout.com). If your project is not listed, contact the team in [Discord](https://discord.com/invite/blockscout). ## Getting Started See the [project documentation](https://docs.blockscout.com/) for instructions: -- [Requirements](https://docs.blockscout.com/for-developers/information-and-settings/requirements) + +- [Manual deployment](https://docs.blockscout.com/for-developers/deployment/manual-deployment-guide) +- [Docker-compose deployment](https://docs.blockscout.com/for-developers/deployment/docker-compose-deployment) +- [Kubernetes deployment](https://docs.blockscout.com/for-developers/deployment/kubernetes-deployment) +- [Manual deployment (backend + old UI)](https://docs.blockscout.com/for-developers/deployment/manual-old-ui) - [Ansible deployment](https://docs.blockscout.com/for-developers/ansible-deployment) -- [Manual deployment](https://docs.blockscout.com/for-developers/manual-deployment) -- [ENV variables](https://docs.blockscout.com/for-developers/information-and-settings/env-variables) +- [ENV variables](https://docs.blockscout.com/setup/env-variables) - [Configuration options](https://docs.blockscout.com/for-developers/configuration-options) - ## Acknowledgements -We would like to thank the [EthPrize foundation](http://ethprize.io/) for their funding support. +We would like to thank the EthPrize foundation for their funding support. ## Contributing -See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution and pull request protocol. We expect contributors to follow our [code of conduct](CODE_OF_CONDUCT.md) when submitting code or comments. +See [CONTRIBUTING.md](.github/CONTRIBUTING.md) for contribution and pull request protocol. We expect contributors to follow our [code of conduct](.github/CODE_OF_CONDUCT.md) when submitting code or comments. ## License -[![License: GPL v3.0](https://img.shields.io/badge/License-GPL%20v3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) +[![License: Blockscout Software Licence](https://img.shields.io/badge/License-Blockscout%20Software%20Licence-blue.svg)](LICENSE) + +This project is licensed under the Blockscout Software Licence. See the [LICENSE](LICENSE) file for full terms. -This project is licensed under the GNU General Public License v3.0. See the [LICENSE](LICENSE) file for details. +Third-party components included in this repository remain subject to their own licenses. See dependency manifests and bundled third-party notices for component-level license terms. diff --git a/apps/block_scout_web/.sobelow-conf b/apps/block_scout_web/.sobelow-conf index 99d6ca9eeba0..64b8c550a18f 100644 --- a/apps/block_scout_web/.sobelow-conf +++ b/apps/block_scout_web/.sobelow-conf @@ -7,6 +7,11 @@ format: "compact", ignore: ["Config.Headers", "Config.CSWH", "XSS.SendResp", "XSS.Raw"], ignore_files: [ - "apps/block_scout_web/lib/block_scout_web/views/tokens/instance/overview_view.ex" + "apps/block_scout_web/lib/block_scout_web/routers/tokens_api_v2_router.ex", + "apps/block_scout_web/lib/block_scout_web/routers/smart_contracts_api_v2_router.ex", + "apps/block_scout_web/lib/block_scout_web/routers/utils_api_v2_router.ex", + "apps/block_scout_web/lib/block_scout_web/routers/address_badges_v2_router.ex", + "apps/block_scout_web/lib/block_scout_web/utility/rate_limit_config_helper.ex", + "apps/block_scout_web/lib/block_scout_web/rate_limit.ex" ] ] diff --git a/apps/block_scout_web/API blueprint.md b/apps/block_scout_web/API blueprint.md new file mode 100644 index 000000000000..8e5de5f06ab2 --- /dev/null +++ b/apps/block_scout_web/API blueprint.md @@ -0,0 +1,2102 @@ +FORMAT: 1A +HOST:http://blockscout.com/poa/core +# + + +# API Documentation + + +# Group BlockScoutWeb.Account.Api.V1.UserController +## BlockScoutWeb.Account.Api.V1.UserController [/api/account/v1/user/info] +### BlockScoutWeb.Account.Api.V1.UserController info [GET /api/account/v1/user/info] + + + + + ++ Request Get info about user +**GET**  `/api/account/v1/user/info` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjNkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTM3QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABHGQABG5hbWVtAAAAC1VzZXIgVGVzdDIzZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIzZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIzZAAMd2F0Y2hsaXN0X2lkYgAAARw.E0Sm_2oS5AyE0tua4lSouZRAcWS_F5ZcfGxLWSTUkXA; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2a5ilyuHABAAABjC + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "nickname": "test_user23", + "name": "User Test23", + "email": "test_user-37@blockscout.com", + "avatar": "https://example.com/avatar/test_user23" + } +### BlockScoutWeb.Account.Api.V1.UserController create_tag_address [POST /api/account/v1/user/tags/address] + + + + + ++ Request Add private address tag +**POST**  `/api/account/v1/user/tags/address` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "MyName", + "address_hash": "0x3e9ac8f16c92bc4f093357933b5befbf1e16987b" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyN2QABWVtYWlsbQAAABt0ZXN0X3VzZXItMTdAYmxvY2tzY291dC5jb21kAAJpZGIAAAEMZAAEbmFtZW0AAAAKVXNlciBUZXN0N2QACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI3ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDdkAAx3YXRjaGxpc3RfaWRiAAABDA.nTbrGL1cYPUoZ-N2MiHq9YBaqutQsS6G_gJBJmjD_mE; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2Za89gG9wigAABTB + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "name": "MyName", + "id": 66, + "address_hash": "0x3e9ac8f16c92bc4f093357933b5befbf1e16987b", + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x3E9AC8f16C92bc4F093357933B5BEFBF1E16987B" + } + } + +# Group BlockScoutWeb.Account.Api.V1.TagsController +## BlockScoutWeb.Account.Api.V1.TagsController [/api/account/v1/tags/address/0x3e9ac8f16c92bc4f093357933b5befbf1e16987b] +### BlockScoutWeb.Account.Api.V1.TagsController tags_address [GET /api/account/v1/tags/address/{address_hash}] + + + + ++ Parameters + + address_hash: `0x3e9ac8f16c92bc4f093357933b5befbf1e16987b` + address_hash: 0x3e9ac8f16c92bc4f093357933b5befbf1e16987b + + ++ Request Get tags for address +**GET**  `/api/account/v1/tags/address/0x3e9ac8f16c92bc4f093357933b5befbf1e16987b` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyN2QABWVtYWlsbQAAABt0ZXN0X3VzZXItMTdAYmxvY2tzY291dC5jb21kAAJpZGIAAAEMZAAEbmFtZW0AAAAKVXNlciBUZXN0N2QACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI3ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDdkAAx3YXRjaGxpc3RfaWRiAAABDA.nTbrGL1cYPUoZ-N2MiHq9YBaqutQsS6G_gJBJmjD_mE; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2ZcSwwK9wigAABMC + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "watchlist_names": [], + "personal_tags": [ + { + "label": "MyName", + "display_name": "MyName", + "address_hash": "0x3e9ac8f16c92bc4f093357933b5befbf1e16987b" + } + ], + "common_tags": [] + } + +# Group BlockScoutWeb.Account.Api.V1.UserController +## BlockScoutWeb.Account.Api.V1.UserController [/api/account/v1/user/tags/address/70] +### BlockScoutWeb.Account.Api.V1.UserController update_tag_address [PUT /api/account/v1/user/tags/address/{id}] + + + + ++ Parameters + + id: `70` + id: 70 + + ++ Request Edit private address tag +**PUT**  `/api/account/v1/user/tags/address/70` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "name3", + "address_hash": "0x000000000000000000000000000000000000007e" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTlkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTMxQGJsb2Nrc2NvdXQuY29tZAACaWRiAAABGGQABG5hbWVtAAAAC1VzZXIgVGVzdDE5ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE5ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE5ZAAMd2F0Y2hsaXN0X2lkYgAAARg.gpllu6S6EuYQy2GBhhmdrwjWa7uNmRUMz8aoKGDaPQU; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aYSywZD3jIAAAQF + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "name": "name3", + "id": 70, + "address_hash": "0x000000000000000000000000000000000000007e", + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000007E" + } + } +### BlockScoutWeb.Account.Api.V1.UserController tags_address [GET /api/account/v1/user/tags/address] + + + + + ++ Request Get private addresses tags +**GET**  `/api/account/v1/user/tags/address` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMThkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTMwQGJsb2Nrc2NvdXQuY29tZAACaWRiAAABF2QABG5hbWVtAAAAC1VzZXIgVGVzdDE4ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE4ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE4ZAAMd2F0Y2hsaXN0X2lkYgAAARc.MgpnF7n_gJEhkWphCunY7unXVQWz6NAKdXJtAlCtm-E; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aT84qhvvqoAABfh + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + [ + { + "name": "name2", + "id": 69, + "address_hash": "0x000000000000000000000000000000000000007c", + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000007c" + } + }, + { + "name": "name1", + "id": 68, + "address_hash": "0x000000000000000000000000000000000000007b", + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000007B" + } + }, + { + "name": "name0", + "id": 67, + "address_hash": "0x000000000000000000000000000000000000007a", + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000007a" + } + } + ] +### BlockScoutWeb.Account.Api.V1.UserController delete_tag_address [DELETE /api/account/v1/user/tags/address/{id}] + + + + ++ Parameters + + id: `63` + id: 63 + + ++ Request Delete private address tag +**DELETE**  `/api/account/v1/user/tags/address/63` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyNGQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTRAYmxvY2tzY291dC5jb21kAAJpZGIAAAEJZAAEbmFtZW0AAAAKVXNlciBUZXN0NGQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI0ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDRkAAx3YXRjaGxpc3RfaWRiAAABCQ.3f3SFCRJgY59jb-YfVwAjM-xZEMv78Z1X-yNR03pCOI; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2YwZcxcJlUgAABJh + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "message": "OK" + } +### BlockScoutWeb.Account.Api.V1.UserController create_tag_transaction [POST /api/account/v1/user/tags/transaction] + + + + + ++ Request Create private transaction tag +**POST**  `/api/account/v1/user/tags/transaction` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000006", + "name": "MyName" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTVkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI3QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABFGQABG5hbWVtAAAAC1VzZXIgVGVzdDE1ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE1ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE1ZAAMd2F0Y2hsaXN0X2lkYgAAARQ.y7cpDUrwXiGxhgdOS0V14Rsohk8wJHkv940fW0Mw1YQ; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aDXRGevcEwAABYh + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000006", + "name": "MyName", + "id": 61 + } + + ++ Request Error on try to create private transaction tag for tx does not exist +**POST**  `/api/account/v1/user/tags/transaction` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000005", + "name": "MyName" + } + ++ Response 422 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTVkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI3QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABFGQABG5hbWVtAAAAC1VzZXIgVGVzdDE1ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE1ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE1ZAAMd2F0Y2hsaXN0X2lkYgAAARQ.y7cpDUrwXiGxhgdOS0V14Rsohk8wJHkv940fW0Mw1YQ; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aCGof2vcEwAAAlk + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "errors": { + "tx_hash": [ + "Transaction does not exist" + ] + } + } + +# Group BlockScoutWeb.Account.Api.V1.TagsController +## BlockScoutWeb.Account.Api.V1.TagsController [/api/account/v1/tags/transaction/0x0000000000000000000000000000000000000000000000000000000000000006] +### BlockScoutWeb.Account.Api.V1.TagsController tags_transaction [GET /api/account/v1/tags/transaction/{transaction_hash}] + + + + ++ Parameters + + transaction_hash: `0x0000000000000000000000000000000000000000000000000000000000000006` + transaction_hash: 0x0000000000000000000000000000000000000000000000000000000000000006 + + ++ Request Get tags for transaction +**GET**  `/api/account/v1/tags/transaction/0x0000000000000000000000000000000000000000000000000000000000000006` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTVkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI3QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABFGQABG5hbWVtAAAAC1VzZXIgVGVzdDE1ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE1ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE1ZAAMd2F0Y2hsaXN0X2lkYgAAARQ.y7cpDUrwXiGxhgdOS0V14Rsohk8wJHkv940fW0Mw1YQ; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aEbojKvcEwAABZB + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "watchlist_names": [], + "personal_tx_tag": { + "label": "MyName" + }, + "personal_tags": [], + "common_tags": [] + } + +# Group BlockScoutWeb.Account.Api.V1.UserController +## BlockScoutWeb.Account.Api.V1.UserController [/api/account/v1/user/tags/transaction/57] +### BlockScoutWeb.Account.Api.V1.UserController update_tag_transaction [PUT /api/account/v1/user/tags/transaction/{id}] + + + + ++ Parameters + + id: `57` + id: 57 + + ++ Request Edit private transaction tag +**PUT**  `/api/account/v1/user/tags/transaction/57` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "name": "name1" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMWQABWVtYWlsbQAAABp0ZXN0X3VzZXItMUBibG9ja3Njb3V0LmNvbWQAAmlkYgAAAQZkAARuYW1lbQAAAApVc2VyIFRlc3QxZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjFkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMWQADHdhdGNobGlzdF9pZGIAAAEG.K4xvLgb-ji7_yiP-B80J_ItCchTMzzYcgcN7ku9a4B8; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2XSUU7NY8y8AAAME + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "name": "name1", + "id": 57 + } +### BlockScoutWeb.Account.Api.V1.UserController tags_transaction [GET /api/account/v1/user/tags/transaction] + + + + + ++ Request Get private transactions tags +**GET**  `/api/account/v1/user/tags/transaction` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjJkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTM2QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABG2QABG5hbWVtAAAAC1VzZXIgVGVzdDIyZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIyZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIyZAAMd2F0Y2hsaXN0X2lkYgAAARs.O7Ha2Ze8DT1d2yaZbQEy9tZXE6OUDWyuh3yoyB2WNAU; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2a4GFi44x6sAABii + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + [ + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000009", + "name": "name2", + "id": 64 + }, + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000008", + "name": "name1", + "id": 63 + }, + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000007", + "name": "name0", + "id": 62 + } + ] +### BlockScoutWeb.Account.Api.V1.UserController delete_tag_transaction [DELETE /api/account/v1/user/tags/transaction/{id}] + + + + ++ Parameters + + id: `58` + id: 58 + + ++ Request Delete private transaction tag +**DELETE**  `/api/account/v1/user/tags/transaction/58` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTRkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI2QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABE2QABG5hbWVtAAAAC1VzZXIgVGVzdDE0ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE0ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE0ZAAMd2F0Y2hsaXN0X2lkYgAAARM.XN0A5eUbCpZdpnhayHyU-YiQ4jm1-WjwYxvGD6JVCmg; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2Z9NDKXc1FcAABYC + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "message": "OK" + } +### BlockScoutWeb.Account.Api.V1.UserController create_watchlist [POST /api/account/v1/user/watchlist] + + + + + ++ Request Add address to watch list +**POST**  `/api/account/v1/user/watchlist` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "notification_settings": { + "native": { + "outcoming": true, + "incoming": true + }, + "ERC-721": { + "outcoming": true, + "incoming": false + }, + "ERC-20": { + "outcoming": true, + "incoming": true + } + }, + "notification_methods": { + "email": false + }, + "name": "test26", + "address_hash": "0x000000000000000000000000000000000000007f" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjBkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTMyQGJsb2Nrc2NvdXQuY29tZAACaWRiAAABGWQABG5hbWVtAAAAC1VzZXIgVGVzdDIwZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIwZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIwZAAMd2F0Y2hsaXN0X2lkYgAAARk.vaGEF62HMb-YGk5JNfvq8xH6YkGmQaEEa1gpNIUmjJM; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2acnBbQAq20AAARF + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "notification_settings": { + "native": { + "outcoming": true, + "incoming": true + }, + "ERC-721": { + "outcoming": true, + "incoming": false + }, + "ERC-20": { + "outcoming": true, + "incoming": true + } + }, + "notification_methods": { + "email": false + }, + "name": "test26", + "id": 73, + "exchange_rate": null, + "address_hash": "0x000000000000000000000000000000000000007f", + "address_balance": null, + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000007f" + } + } +### BlockScoutWeb.Account.Api.V1.UserController watchlist [GET /api/account/v1/user/watchlist] + + + + + ++ Request Get addresses from watchlists +**GET**  `/api/account/v1/user/watchlist` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjBkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTMyQGJsb2Nrc2NvdXQuY29tZAACaWRiAAABGWQABG5hbWVtAAAAC1VzZXIgVGVzdDIwZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIwZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIwZAAMd2F0Y2hsaXN0X2lkYgAAARk.vaGEF62HMb-YGk5JNfvq8xH6YkGmQaEEa1gpNIUmjJM; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aiKtdsAq20AABhh + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + [ + { + "notification_settings": { + "native": { + "outcoming": true, + "incoming": true + }, + "ERC-721": { + "outcoming": true, + "incoming": false + }, + "ERC-20": { + "outcoming": false, + "incoming": false + } + }, + "notification_methods": { + "email": true + }, + "name": "test27", + "id": 74, + "exchange_rate": null, + "address_hash": "0x0000000000000000000000000000000000000080", + "address_balance": null, + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000080" + } + }, + { + "notification_settings": { + "native": { + "outcoming": true, + "incoming": true + }, + "ERC-721": { + "outcoming": true, + "incoming": false + }, + "ERC-20": { + "outcoming": true, + "incoming": true + } + }, + "notification_methods": { + "email": false + }, + "name": "test26", + "id": 73, + "exchange_rate": null, + "address_hash": "0x000000000000000000000000000000000000007f", + "address_balance": null, + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000007f" + } + } + ] +### BlockScoutWeb.Account.Api.V1.UserController delete_watchlist [DELETE /api/account/v1/user/watchlist/{id}] + + + + ++ Parameters + + id: `72` + id: 72 + + ++ Request Delete address from watchlist by id +**DELETE**  `/api/account/v1/user/watchlist/72` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTdkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI5QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABFmQABG5hbWVtAAAAC1VzZXIgVGVzdDE3ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE3ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE3ZAAMd2F0Y2hsaXN0X2lkYgAAARY.bngpdS3ELd9RFd1465ZhfhaitqcUi6xG4s0BoDGWoAw; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aNXuJ9GNz0AABch + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "message": "OK" + } +### BlockScoutWeb.Account.Api.V1.UserController update_watchlist [PUT /api/account/v1/user/watchlist/{id}] + + + + ++ Parameters + + id: `70` + id: 70 + + ++ Request Edit watchlist address +**PUT**  `/api/account/v1/user/watchlist/70` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "notification_settings": { + "native": { + "outcoming": false, + "incoming": false + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": true + } + }, + "notification_methods": { + "email": true + }, + "name": "test21", + "address_hash": "0x0000000000000000000000000000000000000064" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTBkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIxQGJsb2Nrc2NvdXQuY29tZAACaWRiAAABD2QABG5hbWVtAAAAC1VzZXIgVGVzdDEwZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjEwZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDEwZAAMd2F0Y2hsaXN0X2lkYgAAAQ8.JqlZQRGTvi6UZy4cEjJW6UYnZgNo0LaoO3R4mxO_fFA; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2Zo1KOm2BRoAAAJl + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "notification_settings": { + "native": { + "outcoming": false, + "incoming": false + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": true + } + }, + "notification_methods": { + "email": true + }, + "name": "test21", + "id": 70, + "exchange_rate": null, + "address_hash": "0x0000000000000000000000000000000000000064", + "address_balance": null, + "address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": false, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000064" + } + } +### BlockScoutWeb.Account.Api.V1.UserController create_watchlist [POST /api/account/v1/user/watchlist] + + + + + ++ Request Example of error on creating watchlist address +**POST**  `/api/account/v1/user/watchlist` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "notification_settings": { + "native": { + "outcoming": false, + "incoming": false + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": true + } + }, + "notification_methods": { + "email": true + }, + "name": "test0", + "address_hash": "0x0000000000000000000000000000000000000001" + } + ++ Response 422 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMGQABWVtYWlsbQAAABp0ZXN0X3VzZXItMEBibG9ja3Njb3V0LmNvbWQAAmlkYgAAAQVkAARuYW1lbQAAAApVc2VyIFRlc3QwZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjBkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMGQADHdhdGNobGlzdF9pZGIAAAEF.4CS6L7Ror_vIdEgjt8Mh9y2TJagC83VObHAGZ-ABOI4; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2W1ZceoPnWQAAATj + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "errors": { + "watchlist_id": [ + "Address already added to the watch list" + ] + } + } +### BlockScoutWeb.Account.Api.V1.UserController update_watchlist [PUT /api/account/v1/user/watchlist/{id}] + + + + ++ Parameters + + id: `69` + id: 69 + + ++ Request Example of error on editing watchlist address +**PUT**  `/api/account/v1/user/watchlist/69` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "notification_settings": { + "native": { + "outcoming": false, + "incoming": false + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": true + } + }, + "notification_methods": { + "email": true + }, + "name": "test0", + "address_hash": "0x0000000000000000000000000000000000000001" + } + ++ Response 422 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMGQABWVtYWlsbQAAABp0ZXN0X3VzZXItMEBibG9ja3Njb3V0LmNvbWQAAmlkYgAAAQVkAARuYW1lbQAAAApVc2VyIFRlc3QwZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjBkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMGQADHdhdGNobGlzdF9pZGIAAAEF.4CS6L7Ror_vIdEgjt8Mh9y2TJagC83VObHAGZ-ABOI4; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2W6esdoPnWQAAAKE + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "errors": { + "watchlist_id": [ + "Address already added to the watch list" + ] + } + } +### BlockScoutWeb.Account.Api.V1.UserController create_api_key [POST /api/account/v1/user/api_keys] + + + + + ++ Request Add api key +**POST**  `/api/account/v1/user/api_keys` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "test" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTZkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI4QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABFWQABG5hbWVtAAAAC1VzZXIgVGVzdDE2ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE2ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE2ZAAMd2F0Y2hsaXN0X2lkYgAAARU.bIr9Nod33f3ivryxZfzUGzSN34H8R1h_oOPJvRdulDY; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2aGwztUoK_8AAAnk + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "name": "test", + "api_key": "5dcfeb7d-6a73-47ed-8001-130692ebdf30" + } + + ++ Request Example of error on creating api key +**POST**  `/api/account/v1/user/api_keys` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "test" + } + ++ Response 422 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjRkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTM4QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABHWQABG5hbWVtAAAAC1VzZXIgVGVzdDI0ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjI0ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDI0ZAAMd2F0Y2hsaXN0X2lkYgAAAR0.K_0yxkRjZq43jcCKzlzgHFNjm7aB_BmvBzlTVbpDUYI; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2a-lcgwKyxIAAAuk + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "errors": { + "name": [ + "Max 3 keys per account" + ] + } + } +### BlockScoutWeb.Account.Api.V1.UserController api_keys [GET /api/account/v1/user/api_keys] + + + + + ++ Request Get api keys list +**GET**  `/api/account/v1/user/api_keys` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjRkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTM4QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABHWQABG5hbWVtAAAAC1VzZXIgVGVzdDI0ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjI0ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDI0ZAAMd2F0Y2hsaXN0X2lkYgAAAR0.K_0yxkRjZq43jcCKzlzgHFNjm7aB_BmvBzlTVbpDUYI; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2a-2qPMKyxIAABki + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + [ + { + "name": "test", + "api_key": "00c90b31-db68-4de5-8022-32b6d9bdfaf2" + }, + { + "name": "test", + "api_key": "936f1623-4cfb-4581-badf-ff82193cc55e" + }, + { + "name": "test", + "api_key": "8af19684-7d84-4fa5-bc5e-98391204fa21" + } + ] +### BlockScoutWeb.Account.Api.V1.UserController update_api_key [PUT /api/account/v1/user/api_keys/{api_key}] + + + + ++ Parameters + + api_key: `e6fcab8c-d092-415d-a64e-caeebdab7e0a` + api_key: e6fcab8c-d092-415d-a64e-caeebdab7e0a + + ++ Request Edit api key +**PUT**  `/api/account/v1/user/api_keys/e6fcab8c-d092-415d-a64e-caeebdab7e0a` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "test_1" + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTNkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI1QGJsb2Nrc2NvdXQuY29tZAACaWRiAAABEmQABG5hbWVtAAAAC1VzZXIgVGVzdDEzZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjEzZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDEzZAAMd2F0Y2hsaXN0X2lkYgAAARI.oCXF9HRta7QoX4kvCCJGwXim8h2PvKmQnL3qC-BrYT0; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2ZxOPw0OLVMAABTC + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "name": "test_1", + "api_key": "e6fcab8c-d092-415d-a64e-caeebdab7e0a" + } +### BlockScoutWeb.Account.Api.V1.UserController delete_api_key [DELETE /api/account/v1/user/api_keys/{api_key}] + + + + ++ Parameters + + api_key: `ed840181-ee0a-49e7-931c-ed12c44c3c5c` + api_key: ed840181-ee0a-49e7-931c-ed12c44c3c5c + + ++ Request Delete api key +**DELETE**  `/api/account/v1/user/api_keys/ed840181-ee0a-49e7-931c-ed12c44c3c5c` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyOGQABWVtYWlsbQAAABt0ZXN0X3VzZXItMThAYmxvY2tzY291dC5jb21kAAJpZGIAAAENZAAEbmFtZW0AAAAKVXNlciBUZXN0OGQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI4ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDhkAAx3YXRjaGxpc3RfaWRiAAABDQ.N8IAT9JlprYQcjF97-2AwyvKRZ2pWrOhPA-piu_yjxY; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2ZeeHae-W7UAABPi + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "message": "OK" + } +### BlockScoutWeb.Account.Api.V1.UserController create_custom_abi [POST /api/account/v1/user/custom_abis] + + + + + ++ Request Add custom abi +**POST**  `/api/account/v1/user/custom_abis` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "test3", + "contract_address_hash": "0x0000000000000000000000000000000000000049", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyNWQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTVAYmxvY2tzY291dC5jb21kAAJpZGIAAAEKZAAEbmFtZW0AAAAKVXNlciBUZXN0NWQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI1ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDVkAAx3YXRjaGxpc3RfaWRiAAABCg.Ed2YB-WoqETtu1WlAOdX7KJi6sFIJ1SGIeS89Aie2pg; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2Y2Ja_DGUGwAAAWE + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "name": "test3", + "id": 146, + "contract_address_hash": "0x0000000000000000000000000000000000000049", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000049" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } + + ++ Request Example of error on creating custom abi +**POST**  `/api/account/v1/user/custom_abis` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "test19", + "contract_address_hash": "0x0000000000000000000000000000000000000059", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } + ++ Response 422 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyNmQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTZAYmxvY2tzY291dC5jb21kAAJpZGIAAAELZAAEbmFtZW0AAAAKVXNlciBUZXN0NmQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI2ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDZkAAx3YXRjaGxpc3RfaWRiAAABCw.SNgNlsqLtHPQ2HgJTPlyNjbvKw2FlW_U6_cJXTD-ZE4; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2ZR-dhCywD0AABJC + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "errors": { + "name": [ + "Max 15 ABIs per account" + ] + } + } +### BlockScoutWeb.Account.Api.V1.UserController custom_abis [GET /api/account/v1/user/custom_abis] + + + + + ++ Request Get custom abis list +**GET**  `/api/account/v1/user/custom_abis` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyNmQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTZAYmxvY2tzY291dC5jb21kAAJpZGIAAAELZAAEbmFtZW0AAAAKVXNlciBUZXN0NmQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI2ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDZkAAx3YXRjaGxpc3RfaWRiAAABCw.SNgNlsqLtHPQ2HgJTPlyNjbvKw2FlW_U6_cJXTD-ZE4; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2ZSytrGywD0AABJi + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + [ + { + "name": "test18", + "id": 161, + "contract_address_hash": "0x0000000000000000000000000000000000000058", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000058" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test17", + "id": 160, + "contract_address_hash": "0x0000000000000000000000000000000000000057", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000057" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test16", + "id": 159, + "contract_address_hash": "0x0000000000000000000000000000000000000056", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000056" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test15", + "id": 158, + "contract_address_hash": "0x0000000000000000000000000000000000000055", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000055" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test14", + "id": 157, + "contract_address_hash": "0x0000000000000000000000000000000000000054", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000054" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test13", + "id": 156, + "contract_address_hash": "0x0000000000000000000000000000000000000053", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000053" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test12", + "id": 155, + "contract_address_hash": "0x0000000000000000000000000000000000000052", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000052" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test11", + "id": 154, + "contract_address_hash": "0x0000000000000000000000000000000000000051", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000051" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test10", + "id": 153, + "contract_address_hash": "0x0000000000000000000000000000000000000050", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000050" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test9", + "id": 152, + "contract_address_hash": "0x000000000000000000000000000000000000004f", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000004f" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test8", + "id": 151, + "contract_address_hash": "0x000000000000000000000000000000000000004e", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000004e" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test7", + "id": 150, + "contract_address_hash": "0x000000000000000000000000000000000000004d", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000004D" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test6", + "id": 149, + "contract_address_hash": "0x000000000000000000000000000000000000004c", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000004C" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test5", + "id": 148, + "contract_address_hash": "0x000000000000000000000000000000000000004b", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000004B" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test4", + "id": 147, + "contract_address_hash": "0x000000000000000000000000000000000000004a", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x000000000000000000000000000000000000004A" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } + ] +### BlockScoutWeb.Account.Api.V1.UserController update_custom_abi [PUT /api/account/v1/user/custom_abis/{id}] + + + + ++ Parameters + + id: `162` + id: 162 + + ++ Request Edit custom abi +**PUT**  `/api/account/v1/user/custom_abis/162` + + + Headers + + content-type: multipart/mixed; boundary=plug_conn_test + + Body + + { + "name": "test23", + "contract_address_hash": "0x0000000000000000000000000000000000000066", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTFkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIyQGJsb2Nrc2NvdXQuY29tZAACaWRiAAABEGQABG5hbWVtAAAAC1VzZXIgVGVzdDExZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjExZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDExZAAMd2F0Y2hsaXN0X2lkYgAAARA.M0fGYF6uHlLOsjA-gLmGzzXuTxSr8hQVlDi3jIhAXX0; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2ZrqXJvdOdEAAAdE + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "name": "test23", + "id": 162, + "contract_address_hash": "0x0000000000000000000000000000000000000066", + "contract_address": { + "watchlist_names": [], + "public_tags": [], + "private_tags": [], + "name": null, + "is_verified": false, + "is_contract": true, + "implementation_name": null, + "hash": "0x0000000000000000000000000000000000000066" + }, + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } +### BlockScoutWeb.Account.Api.V1.UserController delete_custom_abi [DELETE /api/account/v1/user/custom_abis/{id}] + + + + ++ Parameters + + id: `145` + id: 145 + + ++ Request Delete custom abi +**DELETE**  `/api/account/v1/user/custom_abis/145` + + ++ Response 200 + + + Headers + + set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMmQABWVtYWlsbQAAABp0ZXN0X3VzZXItMkBibG9ja3Njb3V0LmNvbWQAAmlkYgAAAQdkAARuYW1lbQAAAApVc2VyIFRlc3QyZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjJkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMmQADHdhdGNobGlzdF9pZGIAAAEH.xeXAG0XBVkoEw0SR5kJ04tyapR1tY5N9XTrN_nrO63c; path=/; SameSite=Lax + content-type: application/json; charset=utf-8 + cache-control: max-age=0, private, must-revalidate + x-request-id: Fy1W2XZv72akD4sAAAQk + access-control-allow-credentials: true + access-control-allow-origin: * + access-control-expose-headers: + + Body + + { + "message": "OK" + } diff --git a/apps/block_scout_web/API.md b/apps/block_scout_web/API.md new file mode 100644 index 000000000000..74ded7812d48 --- /dev/null +++ b/apps/block_scout_web/API.md @@ -0,0 +1,1844 @@ +# API Documentation + + * [BlockScoutWeb.Account.Api.V1.UserController](#blockscoutweb-account-api-v1-usercontroller) + * [info](#blockscoutweb-account-api-v1-usercontroller-info) + * [create_tag_address](#blockscoutweb-account-api-v1-usercontroller-create_tag_address) + * [BlockScoutWeb.Account.Api.V1.TagsController](#blockscoutweb-account-api-v1-tagscontroller) + * [tags_address](#blockscoutweb-account-api-v1-tagscontroller-tags_address) + * [BlockScoutWeb.Account.Api.V1.UserController](#blockscoutweb-account-api-v1-usercontroller) + * [update_tag_address](#blockscoutweb-account-api-v1-usercontroller-update_tag_address) + * [tags_address](#blockscoutweb-account-api-v1-usercontroller-tags_address) + * [delete_tag_address](#blockscoutweb-account-api-v1-usercontroller-delete_tag_address) + * [create_tag_transaction](#blockscoutweb-account-api-v1-usercontroller-create_tag_transaction) + * [BlockScoutWeb.Account.Api.V1.TagsController](#blockscoutweb-account-api-v1-tagscontroller) + * [tags_transaction](#blockscoutweb-account-api-v1-tagscontroller-tags_transaction) + * [BlockScoutWeb.Account.Api.V1.UserController](#blockscoutweb-account-api-v1-usercontroller) + * [update_tag_transaction](#blockscoutweb-account-api-v1-usercontroller-update_tag_transaction) + * [tags_transaction](#blockscoutweb-account-api-v1-usercontroller-tags_transaction) + * [delete_tag_transaction](#blockscoutweb-account-api-v1-usercontroller-delete_tag_transaction) + * [create_watchlist](#blockscoutweb-account-api-v1-usercontroller-create_watchlist) + * [watchlist](#blockscoutweb-account-api-v1-usercontroller-watchlist) + * [delete_watchlist](#blockscoutweb-account-api-v1-usercontroller-delete_watchlist) + * [update_watchlist](#blockscoutweb-account-api-v1-usercontroller-update_watchlist) + * [create_watchlist](#blockscoutweb-account-api-v1-usercontroller-create_watchlist) + * [update_watchlist](#blockscoutweb-account-api-v1-usercontroller-update_watchlist) + * [create_api_key](#blockscoutweb-account-api-v1-usercontroller-create_api_key) + * [api_keys](#blockscoutweb-account-api-v1-usercontroller-api_keys) + * [update_api_key](#blockscoutweb-account-api-v1-usercontroller-update_api_key) + * [delete_api_key](#blockscoutweb-account-api-v1-usercontroller-delete_api_key) + * [create_custom_abi](#blockscoutweb-account-api-v1-usercontroller-create_custom_abi) + * [custom_abis](#blockscoutweb-account-api-v1-usercontroller-custom_abis) + * [update_custom_abi](#blockscoutweb-account-api-v1-usercontroller-update_custom_abi) + * [delete_custom_abi](#blockscoutweb-account-api-v1-usercontroller-delete_custom_abi) + +## BlockScoutWeb.Account.Api.V1.UserController +### info +#### Get info about user + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/user/info + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyNGQABWVtYWlsbQAAABp0ZXN0X3VzZXItNEBibG9ja3Njb3V0LmNvbWQAAmlkYcRkAARuYW1lbQAAAApVc2VyIFRlc3Q0ZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjRkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwNGQADHdhdGNobGlzdF9pZGHE.Ovcc2Vzzv4fhFzmirtQjJ06gcqQwUHMMlju7VX24fyo; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y1_QfU9-YaIAAGdh +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "nickname": "test_user4", + "name": "User Test4", + "email": "test_user-4@blockscout.com", + "avatar": "https://example.com/avatar/test_user4" +} +``` + +### create_tag_address +#### Add private address tag + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/tags/address +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "MyName", + "address_hash": "0x3e9ac8f16c92bc4f093357933b5befbf1e16987b" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMThkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIyQGJsb2Nrc2NvdXQuY29tZAACaWRh0mQABG5hbWVtAAAAC1VzZXIgVGVzdDE4ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE4ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE4ZAAMd2F0Y2hsaXN0X2lkYdI.tFFJ387fBBdBFuMzzeaWcMTeapzMHnbuEfnqTdq5lJ8; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3ALw8xSCMAAAHAC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "name": "MyName", + "id": 61, + "address_hash": "0x3e9ac8f16c92bc4f093357933b5befbf1e16987b" +} +``` + +## BlockScoutWeb.Account.Api.V1.TagsController +### tags_address +#### Get tags for address + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/tags/address/0x3e9ac8f16c92bc4f093357933b5befbf1e16987b + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMThkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIyQGJsb2Nrc2NvdXQuY29tZAACaWRh0mQABG5hbWVtAAAAC1VzZXIgVGVzdDE4ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE4ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE4ZAAMd2F0Y2hsaXN0X2lkYdI.tFFJ387fBBdBFuMzzeaWcMTeapzMHnbuEfnqTdq5lJ8; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3BIWjdSCMAAAG4B +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "watchlist_names": [], + "personal_tags": [ + { + "label": "MyName", + "display_name": "MyName", + "address_hash": "0x3e9ac8f16c92bc4f093357933b5befbf1e16987b" + } + ], + "common_tags": [] +} +``` + +## BlockScoutWeb.Account.Api.V1.UserController +### update_tag_address +#### Edit private address tag + +##### Request +* __Method:__ PUT +* __Path:__ /api/account/v1/user/tags/address/57 +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "name3", + "address_hash": "0x0000000000000000000000000000000000000016" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyN2QABWVtYWlsbQAAABt0ZXN0X3VzZXItMTBAYmxvY2tzY291dC5jb21kAAJpZGHHZAAEbmFtZW0AAAAKVXNlciBUZXN0N2QACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI3ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDdkAAx3YXRjaGxpc3RfaWRhxw.Bn03yTZrlP0m6amYLQVeI-pvhvUf1F6d9SGAkDTLEck; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2IdgOjzsTkAAGYC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "name": "name3", + "id": 57, + "address_hash": "0x0000000000000000000000000000000000000016" +} +``` + +### tags_address +#### Get private addresses tags + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/user/tags/address + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTVkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTE5QGJsb2Nrc2NvdXQuY29tZAACaWRhz2QABG5hbWVtAAAAC1VzZXIgVGVzdDE1ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE1ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE1ZAAMd2F0Y2hsaXN0X2lkYc8.AoYBq7uUH9JOt11vL4-71qtsXMzpPDFsx8BV97n1Y-o; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2ynKDFWAsYAAG5C +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +[ + { + "name": "name2", + "id": 60, + "address_hash": "0x000000000000000000000000000000000000003f" + }, + { + "name": "name1", + "id": 59, + "address_hash": "0x000000000000000000000000000000000000003e" + }, + { + "name": "name0", + "id": 58, + "address_hash": "0x000000000000000000000000000000000000003d" + } +] +``` + +### delete_tag_address +#### Delete private address tag + +##### Request +* __Method:__ DELETE +* __Path:__ /api/account/v1/user/tags/address/62 + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjRkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTM4QGJsb2Nrc2NvdXQuY29tZAACaWRh2GQABG5hbWVtAAAAC1VzZXIgVGVzdDI0ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjI0ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDI0ZAAMd2F0Y2hsaXN0X2lkYdg.x6Qf5zC5gCGQrKy2MbTqd3Xt7S_2oUYaCnO-pbZwRMI; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3biZmVZE0MAAHKC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "message": "OK" +} +``` + +### create_tag_transaction +#### Error on try to create private transaction tag for tx does not exist + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/tags/transaction +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000008", + "name": "MyName" +} +``` + +##### Response +* __Status__: 422 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTlkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIzQGJsb2Nrc2NvdXQuY29tZAACaWRh02QABG5hbWVtAAAAC1VzZXIgVGVzdDE5ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE5ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE5ZAAMd2F0Y2hsaXN0X2lkYdM.zuwR-sOIcF7Xpo97W6G9Szzi_BPlu6Pu9_4kn7T2c10; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3DXWVBu-HUAAG6h +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "errors": { + "tx_hash": [ + "Transaction does not exist" + ] + } +} +``` + +#### Create private transaction tag + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/tags/transaction +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000009", + "name": "MyName" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTlkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIzQGJsb2Nrc2NvdXQuY29tZAACaWRh02QABG5hbWVtAAAAC1VzZXIgVGVzdDE5ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE5ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE5ZAAMd2F0Y2hsaXN0X2lkYdM.zuwR-sOIcF7Xpo97W6G9Szzi_BPlu6Pu9_4kn7T2c10; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3EB0Ytu-HUAAG7B +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000009", + "name": "MyName", + "id": 64 +} +``` + +## BlockScoutWeb.Account.Api.V1.TagsController +### tags_transaction +#### Get tags for transaction + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/tags/transaction/0x0000000000000000000000000000000000000000000000000000000000000009 + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTlkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIzQGJsb2Nrc2NvdXQuY29tZAACaWRh02QABG5hbWVtAAAAC1VzZXIgVGVzdDE5ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE5ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE5ZAAMd2F0Y2hsaXN0X2lkYdM.zuwR-sOIcF7Xpo97W6G9Szzi_BPlu6Pu9_4kn7T2c10; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3Efe0tu-HUAAG7h +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "watchlist_names": [], + "personal_tx_tag": { + "label": "MyName" + }, + "personal_tags": [], + "common_tags": [] +} +``` + +## BlockScoutWeb.Account.Api.V1.UserController +### update_tag_transaction +#### Edit private transaction tag + +##### Request +* __Method:__ PUT +* __Path:__ /api/account/v1/user/tags/transaction/57 +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "name": "name1" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMGQABWVtYWlsbQAAABp0ZXN0X3VzZXItMEBibG9ja3Njb3V0LmNvbWQAAmlkYcBkAARuYW1lbQAAAApVc2VyIFRlc3QwZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjBkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMGQADHdhdGNobGlzdF9pZGHA.-aMP6TTEeEfxopoeChJPvTvjkSRD9_ZgaeLDlOC21gU; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y1xoENHeIlkAAGEi +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000001", + "name": "name1", + "id": 57 +} +``` + +### tags_transaction +#### Get private transactions tags + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/user/tags/transaction + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTRkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTE4QGJsb2Nrc2NvdXQuY29tZAACaWRhzmQABG5hbWVtAAAAC1VzZXIgVGVzdDE0ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE0ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE0ZAAMd2F0Y2hsaXN0X2lkYc4.8SGhlMOY4aB444Afz1VajofmGp9YZbrfbVkZ4BTyaBI; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2tEsVp5P30AAGzi +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +[ + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000004", + "name": "name2", + "id": 60 + }, + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000003", + "name": "name1", + "id": 59 + }, + { + "transaction_hash": "0x0000000000000000000000000000000000000000000000000000000000000002", + "name": "name0", + "id": 58 + } +] +``` + +### delete_tag_transaction +#### Delete private transaction tag + +##### Request +* __Method:__ DELETE +* __Path:__ /api/account/v1/user/tags/transaction/61 + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTZkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIwQGJsb2Nrc2NvdXQuY29tZAACaWRh0GQABG5hbWVtAAAAC1VzZXIgVGVzdDE2ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE2ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE2ZAAMd2F0Y2hsaXN0X2lkYdA.YfL9L7-UIBleRbWWhHNvutNuw8Y4SadvwGFmGwakxQA; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y26c9UuC4TcAAGwh +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "message": "OK" +} +``` + +### create_watchlist +#### Add address to watch list + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/watchlist +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": false + } + }, + "notification_methods": { + "email": true + }, + "name": "test2", + "address_hash": "0x0000000000000000000000000000000000000007" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyM2QABWVtYWlsbQAAABp0ZXN0X3VzZXItM0BibG9ja3Njb3V0LmNvbWQAAmlkYcNkAARuYW1lbQAAAApVc2VyIFRlc3QzZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjNkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwM2QADHdhdGNobGlzdF9pZGHD.kv5nnz8sVGLaopoZs9ppOfu0hfpFi58yuisPDN6PtPI; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y16Kv_0GzWcAAGKi +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": false + } + }, + "notification_methods": { + "email": true + }, + "name": "test2", + "id": 68, + "exchange_rate": null, + "address_hash": "0x0000000000000000000000000000000000000007", + "address_balance": null +} +``` + +### watchlist +#### Get addresses from watchlists + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/user/watchlist + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyM2QABWVtYWlsbQAAABp0ZXN0X3VzZXItM0BibG9ja3Njb3V0LmNvbWQAAmlkYcNkAARuYW1lbQAAAApVc2VyIFRlc3QzZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjNkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwM2QADHdhdGNobGlzdF9pZGHD.kv5nnz8sVGLaopoZs9ppOfu0hfpFi58yuisPDN6PtPI; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y19FyIUGzWcAAGMC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +[ + { + "notification_settings": { + "native": { + "outcoming": false, + "incoming": false + }, + "ERC-721": { + "outcoming": true, + "incoming": false + }, + "ERC-20": { + "outcoming": true, + "incoming": false + } + }, + "notification_methods": { + "email": false + }, + "name": "test3", + "id": 69, + "exchange_rate": null, + "address_hash": "0x0000000000000000000000000000000000000008", + "address_balance": null + }, + { + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": false, + "incoming": true + }, + "ERC-20": { + "outcoming": false, + "incoming": false + } + }, + "notification_methods": { + "email": true + }, + "name": "test2", + "id": 68, + "exchange_rate": null, + "address_hash": "0x0000000000000000000000000000000000000007", + "address_balance": null + } +] +``` + +### delete_watchlist +#### Delete address from watchlist by id + +##### Request +* __Method:__ DELETE +* __Path:__ /api/account/v1/user/watchlist/74 + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTFkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTE0QGJsb2Nrc2NvdXQuY29tZAACaWRhy2QABG5hbWVtAAAAC1VzZXIgVGVzdDExZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjExZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDExZAAMd2F0Y2hsaXN0X2lkYcs.YjW8nzuA66id0ADg2qpyjTMGfKJ7BHhjU_HdVq8w8vk; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2f5j2WpY30AAGuC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "message": "OK" +} +``` + +### update_watchlist +#### Edit watchlist address + +##### Request +* __Method:__ PUT +* __Path:__ /api/account/v1/user/watchlist/67 +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": true, + "incoming": true + }, + "ERC-20": { + "outcoming": true, + "incoming": true + } + }, + "notification_methods": { + "email": true + }, + "name": "test1", + "address_hash": "0x0000000000000000000000000000000000000006" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMWQABWVtYWlsbQAAABp0ZXN0X3VzZXItMUBibG9ja3Njb3V0LmNvbWQAAmlkYcFkAARuYW1lbQAAAApVc2VyIFRlc3QxZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjFkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMWQADHdhdGNobGlzdF9pZGHB.3KOkZkPrcMrRXfooQckn-zi6xmax1LJMBGBSjmGM8ww; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y12FoNKu97sAAGch +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": true, + "incoming": true + }, + "ERC-20": { + "outcoming": true, + "incoming": true + } + }, + "notification_methods": { + "email": true + }, + "name": "test1", + "id": 67, + "exchange_rate": null, + "address_hash": "0x0000000000000000000000000000000000000006", + "address_balance": null +} +``` + +### create_watchlist +#### Example of error on creating watchlist address + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/watchlist +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": false, + "incoming": false + }, + "ERC-20": { + "outcoming": true, + "incoming": false + } + }, + "notification_methods": { + "email": false + }, + "name": "test4", + "address_hash": "0x0000000000000000000000000000000000000017" +} +``` + +##### Response +* __Status__: 422 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyOGQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTFAYmxvY2tzY291dC5jb21kAAJpZGHIZAAEbmFtZW0AAAAKVXNlciBUZXN0OGQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI4ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDhkAAx3YXRjaGxpc3RfaWRhyA.q1Rmte0qLd31GbmpA46bE8rXo2okwzX8aD_oDHn8CIQ; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2MCqHvooPMAAGbi +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "errors": { + "watchlist_id": [ + "Address already added to the watch list" + ] + } +} +``` + +### update_watchlist +#### Example of error on editing watchlist address + +##### Request +* __Method:__ PUT +* __Path:__ /api/account/v1/user/watchlist/72 +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "notification_settings": { + "native": { + "outcoming": false, + "incoming": true + }, + "ERC-721": { + "outcoming": false, + "incoming": false + }, + "ERC-20": { + "outcoming": true, + "incoming": false + } + }, + "notification_methods": { + "email": false + }, + "name": "test4", + "address_hash": "0x0000000000000000000000000000000000000017" +} +``` + +##### Response +* __Status__: 422 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyOGQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTFAYmxvY2tzY291dC5jb21kAAJpZGHIZAAEbmFtZW0AAAAKVXNlciBUZXN0OGQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI4ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDhkAAx3YXRjaGxpc3RfaWRhyA.q1Rmte0qLd31GbmpA46bE8rXo2okwzX8aD_oDHn8CIQ; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2Nh1eHooPMAAGci +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "errors": { + "watchlist_id": [ + "Address already added to the watch list" + ] + } +} +``` + +### create_api_key +#### Add api key + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/api_keys +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "test" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMmQABWVtYWlsbQAAABp0ZXN0X3VzZXItMkBibG9ja3Njb3V0LmNvbWQAAmlkYcJkAARuYW1lbQAAAApVc2VyIFRlc3QyZAAIbmlja25hbWVtAAAACnRlc3RfdXNlcjJkAAN1aWRtAAAAD2Jsb2Nrc2NvdXR8MDAwMmQADHdhdGNobGlzdF9pZGHC.ULESD1_sOySz8eEVGnagUzGw6eMIx_8Pwoyr_5S3K0M; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y14XlMBqXaQAAGHi +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "name": "test", + "api_key": "de9ef457-3f47-48d3-affa-79ad9d3b27b9" +} +``` + +#### Example of error on creating api key + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/api_keys +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "test" +} +``` + +##### Response +* __Status__: 422 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjJkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI2QGJsb2Nrc2NvdXQuY29tZAACaWRh1mQABG5hbWVtAAAAC1VzZXIgVGVzdDIyZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIyZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIyZAAMd2F0Y2hsaXN0X2lkYdY.P37J2lZZdHaT4P-RatVaXCx77UcSH3s_TMx-FieaYk0; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3LmuuofZKYAAG_h +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "errors": { + "name": [ + "Max 3 keys per account" + ] + } +} +``` + +### api_keys +#### Get api keys list + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/user/api_keys + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjJkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI2QGJsb2Nrc2NvdXQuY29tZAACaWRh1mQABG5hbWVtAAAAC1VzZXIgVGVzdDIyZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIyZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIyZAAMd2F0Y2hsaXN0X2lkYdY.P37J2lZZdHaT4P-RatVaXCx77UcSH3s_TMx-FieaYk0; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3LyOSIfZKYAAHAB +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +[ + { + "name": "test", + "api_key": "2ac16688-34e6-4fa4-8983-a9bc34c912f6" + }, + { + "name": "test", + "api_key": "a55426db-04f0-40be-a146-1ced4558aa0c" + }, + { + "name": "test", + "api_key": "d73fc23b-59f0-4e6f-a739-f4de30995101" + } +] +``` + +### update_api_key +#### Edit api key + +##### Request +* __Method:__ PUT +* __Path:__ /api/account/v1/user/api_keys/2b1d400d-713e-4bfc-8ef0-710555693138 +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "test_1" +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTdkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTIxQGJsb2Nrc2NvdXQuY29tZAACaWRh0WQABG5hbWVtAAAAC1VzZXIgVGVzdDE3ZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjE3ZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDE3ZAAMd2F0Y2hsaXN0X2lkYdE.bLJKM3-kFm04mMC-4-3b2mjrig_lmQYt5C2tg-9q9so; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2-0eR7T2BMAAG0B +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "name": "test_1", + "api_key": "2b1d400d-713e-4bfc-8ef0-710555693138" +} +``` + +### delete_api_key +#### Delete api key + +##### Request +* __Method:__ DELETE +* __Path:__ /api/account/v1/user/api_keys/3bd44c0d-290f-4dfc-9283-5f674080f8ef + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjBkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI0QGJsb2Nrc2NvdXQuY29tZAACaWRh1GQABG5hbWVtAAAAC1VzZXIgVGVzdDIwZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIwZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIwZAAMd2F0Y2hsaXN0X2lkYdQ.WgjMmOxwwBGcTZZscpLA8EXErwL8ITCvoIXPLIQAhtw; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3HQdpa0710AAHBi +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "message": "OK" +} +``` + +### create_custom_abi +#### Add custom abi + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/custom_abis +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "test25", + "contract_address_hash": "0x000000000000000000000000000000000000002c", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTJkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTE1QGJsb2Nrc2NvdXQuY29tZAACaWRhzGQABG5hbWVtAAAAC1VzZXIgVGVzdDEyZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjEyZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDEyZAAMd2F0Y2hsaXN0X2lkYcw.7cCOt6SVrOb5VLYplBzwZ03FWMo9jQpAV7cNroY4txY; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2iZJWbZgfgAAGwC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "name": "test25", + "id": 143, + "contract_address_hash": "0x000000000000000000000000000000000000002c", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] +} +``` + +#### Example of error on creating custom abi + +##### Request +* __Method:__ POST +* __Path:__ /api/account/v1/user/custom_abis +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "test21", + "contract_address_hash": "0x0000000000000000000000000000000000000028", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] +} +``` + +##### Response +* __Status__: 422 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyOWQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTJAYmxvY2tzY291dC5jb21kAAJpZGHJZAAEbmFtZW0AAAAKVXNlciBUZXN0OWQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI5ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDlkAAx3YXRjaGxpc3RfaWRhyQ.MCpJsS-nb95ccHRtzOk7DbIRjEcTG34ONq4PrC5hOcU; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2Ypm-ny0swAAGiB +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "errors": { + "name": [ + "Max 15 ABIs per account" + ] + } +} +``` + +### custom_abis +#### Get custom abis list + +##### Request +* __Method:__ GET +* __Path:__ /api/account/v1/user/custom_abis + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAlaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyOWQABWVtYWlsbQAAABt0ZXN0X3VzZXItMTJAYmxvY2tzY291dC5jb21kAAJpZGHJZAAEbmFtZW0AAAAKVXNlciBUZXN0OWQACG5pY2tuYW1lbQAAAAp0ZXN0X3VzZXI5ZAADdWlkbQAAAA9ibG9ja3Njb3V0fDAwMDlkAAx3YXRjaGxpc3RfaWRhyQ.MCpJsS-nb95ccHRtzOk7DbIRjEcTG34ONq4PrC5hOcU; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2Y-qjXy0swAAGnC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +[ + { + "name": "test20", + "id": 141, + "contract_address_hash": "0x0000000000000000000000000000000000000027", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test19", + "id": 140, + "contract_address_hash": "0x0000000000000000000000000000000000000026", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test18", + "id": 139, + "contract_address_hash": "0x0000000000000000000000000000000000000025", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test17", + "id": 138, + "contract_address_hash": "0x0000000000000000000000000000000000000024", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test16", + "id": 137, + "contract_address_hash": "0x0000000000000000000000000000000000000023", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test15", + "id": 136, + "contract_address_hash": "0x0000000000000000000000000000000000000022", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test14", + "id": 135, + "contract_address_hash": "0x0000000000000000000000000000000000000021", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test13", + "id": 134, + "contract_address_hash": "0x0000000000000000000000000000000000000020", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test12", + "id": 133, + "contract_address_hash": "0x000000000000000000000000000000000000001f", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test11", + "id": 132, + "contract_address_hash": "0x000000000000000000000000000000000000001e", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test10", + "id": 131, + "contract_address_hash": "0x000000000000000000000000000000000000001d", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test9", + "id": 130, + "contract_address_hash": "0x000000000000000000000000000000000000001c", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test8", + "id": 129, + "contract_address_hash": "0x000000000000000000000000000000000000001b", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test7", + "id": 128, + "contract_address_hash": "0x000000000000000000000000000000000000001a", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + }, + { + "name": "test6", + "id": 127, + "contract_address_hash": "0x0000000000000000000000000000000000000019", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] + } +] +``` + +### update_custom_abi +#### Edit custom abi + +##### Request +* __Method:__ PUT +* __Path:__ /api/account/v1/user/custom_abis/144 +* __Request headers:__ +``` +content-type: multipart/mixed; boundary=plug_conn_test +``` +* __Request body:__ +```json +{ + "name": "test27", + "contract_address_hash": "0x000000000000000000000000000000000000004b", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] +} +``` + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMjFkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTI1QGJsb2Nrc2NvdXQuY29tZAACaWRh1WQABG5hbWVtAAAAC1VzZXIgVGVzdDIxZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjIxZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDIxZAAMd2F0Y2hsaXN0X2lkYdU.SEUqq9ZiSD79HIzwKvwTspmBKKU87m_Xwu5gw2pX1e0; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y3JcHmB4X2AAAHDC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "name": "test27", + "id": 144, + "contract_address_hash": "0x000000000000000000000000000000000000004b", + "abi": [ + { + "type": "function", + "stateMutability": "nonpayable", + "payable": false, + "outputs": [], + "name": "set", + "inputs": [ + { + "type": "uint256", + "name": "x" + } + ], + "constant": false + }, + { + "type": "function", + "stateMutability": "view", + "payable": false, + "outputs": [ + { + "type": "uint256", + "name": "" + } + ], + "name": "get", + "inputs": [], + "constant": true + } + ] +} +``` + +### delete_custom_abi +#### Delete custom abi + +##### Request +* __Method:__ DELETE +* __Path:__ /api/account/v1/user/custom_abis/142 + +##### Response +* __Status__: 200 +* __Response headers:__ +``` +set-cookie: _explorer_key=SFMyNTY.g3QAAAABbQAAAAxjdXJyZW50X3VzZXJ0AAAAB2QABmF2YXRhcm0AAAAmaHR0cHM6Ly9leGFtcGxlLmNvbS9hdmF0YXIvdGVzdF91c2VyMTBkAAVlbWFpbG0AAAAbdGVzdF91c2VyLTEzQGJsb2Nrc2NvdXQuY29tZAACaWRhymQABG5hbWVtAAAAC1VzZXIgVGVzdDEwZAAIbmlja25hbWVtAAAAC3Rlc3RfdXNlcjEwZAADdWlkbQAAABBibG9ja3Njb3V0fDAwMDEwZAAMd2F0Y2hsaXN0X2lkYco.x_6dmEjpZ1o8_ct-M7pWWP0LkI66xhwl8gWeQt9XzHA; path=/; HttpOnly +content-type: application/json; charset=utf-8 +cache-control: max-age=0, private, must-revalidate +x-request-id: FxF1Y2b1jJGBaO4AAGrC +access-control-allow-credentials: true +access-control-allow-origin: * +access-control-expose-headers: +``` +* __Response body:__ +```json +{ + "message": "OK" +} +``` diff --git a/apps/block_scout_web/README.md b/apps/block_scout_web/README.md index 5f6d2d67014e..448152b981af 100644 --- a/apps/block_scout_web/README.md +++ b/apps/block_scout_web/README.md @@ -1,6 +1,6 @@ # BlockScout Web -This is a tool for inspecting and analyzing the POA Network blockchain from a web browser. +BlockScoutWeb is the API and presentation layer of BlockScout built on the Phoenix framework. It exposes RESTful and GraphQL APIs for accessing blockchain data. It directs HTTP requests through Phoenix routers to controllers that manage resources like addresses, transactions, blocks, and tokens. It formats responses as JSON via view modules. It provides real-time updates on new blocks, transactions, and exchange rates using Phoenix Channels. It supports smart contract verification through multiple methods including integration with Sourcify. Custom plugs add functionalities such as rate limiting, API version checks, and logging. Configuration is retrieved from the application environment. It manages errors through fallback controllers. ## Machine Requirements @@ -8,21 +8,19 @@ This is a tool for inspecting and analyzing the POA Network blockchain from a we * Elixir 1.9+ * Postgres 10.3 - ## Required Accounts * Github for code storage - ## Setup Instructions ### Development To get BlockScout Web interface up and running locally: - * Setup `../explorer` - * Install Node.js dependencies with `$ cd assets && npm install && cd ..` - * Start Phoenix with `$ mix phx.server` (This can be run from this directory or the project root: the project root is recommended.) +* Setup `../explorer` +* Install Node.js dependencies with `$ cd assets && npm install && cd ..` +* Start Phoenix with `$ mix phx.server` (This can be run from this directory or the project root: the project root is recommended.) Now you can visit [`localhost:4000`](http://localhost:4000) from your browser. @@ -30,14 +28,13 @@ You can also run IEx (Interactive Elixir): `$ iex -S mix phx.server` (This can b ### Testing - * Build the assets: `cd assets && npm run build` - * Format the Elixir code: `mix format` - * Lint the Elixir code: `mix credo --strict` - * Run the dialyzer: `mix dialyzer --halt-exit-status` - * Check the Elixir code for vulnerabilities: `mix sobelow --config` - * Update translations templates and translations and check there are no uncommitted changes: `mix gettext.extract --merge` - * Lint the JavaScript code: `cd assets && npm run eslint` - +* Build the assets: `cd assets && npm run build` +* Format the Elixir code: `mix format` +* Lint the Elixir code: `mix credo --strict` +* Run the dialyzer: `mix dialyzer --halt-exit-status` +* Check the Elixir code for vulnerabilities: `mix sobelow --config` +* Update translation templates and translations and check there are no uncommitted changes: `mix gettext.extract --merge` +* Lint the JavaScript code: `cd assets && npm run eslint` ## Internationalization diff --git a/apps/block_scout_web/SMART_CONTRACT_VERIFICATION_WEBSOCKET.md b/apps/block_scout_web/SMART_CONTRACT_VERIFICATION_WEBSOCKET.md new file mode 100644 index 000000000000..b330f68bcf0e --- /dev/null +++ b/apps/block_scout_web/SMART_CONTRACT_VERIFICATION_WEBSOCKET.md @@ -0,0 +1,253 @@ +# Smart Contract Verification Websocket Events + +This guide explains how to subscribe to websocket notifications related to smart contract verification. + +It covers: +- verification result notifications +- automated source lookup lifecycle notifications +- legacy and V2 websocket namespaces + +## 1. Which Socket To Use + +Blockscout exposes two websocket endpoints: + +- Legacy UI socket: `/socket` +- V2 socket: `/socket/v2` + +For new integrations, use the V2 socket. + +## 2. Topic Format + +Subscribe to an address topic. + +- Legacy topic: `addresses_old:` +- V2 topic: `addresses:` + +Examples: +- `addresses_old:0xabc123...` +- `addresses:0xabc123...` + +The join validates the address hash and access restrictions. Join may fail with: +- `Invalid address hash` +- `Restricted access` + +## 3. Events You Can Receive + +### 3.1 `verification_result` + +Purpose: +- Final result of a verification attempt (success or validation errors). + +Emitted to topics: +- `addresses:` +- `addresses_old:` + +Broadcast type in event bus: +- `:on_demand` + +#### V2 payload + +Success: + +```json +{ + "status": "success" +} +``` + +Error: + +```json +{ + "status": "error", + "errors": { + "field_name": [ + "error message" + ] + } +} +``` + +Notes: +- `errors` is generated from changeset errors. +- Field names and messages depend on verification flow and validator results. + +#### Legacy behavior + +Legacy notifier broadcasts an internal payload with `result`, but the legacy address channel intercepts `verification_result` and pushes event `verification` to clients. + +Legacy client-facing event: +- `verification` + +Legacy client payload: + +```json +{ + "verification_result": "ok" +} +``` + +or + +```json +{ + "verification_result": "" +} +``` + +Important legacy nuance: +- If the intercepted result is `{:error, %Ecto.Changeset{}}`, the channel does not push a websocket message for that event. + +### 3.2 `eth_bytecode_db_lookup_started` + +Purpose: +- Signals that automated lookup in Ethereum Bytecode DB started. + +Emitted to topics: +- `addresses:` +- `addresses_old:` + +Payload: + +```json +{} +``` + +### 3.3 `smart_contract_was_verified` + +Purpose: +- Signals that automated lookup/verification finished with a verified result. + +Emitted to topics: +- `addresses:` +- `addresses_old:` + +Payload: + +```json +{} +``` + +### 3.4 `smart_contract_was_not_verified` + +Purpose: +- Signals that automated lookup/verification finished without verification. + +Emitted to topics: +- `addresses:` +- `addresses_old:` + +Payload: + +```json +{} +``` + +## 4. Event Producers (Server-Side) + +### `contract_verification_result` chain event + +Produced by verification workers/helpers and then mapped to websocket `verification_result`: +- Solidity verification worker +- Vyper verification worker +- Stylus verification worker +- Solidity publish helper (including some error paths) + +### Automated source lookup lifecycle chain events + +Produced by on-demand source lookup fetcher and mapped 1:1 to websocket event names: +- `eth_bytecode_db_lookup_started` +- `smart_contract_was_verified` +- `smart_contract_was_not_verified` + +## 5. Subscription Example (Phoenix JS) + +### V2 (recommended) + +```javascript +import { Socket } from "phoenix"; + +const socket = new Socket("https://your-blockscout.example/socket/v2", { + params: {} +}); + +socket.connect(); + +const addressHash = "0x..."; +const channel = socket.channel(`addresses:${addressHash}`, {}); + +channel + .join() + .receive("ok", () => console.log("joined")) + .receive("error", (err) => console.error("join failed", err)); + +channel.on("verification_result", (payload) => { + // { status: "success" } OR { status: "error", errors: {...} } + console.log("verification_result", payload); +}); + +channel.on("eth_bytecode_db_lookup_started", () => { + console.log("lookup started"); +}); + +channel.on("smart_contract_was_verified", () => { + console.log("verified via automatic lookup"); +}); + +channel.on("smart_contract_was_not_verified", () => { + console.log("not verified via automatic lookup"); +}); +``` + +### Legacy + +```javascript +import { Socket } from "phoenix"; + +const socket = new Socket("https://your-blockscout.example/socket", { + params: { locale: "en" } +}); + +socket.connect(); + +const addressHash = "0x..."; +const channel = socket.channel(`addresses_old:${addressHash}`, {}); + +channel.join(); + +// Legacy verification result event name is "verification" +channel.on("verification", (payload) => { + // payload.verification_result is "ok" or rendered html error string + console.log("verification", payload); +}); + +// Automatic lookup lifecycle events are forwarded with original names +channel.on("eth_bytecode_db_lookup_started", () => { + console.log("lookup started"); +}); + +channel.on("smart_contract_was_verified", () => { + console.log("verified"); +}); + +channel.on("smart_contract_was_not_verified", () => { + console.log("not verified"); +}); +``` + +## 6. Practical Client Flow + +Recommended for automation clients: + +1. Submit verification request via HTTP API. +2. Immediately subscribe to `addresses:` on `/socket/v2`. +3. Wait for `verification_result` for final API-style outcome. +4. Optionally track automated lookup lifecycle with: + - `eth_bytecode_db_lookup_started` + - `smart_contract_was_verified` + - `smart_contract_was_not_verified` + +Notes: +- API response like "verification started" means the job was accepted, not completed. +- Final state should be taken from websocket events. +- Server currently broadcasts to both legacy and V2 address namespaces for backward compatibility. diff --git a/apps/block_scout_web/assets/.eslintrc b/apps/block_scout_web/assets/.eslintrc deleted file mode 100644 index 535509b69a40..000000000000 --- a/apps/block_scout_web/assets/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "extends": "standard", - "env": { - "browser": true - } -} diff --git a/apps/block_scout_web/assets/__tests__/lib/autocomplete.js b/apps/block_scout_web/assets/__tests__/lib/autocomplete.js new file mode 100644 index 000000000000..877474c92797 --- /dev/null +++ b/apps/block_scout_web/assets/__tests__/lib/autocomplete.js @@ -0,0 +1,31 @@ +/** + * @jest-environment jsdom + */ + + import { searchEngine } from '../../js/lib/autocomplete' + + test('searchEngine', () => { + expect(searchEngine('qwe', { + 'name': 'Test', + 'symbol': 'TST', + 'address_hash': '0x000', + 'tx_hash': '0x000', + 'block_hash': '0x000' + })).toEqual(undefined) + + expect(searchEngine('tes', { + 'name': 'Test', + 'symbol': 'TST', + 'address_hash': '0x000', + 'tx_hash': '0x000', + 'block_hash': '0x000' + })).toEqual('
0x000
Test (TST)
') + + expect(searchEngine('qwe', { + 'name': 'qwe1\'">