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

Fix hydra-typegen to properly generate types for deprecated/deleted events & extrinsics #531

Merged
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
70 changes: 55 additions & 15 deletions packages/hydra-typegen/src/commands/typegen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,34 +136,74 @@
strict: flags.strict,
} as IConfig
}

async buildGeneratorConfigs(config: IConfig): Promise<GeneratorConfig[]> {
async buildGeneratorConfigs(config: IConfig): Promise<{

Check failure on line 139 in packages/hydra-typegen/src/commands/typegen/index.ts

View workflow job for this annotation

GitHub Actions / run Hydra unit tests (18.x)

Expected blank line between class members

Check failure on line 139 in packages/hydra-typegen/src/commands/typegen/index.ts

View workflow job for this annotation

GitHub Actions / run Hydra unit tests (18.x)

Expected blank line between class members
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just need an extra line here to satisfy linter ;)

https://github.com/Joystream/hydra/pull/531/checks#step:4:365

Suggested change
async buildGeneratorConfigs(config: IConfig): Promise<{
async buildGeneratorConfigs(config: IConfig): Promise<{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can do it manually with yarn lint --fix

configs: GeneratorConfig[]
allMissingEvents: string[][]
allMissingCalls: string[][]
}> {
const { outDir } = config

const specsMetadata = await getAllMetadata(config.metadata)

return Promise.all(
const results = await Promise.all(
specsMetadata.map(async ([originalMetadata, chainSpec]) => {
const modules = await extractMeta(config, originalMetadata)
const { extracted, missingEvents, missingCalls } = await extractMeta(
config,
originalMetadata
)

return {
importsRegistry: buildImportsRegistry(),
modules,
validateArgs: config.strict || false, // do not enforce validation by default
dest: path.resolve(
path.join(outDir, chainSpec.specVersion.toString())
),
originalMetadata,
specVersion: chainSpec.specVersion,
config: {
importsRegistry: buildImportsRegistry(),
modules: extracted,
validateArgs: config.strict || false,
dest: path.resolve(
path.join(outDir, chainSpec.specVersion.toString())
),
originalMetadata,
specVersion: chainSpec.specVersion,
},
missingEvents,
missingCalls,
}
})
)

const generatorConfigs = results.map((r) => r.config)
const allMissingEvents = results.map((r) => r.missingEvents)
const allMissingCalls = results.map((r) => r.missingCalls)

return { configs: generatorConfigs, allMissingEvents, allMissingCalls }
}

async generate(config: IConfig): Promise<void> {
const generatorConfigs = await this.buildGeneratorConfigs(config)
const { configs, allMissingEvents, allMissingCalls } =
await this.buildGeneratorConfigs(config)

const globalMissingEvents = config.events.filter(
(event) =>
!allMissingEvents.some(
(missingEvents) => !missingEvents.includes(event)
)
)

const globalMissingCalls = config.calls.filter(
(call) =>
!allMissingCalls.some((missingCalls) => !missingCalls.includes(call))
)

if (globalMissingEvents.length > 0) {
throw new Error(
`No metadata found for the events: ${globalMissingEvents.join(', ')}`
)
}
if (globalMissingCalls.length > 0) {
throw new Error(
`No metadata found for the calls: ${globalMissingCalls.join(', ')}`
)
}

for (const generatorConfig of generatorConfigs) {
for (const generatorConfig of configs) {
const { dest } = generatorConfig

debug(`Output dir: ${dest}`)
Expand All @@ -175,6 +215,6 @@
generateModuleTypes(generatorConfig)
}

generateRootIndex(config, generatorConfigs)
generateRootIndex(config, configs)
}
}
61 changes: 39 additions & 22 deletions packages/hydra-typegen/src/metadata/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,49 +8,66 @@ import { TypeDef } from '@polkadot/types/types'
import { uniq } from 'lodash'
import { IConfig } from '../commands/typegen'
import { pushToDictionary } from '../util'
import { ExtractedModuleMeta, ExtractedVaraintData, weakEquals } from './types'
import { ExtractedVaraintData, MetaExtractionResult, weakEquals } from './types'

const debug = require('debug')('hydra-typegen:extract')

export async function extractMeta(
{ events, calls }: IConfig,
originalMetadata: Metadata
): Promise<ExtractedModuleMeta[]> {
): Promise<MetaExtractionResult> {
const modules: Record<string, PalletMetadataLatest> = {}
const moduleEvents: Record<string, ExtractedVaraintData[]> = {}
const moduleCalls: Record<string, ExtractedVaraintData[]> = {}
const moduleTypes: Record<string, string[]> = {}

const metadata = originalMetadata.asLatest

const missingEvents: string[] = []
const missingCalls: string[] = []

for (const e of events) {
const [module, event, types] = extractEvent(metadata, e)
const name = module.name.toString()
modules[name] = module
pushToDictionary(moduleEvents, name, event)
pushToDictionary(moduleTypes, name, ...types)
const extractedEvent = extractEvent(metadata, e)
if (extractedEvent) {
const [module, event, types] = extractedEvent
const name = module.name.toString()
modules[name] = module
pushToDictionary(moduleEvents, name, event)
pushToDictionary(moduleTypes, name, ...types)
} else {
missingEvents.push(e)
}
}

for (const c of calls) {
const [module, call, types] = extractCall(metadata, c)
const name = module.name.toString()
modules[name] = module
pushToDictionary(moduleCalls, name, call)
pushToDictionary(moduleTypes, name, ...types)
const extractedCall = extractCall(metadata, c)
if (extractedCall) {
const [module, call, types] = extractedCall
const name = module.name.toString()
modules[name] = module
pushToDictionary(moduleCalls, name, call)
pushToDictionary(moduleTypes, name, ...types)
} else {
missingCalls.push(c)
}
}

return Object.keys(modules).map((name) => ({
module: modules[name],
events: moduleEvents[name],
calls: moduleCalls[name],
types: moduleTypes[name],
}))
return {
extracted: Object.keys(modules).map((name) => ({
module: modules[name],
events: moduleEvents[name],
calls: moduleCalls[name],
types: moduleTypes[name],
})),
missingEvents,
missingCalls,
}
}

function extractCall(
meta: MetadataLatest,
callName: string
): [PalletMetadataLatest, ExtractedVaraintData, string[]] {
): [PalletMetadataLatest, ExtractedVaraintData, string[]] | undefined {
const [moduleName, method] = callName.split('.')

const module = meta.pallets.find((v) => weakEquals(v.name, moduleName))
Expand All @@ -69,7 +86,7 @@ function extractCall(
}

if (callVariant === undefined) {
throw new Error(`No metadata found for the call ${callName}`)
return undefined // extrinsic call not found
}

return [
Expand All @@ -82,7 +99,7 @@ function extractCall(
function extractEvent(
meta: MetadataLatest,
eventName: string
): [PalletMetadataLatest, ExtractedVaraintData, string[]] {
): [PalletMetadataLatest, ExtractedVaraintData, string[]] | undefined {
const [moduleName, method] = eventName.split('.')

const module = meta.pallets.find((v) => weakEquals(v.name, moduleName))
Expand All @@ -101,7 +118,7 @@ function extractEvent(
}

if (eventVaraint === undefined) {
throw new Error(`No metadata found for the event ${eventName}`)
return undefined // Event variant not found
}

return [
Expand Down
6 changes: 6 additions & 0 deletions packages/hydra-typegen/src/metadata/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export type ExtractedModuleMeta = {
types: string[]
}

export type MetaExtractionResult = {
extracted: ExtractedModuleMeta[]
missingEvents: string[]
missingCalls: string[]
}

export function weakEquals(s1: string | Text, s2: string | Text): boolean {
if (s1 === undefined || s2 === undefined) {
return false
Expand Down
Loading