Repository: cartesi/cli
Pull request #213: Node 2.0.0-alpha.2 (cli)
Author: login: tuler
Labels: name: cli
Created: 2025-03-25T04:05:30Z | Merged: 2025-03-28T18:14:04Z

Updates the CLI to use devnet alpha.5.
rollups-contract 2.0.0-rc.17
New dataAvailability API for application deployment.
Use cannon chain 13370 instead of 31337.
Move anvil service to http://127.0.0.1:8080/anvil



Diff:
diff --git a/.changeset/bumpy-pens-cover.md b/.changeset/bumpy-pens-cover.md
new file mode 100644
index 00000000..a92f408a
--- /dev/null
+++ b/.changeset/bumpy-pens-cover.md
@@ -0,0 +1,5 @@
+---
+"@cartesi/cli": major
+---
+
+move anvil service to /anvil
diff --git a/.changeset/free-dogs-try.md b/.changeset/free-dogs-try.md
new file mode 100644
index 00000000..b05ea1c3
--- /dev/null
+++ b/.changeset/free-dogs-try.md
@@ -0,0 +1,5 @@
+---
+"@cartesi/cli": major
+---
+
+use devnet 2.0.0-alpha.5
diff --git a/apps/cli/package.json b/apps/cli/package.json
index 3b540633..436c8f09 100644
--- a/apps/cli/package.json
+++ b/apps/cli/package.json
@@ -42,9 +42,9 @@
         "viem": "^2.23.6"
     },
     "devDependencies": {
-        "@cartesi/devnet": "2.0.0-alpha.3",
+        "@cartesi/devnet": "2.0.0-alpha.5",
         "@cartesi/eslint-config": "workspace:*",
-        "@sunodo/wagmi-plugin-hardhat-deploy": "^0.3.0",
+        "@cartesi/rollups": "2.0.0-rc.17",
         "@types/bytes": "^3.1.5",
         "@types/fs-extra": "^11.0.4",
         "@types/inquirer": "^9.0.7",
diff --git a/apps/cli/src/commands/rollups/deploy.ts b/apps/cli/src/commands/rollups/deploy.ts
index faccdc05..9b730624 100644
--- a/apps/cli/src/commands/rollups/deploy.ts
+++ b/apps/cli/src/commands/rollups/deploy.ts
@@ -3,8 +3,15 @@ import input from "@inquirer/input";
 import chalk from "chalk";
 import { execa } from "execa";
 import ora, { Ora } from "ora";
-import { Address, Hash, PublicClient, WalletClient, zeroHash } from "viem";
-import { anvil } from "viem/chains";
+import {
+    Address,
+    encodeFunctionData,
+    Hash,
+    PublicClient,
+    WalletClient,
+    zeroHash,
+} from "viem";
+import { cannon } from "viem/chains";
 import {
     getContextPath,
     getMachineHash,
@@ -16,6 +23,8 @@ import {
     applicationFactoryAddress,
     authorityFactoryAbi,
     authorityFactoryAddress,
+    dataAvailabilityAbi,
+    inputBoxAddress,
 } from "../../contracts.js";
 import { addressInput } from "../../prompts.js";
 import { RollupsCommandOpts } from "../rollups.js";
@@ -100,6 +109,13 @@ const deployApplication = async (
             default: walletClient.account?.address,
         }));
 
+    // create data availability descriptor for InputBox only
+    const dataAvailability = encodeFunctionData({
+        abi: dataAvailabilityAbi,
+        functionName: "InputBox",
+        args: [inputBoxAddress],
+    });
+
     const applicationAddress = await publicClient.readContract({
         abi: applicationFactoryAbi,
         address: applicationFactoryAddress,
@@ -108,7 +124,7 @@ const deployApplication = async (
             authorityAddress,
             applicationOwner,
             templateHash,
-            // "0x", // XXX: update to latest rollups contract
+            dataAvailability,
             salt,
         ],
     });
@@ -125,7 +141,13 @@ const deployApplication = async (
             address: applicationFactoryAddress,
             account: walletClient.account,
             functionName: "newApplication",
-            args: [authorityAddress, applicationOwner, templateHash, salt],
+            args: [
+                authorityAddress,
+                applicationOwner,
+                templateHash,
+                dataAvailability,
+                salt,
+            ],
         });
         progress.start("Deploying application...");
         const hash = await walletClient.writeContract(request);
@@ -210,8 +232,8 @@ const registerApplication = async (options: {
     ]);
     const registration = stdout ? JSON.parse(stdout) : undefined;
     if (registration) {
-        if (registration.State !== "ENABLED") {
-            throw new Error(registration.Reason);
+        if (registration.state !== "ENABLED") {
+            throw new Error(registration.reason);
         }
         progress.succeed(`Registration ${chalk.cyan(name)}`);
     } else {
@@ -224,7 +246,7 @@ export const createDeployCommand = () => {
     return new Command<[], {}, RollupsCommandOpts>("deploy")
         .description("Deploy a rollups application to a rollups node.")
         .configureHelp({ showGlobalOptions: true })
-        .option("--chain-id <id>", "Chain ID", parseInt, 31337)
+        .option("--chain-id <id>", "Chain ID", parseInt, 13370)
         .option("--rpc-url <url>", "RPC URL")
         .option("--mnemonic <phrase>", "Mnemonic passphrase")
         .option(
@@ -296,7 +318,7 @@ export const createDeployCommand = () => {
                     { authorityAddress, progress, templateHash, ...options },
                 );
 
-                if (publicClient.chain?.id === anvil.id) {
+                if (publicClient.chain?.id === cannon.id) {
                     // copy machine snapshot to rollups node container
                     const containerSnapshotPath = await publishMachine({
                         progress,
diff --git a/apps/cli/src/commands/rollups/start.ts b/apps/cli/src/commands/rollups/start.ts
index 4b1b82f3..103b10b4 100644
--- a/apps/cli/src/commands/rollups/start.ts
+++ b/apps/cli/src/commands/rollups/start.ts
@@ -27,7 +27,8 @@ const baseServices: Service[] = [
         name: "anvil",
         file: "docker-compose-anvil.yaml",
         healthySemaphore: "anvil",
-        healthyTitle: `${chalk.cyan("anvil")} service ready at ${chalk.cyan(`${host}:8545`)}`,
+        healthyTitle: (port) =>
+            `${chalk.cyan("anvil")} service ready at ${chalk.cyan(`${host}:${port}/anvil`)}`,
         waitTitle: `${chalk.cyan("anvil")} service starting...`,
         errorTitle: `${chalk.red("anvil")} service failed`,
     },
diff --git a/apps/cli/src/commands/send.ts b/apps/cli/src/commands/send.ts
index 4d4af677..f7694bc0 100755
--- a/apps/cli/src/commands/send.ts
+++ b/apps/cli/src/commands/send.ts
@@ -58,7 +58,7 @@ export const createSendCommand = () => {
         .description(
             "Sends different kinds of input to the application in interactive mode.",
         )
-        .option("--chain-id <id>", "Chain ID", parseInt, 31337)
+        .option("--chain-id <id>", "Chain ID", parseInt, 13370)
         .option("--rpc-url <url>", "RPC URL")
         .option("--mnemonic <phrase>", "Mnemonic passphrase")
         .option(
diff --git a/apps/cli/src/compose/rollups/default.env b/apps/cli/src/compose/rollups/default.env
index aad776f8..3cb03096 100644
--- a/apps/cli/src/compose/rollups/default.env
+++ b/apps/cli/src/compose/rollups/default.env
@@ -17,16 +17,15 @@ CARTESI_CLAIMER_POLLING_INTERVAL="${CARTESI_CLAIMER_POLLING_INTERVAL:-3}"
 CARTESI_MAX_STARTUP_TIME="${CARTESI_MAX_STARTUP_TIME:-15}"
 
 # blockchain
-CARTESI_BLOCKCHAIN_ID="${CARTESI_BLOCKCHAIN_ID:-31337}"
+CARTESI_BLOCKCHAIN_ID="${CARTESI_BLOCKCHAIN_ID:-13370}"
 CARTESI_BLOCKCHAIN_HTTP_ENDPOINT="${CARTESI_BLOCKCHAIN_HTTP_ENDPOINT:-http://anvil:8545}"
 CARTESI_BLOCKCHAIN_WS_ENDPOINT="${CARTESI_BLOCKCHAIN_WS_ENDPOINT:-ws://anvil:8545}"
-CARTESI_BLOCKCHAIN_DEFAULT_BLOCK="${CARTESI_BLOCKCHAIN_DEFAULT_BLOCK:-finalized}"
+CARTESI_BLOCKCHAIN_DEFAULT_BLOCK="${CARTESI_BLOCKCHAIN_DEFAULT_BLOCK:-latest}"
 
 # contracts
-CARTESI_CONTRACTS_INPUT_BOX_ADDRESS="${CARTESI_CONTRACTS_INPUT_BOX_ADDRESS:-0x593E5BCf894D6829Dd26D0810DA7F064406aebB6}"
-CARTESI_CONTRACTS_INPUT_BOX_DEPLOYMENT_BLOCK_NUMBER="${CARTESI_CONTRACTS_INPUT_BOX_DEPLOYMENT_BLOCK_NUMBER:-1}"
-CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS="${CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS:-0xd7d4d184b82b1a4e08f304DDaB0A2A7a301C2620}"
-CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS="${CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS:-0xB897F7Fe78f220aE34B7FA9493092701a873Ed45}"
+CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS="${CARTESI_CONTRACTS_APPLICATION_FACTORY_ADDRESS:-0x2210ad1d9B0bD2D470c2bfA4814ab6253BC421A0}"
+CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS="${CARTESI_CONTRACTS_AUTHORITY_FACTORY_ADDRESS:-0x451f57Ca716046D114Ab9ff23269a2F9F4a1bdaF}"
+CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS="${CARTESI_CONTRACTS_SELF_HOSTED_APPLICATION_FACTORY_ADDRESS:-0x4a409e1CaB9229711C4e1f68625DdbC75809e721}"
 
 # auth
 CARTESI_AUTH_MNEMONIC="${CARTESI_AUTH_MNEMONIC:-test test test test test test test test test test test junk}"
diff --git a/apps/cli/src/compose/rollups/docker-compose-anvil.yaml b/apps/cli/src/compose/rollups/docker-compose-anvil.yaml
index 12bcc164..85583fbd 100644
--- a/apps/cli/src/compose/rollups/docker-compose-anvil.yaml
+++ b/apps/cli/src/compose/rollups/docker-compose-anvil.yaml
@@ -11,5 +11,7 @@ services:
             retries: 5
         environment:
             ANVIL_IP_ADDR: 0.0.0.0
-        ports:
-            - 8545:8545
+
+    proxy:
+        volumes:
+            - ./proxy/anvil.yaml:/etc/traefik/conf.d/anvil.yaml
diff --git a/apps/cli/src/compose/rollups/docker-compose-explorer.yaml b/apps/cli/src/compose/rollups/docker-compose-explorer.yaml
index 83f35626..19009c87 100644
--- a/apps/cli/src/compose/rollups/docker-compose-explorer.yaml
+++ b/apps/cli/src/compose/rollups/docker-compose-explorer.yaml
@@ -30,9 +30,9 @@ services:
     squid_processor:
         image: cartesi/rollups-explorer-api:0.5.0
         environment:
-            CHAIN_ID: ${CHAIN_ID:-31337}
+            CHAIN_ID: ${CHAIN_ID:-13370}
             RPC_URL_31337: ${RPC_URL:-http://anvil:8545}
-            BLOCK_CONFIRMATIONS_31337: 0
+            BLOCK_CONFIRMATIONS_13370: 0
             DB_NAME: ${PGDATABASE:-squid}
             DB_PORT: ${PGPORT:-5432}
             DB_HOST: ${PGHOST:-database}
diff --git a/apps/cli/src/compose/rollups/proxy/anvil.yaml b/apps/cli/src/compose/rollups/proxy/anvil.yaml
new file mode 100644
index 00000000..2b9718e6
--- /dev/null
+++ b/apps/cli/src/compose/rollups/proxy/anvil.yaml
@@ -0,0 +1,17 @@
+http:
+    routers:
+        anvil:
+            rule: "PathPrefix(`/anvil`)"
+            middlewares:
+                - "remove-anvil-prefix"
+            service: anvil
+    middlewares:
+        remove-anvil-prefix:
+            replacePathRegex:
+                regex: "^/anvil(.*)"
+                replacement: "$1"
+    services:
+        anvil:
+            loadBalancer:
+                servers:
+                    - url: "http://anvil:8545"
diff --git a/apps/cli/src/config.ts b/apps/cli/src/config.ts
index bd720c1d..b2f9a25c 100644
--- a/apps/cli/src/config.ts
+++ b/apps/cli/src/config.ts
@@ -74,7 +74,7 @@ export class InvalidStringArrayError extends Error {
 const DEFAULT_FORMAT = "ext2";
 const DEFAULT_RAM = "128Mi";
 const DEFAULT_RAM_IMAGE = "/usr/share/cartesi-machine/images/linux.bin";
-export const DEFAULT_SDK_VERSION = "0.12.0-alpha.12";
+export const DEFAULT_SDK_VERSION = "0.12.0-alpha.13";
 export const DEFAULT_SDK_IMAGE = `cartesi/sdk:${DEFAULT_SDK_VERSION}`;
 
 type Builder = "directory" | "docker" | "empty" | "none" | "tar";
diff --git a/apps/cli/src/exec/rollups.ts b/apps/cli/src/exec/rollups.ts
index 8a47bba7..509a0108 100644
--- a/apps/cli/src/exec/rollups.ts
+++ b/apps/cli/src/exec/rollups.ts
@@ -31,12 +31,12 @@ export const getDeployments = async (
             "list",
         ]);
         return JSON.parse(stdout).map((deployment: any) => ({
-            id: deployment.ID,
-            name: deployment.Name,
-            address: deployment.IApplicationAddress,
-            templateHash: deployment.TemplateHash,
-            epochLength: deployment.EpochLength,
-            state: deployment.State,
+            id: deployment.id,
+            name: deployment.name,
+            address: deployment.iapplication_address,
+            templateHash: deployment.template_hash,
+            epochLength: deployment.epoch_lenght,
+            state: deployment.state,
         }));
     } catch (e: unknown) {
         return [];
diff --git a/apps/cli/src/wallet.ts b/apps/cli/src/wallet.ts
index d947d835..5d0fafeb 100644
--- a/apps/cli/src/wallet.ts
+++ b/apps/cli/src/wallet.ts
@@ -16,11 +16,11 @@ import {
 } from "viem";
 import { mnemonicToAccount, privateKeyToAccount } from "viem/accounts";
 import {
-    anvil,
     arbitrum,
     arbitrumSepolia,
     base,
     baseSepolia,
+    cannon,
     mainnet,
     optimism,
     optimismSepolia,
@@ -47,7 +47,7 @@ export const supportedChains = (options?: SupportedChainsOptions): Chain[] => {
 
     const chains: Chain[] = [];
     if (options.includeDevnet) {
-        chains.push(anvil);
+        chains.push(cannon);
     }
     if (options.includeTestnets) {
         chains.push(arbitrumSepolia, baseSepolia, optimismSepolia, sepolia);
@@ -63,7 +63,7 @@ export const DEFAULT_DEVNET_MNEMONIC =
 
 export type WalletType = "mnemonic" | "private-key";
 const walletChoices = (chain: Chain): Choice<WalletType>[] => {
-    const dev = chain.id === anvil.id;
+    const dev = chain.id === cannon.id;
     return [
         {
             name: `Mnemonic${dev ? "" : chalk.red(" (UNSAFE)")}`,
@@ -77,14 +77,15 @@ const walletChoices = (chain: Chain): Choice<WalletType>[] => {
 };
 
 /**
- * Test if the default RPC URL for a chain is working
+ * Test if a RPC URL for a chain is working
  * @param chain chain to test
- * @returns true if the default RPC URL is valid, false otherwise
+ * @param url url to test
+ * @returns true if the RPC URL is valid and chainId matches, false otherwise
  */
-const testDefaultPublicClient = async (chain: Chain): Promise<boolean> => {
+const testChainUrl = async (chain: Chain, url: string): Promise<boolean> => {
     try {
         const publicClient = viemCreatePublicClient({
-            transport: http(chain.rpcUrls.default.http[0]),
+            transport: http(url),
             chain,
         });
         const chainId = await publicClient.getChainId();
@@ -94,6 +95,15 @@ const testDefaultPublicClient = async (chain: Chain): Promise<boolean> => {
     }
 };
 
+/**
+ * Test if the default RPC URL for a chain is working
+ * @param chain chain to test
+ * @returns true if the default RPC URL is valid, false otherwise
+ */
+const testDefaultPublicClient = async (chain: Chain): Promise<boolean> => {
+    return testChainUrl(chain, chain.rpcUrls.default.http[0]);
+};
+
 export interface EthereumPromptOptions {
     chain?: Chain;
     rpcUrl?: string;
@@ -142,9 +152,17 @@ const selectTransport = async (
     } else {
         const defaultUrl = chain.rpcUrls.default.http[0];
 
-        // if the chain is anvil and the default URL is valid, use it without asking the user
-        if (chain.id === anvil.id && (await testDefaultPublicClient(chain))) {
-            return http(defaultUrl);
+        // if the chain is cannon and URL is valid, use it without asking the user
+        if (chain.id === cannon.id) {
+            const port = 8080; // XXX: how to get environment port?
+            const url = `http://127.0.0.1:${port}/anvil`;
+            if (await testChainUrl(chain, url)) {
+                return http(url);
+            }
+
+            if (await testDefaultPublicClient(chain)) {
+                return http(defaultUrl);
+            }
         }
 
         const url = await input({
@@ -241,7 +259,9 @@ const createWalletClient = async (
             const mnemonic = await input({
                 message: "Mnemonic",
                 default:
-                    chain.id === anvil.id ? DEFAULT_DEVNET_MNEMONIC : undefined,
+                    chain.id === cannon.id
+                        ? DEFAULT_DEVNET_MNEMONIC
+                        : undefined,
             });
 
             // select account from mnemonic
diff --git a/apps/cli/wagmi.config.ts b/apps/cli/wagmi.config.ts
index 975aabf8..e6c165e6 100644
--- a/apps/cli/wagmi.config.ts
+++ b/apps/cli/wagmi.config.ts
@@ -1,9 +1,81 @@
-import hardhatDeploy from "@sunodo/wagmi-plugin-hardhat-deploy";
-import { defineConfig } from "@wagmi/cli";
+import { defineConfig, type Plugin } from "@wagmi/cli";
+import { readdirSync, readFileSync } from "fs";
+import path from "path";
+
+const DataAvailability = JSON.parse(
+    readFileSync(
+        "node_modules/@cartesi/rollups/out/DataAvailability.sol/DataAvailability.json",
+        "utf8",
+    ),
+);
+
+interface CannonOptions {
+    directory: string;
+    includes?: RegExp[];
+    excludes?: RegExp[];
+}
+
+const shouldIncludeFile = (name: string, config: CannonOptions): boolean => {
+    if (config.excludes) {
+        // if there is a list of excludes, then if the name matches any of them, then exclude
+        for (const exclude of config.excludes) {
+            if (exclude.test(name)) {
+                return false;
+            }
+        }
+    }
+    if (config.includes) {
+        // if there is a list of includes, then only include if the name matches any of them
+        for (const include of config.includes) {
+            if (include.test(name)) {
+                return true;
+            }
+        }
+        return false;
+    } else {
+        // if there is no list of includes, then include everything
+        return true;
+    }
+};
+
+const cannonDeployments = (config: CannonOptions): Plugin => {
+    return {
+        name: "cannon",
+        contracts: () => {
+            // list all files exported by cannon in directory
+            const files = readdirSync(config.directory).filter((file) =>
+                shouldIncludeFile(file, config),
+            );
+
+            // return an array of contracts as expected by wagmi
+            return files.map((file) => {
+                // read the file and parse it as json
+                const deployment = JSON.parse(
+                    readFileSync(path.join(config.directory, file), "utf8"),
+                );
+
+                // get the address and abi from the deployment
+                return {
+                    abi: deployment.abi,
+                    address: deployment.address,
+                    name: deployment.contractName,
+                };
+            });
+        },
+    };
+};
 
 export default defineConfig({
     out: "src/contracts.ts",
+    contracts: [
+        {
+            name: "DataAvailability",
+            abi: DataAvailability.abi as any,
+        },
+    ],
     plugins: [
-        hardhatDeploy({ directory: "node_modules/@cartesi/devnet/export/abi" }),
+        cannonDeployments({
+            directory: "node_modules/@cartesi/devnet/deployments",
+        }),
     ],
 });
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 986d2a71..3e20e8f3 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -94,14 +94,14 @@ importers:
         version: 2.23.6(typescript@5.8.2)(zod@3.23.8)
     devDependencies:
       '@cartesi/devnet':
-        specifier: 2.0.0-alpha.3
-        version: 2.0.0-alpha.3
+        specifier: 2.0.0-alpha.5
+        version: 2.0.0-alpha.5
       '@cartesi/eslint-config':
         specifier: workspace:*
         version: link:../../packages/eslint-config
-      '@sunodo/wagmi-plugin-hardhat-deploy':
-        specifier: ^0.3.0
-        version: 0.3.0(abitype@1.0.8(typescript@5.8.2)(zod@3.23.8))(typescript@5.8.2)
+      '@cartesi/rollups':
+        specifier: 2.0.0-rc.17
+        version: 2.0.0-rc.17
       '@types/bytes':
         specifier: ^3.1.5
         version: 3.1.5
@@ -340,8 +340,11 @@ packages:
     resolution: {integrity: sha512-OwS2CM5KocvQ/k7dFJa8i5bNGJP0hXWfVCfDkqRFP1IreH1JDC7wG6eCYCi0+McbfT8OR/kNqsI0UU0xP9H6PQ==}
     engines: {node: '>=6.9.0'}
 
-  '@cartesi/devnet@2.0.0-alpha.3':
-    resolution: {integrity: sha512-CAtk4xbFSnNB5qLGb8eqs8BtlcdjHJBw+9YBK+tldYW8czYQK7Mz3c2nLRVsxGHv/n5Ef5Rhy/4rVR3CnrpaVA==}
+  '@cartesi/devnet@2.0.0-alpha.5':
+    resolution: {integrity: sha512-fTkJcSnW4JsAF/yg2WRBXCnGNo0sG0mC/0AkZxqUgkiniY7BU8wA/zf06nZaBnHQybnnDSY0DJuPcazOPGoFnw==}
+
+  '@cartesi/rollups@2.0.0-rc.17':
+    resolution: {integrity: sha512-W3yCVyRsbgv8t4qwSogKNT8Zy4bcdDxTIuK4rDNPKFvuDuppSQbZfKaaG2fx0NJGfbmm2c7M/t+on8aB+IN9mg==}
 
   '@changesets/apply-release-plan@7.0.10':
     resolution: {integrity: sha512-wNyeIJ3yDsVspYvHnEz1xQDq18D9ifed3lI+wxRQRK4pArUcuHgCTrHv0QRnnwjhVCQACxZ+CBih3wgOct6UXw==}
@@ -1072,9 +1075,6 @@ packages:
     resolution: {integrity: sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==}
     engines: {node: '>=12.4.0'}
 
-  '@openzeppelin/contracts@5.1.0':
-    resolution: {integrity: sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==}
-
   '@pkgjs/parseargs@0.11.0':
     resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==}
     engines: {node: '>=14'}
@@ -1224,21 +1224,6 @@ packages:
     resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==}
     engines: {node: '>=18'}
 
-  '@sunodo/wagmi-plugin-hardhat-deploy@0.3.0':
-    resolution: {integrity: sha512-O7LL6vgnz+PtyFGthbe8TyQoRYwb/e+Qp5rLJ905MQyEQQLKIeLXJJSk6GEZaWijMPwtKXHkAHUSCiHUgH+kCw==}
-    peerDependencies:
-      '@wagmi/core': '>=2.0.0'
-      abitype: '>=0.10.0'
-      typescript: '>=5.0.4'
-      wagmi: '>=2.0.0'
-    peerDependenciesMeta:
-      '@wagmi/core':
-        optional: true
-      typescript:
-        optional: true
-      wagmi:
-        optional: true
-
   '@tsconfig/node10@1.0.11':
     resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==}
 
@@ -4802,9 +4787,9 @@ snapshots:
       '@babel/helper-string-parser': 7.25.9
       '@babel/helper-validator-identifier': 7.25.9
 
-  '@cartesi/devnet@2.0.0-alpha.3':
-    dependencies:
-      '@openzeppelin/contracts': 5.1.0
+  '@cartesi/devnet@2.0.0-alpha.5': {}
+
+  '@cartesi/rollups@2.0.0-rc.17': {}
 
   '@changesets/apply-release-plan@7.0.10':
     dependencies:
@@ -5491,8 +5476,6 @@ snapshots:
 
   '@nolyfill/is-core-module@1.0.39': {}
 
-  '@openzeppelin/contracts@5.1.0': {}
-
   '@pkgjs/parseargs@0.11.0':
     optional: true
 
@@ -5603,12 +5586,6 @@ snapshots:
 
   '@sindresorhus/merge-streams@4.0.0': {}
 
-  '@sunodo/wagmi-plugin-hardhat-deploy@0.3.0(abitype@1.0.8(typescript@5.8.2)(zod@3.23.8))(typescript@5.8.2)':
-    dependencies:
-      abitype: 1.0.8(typescript@5.8.2)(zod@3.23.8)
-    optionalDependencies:
-      typescript: 5.8.2
-
   '@tsconfig/node10@1.0.11': {}
 
   '@tsconfig/node12@1.0.11': {}


Reviews:
user: login: endersonmaia
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-25T20:53:09Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR updates the CLI to support the new devnet alpha.5, transitioning from the legacy anvil services to the cannon chain and updating configuration and deployment interfaces accordingly.
- Replace hardhatDeploy with a new cannonDeployments plugin for contract loading.
- Update chain ID defaults, RPC URL handling, and logging to support cannon.
- Adjust configuration files and deployment property names to match new API responses.

### Reviewed Changes

Copilot reviewed 12 out of 15 changed files in this pull request and generated 1 comment.

<details>
<summary>Show a summary per file</summary>

| File                                           | Description                                                        |
| ---------------------------------------------- | ------------------------------------------------------------------ |
| apps/cli/wagmi.config.ts                       | Introduces cannonDeployments and loads the DataAvailability artifact. |
| apps/cli/src/wallet.ts                         | Replaces anvil chain usage with cannon and adjusts RPC URL testing. |
| apps/cli/src/exec/rollups.ts                    | Updates deployment response property names to new API conventions.  |
| apps/cli/src/config.ts                          | Changes DEFAULT_SDK_VERSION to "devel" to reflect the new version.   |
| apps/cli/src/compose/rollups/proxy/anvil.yaml    | Adds proxy configuration for the anvil service endpoint.            |
| apps/cli/src/compose/rollups/docker-compose-explorer.yaml | Adjusts chain and block confirmation settings to cannon values.       |
| apps/cli/src/compose/rollups/docker-compose-anvil.yaml      | Integrates proxy volume mapping in the service configuration.         |
| apps/cli/src/commands/send.ts                   | Updates default chain ID for sending commands to cannon.             |
| apps/cli/src/commands/rollups/start.ts          | Modifies healthy service message to include dynamic port information.  |
| apps/cli/src/commands/rollups/deploy.ts         | Replaces anvil-specific logic with cannon integration for deployments.  |
| .changeset/*.md                                | Updates changesets with new version and service naming details.       |
</details>


<details>
<summary>Files not reviewed (3)</summary>

* **apps/cli/package.json**: Language not supported
* **apps/cli/src/compose/rollups/default.env**: Language not supported
* **pnpm-lock.yaml**: Language not supported
</details>

<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**apps/cli/src/wallet.ts:156**
* The log messages and comments still reference 'anvil' even though the chain has been updated to cannon; consider updating these strings to maintain consistency.
```
if (chain.id === cannon.id) {
```
**apps/cli/src/commands/rollups/start.ts:31**
* [nitpick] The service label 'anvil' in the healthy title message may be inconsistent with the updated cannon chain usage; consider updating it to reflect the new service name if appropriate.
```
healthyTitle: (port) => `${chalk.cyan("anvil")} service ready at ${chalk.cyan(`${host}:${port}/anvil`)}`
```
</details>


state: COMMENTED
author_association: NONE
submitted_at: 2025-03-27T17:50:32Z
user: login: endersonmaia
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-27T17:53:41Z

Review comments:
diff_hunk: @@ -31,12 +31,12 @@ export const getDeployments = async (
             "list",
         ]);
         return JSON.parse(stdout).map((deployment: any) => ({
-            id: deployment.ID,
-            name: deployment.Name,
-            address: deployment.IApplicationAddress,
-            templateHash: deployment.TemplateHash,
-            epochLength: deployment.EpochLength,
-            state: deployment.State,
+            id: deployment.id,
+            name: deployment.name,
+            address: deployment.iapplication_address,
+            templateHash: deployment.template_hash,
+            epochLength: deployment.epoch_lenght,
path: apps/cli/src/exec/rollups.ts
user: login: Copilot
body: There appears to be a typo in the property name 'epoch_lenght'; consider correcting it to 'epochLength' to avoid potential issues.
```suggestion
            epochLength: deployment.epochLength,
```
created_at: 2025-03-27T17:50:31Z
author_association: NONE
diff_hunk: @@ -31,12 +31,12 @@ export const getDeployments = async (
             "list",
         ]);
         return JSON.parse(stdout).map((deployment: any) => ({
-            id: deployment.ID,
-            name: deployment.Name,
-            address: deployment.IApplicationAddress,
-            templateHash: deployment.TemplateHash,
-            epochLength: deployment.EpochLength,
-            state: deployment.State,
+            id: deployment.id,
+            name: deployment.name,
+            address: deployment.iapplication_address,
+            templateHash: deployment.template_hash,
+            epochLength: deployment.epoch_lenght,
path: apps/cli/src/exec/rollups.ts
user: login: endersonmaia
body: It's ok the way it is, the change was necessary since the JSON now has its elements in snake_case instead of old version that was CamelCase.
created_at: 2025-03-27T17:53:41Z
author_association: CONTRIBUTOR

PR comments:
user: login: changeset-bot[bot]
created_at: 2025-03-25T04:05:33Z
body: ###  🦋  Changeset detected

Latest commit: f7b5543a80e68a2ddad1f018a52124b08261d2a4

**The changes in this PR will be included in the next version bump.**

<details><summary>This PR includes changesets to release 1 package</summary>

  | Name         | Type  |
| ------------ | ----- |
| @cartesi/cli | Major |

</details>

Not sure what this means? [Click here  to learn what changesets are](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md).

[Click here if you're a maintainer who wants to add another changeset to this PR](https://github.com/cartesi/cli/new/feature/cli-devnet?filename=.changeset/soft-ravens-suffer.md&value=---%0A%22%40cartesi%2Fcli%22%3A%20patch%0A---%0A%0ANode%202.0.0-alpha.2%20(cli)%0A)


author_association: NONE
user: login: socket-security[bot]
created_at: 2025-03-25T04:06:07Z
body: **New, updated, and removed dependencies detected.** Learn more about [Socket for GitHub ↗︎](https://socket.dev?utm_medium=gh)


| Package | New capabilities | Transitives | Size | Publisher |
|:--- |:--- |:--- |:--- |:--- |
| [npm/@cartesi/devnet@2.0.0-alpha.3](https://socket.dev/npm/package/@cartesi/devnet/overview/2.0.0-alpha.3) ➜ [2.0.0-alpha.5](https://socket.dev/npm/package/@cartesi/devnet/overview/2.0.0-alpha.5) | None | <a href="https://socket.dev/npm/package/@cartesi/devnet/dependencies/2.0.0-alpha.5">`0`</a> | 546 kB | <a href="https://socket.dev/npm/user/tuler">tuler</a> |
| [npm/@cartesi/rollups@2.0.0-rc.17](https://socket.dev/npm/package/@cartesi/rollups/overview/2.0.0-rc.17) | None | <a href="https://socket.dev/npm/package/@cartesi/rollups/dependencies/2.0.0-rc.17">`0`</a> | 791 kB | <a href="https://socket.dev/npm/user/tuler">tuler</a> |


**🚮 Removed packages:** [npm/ts-node@10.9.2](https://socket.dev/npm/package/ts-node/overview/10.9.2), [npm/tslib@2.8.0](https://socket.dev/npm/package/tslib/overview/2.8.0), [npm/tsup@8.3.0](https://socket.dev/npm/package/tsup/overview/8.3.0), [npm/turbo@2.4.4](https://socket.dev/npm/package/turbo/overview/2.4.4), [npm/typescript@5.5.4](https://socket.dev/npm/package/typescript/overview/5.5.4), [npm/typescript@5.6.3](https://socket.dev/npm/package/typescript/overview/5.6.3)



[**View full report↗︎**](https://socket.dev/dashboard/org/cartesi/diff/360f5d38-2a8a-45bf-9a9d-0867e08b4702/1d1618cf-4537-4294-bfc1-1fce9187f38e)

<!-- overview-comment -->
author_association: NONE
user: login: tuler
created_at: 2025-03-25T04:06:38Z
body: Depend on new node with rollups-contracts 2.0.0-rc.16
https://github.com/cartesi/rollups-node/pull/630
author_association: MEMBER
user: login: github-actions[bot]
created_at: 2025-03-25T04:06:52Z
body: <h2>Coverage Report for ./apps/cli</h2>
<table> <thead> <tr> <th align="center">Status</th> <th align="left">Category</th> <th align="right">Percentage</th> <th align="right">Covered / Total</th> </tr> </thead> <tbody> <tr> <td align="center">🔵</td> <td align="left">Lines</td> <td align="right">26.77%</td> <td align="right">294 / 1098</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Statements</td> <td align="right">26.74%</td> <td align="right">299 / 1118</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Functions</td> <td align="right">26.28%</td> <td align="right">51 / 194</td> </tr> <tr> <td align="center">🔵</td> <td align="left">Branches</td> <td align="right">25.2%</td> <td align="right">121 / 480</td> </tr> </tbody> </table><details><summary>File Coverage</summary><table> <thead> <tr> <th align="left">File</th> <th align="right">Stmts</th> <th align="right">Branches</th> <th align="right">Functions</th> <th align="right">Lines</th> <th align="left">Uncovered Lines</th> </tr> </thead> <tbody> <tr> <td align="left" colspan="6"><b>Changed Files</b></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/wagmi.config.ts">apps/cli/wagmi.config.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/wagmi.config.ts#L5-L62" class="text-red">5-62</a></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts">apps/cli/src/config.ts</a></td> <td align="right">89.57%</td> <td align="right">82.02%</td> <td align="right">96.77%</td> <td align="right">89.37%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L66-L67" class="text-red">66-67</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L216" class="text-red">216</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L223" class="text-red">223</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L232" class="text-red">232</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L247-L250" class="text-red">247-250</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L261" class="text-red">261</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L270" class="text-red">270</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L272" class="text-red">272</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L281" class="text-red">281</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L319" class="text-red">319</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L329-L333" class="text-red">329-333</a>, <a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/config.ts#L345" class="text-red">345</a></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/wallet.ts">apps/cli/src/wallet.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/wallet.ts#L39-L342" class="text-red">39-342</a></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/commands/send.ts">apps/cli/src/commands/send.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/commands/send.ts#L13-L100" class="text-red">13-100</a></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/commands/rollups/deploy.ts">apps/cli/src/commands/rollups/deploy.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/commands/rollups/deploy.ts#L38-L343" class="text-red">38-343</a></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/commands/rollups/start.ts">apps/cli/src/commands/rollups/start.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/commands/rollups/start.ts#L11-L300" class="text-red">11-300</a></td> </tr> <tr> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/exec/rollups.ts">apps/cli/src/exec/rollups.ts</a></td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="right">0%</td> <td align="left"><a href="https://github.com/cartesi/cli/blob/f7b5543a80e68a2ddad1f018a52124b08261d2a4/apps/cli/src/exec/rollups.ts#L18-L61" class="text-red">18-61</a></td> </tr> </tbody> </table></details>
<em>Generated in workflow <a href=https://github.com/cartesi/cli/actions/runs/14134634154>#432</a> for commit <a href="https://github.com/cartesi/cli/commit/f7b5543a80e68a2ddad1f018a52124b08261d2a4">f7b5543</a> by the <a href="https://github.com/davelosert/vitest-coverage-report-action">Vitest Coverage Report Action</a></em>

<!-- vitest-coverage-report-marker-./apps/cli -->
author_association: CONTRIBUTOR
user: login: endersonmaia
created_at: 2025-03-25T12:04:54Z
body: I'm getting this error when trying to build on my machine:

```
✗ pnpm build --filter=@cartesi/cli


> cartesi-cli-monorepo@0.0.0 build /home/endersonmaia/Development/cartesi/cli
> turbo run build "--filter=@cartesi/cli"

turbo 2.4.4

• Packages in scope: @cartesi/cli
• Running build in 1 packages
• Remote caching disabled
@cartesi/cli:build: cache miss, executing 9d446c0d69e69b84
@cartesi/cli:build: 
@cartesi/cli:build: 
@cartesi/cli:build: > @cartesi/cli@2.0.0-alpha.7 build /home/endersonmaia/Development/cartesi/cli/apps/cli
@cartesi/cli:build: > run-s clean codegen compile copy-files
@cartesi/cli:build: 
@cartesi/cli:build: 
@cartesi/cli:build: > @cartesi/cli@2.0.0-alpha.7 clean /home/endersonmaia/Development/cartesi/cli/apps/cli
@cartesi/cli:build: > rimraf dist
@cartesi/cli:build: 
@cartesi/cli:build: 
@cartesi/cli:build: > @cartesi/cli@2.0.0-alpha.7 codegen /home/endersonmaia/Development/cartesi/cli/apps/cli
@cartesi/cli:build: > run-p codegen:wagmi
@cartesi/cli:build: 
@cartesi/cli:build: 
@cartesi/cli:build: > @cartesi/cli@2.0.0-alpha.7 codegen:wagmi /home/endersonmaia/Development/cartesi/cli/apps/cli
@cartesi/cli:build: > wagmi generate
@cartesi/cli:build: 
@cartesi/cli:build: (node:35875) ExperimentalWarning: Importing JSON modules is an experimental feature and might change at any time
@cartesi/cli:build: (Use `node --trace-warnings ...` to show where the warning was created)
✔ Validating plugins
⠙ Resolving contracts
@cartesi/cli:build: EISDIR: illegal operation on a directory, read
@cartesi/cli:build:  ELIFECYCLE  Command failed with exit code 1.
@cartesi/cli:build: ERROR: "codegen:wagmi" exited with 1.
@cartesi/cli:build:  ELIFECYCLE  Command failed with exit code 1.
@cartesi/cli:build: ERROR: "codegen" exited with 1.
@cartesi/cli:build:  ELIFECYCLE  Command failed with exit code 1.
@cartesi/cli:build: ERROR: command finished with error: command (/home/endersonmaia/Development/cartesi/cli/apps/cli) /home/endersonmaia/.nvm/versions/node/v20.11.1/bin/pnpm run build exited (1)
@cartesi/cli#build: command (/home/endersonmaia/Development/cartesi/cli/apps/cli) /home/endersonmaia/.nvm/versions/node/v20.11.1/bin/pnpm run build exited (1)

 Tasks:    0 successful, 1 total
Cached:    0 cached, 1 total
  Time:    8.661s 
Failed:    @cartesi/cli#build

 ERROR  run failed: command  exited (1)
 ELIFECYCLE  Command failed with exit code 1.
```
author_association: CONTRIBUTOR
user: login: tuler
created_at: 2025-03-25T12:24:11Z
body: Did you run `pnpm i`?
author_association: MEMBER
user: login: endersonmaia
created_at: 2025-03-25T12:55:48Z
body: > Did you run `pnpm i`?

Yes, I did.
author_association: CONTRIBUTOR