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

All system contract compatibility and better tests #52

Merged
merged 30 commits into from
Aug 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
909fc68
Rewrote tests to remove recursion and throw
aaroncox Aug 20, 2023
7ea64c6
removed try/catch
aaroncox Aug 20, 2023
3441ddd
Fixed issue with Symbol typing
aaroncox Aug 21, 2023
4d23ec2
Switching imports to wharfkit/antelope
aaroncox Aug 21, 2023
2f749a3
catching `Bool` type
aaroncox Aug 21, 2023
45059e9
Dynamically import all core types related to ABIs
aaroncox Aug 21, 2023
c9aa1a0
Adding missing types
aaroncox Aug 21, 2023
f6cfcaf
Fixing TableNames key stringify
aaroncox Aug 21, 2023
9a1a062
Updating tests to support many contracts
aaroncox Aug 21, 2023
6de4f4c
Changing imports over to wharfkit/antelope instead of session
aaroncox Aug 21, 2023
dce942a
Removed notes
aaroncox Aug 21, 2023
561a515
Only override `action` and `table` call if data for those exist
aaroncox Aug 21, 2023
1d1b64f
Scopes should accept generic numbers and cast to strings
aaroncox Aug 22, 2023
69a3295
Fixed scope logic
aaroncox Aug 22, 2023
3b2e81c
Allow passing `scope` as 2nd param to `contract.table`
aaroncox Aug 22, 2023
aa0af60
Version 0.4.1
aaroncox Aug 24, 2023
7c0c642
chore: renamed EOSIO_CORE variables
dafuga Aug 25, 2023
382a8d3
refactor: added helper folder
dafuga Aug 25, 2023
ec25a8b
enhancement: making sure that Name is always in contract imports
dafuga Aug 25, 2023
2eff3da
fix: removing $ from field name when applicable
dafuga Aug 25, 2023
127e602
chore: added full eosio abi
dafuga Aug 25, 2023
fcfadeb
cleanup: removed contracts folder
dafuga Aug 25, 2023
12b04b8
fix: parsing data types properly
dafuga Aug 25, 2023
1b42c88
fix: using proper eosio abi
dafuga Aug 25, 2023
09aa3f1
fix: handling variant and alias types
dafuga Aug 26, 2023
e4f1f3e
fix: handling booleans properly
dafuga Aug 26, 2023
eb802a7
fix: handling variants in external and internal types
dafuga Aug 26, 2023
97675bc
cleanup: removed redundant Types namespace from Struct field type
dafuga Aug 26, 2023
e1fe51f
style: linted
dafuga Aug 26, 2023
5d0ca65
Merge pull request #54 from wharfkit/codegen-touchups
aaroncox Aug 26, 2023
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
805 changes: 0 additions & 805 deletions contracts/decentiumorg.ts

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@wharfkit/contract",
"description": "ContractKit for Wharf",
"version": "0.4.0",
"version": "0.4.1",
"homepage": "https://github.com/wharfkit/contract",
"license": "BSD-3-Clause",
"main": "lib/contract.js",
Expand Down
16 changes: 13 additions & 3 deletions src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,21 @@ export async function codegen(contractName, abi) {
'@wharfkit/contract'
)

const sessionImports = ['ABI', 'Action', 'Blob', 'Struct', ...getCoreImports(abi)]
const allAntelopeImports = [
'ABI',
'Action',
'Blob',
'Struct',
'Name',
...getCoreImports(abi),
]
const antelopeImports = allAntelopeImports.filter(
(item, index) => allAntelopeImports.indexOf(item) === index
)

sessionImports.sort()
antelopeImports.sort()

const importCoreStatement = generateImportStatement(sessionImports, '@wharfkit/session')
const importCoreStatement = generateImportStatement(antelopeImports, '@wharfkit/antelope')

const {classDeclaration} = await generateContractClass(contractName, abi)

Expand Down
27 changes: 21 additions & 6 deletions src/codegen/contract.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ABI} from '@wharfkit/session'
import {ABI} from '@wharfkit/antelope'
import * as ts from 'typescript'

import {generateClassDeclaration} from './helpers'
Expand Down Expand Up @@ -43,13 +43,17 @@ export async function generateContractClass(contractName: string, abi: ABI.Def)

classMembers.push(constructorMember)

const actionMethod = generateActionMethod(abi)
if (abi.actions.length) {
const actionMethod = generateActionMethod(abi)

classMembers.push(actionMethod)
classMembers.push(actionMethod)
}

const tableMethod = generateTableMethod(abi)
if (abi.tables.length) {
const tableMethod = generateTableMethod(abi)

classMembers.push(tableMethod)
classMembers.push(tableMethod)
}

// Construct class declaration
const classDeclaration = generateClassDeclaration('Contract', classMembers, {
Expand Down Expand Up @@ -189,6 +193,16 @@ function generateTableMethod(abi: ABI.Def): ts.MethodDeclaration {
undefined
)

const scopeParameter = ts.factory.createParameterDeclaration(
undefined,
undefined,
undefined,
'scope',
ts.factory.createToken(ts.SyntaxKind.QuestionToken),
ts.factory.createTypeReferenceNode('NameType'),
undefined
)

// 4. Generate the function body.
const methodBody = ts.factory.createBlock(
[
Expand All @@ -201,6 +215,7 @@ function generateTableMethod(abi: ABI.Def): ts.MethodDeclaration {
undefined,
[
ts.factory.createIdentifier('name'),
ts.factory.createIdentifier('scope'),
ts.factory.createIdentifier('TableMap[name]'),
]
)
Expand All @@ -216,7 +231,7 @@ function generateTableMethod(abi: ABI.Def): ts.MethodDeclaration {
'table',
undefined,
[typeParameter],
[nameParameter],
[nameParameter, scopeParameter],
undefined,
methodBody
)
Expand Down
98 changes: 53 additions & 45 deletions src/codegen/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,19 @@
import * as Antelope from '@wharfkit/antelope'
import {ABI} from '@wharfkit/antelope'
import * as ts from 'typescript'

import {capitalize} from '../utils'

export const EOSIO_CORE_CLASSES = [
'Asset',
'Checksum256',
'Float64',
'Name',
'TimePoint',
'TimePointSec',
'UInt128',
'UInt16',
'UInt32',
'UInt64',
'UInt8',
]

export const EOSIO_CORE_TYPES = [
'AssetType',
'Checksum256Type',
'Float64Type',
'NameType',
'TimePointType',
'UInt128Type',
'UInt16Type',
'UInt32Type',
'UInt64Type',
'UInt8Type',
]
const ANTELOPE_CLASSES: string[] = []
Object.keys(Antelope).map((key) => {
if (Antelope[key].abiName) {
ANTELOPE_CLASSES.push(key)
}
})

export const ANTELOPE_CLASS_MAPPINGS = {
block_timestamp_type: 'BlockTimestamp',
}

export function getCoreImports(abi: ABI.Def) {
const coreImports: string[] = []
Expand Down Expand Up @@ -127,11 +112,18 @@ export function generateInterface(
}

export function findCoreClass(type: string): string | undefined {
for (const coreType of EOSIO_CORE_CLASSES) {
if (type.split('_').join('') === coreType.toLowerCase()) {
return coreType
}
if (ANTELOPE_CLASS_MAPPINGS[type]) {
return ANTELOPE_CLASS_MAPPINGS[type]
}

const parsedType = parseType(type).split('_').join('')

return (
ANTELOPE_CLASSES.find((antelopeClass) => parsedType === antelopeClass.toLowerCase()) ||
ANTELOPE_CLASSES.find(
(antelopeClass) => parsedType.replace(/[0-9]/g, '') === antelopeClass.toLowerCase()
)
)
}

export function findCoreType(type: string): string | undefined {
Expand All @@ -145,26 +137,22 @@ export function findCoreType(type: string): string | undefined {
export function findInternalType(type: string, typeNamespace: string | null, abi: ABI.Def): string {
let {type: typeString} = extractDecorator(type)

typeString = parseType(typeString)

const relevantAbitype = findAbiType(typeString, abi)

if (relevantAbitype) {
typeString = relevantAbitype
}

const variantType = findVariantType(typeString, typeNamespace, abi)

if (variantType) {
typeString = variantType
}

return formatInternalType(typeString, typeNamespace, abi)
}

function formatInternalType(typeString: string, namespace: string | null, abi: ABI.Def): string {
const structNames = abi.structs.map((struct) => struct.name.toLowerCase())

if (structNames.includes(typeString.toLowerCase())) {
return `${namespace ? `${namespace}.` : ''}${generateStructClassName(typeString)}`
return `${namespace ? `${namespace}` : ''}${generateStructClassName(typeString)}`
} else {
return findCoreClass(typeString) || capitalize(typeString)
}
Expand All @@ -177,6 +165,12 @@ export function generateStructClassName(name) {
.join('')
}

function findAliasType(typeString: string, abi: ABI.Def): string | undefined {
const alias = abi.types.find((type) => type.new_type_name === typeString)

return alias?.type
}

function findVariantType(
typeString: string,
namespace: string | null,
Expand All @@ -190,16 +184,24 @@ function findVariantType(
return
}

return abiVariant.types
.map((variant) => formatInternalType(variant, namespace, abi))
.join(' | ')
return abiVariant.types.join(' | ')
}

export function findAbiType(
typeString: string,
abi: ABI.Def,
typeNamespace = ''
): string | undefined {
export function findAbiType(type: string, abi: ABI.Def, typeNamespace = ''): string | undefined {
let typeString = type

const aliasType = findAliasType(typeString, abi)

if (aliasType) {
typeString = aliasType
}

const variantType = findVariantType(typeString, typeNamespace, abi)

if (variantType) {
typeString = variantType
}

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

if (abiType) {
Expand All @@ -211,6 +213,8 @@ export function findExternalType(type: string, abi: ABI.Def, typeNamespace?: str
let {type: typeString} = extractDecorator(type)
const {decorator} = extractDecorator(type)

typeString = parseType(typeString)

const relevantAbitype = findAbiType(typeString, abi, typeNamespace)

if (relevantAbitype) {
Expand All @@ -232,3 +236,7 @@ export function extractDecorator(type: string): {type: string; decorator?: strin

return {type}
}

function parseType(type: string): string {
return type.replace('$', '')
}
29 changes: 24 additions & 5 deletions src/codegen/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ABI} from '@wharfkit/session'
import {ABI} from '@wharfkit/antelope'
import ts from 'typescript'
import {capitalize} from '../utils'
import {findExternalType} from './helpers'
Expand Down Expand Up @@ -29,16 +29,17 @@ export function generateActionNamesInterface(abi: ABI.Def): ts.InterfaceDeclarat

export function generateActionInterface(actionStruct, abi): ts.InterfaceDeclaration {
const members = actionStruct.fields.map((field) => {
const typeReferenceNode = ts.factory.createTypeReferenceNode(
findParamTypeString(field.type, 'Types.', abi)
)

return ts.factory.createPropertySignature(
undefined,
field.name.toLowerCase(),
field.type.includes('?')
? ts.factory.createToken(ts.SyntaxKind.QuestionToken)
: undefined,
ts.factory.createTypeReferenceNode(
findExternalType(field.type, abi, 'Types.'),
undefined
)
typeReferenceNode
)
})

Expand Down Expand Up @@ -68,3 +69,21 @@ export function generateActionsNamespace(abi: ABI.Def): ts.ModuleDeclaration {
ts.NodeFlags.Namespace
)
}

function findParamTypeString(typeString: string, namespace: string | null, abi: ABI.Def): string {
const fieldType = findExternalType(typeString, abi, namespace ? namespace : undefined)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this method specific to interfaces? If not, I would put it in the helper.ts file.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think it is exclusive to the interfaces, since it's only used for ActionParams as it finds the loose types like NameType or IntType.


if (fieldType === 'Symbol') {
return 'Asset.SymbolType'
}

if (fieldType === 'Bool') {
return 'boolean'
}

if (['String', 'Boolean', 'Number'].includes(fieldType)) {
return fieldType.toLowerCase()
}

return fieldType
}
4 changes: 2 additions & 2 deletions src/codegen/maps.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import {ABI} from '@wharfkit/session'
import {ABI} from '@wharfkit/antelope'
import * as ts from 'typescript'
import {findAbiType} from './helpers'

export function generateTableMap(abi: ABI.Def): ts.VariableStatement {
// Map over tables to create the object properties
const tableProperties = abi.tables.map((table) =>
ts.factory.createPropertyAssignment(
String(table.name),
JSON.stringify(table.name),
ts.factory.createIdentifier(findAbiType(table.type, abi, 'Types.') || table.type)
Copy link
Contributor

Choose a reason for hiding this comment

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

TIL 🤷

Copy link
Member Author

Choose a reason for hiding this comment

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

Right? lol....

)
)
Expand Down
41 changes: 28 additions & 13 deletions src/codegen/structs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,9 @@ export function generateField(

function orderStructs(structs) {
const orderedStructs: StructData[] = []
const structNames = structs.map((struct) => struct.structName)

for (const struct of structs) {
for (const field of struct.fields) {
const {type: fieldType} = extractDecorator(field.type)

if (structNames.includes(fieldType.toLowerCase())) {
const dependencyStruct = structs.find(
(struct) => struct.structName === fieldType.toLowerCase()
)
orderedStructs.push(dependencyStruct)
}
}

orderedStructs.push(...findDependencies(struct, structs))
orderedStructs.push(struct)
}

Expand All @@ -179,6 +168,28 @@ function orderStructs(structs) {
})
}

function findDependencies(struct: StructData, allStructs: StructData[]): StructData[] {
const dependencies: StructData[] = []

const structNames = allStructs.map((struct) => struct.structName)

for (const field of struct.fields) {
const {type: fieldType} = extractDecorator(field.type)

if (structNames.includes(fieldType.toLowerCase())) {
const dependencyStruct = allStructs.find(
(struct) => struct.structName === fieldType.toLowerCase()
)
if (dependencyStruct) {
dependencies.push(...findDependencies(dependencyStruct, allStructs))
dependencies.push(dependencyStruct)
}
}
}

return dependencies
}

function findFieldStructType(
typeString: string,
namespace: string | null,
Expand All @@ -200,10 +211,14 @@ function findFieldStructTypeString(
): string {
const fieldType = findInternalType(typeString, namespace, abi)

if (['String', 'Boolean', 'Number'].includes(fieldType)) {
if (['String', 'Number'].includes(fieldType)) {
return fieldType.toLowerCase()
}

if (fieldType === 'Bool') {
return 'boolean'
}

if (fieldType === 'Symbol') {
return 'Asset.Symbol'
}
Expand Down
2 changes: 1 addition & 1 deletion src/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ export class Contract {
return this.tableNames.includes(String(name))
}

public table<RowType = any>(name: NameType, rowType?): Table<RowType> {
public table<RowType = any>(name: NameType, scope?: NameType, rowType?): Table<RowType> {
if (!this.hasTable(name)) {
throw new Error(`Contract (${this.account}) does not have a table named (${name})`)
}
Expand Down
Loading
Loading