chainlink-deployments-framework

module
v0.49.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 22, 2025 License: MIT

README

Chainlink Deployments Framework



This repository contains the Chainlink Deployments Framework, a comprehensive set of libraries that enables developers to build, manage, and execute(in future) deployment changesets. The framework includes the Operations API and Datastore API.

Usage

$ go get github.com/smartcontractkit/chainlink-deployments-framework

Imports

import (
  "github.com/smartcontractkit/chainlink-deployments-framework/deployment" // for writing changesets (migrated from chainlink/deployments
  "github.com/smartcontractkit/chainlink-deployments-framework/operations" // for operations API
  "github.com/smartcontractkit/chainlink-deployments-framework/datastore" // for datastore API
)

Development

Installing Dependencies

Install the required tools using asdf:

asdf install

Linting

task lint

Testing

task test

How to add a new Chain

To add a new chain to the framework, follow these steps:

  1. Create the chain structure and implementation:

    • Create a new directory under chain/ with the name of your chain (e.g., chain/newchain/).
    • Create a new Chain struct that embeds the ChainMetadata struct
    • See the Sui or TON implementations as reference examples. EVM, Solana, and Aptos chains follow a different implementation pattern as they were added before CLDF.
  2. Implement chain providers:

    • Create a provider/ subdirectory under your chain directory (e.g., chain/newchain/provider/)
    • Implement one or more provider types that satisfy the chain.Provider interface:
      type Provider interface {
          Initialize(ctx context.Context) (BlockChain, error)
          Name() string
          ChainSelector() uint64
          BlockChain() BlockChain
      }
      
    • Common provider types to implement:
      • RPC Provider: Connects to a live blockchain node via RPC
      • Simulated Provider: Creates an in-memory simulated chain for testing (if needed)
      • CTF Provider: Connects to Chainlink Testing Framework environments (if needed)

    Example RPC provider implementation:

    package provider
    
    import (
        "context"
        "errors"
        "fmt"
    
        "github.com/smartcontractkit/chainlink-deployments-framework/chain"
        "github.com/smartcontractkit/chainlink-deployments-framework/chain/newchain"
    )
    
    // RPCChainProviderConfig holds the configuration for the RPC provider
    type RPCChainProviderConfig struct {
        RPCURL            string
        DeployerSignerGen SignerGenerator // Your chain-specific signer
    }
    
    func (c RPCChainProviderConfig) validate() error {
        if c.RPCURL == "" {
            return errors.New("rpc url is required")
        }
        if c.DeployerSignerGen == nil {
            return errors.New("deployer signer generator is required")
        }
        return nil
    }
    
    // Ensure provider implements the interface
    var _ chain.Provider = (*RPCChainProvider)(nil)
    
    type RPCChainProvider struct {
        selector uint64
        config   RPCChainProviderConfig
        chain    *newchain.Chain
    }
    
    func NewRPCChainProvider(selector uint64, config RPCChainProviderConfig) *RPCChainProvider {
        return &RPCChainProvider{
            selector: selector,
            config:   config,
        }
    }
    
    func (p *RPCChainProvider) Initialize(ctx context.Context) (chain.BlockChain, error) {
        if p.chain != nil {
            return p.chain, nil // Already initialized
        }
    
        if err := p.config.validate(); err != nil {
            return nil, fmt.Errorf("failed to validate config: %w", err)
        }
    
        // Initialize your chain client
        client, err := newchain.NewClient(p.config.RPCURL)
        if err != nil {
            return nil, fmt.Errorf("failed to create client: %w", err)
        }
    
        // Generate deployer signer
        signer, err := p.config.DeployerSignerGen.Generate()
        if err != nil {
            return nil, fmt.Errorf("failed to generate signer: %w", err)
        }
    
        p.chain = &newchain.Chain{
            Selector: p.selector,
            Client:   client,
            Signer:   signer,
            URL:      p.config.RPCURL,
        }
    
        return *p.chain, nil
    }
    
    func (p *RPCChainProvider) Name() string {
        return "NewChain RPC Provider"
    }
    
    func (p *RPCChainProvider) ChainSelector() uint64 {
        return p.selector
    }
    
    func (p *RPCChainProvider) BlockChain() chain.BlockChain {
        return *p.chain
    }
    
  3. Add environment configuration bindings:

    • Update engine/cld/config/env/config.go:
      • Add a new config struct for your chain (e.g., NewChainConfig):
        // NewChainConfig is the configuration for the NewChain chains.
        //
        // WARNING: This data type contains sensitive fields and should not be logged or set in file
        // configuration.
        type NewChainConfig struct {
            DeployerKey string `mapstructure:"deployer_key" yaml:"deployer_key"` // Secret: The private key of the deployer account.
            // Add any other chain-specific configuration fields
        }
        
      • Add the new config to the OnchainConfig struct:
        type OnchainConfig struct {
            // ... existing fields ...
            NewChain NewChainConfig `mapstructure:"newchain" yaml:"newchain"`
        }
        
      • Add environment variable bindings in the envBindings map:
        envBindings = map[string][]string{
            // ... existing bindings ...
            "onchain.newchain.deployer_key": {"ONCHAIN_NEWCHAIN_DEPLOYER_KEY"},
            // Add other bindings as needed
        }
        
  4. Create chain loader in the CLD engine:

    • Update engine/cld/chains/chains.go:

      • Add a new chain loader struct and methods:

        // chainLoaderNewChain implements the ChainLoader interface for NewChain.
        type chainLoaderNewChain struct {
            *baseChainLoader
        }
        
        // newChainLoaderNewChain creates a new chain loader for NewChain.
        func newChainLoaderNewChain(
            networks *cfgnet.Config, cfg cfgenv.OnchainConfig,
        ) *chainLoaderNewChain {
            return &chainLoaderNewChain{
                baseChainLoader: newBaseChainLoader(networks, cfg),
            }
        }
        
        // Load loads a NewChain Chain for a selector.
        func (l *chainLoaderNewChain) Load(ctx context.Context, selector uint64) (fchain.BlockChain, error) {
            network, err := l.getNetwork(selector)
            if err != nil {
                return nil, err
            }
        
            rpcURL := network.RPCs[0].HTTPURL
            c, err := newchainprov.NewRPCChainProvider(selector,
                newchainprov.RPCChainProviderConfig{
                    RPCURL:            rpcURL,
                    DeployerSignerGen: newchainprov.AccountGenPrivateKey(l.cfg.NewChain.DeployerKey),
                },
            ).Initialize(ctx)
            if err != nil {
                return nil, fmt.Errorf("failed to initialize NewChain chain %d: %w", selector, err)
            }
        
            return c, nil
        }
        
      • Add the loader to the newChainLoaders function with appropriate configuration checks:

        func newChainLoaders(...) map[string]ChainLoader {
            // ... existing loaders ...
        
            if cfg.NewChain.DeployerKey != "" {
                loaders[chainsel.FamilyNewChain] = newChainLoaderNewChain(networks, cfg)
            } else {
                lggr.Warn("Skipping NewChain chains, no private key found in secrets")
            }
        
            return loaders
        }
        
      • Add interface compliance verification:

        var (
            // ... existing verifications ...
            _ ChainLoader = &chainLoaderNewChain{}
        )
        
  5. Update chain registry:

    • Update chain/blockchain.go:
      • Add var _ BlockChain = newchain.Chain{} at the top to verify interface compliance
      • Create a new getter method (e.g., NewChainChains()) that returns map[uint64]newchain.Chain (e.g., NewSuiChains())
  6. Write comprehensive tests:

    • Test chain instantiation
    • Test all interface methods
    • Test the getter method in BlockChains
    • Test provider initialization and chain creation
    • Test provider interface compliance with var _ chain.Provider = (*YourProvider)(nil)
    • Test chain loader functionality

Using Providers: Once you've implemented a provider, users can create and initialize chains like this:

// Create provider with configuration
provider := provider.NewRPCChainProvider(chainSelector, provider.RPCChainProviderConfig{
    RPCURL:            "https://your-chain-rpc-url.com",
    DeployerSignerGen: yourSignerGenerator,
})

// Initialize the chain
ctx := context.Background()
blockchain, err := provider.Initialize(ctx)
if err != nil {
    return fmt.Errorf("failed to initialize chain: %w", err)
}

Contributing

For instructions on how to contribute to chainlink-deployments-framework and the release process, see CONTRIBUTING.md

Releasing

For instructions on how to release chainlink-deployments-framework, see RELEASE.md

Directories

Path Synopsis
Package chain provides the core blockchain abstraction layer for the Chainlink Deployments Framework, supporting multiple blockchain families through a unified interface.
Package chain provides the core blockchain abstraction layer for the Chainlink Deployments Framework, supporting multiple blockchain families through a unified interface.
evm
evm/provider
Package provider contains EVM chain providers for the Chainlink Deployments Framework.
Package provider contains EVM chain providers for the Chainlink Deployments Framework.
sui
ton
utils/addrconv
Package addrconv provides utilities for converting blockchain addresses to bytes across different chain families.
Package addrconv provides utilities for converting blockchain addresses to bytes across different chain families.
changeset
engine
cld/chains
Package chains provides multi-blockchain chain loading and management capabilities for the Chainlink Deployments Framework (CLD) engine.
Package chains provides multi-blockchain chain loading and management capabilities for the Chainlink Deployments Framework (CLD) engine.
cld/legacy
Package legacy contains legacy code and components that are maintained for backward compatibility but may be replaced with alternative implementations in the future.
Package legacy contains legacy code and components that are maintained for backward compatibility but may be replaced with alternative implementations in the future.
cld/legacy/cli
Package cli provides a base struct for creating CLI applications using Cobra.
Package cli provides a base struct for creating CLI applications using Cobra.
cld/legacy/cli/commands
Package commands contains common commands that can be injected into each domain's CLI application.
Package commands contains common commands that can be injected into each domain's CLI application.
test/environment
Package environment provides configuration options for loading test environments with various blockchain networks and components.
Package environment provides configuration options for loading test environments with various blockchain networks and components.
test/internal/testutils
Package testutils provides utility functions for testing the test engine.
Package testutils provides utility functions for testing the test engine.
test/onchain
Package onchain provides chain loaders for testing infrastructure.
Package onchain provides chain loaders for testing infrastructure.
test/runtime
Package runtime provides an execution environment for executing changesets in tests.
Package runtime provides an execution environment for executing changesets in tests.
Package experimental contains experimental features and components that are being trialed before wider rollout across the codebase.
Package experimental contains experimental features and components that are being trialed before wider rollout across the codebase.
proposalutils
Package proposalutils is copied from https://github.com/smartcontractkit/chainlink/blob/c2074f6d70cdf9164f15f4be3f7de8a8427919af/deployment/common/proposalutils/analyze.go#L1-L1 This is a temporary location.
Package proposalutils is copied from https://github.com/smartcontractkit/chainlink/blob/c2074f6d70cdf9164f15f4be3f7de8a8427919af/deployment/common/proposalutils/analyze.go#L1-L1 This is a temporary location.
internal
Package offchain provides client abstractions and provider interfaces for interacting with off-chain services in the Chainlink Deployments Framework ecosystem.
Package offchain provides client abstractions and provider interfaces for interacting with off-chain services in the Chainlink Deployments Framework ecosystem.
internal/p2pkey
Package p2pkey contains code adapted from the Chainlink core node with minor modifications.
Package p2pkey contains code adapted from the Chainlink core node with minor modifications.
jd
Package jd provides a comprehensive framework for interacting with Job Distributor (JD) services in the Chainlink Deployments Framework ecosystem.
Package jd provides a comprehensive framework for interacting with Job Distributor (JD) services in the Chainlink Deployments Framework ecosystem.
ocr
Package operations provides the Operations API for managing and executing deployment operations in a structured, reliable, and traceable manner.
Package operations provides the Operations API for managing and executing deployment operations in a structured, reliable, and traceable manner.
optest
Package optest provides utilities for operations testing.
Package optest provides utilities for operations testing.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL