import { loadDeploymentClasses } from './deployments'; import { InfinityMintScript } from './interfaces'; /** * * @returns */ export const createDeploymentsTypes = async () => { let classes = await loadDeploymentClasses({ name: 'example', network: { name: 'ganache', }, version: { version: '1.0.,0', }, } as any); let typeScript = `//this file is auto-generated by the InfinityMint CLI //do not modify this file directly import { InfinityMintDeploymentScript, InfinityMintDeploymentParameters, InfinityMintDeploymentLocal, InfinityMintDeploymentLive, ValuesReturnType } from '@app/interfaces'; import { Dictionary } from '@app/helpers'; import { InfinityMintDeployment } from '@app/deployments'; import { Contract } from '@ethersproject/contracts'; `; //do imports for classes classes.forEach((cls) => { let fileName = cls.getContractName().replace(/ /g, '').split('.')[0]; fileName = fileName.charAt(0).toUpperCase() + fileName.slice(1); if (cls.isLibrary() || cls.isLink()) return; typeScript += `import { ${fileName} as ${fileName}Contract } from '@typechain-types/index';\n`; }); classes.forEach((cls) => { let fileName = cls.getContractName().replace(/ /g, '').split('.')[0]; fileName = fileName.charAt(0).toUpperCase() + fileName.slice(1); typeScript += ` export abstract class ${fileName}DeploymentClass extends InfinityMintDeployment { public getDeploymentScript(): T { return this.deploymentScript as T; } ${ !cls.isLink() && !cls.isLibrary() ? ` /** * Returns a read only contract which you can use to read values on chain * @returns */ public get read(): ${fileName}Contract { return super.getContract() as ${fileName}Contract; } /** * Returns a signed contract which you can use to change values on chain. The signer is the current default signer. Call getSignedContract for more control on who is the signer! * @returns */ public async write(): Promise<${fileName}Contract> { return super.getSignedContract<${fileName}Contract>(); } ` : '' } ${ cls.values ? `public get values(): ${fileName}OnChainValues { return this.deploymentScript.values; }` : '' }\n }\n `; if (!cls.isLibrary() && !cls.isLink()) { //add it to the InfinityMintDeployments typeScript += `declare module '@app/interfaces' {\n`; typeScript += ` export interface InfinityMintDeployments {\n`; typeScript += ` ${fileName}?: ${fileName}DeploymentClass;\n`; typeScript += ` }\n`; typeScript += `}\n\n`; } if (!cls.isLibrary() && !cls.isLink()) { //add it to the InfinityMintDeployments typeScript += `declare module '@app/interfaces' {\n`; typeScript += ` export interface InfinityMintLiveDeployments {\n`; typeScript += ` ${fileName}?: ${fileName}DeploymentLive_Facade;\n`; typeScript += ` }\n`; typeScript += `}\n\n`; } //add script parameters typeScript += `export interface ${fileName}DeploymentLive_Facade extends InfinityMintDeploymentLive {\n`; if (cls.getDeploymentScript().values) typeScript += ` values?: ${fileName}OnChainValues;\n`; typeScript += `}\n\n`; //add script parameters typeScript += `export interface ${fileName}ScriptParameters extends InfinityMintDeploymentParameters {\n`; typeScript += ` deployment?: ${fileName}DeploymentClass;\n`; typeScript += ` deployScript?: ${fileName}DeployScript;\n`; typeScript += `}\n\n`; //add deploy arg type typeScript += `export type ${fileName}DeployArgType = (params: ${fileName}ScriptParameters) => Promise | string[];\n\n`; typeScript += `export interface ${fileName}DeployScript extends InfinityMintDeploymentScript {\n`; typeScript += ` setup?: (script: ${fileName}ScriptParameters) => Promise;\n`; typeScript += ` cleanup?: (script: ${fileName}ScriptParameters) => Promise;\n`; typeScript += ` update?: (script: ${fileName}ScriptParameters) => Promise;\n`; typeScript += ` post?: (script: ${fileName}ScriptParameters) => Promise;\n`; typeScript += ` deploy?: (script: ${fileName}ScriptParameters) => Promise<{ contract: Contract | Contract[]; localDeployment: InfinityMintDeploymentLocal; }>;\n`; typeScript += ` switch?: (script: ${fileName}ScriptParameters) => Promise;\n`; typeScript += ` deployArgs?: string[] | ${fileName}DeployArgType\n;`; if (cls.getDeploymentScript().values) typeScript += ` values?: ${fileName}OnChainValues\n;`; typeScript += `}\n\n`; typeScript += `export const ${fileName}: ${fileName}DeployScript = ${JSON.stringify( cls.getDeploymentScript(), null, 4 )};\n\n`; //do settings if ( cls.getDeploymentScript().settings || cls.getDeploymentScript().values || cls.getDeploymentScript().config ) { //convert settings to types let getTypes = (obj: any, useValuesReturnType = false) => { let types = ''; let func = (obj: any) => { Object.keys(obj).forEach((key) => { if (typeof obj[key] === 'object') { types += `${key}?: {\n`; func(obj[key]); types += `};\n`; } else if (typeof obj[key] === 'function') { if (useValuesReturnType) { types += `${key}?: ValuesReturnType;\n`; } else { types += `${key}?: any;\n`; } } else { types += `${key}?: ${typeof obj[key]};\n`; } }); }; func(obj); return types; }; if (cls.getDeploymentScript().settings) Object.keys(cls.getDeploymentScript().settings).forEach( (key) => { if ( typeof cls.getDeploymentScript().settings[key] === 'object' ) { //do erc721 typeScript += `declare module '@app/interfaces' {\n`; typeScript += ` export interface InfinityMintProjectSettings${ key === 'erc721' ? key.toUpperCase() : key.charAt(0).toUpperCase() + key.substring(1) } {\n`; typeScript += ` ${getTypes( cls.getDeploymentScript().settings?.[key] )}`; typeScript += ` }\n`; typeScript += `}\n\n`; } else { typeScript += `declare module '@app/interfaces' {\n`; typeScript += ` export interface InfinityMintProjectSettings {\n`; typeScript += ` ${key}?: ${typeof cls.getDeploymentScript() .settings[key]};\n`; typeScript += ` }\n`; typeScript += `}\n\n`; } } ); if (cls.getDeploymentScript().config) { typeScript += `declare module '@app/interfaces' {\n`; typeScript += ` export interface InfinityMintConfigSettingsDeploy {\n`; typeScript += ` ${getTypes( cls.getDeploymentScript().config )}`; typeScript += ` }\n`; typeScript += `}\n\n`; } if (cls.getDeploymentScript().values) { typeScript += `declare module '@app/interfaces' {\n`; typeScript += ` export interface InfinityMintProjectSettingsValues{\n`; typeScript += ` ${getTypes( cls.getDeploymentScript().values, true )}`; typeScript += ` }\n`; typeScript += `}\n\n`; typeScript += ` export interface ${fileName}OnChainValues extends Dictionary {\n`; typeScript += ` [key: string]: number | boolean | ValuesReturnType;\n`; typeScript += ` ${getTypes( cls.getDeploymentScript().values, true )}`; typeScript += ` }\n`; } } }); return typeScript; }; export const createScriptTypes = (scripts: InfinityMintScript[]) => { //create a type defintion for the scripts let typeScript = `//this file is auto-generated by the InfinityMint CLI //do not modify this file directly import { InfinityMintScript, InfinityMintScriptArguments } from '@app/interfaces'; `; scripts.forEach((script) => { let fileName = script.fileName.replace(/ /g, '').split('.')[0]; fileName = fileName.charAt(0).toUpperCase() + fileName.slice(1); //arguments let args = ''; script.arguments?.forEach((arg) => { args += `${arg.name}: ${arg.type};\n`; }); //add interface typeScript += `export interface ${fileName}Arguments extends InfinityMintScriptArguments {\n`; typeScript += `}\n\n`; //add type typeScript += `export interface ${fileName}Script extends InfinityMintScript {\n`; typeScript += ` arguments?: ${fileName}Arguments[];\n`; typeScript += `}\n\n`; typeScript += `export const ${fileName}: ${fileName}Script = ${JSON.stringify( script, null, 4 )};\n\n`; }); return typeScript; };