Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1d3000b
refactor: make simulator chain-agnostic with pluggable chain family a…
Fletch153 Apr 9, 2026
c004b88
chore: audit refactor for parity and abstraction
Fletch153 Apr 15, 2026
cbf498d
test: add EVM chain family unit tests
Fletch153 Apr 15, 2026
329c9ad
refactor: decouple TriggerParams from EVM-specific fields
Fletch153 Apr 15, 2026
b9a4f58
refactor: decouple CLI flags from simulator core into chain family re…
Fletch153 Apr 16, 2026
bf0e64c
refactor: rename ChainWriteEVMGasLimit to ChainWriteGasLimit
Fletch153 Apr 16, 2026
872363d
fix: suppress ui.Success messages on non-interactive trigger path
Fletch153 Apr 16, 2026
4583293
refactor: rename ChainFamily to ChainType throughout simulator
Fletch153 Apr 16, 2026
c2f2f1b
Merge remote-tracking branch 'origin/main' into plex-2751-modularise-…
Fletch153 Apr 16, 2026
d68b63e
fix(lint): resolve golangci-lint errors
Fletch153 Apr 16, 2026
2c25107
fix(lint): gofmt whitespace in chain/evm test files
Fletch153 Apr 16, 2026
e3cb7e5
fix(lint): rename runRPCHealthCheck to avoid confusing-naming; annota…
Fletch153 Apr 16, 2026
086ee93
fix(lint): inline comment on blank import to satisfy goimports
Fletch153 Apr 16, 2026
3916398
refactor: address review feedback on chain family registry
Fletch153 Apr 16, 2026
47ff82f
Merge remote-tracking branch 'origin/main' into plex-2751-modularise-…
Fletch153 Apr 17, 2026
cfed4e5
fix: restore disableEngineLimits call site lost in merge
Fletch153 Apr 17, 2026
932a825
chore: restore getHTTPTriggerPayload comments to match main
Fletch153 Apr 17, 2026
ce7adf3
refactor: rename manualTriggers to triggerCaps to match main
Fletch153 Apr 17, 2026
49ec92a
refactor: rename triggerCaps to manualTriggerCaps for clarity
Fletch153 Apr 17, 2026
bc305e8
refactor: drop redundant ChainTypeClients presence check
Fletch153 Apr 17, 2026
c71c91e
chore: restore trigger start error message to match main
Fletch153 Apr 17, 2026
9462cb4
refactor: restore service append order + trigger caps error message
Fletch153 Apr 17, 2026
683fd4d
refactor: tighten chain capability wiring
Fletch153 Apr 17, 2026
8fd4a16
style(test): strip section divider comments from evm test files
Fletch153 Apr 17, 2026
18ab169
test: prune low-signal tests and consolidate test files
Fletch153 Apr 17, 2026
f55d8ae
test: drop misleading ExecuteTrigger_WrongTriggerDataType test
Fletch153 Apr 17, 2026
f653c97
test: remove unused captureStdout helper
Fletch153 Apr 17, 2026
8f738e2
style: fix gci alignment in simulate.go Inputs literal
Fletch153 Apr 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 9 additions & 69 deletions cmd/workflow/simulate/capabilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,13 @@ package simulate

import (
"context"
"crypto/ecdsa"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"

chaintype "github.com/smartcontractkit/chainlink-common/keystore/corekeys"
corekeys "github.com/smartcontractkit/chainlink-common/keystore/corekeys"
"github.com/smartcontractkit/chainlink-common/keystore/corekeys/ocr2key"
confhttpserver "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/actions/confidentialhttp/server"
httpserver "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/actions/http/server"
evmserver "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/chain-capabilities/evm/server"
consensusserver "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/consensus/server"
crontrigger "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/triggers/cron/server"
httptrigger "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/triggers/http/server"
Expand All @@ -21,79 +18,34 @@ import (
"github.com/smartcontractkit/chainlink/v2/core/capabilities/fakes"
)

type ManualTriggerCapabilitiesConfig struct {
Clients map[uint64]*ethclient.Client
Forwarders map[uint64]common.Address
PrivateKey *ecdsa.PrivateKey
}

// ManualTriggers holds chain-agnostic trigger services used in simulation.
type ManualTriggers struct {
ManualCronTrigger *fakes.ManualCronTriggerService
ManualHTTPTrigger *fakes.ManualHTTPTriggerService
ManualEVMChains map[uint64]*fakes.FakeEVMChain
}

func NewManualTriggerCapabilities(
ctx context.Context,
lggr logger.Logger,
registry *capabilities.Registry,
cfg ManualTriggerCapabilitiesConfig,
dryRunChainWrite bool,
limits *SimulationLimits,
) (*ManualTriggers, error) {
// Cron
// NewManualTriggerCapabilities creates and registers cron and HTTP trigger capabilities.
// These are chain-agnostic and shared across all chain types.
func NewManualTriggerCapabilities(ctx context.Context, lggr logger.Logger, registry *capabilities.Registry) (*ManualTriggers, error) {
manualCronTrigger := fakes.NewManualCronTriggerService(lggr)
manualCronTriggerServer := crontrigger.NewCronServer(manualCronTrigger)
if err := registry.Add(ctx, manualCronTriggerServer); err != nil {
return nil, err
}

// HTTP
manualHTTPTrigger := fakes.NewManualHTTPTriggerService(lggr)
manualHTTPTriggerServer := httptrigger.NewHTTPServer(manualHTTPTrigger)
if err := registry.Add(ctx, manualHTTPTriggerServer); err != nil {
return nil, err
}

// EVM
evmChains := make(map[uint64]*fakes.FakeEVMChain)
for sel, client := range cfg.Clients {
fwd, ok := cfg.Forwarders[sel]
if !ok {
lggr.Infow("Forwarder not found for chain", "selector", sel)
continue
}

evm := fakes.NewFakeEvmChain(
lggr,
client,
cfg.PrivateKey,
fwd,
sel,
dryRunChainWrite,
)

// Wrap with limits enforcement if limits are enabled
var evmCap evmserver.ClientCapability = evm
if limits != nil {
evmCap = NewLimitedEVMChain(evm, limits)
}

evmServer := evmserver.NewClientServer(evmCap)
if err := registry.Add(ctx, evmServer); err != nil {
return nil, err
}

evmChains[sel] = evm
}

return &ManualTriggers{
ManualCronTrigger: manualCronTrigger,
ManualHTTPTrigger: manualHTTPTrigger,
ManualEVMChains: evmChains,
}, nil
}

// Start starts cron and HTTP trigger services.
func (m *ManualTriggers) Start(ctx context.Context) error {
err := m.ManualCronTrigger.Start(ctx)
if err != nil {
Expand All @@ -105,16 +57,10 @@ func (m *ManualTriggers) Start(ctx context.Context) error {
return err
}

// Start all configured EVM chains
for _, evm := range m.ManualEVMChains {
if err := evm.Start(ctx); err != nil {
return err
}
}

return nil
}

// Close closes cron and HTTP trigger services.
func (m *ManualTriggers) Close() error {
err := m.ManualCronTrigger.Close()
if err != nil {
Expand All @@ -126,16 +72,10 @@ func (m *ManualTriggers) Close() error {
return err
}

// Close all EVM chains
for _, evm := range m.ManualEVMChains {
if err := evm.Close(); err != nil {
return err
}
}
return nil
}

// NewFakeCapabilities builds faked capabilities, then registers them with the capability registry.
// NewFakeActionCapabilities builds faked capabilities, then registers them with the capability registry.
func NewFakeActionCapabilities(ctx context.Context, lggr logger.Logger, registry *capabilities.Registry, secretsPath string, limits *SimulationLimits) ([]services.Service, error) {
caps := make([]services.Service, 0)

Expand All @@ -144,7 +84,7 @@ func NewFakeActionCapabilities(ctx context.Context, lggr logger.Logger, registry
nSigners := 4
signers := []ocr2key.KeyBundle{}
for i := 0; i < nSigners; i++ {
signer := ocr2key.MustNewInsecure(fakes.SeedForKeys(), chaintype.EVM)
signer := ocr2key.MustNewInsecure(fakes.SeedForKeys(), corekeys.EVM)
lggr.Infow("Generated new consensus signer", "address", common.BytesToAddress(signer.PublicKey()))
signers = append(signers, signer)
}
Expand Down
88 changes: 88 additions & 0 deletions cmd/workflow/simulate/chain/evm/capabilities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package evm

import (
"context"
"crypto/ecdsa"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"

evmserver "github.com/smartcontractkit/chainlink-common/pkg/capabilities/v2/chain-capabilities/evm/server"
"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink/v2/core/capabilities"
"github.com/smartcontractkit/chainlink/v2/core/capabilities/fakes"
)

// EVMChainCapabilities holds the EVM chain capability servers created for simulation.
type EVMChainCapabilities struct {
EVMChains map[uint64]*fakes.FakeEVMChain
}

// NewEVMChainCapabilities creates EVM chain capability servers and registers them
// with the capability registry. Cron and HTTP triggers are not created here — they
// are chain-agnostic and managed by the simulate command directly.
func NewEVMChainCapabilities(
ctx context.Context,
lggr logger.Logger,
registry *capabilities.Registry,
clients map[uint64]*ethclient.Client,
forwarders map[uint64]string,
privateKey *ecdsa.PrivateKey,
dryRunChainWrite bool,
limits EVMChainLimits,
) (*EVMChainCapabilities, error) {
evmChains := make(map[uint64]*fakes.FakeEVMChain)
for sel, client := range clients {
fwdStr, ok := forwarders[sel]
if !ok {
lggr.Infow("Forwarder not found for chain", "selector", sel)
continue
}

evm := fakes.NewFakeEvmChain(
lggr,
client,
privateKey,
common.HexToAddress(fwdStr),
sel,
dryRunChainWrite,
)

// Wrap with limits enforcement if limits are provided
var evmCap evmserver.ClientCapability = evm
if limits != nil {
evmCap = NewLimitedEVMChain(evm, limits)
}

evmServer := evmserver.NewClientServer(evmCap)
if err := registry.Add(ctx, evmServer); err != nil {
return nil, err
}

evmChains[sel] = evm
}

return &EVMChainCapabilities{
EVMChains: evmChains,
}, nil
}

// Start starts all configured EVM chains.
func (c *EVMChainCapabilities) Start(ctx context.Context) error {
for _, evm := range c.EVMChains {
if err := evm.Start(ctx); err != nil {
return err
}
}
return nil
}

// Close closes all EVM chains.
func (c *EVMChainCapabilities) Close() error {
for _, evm := range c.EVMChains {
if err := evm.Close(); err != nil {
return err
}
}
return nil
}
Loading
Loading