@wharfkit/contract
Advanced tools
Comparing version 0.3.1 to 0.3.2
@@ -1,2 +0,2 @@ | ||
import { API, ABIDef, APIClient, ABI, NameType, Name, BytesType, ABISerializableObject, PermissionLevelType, Action } from '@wharfkit/antelope'; | ||
import { API, ABIDef, APIClient, ABI, NameType, Name, BytesType, ABISerializableObject, PermissionLevelType, Action, Blob } from '@wharfkit/antelope'; | ||
import { ABICacheInterface } from '@wharfkit/abicache'; | ||
@@ -213,2 +213,4 @@ | ||
declare function codegen(contractName: any, abi: any): Promise<string>; | ||
interface ContractKitArgs { | ||
@@ -238,2 +240,11 @@ client: APIClient; | ||
export { ABIDefinition, ActionArgs, ActionDataType, ActionOptions, Contract, ContractArgs, ContractKit, ContractKitArgs, ContractKitOptions, GetTableRowsOptions, QueryParams, Table, TableCursor, TableCursorArgs, TableRowParamsTypes, ContractKit as default }; | ||
type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>; | ||
declare function pascalCase(value: string): string; | ||
declare function capitalize(string: any): string; | ||
declare function singularize(word: string): string; | ||
declare function indexPositionInWords(index: number): string; | ||
declare function wrapIndexValue(value: any): API.v1.TableIndexType | undefined; | ||
declare function abiToBlob(abi: ABI): Blob; | ||
declare function blobStringToAbi(blobString: string): ABI; | ||
export { ABIDefinition, ActionArgs, ActionDataType, ActionOptions, Contract, ContractArgs, ContractKit, ContractKitArgs, ContractKitOptions, GetTableRowsOptions, PartialBy, QueryParams, Table, TableCursor, TableCursorArgs, TableRowParamsTypes, abiToBlob, blobStringToAbi, capitalize, codegen, ContractKit as default, indexPositionInWords, pascalCase, singularize, wrapIndexValue }; |
@@ -8,4 +8,53 @@ 'use strict'; | ||
var tslib = require('tslib'); | ||
var ts = require('typescript'); | ||
var abicache = require('@wharfkit/abicache'); | ||
function _interopNamespace(e) { | ||
if (e && e.__esModule) return e; | ||
var n = Object.create(null); | ||
if (e) { | ||
Object.keys(e).forEach(function (k) { | ||
if (k !== 'default') { | ||
var d = Object.getOwnPropertyDescriptor(e, k); | ||
Object.defineProperty(n, k, d.get ? d : { | ||
enumerable: true, | ||
get: function () { return e[k]; } | ||
}); | ||
} | ||
}); | ||
} | ||
n["default"] = e; | ||
return Object.freeze(n); | ||
} | ||
var ts__namespace = /*#__PURE__*/_interopNamespace(ts); | ||
function pascalCase(value) { | ||
return value | ||
.split(/_| /) | ||
.map((w) => { | ||
return w[0].toUpperCase() + w.slice(1).toLowerCase(); | ||
}) | ||
.join(''); | ||
} | ||
function capitalize(string) { | ||
if (typeof string !== 'string' || string.length === 0) { | ||
return ''; | ||
} | ||
return string.charAt(0).toUpperCase() + string.slice(1); | ||
} | ||
function singularize(word) { | ||
if (word.endsWith('ies')) { | ||
return word.slice(0, -3) + 'y'; | ||
} | ||
else if (word.endsWith('ches') || word.endsWith('ses')) { | ||
return word.slice(0, -2); | ||
} | ||
else if (word.endsWith('s') && word.length > 1 && word[word.length - 2] !== 's') { | ||
return word.slice(0, -1); | ||
} | ||
else { | ||
return word; | ||
} | ||
} | ||
function indexPositionInWords(index) { | ||
@@ -41,2 +90,10 @@ return [ | ||
} | ||
function abiToBlob(abi) { | ||
const serializedABI = antelope.Serializer.encode({ object: abi, type: antelope.ABI }); | ||
return new antelope.Blob(serializedABI.array); | ||
} | ||
function blobStringToAbi(blobString) { | ||
const blob = antelope.Blob.from(blobString); | ||
return antelope.ABI.from(blob); | ||
} | ||
@@ -242,4 +299,13 @@ const defaultParams = { | ||
constructor(args) { | ||
if (!args.abi) { | ||
throw new Error('Contract requires an ABI'); | ||
} | ||
this.abi = antelope.ABI.from(args.abi); | ||
if (!args.account) { | ||
throw new Error('Contract requires an account name'); | ||
} | ||
this.account = antelope.Name.from(args.account); | ||
if (!args.client) { | ||
throw new Error('Contract requires an APIClient'); | ||
} | ||
this.client = args.client; | ||
@@ -303,2 +369,238 @@ } | ||
const EOSIO_CORE_CLASSES = [ | ||
'Asset', | ||
'Checksum256', | ||
'Float64', | ||
'Name', | ||
'TimePoint', | ||
'TimePointSec', | ||
'UInt128', | ||
'UInt16', | ||
'UInt32', | ||
'UInt64', | ||
'UInt8', | ||
]; | ||
const EOSIO_CORE_TYPES = [ | ||
'AssetType', | ||
'Blob', | ||
'Checksum256Type', | ||
'Float64Type', | ||
'NameType', | ||
'TimePointType', | ||
'UInt128Type', | ||
'UInt16Type', | ||
'UInt32Type', | ||
'UInt64Type', | ||
'UInt8Type', | ||
]; | ||
function generateClassDeclaration(name, members, options = {}) { | ||
const heritageClauses = []; | ||
if (options.parent) { | ||
heritageClauses.push(ts__namespace.factory.createHeritageClause(ts__namespace.SyntaxKind.ExtendsKeyword, [ | ||
ts__namespace.factory.createExpressionWithTypeArguments(ts__namespace.factory.createIdentifier(options.parent), undefined), | ||
])); | ||
} | ||
const modifiers = []; | ||
if (options.export === true) { | ||
modifiers.push(ts__namespace.factory.createToken(ts__namespace.SyntaxKind.ExportKeyword)); | ||
} | ||
if (options.decorator) { | ||
modifiers.push(options.decorator); | ||
} | ||
const classDeclaration = ts__namespace.factory.createClassDeclaration(modifiers, ts__namespace.factory.createIdentifier(name), undefined, | ||
heritageClauses, members); | ||
return classDeclaration; | ||
} | ||
function generateImportStatement(classes, path) { | ||
return ts__namespace.factory.createImportDeclaration(undefined, | ||
ts__namespace.factory.createImportClause(false, | ||
undefined, | ||
ts__namespace.factory.createNamedImports(classes.map((className) => ts__namespace.factory.createImportSpecifier(false, undefined, | ||
ts__namespace.factory.createIdentifier(className) | ||
))) | ||
), ts__namespace.factory.createStringLiteral(path) | ||
); | ||
} | ||
function generateStruct(structName, isExport = false, members = []) { | ||
const decorators = [ | ||
ts__namespace.factory.createDecorator(ts__namespace.factory.createCallExpression(ts__namespace.factory.createIdentifier('Struct.type'), undefined, [ | ||
ts__namespace.factory.createStringLiteral(structName), | ||
])), | ||
]; | ||
return ts__namespace.factory.createClassDeclaration(isExport | ||
? [...decorators, ts__namespace.factory.createModifier(ts__namespace.SyntaxKind.ExportKeyword)] | ||
: decorators, ts__namespace.factory.createIdentifier(capitalize(structName)), undefined, | ||
[ | ||
ts__namespace.factory.createHeritageClause(ts__namespace.SyntaxKind.ExtendsKeyword, [ | ||
ts__namespace.factory.createExpressionWithTypeArguments(ts__namespace.factory.createIdentifier('Struct'), []), | ||
]), | ||
], | ||
members | ||
); | ||
} | ||
function generateField(field, isExport = false, namespace, abi) { | ||
const fieldName = field.name.toLowerCase(); | ||
const decorators = [ | ||
ts__namespace.factory.createDecorator(ts__namespace.factory.createCallExpression(ts__namespace.factory.createIdentifier('Struct.field'), undefined, [ts__namespace.factory.createStringLiteral(field.type)])), | ||
]; | ||
return ts__namespace.factory.createPropertyDeclaration(isExport | ||
? [...decorators, ts__namespace.factory.createModifier(ts__namespace.SyntaxKind.DeclareKeyword)] | ||
: decorators, ts__namespace.factory.createIdentifier(fieldName), | ||
undefined, | ||
ts__namespace.factory.createTypeReferenceNode(findInternalType(field.type, namespace, abi)), | ||
undefined | ||
); | ||
} | ||
function getFieldTypesFromAbi(abi) { | ||
const structTypes = []; | ||
if (abi && abi.structs) { | ||
for (const struct of abi.structs) { | ||
const fields = []; | ||
for (const field of struct.fields) { | ||
fields.push({ | ||
name: field.name.charAt(0).toUpperCase() + field.name.slice(1), | ||
type: field.type, | ||
}); | ||
} | ||
structTypes.push({ structName: struct.name, fields }); | ||
} | ||
} | ||
return structTypes; | ||
} | ||
function findCoreClass(type) { | ||
for (const coreType of EOSIO_CORE_CLASSES) { | ||
if (type.split('_').join('') === coreType.toLowerCase()) { | ||
return coreType; | ||
} | ||
} | ||
} | ||
function findInternalType(type, namespace, abi) { | ||
let typeString = removeDecorators(type); | ||
const relevantAbitype = findAbiType(typeString, abi); | ||
if (relevantAbitype) { | ||
typeString = relevantAbitype; | ||
} | ||
const variantType = findVariantType(typeString, namespace, abi); | ||
if (variantType) { | ||
typeString = variantType; | ||
} | ||
return formatInternalType(typeString, namespace, abi); | ||
} | ||
function formatInternalType(typeString, namespace, abi) { | ||
const structNames = abi.structs.map((struct) => struct.name.toLowerCase()); | ||
if (structNames.includes(typeString.toLowerCase())) { | ||
return `${namespace}.${capitalize(typeString)}`; | ||
} | ||
else { | ||
return findCoreClass(typeString) || capitalize(typeString); | ||
} | ||
} | ||
function findVariantType(typeString, namespace, abi) { | ||
const abiVariant = abi.variants.find((variant) => variant.name.toLowerCase() === typeString.toLowerCase()); | ||
if (!abiVariant) { | ||
return; | ||
} | ||
return abiVariant.types | ||
.map((variant) => formatInternalType(variant, namespace, abi)) | ||
.join(' | '); | ||
} | ||
function findAbiType(typeString, abi) { | ||
var _a; | ||
return (_a = abi.types.find((abiType) => abiType.new_type_name.toLowerCase() === typeString.toLowerCase())) === null || _a === void 0 ? void 0 : _a.type; | ||
} | ||
const decorators = ['?', '[]']; | ||
function removeDecorators(type) { | ||
for (const decorator of decorators) { | ||
if (type.includes(decorator)) { | ||
type = type.replace(decorator, ''); | ||
break; | ||
} | ||
} | ||
return type; | ||
} | ||
function generateNamespaceName(contractName) { | ||
return contractName | ||
.split('.') | ||
.map((namePart) => capitalize(namePart)) | ||
.join(''); | ||
} | ||
function generateNamespace(namespaceName, children, isExport = true) { | ||
return ts__namespace.factory.createModuleDeclaration(isExport ? [ts__namespace.factory.createModifier(ts__namespace.SyntaxKind.ExportKeyword)] : [], | ||
ts__namespace.factory.createIdentifier(namespaceName), ts__namespace.factory.createModuleBlock(children), ts__namespace.NodeFlags.Namespace); | ||
} | ||
function generateContractClass(namespaceName, contractName) { | ||
return tslib.__awaiter(this, void 0, void 0, function* () { | ||
const classMembers = []; | ||
const constructorParams = [ | ||
ts__namespace.factory.createParameterDeclaration(undefined, undefined, undefined, 'args', undefined, ts__namespace.factory.createTypeReferenceNode(ts__namespace.factory.createIdentifier('PartialBy'), [ | ||
ts__namespace.factory.createTypeReferenceNode(ts__namespace.factory.createIdentifier('ContractArgs'), undefined), | ||
ts__namespace.factory.createUnionTypeNode([ | ||
ts__namespace.factory.createLiteralTypeNode(ts__namespace.factory.createStringLiteral('abi')), | ||
ts__namespace.factory.createLiteralTypeNode(ts__namespace.factory.createStringLiteral('account')), | ||
]), | ||
]), undefined), | ||
]; | ||
const constructorBody = ts__namespace.factory.createBlock([ | ||
ts__namespace.factory.createExpressionStatement(ts__namespace.factory.createCallExpression(ts__namespace.factory.createSuper(), undefined, [ | ||
ts__namespace.factory.createObjectLiteralExpression([ | ||
ts__namespace.factory.createPropertyAssignment('client', ts__namespace.factory.createPropertyAccessExpression(ts__namespace.factory.createIdentifier('args'), 'client')), | ||
ts__namespace.factory.createPropertyAssignment('abi', ts__namespace.factory.createIdentifier('abi')), | ||
ts__namespace.factory.createPropertyAssignment('account', ts__namespace.factory.createCallExpression(ts__namespace.factory.createPropertyAccessExpression(ts__namespace.factory.createIdentifier('Name'), 'from'), undefined, [ts__namespace.factory.createStringLiteral(contractName)])), | ||
], true), | ||
])), | ||
], true); | ||
const constructorMember = ts__namespace.factory.createConstructorDeclaration(undefined, undefined, constructorParams, constructorBody); | ||
classMembers.push(constructorMember); | ||
const classDeclaration = generateClassDeclaration('Contract', classMembers, { | ||
parent: 'BaseContract', | ||
export: true, | ||
}); | ||
return { classDeclaration }; | ||
}); | ||
} | ||
const printer = ts__namespace.createPrinter(); | ||
function codegen(contractName, abi) { | ||
return tslib.__awaiter(this, void 0, void 0, function* () { | ||
const namespaceName = generateNamespaceName(contractName); | ||
const importCoreStatement = generateImportStatement([ | ||
'ABI', | ||
'APIClient', | ||
'Session', | ||
'Struct', | ||
'TransactResult', | ||
...EOSIO_CORE_CLASSES, | ||
...EOSIO_CORE_TYPES, | ||
], '@wharfkit/session'); | ||
const importContractStatement = generateImportStatement(['Contract as BaseContract', 'ContractArgs', 'PartialBy', 'blobStringToAbi'], '@wharfkit/contract'); | ||
const { classDeclaration } = yield generateContractClass(namespaceName, contractName); | ||
const structs = getFieldTypesFromAbi(abi); | ||
const structDeclarations = []; | ||
for (const struct of structs) { | ||
const structMembers = []; | ||
for (const field of struct.fields) { | ||
structMembers.push(generateField(field, true, `${namespaceName}.Types`, abi)); | ||
} | ||
structDeclarations.push(generateStruct(struct.structName, true, structMembers)); | ||
} | ||
const abiBlob = abiToBlob(abi); | ||
const abiBlobField = ts__namespace.factory.createVariableStatement([ts__namespace.factory.createModifier(ts__namespace.SyntaxKind.ExportKeyword)], ts__namespace.factory.createVariableDeclarationList([ | ||
ts__namespace.factory.createVariableDeclaration('abiBlob', undefined, undefined, ts__namespace.factory.createCallExpression(ts__namespace.factory.createPropertyAccessExpression(ts__namespace.factory.createIdentifier('Blob'), ts__namespace.factory.createIdentifier('from')), undefined, [ts__namespace.factory.createStringLiteral(String(abiBlob))])), | ||
], ts__namespace.NodeFlags.Const)); | ||
const abiField = ts__namespace.factory.createVariableStatement([ts__namespace.factory.createModifier(ts__namespace.SyntaxKind.ExportKeyword)], ts__namespace.factory.createVariableDeclarationList([ | ||
ts__namespace.factory.createVariableDeclaration('abi', undefined, undefined, ts__namespace.factory.createCallExpression(ts__namespace.factory.createPropertyAccessExpression(ts__namespace.factory.createIdentifier('ABI'), ts__namespace.factory.createIdentifier('from')), undefined, [ts__namespace.factory.createIdentifier('abiBlob')])), | ||
], ts__namespace.NodeFlags.Const)); | ||
const namespaceDeclaration = generateNamespace(namespaceName, [ | ||
abiBlobField, | ||
abiField, | ||
classDeclaration, | ||
generateNamespace('Types', structDeclarations), | ||
]); | ||
const sourceFile = ts__namespace.factory.createSourceFile([importContractStatement, importCoreStatement, namespaceDeclaration], ts__namespace.factory.createToken(ts__namespace.SyntaxKind.EndOfFileToken), ts__namespace.NodeFlags.None); | ||
return printer.printFile(sourceFile); | ||
}); | ||
} | ||
const defaultContractKitOptions = {}; | ||
@@ -340,3 +642,11 @@ class ContractKit { | ||
exports.TableCursor = TableCursor; | ||
exports.abiToBlob = abiToBlob; | ||
exports.blobStringToAbi = blobStringToAbi; | ||
exports.capitalize = capitalize; | ||
exports.codegen = codegen; | ||
exports["default"] = ContractKit; | ||
exports.indexPositionInWords = indexPositionInWords; | ||
exports.pascalCase = pascalCase; | ||
exports.singularize = singularize; | ||
exports.wrapIndexValue = wrapIndexValue; | ||
//# sourceMappingURL=contract.js.map |
@@ -1,5 +0,34 @@ | ||
import { isInstanceOf, UInt128, UInt64, Float64, Checksum256, Checksum160, Name, ABI, Serializer, PermissionLevel, Action } from '@wharfkit/antelope'; | ||
import { isInstanceOf, UInt128, UInt64, Float64, Checksum256, Checksum160, Name, Serializer, ABI, Blob, PermissionLevel, Action } from '@wharfkit/antelope'; | ||
import { PlaceholderAuth } from 'eosio-signing-request'; | ||
import * as ts from 'typescript'; | ||
import { ABICache } from '@wharfkit/abicache'; | ||
function pascalCase(value) { | ||
return value | ||
.split(/_| /) | ||
.map((w) => { | ||
return w[0].toUpperCase() + w.slice(1).toLowerCase(); | ||
}) | ||
.join(''); | ||
} | ||
function capitalize(string) { | ||
if (typeof string !== 'string' || string.length === 0) { | ||
return ''; | ||
} | ||
return string.charAt(0).toUpperCase() + string.slice(1); | ||
} | ||
function singularize(word) { | ||
if (word.endsWith('ies')) { | ||
return word.slice(0, -3) + 'y'; | ||
} | ||
else if (word.endsWith('ches') || word.endsWith('ses')) { | ||
return word.slice(0, -2); | ||
} | ||
else if (word.endsWith('s') && word.length > 1 && word[word.length - 2] !== 's') { | ||
return word.slice(0, -1); | ||
} | ||
else { | ||
return word; | ||
} | ||
} | ||
function indexPositionInWords(index) { | ||
@@ -35,2 +64,10 @@ return [ | ||
} | ||
function abiToBlob(abi) { | ||
const serializedABI = Serializer.encode({ object: abi, type: ABI }); | ||
return new Blob(serializedABI.array); | ||
} | ||
function blobStringToAbi(blobString) { | ||
const blob = Blob.from(blobString); | ||
return ABI.from(blob); | ||
} | ||
@@ -217,4 +254,13 @@ const defaultParams = { | ||
constructor(args) { | ||
if (!args.abi) { | ||
throw new Error('Contract requires an ABI'); | ||
} | ||
this.abi = ABI.from(args.abi); | ||
if (!args.account) { | ||
throw new Error('Contract requires an account name'); | ||
} | ||
this.account = Name.from(args.account); | ||
if (!args.client) { | ||
throw new Error('Contract requires an APIClient'); | ||
} | ||
this.client = args.client; | ||
@@ -278,2 +324,233 @@ } | ||
const EOSIO_CORE_CLASSES = [ | ||
'Asset', | ||
'Checksum256', | ||
'Float64', | ||
'Name', | ||
'TimePoint', | ||
'TimePointSec', | ||
'UInt128', | ||
'UInt16', | ||
'UInt32', | ||
'UInt64', | ||
'UInt8', | ||
]; | ||
const EOSIO_CORE_TYPES = [ | ||
'AssetType', | ||
'Blob', | ||
'Checksum256Type', | ||
'Float64Type', | ||
'NameType', | ||
'TimePointType', | ||
'UInt128Type', | ||
'UInt16Type', | ||
'UInt32Type', | ||
'UInt64Type', | ||
'UInt8Type', | ||
]; | ||
function generateClassDeclaration(name, members, options = {}) { | ||
const heritageClauses = []; | ||
if (options.parent) { | ||
heritageClauses.push(ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ | ||
ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier(options.parent), undefined), | ||
])); | ||
} | ||
const modifiers = []; | ||
if (options.export === true) { | ||
modifiers.push(ts.factory.createToken(ts.SyntaxKind.ExportKeyword)); | ||
} | ||
if (options.decorator) { | ||
modifiers.push(options.decorator); | ||
} | ||
const classDeclaration = ts.factory.createClassDeclaration(modifiers, ts.factory.createIdentifier(name), undefined, | ||
heritageClauses, members); | ||
return classDeclaration; | ||
} | ||
function generateImportStatement(classes, path) { | ||
return ts.factory.createImportDeclaration(undefined, | ||
ts.factory.createImportClause(false, | ||
undefined, | ||
ts.factory.createNamedImports(classes.map((className) => ts.factory.createImportSpecifier(false, undefined, | ||
ts.factory.createIdentifier(className) | ||
))) | ||
), ts.factory.createStringLiteral(path) | ||
); | ||
} | ||
function generateStruct(structName, isExport = false, members = []) { | ||
const decorators = [ | ||
ts.factory.createDecorator(ts.factory.createCallExpression(ts.factory.createIdentifier('Struct.type'), undefined, [ | ||
ts.factory.createStringLiteral(structName), | ||
])), | ||
]; | ||
return ts.factory.createClassDeclaration(isExport | ||
? [...decorators, ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)] | ||
: decorators, ts.factory.createIdentifier(capitalize(structName)), undefined, | ||
[ | ||
ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [ | ||
ts.factory.createExpressionWithTypeArguments(ts.factory.createIdentifier('Struct'), []), | ||
]), | ||
], | ||
members | ||
); | ||
} | ||
function generateField(field, isExport = false, namespace, abi) { | ||
const fieldName = field.name.toLowerCase(); | ||
const decorators = [ | ||
ts.factory.createDecorator(ts.factory.createCallExpression(ts.factory.createIdentifier('Struct.field'), undefined, [ts.factory.createStringLiteral(field.type)])), | ||
]; | ||
return ts.factory.createPropertyDeclaration(isExport | ||
? [...decorators, ts.factory.createModifier(ts.SyntaxKind.DeclareKeyword)] | ||
: decorators, ts.factory.createIdentifier(fieldName), | ||
undefined, | ||
ts.factory.createTypeReferenceNode(findInternalType(field.type, namespace, abi)), | ||
undefined | ||
); | ||
} | ||
function getFieldTypesFromAbi(abi) { | ||
const structTypes = []; | ||
if (abi && abi.structs) { | ||
for (const struct of abi.structs) { | ||
const fields = []; | ||
for (const field of struct.fields) { | ||
fields.push({ | ||
name: field.name.charAt(0).toUpperCase() + field.name.slice(1), | ||
type: field.type, | ||
}); | ||
} | ||
structTypes.push({ structName: struct.name, fields }); | ||
} | ||
} | ||
return structTypes; | ||
} | ||
function findCoreClass(type) { | ||
for (const coreType of EOSIO_CORE_CLASSES) { | ||
if (type.split('_').join('') === coreType.toLowerCase()) { | ||
return coreType; | ||
} | ||
} | ||
} | ||
function findInternalType(type, namespace, abi) { | ||
let typeString = removeDecorators(type); | ||
const relevantAbitype = findAbiType(typeString, abi); | ||
if (relevantAbitype) { | ||
typeString = relevantAbitype; | ||
} | ||
const variantType = findVariantType(typeString, namespace, abi); | ||
if (variantType) { | ||
typeString = variantType; | ||
} | ||
return formatInternalType(typeString, namespace, abi); | ||
} | ||
function formatInternalType(typeString, namespace, abi) { | ||
const structNames = abi.structs.map((struct) => struct.name.toLowerCase()); | ||
if (structNames.includes(typeString.toLowerCase())) { | ||
return `${namespace}.${capitalize(typeString)}`; | ||
} | ||
else { | ||
return findCoreClass(typeString) || capitalize(typeString); | ||
} | ||
} | ||
function findVariantType(typeString, namespace, abi) { | ||
const abiVariant = abi.variants.find((variant) => variant.name.toLowerCase() === typeString.toLowerCase()); | ||
if (!abiVariant) { | ||
return; | ||
} | ||
return abiVariant.types | ||
.map((variant) => formatInternalType(variant, namespace, abi)) | ||
.join(' | '); | ||
} | ||
function findAbiType(typeString, abi) { | ||
return abi.types.find((abiType) => abiType.new_type_name.toLowerCase() === typeString.toLowerCase())?.type; | ||
} | ||
const decorators = ['?', '[]']; | ||
function removeDecorators(type) { | ||
for (const decorator of decorators) { | ||
if (type.includes(decorator)) { | ||
type = type.replace(decorator, ''); | ||
break; | ||
} | ||
} | ||
return type; | ||
} | ||
function generateNamespaceName(contractName) { | ||
return contractName | ||
.split('.') | ||
.map((namePart) => capitalize(namePart)) | ||
.join(''); | ||
} | ||
function generateNamespace(namespaceName, children, isExport = true) { | ||
return ts.factory.createModuleDeclaration(isExport ? [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)] : [], | ||
ts.factory.createIdentifier(namespaceName), ts.factory.createModuleBlock(children), ts.NodeFlags.Namespace); | ||
} | ||
async function generateContractClass(namespaceName, contractName) { | ||
const classMembers = []; | ||
const constructorParams = [ | ||
ts.factory.createParameterDeclaration(undefined, undefined, undefined, 'args', undefined, ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('PartialBy'), [ | ||
ts.factory.createTypeReferenceNode(ts.factory.createIdentifier('ContractArgs'), undefined), | ||
ts.factory.createUnionTypeNode([ | ||
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('abi')), | ||
ts.factory.createLiteralTypeNode(ts.factory.createStringLiteral('account')), | ||
]), | ||
]), undefined), | ||
]; | ||
const constructorBody = ts.factory.createBlock([ | ||
ts.factory.createExpressionStatement(ts.factory.createCallExpression(ts.factory.createSuper(), undefined, [ | ||
ts.factory.createObjectLiteralExpression([ | ||
ts.factory.createPropertyAssignment('client', ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('args'), 'client')), | ||
ts.factory.createPropertyAssignment('abi', ts.factory.createIdentifier('abi')), | ||
ts.factory.createPropertyAssignment('account', ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Name'), 'from'), undefined, [ts.factory.createStringLiteral(contractName)])), | ||
], true), | ||
])), | ||
], true); | ||
const constructorMember = ts.factory.createConstructorDeclaration(undefined, undefined, constructorParams, constructorBody); | ||
classMembers.push(constructorMember); | ||
const classDeclaration = generateClassDeclaration('Contract', classMembers, { | ||
parent: 'BaseContract', | ||
export: true, | ||
}); | ||
return { classDeclaration }; | ||
} | ||
const printer = ts.createPrinter(); | ||
async function codegen(contractName, abi) { | ||
const namespaceName = generateNamespaceName(contractName); | ||
const importCoreStatement = generateImportStatement([ | ||
'ABI', | ||
'APIClient', | ||
'Session', | ||
'Struct', | ||
'TransactResult', | ||
...EOSIO_CORE_CLASSES, | ||
...EOSIO_CORE_TYPES, | ||
], '@wharfkit/session'); | ||
const importContractStatement = generateImportStatement(['Contract as BaseContract', 'ContractArgs', 'PartialBy', 'blobStringToAbi'], '@wharfkit/contract'); | ||
const { classDeclaration } = await generateContractClass(namespaceName, contractName); | ||
const structs = getFieldTypesFromAbi(abi); | ||
const structDeclarations = []; | ||
for (const struct of structs) { | ||
const structMembers = []; | ||
for (const field of struct.fields) { | ||
structMembers.push(generateField(field, true, `${namespaceName}.Types`, abi)); | ||
} | ||
structDeclarations.push(generateStruct(struct.structName, true, structMembers)); | ||
} | ||
const abiBlob = abiToBlob(abi); | ||
const abiBlobField = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ | ||
ts.factory.createVariableDeclaration('abiBlob', undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('Blob'), ts.factory.createIdentifier('from')), undefined, [ts.factory.createStringLiteral(String(abiBlob))])), | ||
], ts.NodeFlags.Const)); | ||
const abiField = ts.factory.createVariableStatement([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createVariableDeclarationList([ | ||
ts.factory.createVariableDeclaration('abi', undefined, undefined, ts.factory.createCallExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('ABI'), ts.factory.createIdentifier('from')), undefined, [ts.factory.createIdentifier('abiBlob')])), | ||
], ts.NodeFlags.Const)); | ||
const namespaceDeclaration = generateNamespace(namespaceName, [ | ||
abiBlobField, | ||
abiField, | ||
classDeclaration, | ||
generateNamespace('Types', structDeclarations), | ||
]); | ||
const sourceFile = ts.factory.createSourceFile([importContractStatement, importCoreStatement, namespaceDeclaration], ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), ts.NodeFlags.None); | ||
return printer.printFile(sourceFile); | ||
} | ||
const defaultContractKitOptions = {}; | ||
@@ -309,3 +586,3 @@ class ContractKit { | ||
export { Contract, ContractKit, Table, TableCursor, ContractKit as default }; | ||
export { Contract, ContractKit, Table, TableCursor, abiToBlob, blobStringToAbi, capitalize, codegen, ContractKit as default, indexPositionInWords, pascalCase, singularize, wrapIndexValue }; | ||
//# sourceMappingURL=contract.m.js.map |
{ | ||
"name": "@wharfkit/contract", | ||
"description": "ContractKit for Wharf", | ||
"version": "0.3.1", | ||
"version": "0.3.2", | ||
"homepage": "https://github.com/wharfkit/contract", | ||
@@ -22,3 +22,3 @@ "license": "BSD-3-Clause", | ||
"dependencies": { | ||
"@wharfkit/abicache": "^1.0.1-beta2", | ||
"@wharfkit/abicache": "^1.1.0", | ||
"@wharfkit/antelope": "^0.7.3", | ||
@@ -25,0 +25,0 @@ "eosio-signing-request": "^3.0.0-beta1", |
@@ -1,2 +0,1 @@ | ||
import {ABI} from '@wharfkit/antelope' | ||
import * as ts from 'typescript' | ||
@@ -13,4 +12,4 @@ | ||
import {generateNamespace, generateNamespaceName} from './codegen/namespace' | ||
import {generateActions} from './codegen/actions' | ||
import {generateTableClass} from './codegen/table' | ||
import {generateContractClass} from './codegen/contract' | ||
import {abiToBlob} from './utils' | ||
@@ -24,2 +23,3 @@ const printer = ts.createPrinter() | ||
[ | ||
'ABI', | ||
'APIClient', | ||
@@ -35,30 +35,8 @@ 'Session', | ||
const importContractStatement = generateImportStatement( | ||
['Contract', 'Table', 'TableCursor', 'QueryOptions', 'QueryOptions', 'Query'], | ||
['Contract as BaseContract', 'ContractArgs', 'PartialBy', 'blobStringToAbi'], | ||
'@wharfkit/contract' | ||
) | ||
const {methods: actionMethods, interfaces: actionsInterfaces} = generateActions( | ||
contractName, | ||
namespaceName, | ||
ABI.from(abi) | ||
) | ||
const {classDeclaration} = await generateContractClass(namespaceName, contractName) | ||
// Generate actions namespace | ||
const actionsNamespace = generateNamespace(namespaceName, [ | ||
generateNamespace('actions', actionMethods), | ||
]) | ||
const tableClasses: ts.ClassDeclaration[] = [] | ||
const tableInterfaces: ts.InterfaceDeclaration[] = [] | ||
for (const table of abi.tables) { | ||
const {classDeclaration} = await generateTableClass(contractName, namespaceName, table, abi) | ||
tableClasses.push(classDeclaration) | ||
} | ||
// Generate tables namespace | ||
const tableNamespace = generateNamespace(namespaceName, [ | ||
generateNamespace('tables', tableClasses), | ||
]) | ||
// Extract fields from the ABI | ||
@@ -74,3 +52,3 @@ const structs = getFieldTypesFromAbi(abi) | ||
for (const field of struct.fields) { | ||
structMembers.push(generateField(field, true, `${namespaceName}.types`, abi)) | ||
structMembers.push(generateField(field, true, `${namespaceName}.Types`, abi)) | ||
} | ||
@@ -81,19 +59,61 @@ | ||
// Encode the ABI as a binary hex string | ||
const abiBlob = abiToBlob(abi) | ||
// Generate `abiBlob` field | ||
const abiBlobField = ts.factory.createVariableStatement( | ||
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], | ||
ts.factory.createVariableDeclarationList( | ||
[ | ||
ts.factory.createVariableDeclaration( | ||
'abiBlob', | ||
undefined, | ||
undefined, | ||
ts.factory.createCallExpression( | ||
ts.factory.createPropertyAccessExpression( | ||
ts.factory.createIdentifier('Blob'), | ||
ts.factory.createIdentifier('from') | ||
), | ||
undefined, | ||
[ts.factory.createStringLiteral(String(abiBlob))] | ||
) | ||
), | ||
], | ||
ts.NodeFlags.Const | ||
) | ||
) | ||
// Generate `abiBlob` field | ||
const abiField = ts.factory.createVariableStatement( | ||
[ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], | ||
ts.factory.createVariableDeclarationList( | ||
[ | ||
ts.factory.createVariableDeclaration( | ||
'abi', | ||
undefined, | ||
undefined, | ||
ts.factory.createCallExpression( | ||
ts.factory.createPropertyAccessExpression( | ||
ts.factory.createIdentifier('ABI'), | ||
ts.factory.createIdentifier('from') | ||
), | ||
undefined, | ||
[ts.factory.createIdentifier('abiBlob')] | ||
) | ||
), | ||
], | ||
ts.NodeFlags.Const | ||
) | ||
) | ||
// Generate types namespace | ||
const typesDeclaration = generateNamespace(namespaceName, [ | ||
generateNamespace('types', [ | ||
...actionsInterfaces, | ||
...tableInterfaces, | ||
...structDeclarations, | ||
]), | ||
const namespaceDeclaration = generateNamespace(namespaceName, [ | ||
abiBlobField, | ||
abiField, | ||
classDeclaration, | ||
generateNamespace('Types', structDeclarations), | ||
]) | ||
const sourceFile = ts.factory.createSourceFile( | ||
[ | ||
importContractStatement, | ||
importCoreStatement, | ||
actionsNamespace, | ||
tableNamespace, | ||
typesDeclaration, | ||
], | ||
[importContractStatement, importCoreStatement, namespaceDeclaration], | ||
ts.factory.createToken(ts.SyntaxKind.EndOfFileToken), | ||
@@ -100,0 +120,0 @@ ts.NodeFlags.None |
@@ -22,2 +22,3 @@ import {ABI} from '@wharfkit/antelope' | ||
'AssetType', | ||
'Blob', | ||
'Checksum256Type', | ||
@@ -24,0 +25,0 @@ 'Float64Type', |
@@ -7,6 +7,6 @@ import * as ts from 'typescript' | ||
export function generateNamespaceName(contractName: string) { | ||
return `_${contractName | ||
return contractName | ||
.split('.') | ||
.map((namePart) => capitalize(namePart)) | ||
.join('')}` | ||
.join('') | ||
} | ||
@@ -13,0 +13,0 @@ |
@@ -52,4 +52,13 @@ import { | ||
constructor(args: ContractArgs) { | ||
if (!args.abi) { | ||
throw new Error('Contract requires an ABI') | ||
} | ||
this.abi = ABI.from(args.abi) | ||
if (!args.account) { | ||
throw new Error('Contract requires an account name') | ||
} | ||
this.account = Name.from(args.account) | ||
if (!args.client) { | ||
throw new Error('Contract requires an APIClient') | ||
} | ||
this.client = args.client | ||
@@ -56,0 +65,0 @@ } |
export * from './contract' | ||
export * from './contract/table' | ||
export * from './contract/table-cursor' | ||
export * from './codegen' | ||
export * from './kit' | ||
export * from './utils' |
import { | ||
ABI, | ||
API, | ||
Blob, | ||
Checksum160, | ||
@@ -8,2 +10,3 @@ Checksum256, | ||
Name, | ||
Serializer, | ||
UInt128, | ||
@@ -13,2 +16,4 @@ UInt64, | ||
export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>> | ||
export function pascalCase(value: string): string { | ||
@@ -34,3 +39,3 @@ return value | ||
return word.slice(0, -3) + 'y' | ||
} else if (word.endsWith('ches') || word.endsWith('sses')) { | ||
} else if (word.endsWith('ches') || word.endsWith('ses')) { | ||
return word.slice(0, -2) | ||
@@ -80,1 +85,11 @@ } else if (word.endsWith('s') && word.length > 1 && word[word.length - 2] !== 's') { | ||
} | ||
export function abiToBlob(abi: ABI): Blob { | ||
const serializedABI = Serializer.encode({object: abi, type: ABI}) | ||
return new Blob(serializedABI.array) | ||
} | ||
export function blobStringToAbi(blobString: string): ABI { | ||
const blob = Blob.from(blobString) | ||
return ABI.from(blob) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
149982
2650
21
Updated@wharfkit/abicache@^1.1.0