diff --git a/.changelog/990.feature.md b/.changelog/990.feature.md
new file mode 100644
index 000000000..9c024abc9
--- /dev/null
+++ b/.changelog/990.feature.md
@@ -0,0 +1 @@
+Show block-level evens in block details
diff --git a/src/app/pages/BlockDetailPage/EventsCard.tsx b/src/app/pages/BlockDetailPage/EventsCard.tsx
new file mode 100644
index 000000000..2f8d1e118
--- /dev/null
+++ b/src/app/pages/BlockDetailPage/EventsCard.tsx
@@ -0,0 +1,82 @@
+import { FC, useState } from 'react'
+import { useTranslation } from 'react-i18next'
+import { ScrollingCard } from '../../components/PageLayout/ScrollingCard'
+import CardHeader from '@mui/material/CardHeader'
+import CardContent from '@mui/material/CardContent'
+
+import { Layer, RuntimeEventType, useGetRuntimeEvents } from '../../../oasis-nexus/api'
+import { ErrorBoundary } from '../../components/ErrorBoundary'
+import { AppErrors } from '../../../types/errors'
+import { SearchScope } from '../../../types/searchScope'
+import { RuntimeEventsDetailedList } from '../../components/RuntimeEvents/RuntimeEventsDetailedList'
+import { AddressSwitchOption } from '../../components/AddressSwitch'
+import { EventFilterMode, EventFilterSwitch } from '../../components/RuntimeEvents/EventListFilterSwitch'
+import { EmptyState } from '../../components/EmptyState'
+
+export const eventsContainerId = 'events'
+
+const EventsList: FC<{ scope: SearchScope; blockHeight: number; filterMode: EventFilterMode }> = ({
+ scope,
+ blockHeight,
+ filterMode,
+}) => {
+ const { t } = useTranslation()
+ if (scope.layer === Layer.consensus) {
+ // Loading events for consensus blocks is not yet supported.
+ // Should use useGetConsensusEvents()
+ throw AppErrors.UnsupportedLayer
+ }
+ const eventsQuery = useGetRuntimeEvents(scope.network, scope.layer, {
+ block: blockHeight,
+ // TODO: search for tx_hash = null
+ limit: 100, // We want to avoid pagination here, if possible
+ })
+
+ const { isLoading, isError, data } = eventsQuery
+
+ const events = data?.data.events.filter(
+ event =>
+ !event.tx_hash && // TODO: remove filtering here if it's implemented using the query parameters
+ (filterMode === EventFilterMode.All || event.type !== RuntimeEventType.accountstransfer),
+ )
+
+ if (!events?.length && !isLoading) {
+ return (
+
+ )
+ }
+
+ return (
+
+ )
+}
+
+export const EventsCard: FC<{ scope: SearchScope; blockHeight: number }> = ({ scope, blockHeight }) => {
+ const [filterMode, setFilterMode] = useState(EventFilterMode.All)
+ const { t } = useTranslation()
+ return (
+
+ }
+ />
+
+
+
+
+
+
+ )
+}
diff --git a/src/app/pages/BlockDetailPage/index.tsx b/src/app/pages/BlockDetailPage/index.tsx
index 19211a05f..230ac226b 100644
--- a/src/app/pages/BlockDetailPage/index.tsx
+++ b/src/app/pages/BlockDetailPage/index.tsx
@@ -18,6 +18,7 @@ import { BlockLink, BlockHashLink } from '../../components/Blocks/BlockLink'
import { RouteUtils } from '../../utils/route-utils'
import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { DashboardLink } from '../ParatimeDashboardPage/DashboardLink'
+import { EventsCard } from './EventsCard'
export const BlockDetailPage: FC = () => {
const { t } = useTranslation()
@@ -43,6 +44,7 @@ export const BlockDetailPage: FC = () => {
{!!block?.num_transactions && }
+
)
}
diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index f19edaf87..378a986bc 100644
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -286,6 +286,8 @@
},
"runtimeEvent": {
"cantLoadEvents": "Unfortunately we couldn't load the list of events. Please try again later.",
+ "noEvents": "No events",
+ "cantFindMatchingEvents": "We can't find any matching events.",
"accountsburn": "Tokens burnt",
"accountsmint": "Tokens minted",
"accountstransfer": "Transfer",