-
Notifications
You must be signed in to change notification settings - Fork 162
feat: add metadata versions endpoints #1424
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
Changes from 4 commits
53a2a0d
294f9a1
16d554f
17007a2
132d1b1
2afcf60
c3460b9
e63db36
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1153,6 +1153,54 @@ paths: | |
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/Error' | ||
| /transaction/material/{metadataVersion}: | ||
| get: | ||
| tags: | ||
| - transaction | ||
| summary: Get all the network information needed to construct a transaction offline and | ||
| the version of metadata specified in `metadataVersion`. | ||
| description: Returns the material that is universal to constructing any | ||
| signed transaction offline and the v14 of metadata. Replaces `/tx/artifacts` | ||
| from versions < v1.0.0. | ||
| operationId: getTransactionMaterialwithVersionedMetadata | ||
| parameters: | ||
| - name: metadataVersion | ||
| in: path | ||
| description: The version of metadata. The input is expected in a `vX` format, where `X` | ||
| represents the version number (e.g. `v14`, `v15`). By default, metadata is outputted | ||
| in 'JSON' format, unless the `metadata` query parameter is provided, in which case it can be | ||
| either in 'JSON' or 'SCALE' format. | ||
|
||
| required: true | ||
| schema: | ||
| type: string | ||
| - name: at | ||
| in: query | ||
| description: Block at which to retrieve the transaction construction | ||
| material. | ||
| required: false | ||
| schema: | ||
| type: string | ||
| description: Block identifier, as the block height or block hash. | ||
| format: unsignedInteger or $hex | ||
| - name: metadata | ||
| in: query | ||
| description: Specifies the format of the metadata to be returned. Accepted values are | ||
| 'json', and 'scale'. 'json' being the decoded metadata, and 'scale' being the SCALE encoded metadata. | ||
| schema: | ||
| type: string | ||
| responses: | ||
| "200": | ||
| description: successful operation | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/TransactionMaterial' | ||
| "400": | ||
| description: invalid blockId supplied for at query param | ||
| content: | ||
| application/json: | ||
| schema: | ||
| $ref: '#/components/schemas/Error' | ||
| /pallets/assets/{assetId}/asset-info: | ||
| get: | ||
| tags: | ||
|
|
@@ -1753,6 +1801,69 @@ paths: | |
| schema: | ||
| type: object | ||
| description: Response is dependent on the runtime metadata contents. | ||
| /runtime/metadata/{metadataVersion}: | ||
| get: | ||
| tags: | ||
| - runtime | ||
| summary: Get the requested version of runtime metadata in decoded, JSON form. | ||
| description: >- | ||
| Returns the requested version of runtime metadata as a JSON object. | ||
| Substrate Reference: | ||
| - FRAME Support: https://crates.parity.io/frame_support/metadata/index.html | ||
| - Knowledge Base: https://substrate.dev/docs/en/knowledgebase/runtime/metadata | ||
| parameters: | ||
| - name: metadataVersion | ||
| in: path | ||
| description: The version of metadata. The input is expected in a `vX` format, where `X` | ||
| represents the version number (e.g. `v14`, `v15`). | ||
| required: true | ||
| schema: | ||
| type: string | ||
| - name: at | ||
| in: query | ||
| description: Block at which to retrieve the metadata at. | ||
| 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: object | ||
| description: Response is dependent on the runtime metadata contents. | ||
| /runtime/metadata/versions: | ||
| get: | ||
| tags: | ||
| - runtime | ||
| summary: Get the available versions of runtime metadata. | ||
| description: >- | ||
| Returns the available versions of runtime metadata. | ||
| Substrate Reference: | ||
| - FRAME Support: https://crates.parity.io/frame_support/metadata/index.html | ||
| - Knowledge Base: https://substrate.dev/docs/en/knowledgebase/runtime/metadata | ||
| parameters: | ||
| - name: at | ||
| in: query | ||
| description: Block at which to retrieve the metadata versions at. | ||
| 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 | ||
| items: | ||
| type: string | ||
| description: An array with the available metadata versions. | ||
| /runtime/code: | ||
| get: | ||
| tags: | ||
|
|
||
| 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 | ||||||
|
|
@@ -23,6 +23,10 @@ import AbstractController from '../AbstractController'; | |||||
| /** | ||||||
| * GET the chain's metadata. | ||||||
| * | ||||||
| * Path params: | ||||||
| * - (Optional) `metadataVersion`: The specific version of the Metadata to query. | ||||||
| * The input must conform to the `vX` format, where `X` represents the version number (examples: 'v14', 'v15'). | ||||||
| * | ||||||
| * Query: | ||||||
| * - (Optional) `at`: Block hash or height at which to query. If not provided, queries | ||||||
| * finalized head. | ||||||
|
|
@@ -41,7 +45,11 @@ export default class RuntimeMetadataController extends AbstractController<Runtim | |||||
| } | ||||||
|
|
||||||
| protected initRoutes(): void { | ||||||
| this.safeMountAsyncGetHandlers([['', this.getMetadata]]); | ||||||
| this.safeMountAsyncGetHandlers([ | ||||||
| ['/', this.getMetadata], | ||||||
| ['/versions', this.getMetadataAvailableVersions], | ||||||
| ['/:metadataVersion', this.getMetadataVersioned], | ||||||
| ]); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -65,4 +73,64 @@ export default class RuntimeMetadataController extends AbstractController<Runtim | |||||
| metadataOpts: { registry, version: metadata.version }, | ||||||
| }); | ||||||
| }; | ||||||
|
|
||||||
| /** | ||||||
| * Get the chain's metadata at a specific version in a decoded, JSON format. | ||||||
| * | ||||||
| * @param _req Express Request | ||||||
| * @param res Express Response | ||||||
| */ | ||||||
| private getMetadataVersioned: RequestHandler = async ( | ||||||
| { params: { metadataVersion }, query: { at } }, | ||||||
| res, | ||||||
| ): Promise<void> => { | ||||||
| const hash = await this.getHashFromAt(at); | ||||||
|
|
||||||
| let api; | ||||||
|
||||||
| if (at) { | ||||||
| api = await this.api.at(hash); | ||||||
| } else { | ||||||
| api = this.api; | ||||||
| } | ||||||
|
|
||||||
| // Validation of the `metadataVersion` path parameter. | ||||||
| const metadataV = metadataVersion.slice(1); | ||||||
| const version = this.parseNumberOrThrow( | ||||||
| metadataV, | ||||||
| `Version ${metadataV.toString()} of metadata provided is not a number.`, | ||||||
| ); | ||||||
|
|
||||||
| const regExPattern = new RegExp('^[vV][0-9]+$'); | ||||||
| if (regExPattern.test(metadataVersion) === false) { | ||||||
Imod7 marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||
| throw new Error( | ||||||
| `${metadataVersion} input is not of the expected 'vX' format, where 'X' represents the version number (examples: 'v14', 'v15').`, | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| const availableVersions = (await api.call.metadata.metadataVersions()).toHuman() as string[]; | ||||||
|
||||||
| if (version && availableVersions?.includes(version.toString()) === false) { | ||||||
|
||||||
| if (version && availableVersions?.includes(version.toString()) === false) { | |
| if (version && !availableVersions?.includes(version.toString())) { |
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api will always be true here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ofc! 😱 Changing this!
| 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 | ||||||
|
|
@@ -25,6 +25,10 @@ export type MetadataOpts = 'json' | 'scale'; | |||||
| /** | ||||||
| * GET all the network information needed to construct a transaction offline. | ||||||
| * | ||||||
| * Path params: | ||||||
| * - (Optional) `metadataVersion`: The specific version of the Metadata to query. | ||||||
| * The input must conform to the `vX` format, where `X` represents the version number (examples: 'v14', 'v15'). | ||||||
| * | ||||||
| * Query | ||||||
| * - (Optional) `metadata`: It accepts `json`, or `scale` values. If it is not present, | ||||||
| * the metadata field will not be included. | ||||||
|
|
@@ -59,7 +63,10 @@ export default class TransactionMaterialController extends AbstractController<Tr | |||||
| } | ||||||
|
|
||||||
| protected initRoutes(): void { | ||||||
| this.safeMountAsyncGetHandlers([['', this.getTransactionMaterial]]); | ||||||
| this.safeMountAsyncGetHandlers([ | ||||||
| ['/', this.getTransactionMaterial], | ||||||
| ['/:metadataVersion', this.getTransactionMaterialwithVersionedMetadata], | ||||||
| ]); | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
|
|
@@ -98,4 +105,51 @@ export default class TransactionMaterialController extends AbstractController<Tr | |||||
|
|
||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| /** | ||||||
| * Get the chain's metadata at the requested version in JSON or scale format | ||||||
| * depending on the `metadata` query param. | ||||||
| * | ||||||
| * @param _req Express Request | ||||||
| * @param res Express Response | ||||||
| */ | ||||||
| private getTransactionMaterialwithVersionedMetadata: RequestHandler = async ( | ||||||
| { params: { metadataVersion }, query: { at, metadata } }, | ||||||
| res, | ||||||
| ): Promise<void> => { | ||||||
| const hash = await this.getHashFromAt(at); | ||||||
|
|
||||||
| let api; | ||||||
| if (at) { | ||||||
| api = await this.api.at(hash); | ||||||
| } else { | ||||||
| api = this.api; | ||||||
| } | ||||||
|
|
||||||
| // Validation of the `metadataVersion` path parameter. | ||||||
| const metadataV = metadataVersion.slice(1); | ||||||
| const version = this.parseNumberOrThrow( | ||||||
| metadataV, | ||||||
| `Version ${metadataV.toString()} of metadata provided is not a number.`, | ||||||
| ); | ||||||
|
|
||||||
| const regExPattern = new RegExp('^[vV][0-9]+$'); | ||||||
| if (regExPattern.test(metadataVersion) === false) { | ||||||
| throw new Error( | ||||||
| `${metadataVersion} input is not of the expected 'vX' format, where 'X' represents the version number (examples: 'v14', 'v15').`, | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| const availableVersions = (await api.call.metadata.metadataVersions()).toHuman() as string[]; | ||||||
| if (version && availableVersions?.includes(version.toString()) === false) { | ||||||
|
||||||
| if (version && availableVersions?.includes(version.toString()) === false) { | |
| if (version && !availableVersions?.includes(version.toString())) { |
| 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 | ||
|
|
@@ -15,7 +15,9 @@ | |
| // along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
|
||
| import { Metadata } from '@polkadot/types'; | ||
| import { BlockHash } from '@polkadot/types/interfaces'; | ||
| import type { Option } from '@polkadot/types/codec'; | ||
| import type { BlockHash, OpaqueMetadata } from '@polkadot/types/interfaces'; | ||
| import { InternalServerError } from 'http-errors'; | ||
|
|
||
| import { AbstractService } from '../AbstractService'; | ||
|
|
||
|
|
@@ -32,4 +34,45 @@ export class RuntimeMetadataService extends AbstractService { | |
|
|
||
| return metadata; | ||
| } | ||
|
|
||
| /** | ||
| * Fetch the requested version of `Metadata` in decoded JSON form. | ||
| * | ||
| * @param hash `BlockHash` to make call at | ||
| */ | ||
| async fetchMetadataVersioned(hash: BlockHash, metadataVersion: number): Promise<Metadata> { | ||
| const { api } = this; | ||
| const apiAt = await api.at(hash); | ||
|
||
|
|
||
| let metadata: Option<OpaqueMetadata> | undefined; | ||
| let metadataVersioned: Metadata | undefined; | ||
| try { | ||
| metadata = await apiAt.call.metadata.metadataAtVersion(metadataVersion); | ||
| if (metadata) { | ||
| metadataVersioned = new Metadata(apiAt.registry, metadata.unwrap()); | ||
| } else { | ||
| throw new Error(`Metadata for version ${metadataVersion} is not available.`); | ||
| } | ||
| } catch { | ||
| throw new InternalServerError( | ||
| `An error occured while attempting to fetch ${metadataVersion.toString()} metadata.`, | ||
| ); | ||
| } | ||
|
|
||
| return metadataVersioned; | ||
| } | ||
|
|
||
| /** | ||
| * Fetch the available `Metadata` versions. | ||
| * | ||
| * @param hash `BlockHash` to make call at | ||
| */ | ||
| async fetchMetadataVersions(hash: BlockHash): Promise<string[]> { | ||
| const { api } = this; | ||
| const apiAt = await api.at(hash); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same with this api.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed the previous one but for this one, in the |
||
|
|
||
| const availableVersions = (await apiAt.call.metadata.metadataVersions()).toHuman() as string[]; | ||
|
|
||
| return availableVersions; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Returns all the materials necessary to constructing any signed transactions offline."
I don't think we need any other details, and we can also get rid of the mention to
/tx/artifacts.