diff --git a/apps/cli/src/baseCommand.ts b/apps/cli/src/baseCommand.ts index cf618c45..3ecb8acb 100644 --- a/apps/cli/src/baseCommand.ts +++ b/apps/cli/src/baseCommand.ts @@ -3,11 +3,21 @@ import chalk from "chalk"; import { execa } from "execa"; import fs from "fs"; import path from "path"; -import { Address, Hash, getAddress, isHash } from "viem"; +import { + Address, + getContract, + Hash, + isHash, + PublicClient, + WalletClient, +} from "viem"; +import createClients, { supportedChains } from "./wallet.js"; import { Config, parse } from "./config.js"; import { + applicationFactoryAbi, applicationFactoryAddress, + authorityFactoryAbi, authorityFactoryAddress, erc1155BatchPortalAddress, erc1155SinglePortalAddress, @@ -26,7 +36,7 @@ export type Flags = Interfaces.InferredFlags< (typeof BaseCommand)["baseFlags"] & T["flags"] >; export type Args = Interfaces.InferredArgs; -export type AddressBook = Record; +export type AddressBook = Record; export abstract class BaseCommand extends Command { protected flags!: Flags; @@ -50,10 +60,43 @@ export abstract class BaseCommand extends Command { return ps?.State; } + protected async connect(): Promise<{ + publicClient: PublicClient; + walletClient: WalletClient; + }> { + // create viem clients + return createClients({ + chain: supportedChains({ includeDevnet: true }).find( + (c) => c.id == this.flags["chain-id"], + ), + rpcUrl: this.flags["rpc-url"], + mnemonicPassphrase: this.flags["mnemonic-passphrase"], + mnemonicIndex: this.flags["mnemonic-index"], + }); + } + protected getContextPath(...paths: string[]): string { return path.join(".cartesi", ...paths); } + protected getProjectName(): string { + let projectName: string; + if (this.flags["no-backend"]) { + projectName = "cartesi-node"; + } else { + // get machine hash + const hash = this.getMachineHash(); + // Check if snapshot exists + if (!hash) { + throw new Error( + `Cartesi machine snapshot not found, run '${this.config.bin} build'`, + ); + } + projectName = hash.substring(2, 10); + } + return projectName; + } + protected getApplicationConfig(configPath: string): Config { return fs.existsSync(configPath) ? parse(fs.readFileSync(configPath).toString()) @@ -76,9 +119,51 @@ export abstract class BaseCommand extends Command { this.log(`${chalk.green("?")} ${title} ${chalk.cyan(value)}`); } - protected async getApplicationAddress(): Promise
{ - // fixed value, as we do deterministic deployment with a zero hash - return getAddress("0xab7528bb862fb57e8a2bcd567a2e929a0be56a5e"); + protected async getApplicationAddress(): Promise
{ + let projectName: string; + try { + projectName = this.getProjectName(); + } catch (e: unknown) { + return undefined; + } + + const anvilState = await this.getServiceState(projectName, "anvil"); + + if (anvilState === "running") { + // call calculateAPplicationAddress contract to get the applicationAddress + const { publicClient } = await this.connect(); + + const authorityFactory = getContract({ + address: authorityFactoryAddress, + abi: authorityFactoryAbi, + client: publicClient, + }); + + const authorityAddress = + await authorityFactory.read.calculateAuthorityAddress([ + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + BigInt(720), + "0x0000", + ]); + + const applicationFactory = getContract({ + address: applicationFactoryAddress, + abi: applicationFactoryAbi, + client: publicClient, + }); + + const applicationAddress = + await applicationFactory.read.calculateApplicationAddress([ + authorityAddress, + "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + this.getMachineHash()!, + "0x0", + ]); + + return applicationAddress; + } + + return undefined; } protected async getAddressBook(): Promise { diff --git a/apps/cli/src/commands/run.ts b/apps/cli/src/commands/run.ts index 4dd12bb6..da008c24 100644 --- a/apps/cli/src/commands/run.ts +++ b/apps/cli/src/commands/run.ts @@ -73,21 +73,6 @@ export default class Run extends BaseCommand { public async run(): Promise { const { flags } = await this.parse(Run); - let projectName: string; - - if (flags["no-backend"]) { - projectName = "cartesi-node"; - } else { - // get machine hash - const hash = this.getMachineHash(); - // Check if snapshot exists - if (!hash) { - throw new Error( - `Cartesi machine snapshot not found, run '${this.config.bin} build'`, - ); - } - projectName = hash.substring(2, 10); - } // path of the tool instalation const binPath = path.join( @@ -177,7 +162,7 @@ export default class Run extends BaseCommand { "--project-directory", ".", "--project-name", - projectName, + this.getProjectName(), ]; const up_args = []; diff --git a/apps/cli/src/commands/send/index.ts b/apps/cli/src/commands/send/index.ts index 5f712931..ff67f40d 100644 --- a/apps/cli/src/commands/send/index.ts +++ b/apps/cli/src/commands/send/index.ts @@ -3,10 +3,9 @@ import select from "@inquirer/select"; import { Command, Interfaces, Flags as StandardFlags } from "@oclif/core"; import ora from "ora"; import { Address, PublicClient, WalletClient, isAddress } from "viem"; - import { BaseCommand } from "../../baseCommand.js"; import * as CustomFlags from "../../flags.js"; -import createClients, { supportedChains } from "../../wallet.js"; +import { supportedChains } from "../../wallet.js"; export type Flags = Interfaces.InferredFlags< (typeof SendBaseCommand)["baseFlags"] & T["flags"] @@ -52,21 +51,6 @@ export abstract class SendBaseCommand< protected flags!: Flags; protected args!: Args; - private async connect(): Promise<{ - publicClient: PublicClient; - walletClient: WalletClient; - }> { - // create viem clients - return createClients({ - chain: supportedChains({ includeDevnet: true }).find( - (c) => c.id == this.flags["chain-id"], - ), - rpcUrl: this.flags["rpc-url"], - mnemonicPassphrase: this.flags["mnemonic-passphrase"], - mnemonicIndex: this.flags["mnemonic-index"], - }); - } - protected async getApplicationAddress(): Promise
{ if (this.flags.dapp) { // honor the flag