diff --git a/examples/sample-foundry-project/cannonfile.toml b/examples/sample-foundry-project/cannonfile.toml index 8c14476dc..8471a7d03 100644 --- a/examples/sample-foundry-project/cannonfile.toml +++ b/examples/sample-foundry-project/cannonfile.toml @@ -1,4 +1,4 @@ -name = "greeter-foundry" +name = "greeter" version = "<%= package.version %>" description = "Simple project to verify the functionality of cannon" keywords = ["sample", "greeter"] diff --git a/examples/sample-foundry-project/package.json b/examples/sample-foundry-project/package.json index de9168daa..d6885369c 100644 --- a/examples/sample-foundry-project/package.json +++ b/examples/sample-foundry-project/package.json @@ -1,6 +1,6 @@ { "name": "sample-foundry-project", - "version": "2.11.18", + "version": "2.11.20", "private": true, "scripts": { "test": "forge test", diff --git a/examples/sample-hardhat-project/cannonfile.consumer.toml b/examples/sample-hardhat-project/cannonfile.consumer.toml index 47ec156eb..157438824 100644 --- a/examples/sample-hardhat-project/cannonfile.consumer.toml +++ b/examples/sample-hardhat-project/cannonfile.consumer.toml @@ -15,7 +15,7 @@ options.salt = "second" options.msg = "a message from second greeter set" [invoke.do_change_greeting2] -target = ["greeters.Greeter"] +target = ["greeters.Greeterz"] func = "setGreeting" args = ["<%= settings.change_greeting2 %>"] @@ -40,11 +40,9 @@ args = ["<%= contracts.cloned.address %>", "<%= formatBytes32String('New Greetin var.NewCloneGreeting.event = "NewGreetingAdded" var.NewCloneGreeting.arg = 0 -var.NewCloneGreeting.artifact = "Greeter" var.OldCloneGreeting.event = "OldGreetingRemoved" var.OldCloneGreeting.arg = 0 -var.OldCloneGreeting.artifact = "Greeter" # test to parse through previous emitted event values [invoke.set_new_greeting_for_next_clones] diff --git a/packages/builder/src/access-recorder.test.ts b/packages/builder/src/access-recorder.test.ts index 3c9372f43..635676b03 100644 --- a/packages/builder/src/access-recorder.test.ts +++ b/packages/builder/src/access-recorder.test.ts @@ -1,51 +1,52 @@ -import { computeTemplateAccesses } from './access-recorder'; +import { TemplateContext } from './access-recorder'; describe('access-recorder.ts', () => { - describe('computeTemplateAccesses()', () => { + const templateContext = new TemplateContext({ chainId: 45, timestamp: 0, package: { version: '0.0.0' } }); + describe('TemplateContext.computeAccesses()', () => { it('computes dependency with addition operation', () => { - expect(computeTemplateAccesses('<%= settings.value1 + settings.value2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.value1 + settings.value2 %>')).toEqual({ accesses: ['settings.value1', 'settings.value2'], unableToCompute: false, }); }); it('computes dependency with addition operation using extras', () => { - expect(computeTemplateAccesses('<%= extras.value1 + extras.value2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= extras.value1 + extras.value2 %>')).toEqual({ accesses: ['extras.value1', 'extras.value2'], unableToCompute: false, }); }); it('computes dependency with usage of allowed global variables', () => { - expect(computeTemplateAccesses('<%= parseEther(String(0.3)) %>')).toEqual({ + expect(templateContext.computeAccesses('<%= parseEther(String(0.3)) %>')).toEqual({ accesses: [], unableToCompute: false, }); }); it('computes simple addition', () => { - expect(computeTemplateAccesses('<%= 1 + 1 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= 1 + 1 %>')).toEqual({ accesses: [], unableToCompute: false, }); }); it('computes dependency with subtraction operation', () => { - expect(computeTemplateAccesses('<%= settings.value1 - settings.value2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.value1 - settings.value2 %>')).toEqual({ accesses: ['settings.value1', 'settings.value2'], unableToCompute: false, }); }); it('computes dependency with multiplication operation', () => { - expect(computeTemplateAccesses('<%= settings.value1 * settings.value2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.value1 * settings.value2 %>')).toEqual({ accesses: ['settings.value1', 'settings.value2'], unableToCompute: false, }); }); it('computes dependency with division operation', () => { - expect(computeTemplateAccesses('<%= settings.value1 / settings.value2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.value1 / settings.value2 %>')).toEqual({ accesses: ['settings.value1', 'settings.value2'], unableToCompute: false, }); @@ -53,7 +54,7 @@ describe('access-recorder.ts', () => { it('computes dependency with complex math operation', () => { expect( - computeTemplateAccesses('<%= (settings.value1 + settings.value2) * settings.value3 / settings.value4 %>') + templateContext.computeAccesses('<%= (settings.value1 + settings.value2) * settings.value3 / settings.value4 %>') ).toEqual({ accesses: ['settings.value1', 'settings.value2', 'settings.value3', 'settings.value4'], unableToCompute: false, @@ -61,14 +62,14 @@ describe('access-recorder.ts', () => { }); it('computes multiple dependencies on different template tags', () => { - expect(computeTemplateAccesses('<%= settings.woot %>-<%= settings.woot2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.woot %>-<%= settings.woot2 %>')).toEqual({ accesses: ['settings.woot', 'settings.woot2'], unableToCompute: false, }); }); it('computes simple dependency', () => { - expect(computeTemplateAccesses('<%= settings.woot %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.woot %>')).toEqual({ accesses: ['settings.woot'], unableToCompute: false, }); @@ -76,7 +77,7 @@ describe('access-recorder.ts', () => { it('computes array dependency', () => { expect( - computeTemplateAccesses( + templateContext.computeAccesses( '["<%= settings.camelotSwapPublisherAdmin1 %>","<%= settings.camelotSwapPublisherAdmin2 %>"]' ) ).toEqual({ @@ -86,7 +87,7 @@ describe('access-recorder.ts', () => { }); it('computes dependency using simple CannonHelperContext', () => { - expect(computeTemplateAccesses('<%= parseEther(settings.woot) %>')).toEqual({ + expect(templateContext.computeAccesses('<%= parseEther(settings.woot) %>')).toEqual({ accesses: ['settings.woot'], unableToCompute: false, }); @@ -94,7 +95,7 @@ describe('access-recorder.ts', () => { it('computes dependency using complex CannonHelperContext', () => { expect( - computeTemplateAccesses( + templateContext.computeAccesses( '<%= defaultAbiCoder.encode(parseEther(settings.woot)) %> + <%= defaultAbiCoder.decode(contracts.compound) %>' ) ).toEqual({ @@ -102,32 +103,39 @@ describe('access-recorder.ts', () => { unableToCompute: false, }); }); + + it('computes dependency with chainId as a dynamic value search', () => { + expect(templateContext.computeAccesses('<%= settings[`my_${chainId}`] %>')).toEqual({ + accesses: ['settings.my_45'], + unableToCompute: false, + }); + }); }); describe('computeTemplateAccesses() syntax validation', () => { it('handles invalid template syntax - unmatched brackets', () => { - expect(computeTemplateAccesses('<%= settings.value) %>')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.value) %>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('handles empty template tags', () => { - expect(computeTemplateAccesses('<%=%>')).toEqual({ + expect(templateContext.computeAccesses('<%=%>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('handles multiple template tags with mixed validity', () => { - expect(computeTemplateAccesses('<%= settings.valid %> and <% invalid.syntax')).toEqual({ + expect(templateContext.computeAccesses('<%= settings.valid %> and <% invalid.syntax')).toEqual({ accesses: ['settings.valid'], unableToCompute: false, }); }); it('handles template with only whitespace', () => { - expect(computeTemplateAccesses('<%= %>')).toEqual({ + expect(templateContext.computeAccesses('<%= %>')).toEqual({ accesses: [], unableToCompute: true, }); @@ -136,42 +144,42 @@ describe('access-recorder.ts', () => { describe('computeTemplateAccesses() security', () => { it('prevents direct code execution', () => { - expect(computeTemplateAccesses('<%= process.exit(1) %>')).toEqual({ + expect(templateContext.computeAccesses('<%= process.exit(1) %>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('prevents access to global objects', () => { - expect(computeTemplateAccesses('<%= global.process %>')).toEqual({ + expect(templateContext.computeAccesses('<%= global.process %>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('prevents require/import statements', () => { - expect(computeTemplateAccesses('<%= require("fs") %>')).toEqual({ + expect(templateContext.computeAccesses('<%= require("fs") %>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('prevents eval usage', () => { - expect(computeTemplateAccesses('<%= eval("console.log(\'REKT\')") %>')).toEqual({ + expect(templateContext.computeAccesses('<%= eval("console.log(\'REKT\')") %>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('prevents Function constructor usage', () => { - expect(computeTemplateAccesses('<%= new Function("return process")() %>')).toEqual({ + expect(templateContext.computeAccesses('<%= new Function("return process")() %>')).toEqual({ accesses: [], unableToCompute: true, }); }); it('prevents setTimeout/setInterval usage', () => { - expect(computeTemplateAccesses('<%= setTimeout(() => {}, 1000) %>')).toEqual({ + expect(templateContext.computeAccesses('<%= setTimeout(() => {}, 1000) %>')).toEqual({ accesses: [], unableToCompute: true, }); @@ -179,7 +187,7 @@ describe('access-recorder.ts', () => { it('prevents overriding console.log', () => { expect( - computeTemplateAccesses('<%= console.log=function(n){require("fs").writeFileSync("./exploit.log",n)} %>') + templateContext.computeAccesses('<%= console.log=function(n){require("fs").writeFileSync("./exploit.log",n)} %>') ).toEqual({ accesses: [], unableToCompute: true, @@ -187,7 +195,7 @@ describe('access-recorder.ts', () => { }); it('prevents assignment of values', () => { - expect(computeTemplateAccesses('<%= const value = 1 + 2 %>')).toEqual({ + expect(templateContext.computeAccesses('<%= const value = 1 + 2 %>')).toEqual({ accesses: [], unableToCompute: true, }); diff --git a/packages/builder/src/access-recorder.ts b/packages/builder/src/access-recorder.ts index ffa31814f..bec7ef497 100644 --- a/packages/builder/src/access-recorder.ts +++ b/packages/builder/src/access-recorder.ts @@ -7,12 +7,12 @@ import { CannonHelperContext } from './types'; const debug = Debug('cannon:builder:access-recorder'); class ExtendableProxy { - readonly accessed = new Map(); + accessed = new Map(); constructor(defaultValue?: any) { return new Proxy(this, { get: (obj: any, prop: string) => { - if (prop === 'accessed' || prop === 'getAccesses') { + if (prop === 'accessed' || prop === 'getAccesses' || prop === 'clearAccesses') { return obj[prop]; } if (!this.accessed.has(prop)) { @@ -52,50 +52,105 @@ export class AccessRecorder extends ExtendableProxy { return acc; } + + clearAccesses(depth: number, cur = 1) { + if (cur == depth) { + return Array.from(this.accessed.keys()); + } + + for (const k in this.accessed.keys()) { + this.accessed.get(k)!.clearAccesses(depth, (cur || 1) + 1); + } + + this.accessed.clear(); + } } export type AccessComputationResult = { accesses: string[]; unableToCompute: boolean }; type AccessRecorderMap = { [k: string]: AccessRecorder }; -type TemplateContext = { +type TemplateContextData = { [k: string]: AccessRecorder | AccessRecorderMap | unknown; }; -/** - * Setup the template context. - * @param possibleNames - The possible names to setup the context for - * @returns The template context - */ -function setupTemplateContext(possibleNames: string[] = []): TemplateContext { - // Create a fake helper context, so the render works but no real functions are called - const fakeHelperContext = _createDeepNoopObject(CannonHelperContext); - - const recorders: TemplateContext = { - // Include base context variables, no access recording as they are always available - chainId: 0, - timestamp: 0, - package: { version: '0.0.0' }, - ...fakeHelperContext, - - // Add access recorders for the base context variables, these are the ones - // used to calculate dependencies beween steps - contracts: new AccessRecorder(), - imports: new AccessRecorder(), - extras: new AccessRecorder(), - txns: new AccessRecorder(), - // For settings, we give it a zeroAddress as a best case scenarion that is going - // to be working for most cases. - // e.g., when calculating a setting value for 'settings.owners.split(',')' or 'settings.someNumber' will work. - settings: new AccessRecorder(viem.zeroAddress), - }; +export class TemplateContext { + readonly possibleNames: string[]; + readonly recorders: TemplateContextData; + + constructor( + overrides: { chainId: number; timestamp: number; package: { version: string } }, + possibleNames: string[] = [] + ) { + // Create a fake helper context, so the render works but no real functions are called + const fakeHelperContext = _createDeepNoopObject(CannonHelperContext); + + this.possibleNames = possibleNames; + this.recorders = { + // Include base context variables, no access recording as they are always available + chainId: overrides.chainId, + timestamp: overrides.timestamp, + package: overrides.package, + ...fakeHelperContext, + + // Add access recorders for the base context variables, these are the ones + // used to calculate dependencies beween steps + contracts: new AccessRecorder(), + imports: new AccessRecorder(), + extras: new AccessRecorder(), + txns: new AccessRecorder(), + // For settings, we give it a zeroAddress as a best case scenarion that is going + // to be working for most cases. + // e.g., when calculating a setting value for 'settings.owners.split(',')' or 'settings.someNumber' will work. + settings: new AccessRecorder(viem.zeroAddress), + }; + + // add possible names + for (const n of possibleNames) { + this.recorders[n] = new AccessRecorder(); + } + } - // add possible names - for (const n of possibleNames) { - recorders[n] = new AccessRecorder(); + computeAccesses(str?: string) { + if (!str) { + return { accesses: [], unableToCompute: false }; + } + + try { + // we give it "true" for safeContext to avoid cloning and freezing of the object + // this is because we want to keep the access recorder, and is not a security risk + // if the user can modify that object + template(str, this.recorders, true); + const accesses = this.collectAccesses(); + return { accesses, unableToCompute: false }; + } catch (err) { + debug('Template execution failed:', err); + return { accesses: [], unableToCompute: true }; + } } - return recorders; + /** + * Collect the accesses from the recorders. + * @param recorders - The recorders to collect accesses from + * @param possibleNames - The possible names to collect accesses from + * @returns The accesses + */ + collectAccesses(): string[] { + const accesses: string[] = []; + + for (const recorder of Object.keys(this.recorders)) { + if (this.recorders[recorder] instanceof AccessRecorder) { + if (this.possibleNames.includes(recorder) && this.recorders[recorder].accessed.size > 0) { + accesses.push(recorder); + } else { + accesses.push(...Array.from(this.recorders[recorder].accessed.keys()).map((a: string) => `${recorder}.${a}`)); + } + this.recorders[recorder].clearAccesses(2); + } + } + + return accesses; + } } export function _createDeepNoopObject(obj: T): T { @@ -114,54 +169,6 @@ export function _createDeepNoopObject(obj: T): T { return obj; } -/** - * Collect the accesses from the recorders. - * @param recorders - The recorders to collect accesses from - * @param possibleNames - The possible names to collect accesses from - * @returns The accesses - */ -function collectAccesses(recorders: TemplateContext, possibleNames: string[]): string[] { - const accesses: string[] = []; - - for (const recorder of Object.keys(recorders)) { - if (recorders[recorder] instanceof AccessRecorder) { - if (possibleNames.includes(recorder) && recorders[recorder].accessed.size > 0) { - accesses.push(recorder); - } else { - accesses.push(...Array.from(recorders[recorder].accessed.keys()).map((a: string) => `${recorder}.${a}`)); - } - } - } - - return accesses; -} - -/** - * Compute the accesses from the template. - * @param str - The template to compute accesses from - * @param possibleNames - The possible names to compute accesses from - * @returns The accesses - */ -export function computeTemplateAccesses(str?: string, possibleNames: string[] = []): AccessComputationResult { - if (!str) { - return { accesses: [], unableToCompute: false }; - } - - const recorders = setupTemplateContext(possibleNames); - - try { - // we give it "true" for safeContext to avoid cloning and freezing of the object - // this is because we want to keep the access recorder, and is not a security risk - // if the user can modify that object - template(str, recorders, true); - const accesses = collectAccesses(recorders, possibleNames); - return { accesses, unableToCompute: false }; - } catch (err) { - debug('Template execution failed:', err); - return { accesses: [], unableToCompute: true }; - } -} - /** * Merge two template access computation results. * @param r1 - The first result diff --git a/packages/builder/src/actions.ts b/packages/builder/src/actions.ts index 6559488b8..138e3a458 100644 --- a/packages/builder/src/actions.ts +++ b/packages/builder/src/actions.ts @@ -1,5 +1,5 @@ import { z } from 'zod'; -import { AccessComputationResult } from './access-recorder'; +import { AccessComputationResult, TemplateContext } from './access-recorder'; import { handleZodErrors } from './error/zod'; import { ChainBuilderRuntime } from './runtime'; import { chainDefinitionSchema } from './schemas'; @@ -33,7 +33,7 @@ export interface CannonAction { /** * Returns a list of state keys that this operation consumes (used for dependency inference) */ - getInputs?: (config: Config, possibleFields: string[], packageState: PackageState) => AccessComputationResult; + getInputs?: (config: Config, templateContext: TemplateContext, packageState: PackageState) => AccessComputationResult; /** * Returns a list of state keys this operation produces (used for dependency inference) diff --git a/packages/builder/src/definition.ts b/packages/builder/src/definition.ts index deb17fc08..cae884d57 100644 --- a/packages/builder/src/definition.ts +++ b/packages/builder/src/definition.ts @@ -10,6 +10,7 @@ import { template } from './utils/template'; import { PackageReference } from './package-reference'; import { ZodIssue } from 'zod'; +import { TemplateContext } from '.'; const debug = Debug('cannon:builder:definition'); const debugVerbose = Debug('cannon:verbose:builder:definition'); @@ -61,7 +62,9 @@ export function validatePackageVersion(v: string) { export class ChainDefinition { private raw: RawChainDefinition; private sensitiveDependencies: boolean; + private accessRecordTemplateContext: TemplateContext; + readonly clashes: OutputClashCheckResult[]; readonly allActionNames: string[]; private _roots: Set = new Set(); @@ -75,7 +78,15 @@ export class ChainDefinition { readonly danglingDependencies = new Set<`${string}:${string}`>(); - constructor(def: RawChainDefinition, sensitiveDependencies = false) { + constructor( + def: RawChainDefinition, + sensitiveDependencies = false, + overrides: { chainId: number; timestamp: number; package: { version: string } } = { + chainId: 0, + timestamp: Date.now(), + package: { version: '0.0.0' }, + } + ) { debug('begin chain def init'); this.raw = def; this.sensitiveDependencies = sensitiveDependencies; @@ -108,6 +119,25 @@ export class ChainDefinition { // do some preindexing this.allActionNames = _.sortBy(actions, _.identity); + // checking for output clashes will also fill out the dependency map + this.clashes = this.checkOutputClash(); + + const possibleFields: string[] = []; + for (const k of this.dependencyFor.keys()) { + const baseName = k.split('.')[0]; + if ( + baseName !== 'contracts' && + baseName !== 'imports' && + baseName !== 'settings' && + baseName !== 'extras' && + baseName !== 'txns' + ) { + possibleFields.push(baseName); + } + } + + this.accessRecordTemplateContext = new TemplateContext(overrides); + debug('finished chain def init'); } @@ -254,20 +284,7 @@ export class ChainDefinition { } if (ActionKinds[n].getInputs) { - const possibleFields: string[] = []; - for (const k of this.dependencyFor.keys()) { - const baseName = k.split('.')[0]; - if ( - baseName !== 'contracts' && - baseName !== 'imports' && - baseName !== 'settings' && - baseName !== 'extras' && - baseName !== 'txns' - ) { - possibleFields.push(baseName); - } - } - const accessComputationResults = ActionKinds[n].getInputs!(_.get(this.raw, node), possibleFields, { + const accessComputationResults = ActionKinds[n].getInputs!(_.get(this.raw, node), this.accessRecordTemplateContext, { ref: null, currentLabel: node, }); @@ -325,13 +342,9 @@ export class ChainDefinition { initializeComputedDependencies = _.memoize(() => { const computeDepsDebug = Debug('cannon:builder:dependencies'); computeDepsDebug('start compute dependencies'); - // checking for output clashes will also fill out the dependency map - const clashes = this.checkOutputClash(); - - computeDepsDebug('finished checking clashes'); - if (clashes.length) { - throw new Error(`cannot generate dependency tree: output clashes exist: ${JSON.stringify(clashes)}`); + if (this.clashes.length) { + throw new Error(`cannot generate dependency tree: output clashes exist: ${JSON.stringify(this.clashes)}`); } // get all dependencies, and filter out the extraneous @@ -403,7 +416,7 @@ export class ChainDefinition { const cycle = missing.length ? [] : this.checkCycles(); // TODO: this check seems to be a bit too sensitive atm const extraneousDeps: { node: string; extraneous: string; inDep: string }[] = []; // this.checkExtraneousDependencies(); - const outputClashes = this.checkOutputClash(); + const outputClashes = this.clashes; for (const extDep of extraneousDeps) { const deps = this.resolvedDependencies.get(extDep.node)!; diff --git a/packages/builder/src/index.ts b/packages/builder/src/index.ts index a462ad431..798b1cbde 100644 --- a/packages/builder/src/index.ts +++ b/packages/builder/src/index.ts @@ -6,7 +6,7 @@ if (!Object.prototype.hasOwnProperty.call(BigInt.prototype, 'toJSON')) { } export { createInitialContext, build, getArtifacts, addOutputsToContext, getOutputs } from './builder'; -export { computeTemplateAccesses, mergeTemplateAccesses } from './access-recorder'; +export { TemplateContext, mergeTemplateAccesses } from './access-recorder'; export { registerAction, ActionKinds } from './actions'; export type { CannonAction, RawChainDefinition } from './actions'; export { ChainDefinition } from './definition'; diff --git a/packages/builder/src/package.ts b/packages/builder/src/package.ts index 5250c7ff6..9122041de 100644 --- a/packages/builder/src/package.ts +++ b/packages/builder/src/package.ts @@ -58,7 +58,11 @@ export async function forPackageTree { var: { woot: '<%= settings.b %>', wah: '<%= settings.c %>' }, options: { woot: '<%= settings.d %>', wah: '<%= settings.e %>', tags: '<%= settings.f %>' }, }, - [] + new TemplateContext({ chainId: 0, timestamp: 0, package: { version: '0.0.0.0' } }) ) ).toEqual({ accesses: ['settings.a', 'settings.b', 'settings.c', 'settings.d', 'settings.e', 'settings.f'], diff --git a/packages/builder/src/steps/clone.ts b/packages/builder/src/steps/clone.ts index 42ba9acce..921c28663 100644 --- a/packages/builder/src/steps/clone.ts +++ b/packages/builder/src/steps/clone.ts @@ -3,7 +3,7 @@ import Debug from 'debug'; import _ from 'lodash'; import { z } from 'zod'; import pkg from '../../package.json'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { build, createInitialContext, getOutputs } from '../builder'; import { CANNON_CHAIN_ID } from '../constants'; import { ChainDefinition } from '../definition'; @@ -77,28 +77,22 @@ const cloneSpec = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses(config.source); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.target, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.sourcePreset, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.targetPreset, possibleFields)); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(config.source); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.target)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.sourcePreset)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.targetPreset)); if (config.var) { - _.forEach(config.var, (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a, possibleFields)))); + _.forEach(config.var, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); } if (config.options) { - _.forEach( - config.options, - (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a, possibleFields))) - ); + _.forEach(config.options, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); } if (config.tags) { - _.forEach( - config.tags, - (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a, possibleFields))) - ); + _.forEach(config.tags, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); } return accesses; @@ -155,7 +149,11 @@ const cloneSpec = { deployInfo.def.version = targetRef.version; deployInfo.def.preset = targetRef.preset; - const def = new ChainDefinition(deployInfo.def); + const def = new ChainDefinition(deployInfo.def, false, { + chainId, + timestamp: Date.now(), + package: { version: '0.0.0' }, + }); // always treat upstream state as what is used if its available. otherwise, we might have a state from a previous upgrade. // if all else fails, we can load from scratch (aka this is first deployment) diff --git a/packages/builder/src/steps/deploy.test.ts b/packages/builder/src/steps/deploy.test.ts index 5b30e6fdc..30da38beb 100644 --- a/packages/builder/src/steps/deploy.test.ts +++ b/packages/builder/src/steps/deploy.test.ts @@ -5,6 +5,7 @@ import { ContractArtifact } from '../types'; import action from './deploy'; import { fakeCtx, fakeRuntime, makeFakeSigner } from './utils.test.helper'; import { PackageReference } from '../package-reference'; +import { TemplateContext } from '..'; const DEFAULT_ARACHNID_ADDRESS = '0x4e59b44847b379578588920cA78FbF26c0B4956C'; @@ -159,7 +160,7 @@ describe('steps/deploy.ts', () => { args: ['<%= contracts.h %>', '<%= contracts.i %>'], salt: '<%= contracts.j %>', }, - [] + new TemplateContext({ chainId: 0, timestamp: 0, package: { version: '0.0.0' } }) ) .accesses.sort() ).toEqual([ diff --git a/packages/builder/src/steps/deploy.ts b/packages/builder/src/steps/deploy.ts index 15eeb4c7d..f0eea7492 100644 --- a/packages/builder/src/steps/deploy.ts +++ b/packages/builder/src/steps/deploy.ts @@ -2,7 +2,7 @@ import Debug from 'debug'; import _ from 'lodash'; import * as viem from 'viem'; import { z } from 'zod'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { ARACHNID_DEFAULT_DEPLOY_ADDR, ensureArachnidCreate2Exists, makeArachnidCreate2Txn } from '../create2'; import { CannonError, handleTxnError } from '../error'; import { deploySchema } from '../schemas'; @@ -195,37 +195,31 @@ const deploySpec = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses(config.from); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.nonce, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.artifact, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.value, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.abi, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.salt, possibleFields)); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(config.from); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.nonce)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.artifact)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.value)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.abi)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.salt)); if (config.abiOf) { - _.forEach( - config.abiOf, - (v) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(v, possibleFields))) - ); + _.forEach(config.abiOf, (v) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(v)))); } if (config.args) { _.forEach( config.args, - (v) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(JSON.stringify(v), possibleFields))) + (v) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(JSON.stringify(v)))) ); } if (config.libraries) { - _.forEach( - config.libraries, - (v) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(v, possibleFields))) - ); + _.forEach(config.libraries, (v) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(v)))); } if (config?.overrides?.gasLimit) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.overrides.gasLimit, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.overrides.gasLimit)); } return accesses; diff --git a/packages/builder/src/steps/diamond.ts b/packages/builder/src/steps/diamond.ts index 8e8ad8aa2..4f258655c 100644 --- a/packages/builder/src/steps/diamond.ts +++ b/packages/builder/src/steps/diamond.ts @@ -3,7 +3,7 @@ import _ from 'lodash'; import * as viem from 'viem'; import { z } from 'zod'; import { ARACHNID_DEFAULT_DEPLOY_ADDR, ensureArachnidCreate2Exists, makeArachnidCreate2Txn } from '../create2'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { ChainBuilderRuntime } from '../runtime'; import { diamondSchema } from '../schemas'; import { ContractArtifact, ContractMap, PackageState } from '../types'; @@ -94,23 +94,23 @@ const diamondStep = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses(config.diamondArgs.owner, possibleFields); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(config.diamondArgs.owner); if (config.diamondArgs.init) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.diamondArgs.init, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.diamondArgs.init)); } if (config.diamondArgs.initCalldata) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.diamondArgs.initCalldata, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.diamondArgs.initCalldata)); } - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.salt, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.salt)); accesses.accesses.push( ...config.contracts.map((c) => (c.includes('.') ? `imports.${c.split('.')[0]}` : `contracts.${c}`)) ); if (config?.overrides) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.overrides.gasLimit, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.overrides.gasLimit)); } return accesses; diff --git a/packages/builder/src/steps/invoke.test.ts b/packages/builder/src/steps/invoke.test.ts index c3d2e0402..738a0d4b1 100644 --- a/packages/builder/src/steps/invoke.test.ts +++ b/packages/builder/src/steps/invoke.test.ts @@ -3,6 +3,7 @@ import { validateConfig } from '../actions'; import action from './invoke'; import { fakeCtx, fakeRuntime } from './utils.test.helper'; import { PackageReference } from '../package-reference'; +import { TemplateContext } from '..'; describe('steps/invoke.ts', () => { const fakeContractInfo = { @@ -158,7 +159,7 @@ describe('steps/invoke.ts', () => { args: ['<%= contracts.h %>', '<%= contracts.i %>'], overrides: { gasLimit: '<%= contracts.j %>' }, }, - [] + new TemplateContext({ chainId: 0, timestamp: 0, package: { version: '0.0.0' } }) ) .accesses.sort() ).toEqual([ diff --git a/packages/builder/src/steps/invoke.ts b/packages/builder/src/steps/invoke.ts index 81e594592..0ba178b86 100644 --- a/packages/builder/src/steps/invoke.ts +++ b/packages/builder/src/steps/invoke.ts @@ -2,7 +2,7 @@ import Debug from 'debug'; import _ from 'lodash'; import * as viem from 'viem'; import { z } from 'zod'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { invokeSchema } from '../schemas'; import { CannonSigner, @@ -433,11 +433,11 @@ const invokeSpec = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses(config.abi, possibleFields); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.func, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.from, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.value, possibleFields)); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(config.abi); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.func)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.from)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.value)); if (typeof config.target === 'string') { config.target = [config.target as string]; @@ -452,7 +452,7 @@ const invokeSpec = { accesses.accesses.push(`imports.${target.split('.')[0]}`); } else if (isTemplateString(target)) { for (const match of getTemplateMatches(target)) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(match, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(match)); } } } @@ -460,37 +460,37 @@ const invokeSpec = { if (config.args) { _.forEach( config.args, - (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(JSON.stringify(a), possibleFields))) + (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(JSON.stringify(a)))) ); } if (config.fromCall) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.fromCall.func, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.fromCall.func)); _.forEach( config.fromCall.args, - (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(JSON.stringify(a), possibleFields))) + (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(JSON.stringify(a)))) ); } if (config?.overrides) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.overrides.gasLimit, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.overrides.gasLimit)); } for (const name in config.factory) { const f = config.factory[name]; - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(f.event, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(f.artifact, possibleFields)); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(f.abi, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(f.event)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(f.artifact)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(f.abi)); - _.forEach(f.abiOf, (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a, possibleFields)))); + _.forEach(f.abiOf, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); } const varsConfig = config.var || config.extra; for (const name in varsConfig) { const f = varsConfig[name]; - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(f.event, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(f.event)); } return accesses; diff --git a/packages/builder/src/steps/pull.ts b/packages/builder/src/steps/pull.ts index 790747211..bb3adf6cb 100644 --- a/packages/builder/src/steps/pull.ts +++ b/packages/builder/src/steps/pull.ts @@ -2,7 +2,7 @@ import Debug from 'debug'; import _ from 'lodash'; import { z } from 'zod'; import { Events } from '../runtime'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { getOutputs } from '../builder'; import { ChainDefinition } from '../definition'; import { PackageReference } from '../package-reference'; @@ -59,9 +59,9 @@ const pullSpec = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses(config.source, possibleFields); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.preset, possibleFields)); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(config.source); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.preset)); return accesses; }, @@ -106,7 +106,15 @@ const pullSpec = { imports: { [importLabel]: { url: (await runtime.registry.getUrl(source, chainId))!, // todo: duplication - ...(await getOutputs(runtime, new ChainDefinition(deployInfo.def), deployInfo.state))!, + ...(await getOutputs( + runtime, + new ChainDefinition(deployInfo.def, false, { + chainId, + timestamp: deployInfo.timestamp || 0, + package: { version: '0.0.0' }, + }), + deployInfo.state + ))!, }, }, }; diff --git a/packages/builder/src/steps/router.ts b/packages/builder/src/steps/router.ts index bf5666873..6f882b0b0 100644 --- a/packages/builder/src/steps/router.ts +++ b/packages/builder/src/steps/router.ts @@ -3,7 +3,7 @@ import _ from 'lodash'; import * as viem from 'viem'; import { z } from 'zod'; import { generateRouter } from '@usecannon/router'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { routerSchema } from '../schemas'; import { ContractMap } from '../types'; import { @@ -104,15 +104,15 @@ const routerStep = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses(config.from); - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.salt, possibleFields)); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(config.from); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.salt)); accesses.accesses.push( ...config.contracts.map((c) => (c.includes('.') ? `imports.${c.split('.')[0]}` : `contracts.${c}`)) ); if (config?.overrides) { - accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(config.overrides.gasLimit, possibleFields)); + accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(config.overrides.gasLimit)); } return accesses; diff --git a/packages/builder/src/steps/var.ts b/packages/builder/src/steps/var.ts index 7c24e1297..d6283db0f 100644 --- a/packages/builder/src/steps/var.ts +++ b/packages/builder/src/steps/var.ts @@ -1,7 +1,7 @@ import Debug from 'debug'; import _ from 'lodash'; import { z } from 'zod'; -import { computeTemplateAccesses, mergeTemplateAccesses } from '../access-recorder'; +import { mergeTemplateAccesses } from '../access-recorder'; import { varSchema } from '../schemas'; import { template } from '../utils/template'; import { CannonAction } from '../actions'; @@ -42,11 +42,11 @@ const varSpec = { return config; }, - getInputs(config, possibleFields) { - let accesses = computeTemplateAccesses('', possibleFields); + getInputs(config, templateContext) { + let accesses = templateContext.computeAccesses(''); for (const c in _.omit(config, 'depends')) { - const fields = computeTemplateAccesses(config[c], possibleFields); + const fields = templateContext.computeAccesses(config[c]); accesses = mergeTemplateAccesses(accesses, fields); } diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index 9dd1069f4..4d057540b 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -182,7 +182,11 @@ export async function build({ const resolvedSettings = _.pickBy(_.assign((!wipe && oldDeployData?.options) || {}, packageDefinition.settings)); - def = def || (oldDeployData ? new ChainDefinition(oldDeployData!.def) : undefined); + def = + def || + (oldDeployData + ? new ChainDefinition(oldDeployData!.def, false, { chainId, timestamp: Date.now(), package: { version: '0.0.0' } }) + : undefined); if (!def) { throw new Error('no deployment definition to build'); diff --git a/packages/cli/src/custom-steps/run.ts b/packages/cli/src/custom-steps/run.ts index 76983d14b..7357010e7 100644 --- a/packages/cli/src/custom-steps/run.ts +++ b/packages/cli/src/custom-steps/run.ts @@ -4,11 +4,11 @@ import { ChainArtifacts, ChainBuilderContext, ChainBuilderRuntimeInfo, - computeTemplateAccesses, mergeTemplateAccesses, PackageState, registerAction, template, + TemplateContext, } from '@usecannon/builder'; import crypto from 'crypto'; import Debug from 'debug'; @@ -137,12 +137,12 @@ const runAction = { return config; }, - getInputs(config: Config) { - let accesses = computeTemplateAccesses(config.exec); + getInputs(config: Config, templateContext: TemplateContext) { + let accesses = templateContext.computeAccesses(config.exec); - _.forEach(config.modified, (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a)))); - _.forEach(config.args, (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a)))); - _.forEach(config.env, (a) => (accesses = mergeTemplateAccesses(accesses, computeTemplateAccesses(a)))); + _.forEach(config.modified, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); + _.forEach(config.args, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); + _.forEach(config.env, (a) => (accesses = mergeTemplateAccesses(accesses, templateContext.computeAccesses(a)))); return accesses; }, diff --git a/packages/cli/src/helpers.ts b/packages/cli/src/helpers.ts index 8dece2cd9..e9e771a89 100644 --- a/packages/cli/src/helpers.ts +++ b/packages/cli/src/helpers.ts @@ -230,8 +230,12 @@ export async function loadCannonfile(filepath: string) { } // second argument ensures "sensitive" dependency verification--which ensures users are always specifying dependencies when they cant be reliably determined - const def = new ChainDefinition(rawDef, true); const pkg = loadPackageJson(path.join(path.dirname(path.resolve(filepath)), 'package.json')); + const def = new ChainDefinition(rawDef, true, { + chainId: CANNON_CHAIN_ID, + timestamp: Date.now(), + package: { version: pkg.version || '0.0.0' }, + }); // TODO: there should be a helper in the builder to create the initial ctx const ctx: ChainBuilderContext = { diff --git a/packages/website/src/features/Deploy/TransactionDetailsPage.tsx b/packages/website/src/features/Deploy/TransactionDetailsPage.tsx index e082b562b..09cb76675 100644 --- a/packages/website/src/features/Deploy/TransactionDetailsPage.tsx +++ b/packages/website/src/features/Deploy/TransactionDetailsPage.tsx @@ -222,9 +222,11 @@ function TransactionDetailsPage() { const getChainDef = async () => { if (!cannonDefInfo.def) return; - chainDefinitionRef.current = await getChainDefinitionFromWorker( - cannonDefInfo.def - ); + chainDefinitionRef.current = await getChainDefinitionFromWorker({ + def: cannonDefInfo.def, + chainId, + timestamp: Date.now(), + }); }; void getChainDef(); diff --git a/packages/website/src/features/Packages/CannonfileExplorer.tsx b/packages/website/src/features/Packages/CannonfileExplorer.tsx index 019abdf94..7b2c1d0db 100644 --- a/packages/website/src/features/Packages/CannonfileExplorer.tsx +++ b/packages/website/src/features/Packages/CannonfileExplorer.tsx @@ -123,7 +123,7 @@ export const CannonfileExplorer: FC<{ pkg: ApiPackage }> = ({ pkg }) => { className={`${displayMode === 1 ? 'block h-full' : 'hidden'} `} >
- +
diff --git a/packages/website/src/features/Packages/CannonfileGraph.tsx b/packages/website/src/features/Packages/CannonfileGraph.tsx index 5a11da649..4ace9e553 100644 --- a/packages/website/src/features/Packages/CannonfileGraph.tsx +++ b/packages/website/src/features/Packages/CannonfileGraph.tsx @@ -4,7 +4,7 @@ import * as d3 from 'd3'; import { createGlobalStyle } from 'styled-components'; import { useStepModalContext } from '@/providers/stepModalProvider'; import { getChainDefinitionFromWorker } from '@/helpers/chain-definition'; -import { RawChainDefinition } from '@usecannon/builder'; +import { DeploymentInfo } from '@usecannon/builder'; // Define global styles const GlobalStyles = createGlobalStyle` @@ -47,8 +47,9 @@ interface ExtendedSimulationNodeDatum extends d3.SimulationNodeDatum { } export const CannonfileGraph: FC<{ - deploymentDefinition: RawChainDefinition; -}> = ({ deploymentDefinition }) => { + deployInfo: DeploymentInfo; +}> = ({ deployInfo }) => { + const deploymentDefinition = deployInfo.def; const nodes: ExtendedSimulationNodeDatum[] = []; const links: d3.SimulationLinkDatum[] = []; @@ -59,7 +60,7 @@ export const CannonfileGraph: FC<{ async function initializeGraph() { try { const { allActionNames, resolvedDependencies } = - await getChainDefinitionFromWorker(deploymentDefinition); + await getChainDefinitionFromWorker(deployInfo); // Clear existing nodes and links nodes.length = 0; diff --git a/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx b/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx index e31ddbbe2..5014717f7 100644 --- a/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx +++ b/packages/website/src/features/Packages/PackageAccordionHelper/index.tsx @@ -63,9 +63,11 @@ export default function PackageAccordionHelper({ const { ['run']: _, ...filteredDefinition } = deploymentData.data .def as any; - const chainDefinition = await getChainDefinitionFromWorker( - filteredDefinition - ); + const chainDefinition = await getChainDefinitionFromWorker({ + def: filteredDefinition, + chainId, + timestamp: Date.now(), + }); setChainDefinition(chainDefinition); } diff --git a/packages/website/src/helpers/chain-definition.ts b/packages/website/src/helpers/chain-definition.ts index db8c904a0..1fda3e62a 100644 --- a/packages/website/src/helpers/chain-definition.ts +++ b/packages/website/src/helpers/chain-definition.ts @@ -1,6 +1,6 @@ -import { ChainDefinition, RawChainDefinition } from '@usecannon/builder'; +import { ChainDefinition, DeploymentInfo } from '@usecannon/builder'; -export const getChainDefinitionFromWorker = (deployInfo: RawChainDefinition) => { +export const getChainDefinitionFromWorker = (deployInfo: Pick) => { return new Promise((resolve, reject) => { const worker = new Worker(new URL('@/workers/chain-definition.worker.ts', import.meta.url)); @@ -8,7 +8,11 @@ export const getChainDefinitionFromWorker = (deployInfo: RawChainDefinition) => if ('error' in event.data) { worker.terminate(); // in case of error, fallback to non-worker execution - const def = new ChainDefinition(deployInfo); + const def = new ChainDefinition(deployInfo.def, false, { + chainId: deployInfo.chainId || 0, + timestamp: deployInfo.timestamp, + package: { version: '0.0.0' }, + }); def.initializeComputedDependencies(); resolve(def); } else { diff --git a/packages/website/src/hooks/cannon.ts b/packages/website/src/hooks/cannon.ts index 176a0a076..ef0627049 100644 --- a/packages/website/src/hooks/cannon.ts +++ b/packages/website/src/hooks/cannon.ts @@ -28,7 +28,6 @@ import { publishPackage, findUpgradeFromPackage, ChainBuilderContext, - RawChainDefinition, CannonRegistry, getIpfsUrl, } from '@usecannon/builder'; @@ -597,9 +596,9 @@ export function useMergedCannonDefInfo(gitInfo: CannonfileGitInfo, partialDeploy return null; } - const deployInfo = partialDeployInfo?.ipfsQuery.data?.deployInfo?.def || originalCannonDefInfo.def; + const deployInfo = partialDeployInfo?.ipfsQuery.data?.deployInfo || originalCannonDefInfo; - return await getChainDefinitionFromWorker(deployInfo as RawChainDefinition); + return await getChainDefinitionFromWorker(deployInfo as DeploymentInfo); }, enabled: Boolean(partialDeployInfo?.ipfsQuery.data?.deployInfo || originalCannonDefInfo.def), }); @@ -644,7 +643,7 @@ export function useCannonPackageContracts(packageRef?: string, chainId?: number) { ipfs: loader } ); - const chainDefinition = await getChainDefinitionFromWorker(info.def); + const chainDefinition = await getChainDefinitionFromWorker(info); const outputs = await getOutputs(readRuntime, chainDefinition, info.state); diff --git a/packages/website/src/workers/chain-definition.worker.ts b/packages/website/src/workers/chain-definition.worker.ts index 9c7bb728f..2d418a7fd 100644 --- a/packages/website/src/workers/chain-definition.worker.ts +++ b/packages/website/src/workers/chain-definition.worker.ts @@ -6,7 +6,11 @@ self.onmessage = (event) => { throw new Error('No chain definition data provided'); } - const def = new ChainDefinition(event.data); + const def = new ChainDefinition(event.data.def, false, { + chainId: event.data.chainId, + timestamp: event.data.timestamp, + package: { version: '0.0.0.0' }, + }); if (!def) { throw new Error('Failed to create chain definition'); }