Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add pallets/on-going-referenda endpoint #1471

Merged
merged 6 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/dist/app.bundle.js

Large diffs are not rendered by default.

74 changes: 74 additions & 0 deletions docs/src/openapi-v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,31 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/PalletsNominationPool'
/pallets/on-going-referenda:
get:
tags:
- pallets
summary: Get a list of all on-going referenda that have track `root (0)` and `whitelisted (1)`,
along with their associated information.
description: Returns information associated with on-going referenda which includes
the referendum's `enactment`, `submitted` and `deciding` fields.
operationId: getPalletOnGoingReferenda
parameters:
- name: at
in: query
description: Block at which to retrieve the on-going referenda.
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:
$ref: '#/components/schemas/PalletsOnGoingReferenda'
/pallets/{palletId}/consts:
get:
tags:
Expand Down Expand Up @@ -3796,6 +3821,55 @@ components:
type: number
minJoinBond:
type: number
PalletsOnGoingReferenda:
type: object
properties:
at:
$ref: '#/components/schemas/BlockIdentifiers'
referenda:
type: array
items:
type: object
properties:
id:
type: string
description: Referendum's id.
decisionDeposit:
type: object
properties:
who:
type: string
description: The account who placed the referendum's decision deposit.
amount:
type: string
format: unsignedInteger
description: The amount of the decision deposit.
description: A deposit which is required for a referendum to progress to the decision phase.
enactment:
type: string
enum:
- at
- after
description: The enactment period of the referendum. It can be defined using either the `at` option,
which specifies the exact block height when the referendum will be enacted, or the `after` option,
which indicates the number of blocks after which the enactment will occur.
submitted:
type: string
format: unsignedInteger
description: The block number at which the referendum was submitted.
deciding:
type: object
properties:
since:
type: string
format: unsignedInteger
description: The block number at which the referendum started being `decided`.
confirming:
type: string
format: unsignedInteger
description: The block number at which the referendum's confirmation stage will end at as long as
it doesn't lose its approval in the meantime.
description: A list of ongoing referenda and their details.
PalletsPoolAssetsInfo:
type: object
properties:
Expand Down
3 changes: 2 additions & 1 deletion src/chains-config/defaultControllers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
// Copyright 2017-2024 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
Expand Down Expand Up @@ -43,6 +43,7 @@ export const defaultControllers: ControllerConfig = {
'PalletsErrors',
'PalletsEvents',
'PalletsForeignAssets',
'PalletsOnGoingReferenda',
'PalletsStakingProgress',
'PalletsStorage',
'Paras',
Expand Down
3 changes: 2 additions & 1 deletion src/chains-config/kusamaControllers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
// Copyright 2017-2024 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
Expand Down Expand Up @@ -41,6 +41,7 @@ export const kusamaControllers: ControllerConfig = {
'PalletsErrors',
'PalletsEvents',
'PalletsNominationPools',
'PalletsOnGoingReferenda',
'PalletsStakingProgress',
'PalletsStakingValidators',
'PalletsStorage',
Expand Down
3 changes: 2 additions & 1 deletion src/chains-config/polkadotControllers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2022 Parity Technologies (UK) Ltd.
// Copyright 2017-2024 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
Expand Down Expand Up @@ -41,6 +41,7 @@ export const polkadotControllers: ControllerConfig = {
'PalletsErrors',
'PalletsEvents',
'PalletsNominationPools',
'PalletsOnGoingReferenda',
'PalletsStakingProgress',
'PalletsStakingValidators',
'PalletsStorage',
Expand Down
4 changes: 3 additions & 1 deletion src/controllers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2023 Parity Technologies (UK) Ltd.
// Copyright 2017-2024 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
Expand Down Expand Up @@ -37,6 +37,7 @@ import {
PalletsEvents,
PalletsForeignAssets,
PalletsNominationPools,
PalletsOnGoingReferenda,
PalletsPoolAssets,
PalletsStakingProgress,
PalletsStakingValidators,
Expand Down Expand Up @@ -72,6 +73,7 @@ export const controllers = {
PalletsEvents,
PalletsForeignAssets,
PalletsNominationPools,
PalletsOnGoingReferenda,
PalletsPoolAssets,
PalletsStakingProgress,
PalletsStakingValidators,
Expand Down
44 changes: 44 additions & 0 deletions src/controllers/pallets/PalletsOnGoingReferendaController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2017-2024 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 { RequestHandler } from 'express';

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

export default class PalletsOnGoingReferendaController extends AbstractController<PalletsOnGoingReferendaService> {
constructor(api: ApiPromise) {
super(api, '/pallets/on-going-referenda', new PalletsOnGoingReferendaService(api));
this.initRoutes();
}

protected initRoutes(): void {
this.safeMountAsyncGetHandlers([['', this.getPalletOnGoingReferenda]]);
}

/**
* Get the on-going referenda.
*
* @param _req Express Request
* @param res Express Response
*/
private getPalletOnGoingReferenda: RequestHandler = async ({ query: { at } }, res): Promise<void> => {
const hash = await this.getHashFromAt(at);

PalletsOnGoingReferendaController.sanitizedSend(res, await this.service.derivePalletOnGoingReferenda(hash));
};
}
3 changes: 2 additions & 1 deletion src/controllers/pallets/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2023 Parity Technologies (UK) Ltd.
// Copyright 2017-2024 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
Expand All @@ -22,6 +22,7 @@ export { default as PalletsErrors } from './PalletsErrorsController';
export { default as PalletsEvents } from './PalletsEventsController';
export { default as PalletsForeignAssets } from './PalletsForeignAssetsController';
export { default as PalletsNominationPools } from './PalletsNominationPoolsController';
export { default as PalletsOnGoingReferenda } from './PalletsOnGoingReferendaController';
export { default as PalletsPoolAssets } from './PalletsPoolAssetsController';
export { default as PalletsStakingProgress } from './PalletsStakingProgressController';
export { default as PalletsStakingValidators } from './PalletsStakingValidatorsController';
Expand Down
91 changes: 91 additions & 0 deletions src/services/pallets/PalletsOnGoingReferendaService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright 2017-2024 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 type { ApiPromise } from '@polkadot/api';
import type { ApiDecoration } from '@polkadot/api/types';
import type { Hash } from '@polkadot/types/interfaces';

import { sanitizeNumbers } from '../../sanitize/sanitizeNumbers';
import { polkadotRegistryV9300 } from '../../test-helpers/registries';
import { polkadotRegistryV1000001 } from '../../test-helpers/registries';
import { blockHash13641102, blockHash21275366, mockBlock13641102, mockBlock21275366 } from '../test-helpers/mock';
import { referendaEntries } from '../test-helpers/mock/data/referendaEntries';
import fetchOnGoingReferenda21275366Response from '../test-helpers/responses/pallets/fetchOnGoingReferenda21275366.json';
import { PalletsOnGoingReferendaService } from './PalletsOnGoingReferendaService';

// Mocking APIs for block #13641102
const getHeader13641102 = (_hash: Hash) => Promise.resolve().then(() => mockBlock13641102.header);

const mockHistoricApi13641102 = {
query: {},
registry: polkadotRegistryV9300,
} as unknown as ApiDecoration<'promise'>;

const mockApi13641102 = {
rpc: {
chain: {
getHeader: getHeader13641102,
},
},
at: (_hash: Hash) => mockHistoricApi13641102,
} as unknown as ApiPromise;

// Mock PalletsOnGoingReferendaService instance for block #13641102
const palletsOnGoingReferendaService13641102 = new PalletsOnGoingReferendaService(mockApi13641102);

// Mocking APIs for block #21275366
const getHeader21275366 = (_hash: Hash) => Promise.resolve().then(() => mockBlock21275366.header);
const referendaEntriesAt21275366 = () => Promise.resolve().then(() => referendaEntries());

const mockHistoricApi21275366 = {
registry: polkadotRegistryV1000001,
query: {
referenda: {
referendumInfoFor: {
entries: referendaEntriesAt21275366,
},
},
},
} as unknown as ApiDecoration<'promise'>;

const mockApi21275366 = {
rpc: {
chain: {
getHeader: getHeader21275366,
},
},
at: (_hash: Hash) => mockHistoricApi21275366,
} as unknown as ApiPromise;

// Mock PalletsOnGoingReferendaService instance for block #21275366
const palletsOnGoingReferendaService21275366 = new PalletsOnGoingReferendaService(mockApi21275366);

describe('PalletOnGoingReferendaService', () => {
describe('derivePalletOnGoingReferenda', () => {
it('throws error for block 13641102', async () => {
await expect(
palletsOnGoingReferendaService13641102.derivePalletOnGoingReferenda(blockHash13641102),
).rejects.toStrictEqual(
new Error(`The runtime does not include the module 'api.query.referenda' at this block height: 13641102`),
);
});
it('works for block 21275366 (Polkadot) & returns 7 referendas, 2 of which are runtime upgrades', async () => {
expect(
sanitizeNumbers(await palletsOnGoingReferendaService21275366.derivePalletOnGoingReferenda(blockHash21275366)),
).toStrictEqual(fetchOnGoingReferenda21275366Response);
});
});
});
73 changes: 73 additions & 0 deletions src/services/pallets/PalletsOnGoingReferendaService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// Copyright 2017-2024 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 { BlockHash } from '@polkadot/types/interfaces';

import { IPalletOnGoingReferenda, IReferendaInfo } from '../../types/responses';
import { AbstractService } from '../AbstractService';

export class PalletsOnGoingReferendaService extends AbstractService {
/**
* Fetch all on-going referenda that have track: root (0) and whitelisted (1), along
* with their associated information.
*
* @param hash `BlockHash` to make call at
*/
async derivePalletOnGoingReferenda(hash: BlockHash): Promise<IPalletOnGoingReferenda> {
const { api } = this;
const [historicApi, { number }] = await Promise.all([api.at(hash), api.rpc.chain.getHeader(hash)]);
const referenda: IReferendaInfo[] = [];
if (historicApi.query.referenda) {
const referendaEntries = await historicApi.query.referenda.referendumInfoFor.entries();
for (const referendum of referendaEntries) {
const referendumInfo = referendum[1];
if (referendumInfo.isSome) {
const refUnwrapped = referendumInfo.unwrap();
const refId = referendum[0].toHuman() as string[];
if (
refUnwrapped.type == 'Ongoing' &&
(refUnwrapped.asOngoing.track.toHuman() == '0' || refUnwrapped.asOngoing.track.toHuman() == '1')
) {
const decisionDeposit = refUnwrapped.asOngoing.decisionDeposit.isSome
? refUnwrapped.asOngoing.decisionDeposit.unwrap()
: null;
const enactment = refUnwrapped.asOngoing.enactment;
const submitted = refUnwrapped.asOngoing.submitted;
const deciding = refUnwrapped.asOngoing.deciding.isSome ? refUnwrapped.asOngoing.deciding.unwrap() : null;

const refInfo = { id: refId[0], decisionDeposit, enactment, submitted, deciding };
referenda.push(refInfo);
}
}
}
} else {
throw new Error(
`The runtime does not include the module 'api.query.referenda' at this block height: ${number
.unwrap()
.toString(10)}`,
);
}

const at = {
hash,
height: number.unwrap().toString(10),
};

return {
at,
referenda,
};
}
}
3 changes: 2 additions & 1 deletion src/services/pallets/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright 2017-2023 Parity Technologies (UK) Ltd.
// Copyright 2017-2024 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
Expand All @@ -22,6 +22,7 @@ export * from './PalletsConstantsService';
export * from './PalletsDispatchablesService';
export * from './PalletsForeignAssetsService';
export * from './PalletsNominationPoolsService';
export * from './PalletsOnGoingReferendaService';
export * from './PalletsPoolAssetsService';
export * from './PalletsStakingProgressService';
export * from './PalletsStakingValidatorsService';
Expand Down
Loading
Loading