-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathInputsInterfaceGenerator.ts
More file actions
105 lines (88 loc) · 3.56 KB
/
Copy pathInputsInterfaceGenerator.ts
File metadata and controls
105 lines (88 loc) · 3.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { ManifestInputs } from '../types'
export default {
generate(inputs: ManifestInputs): string {
if (Object.entries(inputs).length == 0) return ''
const convertedInputs = convertInputs(inputs)
const inputsMapping = generateInputsMapping(convertedInputs, inputs)
const imports = generateImports(convertedInputs)
const inputsClass = generateInputsClass(convertedInputs)
return [
'// THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE MANUALLY.',
'',
imports,
'',
'declare namespace input {',
` ${inputsMapping}`,
'}',
'',
'// The class name is intentionally lowercase and plural to resemble a namespace when used in a function.',
'export class inputs {',
` ${inputsClass}`,
'}',
]
.join('\n')
.trim()
},
}
function convertInputs(inputs: ManifestInputs): Record<string, string> {
return Object.fromEntries(
Object.entries(inputs).map(([name, input]) => {
const type = typeof input === 'string' ? input : input.type
return [name, convertType(type)]
})
)
}
function generateImports(inputs: Record<string, string>): string {
const IMPORTABLE_TYPES = new Set(['Address', 'Bytes', 'BigInt', 'TokenAmount', 'BlockchainToken'])
const imports = new Set<string>(Object.values(inputs).filter((type) => IMPORTABLE_TYPES.has(type)))
if (imports.size === 0) return ''
return `import { ${[...imports].sort().join(', ')} } from '@mimicprotocol/lib-ts'`
}
function generateInputsMapping(inputs: Record<string, string>, originalInputs: ManifestInputs): string {
const variableTypes = new Set(['string', 'Address', 'Bytes', 'BigInt', 'BlockchainToken', 'TokenAmount'])
return Object.entries(inputs)
.map(([name, type]) => {
const declaration = variableTypes.has(type) ? `var ${name}: string | null` : `const ${name}: ${type}`
const originalInput = originalInputs[name]
const hasDescription = typeof originalInput === 'object' && !!originalInput.description
return hasDescription ? `\n// ${originalInput.description}\n\t${declaration}` : declaration
})
.join('\n')
}
function generateInputsClass(inputs: Record<string, string>): string {
return Object.entries(inputs)
.map(([name, type]) => generateGetter(name, type))
.join('\n\n ')
}
function convertType(type: string): string {
const match = type.match(/^(u?)int(\d+)?$/)
if (match) {
const isUnsigned = match[1] === 'u'
const size = parseInt(match[2] || '256')
const prefix = isUnsigned ? 'u' : 'i'
if (size <= 8) return `${prefix}8`
if (size <= 16) return `${prefix}16`
if (size <= 32) return `${prefix}32`
if (size <= 64) return `${prefix}64`
return 'BigInt' // 128 and 256 go here
}
if (type.includes('address')) return 'Address'
if (type.includes('bytes')) return 'Bytes'
if (type === 'Token') return 'BlockchainToken'
if (type === 'TokenAmount') return 'TokenAmount'
return type
}
function generateGetter(name: string, type: string): string {
const str = `input.${name}`
let returnStr: string
if (type === 'string') returnStr = `${str}!`
else if (type === 'Address') returnStr = `Address.fromString(${str}!)`
else if (type === 'Bytes') returnStr = `Bytes.fromHexString(${str}!)`
else if (type === 'BigInt') returnStr = `BigInt.fromString(${str}!)`
else if (type === 'BlockchainToken') returnStr = `BlockchainToken.fromSerializable(${str}!)`
else if (type === 'TokenAmount') returnStr = `TokenAmount.fromSerializable(${str}!)`
else returnStr = str
return `static get ${name}(): ${type} {
return ${returnStr}
}`
}