{"_id":"@aztec-foundation/aztec-benchmark","_rev":"3-0c36e0c75a803f5f703ffa0b3cff89a3","name":"@aztec-foundation/aztec-benchmark","dist-tags":{"canary":"0.0.0-snapshot.39244c93","latest":"5.0.1"},"versions":{"0.0.0-snapshot.39244c93":{"name":"@aztec-foundation/aztec-benchmark","version":"0.0.0-snapshot.39244c93","license":"MIT","_id":"@aztec-foundation/aztec-benchmark@0.0.0-snapshot.39244c93","maintainers":[{"name":"aztec-foundation-user-account","email":"npm@aztec.foundation"}],"homepage":"https://github.com/AztecProtocol/aztec-benchmark#readme","bugs":{"url":"https://github.com/AztecProtocol/aztec-benchmark/issues"},"bin":{"aztec-benchmark":"bin/aztec-benchmark"},"dist":{"shasum":"65825cb9c71a4e066cd7345f20e7e10ea6879fd9","tarball":"https://registry.npmjs.org/@aztec-foundation/aztec-benchmark/-/aztec-benchmark-0.0.0-snapshot.39244c93.tgz","fileCount":20,"integrity":"sha512-HjhWI1/Pk3cyor2hxHzixAc9M/YOM76Fq4t5sejmPR8MsuQ2liIr2iC5KG0cLxeA41u5Uio2SelCkAavLM6mOg==","signatures":[{"sig":"MEQCIC9JXwcrylyBZupdMKUaMMXghlmvysXLe4dBqYb6s1BSAiAWt9OnQlWdp/Odss8Xm4gNPPgQFPbw2smToqNNXPuMfA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":568143},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","config":{"aztecVersion":"5.0.1"},"engines":{"node":">=22"},"gitHead":"39244c9306f7b460aec570297100f3513f7ef936","scripts":{"build":"tsc && ncc build action/index.cjs -o action/dist -m -C","start":"tsx cli/cli.ts","prepare":"husky","lint:prettier":"prettier '**/*.{js,ts}' --write"},"_npmUser":{"name":"aztec-foundation-user-account","email":"npm@aztec.foundation"},"repository":{"url":"git+https://github.com/AztecProtocol/aztec-benchmark.git","type":"git"},"_npmVersion":"10.9.2","description":"CLI tool and GitHub Action for Aztec contract benchmarking","directories":{},"lint-staged":{"*.ts":"prettier --write -u"},"_nodeVersion":"22.17.0","dependencies":{"tsx":"4.19.4","esbuild":"0.25.0","commander":"13.1.0","typescript":"5.8.3","@iarna/toml":"2.2.5","@types/node":"22.15.3","@actions/core":"1.10.1","@actions/exec":"1.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e","devDependencies":{"husky":"9.1.7","prettier":"3.8.0","@vercel/ncc":"0.38.3","lint-staged":"16.2.7","@aztec/wallets":"5.0.1","@aztec/aztec.js":"5.0.1","@commitlint/cli":"20.3.1","@commitlint/config-conventional":"20.2.0"},"peerDependencies":{"@aztec/wallets":">=5.0.0 <6","@aztec/aztec.js":">=5.0.0 <6"},"_npmOperationalInternal":{"tmp":"tmp/aztec-benchmark_0.0.0-snapshot.39244c93_1784198648523_0.9630311085155216","host":"s3://npm-registry-packages-npm-production"}},"5.0.1":{"name":"@aztec-foundation/aztec-benchmark","version":"5.0.1","license":"MIT","_id":"@aztec-foundation/aztec-benchmark@5.0.1","maintainers":[{"name":"aztec-foundation-user-account","email":"npm@aztec.foundation"}],"homepage":"https://github.com/AztecProtocol/aztec-benchmark#readme","bugs":{"url":"https://github.com/AztecProtocol/aztec-benchmark/issues"},"bin":{"aztec-benchmark":"bin/aztec-benchmark"},"dist":{"shasum":"c48fcaa40280bb76a27e1352b2d7757b6598cdfe","tarball":"https://registry.npmjs.org/@aztec-foundation/aztec-benchmark/-/aztec-benchmark-5.0.1.tgz","fileCount":20,"integrity":"sha512-u6k6grNSC7/Oq4cHBiDRlkn1SyhsjeKpXv/wyuTOIpcZHK1INOHnDsOJFCduTdg9G3LBrUPg3as8B4sj6r+L+Q==","signatures":[{"sig":"MEQCICJpVtAWIMw8ivx/OUTUZsPK0nxKYHZxSI7BIxxC/EmUAiAEr+L8PBAgAHjeMD94z5MgK4LjoCuexOaDUq9Mj3VzKw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":568125},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","config":{"aztecVersion":"5.0.1"},"engines":{"node":">=22"},"gitHead":"39244c9306f7b460aec570297100f3513f7ef936","scripts":{"build":"tsc && ncc build action/index.cjs -o action/dist -m -C","start":"tsx cli/cli.ts","prepare":"husky","lint:prettier":"prettier '**/*.{js,ts}' --write"},"_npmUser":{"name":"aztec-foundation-user-account","email":"npm@aztec.foundation"},"repository":{"url":"git+https://github.com/AztecProtocol/aztec-benchmark.git","type":"git"},"_npmVersion":"10.9.2","description":"CLI tool and GitHub Action for Aztec contract benchmarking","directories":{},"lint-staged":{"*.ts":"prettier --write -u"},"_nodeVersion":"22.17.0","dependencies":{"tsx":"4.19.4","esbuild":"0.25.0","commander":"13.1.0","typescript":"5.8.3","@iarna/toml":"2.2.5","@types/node":"22.15.3","@actions/core":"1.10.1","@actions/exec":"1.1.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"packageManager":"yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e","devDependencies":{"husky":"9.1.7","prettier":"3.8.0","@vercel/ncc":"0.38.3","lint-staged":"16.2.7","@aztec/wallets":"5.0.1","@aztec/aztec.js":"5.0.1","@commitlint/cli":"20.3.1","@commitlint/config-conventional":"20.2.0"},"peerDependencies":{"@aztec/wallets":">=5.0.0 <6","@aztec/aztec.js":">=5.0.0 <6"},"_npmOperationalInternal":{"tmp":"tmp/aztec-benchmark_5.0.1_1784199093308_0.9573207085574602","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2026-07-16T10:44:08.413Z","modified":"2026-08-27T14:15:45.474Z","0.0.0-snapshot.39244c93":"2026-07-16T10:44:08.716Z","5.0.1":"2026-07-16T10:51:33.478Z"},"bugs":{"url":"https://github.com/AztecProtocol/aztec-benchmark/issues"},"license":"MIT","homepage":"https://github.com/AztecProtocol/aztec-benchmark#readme","repository":{"url":"git+https://github.com/AztecProtocol/aztec-benchmark.git","type":"git"},"description":"CLI tool and GitHub Action for Aztec contract benchmarking","maintainers":[{"email":"npm@aztec.foundation","name":"aztec-foundation-user-account"},{"email":"adamdomurad@gmail.com","name":"ludamad"}],"readme":"# Aztec Benchmark\n[![npm version](https://badge.fury.io/js/%40aztec-foundation%2Faztec-benchmark.svg)](https://www.npmjs.com/package/@aztec-foundation/aztec-benchmark)\n\n**CLI tool and reusable CI workflows for running Aztec contract benchmarks.**\n\nUse the CLI to execute benchmark files written in TypeScript. For CI integration, this repository provides **reusable GitHub workflows** that handle the full benchmark-and-compare cycle — including environment setup, baseline management, and PR commenting — so consumer repos can integrate with a single `uses:` line.\n\n## Table of Contents\n\n- [Installation](#installation)\n- [CLI Usage](#cli-usage)\n  - [Configuration (`Nargo.toml`)](#configuration-nargotoml)\n  - [Options](#options)\n  - [Examples](#examples)\n- [Writing Benchmarks](#writing-benchmarks)\n- [Benchmark Output](#benchmark-output)\n- [Reusable Workflows](#reusable-workflows)\n  - [PR Benchmark (`pr-benchmark.yml`)](#pr-benchmark-pr-benchmarkyml)\n  - [Update Baseline (`update-baseline.yml`)](#update-baseline-update-baselineyml)\n  - [How Baselines Work](#how-baselines-work)\n- [Action Usage (Advanced)](#action-usage-advanced)\n  - [Inputs](#inputs)\n  - [Outputs](#outputs)\n\n---\n\n## Installation\n\n```sh\nyarn add --dev @aztec-foundation/aztec-benchmark\n# or\nnpm install --save-dev @aztec-foundation/aztec-benchmark\n```\n\n---\n\n## CLI Usage\n\nAfter installing, run the CLI using `npx aztec-benchmark`. By default, it looks for a `Nargo.toml` file in the current directory and runs benchmarks defined within it.\n\n```sh\nnpx aztec-benchmark [options]\n```\n\n### Configuration (`Nargo.toml`)\n\nDefine which contracts have associated benchmark files in your `Nargo.toml` under the `[benchmark]` section:\n\n```toml\n[benchmark]\ntoken = \"benchmarks/token_contract.benchmark.ts\"\nanother_contract = \"path/to/another.benchmark.ts\"\n```\n\nThe paths to the `.benchmark.ts` files are relative to the `Nargo.toml` file.\n\n### Options\n\n- `-c, --contracts <names...>`: Specify which contracts (keys from the `[benchmark]` section) to run. If omitted, runs all defined benchmarks.\n- `--config <path>`: Path to your `Nargo.toml` file (default: `./Nargo.toml`).\n- `-o, --output-dir <path>`: Directory to save benchmark JSON reports (default: `./benchmarks`).\n- `-s, --suffix <suffix>`: Optional suffix to append to report filenames (e.g., `_pr` results in `token_pr.benchmark.json`).\n- `--skip-proving`: Skip proving transactions. Only measures gate counts and gas; proving time will be `0` in reports. When enabled, the `wallet` is not required in the benchmark context.\n\n### Examples\n\nRun all benchmarks defined in `./Nargo.toml`:\n```sh\nnpx aztec-benchmark \n```\n\nRun only the `token` benchmark:\n```sh\nnpx aztec-benchmark --contracts token\n```\n\nRun `token` and `another_contract` benchmarks, saving reports with a suffix:\n```sh\nnpx aztec-benchmark --contracts token another_contract --output-dir ./benchmark_results --suffix _v2\n```\n\n---\n\n## Writing Benchmarks\n\nBenchmarks are TypeScript classes extending `BenchmarkBase` from this package.\nEach entry in the array returned by `getMethods` can either be a plain `ContractFunctionInteractionCallIntent` \n(in which case the benchmark name is auto-derived) or a `NamedBenchmarkedInteraction` object \n(which includes the `interaction` and a custom `name` for reporting).\n\n### Fee Payment\n\nBy default, every benchmarked account must hold Fee Juice (FJ) to pay for transaction fees. If your accounts don't have pre-existing FJ (e.g. freshly-created accounts on sandbox), you can return a `feePaymentMethod` from `setup()` inside the `BenchmarkContext`. The profiler will pass it to every `send()` and `proveInteraction()` call automatically.\n\nThe sandbox ships with a canonical `SponsoredFPC` contract that has FJ and can sponsor fees for any account — making it the easiest way to get benchmarks running without bridging from L1.\n\n```ts\nimport {\n  Benchmark, // Alias for BenchmarkBase\n  type BenchmarkContext,\n  type NamedBenchmarkedInteraction\n} from '@aztec-foundation/aztec-benchmark';\nimport type { PXE } from '@aztec/pxe/server';\nimport type { Contract } from '@aztec/aztec.js/contracts'; // Generic Contract type from Aztec.js\nimport type { AztecAddress } from '@aztec/aztec.js/addresses';\nimport type { ContractFunctionInteractionCallIntent } from '@aztec/aztec.js/authorization';\nimport type { FeePaymentMethod } from '@aztec/aztec.js/fee';\nimport { createStore } from '@aztec/kv-store/lmdb-v2';\nimport { createPXE, getPXEConfig } from '@aztec/pxe/server';\nimport { createAztecNodeClient, waitForNode } from '@aztec/aztec.js/node';\nimport { EmbeddedWallet } from '@aztec/wallets/embedded';\nimport { registerInitialLocalNetworkAccountsInWallet } from '@aztec/wallets/testing';\n// import { YourSpecificContract } from '../artifacts/YourSpecificContract.js'; // Replace with your actual contract artifact\n\n// 1. Define a specific context for your benchmark (optional but good practice)\ninterface MyBenchmarkContext extends BenchmarkContext {\n  pxe: PXE;\n  wallet: EmbeddedWallet;\n  deployer: AztecAddress;\n  contract: Contract; // Use the generic Contract type or your specific contract type\n  feePaymentMethod?: FeePaymentMethod;\n}\n\nexport default class MyContractBenchmark extends Benchmark {\n  // Runs once before all benchmark methods.\n  async setup(): Promise<MyBenchmarkContext> {\n    console.log('Setting up benchmark environment...');\n\n    const { NODE_URL = 'http://localhost:8080' } = process.env;\n    const node = createAztecNodeClient(NODE_URL);\n    await waitForNode(node);\n    const l1Contracts = await node.getL1ContractAddresses();\n    const config = getPXEConfig();\n    const fullConfig = { ...config, l1Contracts };\n    // IMPORTANT: true enables proof generation for the benchmark, set it to false when using --skip-proving\n    fullConfig.proverEnabled = true;\n    const pxeVersion = 2;\n    const store = await createStore('pxe', pxeVersion, {\n      dataDirectory: 'store',\n      dataStoreMapSizeKb: 1e6,\n    });\n\n    const pxe: PXE = await createPXE(node, fullConfig, { store });\n    // `EmbeddedWalletOptions` uses a unified `pxe` field for PXE config and dependency overrides.\n    const wallet: EmbeddedWallet = await EmbeddedWallet.create(node, { pxe: fullConfig });\n    const accounts: AztecAddress[] = await registerInitialLocalNetworkAccountsInWallet(wallet);\n    const [deployer] = accounts;\n    \n    //  Deploy your contract (replace YourSpecificContract with your actual contract class).\n    //  `DeployMethod.send()` now always returns `{ contract, receipt, instance }`.\n    const { contract } = await YourSpecificContract\n      .deploy(wallet, /* constructor args */)\n      .send({ from: deployer });\n    console.log('Contract deployed at:', contract.address.toString());\n\n    // Optional: use SponsoredFPC so accounts don't need pre-existing Fee Juice.\n    // The sandbox ships with a canonical SponsoredFPC pre-deployed at a deterministic address.\n    //\n    // import { SponsoredFeePaymentMethod } from '@aztec/aztec.js/fee/testing';\n    // import { SponsoredFPCContract } from '@aztec/noir-contracts.js/SponsoredFPC';\n    // import { getContractInstanceFromInstantiationParams } from '@aztec/aztec.js/contracts';\n    //\n    // const instance = await getContractInstanceFromInstantiationParams(\n    //   SponsoredFPCContract.artifact,\n    //   { salt: new Fr(0n) },\n    // );\n    // await wallet.registerContract(instance, SponsoredFPCContract.artifact);\n    // const feePaymentMethod = new SponsoredFeePaymentMethod(instance.address);\n\n    return { pxe, wallet, deployer, contract /*, feePaymentMethod */ }; \n  }\n\n  // Returns an array of interactions to benchmark. \n  getMethods(context: MyBenchmarkContext): Promise<Array<ContractFunctionInteractionCallIntent | NamedBenchmarkedInteraction>> {\n    // Ensure context is available (it should be if setup ran correctly)\n    if (!context || !context.contract) {\n      // In a real scenario, setup() must initialize the context properly.\n      // Throwing an error or returning an empty array might be appropriate here if setup failed.\n      console.error(\"Benchmark context or contract not initialized in setup(). Skipping getMethods.\");\n      return [];\n    }\n    \n    const { contract, deployer } = context;\n    const recipient = deployer; // Example recipient\n\n    // Replace `contract.methods.someMethodName` with actual methods from your contract.\n    const interactionPlain = { caller: deployer, action: contract.methods.transfer(recipient, 100n) }\n    const interactionNamed1 = { caller: deployer, action: contract.methods.someOtherMethod(\"test_value_1\") };\n    const interactionNamed2 = { caller: deployer, action: contract.methods.someOtherMethod(\"test_value_2\") };\n\n    return [\n      // Example of a plain interaction - name will be auto-derived\n      interactionPlain,\n      // Example of a named interaction\n      { interaction: interactionNamed1, name: \"Some Other Method (value 1)\" }, \n      // Another named interaction\n      { interaction: interactionNamed2, name: \"Some Other Method (value 2)\" }, \n    ];\n  }\n\n  // Optional cleanup phase\n  async teardown(context: MyBenchmarkContext): Promise<void> {\n    console.log('Cleaning up benchmark environment...');\n    if (context && context.pxe) { \n      await context.pxe.stop(); \n    }\n  }\n}\n```\n\n**Note:** Your benchmark code needs a valid Aztec project setup to interact with contracts.\nYour `BenchmarkBase` implementation is responsible for constructing the `ContractFunctionInteractionCallIntent` objects.\nIf you provide a `NamedBenchmarkedInteraction` object, its `name` field will be used in reports. \nIf you provide a plain `ContractFunctionInteractionCallIntent`, the tool will attempt to derive a name from the interaction (e.g., the method name).\nIf you return a `feePaymentMethod` in the `BenchmarkContext`, it is automatically passed to every transaction the profiler sends — no changes to `getMethods` are needed.\n\n### Aztec's Usage Example\n\nYou can find how we use this tool for benchmarking our Aztec contracts in [`aztec-standards`](https://github.com/AztecProtocol/aztec-standards/tree/main/benchmarks).\n\n---\n\n## Benchmark Output\n\nYour `BenchmarkBase` implementation is responsible for measuring and outputting performance data (e.g., as JSON). The comparison action uses this output.\nEach entry in the output will be identified by the custom `name` you provided (if any) or the auto-derived name.\n\n---\n\n## Reusable Workflows\n\nThis repository ships two **reusable GitHub workflows** (`workflow_call`) that handle the full CI benchmark cycle. Consumer repos call them with a single `uses:` line — no need to copy workflow YAML or wire up artifact management manually.\n\n### PR Benchmark (`pr-benchmark.yml`)\n\nRuns benchmarks on the PR head, downloads the baseline from the base branch, generates a comparison report, comments it on the PR (hiding any previous benchmark comments as outdated), and uploads the new results as a baseline artifact for the PR branch.\n\n**Usage:**\n\n```yaml\n# .github/workflows/pr-checks.yml\nname: PR Checks\n\non:\n  pull_request:\n    branches: [main]\n\njobs:\n  benchmark:\n    uses: AztecProtocol/aztec-benchmark/.github/workflows/pr-benchmark.yml@v0\n    permissions:\n      pull-requests: write\n      issues: write\n      actions: read\n```\n\n**Inputs:**\n\n| Input | Type | Default | Description |\n|---|---|---|---|\n| `runner` | `string` | `ubuntu-latest-m` | GitHub runner label |\n| `timeout` | `number` | `120` | Job timeout in minutes |\n| `bench-dir` | `string` | `./benchmarks` | Directory for benchmark files |\n\n**With custom inputs:**\n\n```yaml\njobs:\n  benchmark:\n    uses: AztecProtocol/aztec-benchmark/.github/workflows/pr-benchmark.yml@v0\n    permissions:\n      pull-requests: write\n      issues: write\n      actions: read\n    with:\n      runner: ubuntu-latest-l\n      timeout: 180\n      bench-dir: ./my-benchmarks\n```\n\n### Update Baseline (`update-baseline.yml`)\n\nRuns benchmarks on the current branch and uploads the results as a baseline artifact. This should be triggered on pushes to your default branches so that PR benchmarks have a baseline to compare against.\n\n**Usage:**\n\n```yaml\n# .github/workflows/update-baseline.yml\nname: Update Baseline\n\non:\n  push:\n    branches: [main]\n\njobs:\n  update-baseline:\n    uses: AztecProtocol/aztec-benchmark/.github/workflows/update-baseline.yml@v0\n    permissions:\n      contents: read\n      actions: write\n```\n\n**Inputs:**\n\n| Input | Type | Default | Description |\n|---|---|---|---|\n| `runner` | `string` | `ubuntu-latest-m` | GitHub runner label |\n| `timeout` | `number` | `120` | Job timeout in minutes |\n| `bench-dir` | `string` | `./benchmarks` | Directory for benchmark files |\n\n### How Baselines Work\n\nThe workflows use GitHub Actions artifacts to store and retrieve baseline benchmark results:\n\n1. **`update-baseline.yml`** runs benchmarks with the `_latest` suffix and uploads the results as `benchmark-baseline-<branch>`.\n2. **`pr-benchmark.yml`** runs benchmarks with the `_new` suffix on the PR head, then downloads the `benchmark-baseline-<base-branch>` artifact to get the `_latest` files. It compares `_latest` (baseline) vs `_new` (PR) and comments a Markdown diff table on the PR.\n3. Before posting the new comment, the workflow finds all previous benchmark comments on the PR (identified by a unique marker in the comment body) and hides them as **Outdated** via the GitHub GraphQL API, so the PR timeline stays clean.\n4. After comparison, the PR workflow renames `_new` files to `_latest` and uploads them as `benchmark-baseline-<head-branch>`, so stacked PRs can also compare against each other.\n\nArtifacts are retained for **90 days** by default.\n\n---\n\n## Action Usage (Advanced)\n\n> **Note:** For most projects, the [reusable workflows](#reusable-workflows) above are the recommended approach. The action below is a lower-level building block for projects that need a custom CI setup.\n\nThis repository also includes a GitHub Action (defined in `action/action.yml`) that runs `aztec-benchmark` and compares results. It automatically finds benchmark reports (named with `_base` and `_latest` suffixes) and produces a Markdown comparison report.\n\n### Inputs\n\n- `threshold`: Regression threshold percentage (default: `2.5`).\n- `output_markdown_path`: Path to save the generated Markdown comparison report (default: `benchmark-comparison.md`).\n\n### Outputs\n\n- `comparison_markdown`: The generated Markdown report content.\n- `markdown_file_path`: Path to the saved Markdown file.\n\nRefer to the `action/action.yml` file for the definitive inputs and description.\n","readmeFilename":"README.md"}