Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 6 additions & 5 deletions openapi/openapi-proposal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -979,7 +979,7 @@ paths:
get:
tags:
- runtime
summary: Get version information of the runtime.
summary: Get version information of the Substrate runtime.
description: Returns version information related to the runtime.
parameters:
- name: at
Expand Down Expand Up @@ -1599,16 +1599,17 @@ components:
- Live
implVersion:
type: string
description: Version of the implementation of the specification. Non-consensus-breaking
description: Version of the implementation specification. Non-consensus-breaking
optimizations are about the only changes that could be made which would
result in only the `impl_version` changing.
result in only the `impl_version` changing. The `impl_version` is set to 0
when `spec_version` is incremented.
specName:
type: string
description: Identifies the different Substrate runtimes.
specVersion:
type: string
description: version of the runtime specification
txVersion:
description: Version of the runtime specification.
transactionVersion:
type: string
description: All existing dispatches are fully compatible when this number
doesn't change. This number must change when an existing dispatchable
Expand Down
51 changes: 51 additions & 0 deletions src/controllers/runtime/RuntimeCodeController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { ApiPromise } from '@polkadot/api';
import { RequestHandler } from 'express';

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

/**
* Get version information of the Substrate runtime.
*
* Query:
* - (Optional)`at`: Block at which to retrieve runtime version information at. Block
* identifier, as the block height or block hash. Defaults to most recent block.
*
* Returns:
* - `at`: Block number and hash at which the call was made.
* - `code`: Runtime code wasm blob.
Comment thread
emostov marked this conversation as resolved.
Outdated
*/
export default class RuntimeCodeController extends AbstractController<
RuntimeCodeService
> {
constructor(api: ApiPromise) {
super(api, '/runtime/code', new RuntimeCodeService(api));
this.initRoutes();
}

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

/**
* Get the chain's latest metadata in a decoded, JSON format.
*
* @param _req Express Request
* @param res Express Response
*/

private getCodeAtBlock: RequestHandler = async (
{ query: { at } },
res
): Promise<void> => {
const hash =
typeof at === 'string'
? await this.getHashForBlock(at)
: await this.api.rpc.chain.getFinalizedHead();

RuntimeCodeController.sanitizedSend(
res,
await this.service.fetchCode(hash)
);
};
}
55 changes: 55 additions & 0 deletions src/controllers/runtime/RuntimeSpecController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { ApiPromise } from '@polkadot/api';
import { RequestHandler } from 'express';

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

/**
* Get version information of the Substrate runtime.
*
* Query:
* - (Optional)`at`: Block at which to retrieve runtime version information at. Block
Comment thread
emostov marked this conversation as resolved.
Outdated
* identifier, as the block height or block hash. Defaults to most recent block.
*
* Returns:
* - `at`: Block number and hash at which the call was made.
* - `authoringVersion`: The version of the authorship interface. An authoring node
* will not attempt to author blocks unless this is equal to its native runtime.
* - `chainType`: Type of the chain.
* - `implVersion`: Version of the implementation specification. Non-consensus-breaking
* optimizations are about the only changes that could be made which would
* result in only the `impl_version` changing. The `impl_version` is set to 0
* when `spec_version` is incremented.
* - `specName`: Identifies different Substrate runtimes.
Comment thread
emostov marked this conversation as resolved.
Outdated
* - `specVersion`: Version of the runtime specification.
* - `transactionVersion`: All existing dispatches are fully compatible when this
* number doesn't change. This number must change when an existing dispatchable
* (module ID, dispatch ID) is changed, either through an alteration in its
* user-level semantics, a parameter added/removed/changed, a dispatchable
* its index.
* - `properties`: Arbitrary properties defined in the chain spec.
*/
export default class RuntimeSpecController extends AbstractController<
RuntimeSpecService
> {
constructor(api: ApiPromise) {
super(api, '/runtime/spec', new RuntimeSpecService(api));
this.initRoutes();
}

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

private getSpec: RequestHandler = async ({ query: { at } }, res) => {
const hash =
typeof at === 'string'
? await this.getHashForBlock(at)
: await this.api.rpc.chain.getFinalizedHead();

RuntimeSpecController.sanitizedSend(
res,
await this.service.fetchSpec(hash)
);
};
}
2 changes: 2 additions & 0 deletions src/controllers/runtime/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export { default as Metadata } from './RuntimeMetadataController';
export { default as RuntimeCode } from './RuntimeCodeController';
export { default as RuntimeSpec } from './RuntimeSpecController';
4 changes: 4 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ async function main() {
const stakingController = new controllers.PalletsStakingProgress(api);
const vestingController = new controllers.AccountsVestingInfo(api);
const metadataController = new controllers.Metadata(api);
const runtimeCodeController = new controllers.RuntimeCode(api);
const runtimeSpecController = new controllers.RuntimeSpec(api);
const claimsController = new controllers.Claims(api);
const txArtifactsController = new controllers.TransactionMaterial(api);
const txFeeEstimateController = new controllers.TransactionFeeEstimate(api);
Expand All @@ -81,6 +83,8 @@ async function main() {
stakingController,
vestingController,
metadataController,
runtimeCodeController,
runtimeSpecController,
claimsController,
txArtifactsController,
txFeeEstimateController,
Expand Down
2 changes: 1 addition & 1 deletion src/services/accounts/AccountsStakingInfoService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class AccountsStakingInfoService extends AbstractService {

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

if (controllerOption.isNone) {
Expand Down
18 changes: 18 additions & 0 deletions src/services/runtime/RuntimeCodeService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { sanitizeNumbers } from '../../sanitize/sanitizeNumbers';
import { blockHash789629, mockApi } from '../test-helpers/mock';
import * as codeResponse from '../test-helpers/responses/runtime/code789629.json';
import { RuntimeCodeService } from './RuntimeCodeService';

const runtimeCodeService = new RuntimeCodeService(mockApi);

describe('RuntimeCodeService', () => {
describe('fetchCode', () => {
it('works when ApiPromise works', async () => {
expect(
sanitizeNumbers(
await runtimeCodeService.fetchCode(blockHash789629)
)
).toStrictEqual(codeResponse);
});
});
});
32 changes: 32 additions & 0 deletions src/services/runtime/RuntimeCodeService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Option, Raw } from '@polkadot/types';
import { BlockHash } from '@polkadot/types/interfaces';
import { IMetadataCode } from 'src/types/responses';

import { AbstractService } from '../AbstractService';

// https://github.com/shawntabrizi/substrate-graph-benchmarks/blob/master/js/extensions/known-keys.js#L21
Comment thread
emostov marked this conversation as resolved.
Outdated
export const CODE_KEY = '0x3a636f6465';
Comment thread
joepetrowski marked this conversation as resolved.
Outdated

export class RuntimeCodeService extends AbstractService {
/**
* Fetch `Metadata` in decoded JSON form.
*
* @param hash `BlockHash` to make call at
*/
async fetchCode(hash: BlockHash): Promise<IMetadataCode> {
const api = await this.ensureMeta(hash);

const [code, { number }] = await Promise.all([
api.rpc.state.getStorage(CODE_KEY, hash),
api.rpc.chain.getHeader(hash),
]);

return {
at: {
hash,
height: number.unwrap().toString(10),
},
code: code as Option<Raw>,
};
}
}
18 changes: 18 additions & 0 deletions src/services/runtime/RuntimeSpecService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { sanitizeNumbers } from '../../sanitize/sanitizeNumbers';
import { blockHash789629, mockApi } from '../test-helpers/mock';
import * as response from '../test-helpers/responses/runtime/spec.json';
import { RuntimeSpecService } from './RuntimeSpecService';

const runtimeSpecService = new RuntimeSpecService(mockApi);

describe('RuntimeSpecService', () => {
describe('fetchSpec', () => {
it('works when ApiPromise works', async () => {
expect(
sanitizeNumbers(
await runtimeSpecService.fetchSpec(blockHash789629)
)
).toStrictEqual(response);
});
});
});
33 changes: 33 additions & 0 deletions src/services/runtime/RuntimeSpecService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { BlockHash } from '@polkadot/types/interfaces';
import { IRuntimeSpec } from 'src/types/responses';

import { AbstractService } from '../AbstractService';
export class RuntimeSpecService extends AbstractService {
async fetchSpec(hash: BlockHash): Promise<IRuntimeSpec> {
const [
{
authoringVersion,
specName,
specVersion,
transactionVersion,
implVersion,
},
chainType,
properties,
] = await Promise.all([
this.api.rpc.state.getRuntimeVersion(hash),
this.api.rpc.system.chainType(),
this.api.rpc.system.properties(),
]);

return {
authoringVersion,
transactionVersion,
implVersion,
specName,
specVersion,
chainType,
properties,
};
}
}
2 changes: 2 additions & 0 deletions src/services/runtime/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
export * from './RuntimeMetadataService';
export * from './RuntimeCodeService';
export * from './RuntimeSpecService';
26 changes: 26 additions & 0 deletions src/services/test-helpers/mock/mockApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ const getRuntimeVersion = () =>
specName: polkadotRegistry.createType('Text', 'polkadot'),
specVersion: polkadotRegistry.createType('u32', 16),
transactionVersion: polkadotRegistry.createType('u32', 2),
authoringVersion: polkadotRegistry.createType('u32', 0),
implVersion: polkadotRegistry.createType('u32', 0),
};
});

Expand Down Expand Up @@ -193,6 +195,27 @@ export const queryInfoBalancesTransfer = (
export const submitExtrinsic = (_extrinsic: string): Promise<Hash> =>
Promise.resolve().then(() => polkadotRegistry.createType('Hash'));

const getStorage = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('Option<Raw>', '0x')
);

const chainType = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('ChainType', {
Live: null,
})
);

const properties = () =>
Promise.resolve().then(() =>
polkadotRegistry.createType('ChainProperties', {
ss58Format: '0',
tokenDecimals: '12',
tokenSymbol: 'DOT',
})
);

const getFinalizedHead = () => Promise.resolve().then(() => blockHash789629);

export const tx = (): Extrinsic =>
Expand Down Expand Up @@ -275,9 +298,12 @@ export const mockApi = ({
state: {
getRuntimeVersion,
getMetadata,
getStorage,
},
system: {
chain,
chainType,
properties,
},
payment: {
queryInfo: queryInfoBalancesTransfer,
Expand Down
7 changes: 7 additions & 0 deletions src/services/test-helpers/responses/runtime/code789629.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"at": {
"hash": "0x7b713de604a99857f6c25eacc115a4f28d2611a23d9ddff99ab0e4f1c17a8578",
"height": "789629"
},
"code": "0x"
}
15 changes: 15 additions & 0 deletions src/services/test-helpers/responses/runtime/spec.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"authoringVersion": "0",
"transactionVersion": "2",
"implVersion": "0",
"specName": "polkadot",
"specVersion": "16",
"chainType": {
"Live": null
},
"properties": {
"ss58Format": "0",
"tokenDecimals": "12",
"tokenSymbol": "DOT"
}
}
8 changes: 8 additions & 0 deletions src/types/responses/MetadataCode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { Option, Raw } from '@polkadot/types';

import { IAt } from '.';

export interface IMetadataCode {
at: IAt;
code: Option<Raw>;
}
12 changes: 12 additions & 0 deletions src/types/responses/RuntimeSpec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { ChainProperties, ChainType } from '@polkadot/types/interfaces';
import { Text, u32 } from '@polkadot/types/primitive';

export interface IRuntimeSpec {
authoringVersion: u32;
transactionVersion: u32;
implVersion: u32;
specName: Text;
specVersion: u32;
chainType: ChainType;
properties: ChainProperties;
}
2 changes: 2 additions & 0 deletions src/types/responses/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ export * from './AccountStakingInfo';
export * from './AccountVestingInfo';
export * from './TransactionMaterial';
export * from './Extrinsic';
export * from './MetadataCode';
export * from './RuntimeSpec';