diff --git a/src/boilerplate/common/api.mjs b/src/boilerplate/common/api.mjs index d7d60d506..4ed05160a 100644 --- a/src/boilerplate/common/api.mjs +++ b/src/boilerplate/common/api.mjs @@ -1,29 +1,33 @@ + import express from 'express'; -import router from "./api_routes.mjs"; // import the routes -import Web3 from './common/web3.mjs' +import { ServiceManager } from './api_services.mjs'; +import { Router } from './api_routes.mjs'; +import Web3 from './common/web3.mjs'; ENCRYPTEDLISTENER_IMPORT -const app = express(); - -app.use(express.json()); - -app.use('/', router); //to use the routes - function gracefulshutdown() { - console.log("Shutting down"); - listener.close(() => { - console.log("HTTP server closed."); - process.exit(0); - }); + console.log('Shutting down'); + listener.close(() => { + console.log('HTTP server closed.'); + process.exit(0); + }); } -process.on("SIGTERM", gracefulshutdown); -process.on("SIGINT", gracefulshutdown); +process.on('SIGTERM', gracefulshutdown); +process.on('SIGINT', gracefulshutdown); + +const app = express(); +app.use(express.json()); -const web3 = Web3.connection() -ENCRYPTEDLISTENER_CALL +const web3 = Web3.connection(); +const serviceMgr = new ServiceManager(web3); +serviceMgr.init().then(async () => { + ENCRYPTEDLISTENER_CALL - -const listener = app.listen(process.env.PORT || 3000, () => { - console.log('Your app is listening on port ' + listener.address().port) -}) + const router = new Router(serviceMgr); + const r = router.addRoutes(); + app.use('/', r); + const listener = app.listen(process.env.PORT || 3000, () => { + console.log('Your app is listening on port ' + listener.address().port); + }); +}); \ No newline at end of file diff --git a/src/boilerplate/common/encryptedEvnetListener.mjs b/src/boilerplate/common/encryptedEvnetListener.mjs deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/boilerplate/common/routes/generic-api_routes.mjs b/src/boilerplate/common/routes/generic-api_routes.mjs index 8f606ba85..a8c240dc8 100644 --- a/src/boilerplate/common/routes/generic-api_routes.mjs +++ b/src/boilerplate/common/routes/generic-api_routes.mjs @@ -1,6 +1,17 @@ import express from 'express'; -import {service_FUNCTION_NAME} from "./api_services.mjs"; -const router = express.Router(); + +export class Router { + constructor(serviceMgr){ + this.serviceMgr =serviceMgr; + } + + addRoutes() { + + const router = express.Router(); //router.get('/database', serviceController.getAllCommitment); -router.post('/FUNCTION_NAME', service_FUNCTION_NAME); +router.post('/FUNCTION_NAME', this.serviceMgr.service_FUNCTION_NAME.bind(this.serviceMgr),); + + } +} + diff --git a/src/boilerplate/common/services/generic-api_services.mjs b/src/boilerplate/common/services/generic-api_services.mjs index 5134618ec..2997da5d1 100644 --- a/src/boilerplate/common/services/generic-api_services.mjs +++ b/src/boilerplate/common/services/generic-api_services.mjs @@ -7,6 +7,7 @@ import fs from "fs"; import logger from "./common/logger.mjs"; import { decrypt } from "./common/number-theory.mjs"; import { getAllCommitments, getCommitmentsByState } from "./common/commitment-storage.mjs"; +import ServiceManager from './common/serviceManager.mjs' import web3 from "./common/web3.mjs"; /** @@ -23,18 +24,22 @@ let leafIndex; let encryption = {}; // eslint-disable-next-line func-names -export async function service_FUNCTION_NAME (req, res, next){ - try { - await web3.connect(); - await new Promise((resolve) => setTimeout(() => resolve(), 3000)); - } catch (err) { - throw new Error(err); +export class ServiceManager{ + constructor(web3){ + this.web3 =web3; + this.FUNCTION_NAME = new FUNCTION_NAME(web3); + } + + async init(){ + await this.FUNCTION_NAME.init(); } + + async service_FUNCTION_NAME (req, res, next){ try { await startEventFilter('CONTRACT_NAME'); const FUNCTION_SIG; CONSTRUCTOR_INPUTS; - const { tx , encEvent, encBackupEvent, _RESPONSE_} = await FUNCTION_NAME(FUNCTION_SIG); + const { tx , encEvent, encBackupEvent, _RESPONSE_} = await this.FUNCTION_NAME.FUNCTION_NAME(FUNCTION_SIG); // prints the tx console.log(tx); res.send({tx, encEvent, encBackupEvent, _RESPONSE_}); diff --git a/src/boilerplate/common/services/genericpublic-api_services.mjs b/src/boilerplate/common/services/genericpublic-api_services.mjs index 358c849af..0e69c1b87 100644 --- a/src/boilerplate/common/services/genericpublic-api_services.mjs +++ b/src/boilerplate/common/services/genericpublic-api_services.mjs @@ -9,16 +9,9 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); let leafIndex; let encryption = {}; // eslint-disable-next-line func-names -export async function service_FUNCTION_NAME (req, res, next){ - try { - await web3.connect(); - await new Promise((resolve) => setTimeout(() => resolve(), 3000)); - } catch (err) { - throw new Error(err); - } - + async service_FUNCTION_NAME (req, res, next){ const FUNCTION_SIG; - const { tx , _RESPONSE_} = await FUNCTION_NAME(FUNCTION_SIG); + const { tx , _RESPONSE_} = await this.FUNCTION_NAME.FUNCTION_NAME(FUNCTION_SIG); // prints the tx console.log(tx); res.send({tx, _RESPONSE_}); diff --git a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts index ff13194f8..cbfb7b3ce 100644 --- a/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts +++ b/src/boilerplate/orchestration/javascript/raw/boilerplate-generator.ts @@ -424,12 +424,10 @@ class BoilerplateGenerator { `\nimport { storeCommitment, getCurrentWholeCommitment, getCommitmentsById, getAllCommitments, getInputCommitments, joinCommitments, splitCommitments, markNullified,getnullifierMembershipWitness,getupdatedNullifierPaths,temporaryUpdateNullifier,updateNullifierTree} from './common/commitment-storage.mjs';`, `\nimport { generateProof } from './common/zokrates.mjs';`, `\nimport { getMembershipWitness, getRoot } from './common/timber.mjs';`, - `\nimport Web3 from './common/web3.mjs';`, `\nimport { decompressStarlightKey, compressStarlightKey, encrypt, decrypt, poseidonHash, scalarMult } from './common/number-theory.mjs'; \n`, `\nconst { generalise } = GN;`, `\nconst db = '/app/orchestration/common/db/preimage.json';`, - `const web3 = Web3.connection();`, `\nconst keyDb = '/app/orchestration/common/db/key.json';\n\n`, ]; }, @@ -466,6 +464,7 @@ class BoilerplateGenerator { decompressStarlightKey(${stateName}_newOwnerPublicKey)[1].integer]` : ``} `]; case 'decrement': + prev = (index: number) => structProperties ? structProperties.map(p => `\t${stateName}_${index}_prev.${p}.integer`) : `\t${stateName}_${index}_prev.integer`; return [` ${parameters.join('\n')}${stateVarIds.join('\n')} @@ -773,7 +772,7 @@ postStatements(): string { }; integrationApiServicesBoilerplate = { import(): string { - return `import FUNCTION_NAME from './FUNCTION_NAME.mjs';\n + return `import { FUNCTION_NAME } from './FUNCTION_NAME.mjs';\n ` }, preStatements(): string{ @@ -781,26 +780,22 @@ integrationApiServicesBoilerplate = { /** NOTE: this is the api service file, if you need to call any function use the correct url and if Your input contract has two functions, add() and minus(). minus() cannot be called before an initial add(). */ - - const sleep = ms => new Promise(r => setTimeout(r, ms)); + + const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); let leafIndex; let encryption = {}; // eslint-disable-next-line func-names - export async function CONTRACT_NAME(){ - - try { - await web3.connect(); - } catch (err) { - throw new Error(err); - } - }` + export class ServiceManager{ + constructor(web3){ + this.web3 =web3; + ` }, postStatements(): string[] { return [`// eslint-disable-next-line func-names \n ${ - (fs.readFileSync(apiServiceReadPath, 'utf8').match(/export?[\s\S]*/g)|| [])[0]}`, + (fs.readFileSync(apiServiceReadPath, 'utf8').match(/async service_FUNCTION_NAME?[\s\S]*/g)|| [])[0]}`, `// eslint-disable-next-line func-names \n ${ - (fs.readFileSync(apiPublicServiceReadPath, 'utf8').match(/export?[\s\S]*/g)|| [])[0]}`]; + (fs.readFileSync(apiPublicServiceReadPath, 'utf8').match(/async service_FUNCTION_NAME?[\s\S]*/g)|| [])[0]}`]; }, commitments(): string { return ` @@ -890,17 +885,18 @@ integrationApiServicesBoilerplate = { }; integrationApiRoutesBoilerplate = { - import(): string { - return `import {service_FUNCTION_NAME} from "./api_services.mjs";\n - ` - }, preStatements(): string{ return ` import express from 'express';\n - \nconst router = express.Router();` + \nexport class Router { + constructor(serviceMgr) { + this.serviceMgr = serviceMgr; + } + addRoutes() { + const router = express.Router(); + ` }, postStatements(): string { - return `// eslint-disable-next-line func-names \n ${ - (fs.readFileSync(apiRoutesReadPath, 'utf8').match(/router.post?[\s\S]*/g)|| [])[0]}` + return `router.post('/FUNCTION_NAME', this.serviceMgr.service_FUNCTION_NAME.bind(this.serviceMgr),);` }, commitmentImports(): string { return `import { service_allCommitments, service_getCommitmentsByState, service_reinstateNullifiers, service_getSharedKeys, service_getBalance, service_getBalanceByState, service_backupData, } from "./api_services.mjs";\n`; diff --git a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts index 00e974a42..328a3e020 100644 --- a/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts +++ b/src/boilerplate/orchestration/javascript/raw/toOrchestration.ts @@ -451,6 +451,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { const params:any[] = []; const states: string[] = []; const rtnparams: string[] = []; + const functionSig: string[] = []; let returnInputs: string[] = []; let stateName: string; let stateNode: any; @@ -460,12 +461,24 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { return { statements: Orchestrationbp.generateProof.import() } case 'FunctionDefinition': - // the main function - if (node.name !== 'cnstrctr') lines.push( - `\n\n// Initialisation of variables: - \nconst instance = await getContractInstance('${node.contractName}'); - \nconst contractAddr = await getContractAddress('${node.contractName}'); `, + // the main function class + if (node.name !== 'cnstrctr') {functionSig.push( + `export class ${(node.name).charAt(0).toUpperCase() + node.name.slice(1)}Manager { + constructor(web3) { + this.web3 = web3; + } + + async init() { + this.instance = await getContractInstance('${node.contractName}'); + this.contractAddr = await getContractAddress('${node.contractName}'); + } + ` ); + lines.push(` + const instance = this.instance; + const contractAddr = this.contractAddr; + const web3 = this.web3;`) + } if (node.msgSenderParam) lines.push(` \nconst msgSender = generalise(config.web3.options.defaultAccount);`); @@ -505,7 +518,7 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { if (node.name === 'cnstrctr') return { signature: [ - `\nexport default async function ${node.name}(${params} ${states}) {`, + `\n export default async function ${node.name}(${params} ${states}) {`, `\nprocess.exit(0); \n}`, ], @@ -514,8 +527,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { if(rtnparams.length == 0) { return { signature: [ - `\nexport default async function ${node.name}(${params} ${states}) {`, + `${functionSig} + \n async ${node.name}(${params} ${states}) {`, `\n return { tx, encEvent, encBackupEvent }; + \n} \n}`, ], statements: lines, @@ -525,8 +540,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { if(rtnparams.includes('bool: bool')) { return { signature: [ - `\nexport default async function ${node.name}(${params} ${states}) {`, + ` + \n async ${node.name}(${params} ${states}) {`, `\n const bool = true; \n return { tx, encEvent, encBackupEvent, ${rtnparams} }; + \n} \n}`, ], statements: lines, @@ -535,8 +552,10 @@ export const OrchestrationCodeBoilerPlate: any = (node: any) => { return { signature: [ - `\nexport default async function ${node.name}(${params} ${states}) {`, + ` ${functionSig} + \n async ${node.name}(${params} ${states}) {`, `\nreturn { tx, encEvent, encBackupEvent, ${rtnparams} }; + \n} \n}`, ], statements: lines, diff --git a/src/codeGenerators/orchestration/files/toOrchestration.ts b/src/codeGenerators/orchestration/files/toOrchestration.ts index 502954435..918c96337 100644 --- a/src/codeGenerators/orchestration/files/toOrchestration.ts +++ b/src/codeGenerators/orchestration/files/toOrchestration.ts @@ -131,24 +131,22 @@ const prepareIntegrationTest = (node: any) => { const prepareIntegrationApiServices = (node: any) => { // import generic test skeleton const genericApiServiceFile: any = Orchestrationbp.integrationApiServicesBoilerplate; - let outputApiServiceFile = ` import { startEventFilter, getSiblingPath } from './common/timber.mjs';\nimport fs from "fs";\nimport logger from './common/logger.mjs';\nimport { decrypt } from "./common/number-theory.mjs";\nimport { getAllCommitments, getCommitmentsByState, reinstateNullifiers } from "./common/commitment-storage.mjs";\nimport web3 from './common/web3.mjs';\n\n - /** - NOTE: this is the api service file, if you need to call any function use the correct url and if Your input contract has two functions, add() and minus(). - minus() cannot be called before an initial add(). */ - const sleep = ms => new Promise(r => setTimeout(r, ms)); - let leafIndex; - let encryption = {}; - // eslint-disable-next-line func-names - export async function ${node.contractName}(){ - try { - await web3.connect(); - } catch (err) { - throw new Error(err); - } - }` - - + // replace references to contract and functions with ours + let outputApiServiceFile = genericApiServiceFile.preStatements(); + + ` + this.FUNCTION_NAME = new FUNCTION_NAMEManager(web3); + ` const relevantFunctions = node.functions.filter((fn: any) => fn.name !== 'cnstrctr'); + relevantFunctions.forEach((fn: any) => { + outputApiServiceFile = `${outputApiServiceFile} \n this.${fn.name} = new ${(fn.name).charAt(0).toUpperCase() + fn.name.slice(1)}Manager(web3)` + }) + outputApiServiceFile = `${outputApiServiceFile}} \n async init() { \n`; + relevantFunctions.forEach((fn: any) => { + outputApiServiceFile = `${outputApiServiceFile} \n await this.${fn.name}.init();` + }) + outputApiServiceFile = `${outputApiServiceFile}} \n`; + relevantFunctions.forEach((fn: any) => { let fnboilerplate = fn.nodeType === 'IntegrationApiServiceFunction'? @@ -202,17 +200,15 @@ const prepareIntegrationApiServices = (node: any) => { fnboilerplate = fnboilerplate.replace(/_RESPONSE_/g, returnParams); // replace function imports at top of file - const fnimport = genericApiServiceFile.import().replace( - /FUNCTION_NAME/g, - fn.name, - ); + const fnimport = ` import { ${(fn.name).charAt(0).toUpperCase() + fn.name.slice(1)}Manager } from './${fn.name}.mjs' ;` + // for each function, add the new imports and boilerplate to existing test outputApiServiceFile = `${fnimport}\n${outputApiServiceFile}\n${fnboilerplate}`; }); // add linting and config const preprefix = `/* eslint-disable prettier/prettier, camelcase, prefer-const, no-unused-vars */ \nimport config from 'config';\nimport assert from 'assert';\n`; - outputApiServiceFile = `${preprefix}\n${outputApiServiceFile}\n ${genericApiServiceFile.commitments()}\n`; + outputApiServiceFile = `${preprefix}\n${outputApiServiceFile}}\n ${genericApiServiceFile.commitments()}\n`; return outputApiServiceFile; }; const prepareIntegrationApiRoutes = (node: any) => { @@ -230,21 +226,14 @@ const prepareIntegrationApiRoutes = (node: any) => { let fnboilerplate = genericApiRoutesFile.postStatements() .replace(/FUNCTION_NAME/g, fn.name); - // replace function imports at top of file - fnimport = genericApiRoutesFile.import().replace( - /FUNCTION_NAME/g, - fn.name, - ); - - // for each function, add the new imports and boilerplate to existing test - outputApiRoutesimport = `${outputApiRoutesimport}\n${fnimport}\n`; + outputApiRoutesboilerplate = `${outputApiRoutesboilerplate}\n${fnboilerplate}\n` }); // add getters for commitments outputApiRoutesimport = `${outputApiRoutesimport}\n${genericApiRoutesFile.commitmentImports()}\n`; outputApiRoutesboilerplate = `${outputApiRoutesboilerplate}\n${genericApiRoutesFile.commitmentRoutes()}\n` const fnprestatement = genericApiRoutesFile.preStatements(); - const postfix = `export default router;`; + const postfix = `return router; \n} \n }`; outputApiRoutesFile = `${outputApiRoutesimport}\n${fnprestatement}\n${outputApiRoutesboilerplate}\n ${postfix}`; // add linting and config return outputApiRoutesFile; diff --git a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts index 595b6edf2..864bea824 100644 --- a/src/codeGenerators/orchestration/nodejs/toOrchestration.ts +++ b/src/codeGenerators/orchestration/nodejs/toOrchestration.ts @@ -62,6 +62,7 @@ export default function codeGenerator(node: any, options: any = {}): any { const fn = OrchestrationCodeBoilerPlate(node); const statements = codeGenerator(node.body); fn.statements.push(statements); + return `${fn.signature[0]}\n\t${fn.statements.join('')}\n${ fn.signature[1] }`; diff --git a/src/transformers/visitors/toOrchestrationVisitor.ts b/src/transformers/visitors/toOrchestrationVisitor.ts index 9c518b73c..21a6afda1 100644 --- a/src/transformers/visitors/toOrchestrationVisitor.ts +++ b/src/transformers/visitors/toOrchestrationVisitor.ts @@ -503,8 +503,7 @@ const visitor = { node._newASTPointer.msgSenderParam ??= state.msgSenderParam; node._newASTPointer.msgValueParam ??= state.msgValueParam; - if(node.containsPublic && !scope.modifiesSecretState){ - + if(node.containsPublic && !scope.modifiesSecretState()){ interface PublicParam { name: string; properties?: { name: string; type: string }[];