Skip to content

Commit 00f8311

Browse files
authored
feat: Support rcAt for /pallets/* endpoints (#1703)
* Support rcAt for /pallets/assets/{assetId}/asset-info * support rcAt for /pallets/asset-conversion/* * Support rcAt for /pallets/foreign-assets * Support rcAt for /pallets/nomination-pools/* * Support rcAt for /pallets/-on-going-referenda * support rcAt for /pallets/{palletId}/consts/* * Support rcAt for events and error endpoints for pallets * support rcAt for pallet storage * Support rcAt for pallets pool assets * Support rcAt for pallets validators * Support rcAt for dispatchables
1 parent c350c7e commit 00f8311

14 files changed

+938
-155
lines changed

docs/dist/app.bundle.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/src/openapi-v1.yaml

Lines changed: 300 additions & 3 deletions
Large diffs are not rendered by default.

src/controllers/pallets/PalletsAssetConversionController.ts

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
// You should have received a copy of the GNU General Public License
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17+
import { BlockHash } from '@polkadot/types/interfaces';
1718
import { RequestHandler } from 'express';
1819

20+
import { validateRcAt } from '../../middleware';
1921
import { PalletsAssetConversionService } from '../../services';
2022
import AbstractController from '../AbstractController';
2123

@@ -28,20 +30,70 @@ export default class PalletsAssetConversionController extends AbstractController
2830
}
2931

3032
protected initRoutes(): void {
33+
this.router.use(this.path, validateRcAt);
3134
this.safeMountAsyncGetHandlers([
3235
['/next-available-id', this.getNextAvailableId],
3336
['/liquidity-pools', this.getLiquidityPools],
3437
]);
3538
}
3639

37-
private getNextAvailableId: RequestHandler = async ({ query: { at } }, res): Promise<void> => {
38-
const hash = await this.getHashFromAt(at);
40+
private getNextAvailableId: RequestHandler = async ({ query: { at, rcAt } }, res): Promise<void> => {
41+
let hash: BlockHash;
42+
let rcBlockNumber: string | undefined;
3943

40-
PalletsAssetConversionController.sanitizedSend(res, await this.service.fetchNextAvailableId(hash));
44+
if (rcAt) {
45+
const rcAtResult = await this.getHashFromRcAt(rcAt);
46+
hash = rcAtResult.ahHash;
47+
rcBlockNumber = rcAtResult.rcBlockNumber;
48+
} else {
49+
hash = await this.getHashFromAt(at);
50+
}
51+
52+
const result = await this.service.fetchNextAvailableId(hash);
53+
54+
if (rcBlockNumber) {
55+
const apiAt = await this.api.at(hash);
56+
const ahTimestamp = await apiAt.query.timestamp.now();
57+
58+
const enhancedResult = {
59+
...result,
60+
rcBlockNumber,
61+
ahTimestamp: ahTimestamp.toString(),
62+
};
63+
64+
PalletsAssetConversionController.sanitizedSend(res, enhancedResult);
65+
} else {
66+
PalletsAssetConversionController.sanitizedSend(res, result);
67+
}
4168
};
4269

43-
private getLiquidityPools: RequestHandler = async ({ query: { at } }, res): Promise<void> => {
44-
const hash = await this.getHashFromAt(at);
45-
PalletsAssetConversionController.sanitizedSend(res, await this.service.fetchLiquidityPools(hash));
70+
private getLiquidityPools: RequestHandler = async ({ query: { at, rcAt } }, res): Promise<void> => {
71+
let hash: BlockHash;
72+
let rcBlockNumber: string | undefined;
73+
74+
if (rcAt) {
75+
const rcAtResult = await this.getHashFromRcAt(rcAt);
76+
hash = rcAtResult.ahHash;
77+
rcBlockNumber = rcAtResult.rcBlockNumber;
78+
} else {
79+
hash = await this.getHashFromAt(at);
80+
}
81+
82+
const result = await this.service.fetchLiquidityPools(hash);
83+
84+
if (rcBlockNumber) {
85+
const apiAt = await this.api.at(hash);
86+
const ahTimestamp = await apiAt.query.timestamp.now();
87+
88+
const enhancedResult = {
89+
...result,
90+
rcBlockNumber,
91+
ahTimestamp: ahTimestamp.toString(),
92+
};
93+
94+
PalletsAssetConversionController.sanitizedSend(res, enhancedResult);
95+
} else {
96+
PalletsAssetConversionController.sanitizedSend(res, result);
97+
}
4698
};
4799
}

src/controllers/pallets/PalletsAssetsController.ts

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,10 @@
1414
// You should have received a copy of the GNU General Public License
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17+
import { BlockHash } from '@polkadot/types/interfaces';
1718
import { RequestHandler } from 'express';
1819

20+
import { validateRcAt } from '../../middleware';
1921
import { PalletsAssetsService } from '../../services';
2022
import AbstractController from '../AbstractController';
2123

@@ -28,6 +30,8 @@ import AbstractController from '../AbstractController';
2830
* Query:
2931
* - (Optional)`at`: Block at which to retrieve runtime version information at. Block
3032
* identifier, as the block height or block hash. Defaults to most recent block.
33+
* - (Optional)`rcAt`: Relay chain block at which to retrieve Asset Hub asset info. Only supported
34+
* for Asset Hub endpoints. Cannot be used with 'at' parameter.
3135
*
3236
* `/pallets/assets/:assetId/asset-info`
3337
* Returns:
@@ -54,6 +58,8 @@ import AbstractController from '../AbstractController';
5458
* - `symbol`: The ticker symbol for this asset.
5559
* - `decimals`: The number of decimals this asset uses to represent one unit.
5660
* - `isFrozen`: Whether the asset metadata may be changed by a non Force origin.
61+
* - `rcBlockNumber`: The relay chain block number used for the query. Only present when `rcAt` parameter is used.
62+
* - `ahTimestamp`: The Asset Hub block timestamp. Only present when `rcAt` parameter is used.
5763
*
5864
* Substrate References:
5965
* - Assets Pallet: https://crates.parity.io/pallet_assets/index.html
@@ -69,16 +75,42 @@ export default class PalletsAssetsController extends AbstractController<PalletsA
6975
}
7076

7177
protected initRoutes(): void {
78+
this.router.use(this.path, validateRcAt);
7279
this.safeMountAsyncGetHandlers([['/asset-info', this.getAssetById]]);
7380
}
7481

75-
private getAssetById: RequestHandler = async ({ params: { assetId }, query: { at } }, res): Promise<void> => {
76-
const hash = await this.getHashFromAt(at);
82+
private getAssetById: RequestHandler = async ({ params: { assetId }, query: { at, rcAt } }, res): Promise<void> => {
83+
let hash: BlockHash;
84+
let rcBlockNumber: string | undefined;
85+
86+
if (rcAt) {
87+
const rcAtResult = await this.getHashFromRcAt(rcAt);
88+
hash = rcAtResult.ahHash;
89+
rcBlockNumber = rcAtResult.rcBlockNumber;
90+
} else {
91+
hash = await this.getHashFromAt(at);
92+
}
93+
7794
/**
7895
* Verify our param `assetId` is an integer represented as a string, and return
7996
* it as an integer
8097
*/
8198
const index = this.parseNumberOrThrow(assetId, '`assetId` path param is not a number');
82-
PalletsAssetsController.sanitizedSend(res, await this.service.fetchAssetById(hash, index));
99+
const result = await this.service.fetchAssetById(hash, index);
100+
101+
if (rcBlockNumber) {
102+
const apiAt = await this.api.at(hash);
103+
const ahTimestamp = await apiAt.query.timestamp.now();
104+
105+
const enhancedResult = {
106+
...result,
107+
rcBlockNumber,
108+
ahTimestamp: ahTimestamp.toString(),
109+
};
110+
111+
PalletsAssetsController.sanitizedSend(res, enhancedResult);
112+
} else {
113+
PalletsAssetsController.sanitizedSend(res, result);
114+
}
83115
};
84116
}

src/controllers/pallets/PalletsConstsController.ts

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
// You should have received a copy of the GNU General Public License
1515
// along with this program. If not, see <http://www.gnu.org/licenses/>.
1616

17+
import { BlockHash } from '@polkadot/types/interfaces';
1718
import { stringCamelCase } from '@polkadot/util';
1819
import { RequestHandler } from 'express-serve-static-core';
1920

21+
import { validateRcAt } from '../../middleware';
2022
import { PalletsConstantsService } from '../../services';
2123
import { IPalletsConstantsParam } from '../../types/requests';
2224
import AbstractController from '../AbstractController';
@@ -42,44 +44,92 @@ export default class PalletsConstantsController extends AbstractController<Palle
4244
}
4345

4446
protected initRoutes(): void {
47+
this.router.use(this.path, validateRcAt);
4548
this.safeMountAsyncGetHandlers([
4649
['/:constantItemId', this.getConstById as RequestHandler],
4750
['/', this.getConsts],
4851
]);
4952
}
5053

5154
private getConstById: RequestHandler<IPalletsConstantsParam, unknown, unknown> = async (
52-
{ query: { at, metadata }, params: { palletId, constantItemId } },
55+
{ query: { at, metadata, rcAt }, params: { palletId, constantItemId } },
5356
res,
5457
): Promise<void> => {
5558
const metadataArg = metadata === 'true';
56-
const hash = await this.getHashFromAt(at);
59+
let hash: BlockHash;
60+
let rcBlockNumber: string | undefined;
61+
62+
if (rcAt) {
63+
const rcAtResult = await this.getHashFromRcAt(rcAt);
64+
hash = rcAtResult.ahHash;
65+
rcBlockNumber = rcAtResult.rcBlockNumber;
66+
} else {
67+
hash = await this.getHashFromAt(at);
68+
}
69+
5770
const historicApi = await this.api.at(hash);
5871

59-
PalletsConstantsController.sanitizedSend(
60-
res,
61-
await this.service.fetchConstantItem(historicApi, {
62-
hash,
63-
// stringCamelCase ensures we don't have snake case or kebab case
64-
palletId: stringCamelCase(palletId),
65-
constantItemId: stringCamelCase(constantItemId),
66-
metadata: metadataArg,
67-
}),
68-
);
72+
const result = await this.service.fetchConstantItem(historicApi, {
73+
hash,
74+
// stringCamelCase ensures we don't have snake case or kebab case
75+
palletId: stringCamelCase(palletId),
76+
constantItemId: stringCamelCase(constantItemId),
77+
metadata: metadataArg,
78+
});
79+
80+
if (rcBlockNumber) {
81+
const apiAt = await this.api.at(hash);
82+
const ahTimestamp = await apiAt.query.timestamp.now();
83+
84+
const enhancedResult = {
85+
...result,
86+
rcBlockNumber,
87+
ahTimestamp: ahTimestamp.toString(),
88+
};
89+
90+
PalletsConstantsController.sanitizedSend(res, enhancedResult);
91+
} else {
92+
PalletsConstantsController.sanitizedSend(res, result);
93+
}
6994
};
7095

71-
private getConsts: RequestHandler = async ({ params: { palletId }, query: { at, onlyIds } }, res): Promise<void> => {
96+
private getConsts: RequestHandler = async (
97+
{ params: { palletId }, query: { at, onlyIds, rcAt } },
98+
res,
99+
): Promise<void> => {
72100
const onlyIdsArg = onlyIds === 'true';
73-
const hash = await this.getHashFromAt(at);
101+
let hash: BlockHash;
102+
let rcBlockNumber: string | undefined;
103+
104+
if (rcAt) {
105+
const rcAtResult = await this.getHashFromRcAt(rcAt);
106+
hash = rcAtResult.ahHash;
107+
rcBlockNumber = rcAtResult.rcBlockNumber;
108+
} else {
109+
hash = await this.getHashFromAt(at);
110+
}
111+
74112
const historicApi = await this.api.at(hash);
75113

76-
PalletsConstantsController.sanitizedSend(
77-
res,
78-
await this.service.fetchConstants(historicApi, {
79-
hash,
80-
palletId: stringCamelCase(palletId),
81-
onlyIds: onlyIdsArg,
82-
}),
83-
);
114+
const result = await this.service.fetchConstants(historicApi, {
115+
hash,
116+
palletId: stringCamelCase(palletId),
117+
onlyIds: onlyIdsArg,
118+
});
119+
120+
if (rcBlockNumber) {
121+
const apiAt = await this.api.at(hash);
122+
const ahTimestamp = await apiAt.query.timestamp.now();
123+
124+
const enhancedResult = {
125+
...result,
126+
rcBlockNumber,
127+
ahTimestamp: ahTimestamp.toString(),
128+
};
129+
130+
PalletsConstantsController.sanitizedSend(res, enhancedResult);
131+
} else {
132+
PalletsConstantsController.sanitizedSend(res, result);
133+
}
84134
};
85135
}

0 commit comments

Comments
 (0)