Skip to content

Commit

Permalink
feat: add pallets/events endpoint (#1204)
Browse files Browse the repository at this point in the history
* add events pallet events endpoint
add unit tests
add e2e test

* update docs for pallet events endpoint

* add statemint e2e tests for pallet events endpoint

* update events references

* remove duplicate IPalletEventsParam reference

* lint

* add events check to getPalletMetadataType
add unhappy path check to fetchEventItem unit tests

* merge master

* update abstratpalletservice types
refactored events items assignment

* update error message to reflect more accurately when the pallet metadata has no items to query of a specific field type

* debug historicApi pallets

* update check for isValidPalletName to use the pallet meta data instead of the historicApi

* update error log for when a pallet id is not recognized

* yarn lint
  • Loading branch information
marshacb committed Feb 13, 2023
1 parent 3189864 commit 289d804
Show file tree
Hide file tree
Showing 32 changed files with 919 additions and 31 deletions.
2 changes: 1 addition & 1 deletion docs/dist/app.bundle.js

Large diffs are not rendered by default.

164 changes: 164 additions & 0 deletions docs/src/openapi-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1159,6 +1159,113 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/Error'
/pallets/{palletId}/events:
get:
tags:
- pallets
summary: Get a list of events for a pallet.
description: Returns a list of event item metadata for event items of the
specified palletId.
parameters:
- name: palletId
in: path
description: 'Name or index of the pallet to read event metadata for. Note: the pallet name must match what is
specified in the runtime metadata.'
required: true
schema:
type: string
- name: onlyIds
in: query
description: Only return the names (IDs) of the event items instead of every event's metadata.
required: false
schema:
type: boolean
- name: at
in: query
description: Block at which to retrieve a list of
the pallet's event items.
required: false
schema:
type: string
description: Block identifier, as the block height or block hash.
format: unsignedInteger or $hex
responses:
"200":
description: successful operation
content:
application/json:
schema:
type: array
description: Pallet info and Array of eventItemIds.
items:
$ref: '#/components/schemas/PalletEvents'
"400":
description: invalid blockId supplied for at query param
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
"404":
description: could not find pallet with palletId
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/pallets/{palletId}/events/{eventItemId}:
get:
tags:
- pallets
summary: Get the value of an event item.
description: Returns the value stored under the eventItemId.
parameters:
- name: palletId
in: path
description: 'Name or index of the pallet to read event metadata for. Note: the pallet name must match what is
specified in the runtime metadata.'
required: true
schema:
type: string
- name: eventItemId
in: path
description: Id of the event item to query for.
required: true
schema:
type: string
- name: at
in: query
description: Block at which to query the event item at.
required: false
schema:
type: string
description: Block identifier, as the block height or block hash.
format: unsignedInteger or $hex
- name: metadata
in: query
description: Include the event items metadata (including documentation)
if set to true.
required: false
schema:
default: false
type: boolean
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: '#/components/schemas/PalletEventsItem'
"400":
description: invalid blockId supplied for at query param
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
"404":
description: could not find resource with with id
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
/runtime/metadata:
get:
tags:
Expand Down Expand Up @@ -2601,6 +2708,63 @@ components:
items:
type: string
description: Metadata of an error item from a FRAME pallet.
PalletEvents:
type: object
properties:
at:
$ref: '#/components/schemas/BlockIdentifiers'
pallet:
type: string
description: Name of the pallet.
example: "democracy"
palletIndex:
type: string
description: Index of the pallet for looking up events.
example: "14"
items:
type: array
items:
$ref: '#/components/schemas/PalletEventsItemMetadata'
PalletEventsItem:
type: object
properties:
pallet:
type: string
description: Name of the pallet.
example: "democracy"
palletIndex:
type: string
description: Index of the pallet for looking up events.
example: "14"
eventItem:
type: string
description: Name of the events item.
example: "Proposed"
metadata:
$ref: '#/components/schemas/PalletEventsItemMetadata'
PalletEventsItemMetadata:
type: object
properties:
name:
type: string
example: "Tabled"
description: The event item's name (which is the same as the event item's ID).
fields:
type: array
items:
type: string
index:
type: string
example: "0"
description: The index of the error item in the lists of pallet events
docs:
type: string
example: " Information concerning any given event.\n\n TWOX-NOTE: SAFE as indexes are not under an attacker’s control."
args:
type: array
items:
type: string
description: Metadata of an event item from a FRAME pallet.
PalletsNominationPool:
type: object
properties:
Expand Down
13 changes: 13 additions & 0 deletions e2e-tests/latest/endpoints/polkadot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,19 @@ export const polkadot: IConfig = {
'at={blockId}'
],
},
'/pallets/{palletId}/events': {
path: '/pallets/balances/events',
queryParams: [
'at={blockId}'
],
},
'/pallets/{palletId}/events/{eventItemId}': {
path: '/pallets/democracy/events/Proposed',
queryParams: [
'at={blockId}',
'metadata=true'
],
},
'/pallets/nominationPoools/info': {
path: '/pallets/nomination-pools/info',
queryParams: [
Expand Down
12 changes: 12 additions & 0 deletions e2e-tests/latest/endpoints/statemint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,16 @@ export const statemint = {
'at={blockId}'
],
},
'/pallets/{palletId}/events': {
path: '/pallets/assets/events',
queryParams: [
'at={blockId}'
],
},
'/pallets/{palletId}/events/{eventItemId}': {
path: '/pallets/assets/events/Created',
queryParams: [
'at={blockId}'
],
},
};
1 change: 1 addition & 0 deletions src/chains-config/defaultControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export const defaultControllers: ControllerConfig = {
'NodeVersion',
'PalletsAssets',
'PalletsErrors',
'PalletsEvents',
'PalletsStakingProgress',
'PalletsStorage',
'Paras',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/kusamaControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const kusamaControllers: ControllerConfig = {
'NodeTransactionPool',
'NodeVersion',
'PalletsErrors',
'PalletsEvents',
'PalletsNominationPools',
'PalletsStakingProgress',
'PalletsStakingValidators',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/polkadotControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export const polkadotControllers: ControllerConfig = {
'NodeTransactionPool',
'NodeVersion',
'PalletsErrors',
'PalletsEvents',
'PalletsNominationPools',
'PalletsStakingProgress',
'PalletsStakingValidators',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/statemineControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const statemineControllers: ControllerConfig = {
'NodeVersion',
'PalletsAssets',
'PalletsErrors',
'PalletsEvents',
'RuntimeCode',
'RuntimeMetadata',
'RuntimeSpec',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/statemintControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const statemintControllers: ControllerConfig = {
'NodeTransactionPool',
'NodeVersion',
'PalletsAssets',
'PalletsEvents',
'PalletsErrors',
'RuntimeCode',
'RuntimeMetadata',
Expand Down
1 change: 1 addition & 0 deletions src/chains-config/westendControllers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const westendControllers: ControllerConfig = {
'NodeTransactionPool',
'NodeVersion',
'PalletsErrors',
'PalletsEvents',
'PalletsNominationPools',
'PalletsStakingProgress',
'PalletsStakingValidators',
Expand Down
2 changes: 2 additions & 0 deletions src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { NodeNetwork, NodeTransactionPool, NodeVersion } from './node';
import {
PalletsAssets,
PalletsErrors,
PalletsEvents,
PalletsNominationPools,
PalletsStakingProgress,
PalletsStakingValidators,
Expand Down Expand Up @@ -60,6 +61,7 @@ export const controllers = {
ContractsInk,
PalletsAssets,
PalletsErrors,
PalletsEvents,
PalletsNominationPools,
PalletsStakingProgress,
PalletsStakingValidators,
Expand Down
77 changes: 77 additions & 0 deletions src/controllers/pallets/PalletsEventsController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
// This file is part of Substrate API Sidecar.
//
// Substrate API Sidecar 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 <http://www.gnu.org/licenses/>.

import { ApiPromise } from '@polkadot/api';
import { stringCamelCase } from '@polkadot/util';
import { RequestHandler } from 'express-serve-static-core';
import { IPalletsEventsParam } from 'src/types/requests';

import { PalletsEventsService } from '../../services';
import AbstractController from '../AbstractController';

export default class PalletsEventsController extends AbstractController<PalletsEventsService> {
constructor(api: ApiPromise) {
super(api, '/pallets/:palletId/events', new PalletsEventsService(api));

this.initRoutes();
}

protected initRoutes(): void {
this.safeMountAsyncGetHandlers([
['/:eventItemId', this.getEventById as RequestHandler],
['/', this.getEvents],
]);
}

private getEventById: RequestHandler<IPalletsEventsParam, unknown, unknown> =
async (
{ query: { at, metadata }, params: { palletId, eventItemId } },
res
): Promise<void> => {
const metadataArg = metadata === 'true';
const hash = await this.getHashFromAt(at);
const historicApi = await this.api.at(hash);

PalletsEventsController.sanitizedSend(
res,
await this.service.fetchEventItem(historicApi, {
hash,
// stringCamelCase ensures we don't have snake case or kebab case
palletId: stringCamelCase(palletId),
eventItemId: stringCamelCase(eventItemId),
metadata: metadataArg,
})
);
};

private getEvents: RequestHandler = async (
{ params: { palletId }, query: { at, onlyIds } },
res
): Promise<void> => {
const onlyIdsArg = onlyIds === 'true';
const hash = await this.getHashFromAt(at);
const historicApi = await this.api.at(hash);

PalletsEventsController.sanitizedSend(
res,
await this.service.fetchEvents(historicApi, {
hash,
palletId: stringCamelCase(palletId),
onlyIds: onlyIdsArg,
})
);
};
}
1 change: 1 addition & 0 deletions src/controllers/pallets/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

export { default as PalletsAssets } from './PalletsAssetsController';
export { default as PalletsErrors } from './PalletsErrorsController';
export { default as PalletsEvents } from './PalletsEventsController';
export { default as PalletsNominationPools } from './PalletsNominationPoolsController';
export { default as PalletsStakingProgress } from './PalletsStakingProgressController';
export { default as PalletsStakingValidators } from './PalletsStakingValidatorsController';
Expand Down
Loading

0 comments on commit 289d804

Please sign in to comment.