Skip to content

Commit

Permalink
enhancement: using JS native types in params
Browse files Browse the repository at this point in the history
  • Loading branch information
dafuga committed Dec 9, 2023
1 parent 2eb4502 commit 12f347c
Show file tree
Hide file tree
Showing 4 changed files with 1,619 additions and 12 deletions.
29 changes: 29 additions & 0 deletions src/commands/contract/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,21 @@ function findAliasType(typeString: string, abi: ABI.Def): string | undefined {
return alias?.type && `${alias?.type}${decorator || ''}`
}

export function findAbiStruct(
type: string,
abi: ABI.Def,
): ABI.Struct | undefined {
const extractDecoratorResponse = extractDecorator(type)
const typeString = extractDecoratorResponse.type
const decorator = extractDecoratorResponse.decorator

const abiStruct = abi.structs.find(
(abiType) => abiType.name === typeString
)

return abiStruct
}

export function findAbiType(
type: string,
abi: ABI.Def,
Expand Down Expand Up @@ -299,3 +314,17 @@ export function capitalize(string) {

return string.charAt(0).toUpperCase() + string.slice(1)
}

export function removeDuplicateInterfaces(interfaces: ts.InterfaceDeclaration[]): ts.InterfaceDeclaration[] {
const seen: string[] = [];

return interfaces.filter(interfaceDeclaration => {
const name = String(interfaceDeclaration.name.escapedText);

if (seen.includes(name)) {
return false;
}
seen.push(name);
return true;
});
}
56 changes: 45 additions & 11 deletions src/commands/contract/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import type {ABI} from '@wharfkit/antelope'
import ts from 'typescript'
import {findExternalType, parseType} from './helpers'
import {findAbiStruct, findExternalType, parseType, removeDuplicateInterfaces} from './helpers'
import {getActionFieldFromAbi} from './structs'
import {capitalizeName} from '../../utils'

export function generateActionNamesInterface(abi: ABI.Def): ts.InterfaceDeclaration {
// Generate property signatures for each action
const members = abi.actions.map((action) => {
const actionName = String(action.name)
const actionNameKey = actionName.includes('.') ? `'${actionName}'` : actionName

const actionNameCapitalized = capitalizeName(actionName)

return ts.factory.createPropertySignature(
undefined,
actionNameKey,
undefined,
ts.factory.createTypeReferenceNode(`ActionParams.${actionNameCapitalized}`)
ts.factory.createTypeReferenceNode(`ActionParams.${actionName}`)
)
})

Expand All @@ -29,12 +26,29 @@ export function generateActionNamesInterface(abi: ABI.Def): ts.InterfaceDeclarat
)
}

export function generateActionInterface(actionStruct, abi): ts.InterfaceDeclaration {
const members = actionStruct.fields.map((field) => {
export function generateActionInterface(struct, abi): { actionInterface: ts.InterfaceDeclaration, typeInterfaces: ts.InterfaceDeclaration[] } {
const typeInterfaces: ts.InterfaceDeclaration[] = []

const members = struct.fields.map((field) => {
const typeReferenceNode = ts.factory.createTypeReferenceNode(
findParamTypeString(field.type, 'Types.', abi)
)

// We need to check for types and variants. We also need to add core types that may be used in structs that are
// used in action params (the check will have to recursivly look for those structs). Optionally, we can add all
// core types and have eslint remove them.
if (field.type === 'blockchain_parameters_v1') {
console.log({type: field.type})
}

const typeStruct = findAbiStruct(field.type, abi)

if (typeStruct) {
const interfaces = generateActionInterface(typeStruct, abi)

typeInterfaces.push(interfaces.actionInterface, ...interfaces.typeInterfaces)
}

return ts.factory.createPropertySignature(
undefined,
field.name.toLowerCase(),
Expand All @@ -43,29 +57,49 @@ export function generateActionInterface(actionStruct, abi): ts.InterfaceDeclarat
)
})

return ts.factory.createInterfaceDeclaration(
const actionInterface = ts.factory.createInterfaceDeclaration(
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
capitalizeName(actionStruct.structName),
struct.structName || struct.name,
undefined,
undefined,
members
)

return { actionInterface, typeInterfaces: removeDuplicateInterfaces(typeInterfaces) }
}

export function generateActionsNamespace(abi: ABI.Def): ts.ModuleDeclaration {
const actionStructsWithFields = getActionFieldFromAbi(abi)

const typeInterfaces: ts.InterfaceDeclaration[] = []

const interfaces = abi.actions.map((action) => {
const actionStruct = actionStructsWithFields.find(
(actionStructWithField) => actionStructWithField.structName === action.type
)
return generateActionInterface(actionStruct, abi)

const interfaces = generateActionInterface(actionStruct, abi)

if (interfaces.actionInterface) {
typeInterfaces.push(...interfaces.typeInterfaces)
}

return interfaces.actionInterface
})

const actionParamsTypes = ts.factory.createModuleDeclaration(
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
ts.factory.createIdentifier('Types'),
ts.factory.createModuleBlock(
removeDuplicateInterfaces(typeInterfaces)
),
ts.NodeFlags.Namespace
)

return ts.factory.createModuleDeclaration(
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
ts.factory.createIdentifier('ActionParams'),
ts.factory.createModuleBlock(interfaces),
ts.factory.createModuleBlock([actionParamsTypes, ...interfaces]),
ts.NodeFlags.Namespace
)
}
Expand Down
1,544 changes: 1,544 additions & 0 deletions test/tmp/eosio.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion test/utils/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,5 @@ export async function generateCodegenContract(contractName: string) {
}

export function removeCodegenContracts() {
fs.rmSync('test/tmp', {recursive: true, force: true})
// fs.rmSync('test/tmp', {recursive: true, force: true})
}

0 comments on commit 12f347c

Please sign in to comment.