@aeternity/aepp-calldata
Version:
Aeternity data serialization library
146 lines (112 loc) • 3.78 kB
JavaScript
import TypeResolver from './TypeResolver.js'
import TypeResolveError from './Errors/TypeResolveError.js'
import {FateTypeEvent} from './FateTypes.js'
const isObject = (value) => {
return value && typeof value === 'object' && value.constructor === Object
}
const isOption = ({type}) => {
let key = type
let _
if (isObject(key)) {
[[key, _]] = Object.entries(key)
}
return key === 'option'
}
class AciTypeResolver extends TypeResolver {
constructor(aci) {
super()
this.aci = aci
}
getCallTypes(contract, funName) {
const funcAci = this.getNamespaceAci(contract).functions.find(e => e.name === funName)
if (funcAci) {
const types = funcAci.arguments.map(e => this.resolveType(e.type))
const options = funcAci.arguments.filter(isOption)
return {
types,
required: types.length - options.length,
}
}
if (funName === 'init') {
return {types: [], required: 0}
}
throw new TypeResolveError(`Unknown function ${funName}`)
}
getReturnType(contract, funName) {
if (funName === 'init') {
return this.resolveType('void')
}
const funcAci = this.getNamespaceAci(contract).functions.find(e => e.name === funName)
if (!funcAci) {
throw new TypeResolveError(`Unknown function ${funName}`)
}
return this.resolveType(funcAci.returns)
}
getEventType(contract, topics) {
const aci = this.getNamespaceAci(contract)
if (!aci.hasOwnProperty('event')) {
throw new TypeResolveError('Missing event declaration')
}
return FateTypeEvent(this.resolveType(aci.event), topics)
}
isCustomType(type) {
if (typeof type !== 'string') {
return false
}
if (this.isStdType(type)) {
return false
}
const [namespace, _localType] = type.split('.')
const namespaceData = this.getNamespaceAci(namespace)
return !!namespaceData
}
isStdType(type) {
if (type === 'Set.set') {
return true
}
return false
}
getNamespaceAci(name) {
for (const e of this.aci) {
const [[_type, data]] = Object.entries(e)
if (data.name === name) {
return data
}
}
return null
}
resolveTypeDef(type, params = []) {
const [namespace, localType] = type.split('.')
const namespaceData = this.getNamespaceAci(namespace)
// not a custom type
if (!namespaceData) {
throw new TypeResolveError('Unknown namespace for ' + JSON.stringify(type))
}
if (namespaceData.name === type) {
return ['contract_pubkey', []]
}
const def = [
/**
* @deprecated use ACIs generated by aesophia@^7.1.0
* TODO remove `type_defs` in next major release
*/
...namespaceData.typedefs || namespaceData.type_defs,
...namespaceData.state ? [{
name: 'state',
typedef: namespaceData.state,
vars: []
}] : []
].find(e => e.name === localType)
if (!def) {
throw new TypeResolveError('Unknown type definition: ' + JSON.stringify(type))
}
const vars = {}
def.vars.forEach((e, i) => {
const [[_, k]] = Object.entries(e)
vars[k] = params[i]
})
const typeDef = vars.hasOwnProperty(def.typedef) ? vars[def.typedef] : def.typedef
return [typeDef, vars]
}
}
export default AciTypeResolver