From 245bbbfca7b9bfaf5dcb782d107b7c5f5505b213 Mon Sep 17 00:00:00 2001 From: Harbduls Date: Wed, 24 Jun 2026 04:32:49 +0100 Subject: [PATCH] added pause status integration --- .github/workflows/ci.yml | 73 + .github/workflows/staging.yml | 23 + .../specs/event-explorer-filters/.config.kiro | 1 + .../event-explorer-filters/requirements.md | 155 + ARCHITECTURE_OVERVIEW.md | 482 + CONTRACT_UPGRADE_GUIDE.md | 312 + CONTRIBUTING.md | 176 + NOTIFICATION_FAILURE_RECOVERY.md | 332 + NOTIFICATION_PAYLOAD_SCHEMA.md | 231 + PULL_REQUEST_SUMMARY.md | 327 + RATE-LIMITING-IMPLEMENTATION.md | 459 + README.md | 568 +- REVOCATION_CHANGELOG.md | 558 + REVOCATION_IMPLEMENTATION_GUIDE.md | 315 + REVOCATION_INTERFACE_CHANGES.md | 489 + REVOCATION_ISSUE_COMPLETION.md | 471 + REVOCATION_QUICK_REFERENCE.md | 465 + REVOCATION_SUMMARY.md | 222 + SCHEDULED-NOTIFICATIONS-DELIVERY.md | 443 + TROUBLESHOOTING.md | 397 + contract/README.md | 75 +- .../hello-world/src/autoshare_logic.rs | 337 +- .../contracts/hello-world/src/base/errors.rs | 55 +- .../contracts/hello-world/src/base/events.rs | 186 +- .../contracts/hello-world/src/base/types.rs | 26 + .../hello-world/src/interfaces/autoshare.rs | 8 +- contract/contracts/hello-world/src/lib.rs | 115 +- .../hello-world/src/tests/autoshare_test.rs | 354 +- .../hello-world/src/tests/expiration_test.rs | 328 + .../src/tests/notification_test.rs | 579 + .../hello-world/src/tests/pause_test.rs | 2 +- .../hello-world/src/tests/revocation_test.rs | 360 + .../hello-world/src/tests/version_test.rs | 11 + dashboard/.env.example | 8 + dashboard/.env.staging | 2 + dashboard/.eslintignore | 6 + dashboard/.eslintrc.cjs | 20 + dashboard/.gitignore | 3 + .../event-explorer-filters/requirements.md | 141 + dashboard/index.html | 12 + dashboard/jest.config.cjs | 27 + dashboard/jest.setup.cjs | 26 + dashboard/package-lock.json | 19226 ++++++++++++++++ dashboard/package.json | 44 + dashboard/src/App.tsx | 9 + .../src/benchmark/render-benchmark.test.tsx | 50 + dashboard/src/components/EventCard.test.tsx | 38 + dashboard/src/components/EventCard.tsx | 234 + .../src/components/EventExplorerCard.tsx | 95 + .../src/components/EventExplorerSkeleton.tsx | 22 + .../src/components/EventExplorerTable.tsx | 69 + .../src/components/EventFiltersBar.test.tsx | 36 + dashboard/src/components/EventFiltersBar.tsx | 60 + dashboard/src/components/EventList.tsx | 93 + dashboard/src/components/EventListNaive.tsx | 18 + dashboard/src/components/EventListPanel.tsx | 21 + dashboard/src/components/EventRow.tsx | 46 + .../src/components/PaginationControls.tsx | 74 + .../src/components/SearchAutocomplete.tsx | 188 + .../components/WalletConnectButton.test.tsx | 58 + .../src/components/WalletConnectButton.tsx | 63 + dashboard/src/config/stellarNetwork.ts | 10 + dashboard/src/hooks/useDebounce.ts | 17 + dashboard/src/hooks/useEventSelectors.ts | 56 + dashboard/src/index.css | 830 + dashboard/src/main.tsx | 10 + dashboard/src/pages/EventExplorerPage.tsx | 220 + dashboard/src/pages/EventsPage.tsx | 80 + dashboard/src/services/eventsApi.ts | 30 + dashboard/src/services/wallet.test.tsx | 158 + dashboard/src/services/wallet.ts | 143 + dashboard/src/store/eventStore.test.tsx | 117 + dashboard/src/store/eventStore.ts | 92 + dashboard/src/store/walletStore.ts | 80 + dashboard/src/test/stellarNetworkMock.ts | 8 + dashboard/src/test/stellarWalletsKitMock.ts | 51 + .../src/test/stellarWalletsKitModulesMock.ts | 8 + dashboard/src/types/event.ts | 17 + dashboard/src/utils/eventData.ts | 63 + dashboard/src/utils/formatTime.test.ts | 65 + dashboard/src/utils/formatTime.ts | 41 + dashboard/src/vite-env.d.ts | 9 + dashboard/tsconfig.json | 20 + dashboard/vite.config.ts | 19 + issues/issue-1-add-github-actions-tests.md | 15 + issues/issue-2-create-contributing-guide.md | 16 + .../issue-3-add-unit-tests-get-all-groups.md | 15 + issues/issue-4-fix-reduce-usage-dummy.md | 15 + issues/issue-5-add-bug-report-template.md | 19 + listener/.env.example | 46 + listener/.env.staging | 4 + listener/.eslintignore | 8 + listener/.eslintrc.cjs | 17 + listener/.gitignore | 4 + listener/API.md | 850 + listener/API_USAGE_COOKBOOK.md | 558 + listener/ARCHITECTURE-DIAGRAM.md | 421 + listener/FIXTURE-BUILDER-QUICK-REFERENCE.md | 216 + listener/IMPLEMENTATION-SUMMARY.md | 417 + listener/INSTALLATION.md | 316 + listener/LOGGING.md | 94 + listener/QUICK-START-SCHEDULER.md | 108 + listener/RATE-LIMITING-GUIDE.md | 425 + listener/README-SCHEDULED-NOTIFICATIONS.md | 617 + listener/README-SCHEDULER.md | 399 + listener/SCHEDULED-NOTIFICATIONS-INDEX.md | 277 + .../TEST-FIXTURE-IMPLEMENTATION-SUMMARY.md | 507 + listener/TEST-FIXTURE-MIGRATION-GUIDE.md | 488 + listener/jest.config.js | 10 + listener/jest.setup.js | 17 + listener/package-lock.json | 7869 +++++++ listener/package.json | 44 + listener/reports/last-validation-run.json | 8 + listener/src/__tests__/integration.test.ts | 54 + .../multi-channel-delivery.e2e.test.ts | 361 + ...otification-delivery-lifecycle.e2e.test.ts | 423 + listener/src/api/events-server.test.ts | 437 + listener/src/api/events-server.ts | 810 + .../src/api/notifications-history.test.ts | 255 + listener/src/api/rate-limiter.test.ts | 525 + listener/src/api/rate-limiter.ts | 258 + listener/src/api/template-api.ts | 92 + listener/src/api/templates-api.test.ts | 202 + listener/src/config.test.ts | 140 + listener/src/config.ts | 158 + listener/src/database/database.ts | 228 + listener/src/database/schema.sql | 169 + .../examples/schedule-notification-example.ts | 197 + listener/src/index.ts | 105 + listener/src/scripts/migrate-db.ts | 42 + .../discord-notification-refactored.test.ts | 360 + .../src/services/discord-notification.test.ts | 304 + listener/src/services/discord-notification.ts | 307 + .../src/services/event-subscriber.test.ts | 636 + listener/src/services/event-subscriber.ts | 259 + .../notification-analytics-aggregator.test.ts | 293 + .../notification-analytics-aggregator.ts | 433 + listener/src/services/notification-api.ts | 91 + .../notification-deduplicator.test.ts | 196 + .../src/services/notification-deduplicator.ts | 97 + listener/src/services/notification-history.ts | 108 + ...otification-retry-queue-refactored.test.ts | 331 + .../services/notification-retry-queue.test.ts | 298 + .../src/services/notification-retry-queue.ts | 195 + .../src/services/notification-scheduler.ts | 283 + .../notification-template-cache.test.ts | 145 + .../services/notification-template-cache.ts | 176 + .../notification-template-repository.test.ts | 235 + .../notification-template-repository.ts | 202 + .../notification-template-service.test.ts | 46 + .../services/notification-template-service.ts | 41 + .../scheduled-notification-repository.ts | 400 + listener/src/services/template-audit-trail.ts | 85 + .../src/services/webhook-verifier.test.ts | 110 + listener/src/services/webhook-verifier.ts | 48 + listener/src/store/event-registry.test.ts | 88 + listener/src/store/event-registry.ts | 60 + listener/src/store/preference-store.test.ts | 77 + listener/src/store/preference-store.ts | 40 + listener/src/test-utils/README.md | 596 + .../notification-fixture-builder.test.ts | 419 + .../notification-fixture-builder.ts | 503 + listener/src/tests/events-server.test.ts | 66 + .../notification-scheduler-refactored.test.ts | 424 + .../src/tests/notification-scheduler.test.ts | 338 + listener/src/types/display-event.ts | 11 + listener/src/types/index.ts | 59 + listener/src/types/notification-template.ts | 64 + listener/src/types/preferences.ts | 12 + listener/src/types/registry-event-input.ts | 12 + listener/src/types/scheduled-notification.ts | 96 + listener/src/utils/batch-validator.ts | 83 + listener/src/utils/event-utils.test.ts | 96 + listener/src/utils/event-utils.ts | 68 + listener/src/utils/logger.test.ts | 34 + listener/src/utils/logger.ts | 107 + listener/src/utils/pagination.test.ts | 79 + listener/src/utils/pagination.ts | 58 + listener/src/utils/request-actor.ts | 31 + listener/src/utils/request-id.ts | 18 + listener/src/utils/scval-format.ts | 21 + listener/test-sdk.ts | 7 + listener/tsconfig.json | 19 + scripts/health-check.sh | 8 + 184 files changed, 59000 insertions(+), 197 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/staging.yml create mode 100644 .kiro/specs/event-explorer-filters/.config.kiro create mode 100644 .kiro/specs/event-explorer-filters/requirements.md create mode 100644 ARCHITECTURE_OVERVIEW.md create mode 100644 CONTRACT_UPGRADE_GUIDE.md create mode 100644 CONTRIBUTING.md create mode 100644 NOTIFICATION_FAILURE_RECOVERY.md create mode 100644 NOTIFICATION_PAYLOAD_SCHEMA.md create mode 100644 PULL_REQUEST_SUMMARY.md create mode 100644 RATE-LIMITING-IMPLEMENTATION.md create mode 100644 REVOCATION_CHANGELOG.md create mode 100644 REVOCATION_IMPLEMENTATION_GUIDE.md create mode 100644 REVOCATION_INTERFACE_CHANGES.md create mode 100644 REVOCATION_ISSUE_COMPLETION.md create mode 100644 REVOCATION_QUICK_REFERENCE.md create mode 100644 REVOCATION_SUMMARY.md create mode 100644 SCHEDULED-NOTIFICATIONS-DELIVERY.md create mode 100644 TROUBLESHOOTING.md create mode 100644 contract/contracts/hello-world/src/tests/expiration_test.rs create mode 100644 contract/contracts/hello-world/src/tests/notification_test.rs create mode 100644 contract/contracts/hello-world/src/tests/revocation_test.rs create mode 100644 contract/contracts/hello-world/src/tests/version_test.rs create mode 100644 dashboard/.env.example create mode 100644 dashboard/.env.staging create mode 100644 dashboard/.eslintignore create mode 100644 dashboard/.eslintrc.cjs create mode 100644 dashboard/.gitignore create mode 100644 dashboard/.kiro/specs/event-explorer-filters/requirements.md create mode 100644 dashboard/index.html create mode 100644 dashboard/jest.config.cjs create mode 100644 dashboard/jest.setup.cjs create mode 100644 dashboard/package-lock.json create mode 100644 dashboard/package.json create mode 100644 dashboard/src/App.tsx create mode 100644 dashboard/src/benchmark/render-benchmark.test.tsx create mode 100644 dashboard/src/components/EventCard.test.tsx create mode 100644 dashboard/src/components/EventCard.tsx create mode 100644 dashboard/src/components/EventExplorerCard.tsx create mode 100644 dashboard/src/components/EventExplorerSkeleton.tsx create mode 100644 dashboard/src/components/EventExplorerTable.tsx create mode 100644 dashboard/src/components/EventFiltersBar.test.tsx create mode 100644 dashboard/src/components/EventFiltersBar.tsx create mode 100644 dashboard/src/components/EventList.tsx create mode 100644 dashboard/src/components/EventListNaive.tsx create mode 100644 dashboard/src/components/EventListPanel.tsx create mode 100644 dashboard/src/components/EventRow.tsx create mode 100644 dashboard/src/components/PaginationControls.tsx create mode 100644 dashboard/src/components/SearchAutocomplete.tsx create mode 100644 dashboard/src/components/WalletConnectButton.test.tsx create mode 100644 dashboard/src/components/WalletConnectButton.tsx create mode 100644 dashboard/src/config/stellarNetwork.ts create mode 100644 dashboard/src/hooks/useDebounce.ts create mode 100644 dashboard/src/hooks/useEventSelectors.ts create mode 100644 dashboard/src/index.css create mode 100644 dashboard/src/main.tsx create mode 100644 dashboard/src/pages/EventExplorerPage.tsx create mode 100644 dashboard/src/pages/EventsPage.tsx create mode 100644 dashboard/src/services/eventsApi.ts create mode 100644 dashboard/src/services/wallet.test.tsx create mode 100644 dashboard/src/services/wallet.ts create mode 100644 dashboard/src/store/eventStore.test.tsx create mode 100644 dashboard/src/store/eventStore.ts create mode 100644 dashboard/src/store/walletStore.ts create mode 100644 dashboard/src/test/stellarNetworkMock.ts create mode 100644 dashboard/src/test/stellarWalletsKitMock.ts create mode 100644 dashboard/src/test/stellarWalletsKitModulesMock.ts create mode 100644 dashboard/src/types/event.ts create mode 100644 dashboard/src/utils/eventData.ts create mode 100644 dashboard/src/utils/formatTime.test.ts create mode 100644 dashboard/src/utils/formatTime.ts create mode 100644 dashboard/src/vite-env.d.ts create mode 100644 dashboard/tsconfig.json create mode 100644 dashboard/vite.config.ts create mode 100644 issues/issue-1-add-github-actions-tests.md create mode 100644 issues/issue-2-create-contributing-guide.md create mode 100644 issues/issue-3-add-unit-tests-get-all-groups.md create mode 100644 issues/issue-4-fix-reduce-usage-dummy.md create mode 100644 issues/issue-5-add-bug-report-template.md create mode 100644 listener/.env.example create mode 100644 listener/.env.staging create mode 100644 listener/.eslintignore create mode 100644 listener/.eslintrc.cjs create mode 100644 listener/.gitignore create mode 100644 listener/API.md create mode 100644 listener/API_USAGE_COOKBOOK.md create mode 100644 listener/ARCHITECTURE-DIAGRAM.md create mode 100644 listener/FIXTURE-BUILDER-QUICK-REFERENCE.md create mode 100644 listener/IMPLEMENTATION-SUMMARY.md create mode 100644 listener/INSTALLATION.md create mode 100644 listener/LOGGING.md create mode 100644 listener/QUICK-START-SCHEDULER.md create mode 100644 listener/RATE-LIMITING-GUIDE.md create mode 100644 listener/README-SCHEDULED-NOTIFICATIONS.md create mode 100644 listener/README-SCHEDULER.md create mode 100644 listener/SCHEDULED-NOTIFICATIONS-INDEX.md create mode 100644 listener/TEST-FIXTURE-IMPLEMENTATION-SUMMARY.md create mode 100644 listener/TEST-FIXTURE-MIGRATION-GUIDE.md create mode 100644 listener/jest.config.js create mode 100644 listener/jest.setup.js create mode 100644 listener/package-lock.json create mode 100644 listener/package.json create mode 100644 listener/reports/last-validation-run.json create mode 100644 listener/src/__tests__/integration.test.ts create mode 100644 listener/src/__tests__/multi-channel-delivery.e2e.test.ts create mode 100644 listener/src/__tests__/notification-delivery-lifecycle.e2e.test.ts create mode 100644 listener/src/api/events-server.test.ts create mode 100644 listener/src/api/events-server.ts create mode 100644 listener/src/api/notifications-history.test.ts create mode 100644 listener/src/api/rate-limiter.test.ts create mode 100644 listener/src/api/rate-limiter.ts create mode 100644 listener/src/api/template-api.ts create mode 100644 listener/src/api/templates-api.test.ts create mode 100644 listener/src/config.test.ts create mode 100644 listener/src/config.ts create mode 100644 listener/src/database/database.ts create mode 100644 listener/src/database/schema.sql create mode 100644 listener/src/examples/schedule-notification-example.ts create mode 100644 listener/src/index.ts create mode 100644 listener/src/scripts/migrate-db.ts create mode 100644 listener/src/services/discord-notification-refactored.test.ts create mode 100644 listener/src/services/discord-notification.test.ts create mode 100644 listener/src/services/discord-notification.ts create mode 100644 listener/src/services/event-subscriber.test.ts create mode 100644 listener/src/services/event-subscriber.ts create mode 100644 listener/src/services/notification-analytics-aggregator.test.ts create mode 100644 listener/src/services/notification-analytics-aggregator.ts create mode 100644 listener/src/services/notification-api.ts create mode 100644 listener/src/services/notification-deduplicator.test.ts create mode 100644 listener/src/services/notification-deduplicator.ts create mode 100644 listener/src/services/notification-history.ts create mode 100644 listener/src/services/notification-retry-queue-refactored.test.ts create mode 100644 listener/src/services/notification-retry-queue.test.ts create mode 100644 listener/src/services/notification-retry-queue.ts create mode 100644 listener/src/services/notification-scheduler.ts create mode 100644 listener/src/services/notification-template-cache.test.ts create mode 100644 listener/src/services/notification-template-cache.ts create mode 100644 listener/src/services/notification-template-repository.test.ts create mode 100644 listener/src/services/notification-template-repository.ts create mode 100644 listener/src/services/notification-template-service.test.ts create mode 100644 listener/src/services/notification-template-service.ts create mode 100644 listener/src/services/scheduled-notification-repository.ts create mode 100644 listener/src/services/template-audit-trail.ts create mode 100644 listener/src/services/webhook-verifier.test.ts create mode 100644 listener/src/services/webhook-verifier.ts create mode 100644 listener/src/store/event-registry.test.ts create mode 100644 listener/src/store/event-registry.ts create mode 100644 listener/src/store/preference-store.test.ts create mode 100644 listener/src/store/preference-store.ts create mode 100644 listener/src/test-utils/README.md create mode 100644 listener/src/test-utils/notification-fixture-builder.test.ts create mode 100644 listener/src/test-utils/notification-fixture-builder.ts create mode 100644 listener/src/tests/events-server.test.ts create mode 100644 listener/src/tests/notification-scheduler-refactored.test.ts create mode 100644 listener/src/tests/notification-scheduler.test.ts create mode 100644 listener/src/types/display-event.ts create mode 100644 listener/src/types/index.ts create mode 100644 listener/src/types/notification-template.ts create mode 100644 listener/src/types/preferences.ts create mode 100644 listener/src/types/registry-event-input.ts create mode 100644 listener/src/types/scheduled-notification.ts create mode 100644 listener/src/utils/batch-validator.ts create mode 100644 listener/src/utils/event-utils.test.ts create mode 100644 listener/src/utils/event-utils.ts create mode 100644 listener/src/utils/logger.test.ts create mode 100644 listener/src/utils/logger.ts create mode 100644 listener/src/utils/pagination.test.ts create mode 100644 listener/src/utils/pagination.ts create mode 100644 listener/src/utils/request-actor.ts create mode 100644 listener/src/utils/request-id.ts create mode 100644 listener/src/utils/scval-format.ts create mode 100644 listener/test-sdk.ts create mode 100644 listener/tsconfig.json create mode 100755 scripts/health-check.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..3a31d29 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,73 @@ +name: CI + +on: + pull_request: + +jobs: + frontend: + name: Frontend (lint, typecheck, test) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: "npm" + cache-dependency-path: dashboard/package-lock.json + - name: Install dependencies + working-directory: dashboard + run: npm ci + - name: Run lint + working-directory: dashboard + run: npm run lint + - name: TypeScript check (build) + working-directory: dashboard + run: npm run build + - name: Run tests + working-directory: dashboard + run: npm test --silent + + listener: + name: Listener (lint, typecheck, test) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: "npm" + cache-dependency-path: listener/package-lock.json + - name: Install dependencies + working-directory: listener + run: npm ci + - name: Run lint + working-directory: listener + run: npm run lint + - name: TypeScript check + working-directory: listener + run: npm run typecheck + - name: Run tests + working-directory: listener + run: npm test --silent + + rust: + name: Rust (fmt check, tests) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + profile: minimal + override: true + - name: Check formatting + working-directory: contract + run: | + rustup component add rustfmt || true + cargo fmt --all -- --check + - name: Run tests + working-directory: contract + run: cargo test --workspace --all-features --verbose diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml new file mode 100644 index 0000000..db2123e --- /dev/null +++ b/.github/workflows/staging.yml @@ -0,0 +1,23 @@ +name: Staging Deployment +on: + push: + branches: + - staging +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + - run: | + cd listener + npm ci + npm run build + - run: | + cd dashboard + npm ci + npm run build + - run: | + bash scripts/health-check.sh http://localhost:3000/health diff --git a/.kiro/specs/event-explorer-filters/.config.kiro b/.kiro/specs/event-explorer-filters/.config.kiro new file mode 100644 index 0000000..d52d55f --- /dev/null +++ b/.kiro/specs/event-explorer-filters/.config.kiro @@ -0,0 +1 @@ +{"specId": "9cc9bcb6-936c-486e-9b84-7647b17281e6", "workflowType": "requirements-first", "specType": "feature"} diff --git a/.kiro/specs/event-explorer-filters/requirements.md b/.kiro/specs/event-explorer-filters/requirements.md new file mode 100644 index 0000000..e36cd3f --- /dev/null +++ b/.kiro/specs/event-explorer-filters/requirements.md @@ -0,0 +1,155 @@ +# Requirements Document + +## Introduction + +This feature enhances the Event Explorer page in the Notify-Chain Web3 dashboard with an advanced search and multi-filter system. The current filtering supports a single free-text search, a single-select contract address dropdown, and a single-select event type dropdown with no debounce. The enhancement introduces debounced search, a multi-select event type filter (using the `type` field on `BlockchainEvent`), a date range filter against the `receivedAt` timestamp, a clear-all action, an improved empty state, and ensures performance, responsive layout, and accessibility standards are met. + +## Glossary + +- **EventExplorer**: The Event Explorer page component (`EventExplorerPage`) that renders the filter bar, event table, pagination, and empty state. +- **EventFiltersBar**: The React component that renders all filter controls (search input, contract filter, event type multi-select, date range inputs, clear-all button). +- **FilterEngine**: The `filterEvents` utility function in `eventData.ts` that applies all active filters to the in-memory event list. +- **EventStore**: The Zustand store (`eventStore.ts`) that holds `events`, `filters`, loading state, and all filter-mutation actions. +- **BlockchainEvent**: The TypeScript interface representing a single on-chain event, containing `eventId`, `contractAddress`, `eventName`, `ledger`, `type`, `topic`, `value`, `txHash`, and `receivedAt`. +- **EventFilters**: The TypeScript interface that holds all active filter state: `search`, `contractAddress`, `eventTypes` (set of selected type strings), `startDate`, and `endDate`. +- **DebounceInterval**: The 300 ms delay applied to the search input before the filter state is updated in the EventStore. +- **ReceivedAt**: The Unix millisecond timestamp field on `BlockchainEvent` used for date range filtering. +- **StartOfDayUTC**: Midnight (00:00:00.000 UTC) on the selected start date, expressed as a Unix ms timestamp. +- **EndOfDayUTC**: 23:59:59.999 UTC on the selected end date, expressed as a Unix ms timestamp. +- **ClearAllAction**: The Zustand store action that resets all filter fields to their default (empty/all) values in a single atomic update. + +--- + +## Requirements + +### Requirement 1: Debounced Contract ID Text Search + +**User Story:** As a blockchain analyst, I want a debounced text search across event identifiers, so that the filter does not re-execute on every keystroke and the UI remains responsive during fast typing. + +#### Acceptance Criteria + +1. THE EventFiltersBar SHALL render a text input with a visible label for the search field. +2. WHEN the user types in the search input, THE EventFiltersBar SHALL update the visible input value immediately without delay. +3. WHEN the user stops typing for 300 ms, THE EventStore SHALL update the `search` field in `EventFilters` with the current input value. +4. WHEN the user resumes typing before 300 ms have elapsed, THE EventFiltersBar SHALL reset the debounce timer and not dispatch a store update. +5. WHEN the `search` filter is non-empty, THE FilterEngine SHALL include only events whose `contractAddress`, `eventId`, `eventName`, or `txHash` contains the search string (case-insensitive substring match). +6. WHEN the `search` filter is empty, THE FilterEngine SHALL apply no search restriction and return events matching the remaining active filters. + +--- + +### Requirement 2: Event Type Multi-Select Filter + +**User Story:** As a blockchain analyst, I want to select multiple event types simultaneously, so that I can view events of more than one type in a single filtered result set. + +#### Acceptance Criteria + +1. THE EventFiltersBar SHALL render a multi-select control with one toggle per distinct `type` value present in the loaded `BlockchainEvent` set (values: `contract`, `system`, `diagnostic`). +2. WHEN no event types are selected, THE FilterEngine SHALL apply no type restriction and return events matching the remaining active filters. +3. WHEN one or more event types are selected, THE FilterEngine SHALL include only events whose `type` field matches any of the selected types (OR logic within the type set). +4. WHEN an event type toggle is activated, THE EventStore SHALL add that type to the `eventTypes` set in `EventFilters`. +5. WHEN an active event type toggle is deactivated, THE EventStore SHALL remove that type from the `eventTypes` set in `EventFilters`. +6. THE EventFiltersBar SHALL visually distinguish selected type toggles from unselected ones. + +--- + +### Requirement 3: Date Range Filter + +**User Story:** As a blockchain analyst, I want to filter events by a date range, so that I can focus on events that occurred within a specific time window. + +#### Acceptance Criteria + +1. THE EventFiltersBar SHALL render a Start Date input and an End Date input using native HTML date inputs. +2. WHEN a Start Date is set and no End Date is set, THE FilterEngine SHALL include only events whose `receivedAt` is greater than or equal to the StartOfDayUTC of the selected start date. +3. WHEN an End Date is set and no Start Date is set, THE FilterEngine SHALL include only events whose `receivedAt` is less than or equal to the EndOfDayUTC of the selected end date. +4. WHEN both a Start Date and End Date are set, THE FilterEngine SHALL include only events whose `receivedAt` falls within the inclusive range from StartOfDayUTC to EndOfDayUTC. +5. IF a Start Date and End Date are both set and the Start Date is after the End Date, THEN THE FilterEngine SHALL return zero events for the date filter criterion. +6. WHEN neither Start Date nor End Date is set, THE FilterEngine SHALL apply no date restriction. +7. THE EventFiltersBar SHALL render visible labels for both the Start Date and End Date inputs. + +--- + +### Requirement 4: Additive AND Filter Logic + +**User Story:** As a blockchain analyst, I want all active filters to apply simultaneously, so that I can narrow results precisely using multiple criteria at once. + +#### Acceptance Criteria + +1. WHEN multiple filters are active, THE FilterEngine SHALL include only events that satisfy every active filter condition simultaneously (AND logic across filter dimensions). +2. THE FilterEngine SHALL apply the search filter, contract address filter, event type filter, and date range filter as independent, composable predicates. +3. WHEN a filter field holds its default value (`search` is empty, `contractAddress` is `'all'`, `eventTypes` is empty, `startDate` and `endDate` are empty), THE FilterEngine SHALL treat that filter as inactive and not exclude events based on it. + +--- + +### Requirement 5: Clear All Filters + +**User Story:** As a blockchain analyst, I want a single button to reset all filters at once, so that I can return to the full unfiltered event list without manually resetting each control. + +#### Acceptance Criteria + +1. THE EventFiltersBar SHALL render a visible "Clear filters" button. +2. WHEN the "Clear filters" button is activated, THE EventStore SHALL atomically reset `search` to `''`, `contractAddress` to `'all'`, `eventTypes` to an empty set, `startDate` to `''`, and `endDate` to `''` via the ClearAllAction. +3. WHEN the ClearAllAction is dispatched, THE EventExplorer SHALL reset the current page to 1. +4. WHEN all filters are already at their default values, THE EventFiltersBar SHALL render the "Clear filters" button in a visually disabled state. + +--- + +### Requirement 6: Empty State for Zero Filtered Results + +**User Story:** As a blockchain analyst, I want a clear message when my filters return no results, so that I understand the list is empty due to active filters rather than a data loading problem. + +#### Acceptance Criteria + +1. WHEN the FilterEngine returns zero events and at least one filter is active, THE EventExplorer SHALL render a heading containing "No matching events found". +2. WHEN the FilterEngine returns zero events and at least one filter is active, THE EventExplorer SHALL render body text containing "Try adjusting or clearing your filters to see more results." +3. WHEN the FilterEngine returns zero events and no filters are active, THE EventExplorer SHALL render the existing "No events found" empty state. +4. THE EventExplorer SHALL render the empty state region with `role="status"` and `aria-live="polite"` so assistive technologies announce the state change. + +--- + +### Requirement 7: Performance + +**User Story:** As a user browsing the Event Explorer, I want filter operations to complete without perceptible lag even when thousands of events are loaded, so that interaction remains smooth. + +#### Acceptance Criteria + +1. THE EventExplorer SHALL derive the filtered event list using `useMemo`, recomputing only when `events` or `filters` change. +2. WHEN the user types in the search input, THE EventExplorer SHALL not recompute the filtered list until the DebounceInterval has elapsed. +3. WHEN any filter changes, THE EventExplorer SHALL not trigger a full-page reload or re-fetch of events. + +--- + +### Requirement 8: Responsive Filter Panel Layout + +**User Story:** As a user on a mobile device, I want the filter controls to stack vertically, so that they are accessible and usable on small screens. + +#### Acceptance Criteria + +1. WHILE the viewport width is below 768 px, THE EventFiltersBar SHALL render all filter controls in a single-column vertical stack. +2. WHILE the viewport width is 768 px or greater, THE EventFiltersBar SHALL render filter controls in a horizontal row layout. + +--- + +### Requirement 9: Accessibility + +**User Story:** As a user relying on assistive technology, I want all filter controls to be labelled and keyboard navigable, so that I can use the Event Explorer without a mouse. + +#### Acceptance Criteria + +1. THE EventFiltersBar SHALL associate every filter input with a visible `