npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@diamondslab/diamonds

v1.5.0

Published

Tools for deploying and interfacing with ERC-2535 Diamond Proxies

Readme

Diamonds Module

npm version License: MIT TypeScript Hardhat

@diamondslab/diamonds is a TypeScript framework for deploying, upgrading, and managing ERC-2535 Diamond Proxy contracts. It provides a pluggable deployment-strategy system, automatic function selector management, configuration-driven facet versioning, and ABI tooling.

Package manager: this project uses Yarn 4 (packageManager: [email protected]). The examples below use yarn. npm/pnpm work for consuming the published package but the repo scripts assume Yarn.

✨ Key Features

🏗️ Complete Diamond Implementation

  • Full ERC-2535 Diamond Proxy Standard support
  • Modular facet architecture with automated function selector management
  • Selector collision detection and resolution
  • State management and validation

🔄 Deployment Management

  • Strategy Pattern: pluggable deployment strategies (Local, RPC, Base, Defender)
  • Version Control: configuration-driven versioning for facets and protocols
  • Upgrade Automation: DiamondDeployer detects an existing deployment and performs an upgrade instead of a fresh deploy
  • Post-deployment Callbacks: run custom initialization after a cut

🏭 Production Ready

  • Repository Pattern: pluggable persistence (file-based out of the box)
  • Configuration Management: JSON configuration with Zod validation
  • ABI Tooling: combined Diamond ABI generation, preview, compare, and validate
  • Comprehensive Testing: unit and integration test suites

🚀 Quick Start

Prerequisites

  • Node.js ≥ 18
  • Yarn ≥ 4 (for developing this repo; npm/pnpm work for consuming the published package)

Installation

yarn add @diamondslab/diamonds
# or
npm install @diamondslab/diamonds

# peer deps (if not already present)
yarn add --dev hardhat @nomicfoundation/hardhat-ethers ethers

Entry points

The package exposes the following entry points (exports in package.json):

| Entry point | Purpose | | ------------------------------------ | ------------------------------------------------------------------------------------------------- | | @diamondslab/diamonds | Main entry — everything documented below is exported here | | @diamondslab/diamonds/core | Core classes only (Diamond, DiamondDeployer, DeploymentManager, CallbackManager) | | @diamondslab/diamonds/dist/* | Back-compat deep imports, e.g. @diamondslab/diamonds/dist/repositories/FileDeploymentRepository | | @diamondslab/diamonds/package.json | Package metadata (for tooling) |

Prefer the root entry point for new code; the dist/* subpaths exist so older deep imports keep working. Source maps and declaration maps are not shipped.

Basic Usage

Everything is exported from the package root (@diamondslab/diamonds):

import {
  Diamond,
  DiamondDeployer,
  FileDeploymentRepository,
  LocalDeploymentStrategy,
} from "@diamondslab/diamonds";
import { ethers } from "hardhat";

// Diamond configuration
const config = {
  diamondName: "MyDiamond",
  networkName: "localhost",
  chainId: 31337,
  deploymentsPath: "./diamonds",
  contractsPath: "./contracts",
};

// Set up diamond + deployment components
const repository = new FileDeploymentRepository(config);
const diamond = new Diamond(config, repository);

// Provide a provider and signer
diamond.setProvider(ethers.provider);
const [signer] = await ethers.getSigners();
diamond.setSigner(signer);

// Deploy using the local strategy (verbose logging on)
const strategy = new LocalDeploymentStrategy(true);
const deployer = new DiamondDeployer(diamond, strategy);

// Deploys if new, upgrades if already deployed
await deployer.deployDiamond();

📋 Project Structure

src/
├── core/                      # Core classes
│   ├── Diamond.ts             # Diamond state + selector registry
│   ├── DiamondDeployer.ts     # Deploy/upgrade orchestration
│   ├── DeploymentManager.ts   # Deployment lifecycle
│   └── CallbackManager.ts     # Post-deployment callbacks
├── strategies/                # Deployment strategies
│   ├── DeploymentStrategy.ts  # Strategy interface
│   ├── BaseDeploymentStrategy.ts
│   ├── LocalDeploymentStrategy.ts
│   ├── RPCDeploymentStrategy.ts
│   └── OZDefenderDeploymentStrategy.ts   # legacy (see note below)
├── repositories/              # Data persistence
│   ├── DeploymentRepository.ts
│   ├── FileDeploymentRepository.ts
│   └── jsonFileHandler.ts
├── schemas/                   # Zod validation schemas
├── types/                     # TypeScript definitions
├── utils/                     # Utilities (ABI generation, loupe, selectors, …)
└── cli/                       # `diamond-abi` CLI

🔧 Configuration

Diamond Configuration

Create a diamond configuration file (e.g. myDiamond.config.json):

{
  "protocolVersion": 1.0,
  "protocolInitFacet": "MyProtocolFacet",
  "facets": {
    "DiamondCutFacet": {
      "priority": 10,
      "versions": { "1.0": {} }
    },
    "DiamondLoupeFacet": {
      "priority": 20,
      "versions": { "1.0": {} }
    },
    "MyCustomFacet": {
      "priority": 30,
      "versions": {
        "1.0": {
          "deployInit": "initialize()",
          "upgradeInit": "upgradeToV1()",
          "callbacks": ["postDeployCallback"],
          "deployInclude": ["0x12345678"],
          "deployExclude": ["0x87654321"]
        }
      }
    }
  }
}

Environment Configuration

# Network Configuration
NETWORK_NAME=sepolia
CHAIN_ID=11155111
RPC_URL=https://sepolia.infura.io/v3/YOUR_KEY

# OpenZeppelin Defender (only for the legacy Defender strategy)
DEFENDER_API_KEY=your_api_key
DEFENDER_API_SECRET=your_api_secret
DEFENDER_RELAYER_ADDRESS=0x...
DEFENDER_SAFE_ADDRESS=0x...

# Deployment Options
VERBOSE_DEPLOYMENT=true

🔄 Deployment Strategies

All strategies extend BaseDeploymentStrategy and accept an optional verbose flag. Pass a strategy instance to DiamondDeployer.

Local Strategy

For development and testing against a local/forked node:

import { LocalDeploymentStrategy } from "@diamondslab/diamonds";

const strategy = new LocalDeploymentStrategy(true); // verbose

RPC Strategy

For deploying through a configured RPC endpoint / signer:

import { RPCDeploymentStrategy } from "@diamondslab/diamonds";

const strategy =
  new RPCDeploymentStrategy(/* see RPCDeploymentStrategy options */);

Custom Strategy

Implement your own by extending BaseDeploymentStrategy and overriding the protected task hooks:

import { BaseDeploymentStrategy, Diamond } from "@diamondslab/diamonds";

export class CustomDeploymentStrategy extends BaseDeploymentStrategy {
  protected async deployDiamondTasks(diamond: Diamond): Promise<void> {
    // Custom deployment logic
  }

  protected async performDiamondCutTasks(diamond: Diamond): Promise<void> {
    // Custom diamond cut logic
  }
}

OpenZeppelin Defender Strategy (legacy)

⚠️ Deprecated / legacy. OZDefenderDeploymentStrategy is being phased out and is not recommended for new work. It remains exported for backward compatibility. Prefer LocalDeploymentStrategy / RPCDeploymentStrategy or a custom strategy.

import { OZDefenderDeploymentStrategy } from "@diamondslab/diamonds";

const strategy = new OZDefenderDeploymentStrategy(
  process.env.DEFENDER_API_KEY!,
  process.env.DEFENDER_API_SECRET!,
  process.env.DEFENDER_RELAYER_ADDRESS!,
  false, // auto-approve
  process.env.DEFENDER_SAFE_ADDRESS!,
  "Safe",
);

📊 Advanced Features

Version Management

Facets are versioned in the configuration; upgrades declare which prior versions they apply from:

{
  "facets": {
    "MyFacet": {
      "priority": 100,
      "versions": {
        "1.0": { "deployInit": "initialize()", "upgradeInit": "upgradeToV1()" },
        "2.0": {
          "deployInit": "initialize()",
          "upgradeInit": "upgradeToV2()",
          "fromVersions": [1.0]
        }
      }
    }
  }
}

Function Selector Management

Automatic selector management with collision detection:

  • Priority-based resolution: higher-priority facets take precedence
  • Include/Exclude lists: fine-grained selector control (deployInclude / deployExclude)
  • Collision detection: automatic detection and resolution of selector conflicts
  • Orphaned selector prevention: validation guards against bad cuts

Post-Deployment Callbacks

// In your callbacks directory
export async function postDeployCallback(args: CallbackArgs) {
  const { diamond } = args;
  console.log(`Post-deployment callback for ${diamond.diamondName}`);
  // Custom post-deployment logic
}

💎 Diamond ABI Tooling

This package ships a diamond-abi CLI for working with the combined Diamond ABI.

# Generate the combined ABI for a deployed diamond (requires a Hardhat project)
npx diamond-abi generate --diamond MyDiamond --network localhost

# Preview the ABI changes implied by planned cuts (requires a Hardhat project)
npx diamond-abi preview --diamond MyDiamond --verbose

# Compare two ABI files (no chain / Hardhat needed)
npx diamond-abi compare old-abi.json new-abi.json

# Validate an ABI artifact file (no chain / Hardhat needed)
npx diamond-abi validate diamond-abi.json

generate and preview connect to a chain and load your project's Hardhat config (run them inside a Hardhat project). compare and validate operate on ABI JSON files and run standalone. Run npx diamond-abi <command> --help for all options.

The same combined ABI can also be produced programmatically via generateDiamondAbi / previewDiamondAbi from @diamondslab/diamonds.

📖 Examples

Basic Diamond Deployment

import {
  Diamond,
  DiamondDeployer,
  FileDeploymentRepository,
  LocalDeploymentStrategy,
} from "@diamondslab/diamonds";
import { ethers } from "hardhat";

async function deployBasicDiamond() {
  const config = {
    diamondName: "BasicDiamond",
    networkName: "localhost",
    chainId: 31337,
    deploymentsPath: "./diamonds",
    contractsPath: "./contracts",
  };

  const repository = new FileDeploymentRepository(config);
  const diamond = new Diamond(config, repository);

  diamond.setProvider(ethers.provider);
  const [signer] = await ethers.getSigners();
  diamond.setSigner(signer);

  const strategy = new LocalDeploymentStrategy();
  const deployer = new DiamondDeployer(diamond, strategy);

  await deployer.deployDiamond();
  console.log("Diamond deployed successfully!");
}

Multi-Facet Upgrade

async function performUpgrade(
  diamond: Diamond,
  repository: FileDeploymentRepository,
) {
  // Update configuration for the new version
  const config = repository.loadDeployConfig();
  config.protocolVersion = 2.0;

  // Add a new facet
  config.facets.NewFeatureFacet = {
    priority: 150,
    versions: {
      "2.0": { deployInit: "initialize()", callbacks: ["setupNewFeature"] },
    },
  };

  // Upgrade an existing facet
  config.facets.ExistingFacet.versions["2.0"] = {
    upgradeInit: "upgradeToV2()",
    fromVersions: [1.0],
  };

  repository.saveDeployConfig(config);

  // DiamondDeployer detects the existing deployment and performs the upgrade
  const deployer = new DiamondDeployer(diamond, new LocalDeploymentStrategy());
  await deployer.deployDiamond();
}

🔍 Monitoring and Debugging

Inspect Function Selectors

import { getSighash } from "@diamondslab/diamonds";

const selector = getSighash("transfer(address,uint256)");
console.log("Selector:", selector);

console.log("Registered:", diamond.isFunctionSelectorRegistered(selector));

Compare On-Chain vs. Local State

import { diffDeployedFacets } from "@diamondslab/diamonds";
import { ethers } from "hardhat";

const deployedData = diamond.getDeployedDiamondData();
console.log("Diamond address:", deployedData.DiamondAddress);
console.log("Deployed facets:", Object.keys(deployedData.DeployedFacets ?? {}));

// Returns true when on-chain facets match the local deployment record
const isConsistent = await diffDeployedFacets(
  deployedData,
  ethers.provider,
  true,
);

🧪 Testing & Development

Run from the package directory:

yarn install          # install dependencies (Yarn 4)
yarn build            # compile TypeScript to dist/
yarn test             # run the Hardhat test suite
yarn test:unit        # unit tests only
yarn test:integration # integration tests only
yarn test:coverage    # tests with coverage
yarn lint             # lint

🔐 Security Considerations

  1. Use multi-signature wallets for mainnet deployments.
  2. Test upgrades on a testnet/fork first.
  3. Verify contracts on the relevant block explorer.
  4. Apply role-based access control to privileged diamond functions.
  5. Never commit secrets — deployment records may contain addresses/keys and are gitignored.

🤝 Contributing

Contributions are welcome. See CONTRIBUTING.md for the full workflow, and open an issue or pull request on GitHub.

git clone https://github.com/DiamondsLab/diamonds.git
cd diamonds
yarn install
yarn test
yarn build
yarn lint

Coding Standards

  • Follow the existing TypeScript style
  • Use Conventional Commits
  • Add tests for new functionality
  • Update documentation for new features

📄 License

MIT — see the LICENSE file.

🙏 Acknowledgments

📞 Support


Built with ❤️ for the Ethereum ecosystem by DiamondsLab