| 26 | |
| 27 | @Injectable() |
| 28 | export class CompilerService { |
| 29 | private readonly logger: Logger = new Logger(CompilerService.name) |
| 30 | |
| 31 | constructor( |
| 32 | private workflowActionService: WorkflowActionService, |
| 33 | private integrationService: IntegrationService, |
| 34 | private integrationActionService: IntegrationActionService, |
| 35 | protected integrationDefinitionFactory: IntegrationDefinitionFactory, |
| 36 | ) {} |
| 37 | |
| 38 | async compile(workflow: Workflow): Promise<{ bytecode: string; abi: object[]; sourcecode: string }> { |
| 39 | const workflowActions = await this.getOnChainWorkflowActions(workflow) |
| 40 | |
| 41 | const contractPath = path.join(__dirname, '../../../contracts/WorkflowTask.sol.template') |
| 42 | const contractContent = (await fs.promises.readFile(contractPath, 'utf8')).toString() |
| 43 | |
| 44 | const templates: TemplateEvm[] = [] |
| 45 | const usedVars: VarEvm[] = [] |
| 46 | for (const workflowAction of workflowActions) { |
| 47 | const template = await this.getTemplate(workflowAction, workflowActions, usedVars) |
| 48 | usedVars.push(...template.args, ...template.vars) |
| 49 | templates.push(template) |
| 50 | } |
| 51 | |
| 52 | const imports = Array.from(new Set(templates.flatMap((template) => template.imports))).map( |
| 53 | (importFile) => `import "${importFile}";`, |
| 54 | ) |
| 55 | const code = templates.map((template) => template.code.trim()).join('\n') |
| 56 | const mutability = templates.reduce((prev, curr) => { |
| 57 | if (curr.mutability === MutabilityEvm.Modify || prev === MutabilityEvm.Modify) { |
| 58 | return MutabilityEvm.Modify |
| 59 | } |
| 60 | return MutabilityEvm.View |
| 61 | }, MutabilityEvm.View) |
| 62 | const args = templates |
| 63 | .flatMap((template) => template.args) |
| 64 | .map((arg) => `${arg.type} ${arg.name}`) |
| 65 | .join(', ') |
| 66 | |
| 67 | const sourcecode = contractContent |
| 68 | .replace('/* {{imports}} */', imports.join('\n')) |
| 69 | .replace('/* {{code}} */', code) |
| 70 | .replace('/* {{mutability}} */', mutability) |
| 71 | .replace('/* {{args}} */', args) |
| 72 | const { abi, bytecode } = await this.compileSourceCode(workflow.id, sourcecode) |
| 73 | |
| 74 | return { |
| 75 | abi, |
| 76 | bytecode, |
| 77 | sourcecode, |
| 78 | } |
| 79 | } |
| 80 | |
| 81 | private async getOnChainWorkflowActions(workflow: Workflow): Promise<WorkflowAction[]> { |
| 82 | const actions = await this.workflowActionService.find({ workflow: workflow.id, type: OperationType.EVM }) |
| 83 | const routeAction = actions.find((action) => action.isContractRootAction) |
| 84 | return routeAction ? this.getActionTree(actions, routeAction) : [] |
| 85 | } |
nothing calls this directly
no outgoing calls
no test coverage detected