Skip to content

Deployments export and NPM packaging improvement #1957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Apr 18, 2025
Merged

Conversation

jaybuidl
Copy link
Member

@jaybuidl jaybuidl commented Apr 17, 2025

Improvements

  • Support for both CJS and ESM
  • Correct entry points
  • Contract getters for both Viem and Ethers v6

PR-Codex overview

This PR primarily updates the import paths for the IHomeGateway interface and enhances the deployment configurations and utility functions for handling contract instances across different networks. Additionally, it introduces tests for contract address retrieval.

Detailed summary

  • Updated import paths for IHomeGateway in contracts/wagmi.config.devnet.ts, contracts/wagmi.config.mainnet.ts, and contracts/wagmi.config.testnet.ts.
  • Added new exports in contracts/deployments/index.ts for various network configurations.
  • Introduced deployments object in contracts/deployments/utils.ts with chain IDs for different networks.
  • Created getActualAddress function in contracts/test/utils/getActualAddress.ts to retrieve deployed contract addresses.
  • Added tests for getActualAddress in contracts/test/utils/getActualAddress.test.ts.
  • Modified contracts/scripts/publish.sh for improved error handling and build processes.
  • Increased version number in contracts/package.json to 0.9.3 and updated module paths.
  • Enhanced contract retrieval functions in contracts/deployments/contractsEthers.ts and contracts/deployments/contractsViem.ts.
  • Added integration tests for contract retrieval in contracts/test/integration/getContractsEthers.test.ts.

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Summary by CodeRabbit

  • New Features
    • Added unified interfaces to connect with Kleros smart contracts across multiple Ethereum-compatible networks using both Ethers and Viem libraries.
    • Introduced centralized access points for contract deployment artifacts and utilities for different environments.
    • Added utility functions to retrieve deployed contract addresses with error handling.
  • Bug Fixes
    • Updated artifact import paths in configuration files to ensure correct artifact resolution.
  • Documentation
    • Added detailed JSDoc comments to utility functions for improved developer guidance.
  • Tests
    • Introduced comprehensive integration tests to validate contract retrieval and address consistency across various deployments.
    • Added utility tests for verifying deployed contract addresses.
  • Chores
    • Enhanced package configuration for better module resolution, build consistency, and test support.
    • Improved build and publish scripts for stricter artifact management and safer publishing workflow.

@jaybuidl jaybuidl requested a review from a team as a code owner April 17, 2025 18:45
Copy link
Contributor

coderabbitai bot commented Apr 17, 2025

Walkthrough

This update introduces unified TypeScript modules for instantiating and managing Kleros smart contract instances across multiple Ethereum-compatible networks and deployment environments, supporting both Ethers.js and Viem libraries. New integration tests validate the correctness of contract retrieval for various deployment configurations. The package's build, export, and publishing scripts are improved for consistency and clarity, and new utilities and tests are added for contract address verification. Indexing and re-export modules are provided for streamlined access to deployment artifacts and contract getter functions.

Changes

File(s) Change Summary
contracts/deployments/contractsEthers.ts New module providing unified Ethers.js-based contract connection logic for multiple deployments with type safety and utility functions.
contracts/deployments/contractsViem.ts New module offering Viem-based contract instantiation and configuration for various deployment environments, including utility and getter functions.
contracts/deployments/index.ts New index module re-exporting deployment artifacts, typechain types, and contract getter functions for both Ethers.js and Viem.
contracts/deployments/utils.ts New utility module defining deployment environments, chain IDs, contract config types, and address retrieval helper function with error handling.
contracts/package.json Refined build, export, and module entry configuration; added exports and files fields; updated build scripts and dev dependencies.
contracts/scripts/publish.sh Enhanced script with stricter directory checks, reordered build/publish steps, improved artifact cleanup, and enabled actual publishing (no dry run).
contracts/scripts/utils/contracts.ts Added JSDoc comments; refactored contract retrieval logic by moving common contract instantiations outside switch blocks for clarity.
contracts/test/integration/getContractsEthers.test.ts New integration tests for Ethers.js contract getter, verifying instance types, addresses, and error handling across deployments.
contracts/test/integration/getContractsViem.test.ts New integration tests for Viem contract getter, checking contract instances, addresses, and deployment consistency.
contracts/test/utils/getActualAddress.ts New utility function to retrieve deployed contract addresses from deployment JSON files with error handling.
contracts/test/utils/getActualAddress.test.ts New tests verifying correct address retrieval and error cases for the getActualAddress utility.
contracts/tsconfig-release.json Removed "./src" from the "include" array to limit compilation scope.
contracts/wagmi.config.devnet.ts, contracts/wagmi.config.mainnet.ts, contracts/wagmi.config.testnet.ts Changed artifact import paths for IHomeGateway JSON to use local relative paths.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Provider
    participant getContracts (Ethers/Viem)
    participant DeploymentConfig
    participant ContractFactory
    User->>getContracts: Call with (provider/client, deployment)
    getContracts->>DeploymentConfig: Lookup contract addresses/ABIs for deployment
    getContracts->>ContractFactory: Instantiate contract objects with provider/client
    ContractFactory-->>getContracts: Contract instances
    getContracts-->>User: Return contract instances (core, modules, common, RNG, etc.)
Loading

Possibly related PRs

  • Chainlink RNG #1778: Adds and integrates the ChainlinkRNG contract and related deployment updates, complementing this PR's contract instantiation and connection logic involving the same RNG contracts.
  • DevTools and Ruler deployment on arbitrum #1812: Adds deployment JSON files and documentation for new contracts (KlerosCoreRulerNeo, DisputeResolverRulerNeo) on Arbitrum, which are likely intended to be integrated or referenced by the new contract connection logic introduced in this PR.

Poem

In the warren where contracts reside,
New modules now help us decide—
Ethers or Viem, whichever you please,
Instantiating contracts is now a breeze!
With tests and configs all neat and spry,
This bunny hops forward—oh my, oh my!
🐇✨


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 01d9430 and e832cc7.

📒 Files selected for processing (2)
  • contracts/package.json (4 hunks)
  • contracts/scripts/publish.sh (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • contracts/scripts/publish.sh
  • contracts/package.json
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: Redirect rules - kleros-v2-university
  • GitHub Check: Header rules - kleros-v2-university
  • GitHub Check: Pages changed - kleros-v2-university
  • GitHub Check: Redirect rules - kleros-v2-testnet-devtools
  • GitHub Check: Header rules - kleros-v2-testnet-devtools
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-testnet-devtools
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: contracts-testing
  • GitHub Check: Analyze (javascript)
  • GitHub Check: SonarCloud

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai or @coderabbitai title anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Apr 17, 2025

Deploy Preview for kleros-v2-university failed. Why did it fail? →

Name Link
🔨 Latest commit e832cc7
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-university/deploys/6802613bb574970008f60612

Copy link

netlify bot commented Apr 17, 2025

Deploy Preview for kleros-v2-testnet failed. Why did it fail? →

Name Link
🔨 Latest commit e832cc7
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-testnet/deploys/6802613b4123f20008e85b69

Copy link

netlify bot commented Apr 17, 2025

Deploy Preview for kleros-v2-neo failed. Why did it fail? →

Name Link
🔨 Latest commit e832cc7
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-neo/deploys/6802613b6a4db00008c3e461

Copy link

netlify bot commented Apr 17, 2025

Deploy Preview for kleros-v2-testnet-devtools failed. Why did it fail? →

Name Link
🔨 Latest commit e832cc7
🔍 Latest deploy log https://app.netlify.com/sites/kleros-v2-testnet-devtools/deploys/6802613b6f513d00086d4288

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
contracts/scripts/publish.sh (1)

17-17: Consider implementing version rollback

The TODO comment indicates a missing feature to roll back version bumps if the publishing process fails. This would prevent version number inconsistencies if errors occur.

function _finally {
-    # TODO: rollback version bump
+    if [ $? -ne 0 ] && [ -f "package.json.bak" ]; then
+        # Restore the original package.json if an error occurred
+        mv package.json.bak package.json
+        echo "Rolled back version bump due to error"
+    fi
     rm -rf $SCRIPT_DIR/../dist
}
contracts/test/integration/getContractsViem.test.ts (1)

73-81: Consider mocking external RPC endpoints for more stable tests

The test uses live RPC endpoints, which could make tests unstable if these endpoints are unavailable.

For more reliable tests, consider using mocked clients:

import { createPublicClient, http } from "viem";
import { arbitrum, arbitrumSepolia } from "viem/chains";
import sinon from "sinon";

// Create a stubbed client that doesn't make real network requests
const stubbedTransport = sinon.stub().returns({
  request: async () => ({ chainId: arbitrumSepolia.id }),
});

const arbitrumSepoliaClient = createPublicClient({
  chain: arbitrumSepolia,
  transport: { request: stubbedTransport } as any,
});
contracts/test/integration/getContractsEthers.test.ts (1)

92-93: Consider using mocked providers for more stable tests

Similar to the Viem tests, using live RPC endpoints could make tests unstable.

For more reliable tests, consider mocking the providers:

import { ethers } from "ethers";
import sinon from "sinon";

// Create a stubbed provider that doesn't make real network requests
const arbitrumSepoliaProvider = new ethers.JsonRpcProvider();
sinon.stub(arbitrumSepoliaProvider, "getNetwork").resolves({ 
  chainId: BigInt(arbitrumSepolia.id), 
  name: "arbitrum-sepolia" 
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d574ce8 and 1aeb0a2.

⛔ Files ignored due to path filters (1)
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (14)
  • contracts/deployments/contractsEthers.ts (1 hunks)
  • contracts/deployments/contractsViem.ts (1 hunks)
  • contracts/deployments/index.ts (1 hunks)
  • contracts/package.json (4 hunks)
  • contracts/scripts/publish.sh (2 hunks)
  • contracts/scripts/utils/contracts.ts (4 hunks)
  • contracts/test/integration/getContractsEthers.test.ts (1 hunks)
  • contracts/test/integration/getContractsViem.test.ts (1 hunks)
  • contracts/test/utils/getActualAddress.test.ts (1 hunks)
  • contracts/test/utils/getActualAddress.ts (1 hunks)
  • contracts/tsconfig-release.json (0 hunks)
  • contracts/wagmi.config.devnet.ts (1 hunks)
  • contracts/wagmi.config.mainnet.ts (1 hunks)
  • contracts/wagmi.config.testnet.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • contracts/tsconfig-release.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
contracts/test/utils/getActualAddress.test.ts (1)
contracts/test/utils/getActualAddress.ts (1)
  • getActualAddress (8-23)
⏰ Context from checks skipped due to timeout of 90000ms (15)
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-university
  • GitHub Check: Header rules - kleros-v2-university
  • GitHub Check: Pages changed - kleros-v2-university
  • GitHub Check: contracts-testing
  • GitHub Check: Analyze (javascript)
  • GitHub Check: SonarCloud
🔇 Additional comments (46)
contracts/test/utils/getActualAddress.ts (1)

1-23: Well-implemented utility function with comprehensive error handling.

This utility function is nicely crafted with:

  • Clear JSDoc documentation
  • Proper TypeScript typing
  • Comprehensive error handling with specific error messages
  • Clean implementation using dynamic imports with type assertion

The function effectively serves its purpose of retrieving contract addresses from deployment files while providing meaningful errors when issues occur.

contracts/wagmi.config.testnet.ts (1)

2-2: Good transition to local artifact imports.

Updating the import path from an external package to a local relative path is a good change that reduces external dependencies and ensures artifact version consistency. This aligns well with the PR objectives of improving NPM packaging.

contracts/wagmi.config.devnet.ts (1)

2-2: Good transition to local artifact imports.

Updating the import path from an external package to a local relative path is a good change that reduces external dependencies and ensures artifact version consistency. This aligns well with the PR objectives of improving NPM packaging.

contracts/wagmi.config.mainnet.ts (1)

2-2: Good transition to local artifact imports.

Updating the import path from an external package to a local relative path is a good change that reduces external dependencies and ensures artifact version consistency. This aligns well with the PR objectives of improving NPM packaging.

contracts/test/utils/getActualAddress.test.ts (1)

1-22: Well-structured test suite with comprehensive coverage

This test suite for getActualAddress is well-designed with good coverage of the expected functionality:

  1. Verifies successful retrieval of a valid Ethereum address
  2. Validates error handling for non-existent networks
  3. Confirms proper error handling for non-existent contracts

The tests appropriately use async/await patterns with chai's promise rejection expectations, providing clear assertions and error message validations.

contracts/scripts/publish.sh (6)

1-3: Improved script portability with better shebang and extended globbing

The updated shebang line (#!/usr/bin/env bash) is more portable across different environments, and enabling extended globbing provides more powerful pattern matching capabilities that will help with the file operations later in the script.


25-28: Good safety check for script execution context

Adding this directory check prevents accidental execution from the wrong location, which could cause unintended consequences. This is a good practice for scripts that perform sensitive operations like publishing packages.


30-38: Improved build process flow

The reordering of the build process to clean and rebuild before other operations ensures a fresh start. The removal of mock artifacts and debug JSON files before regenerating typechain types helps create a cleaner package.


50-53: Enhanced distribution build process

Using yarn build:all instead of just TypeScript compilation likely provides a more comprehensive build that includes all necessary artifacts for both CJS and ESM modules, supporting the PR's objective of better packaging.


58-64: Thorough cleanup of unnecessary files

The additional cleanup steps to remove mock files from the distribution package create a cleaner, more focused package that only contains production-relevant code.


75-77: Safer publishing approach using dry run

Changing to npm publish --dry-run is a safer approach that allows verification of what would be published without actually releasing it to the npm registry. This is particularly helpful during development and testing of the publishing process.

contracts/scripts/utils/contracts.ts (4)

30-35: Improved documentation with JSDoc comments

Adding JSDoc comments to the getContractNames function enhances code documentation, making it more accessible to other developers and providing clear information about parameters and return values.


73-79: Improved documentation with JSDoc comments

Similar to the previous function, adding JSDoc comments to the getContracts function improves code documentation and provides valuable context for developers.


99-100: Code refactoring to reduce duplication

Moving the declarations of disputeKitClassic and disputeResolver out of the switch statement to a single instantiation point reduces code duplication and improves maintainability. This change ensures that these contracts are instantiated consistently regardless of the core type.


131-136: Improved documentation with JSDoc comments

Adding JSDoc comments to the getContractsFromNetwork and getContractNamesFromNetwork functions completes the documentation effort for this module, providing a consistent approach to code documentation throughout the file.

Also applies to: 147-152

contracts/deployments/index.ts (1)

1-17: Well-structured module exports for multiple environments and libraries

This new index file elegantly organizes the package exports in a clean, logical structure:

  1. Typechain Ethers v6 artifacts grouped by network
  2. Viem artifacts for different deployment environments
  3. Re-exports from typechain-types for complete type coverage
  4. Unified access to contract getters for both Ethers and Viem libraries

This structure supports the PR objective of improving packaging by providing clear and consistent entry points for both CJS and ESM module systems, and it enables developers to seamlessly use either Viem or Ethers v6 libraries with the same underlying deployment artifacts.

contracts/package.json (4)

5-15: Improved package.json configuration for dual module support!

The new fields correctly define entry points for different module systems. The exports field is properly configured to support both CommonJS and ES module imports.


16-31: Verify the files field includes necessary directories

While the build output directories (types, esm, cjs) are properly included, I noticed several source directories are also listed. This is unusual as published packages typically only include build outputs, not source files.

Are all these directories intentionally included in the published package? If not, consider moving source directories into the src folder and including only build outputs.


93-96: Well-structured build scripts for multiple module formats

The build scripts correctly generate outputs for CommonJS, ESM, and TypeScript declaration files. The package.json files in each output directory properly specify the module type.

One minor suggestion for better cross-platform compatibility:

-    "build:all": "rm -rf ./dist && yarn build:cjs && yarn build:esm && yarn build:types",
+    "build:all": "rimraf ./dist && yarn build:cjs && yarn build:esm && yarn build:types",

113-113: Added testing dependencies

The added dependencies sinon and @types/sinon are appropriate for mocking in tests.

Also applies to: 139-139

contracts/test/integration/getContractsViem.test.ts (8)

1-22: Well-structured test setup with appropriate types

The test imports, constants, and type definitions are well organized. The ContractMapping type is particularly useful for type safety when verifying contracts.


23-69: Comprehensive contract mappings for different deployments

The contract mappings for base, university, and neo deployments are thorough and properly account for optional contracts like RNG modules.


84-111: Good helper functions for contract verification

The helper functions effectively encapsulate the verification logic, making the test cases cleaner and more maintainable.


114-129: Robust address verification against actual deployment files

Using getActualAddress to verify against the actual deployment addresses is a robust approach to ensure contract instances have the correct addresses.


131-149: Thorough testing of devnet deployment

The test covers all important aspects: chain ID verification, contract instance validation, and address verification. Good specific checks for RNG instances that should be present or absent.


151-169: University deployment testing follows same pattern

The test for university deployment maintains consistency with the devnet test pattern, which is good for maintainability.


171-189: Testnet and mainnetNeo deployment tests are consistent

Both tests follow the same pattern as previous tests, maintaining consistency throughout the test suite.

Also applies to: 191-209


211-219: Good error case testing

Testing the error case for unsupported deployment ensures robust error handling.

contracts/test/integration/getContractsEthers.test.ts (7)

1-34: Well-structured imports and type definitions

The imports are comprehensive and the type definitions are clear. Using type inference from the getContracts return type for ContractMapping is a smart approach to maintain type safety.


42-88: Comprehensive contract mappings for different deployments

As with the Viem tests, the contract mappings are thorough and properly account for optional contracts.


95-100: Clever approach to get constructor for instance checks

Using a helper function to get the constructor for type checking is a good workaround for checking instance types.


102-125: Thorough common contract instance verification

The verification checks all contract instances against their expected types, including conditional checks for optional RNG contracts.


128-171: Good helper functions for address verification

The helper functions for address verification are well-structured and reusable across test cases.


173-190: Consistent and thorough testing for all deployments

All deployment tests follow the same pattern, checking instance types, addresses, and specific RNG availability. This consistency is good for maintainability.

Also applies to: 192-213, 215-232, 234-251


253-258: Good error case testing with async/await

Properly testing the error case for an unsupported deployment using async/await and chai's expect.

contracts/deployments/contractsEthers.ts (6)

1-85: Comprehensive imports for contract configurations and types

The imports are well-organized, clearly separating configurations for different deployment environments and contract factory types.


87-100: Clear deployment configuration with chain IDs

The deployments constant clearly maps deployment names to their respective chain IDs using a const assertion for type safety.


102-113: Good address retrieval utility with error handling

The getAddress function effectively extracts addresses for specific chains and includes proper error handling for missing addresses.


115-141: Well-typed interfaces for contract configurations and instances

The type definitions for CommonFactoriesConfigs and CommonFactories provide clear expectations for the inputs and outputs of the factory function.


143-168: Robust common factories function

The getCommonFactories function properly handles optional RNG contracts by returning null when not configured. The function is well-structured and type-safe.


170-267: The main getContracts function handles all deployment scenarios

The switch statement properly handles different deployment types, initializing the appropriate contracts for each scenario. The function correctly throws an error for unsupported deployments.

One minor note: The function is declared as async but doesn't contain any await operations. This might be for consistency with other APIs or to support future async operations.

contracts/deployments/contractsViem.ts (5)

94-98: Add early‑exit guard for missing addresses (improves DX).

getAddress throws, but the error message does not convey which contract was missing. Passing the config name (or at least the known addresses) would save time when debugging multi‑chain issues.

-function getAddress(config: ContractConfig, chainId: number): `0x${string}` {
-  const address = config.address[chainId];
-  if (!address) throw new Error(`No address found for chainId ${chainId}`);
-  return address;
+function getAddress(
+  config: ContractConfig,
+  chainId: number,
+  label?: string,
+): `0x${string}` {
+  const address = config.address[chainId];
+  if (!address) {
+    throw new Error(
+      `No address found for chainId ${chainId}${
+        label ? ` (contract: ${label})` : ""
+      }`,
+    );
+  }
+  return address;
}

You would then pass the label from getContractConfig.
[ suggest_optional_refactor ]


171-184: FIXME is a blocker – university deployment re‑uses devnet artefacts.

The TODO comments indicate that several contracts (disputeTemplateRegistry, evidence, policyRegistry, …) are copied from devnet rather than having university‑specific deployments. Shipping this as‑is may break consumers that assume addresses differ between deployments or, worse, point them to a wrong chain.

At minimum:

  1. Document clearly in README / code that these are intentional placeholders.
  2. Fallback to throwing when the university deployment does not yet have its own contracts to prevent silent misconfiguration.
-    disputeTemplateRegistry: getContractConfig({ config: devnetDtrConfig, chainId }), // FIXME: should not be shared with devnet
+    // TODO(university): replace with dedicated deployment artefacts once available.
+    // A runtime error is preferable to silently pointing to devnet addresses.
+    disputeTemplateRegistry: (() => {
+      throw new Error(
+        "University deployment missing disputeTemplateRegistry artefact",
+      );
+    })(),

[ flag_critical_issue ]


240-244: Verify getContract call‑site – signature changed in viem ≥1.4.

Recent versions of viem expect either:

getContract({ address, abi, publicClient, walletClient })

or

getContract({ address, abi, client: { public: pc, wallet: wc } })

The second form is correct only for versions ≥1.4.0. If your package.json still pins an older viem, users will get a TS/RT error (“unknown property client”). Please double‑check the version constraint or switch to the first signature for wider compatibility.

[ request_verification ]
Would you run the snippet below to confirm the installed viem major version?

#!/bin/bash
jq -r '.dependencies.viem' package.json

230-317: Reduce boilerplate by iterating over config keys.

The block instantiating every contract repeats the same pattern 13 × . A tiny utility cuts 30+ LOC, removes the risk of omissions, and keeps the code in sync with ContractInstances.

-const klerosCore = getContract({ ...contractConfigs.klerosCore, ...clientConfig })
-const sortition = getContract({ ...contractConfigs.sortition, ...clientConfig })
-// …
-const klerosCoreSnapshotProxy = getContract({
-  ...contractConfigs.klerosCoreSnapshotProxy,
-  ...clientConfig,
-})
-return {
-  klerosCore,
-  sortition,
-  disputeKitClassic,
-  disputeResolver,
-  disputeTemplateRegistry,
-  evidence,
-  policyRegistry,
-  transactionBatcher,
-  chainlinkRng,
-  randomizerRng,
-  blockHashRng,
-  pnk,
-  klerosCoreSnapshotProxy,
-};
+const instances = Object.fromEntries(
+  Object.entries(contractConfigs).map(([key, cfg]) => [
+    key,
+    cfg ? getContract({ ...(cfg as ContractInstance), ...clientConfig }) : undefined,
+  ]),
+) as { [K in keyof typeof contractConfigs]: ReturnType<typeof getContract> };
+return instances;

Cleaner, easier to extend (e.g., when you add fastBridge, you only update ContractInstances).

[ suggest_essential_refactor ]


51-64: Consider sourcing chain IDs from artefacts instead of hard‑coding.

deployments hard‑codes arbitrumSepolia.id for devnet, university & testnet. When you migrate testnet from Sepolia to Arbitrum One (or another L2), forgetting to update this constant will break consumers silently.

Prefer deriving the chainId from the artefact JSON itself (every *.viem export already contains the target chain in most setups) or from an env variable.

[ offer_architecture_advice ]

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 17, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (6)
contracts/deployments/contractsEthers.ts (2)

142-239: Contract instantiation function looks good but could benefit from explicit type annotations.

The getContracts function successfully implements contract instantiation across multiple deployment environments. It closely mirrors the Viem implementation while adapting for Ethers.js patterns.

Consider adding an explicit return type to increase type safety and improve documentation:

- export const getContracts = async (provider: ethers.Provider, deployment: DeploymentName) => {
+ export const getContracts = async (provider: ethers.Provider, deployment: DeploymentName): Promise<{
+   klerosCore: KlerosCore | KlerosCoreNeo | KlerosCoreUniversity;
+   sortition: SortitionModule | SortitionModuleNeo | SortitionModuleUniversity;
+   disputeKitClassic: DisputeKitClassic;
+   disputeResolver: DisputeResolver;
+   disputeTemplateRegistry: DisputeTemplateRegistry;
+   evidence: EvidenceModule;
+   policyRegistry: PolicyRegistry;
+   transactionBatcher: TransactionBatcher;
+   chainlinkRng: ChainlinkRNG | null;
+   randomizerRng: RandomizerRNG | null;
+   blockHashRng: BlockHashRNG;
+   pnk: PNK;
+   klerosCoreSnapshotProxy: KlerosCoreSnapshotProxy;
+ }> => {

127-139: Consider using undefined instead of null for optional contracts.

The function currently returns null for optional contracts that are not available in a particular deployment. In TypeScript, it's generally more conventional to use undefined for optional values.

Consider updating the return types and values:

  type CommonFactories = {
    disputeKitClassic: DisputeKitClassic;
    disputeResolver: DisputeResolver;
    disputeTemplateRegistry: DisputeTemplateRegistry;
    evidence: EvidenceModule;
    policyRegistry: PolicyRegistry;
    transactionBatcher: TransactionBatcher;
-   chainlinkRng: ChainlinkRNG | null;
-   randomizerRng: RandomizerRNG | null;
+   chainlinkRng: ChainlinkRNG | undefined;
+   randomizerRng: RandomizerRNG | undefined;
    blockHashRng: BlockHashRNG;
    pnk: PNK;
    klerosCoreSnapshotProxy: KlerosCoreSnapshotProxy;
  };

  // And in the implementation:
  chainlinkRng: configs.chainlinkRngConfig
    ? ChainlinkRNG__factory.connect(getAddress(configs.chainlinkRngConfig, chainId), provider)
-    : null,
+    : undefined,
  randomizerRng: configs.randomizerRngConfig
    ? RandomizerRNG__factory.connect(getAddress(configs.randomizerRngConfig, chainId), provider)
-    : null,
+    : undefined,
contracts/test/integration/getContractsEthers.test.ts (4)

92-93: Hardcoded RPC URLs could be centralized or made configurable.

Using hardcoded URLs for production RPC endpoints can create maintenance issues if these endpoints change, and may expose tests to rate limiting during frequent test runs.

Consider centralizing these URLs or making them configurable:

- const arbitrumSepoliaProvider = new ethers.JsonRpcProvider("https://sepolia-rollup.arbitrum.io/rpc");
- const arbitrumProvider = new ethers.JsonRpcProvider("https://arb1.arbitrum.io/rpc");
+ // Import from a central configuration file or environment variables
+ import { RPC_URLS } from "../../config";
+ 
+ const arbitrumSepoliaProvider = new ethers.JsonRpcProvider(RPC_URLS.arbitrumSepolia);
+ const arbitrumProvider = new ethers.JsonRpcProvider(RPC_URLS.arbitrum);

58-72: Redundancy in contract mappings could be reduced with inheritance patterns.

The universityContractMapping and neoContractMapping objects share most properties with baseContractMapping but override a few specific entries. This creates redundancy.

Consider using object spread to derive these mappings:

const baseContractMapping: ContractMapping = {
  klerosCore: { name: "KlerosCore" },
  sortition: { name: "SortitionModule" },
  // ... other properties
};

- const universityContractMapping: ContractMapping = {
-   klerosCore: { name: "KlerosCoreUniversity" },
-   sortition: { name: "SortitionModuleUniversity" },
-   disputeKitClassic: { name: "DisputeKitClassicUniversity" },
-   disputeResolver: { name: "DisputeResolverUniversity" },
-   disputeTemplateRegistry: { name: "DisputeTemplateRegistry" },
-   // ... duplicate properties
- };
+ const universityContractMapping: ContractMapping = {
+   ...baseContractMapping,
+   klerosCore: { name: "KlerosCoreUniversity" },
+   sortition: { name: "SortitionModuleUniversity" },
+   disputeKitClassic: { name: "DisputeKitClassicUniversity" },
+   disputeResolver: { name: "DisputeResolverUniversity" },
+ };

- const neoContractMapping: ContractMapping = {
-   klerosCore: { name: "KlerosCoreNeo" },
-   sortition: { name: "SortitionModuleNeo" },
-   disputeKitClassic: { name: "DisputeKitClassicNeo" },
-   disputeResolver: { name: "DisputeResolverNeo" },
-   // ... duplicate properties
- };
+ const neoContractMapping: ContractMapping = {
+   ...baseContractMapping,
+   klerosCore: { name: "KlerosCoreNeo" },
+   sortition: { name: "SortitionModuleNeo" },
+   disputeKitClassic: { name: "DisputeKitClassicNeo" },
+   disputeResolver: { name: "DisputeResolverNeo" },
+   chainlinkRng: { name: "ChainlinkRNG", optional: false },
+   randomizerRng: { name: "RandomizerRNG", optional: false },
+ };

Also applies to: 74-88


253-258: Consider making the error message assertion more specific.

The error message assertion is using a regex that matches multiple possible error messages. While this works, it might hide subtle differences in error behavior.

Consider making this assertion more specific:

- await expect(getContracts(arbitrumSepoliaProvider, "invalid")).to.be.rejectedWith(
-   /Unsupported deployment|Cannot destructure property/
- );
+ await expect(getContracts(arbitrumSepoliaProvider, "invalid")).to.be.rejectedWith(
+   "Unsupported deployment: invalid"
+ );

If there are legitimate different error paths, add separate test cases for each scenario to explicitly document the expected behavior.


184-185: Test expectations differ between deployment types.

The tests for different deployments have different expectations for RNG contracts:

  • Devnet: chainlinkRng not null, randomizerRng null
  • University: chainlinkRng not null, randomizerRng null
  • Testnet: chainlinkRng not null, randomizerRng null
  • MainnetNeo: Both not null

These differences are implicit and not explained in the test comments.

Consider adding comments to explain why different deployments have different RNG contracts available, or at least make the pattern more explicit:

  // Verify contract instances
  expect(contracts.klerosCore).to.be.instanceOf(getConstructor(KlerosCoreNeo__factory, arbitrumProvider));
  expect(contracts.sortition).to.be.instanceOf(getConstructor(SortitionModuleNeo__factory, arbitrumProvider));
  verifyCommonContractInstances(contracts, arbitrumProvider);
+ // MainnetNeo has both RNG contracts available
  expect(contracts.chainlinkRng).to.not.be.null;
  expect(contracts.randomizerRng).to.not.be.null;

Also applies to: 207-208, 226-227, 245-246

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro (Legacy)

📥 Commits

Reviewing files that changed from the base of the PR and between 1aeb0a2 and 01d9430.

📒 Files selected for processing (8)
  • contracts/deployments/contractsEthers.ts (1 hunks)
  • contracts/deployments/contractsViem.ts (1 hunks)
  • contracts/deployments/index.ts (1 hunks)
  • contracts/deployments/utils.ts (1 hunks)
  • contracts/package.json (4 hunks)
  • contracts/scripts/publish.sh (3 hunks)
  • contracts/test/integration/getContractsEthers.test.ts (1 hunks)
  • contracts/test/integration/getContractsViem.test.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • contracts/deployments/utils.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • contracts/test/integration/getContractsViem.test.ts
  • contracts/deployments/index.ts
  • contracts/package.json
  • contracts/scripts/publish.sh
  • contracts/deployments/contractsViem.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
contracts/deployments/contractsEthers.ts (4)
contracts/deployments/utils.ts (4)
  • ContractConfig (20-23)
  • getAddress (25-29)
  • DeploymentName (18-18)
  • deployments (3-16)
contracts/deployments/index.ts (2)
  • getContracts (18-18)
  • getContracts (19-19)
contracts/deployments/contractsViem.ts (1)
  • getContracts (202-289)
contracts/scripts/utils/contracts.ts (1)
  • getContracts (79-129)
⏰ Context from checks skipped due to timeout of 90000ms (15)
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Header rules - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Pages changed - kleros-v2-testnet
  • GitHub Check: Redirect rules - kleros-v2-university
  • GitHub Check: Header rules - kleros-v2-university
  • GitHub Check: Pages changed - kleros-v2-university
  • GitHub Check: Redirect rules - kleros-v2-neo
  • GitHub Check: Header rules - kleros-v2-neo
  • GitHub Check: Pages changed - kleros-v2-neo
  • GitHub Check: SonarCloud
  • GitHub Check: contracts-testing
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (4)
contracts/deployments/contractsEthers.ts (1)

142-147: Why is this function marked as async when it doesn't contain awaits?

The getContracts function is marked as async but doesn't contain any await expressions. This makes it unnecessarily return a Promise.

Is there a specific reason for marking this function as async? If it's to maintain a consistent interface with another implementation that does use await, that makes sense. Otherwise, removing the async keyword would make the function more straightforward.

contracts/test/integration/getContractsEthers.test.ts (3)

95-100: Smart helper function for constructor testing.

The getConstructor helper function is a clever approach to testing class instances without exposing TypeScript-specific implementation details.


127-153: Comprehensive address verification.

The test utilities for verifying contract addresses are thorough. They check for proper format, non-zero value, and match against expected deployment addresses.


173-259: Well-structured test cases for each deployment environment.

The test cases for different deployment environments are well-structured and consistent. They verify chain IDs, contract instances, and addresses, which provides thorough coverage of the getContracts function.

coderabbitai[bot]
coderabbitai bot previously approved these changes Apr 17, 2025
kemuru
kemuru previously approved these changes Apr 17, 2025
@jaybuidl jaybuidl dismissed stale reviews from kemuru and coderabbitai[bot] via e832cc7 April 18, 2025 14:27
Copy link

codeclimate bot commented Apr 18, 2025

Code Climate has analyzed commit e832cc7 and detected 30 issues on this pull request.

Here's the issue category breakdown:

Category Count
Duplication 14
Style 16

View more on Code Climate.

@jaybuidl jaybuidl merged commit 04cb0d4 into dev Apr 18, 2025
6 of 20 checks passed
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants