From dcd82187ff8dc1e2b7da956105d3726f6b8a0a15 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Wed, 22 Apr 2026 11:58:32 -0500 Subject: [PATCH 01/25] step 1, remove option for non-LOOP mode --- core/services/chainlink/relayer_factory.go | 59 ++++++++-------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index bd781717854..d0bdd4f8023 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -19,7 +19,6 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" evmtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/keys" - "github.com/smartcontractkit/chainlink-solana/pkg/solana" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -143,7 +142,7 @@ type SolanaFactoryConfig struct { } func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFactoryConfig) (map[types.RelayID]loop.Relayer, error) { - chainCfgs, ds := config.TOMLConfigs, config.DS + chainCfgs := config.TOMLConfigs solanaRelayers := make(map[types.RelayID]loop.Relayer) var solLggr = logger.Named(r.Logger, "Solana") @@ -164,43 +163,27 @@ func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFa } lggr := logger.Named(solLggr, relayID.ChainID) - - if cmdName := env.SolanaPlugin.Cmd.Get(); cmdName != "" { - // setup the solana relayer to be a LOOP - cfgTOML, err := toml.Marshal(struct { - Solana solcfg.TOMLConfig - }{Solana: *chainCfg}) - if err != nil { - return nil, fmt.Errorf("failed to marshal Solana configs: %w", err) - } - envVars, err := plugins.ParseEnvFile(env.SolanaPlugin.Env.Get()) - if err != nil { - return nil, fmt.Errorf("failed to parse Solana env file: %w", err) - } - solCmdFn, err := plugins.NewCmdFactory(r.Register, plugins.CmdConfig{ - ID: relayID.Name(), - Cmd: cmdName, - Env: envVars, - }) - if err != nil { - return nil, fmt.Errorf("failed to create Solana LOOP command: %w", err) - } - - solanaRelayers[relayID] = loop.NewRelayerService(lggr, r.GRPCOpts, solCmdFn, string(cfgTOML), ks, ksCSA, r.CapabilitiesRegistry) - } else { - // fallback to embedded chain - opts := solana.ChainOpts{ - Logger: lggr, - KeyStore: ks, - DS: ds, - } - - chain, err := solana.NewChain(chainCfg, opts) - if err != nil { - return nil, err - } - solanaRelayers[relayID] = relay.NewServerAdapter(solana.NewRelayer(lggr, chain, r.CapabilitiesRegistry)) + // setup the solana relayer to be a LOOP + cfgTOML, err := toml.Marshal(struct { + Solana solcfg.TOMLConfig + }{Solana: *chainCfg}) + if err != nil { + return nil, fmt.Errorf("failed to marshal Solana configs: %w", err) } + envVars, err := plugins.ParseEnvFile(env.SolanaPlugin.Env.Get()) + if err != nil { + return nil, fmt.Errorf("failed to parse Solana env file: %w", err) + } + solCmdFn, err := plugins.NewCmdFactory(r.Register, plugins.CmdConfig{ + ID: relayID.Name(), + Cmd: "chainlink-solana", + Env: envVars, + }) + if err != nil { + return nil, fmt.Errorf("failed to create Solana LOOP command: %w", err) + } + + solanaRelayers[relayID] = loop.NewRelayerService(lggr, r.GRPCOpts, solCmdFn, string(cfgTOML), ks, ksCSA, r.CapabilitiesRegistry) } return solanaRelayers, nil } From 557abdf43365a0bf9b34105d0cf0bbaf56dea72e Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Thu, 23 Apr 2026 17:30:06 -0500 Subject: [PATCH 02/25] do not use hard coded cmd --- core/services/chainlink/relayer_factory.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index d0bdd4f8023..a5a9184c18d 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -176,7 +176,7 @@ func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFa } solCmdFn, err := plugins.NewCmdFactory(r.Register, plugins.CmdConfig{ ID: relayID.Name(), - Cmd: "chainlink-solana", + Cmd: env.SolanaPlugin.Cmd.Get(), Env: envVars, }) if err != nil { From c6f0a3c4ba899e6c52e8c4c0164574e0aad78d19 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Thu, 23 Apr 2026 19:06:07 -0500 Subject: [PATCH 03/25] rm non-LOOPP solana e2e test --- .github/integration-in-memory-tests.yml | 32 ------------------------- 1 file changed, 32 deletions(-) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index ac12f7aab31..d3cf8915a4b 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -54,22 +54,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_EVM2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_EVM2Solana - path: integration-tests/smoke/ccip/ccip_messaging_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - runs_on_self_hosted: runs-on/cpu=8/ram=32/family=m6i+m5.*/spot=false/image=ubuntu24-full-x64/extras=s3-cache+tmpfs - triggers: - - PR Integration CCIP Tests - - Nightly Integration CCIP Tests - test_cmd: | - gotestsum \ - --junitfile=/tmp/junit.xml \ - --jsonfile=/tmp/gotest.log \ - --format=github-actions \ - -- -v -run "Test_CCIPMessaging_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip - test_go_project_path: integration-tests - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_EVM2Solana_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go test_env_type: in-memory @@ -89,22 +73,6 @@ runner-test-matrix: test_env_vars: CL_SOLANA_CMD: chainlink-solana - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM - path: integration-tests/smoke/ccip/ccip_messaging_test.go - test_env_type: in-memory - runs_on: ubuntu-latest - runs_on_self_hosted: runs-on/cpu=8/ram=32/family=m6i+m5.*/spot=false/image=ubuntu24-full-x64/extras=s3-cache+tmpfs - triggers: - - PR Integration CCIP Tests - - Nightly Integration CCIP Tests - test_cmd: | - gotestsum \ - --junitfile=/tmp/junit.xml \ - --jsonfile=/tmp/gotest.log \ - --format=github-actions \ - -- -v -run "Test_CCIPMessaging_Solana2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip - test_go_project_path: integration-tests - - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go test_env_type: in-memory From 0bd92fd7c5504e3bf4e91d08dfba609335116e06 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Thu, 23 Apr 2026 20:42:48 -0500 Subject: [PATCH 04/25] update CI --- .github/integration-in-memory-tests.yml | 39 +++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index d3cf8915a4b..e4bce4ad4ac 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -417,6 +417,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseUncurseAptos path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -466,6 +469,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -481,6 +487,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -496,6 +505,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurse path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -528,6 +540,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -544,6 +559,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseConfigValidate path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -560,6 +578,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseConfigValidate$" -timeout 20m -count=1 -parallel=2 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseNoConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -575,6 +596,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseNoConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -590,6 +614,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesSolana path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -605,6 +632,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanesSolana$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesGlobalOnly path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -620,6 +650,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanesGlobalOnly$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesLaneOnlyOnSource path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -635,6 +668,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseOneConnectedLanesLaneOnlyOnSource$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseForceOption path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -651,6 +687,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurseForceOption$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_disable_lane_test.go:* path: integration-tests/smoke/ccip/ccip_disable_lane_test.go From 2dc6c1bc139ac78494173b6df4a8930f07d38a65 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Fri, 24 Apr 2026 11:15:24 -0500 Subject: [PATCH 05/25] add Solana loop for failing test --- .github/integration-in-memory-tests.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index e4bce4ad4ac..5af678d470c 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -367,6 +367,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_token_transfer_test.go:*_LOOPP path: integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -453,6 +456,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNCurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go From ca14ec08a95bad92995ef6b98fb9e14aaaf04a3d Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Fri, 24 Apr 2026 16:09:19 -0500 Subject: [PATCH 06/25] refactor solana core test into integration with LOOP plugin --- .github/integration-in-memory-tests.yml | 3 + core/cmd/chains_commands_test.go | 22 -- core/cmd/node_commands_test.go | 70 ------ core/cmd/shell_test.go | 13 +- ...solana_chains_commands_integration_test.go | 109 ++++++++ .../relayer_chain_interoperators_test.go | 75 ++---- core/services/chainlink/relayer_factory.go | 19 +- core/web/chains_controller_test.go | 217 ---------------- ...lana_chains_controller_integration_test.go | 237 ++++++++++++++++++ 9 files changed, 384 insertions(+), 381 deletions(-) create mode 100644 core/cmd/solana_chains_commands_integration_test.go create mode 100644 core/web/solana_chains_controller_integration_test.go diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 5af678d470c..16021df2bad 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -530,6 +530,9 @@ runner-test-matrix: --format=github-actions \ -- -v -run "^TestRMNUncurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests + install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseMCMS path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go diff --git a/core/cmd/chains_commands_test.go b/core/cmd/chains_commands_test.go index c509cf7f5eb..645b0d4551e 100644 --- a/core/cmd/chains_commands_test.go +++ b/core/cmd/chains_commands_test.go @@ -7,14 +7,11 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" client2 "github.com/smartcontractkit/chainlink-evm/pkg/client" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -39,22 +36,3 @@ func TestShell_IndexEVMChains(t *testing.T) { assert.Equal(t, strconv.Itoa(client2.NullClientChainID), c.ID) assertTableRenders(t, r) } - -func TestShell_IndexSolanaChains(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - cfg := solcfg.TOMLConfig{ - ChainID: &id, - Enabled: ptr(true), - } - app := solanaStartNewApplication(t, &cfg) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) - chains := *r.Renders[0].(*cmd.ChainPresenters) - require.Len(t, chains, 1) - c := chains[0] - assert.Equal(t, id, c.ID) - assertTableRenders(t, r) -} diff --git a/core/cmd/node_commands_test.go b/core/cmd/node_commands_test.go index 53021b33216..3841d8ddece 100644 --- a/core/cmd/node_commands_test.go +++ b/core/cmd/node_commands_test.go @@ -10,12 +10,10 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" configtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -96,71 +94,3 @@ func TestShell_IndexEVMNodes(t *testing.T) { assert.Contains(t, renderLines[14], n2.State) } -func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].SetDefaults() - } - return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) -} - -func TestShell_IndexSolanaNodes(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - node1 := solcfg.Node{ - Name: ptr("first"), - URL: config.MustParseURL("https://solana1.example"), - } - node2 := solcfg.Node{ - Name: ptr("second"), - URL: config.MustParseURL("https://solana2.example"), - } - chain := solcfg.TOMLConfig{ - ChainID: &id, - Nodes: solcfg.Nodes{&node1, &node2}, - } - app := solanaStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 2) - n1 := nodes[0] - n2 := nodes[1] - assert.Equal(t, id, n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) - assert.Equal(t, id, n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 19) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n1.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n1.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[10], "Name") - assert.Contains(t, renderLines[10], n2.Name) - assert.Contains(t, renderLines[11], "Chain ID") - assert.Contains(t, renderLines[11], n2.ChainID) - assert.Contains(t, renderLines[12], "State") - assert.Contains(t, renderLines[12], n2.State) -} diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index c5a72a93a1d..b650f7ef138 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -410,12 +410,19 @@ func TestSetupSolanaRelayer(t *testing.T) { // not parallel; shared state t.Run("no plugin", func(t *testing.T) { - relayers, err := rf.NewSolana(ks, ksCSA, cfg) + // CL_SOLANA_CMD is unset here. Solana is LOOP-only, so NewSolana must fall back to + // env.SolanaPlugin.CmdDefault (chainlink-solana) and still register each enabled chain. + // Use an isolated registry so this case doesn't collide with the shared one used by + // the "plugin" and "plugin already registered" subtests below. + isoReg := plugins.NewTestLoopRegistry(lggr) + isoRF := chainlink.RelayerFactory{Logger: lggr, LoopRegistry: isoReg} + + relayers, err := isoRF.NewSolana(ks, ksCSA, cfg) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) - // no using plugin, so registry should be empty - require.Empty(t, reg.List()) + // the default plugin cmd is used, so the registry must contain one entry per chain + require.Len(t, isoReg.List(), nEnabledChains) }) t.Run("plugin", func(t *testing.T) { diff --git a/core/cmd/solana_chains_commands_integration_test.go b/core/cmd/solana_chains_commands_integration_test.go new file mode 100644 index 00000000000..6d262a96b0c --- /dev/null +++ b/core/cmd/solana_chains_commands_integration_test.go @@ -0,0 +1,109 @@ +//go:build integration + +package cmd_test + +import ( + "bytes" + "strings" + "testing" + + "github.com/pelletier/go-toml/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/config" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" +) + +func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { + for i := range cfgs { + cfgs[i].SetDefaults() + } + return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) +} + +func TestShell_IndexSolanaChains(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + cfg := solcfg.TOMLConfig{ + ChainID: &id, + Enabled: ptr(true), + } + app := solanaStartNewApplication(t, &cfg) + client, r := app.NewShellAndRenderer() + + require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) + chains := *r.Renders[0].(*cmd.ChainPresenters) + require.Len(t, chains, 1) + c := chains[0] + assert.Equal(t, id, c.ID) + assertTableRenders(t, r) +} + +func TestShell_IndexSolanaNodes(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + node1 := solcfg.Node{ + Name: ptr("first"), + URL: config.MustParseURL("https://solana1.example"), + } + node2 := solcfg.Node{ + Name: ptr("second"), + URL: config.MustParseURL("https://solana2.example"), + } + chain := solcfg.TOMLConfig{ + ChainID: &id, + Nodes: solcfg.Nodes{&node1, &node2}, + } + app := solanaStartNewApplication(t, &chain) + client, r := app.NewShellAndRenderer() + + require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.NodePresenters) + require.Len(t, nodes, 2) + n1 := nodes[0] + n2 := nodes[1] + assert.Equal(t, id, n1.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) + assert.Equal(t, *node1.Name, n1.Name) + wantConfig, err := toml.Marshal(node1) + require.NoError(t, err) + assert.Equal(t, string(wantConfig), n1.Config) + assert.Equal(t, id, n2.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) + assert.Equal(t, *node2.Name, n2.Name) + wantConfig2, err := toml.Marshal(node2) + require.NoError(t, err) + assert.Equal(t, string(wantConfig2), n2.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Len(t, renderLines, 19) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n1.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n1.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n1.State) + assert.Contains(t, renderLines[10], "Name") + assert.Contains(t, renderLines[10], n2.Name) + assert.Contains(t, renderLines[11], "Chain ID") + assert.Contains(t, renderLines[11], n2.ChainID) + assert.Contains(t, renderLines[12], "State") + assert.Contains(t, renderLines[12], n2.State) +} diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 54d8b7ab747..eeafea8b0ae 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -16,8 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" @@ -34,7 +32,6 @@ import ( func TestCoreRelayerChainInteroperators(t *testing.T) { evmChainID1, evmChainID2 := sqlutil.New(big.NewInt(1)), sqlutil.New(big.NewInt(2)) - solanaChainID1, solanaChainID2 := "solana-id-1", "solana-id-2" newConfig := func() chainlink.GeneralConfig { return configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -75,28 +72,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { Enabled: ptr(true), Nodes: toml.EVMNodes{&node2_1}, }) - - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: &solanaChainID1, - Enabled: ptr(true), - Nodes: []*solcfg.Node{{ - Name: ptr("solana chain 1 node 1"), - URL: commonconfig.MustParseURL("http://localhost:8547"), - }}, - }, - &solcfg.TOMLConfig{ - ChainID: &solanaChainID2, - Enabled: ptr(true), - Nodes: []*solcfg.Node{{ - Name: ptr("solana chain 2 node 1"), - URL: commonconfig.MustParseURL("http://localhost:8527"), - }}, - }, - } - for i := range c.Solana { - c.Solana[i].SetDefaults() - } }) } @@ -124,10 +99,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedEVMNodeCnt int expectedEVMRelayerIds []types.RelayID - expectedSolanaChainCnt int - expectedSolanaNodeCnt int - expectedSolanaRelayerIds []types.RelayID - expectedStarknetChainCnt int expectedStarknetNodeCnt int @@ -163,23 +134,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}}, }, - {name: "2 solana chain with 2 node", - initFuncs: []chainlink.CoreRelayerChainInitFunc{ - chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), chainlink.SolanaFactoryConfig{ - TOMLConfigs: newConfig().SolanaConfigs()}), - }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []types.RelayID{ - {Network: relay.NetworkSolana, ChainID: solanaChainID1}, - {Network: relay.NetworkSolana, ChainID: solanaChainID2}, - }, - expectedRelayerNetworks: map[string]struct{}{relay.NetworkSolana: {}}, - }, - {name: "all chains", - initFuncs: []chainlink.CoreRelayerChainInitFunc{chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), chainlink.SolanaFactoryConfig{ - TOMLConfigs: newConfig().SolanaConfigs()}), + initFuncs: []chainlink.CoreRelayerChainInitFunc{ chainlink.InitEVM(factory, chainlink.EVMFactoryConfig{ ChainOpts: legacyevm.ChainOpts{ ChainConfigs: cfg.EVMConfigs(), @@ -203,14 +159,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { {Network: relay.NetworkEVM, ChainID: evmChainID2.String()}, }, - expectedSolanaChainCnt: 2, - expectedSolanaNodeCnt: 2, - expectedSolanaRelayerIds: []types.RelayID{ - {Network: relay.NetworkSolana, ChainID: solanaChainID1}, - {Network: relay.NetworkSolana, ChainID: solanaChainID2}, - }, - - expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}, relay.NetworkCosmos: {}, relay.NetworkSolana: {}, relay.NetworkStarkNet: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}, relay.NetworkCosmos: {}, relay.NetworkStarkNet: {}}, }, } for _, tt := range tests { @@ -223,7 +172,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { cr, err = chainlink.NewCoreRelayerChainInteroperators(tt.initFuncs...) require.NoError(t, err) - expectedChainCnt := tt.expectedEVMChainCnt + tt.expectedCosmosChainCnt + tt.expectedSolanaChainCnt + tt.expectedStarknetChainCnt + expectedChainCnt := tt.expectedEVMChainCnt + tt.expectedCosmosChainCnt + tt.expectedStarknetChainCnt allChainsStats, cnt, err := cr.ChainStatuses(testctx, 0, 0) assert.NoError(t, err) assert.Len(t, allChainsStats, expectedChainCnt) @@ -234,7 +183,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { assert.Len(t, cr.Slice(), expectedChainCnt) assert.Len(t, cr.Services(), expectedChainCnt) - expectedNodeCnt := tt.expectedEVMNodeCnt + tt.expectedCosmosNodeCnt + tt.expectedSolanaNodeCnt + tt.expectedStarknetNodeCnt + expectedNodeCnt := tt.expectedEVMNodeCnt + tt.expectedCosmosNodeCnt + tt.expectedStarknetNodeCnt allNodeStats, cnt, err := cr.NodeStatuses(testctx, 0, 0) assert.NoError(t, err) assert.Len(t, allNodeStats, expectedNodeCnt) @@ -249,20 +198,25 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedEVMChainCnt, tt.expectedEVMNodeCnt case relay.NetworkCosmos: expectedChainCnt, expectedNodeCnt = tt.expectedCosmosChainCnt, tt.expectedCosmosNodeCnt + // LOOP-only relayers (solana, aptos, tron, ton, sui) can't be exercised at + // this level without booting the LOOPP subprocess — ChainStatus/NodeStatus + // block on Wait until the plugin is started. Integration tests cover them + // end-to-end. Only networks with embedded (in-process) relayers are asserted + // here. case relay.NetworkSolana: - expectedChainCnt, expectedNodeCnt = tt.expectedSolanaChainCnt, tt.expectedSolanaNodeCnt + t.Skip("solana is LOOP-only; exercised via integration tests") case relay.NetworkStarkNet: expectedChainCnt, expectedNodeCnt = tt.expectedStarknetChainCnt, tt.expectedStarknetNodeCnt case relay.NetworkDummy: expectedChainCnt, expectedNodeCnt = tt.expectedDummyChainCnt, tt.expectedDummyNodeCnt case relay.NetworkAptos: - t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") + t.Skip("aptos is LOOP-only; exercised via integration tests") case relay.NetworkTron: - t.Skip("tron doesn't need a CoreRelayerChainInteroperator") + t.Skip("tron is LOOP-only; exercised via integration tests") case relay.NetworkTON: - t.Skip("ton doesn't need a CoreRelayerChainInteroperator") + t.Skip("ton is LOOP-only; exercised via integration tests") case relay.NetworkSui: - t.Skip("sui doesn't need a CoreRelayerChainInteroperator") + t.Skip("sui is LOOP-only; exercised via integration tests") default: require.Fail(t, "untested relay network", relayNetwork) @@ -293,7 +247,6 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { allRelayerIds := [][]types.RelayID{ tt.expectedEVMRelayerIds, - tt.expectedSolanaRelayerIds, } for _, chainSpecificRelayerIds := range allRelayerIds { diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index a5a9184c18d..9a2b35f33f3 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -146,12 +146,20 @@ func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFa solanaRelayers := make(map[types.RelayID]loop.Relayer) var solLggr = logger.Named(r.Logger, "Solana") + cmdName := cmp.Or(env.SolanaPlugin.Cmd.Get(), env.SolanaPlugin.CmdDefault) + if cmdName == "" { + return nil, fmt.Errorf("plugin command not defined: %s", env.SolanaPlugin.Cmd) + } + envVars, err := plugins.ParseEnvFile(env.SolanaPlugin.Env.Get()) + if err != nil { + return nil, fmt.Errorf("failed to parse Solana env file: %w", err) + } + unique := make(map[string]struct{}) // create one relayer per chain id for _, chainCfg := range chainCfgs { relayID := types.RelayID{Network: relay.NetworkSolana, ChainID: *chainCfg.ChainID} - _, alreadyExists := unique[relayID.Name()] - if alreadyExists { + if _, alreadyExists := unique[relayID.Name()]; alreadyExists { return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) } unique[relayID.Name()] = struct{}{} @@ -163,20 +171,15 @@ func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFa } lggr := logger.Named(solLggr, relayID.ChainID) - // setup the solana relayer to be a LOOP cfgTOML, err := toml.Marshal(struct { Solana solcfg.TOMLConfig }{Solana: *chainCfg}) if err != nil { return nil, fmt.Errorf("failed to marshal Solana configs: %w", err) } - envVars, err := plugins.ParseEnvFile(env.SolanaPlugin.Env.Get()) - if err != nil { - return nil, fmt.Errorf("failed to parse Solana env file: %w", err) - } solCmdFn, err := plugins.NewCmdFactory(r.Register, plugins.CmdConfig{ ID: relayID.Name(), - Cmd: env.SolanaPlugin.Cmd.Get(), + Cmd: cmdName, Env: envVars, }) if err != nil { diff --git a/core/web/chains_controller_test.go b/core/web/chains_controller_test.go index 04399e70f73..84aa901b9e4 100644 --- a/core/web/chains_controller_test.go +++ b/core/web/chains_controller_test.go @@ -1,24 +1,18 @@ package web_test import ( - "fmt" "math/big" "net/http" "sort" "testing" - "time" "github.com/manyminds/api2go/jsonapi" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/exp/rand" "github.com/smartcontractkit/quarantine" - commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/types" @@ -230,215 +224,4 @@ func setupEVMChainsControllerTest(t *testing.T, cfg chainlink.GeneralConfig) *Te } } -func Test_SolanaChainsController_Show(t *testing.T) { - t.Parallel() - - const validID = "Chainlink-12" - - testCases := []struct { - name string - inputID string - wantStatusCode int - want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus - }{ - { - inputID: validID, - name: "success", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return &commonTypes.ChainStatus{ - ID: validID, - Enabled: true, - Config: `ChainID = 'Chainlink-12' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = false -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 -Nodes = [] - -[Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 - -[MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '15s' -SelectionMode = 'PriorityLevel' -SyncThreshold = 10 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '20s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '20s' -NoNewFinalizedHeadsThreshold = '20s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 50 -`, - } - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "234", - name: "not found", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return nil - }, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - }) - - wantedResult := tc.want(t, controller.app) - resp, cleanup := controller.client.Get( - "/v2/chains/solana/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, wantedResult.ID, resource1.ID) - assert.Equal(t, wantedResult.Enabled, resource1.Enabled) - assert.Equal(t, wantedResult.Config, resource1.Config) - } - }) - } -} - -func Test_SolanaChainsController_Index(t *testing.T) { - t.Parallel() - - chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), - Chain: config.Chain{ - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), - Chain: config.Chain{ - SkipPreflight: ptr(false), - }, - } - controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) - - badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 2, metaCount) - - var links jsonapi.Links - - chains := []presenters.ChainResource{} - err = web.ParsePaginatedResponse(body, &chains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - chains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) -} - -type TestSolanaChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) - app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) - - client := app.NewHTTPClient(nil) - - return &TestSolanaChainsController{ - app: app, - client: client, - } -} - func ptr[T any](t T) *T { return &t } diff --git a/core/web/solana_chains_controller_integration_test.go b/core/web/solana_chains_controller_integration_test.go new file mode 100644 index 00000000000..14b0f3c4599 --- /dev/null +++ b/core/web/solana_chains_controller_integration_test.go @@ -0,0 +1,237 @@ +//go:build integration + +package web_test + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/manyminds/api2go/jsonapi" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "golang.org/x/exp/rand" + + commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" + commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func Test_SolanaChainsController_Show(t *testing.T) { + t.Parallel() + + const validID = "Chainlink-12" + + testCases := []struct { + name string + inputID string + wantStatusCode int + want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus + }{ + { + inputID: validID, + name: "success", + want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { + return &commonTypes.ChainStatus{ + ID: validID, + Enabled: true, + Config: `ChainID = 'Chainlink-12' +Enabled = true +BlockTime = '500ms' +BalancePollPeriod = '5s' +ConfirmPollPeriod = '500ms' +OCR2CachePollPeriod = '1s' +OCR2CacheTTL = '1m0s' +TxTimeout = '1h0m0s' +TxRetryTimeout = '10s' +TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false +TxRetentionTimeout = '0s' +SkipPreflight = false +Commitment = 'confirmed' +MaxRetries = 0 +FeeEstimatorMode = 'fixed' +ComputeUnitPriceMax = 1000 +ComputeUnitPriceMin = 0 +ComputeUnitPriceDefault = 0 +FeeBumpPeriod = '3s' +BlockHistoryPollPeriod = '5s' +BlockHistorySize = 1 +BlockHistoryBatchLoadSize = 20 +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false +LogPollerStartingLookback = '24h0m0s' +LogPollerCPIEventsEnabled = true +LogPollerSlotsBatchSize = 1000 +Nodes = [] + +[Workflow] +AcceptanceTimeout = '45s' +ForwarderAddress = '11111111111111111111111111111111' +ForwarderState = '11111111111111111111111111111111' +FromAddress = '11111111111111111111111111111111' +GasLimitDefault = 300000 +Local = false +PollPeriod = '3s' +TxAcceptanceState = 3 + +[MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '15s' +SelectionMode = 'PriorityLevel' +SyncThreshold = 10 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +NewHeadsPollInterval = '5s' +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '20s' +VerifyChainID = true +NodeNoNewHeadsThreshold = '20s' +NoNewFinalizedHeadsThreshold = '20s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 50 +`, + } + }, + wantStatusCode: http.StatusOK, + }, + { + inputID: "234", + name: "not found", + want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { + return nil + }, + wantStatusCode: http.StatusBadRequest, + }, + } + + for _, testCase := range testCases { + tc := testCase + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ + ChainID: ptr(validID), + Chain: config.Chain{ + SkipPreflight: ptr(false), + TxTimeout: commoncfg.MustNewDuration(time.Hour), + }, + }) + + wantedResult := tc.want(t, controller.app) + resp, cleanup := controller.client.Get( + "/v2/chains/solana/" + tc.inputID, + ) + t.Cleanup(cleanup) + require.Equal(t, tc.wantStatusCode, resp.StatusCode) + + if wantedResult != nil { + resource1 := presenters.ChainResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) + require.NoError(t, err) + + assert.Equal(t, wantedResult.ID, resource1.ID) + assert.Equal(t, wantedResult.Enabled, resource1.Enabled) + assert.Equal(t, wantedResult.Config, resource1.Config) + } + }) + } +} + +func Test_SolanaChainsController_Index(t *testing.T) { + t.Parallel() + + chainA := &config.TOMLConfig{ + ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), + Chain: config.Chain{ + TxTimeout: commoncfg.MustNewDuration(time.Hour), + }, + } + chainB := &config.TOMLConfig{ + ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), + Chain: config.Chain{ + SkipPreflight: ptr(false), + }, + } + controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) + + badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") + t.Cleanup(cleanup) + require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) + + resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + body := cltest.ParseResponseBody(t, resp) + + metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) + require.NoError(t, err) + require.Equal(t, 2, metaCount) + + var links jsonapi.Links + + chains := []presenters.ChainResource{} + err = web.ParsePaginatedResponse(body, &chains, &links) + require.NoError(t, err) + assert.NotEmpty(t, links["next"].Href) + assert.Empty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainA.ChainID, chains[0].ID) + tomlA, err := chainA.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlA, chains[0].Config) + + resp, cleanup = controller.client.Get(links["next"].Href) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + chains = []presenters.ChainResource{} + err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) + require.NoError(t, err) + assert.Empty(t, links["next"].Href) + assert.NotEmpty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainB.ChainID, chains[0].ID) + tomlB, err := chainB.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlB, chains[0].Config) +} + +type TestSolanaChainsController struct { + app *cltest.TestApplication + client cltest.HTTPClientCleaner +} + +func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { + for i := range cfgs { + cfgs[i].SetDefaults() + } + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) + app := cltest.NewApplicationWithConfig(t, cfg) + require.NoError(t, app.Start(testutils.Context(t))) + + client := app.NewHTTPClient(nil) + + return &TestSolanaChainsController{ + app: app, + client: client, + } +} From ac8c35ed962162be9510b18ef6c4e9b5c145ab42 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Fri, 24 Apr 2026 16:33:11 -0500 Subject: [PATCH 07/25] refactor test --- core/cmd/chains_commands_integration_test.go | 22 ++ core/cmd/node_commands_integration_test.go | 72 ++++++ ...solana_chains_commands_integration_test.go | 109 -------- .../web/chains_controller_integration_test.go | 216 ++++++++++++++++ ...lana_chains_controller_integration_test.go | 237 ------------------ 5 files changed, 310 insertions(+), 346 deletions(-) delete mode 100644 core/cmd/solana_chains_commands_integration_test.go delete mode 100644 core/web/solana_chains_controller_integration_test.go diff --git a/core/cmd/chains_commands_integration_test.go b/core/cmd/chains_commands_integration_test.go index 8427f483b3e..832d487f7a7 100644 --- a/core/cmd/chains_commands_integration_test.go +++ b/core/cmd/chains_commands_integration_test.go @@ -8,9 +8,12 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -35,3 +38,22 @@ func TestShell_IndexCosmosChains(t *testing.T) { assert.Equal(t, chainID, c.ID) assertTableRenders(t, r) } + +func TestShell_IndexSolanaChains(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + cfg := solcfg.TOMLConfig{ + ChainID: &id, + Enabled: ptr(true), + } + app := solanaStartNewApplication(t, &cfg) + client, r := app.NewShellAndRenderer() + + require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) + chains := *r.Renders[0].(*cmd.ChainPresenters) + require.Len(t, chains, 1) + c := chains[0] + assert.Equal(t, id, c.ID) + assertTableRenders(t, r) +} diff --git a/core/cmd/node_commands_integration_test.go b/core/cmd/node_commands_integration_test.go index 5e81319ae54..17b980d9c43 100644 --- a/core/cmd/node_commands_integration_test.go +++ b/core/cmd/node_commands_integration_test.go @@ -12,9 +12,12 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -25,6 +28,16 @@ func cosmosStartNewApplication(t *testing.T, cfgs ...chainlink.RawConfig) *cltes }) } +func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { + for i := range cfgs { + cfgs[i].SetDefaults() + } + return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) +} + func TestShell_IndexCosmosNodes(t *testing.T) { t.Parallel() @@ -132,3 +145,62 @@ func TestShell_IndexStarkNetNodes(t *testing.T) { assert.Contains(t, renderLines[11], "State") assert.Contains(t, renderLines[11], n2.State) } + +func TestShell_IndexSolanaNodes(t *testing.T) { + t.Parallel() + + id := solanatest.RandomChainID() + node1 := solcfg.Node{ + Name: ptr("first"), + URL: config.MustParseURL("https://solana1.example"), + } + node2 := solcfg.Node{ + Name: ptr("second"), + URL: config.MustParseURL("https://solana2.example"), + } + chain := solcfg.TOMLConfig{ + ChainID: &id, + Nodes: solcfg.Nodes{&node1, &node2}, + } + app := solanaStartNewApplication(t, &chain) + client, r := app.NewShellAndRenderer() + + require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) + require.NotEmpty(t, r.Renders) + nodes := *r.Renders[0].(*cmd.NodePresenters) + require.Len(t, nodes, 2) + n1 := nodes[0] + n2 := nodes[1] + assert.Equal(t, id, n1.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) + assert.Equal(t, *node1.Name, n1.Name) + wantConfig, err := toml.Marshal(node1) + require.NoError(t, err) + assert.Equal(t, string(wantConfig), n1.Config) + assert.Equal(t, id, n2.ChainID) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) + assert.Equal(t, *node2.Name, n2.Name) + wantConfig2, err := toml.Marshal(node2) + require.NoError(t, err) + assert.Equal(t, string(wantConfig2), n2.Config) + assertTableRenders(t, r) + + // Render table and check the fields order + b := new(bytes.Buffer) + rt := cmd.RendererTable{b} + require.NoError(t, nodes.RenderTable(rt)) + renderLines := strings.Split(b.String(), "\n") + assert.Len(t, renderLines, 19) + assert.Contains(t, renderLines[2], "Name") + assert.Contains(t, renderLines[2], n1.Name) + assert.Contains(t, renderLines[3], "Chain ID") + assert.Contains(t, renderLines[3], n1.ChainID) + assert.Contains(t, renderLines[4], "State") + assert.Contains(t, renderLines[4], n1.State) + assert.Contains(t, renderLines[10], "Name") + assert.Contains(t, renderLines[10], n2.Name) + assert.Contains(t, renderLines[11], "Chain ID") + assert.Contains(t, renderLines[11], n2.ChainID) + assert.Contains(t, renderLines[12], "State") + assert.Contains(t, renderLines[12], n2.State) +} diff --git a/core/cmd/solana_chains_commands_integration_test.go b/core/cmd/solana_chains_commands_integration_test.go deleted file mode 100644 index 6d262a96b0c..00000000000 --- a/core/cmd/solana_chains_commands_integration_test.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build integration - -package cmd_test - -import ( - "bytes" - "strings" - "testing" - - "github.com/pelletier/go-toml/v2" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - - "github.com/smartcontractkit/chainlink/v2/core/cmd" - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/solanatest" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" -) - -func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].SetDefaults() - } - return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) -} - -func TestShell_IndexSolanaChains(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - cfg := solcfg.TOMLConfig{ - ChainID: &id, - Enabled: ptr(true), - } - app := solanaStartNewApplication(t, &cfg) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) - chains := *r.Renders[0].(*cmd.ChainPresenters) - require.Len(t, chains, 1) - c := chains[0] - assert.Equal(t, id, c.ID) - assertTableRenders(t, r) -} - -func TestShell_IndexSolanaNodes(t *testing.T) { - t.Parallel() - - id := solanatest.RandomChainID() - node1 := solcfg.Node{ - Name: ptr("first"), - URL: config.MustParseURL("https://solana1.example"), - } - node2 := solcfg.Node{ - Name: ptr("second"), - URL: config.MustParseURL("https://solana2.example"), - } - chain := solcfg.TOMLConfig{ - ChainID: &id, - Nodes: solcfg.Nodes{&node1, &node2}, - } - app := solanaStartNewApplication(t, &chain) - client, r := app.NewShellAndRenderer() - - require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) - require.NotEmpty(t, r.Renders) - nodes := *r.Renders[0].(*cmd.NodePresenters) - require.Len(t, nodes, 2) - n1 := nodes[0] - n2 := nodes[1] - assert.Equal(t, id, n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) - assert.Equal(t, id, n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) - assertTableRenders(t, r) - - // Render table and check the fields order - b := new(bytes.Buffer) - rt := cmd.RendererTable{b} - require.NoError(t, nodes.RenderTable(rt)) - renderLines := strings.Split(b.String(), "\n") - assert.Len(t, renderLines, 19) - assert.Contains(t, renderLines[2], "Name") - assert.Contains(t, renderLines[2], n1.Name) - assert.Contains(t, renderLines[3], "Chain ID") - assert.Contains(t, renderLines[3], n1.ChainID) - assert.Contains(t, renderLines[4], "State") - assert.Contains(t, renderLines[4], n1.State) - assert.Contains(t, renderLines[10], "Name") - assert.Contains(t, renderLines[10], n2.Name) - assert.Contains(t, renderLines[11], "Chain ID") - assert.Contains(t, renderLines[11], n2.ChainID) - assert.Contains(t, renderLines[12], "State") - assert.Contains(t, renderLines[12], n2.State) -} diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 6e80932e1c8..1e1c1353f04 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -7,13 +7,18 @@ import ( "fmt" "net/http" "testing" + "time" "github.com/manyminds/api2go/jsonapi" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "golang.org/x/exp/rand" + commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" + "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -214,3 +219,214 @@ func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...chainlink.RawConfig client: client, } } + +func Test_SolanaChainsController_Show(t *testing.T) { + t.Parallel() + + const validID = "Chainlink-12" + + testCases := []struct { + name string + inputID string + wantStatusCode int + want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus + }{ + { + inputID: validID, + name: "success", + want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { + return &commonTypes.ChainStatus{ + ID: validID, + Enabled: true, + Config: `ChainID = 'Chainlink-12' +Enabled = true +BlockTime = '500ms' +BalancePollPeriod = '5s' +ConfirmPollPeriod = '500ms' +OCR2CachePollPeriod = '1s' +OCR2CacheTTL = '1m0s' +TxTimeout = '1h0m0s' +TxRetryTimeout = '10s' +TxConfirmTimeout = '30s' +TxExpirationRebroadcast = false +TxRetentionTimeout = '0s' +SkipPreflight = false +Commitment = 'confirmed' +MaxRetries = 0 +FeeEstimatorMode = 'fixed' +ComputeUnitPriceMax = 1000 +ComputeUnitPriceMin = 0 +ComputeUnitPriceDefault = 0 +FeeBumpPeriod = '3s' +BlockHistoryPollPeriod = '5s' +BlockHistorySize = 1 +BlockHistoryBatchLoadSize = 20 +ComputeUnitLimitDefault = 200000 +EstimateComputeUnitLimit = false +LogPollerStartingLookback = '24h0m0s' +LogPollerCPIEventsEnabled = true +LogPollerSlotsBatchSize = 1000 +Nodes = [] + +[Workflow] +AcceptanceTimeout = '45s' +ForwarderAddress = '11111111111111111111111111111111' +ForwarderState = '11111111111111111111111111111111' +FromAddress = '11111111111111111111111111111111' +GasLimitDefault = 300000 +Local = false +PollPeriod = '3s' +TxAcceptanceState = 3 + +[MultiNode] +Enabled = false +PollFailureThreshold = 5 +PollInterval = '15s' +SelectionMode = 'PriorityLevel' +SyncThreshold = 10 +NodeIsSyncingEnabled = false +LeaseDuration = '1m0s' +NewHeadsPollInterval = '5s' +FinalizedBlockPollInterval = '5s' +EnforceRepeatableRead = true +DeathDeclarationDelay = '20s' +VerifyChainID = true +NodeNoNewHeadsThreshold = '20s' +NoNewFinalizedHeadsThreshold = '20s' +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 50 +`, + } + }, + wantStatusCode: http.StatusOK, + }, + { + inputID: "234", + name: "not found", + want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { + return nil + }, + wantStatusCode: http.StatusBadRequest, + }, + } + + for _, testCase := range testCases { + tc := testCase + + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ + ChainID: ptr(validID), + Chain: config.Chain{ + SkipPreflight: ptr(false), + TxTimeout: commoncfg.MustNewDuration(time.Hour), + }, + }) + + wantedResult := tc.want(t, controller.app) + resp, cleanup := controller.client.Get( + "/v2/chains/solana/" + tc.inputID, + ) + t.Cleanup(cleanup) + require.Equal(t, tc.wantStatusCode, resp.StatusCode) + + if wantedResult != nil { + resource1 := presenters.ChainResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) + require.NoError(t, err) + + assert.Equal(t, wantedResult.ID, resource1.ID) + assert.Equal(t, wantedResult.Enabled, resource1.Enabled) + assert.Equal(t, wantedResult.Config, resource1.Config) + } + }) + } +} + +func Test_SolanaChainsController_Index(t *testing.T) { + t.Parallel() + + chainA := &config.TOMLConfig{ + ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), + Chain: config.Chain{ + TxTimeout: commoncfg.MustNewDuration(time.Hour), + }, + } + chainB := &config.TOMLConfig{ + ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), + Chain: config.Chain{ + SkipPreflight: ptr(false), + }, + } + controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) + + badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") + t.Cleanup(cleanup) + require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) + + resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + body := cltest.ParseResponseBody(t, resp) + + metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) + require.NoError(t, err) + require.Equal(t, 2, metaCount) + + var links jsonapi.Links + + chains := []presenters.ChainResource{} + err = web.ParsePaginatedResponse(body, &chains, &links) + require.NoError(t, err) + assert.NotEmpty(t, links["next"].Href) + assert.Empty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainA.ChainID, chains[0].ID) + tomlA, err := chainA.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlA, chains[0].Config) + + resp, cleanup = controller.client.Get(links["next"].Href) + t.Cleanup(cleanup) + require.Equal(t, http.StatusOK, resp.StatusCode) + + chains = []presenters.ChainResource{} + err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) + require.NoError(t, err) + assert.Empty(t, links["next"].Href) + assert.NotEmpty(t, links["prev"].Href) + + assert.Len(t, links, 1) + assert.Equal(t, *chainB.ChainID, chains[0].ID) + tomlB, err := chainB.TOMLString() + require.NoError(t, err) + assert.Equal(t, tomlB, chains[0].Config) +} + +type TestSolanaChainsController struct { + app *cltest.TestApplication + client cltest.HTTPClientCleaner +} + +func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { + for i := range cfgs { + cfgs[i].SetDefaults() + } + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + c.Solana = cfgs + c.EVM = nil + }) + app := cltest.NewApplicationWithConfig(t, cfg) + require.NoError(t, app.Start(testutils.Context(t))) + + client := app.NewHTTPClient(nil) + + return &TestSolanaChainsController{ + app: app, + client: client, + } +} diff --git a/core/web/solana_chains_controller_integration_test.go b/core/web/solana_chains_controller_integration_test.go deleted file mode 100644 index 14b0f3c4599..00000000000 --- a/core/web/solana_chains_controller_integration_test.go +++ /dev/null @@ -1,237 +0,0 @@ -//go:build integration - -package web_test - -import ( - "fmt" - "net/http" - "testing" - "time" - - "github.com/manyminds/api2go/jsonapi" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/exp/rand" - - commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" - commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - - "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" - "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" - "github.com/smartcontractkit/chainlink/v2/core/web" - "github.com/smartcontractkit/chainlink/v2/core/web/presenters" -) - -func Test_SolanaChainsController_Show(t *testing.T) { - t.Parallel() - - const validID = "Chainlink-12" - - testCases := []struct { - name string - inputID string - wantStatusCode int - want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus - }{ - { - inputID: validID, - name: "success", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return &commonTypes.ChainStatus{ - ID: validID, - Enabled: true, - Config: `ChainID = 'Chainlink-12' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = false -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 -Nodes = [] - -[Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 - -[MultiNode] -Enabled = false -PollFailureThreshold = 5 -PollInterval = '15s' -SelectionMode = 'PriorityLevel' -SyncThreshold = 10 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '5s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '20s' -VerifyChainID = true -NodeNoNewHeadsThreshold = '20s' -NoNewFinalizedHeadsThreshold = '20s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 50 -`, - } - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "234", - name: "not found", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return nil - }, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - }) - - wantedResult := tc.want(t, controller.app) - resp, cleanup := controller.client.Get( - "/v2/chains/solana/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, wantedResult.ID, resource1.ID) - assert.Equal(t, wantedResult.Enabled, resource1.Enabled) - assert.Equal(t, wantedResult.Config, resource1.Config) - } - }) - } -} - -func Test_SolanaChainsController_Index(t *testing.T) { - t.Parallel() - - chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), - Chain: config.Chain{ - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), - Chain: config.Chain{ - SkipPreflight: ptr(false), - }, - } - controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) - - badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 2, metaCount) - - var links jsonapi.Links - - chains := []presenters.ChainResource{} - err = web.ParsePaginatedResponse(body, &chains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - chains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) -} - -type TestSolanaChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) - app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) - - client := app.NewHTTPClient(nil) - - return &TestSolanaChainsController{ - app: app, - client: client, - } -} From 229e097f7507b524ec1b35c14a029d929f2c4ef6 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Fri, 24 Apr 2026 16:43:51 -0500 Subject: [PATCH 08/25] fix lint --- core/web/chains_controller_integration_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 1e1c1353f04..5272d8c0c9b 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -5,6 +5,7 @@ package web_test import ( "cmp" "fmt" + "math/rand/v2" "net/http" "testing" "time" @@ -13,7 +14,6 @@ import ( "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/exp/rand" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -349,13 +349,13 @@ func Test_SolanaChainsController_Index(t *testing.T) { t.Parallel() chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), + ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int32N(999999))), Chain: config.Chain{ TxTimeout: commoncfg.MustNewDuration(time.Hour), }, } chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), + ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int32N(999999))), Chain: config.Chain{ SkipPreflight: ptr(false), }, From 9752a12808fd4e5e98c40e5560b479001bb32ab5 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Fri, 24 Apr 2026 18:37:23 -0500 Subject: [PATCH 09/25] move refactor and remove solana from non-loop health report --- core/cmd/blocks_commands_integration_test.go | 33 ++ core/cmd/blocks_commands_test.go | 16 - core/cmd/shell_remote_test.go | 13 +- core/web/health_controller_test.go | 12 +- core/web/testdata/body/health.html | 18 - core/web/testdata/body/health.json | 36 -- core/web/testdata/body/health.txt | 4 - testdata/scripts/health/multi-chain.txtar | 421 ------------------ testdata/scripts/nodes/solana/list/list.txtar | 1 + 9 files changed, 36 insertions(+), 518 deletions(-) create mode 100644 core/cmd/blocks_commands_integration_test.go delete mode 100644 testdata/scripts/health/multi-chain.txtar diff --git a/core/cmd/blocks_commands_integration_test.go b/core/cmd/blocks_commands_integration_test.go new file mode 100644 index 00000000000..3bd0939a2c0 --- /dev/null +++ b/core/cmd/blocks_commands_integration_test.go @@ -0,0 +1,33 @@ +//go:build integration + +package cmd_test + +import ( + "flag" + "testing" + + "github.com/stretchr/testify/require" + "github.com/urfave/cli" + + solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" +) + +func Test_ReplayFromBlock_Solana(t *testing.T) { + t.Parallel() + + cfg := solcfg.TOMLConfig{ + ChainID: ptr("devnet"), + Enabled: ptr(true), + } + app := solanaStartNewApplication(t, &cfg) + client, _ := app.NewShellAndRenderer() + + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(client.ReplayFromBlock, set, "") + + require.NoError(t, set.Set("block-number", "1")) + require.NoError(t, set.Set("chain-id", "devnet")) + require.NoError(t, set.Set("family", "solana")) + c := cli.NewContext(nil, set, nil) + require.NoError(t, client.ReplayFromBlock(c)) +} diff --git a/core/cmd/blocks_commands_test.go b/core/cmd/blocks_commands_test.go index a510df01054..da50bc03060 100644 --- a/core/cmd/blocks_commands_test.go +++ b/core/cmd/blocks_commands_test.go @@ -9,7 +9,6 @@ import ( "github.com/urfave/cli" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) @@ -19,13 +18,6 @@ func Test_ReplayFromBlock(t *testing.T) { app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].ChainID = (*sqlutil.Big)(big.NewInt(5)) c.EVM[0].Enabled = ptr(true) - - solCfg := &config.TOMLConfig{ - ChainID: ptr("devnet"), - Enabled: ptr(true), - } - solCfg.SetDefaults() - c.Solana = config.TOMLConfigs{solCfg} }) client, _ := app.NewShellAndRenderer() @@ -59,14 +51,6 @@ func Test_ReplayFromBlock(t *testing.T) { c := cli.NewContext(nil, set, nil) require.NoError(t, client.ReplayFromBlock(c)) }) - - t.Run("solana replay", func(t *testing.T) { - require.NoError(t, set.Set("block-number", "1")) - require.NoError(t, set.Set("chain-id", "devnet")) - require.NoError(t, set.Set("family", "solana")) - c := cli.NewContext(nil, set, nil) - require.NoError(t, client.ReplayFromBlock(c)) - }) } func Test_FindLCA(t *testing.T) { diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index 4c110cced8d..319dcbe0c47 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -24,7 +24,7 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-evm/pkg/client/clienttest" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/auth" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/cmd" @@ -122,13 +122,6 @@ func TestShell_ReplayBlocks(t *testing.T) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) c.EVM[0].GasEstimator.Mode = ptr("FixedPrice") - - solCfg := &config.TOMLConfig{ - ChainID: ptr("devnet"), - Enabled: ptr(true), - } - solCfg.SetDefaults() - c.Solana = config.TOMLConfigs{solCfg} }) client, _ := app.NewShellAndRenderer() @@ -144,10 +137,6 @@ func TestShell_ReplayBlocks(t *testing.T) { require.NoError(t, set.Set("chain-id", testutils.FixtureChainID.String())) c = cli.NewContext(nil, set, nil) assert.NoError(t, client.ReplayFromBlock(c)) - - require.NoError(t, set.Set("chain-id", "devnet")) - require.NoError(t, set.Set("family", "solana")) - assert.NoError(t, client.ReplayFromBlock(c)) } func TestShell_CreateExternalInitiator(t *testing.T) { diff --git a/core/web/health_controller_test.go b/core/web/health_controller_test.go index 90911991700..78f34df8a9e 100644 --- a/core/web/health_controller_test.go +++ b/core/web/health_controller_test.go @@ -13,8 +13,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" @@ -136,15 +134,7 @@ func TestHealthController_Health_body(t *testing.T) { {".txt-failing", "/health.txt?failing", nil, bodyTXTFailing}, } { t.Run(tc.name, func(t *testing.T) { - cfg := configtest.NewGeneralConfig(t, func(cfg *chainlink.Config, secrets *chainlink.Secrets) { - cfg.Solana = []*solcfg.TOMLConfig{{ - ChainID: ptr("Bar"), - Nodes: solcfg.Nodes{ - {Name: ptr("primary"), URL: config.MustParseURL("http://solana.web")}, - }, - }} - cfg.Solana[0].SetDefaults() - }) + cfg := configtest.NewGeneralConfig(t, func(cfg *chainlink.Config, secrets *chainlink.Secrets) {}) app := cltest.NewApplicationWithConfigAndKey(t, cfg) require.NoError(t, app.Start(testutils.Context(t))) diff --git a/core/web/testdata/body/health.html b/core/web/testdata/body/health.html index cf189621cf5..851f5e6902f 100644 --- a/core/web/testdata/body/health.html +++ b/core/web/testdata/body/health.html @@ -126,24 +126,6 @@
RetirementReportCache
-
- Solana -
- Bar -
- Chain -
- BalanceMonitor -
-
- Txm -
-
-
- Relayer -
-
-
TelemetryManager
diff --git a/core/web/testdata/body/health.json b/core/web/testdata/body/health.json index 31054ef17e7..5f6fae19e30 100644 --- a/core/web/testdata/body/health.json +++ b/core/web/testdata/body/health.json @@ -252,42 +252,6 @@ "output": "" } }, - { - "type": "checks", - "id": "Solana.Bar.Chain", - "attributes": { - "name": "Solana.Bar.Chain", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.BalanceMonitor", - "attributes": { - "name": "Solana.Bar.Chain.BalanceMonitor", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.Txm", - "attributes": { - "name": "Solana.Bar.Chain.Txm", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Relayer", - "attributes": { - "name": "Solana.Bar.Relayer", - "status": "passing", - "output": "" - } - }, { "type": "checks", "id": "TelemetryManager", diff --git a/core/web/testdata/body/health.txt b/core/web/testdata/body/health.txt index 59a77f4a057..1070a89f475 100644 --- a/core/web/testdata/body/health.txt +++ b/core/web/testdata/body/health.txt @@ -27,9 +27,5 @@ ok PipelineORM ok PipelineRunner ok PipelineRunner.BridgeCache ok RetirementReportCache -ok Solana.Bar.Chain -ok Solana.Bar.Chain.BalanceMonitor -ok Solana.Bar.Chain.Txm -ok Solana.Bar.Relayer ok TelemetryManager ok WorkflowStore diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar deleted file mode 100644 index ad456fc2db8..00000000000 --- a/testdata/scripts/health/multi-chain.txtar +++ /dev/null @@ -1,421 +0,0 @@ -# start node -exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' -exec chainlink node -c config.toml start -p password -a creds & - -# initialize client -env NODEURL=http://localhost:$PORT -exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL -exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check - -exec chainlink --remote-node-url $NODEURL health -cmp stdout out.txt - -exec chainlink --remote-node-url $NODEURL health -json -cp stdout compact.json -exec jq . compact.json -cmp stdout out.json - -exec chainlink --remote-node-url $NODEURL health -failing -cmp stdout out-unhealthy.txt - -exec chainlink --remote-node-url $NODEURL health -f -json -cp stdout compact.json -exec jq . compact.json -cmp stdout out-unhealthy.json - --- testdb.txt -- -CL_DATABASE_URL --- testport.txt -- -PORT - --- password -- -T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ --- creds -- -notreal@fakeemail.ch -fj293fbBnlQ!f9vNs - --- config.toml.tmpl -- -[Webserver] -HTTPPort = $PORT - -[[EVM]] -ChainID = '1' - -[[EVM.Nodes]] -Name = 'fake' -WSURL = 'wss://foo.bar/ws' -HTTPURL = 'https://foo.bar' - -[[Solana]] -ChainID = 'Bar' - -[[Solana.Nodes]] -Name = 'primary' -URL = 'http://solana.web' - --- out.txt -- -ok BridgeStatusReporter -ok CRE -ok CRE.DispatcherWrapper -ok EVM.1 -ok EVM.1.BalanceMonitor -ok EVM.1.HeadBroadcaster -ok EVM.1.HeadTracker -! EVM.1.HeadTracker.HeadListener - Listener connected = false, receiving heads = false -ok EVM.1.LogBroadcaster -ok EVM.1.Relayer -ok EVM.1.Txm -ok EVM.1.Txm.BlockHistoryEstimator -ok EVM.1.Txm.Broadcaster -ok EVM.1.Txm.Confirmer -ok EVM.1.Txm.Finalizer -ok EVM.1.Txm.WrappedEvmEstimator -ok HeadReporter -ok Heartbeat -ok JobSpawner -ok LLOTransmissionReaper -ok Mailbox.Monitor -ok Mercury.WSRPCPool -ok Mercury.WSRPCPool.CacheSet -ok NodePlatformBuildInfo -ok PipelineORM -ok PipelineRunner -ok PipelineRunner.BridgeCache -ok RetirementReportCache -ok Solana.Bar.Chain -ok Solana.Bar.Chain.BalanceMonitor -ok Solana.Bar.Chain.Txm -ok Solana.Bar.Relayer -ok TelemetryManager -ok WorkflowStore - --- out-unhealthy.txt -- -! EVM.1.HeadTracker.HeadListener - Listener connected = false, receiving heads = false - --- out.json -- -{ - "data": [ - { - "type": "checks", - "id": "BridgeStatusReporter", - "attributes": { - "name": "BridgeStatusReporter", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "CRE", - "attributes": { - "name": "CRE", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "CRE.DispatcherWrapper", - "attributes": { - "name": "CRE.DispatcherWrapper", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1", - "attributes": { - "name": "EVM.1", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.BalanceMonitor", - "attributes": { - "name": "EVM.1.BalanceMonitor", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.HeadBroadcaster", - "attributes": { - "name": "EVM.1.HeadBroadcaster", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.HeadTracker", - "attributes": { - "name": "EVM.1.HeadTracker", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.HeadTracker.HeadListener", - "attributes": { - "name": "EVM.1.HeadTracker.HeadListener", - "status": "failing", - "output": "Listener connected = false, receiving heads = false" - } - }, - { - "type": "checks", - "id": "EVM.1.LogBroadcaster", - "attributes": { - "name": "EVM.1.LogBroadcaster", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Relayer", - "attributes": { - "name": "EVM.1.Relayer", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Txm", - "attributes": { - "name": "EVM.1.Txm", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Txm.BlockHistoryEstimator", - "attributes": { - "name": "EVM.1.Txm.BlockHistoryEstimator", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Txm.Broadcaster", - "attributes": { - "name": "EVM.1.Txm.Broadcaster", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Txm.Confirmer", - "attributes": { - "name": "EVM.1.Txm.Confirmer", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Txm.Finalizer", - "attributes": { - "name": "EVM.1.Txm.Finalizer", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "EVM.1.Txm.WrappedEvmEstimator", - "attributes": { - "name": "EVM.1.Txm.WrappedEvmEstimator", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "HeadReporter", - "attributes": { - "name": "HeadReporter", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Heartbeat", - "attributes": { - "name": "Heartbeat", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "JobSpawner", - "attributes": { - "name": "JobSpawner", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "LLOTransmissionReaper", - "attributes": { - "name": "LLOTransmissionReaper", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Mailbox.Monitor", - "attributes": { - "name": "Mailbox.Monitor", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Mercury.WSRPCPool", - "attributes": { - "name": "Mercury.WSRPCPool", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Mercury.WSRPCPool.CacheSet", - "attributes": { - "name": "Mercury.WSRPCPool.CacheSet", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "NodePlatformBuildInfo", - "attributes": { - "name": "NodePlatformBuildInfo", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "PipelineORM", - "attributes": { - "name": "PipelineORM", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "PipelineRunner", - "attributes": { - "name": "PipelineRunner", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "PipelineRunner.BridgeCache", - "attributes": { - "name": "PipelineRunner.BridgeCache", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "RetirementReportCache", - "attributes": { - "name": "RetirementReportCache", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain", - "attributes": { - "name": "Solana.Bar.Chain", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.BalanceMonitor", - "attributes": { - "name": "Solana.Bar.Chain.BalanceMonitor", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Chain.Txm", - "attributes": { - "name": "Solana.Bar.Chain.Txm", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "Solana.Bar.Relayer", - "attributes": { - "name": "Solana.Bar.Relayer", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "TelemetryManager", - "attributes": { - "name": "TelemetryManager", - "status": "passing", - "output": "" - } - }, - { - "type": "checks", - "id": "WorkflowStore", - "attributes": { - "name": "WorkflowStore", - "status": "passing", - "output": "" - } - } - ] -} --- out-unhealthy.json -- -{ - "data": [ - { - "type": "checks", - "id": "EVM.1.HeadTracker.HeadListener", - "attributes": { - "name": "EVM.1.HeadTracker.HeadListener", - "status": "failing", - "output": "Listener connected = false, receiving heads = false" - } - } - ] -} diff --git a/testdata/scripts/nodes/solana/list/list.txtar b/testdata/scripts/nodes/solana/list/list.txtar index dc65e06103f..81f5ec851f8 100644 --- a/testdata/scripts/nodes/solana/list/list.txtar +++ b/testdata/scripts/nodes/solana/list/list.txtar @@ -10,6 +10,7 @@ exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-versi exec chainlink --remote-node-url $NODEURL nodes solana list cmp stdout out.txt +-- go:build.integration -- -- testdb.txt -- CL_DATABASE_URL -- testport.txt -- From 7a1973e0d7fd543cac7758a607ba347dc22a914d Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Fri, 24 Apr 2026 22:02:03 -0500 Subject: [PATCH 10/25] revert removal, only remove solana --- testdata/scripts/health/multi-chain.txtar | 374 ++++++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 testdata/scripts/health/multi-chain.txtar diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar new file mode 100644 index 00000000000..ec3e64b65b4 --- /dev/null +++ b/testdata/scripts/health/multi-chain.txtar @@ -0,0 +1,374 @@ +# start node +exec sh -c 'eval "echo \"$(cat config.toml.tmpl)\" > config.toml"' +exec chainlink node -c config.toml start -p password -a creds & + +# initialize client +env NODEURL=http://localhost:$PORT +exec curl --retry 10 --retry-max-time 60 --retry-connrefused $NODEURL +exec chainlink --remote-node-url $NODEURL admin login -file creds --bypass-version-check + +exec chainlink --remote-node-url $NODEURL health +cmp stdout out.txt + +exec chainlink --remote-node-url $NODEURL health -json +cp stdout compact.json +exec jq . compact.json +cmp stdout out.json + +exec chainlink --remote-node-url $NODEURL health -failing +cmp stdout out-unhealthy.txt + +exec chainlink --remote-node-url $NODEURL health -f -json +cp stdout compact.json +exec jq . compact.json +cmp stdout out-unhealthy.json + +-- testdb.txt -- +CL_DATABASE_URL +-- testport.txt -- +PORT + +-- password -- +T.tLHkcmwePT/p,]sYuntjwHKAsrhm#4eRs4LuKHwvHejWYAC2JP4M8HimwgmbaZ +-- creds -- +notreal@fakeemail.ch +fj293fbBnlQ!f9vNs + +-- config.toml.tmpl -- +[Webserver] +HTTPPort = $PORT + +[[EVM]] +ChainID = '1' + +[[EVM.Nodes]] +Name = 'fake' +WSURL = 'wss://foo.bar/ws' +HTTPURL = 'https://foo.bar' + +-- out.txt -- +ok BridgeStatusReporter +ok CRE +ok CRE.DispatcherWrapper +ok EVM.1 +ok EVM.1.BalanceMonitor +ok EVM.1.HeadBroadcaster +ok EVM.1.HeadTracker +! EVM.1.HeadTracker.HeadListener + Listener connected = false, receiving heads = false +ok EVM.1.LogBroadcaster +ok EVM.1.Relayer +ok EVM.1.Txm +ok EVM.1.Txm.BlockHistoryEstimator +ok EVM.1.Txm.Broadcaster +ok EVM.1.Txm.Confirmer +ok EVM.1.Txm.Finalizer +ok EVM.1.Txm.WrappedEvmEstimator +ok HeadReporter +ok Heartbeat +ok JobSpawner +ok LLOTransmissionReaper +ok Mailbox.Monitor +ok Mercury.WSRPCPool +ok Mercury.WSRPCPool.CacheSet +ok NodePlatformBuildInfo +ok PipelineORM +ok PipelineRunner +ok PipelineRunner.BridgeCache +ok RetirementReportCache +ok TelemetryManager +ok WorkflowStore + +-- out-unhealthy.txt -- +! EVM.1.HeadTracker.HeadListener + Listener connected = false, receiving heads = false + +-- out.json -- +{ + "data": [ + { + "type": "checks", + "id": "BridgeStatusReporter", + "attributes": { + "name": "BridgeStatusReporter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "CRE", + "attributes": { + "name": "CRE", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "CRE.DispatcherWrapper", + "attributes": { + "name": "CRE.DispatcherWrapper", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1", + "attributes": { + "name": "EVM.1", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.BalanceMonitor", + "attributes": { + "name": "EVM.1.BalanceMonitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadBroadcaster", + "attributes": { + "name": "EVM.1.HeadBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadTracker", + "attributes": { + "name": "EVM.1.HeadTracker", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.HeadTracker.HeadListener", + "attributes": { + "name": "EVM.1.HeadTracker.HeadListener", + "status": "failing", + "output": "Listener connected = false, receiving heads = false" + } + }, + { + "type": "checks", + "id": "EVM.1.LogBroadcaster", + "attributes": { + "name": "EVM.1.LogBroadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Relayer", + "attributes": { + "name": "EVM.1.Relayer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm", + "attributes": { + "name": "EVM.1.Txm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.BlockHistoryEstimator", + "attributes": { + "name": "EVM.1.Txm.BlockHistoryEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Broadcaster", + "attributes": { + "name": "EVM.1.Txm.Broadcaster", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Confirmer", + "attributes": { + "name": "EVM.1.Txm.Confirmer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.Finalizer", + "attributes": { + "name": "EVM.1.Txm.Finalizer", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "EVM.1.Txm.WrappedEvmEstimator", + "attributes": { + "name": "EVM.1.Txm.WrappedEvmEstimator", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "HeadReporter", + "attributes": { + "name": "HeadReporter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Heartbeat", + "attributes": { + "name": "Heartbeat", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "JobSpawner", + "attributes": { + "name": "JobSpawner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "LLOTransmissionReaper", + "attributes": { + "name": "LLOTransmissionReaper", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mailbox.Monitor", + "attributes": { + "name": "Mailbox.Monitor", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool", + "attributes": { + "name": "Mercury.WSRPCPool", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Mercury.WSRPCPool.CacheSet", + "attributes": { + "name": "Mercury.WSRPCPool.CacheSet", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "NodePlatformBuildInfo", + "attributes": { + "name": "NodePlatformBuildInfo", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineORM", + "attributes": { + "name": "PipelineORM", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner", + "attributes": { + "name": "PipelineRunner", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "PipelineRunner.BridgeCache", + "attributes": { + "name": "PipelineRunner.BridgeCache", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "RetirementReportCache", + "attributes": { + "name": "RetirementReportCache", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "TelemetryManager", + "attributes": { + "name": "TelemetryManager", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "WorkflowStore", + "attributes": { + "name": "WorkflowStore", + "status": "passing", + "output": "" + } + } + ] +} +-- out-unhealthy.json -- +{ + "data": [ + { + "type": "checks", + "id": "EVM.1.HeadTracker.HeadListener", + "attributes": { + "name": "EVM.1.HeadTracker.HeadListener", + "status": "failing", + "output": "Listener connected = false, receiving heads = false" + } + } + ] +} From 6bbcac987f27b80bddd56e4e5cea9d65efffda46 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 12:04:24 -0500 Subject: [PATCH 11/25] rm no plugin test --- core/cmd/shell_test.go | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index b650f7ef138..f79d14d1a9c 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -408,23 +408,6 @@ func TestSetupSolanaRelayer(t *testing.T) { TOMLConfigs: tConfig.SolanaConfigs(), DS: ds} - // not parallel; shared state - t.Run("no plugin", func(t *testing.T) { - // CL_SOLANA_CMD is unset here. Solana is LOOP-only, so NewSolana must fall back to - // env.SolanaPlugin.CmdDefault (chainlink-solana) and still register each enabled chain. - // Use an isolated registry so this case doesn't collide with the shared one used by - // the "plugin" and "plugin already registered" subtests below. - isoReg := plugins.NewTestLoopRegistry(lggr) - isoRF := chainlink.RelayerFactory{Logger: lggr, LoopRegistry: isoReg} - - relayers, err := isoRF.NewSolana(ks, ksCSA, cfg) - require.NoError(t, err) - require.NotNil(t, relayers) - require.Len(t, relayers, nEnabledChains) - // the default plugin cmd is used, so the registry must contain one entry per chain - require.Len(t, isoReg.List(), nEnabledChains) - }) - t.Run("plugin", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") From 6dcbc46b60e9ba29d901305b8688ba7ed670d1bb Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 12:07:33 -0500 Subject: [PATCH 12/25] update comment --- .../chainlink/relayer_chain_interoperators_test.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index eeafea8b0ae..2d1ade7df49 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -198,11 +198,9 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedEVMChainCnt, tt.expectedEVMNodeCnt case relay.NetworkCosmos: expectedChainCnt, expectedNodeCnt = tt.expectedCosmosChainCnt, tt.expectedCosmosNodeCnt - // LOOP-only relayers (solana, aptos, tron, ton, sui) can't be exercised at - // this level without booting the LOOPP subprocess — ChainStatus/NodeStatus - // block on Wait until the plugin is started. Integration tests cover them - // end-to-end. Only networks with embedded (in-process) relayers are asserted - // here. + // LOOP-only relayers (solana, aptos, tron, ton, sui) can't be exercised at this level without booting + // the LOOPP subprocess, as ChainStatus/NodeStatus block on Wait until the plugin is started. Integration + // tests cover them end-to-end. Only networks with embedded (in-process) relayers are asserted here. case relay.NetworkSolana: t.Skip("solana is LOOP-only; exercised via integration tests") case relay.NetworkStarkNet: From 2130f0db1ca511fd6eae357e85808e4cbc6bd2a0 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 13:22:57 -0500 Subject: [PATCH 13/25] test: align solana interoperator test with cosmos/starknet pattern --- core/services/chainlink/config_test.go | 311 +++++++----------- .../relayer_chain_interoperators_test.go | 24 +- .../chainlink/testdata/config-full.toml | 96 +++--- .../config-multi-chain-effective.toml | 124 ++----- .../testdata/config-multi-chain.toml | 52 +-- 5 files changed, 240 insertions(+), 367 deletions(-) diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index 87ef592f7c2..ebbed878de9 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -9,7 +9,6 @@ import ( "testing" "time" - "github.com/gagliardetto/solana-go" "github.com/kylelemons/godebug/diff" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" @@ -25,8 +24,6 @@ import ( commontypes "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/hex" "github.com/smartcontractkit/chainlink-framework/multinode" - mnCfg "github.com/smartcontractkit/chainlink-framework/multinode/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-evm/pkg/assets" "github.com/smartcontractkit/chainlink-evm/pkg/config/chaintype" @@ -52,6 +49,26 @@ var ( minute = *commoncfg.MustNewDuration(time.Minute) selectionMode = multinode.NodeSelectionModeHighestHead + multiNodeRaw = map[string]any{ + "Enabled": false, + "PollFailureThreshold": int64(5), + "PollInterval": "1s", + "SelectionMode": "HighestHead", + "SyncThreshold": int64(5), + "NodeIsSyncingEnabled": false, + "LeaseDuration": "1m0s", + "NewHeadsPollInterval": "1s", + "FinalizedBlockPollInterval": "1s", + "EnforceRepeatableRead": true, + "DeathDeclarationDelay": "1m0s", + "VerifyChainID": true, + "NodeNoNewHeadsThreshold": "1m0s", + "NoNewFinalizedHeadsThreshold": "1m0s", + "FinalityDepth": int64(0), + "FinalityTagEnabled": true, + "FinalizedBlockOffset": int64(0), + } + multiChain = Config{ Core: toml.Core{ RootDir: ptr("my/root/dir"), @@ -156,65 +173,21 @@ var ( }, }}, }, - Solana: []*solcfg.TOMLConfig{ + Solana: RawConfigs{ { - ChainID: ptr("mainnet"), - Chain: solcfg.Chain{ - MaxRetries: ptr[int64](12), - }, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - Enabled: ptr(false), - PollFailureThreshold: ptr[uint32](5), - PollInterval: &second, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](5), - NodeIsSyncingEnabled: ptr(false), - LeaseDuration: &minute, - NewHeadsPollInterval: &second, - FinalizedBlockPollInterval: &second, - EnforceRepeatableRead: ptr(true), - DeathDeclarationDelay: &minute, - VerifyChainID: ptr(true), - NodeNoNewHeadsThreshold: &minute, - NoNewFinalizedHeadsThreshold: &minute, - FinalityDepth: ptr[uint32](0), - FinalityTagEnabled: ptr(true), - FinalizedBlockOffset: ptr[uint32](0), - }, - }, - Nodes: []*solcfg.Node{ - {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://mainnet.solana.com"), Order: ptr(int32(1))}, + "ChainID": "mainnet", + "MaxRetries": int64(12), + "MultiNode": multiNodeRaw, + "Nodes": []any{ + map[string]any{"Name": "primary", "URL": "http://mainnet.solana.com", "SendOnly": false, "Order": int64(1)}, }, }, { - ChainID: ptr("testnet"), - Chain: solcfg.Chain{ - OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), - }, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - Enabled: ptr(false), - PollFailureThreshold: ptr[uint32](5), - PollInterval: &second, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](5), - NodeIsSyncingEnabled: ptr(false), - LeaseDuration: &minute, - NewHeadsPollInterval: &second, - FinalizedBlockPollInterval: &second, - EnforceRepeatableRead: ptr(true), - DeathDeclarationDelay: &minute, - VerifyChainID: ptr(true), - NodeNoNewHeadsThreshold: &minute, - NoNewFinalizedHeadsThreshold: &minute, - FinalityDepth: ptr[uint32](0), - FinalityTagEnabled: ptr(true), - FinalizedBlockOffset: ptr[uint32](0), - }, - }, - Nodes: []*solcfg.Node{ - {Name: ptr("secondary"), URL: commoncfg.MustParseURL("http://testnet.solana.com"), Order: ptr(int32(2))}, + "ChainID": "testnet", + "OCR2CachePollPeriod": "1m0s", + "MultiNode": multiNodeRaw, + "Nodes": []any{ + map[string]any{"Name": "secondary", "URL": "http://testnet.solana.com", "SendOnly": false, "Order": int64(2)}, }, }, }, @@ -878,73 +851,51 @@ func TestConfig_Marshal(t *testing.T) { }, }}, } - full.Solana = []*solcfg.TOMLConfig{ + full.Solana = RawConfigs{ { - ChainID: ptr("mainnet"), - Enabled: ptr(false), - Chain: solcfg.Chain{ - BlockTime: commoncfg.MustNewDuration(500 * time.Millisecond), - BalancePollPeriod: commoncfg.MustNewDuration(time.Minute), - ConfirmPollPeriod: commoncfg.MustNewDuration(time.Second), - OCR2CachePollPeriod: commoncfg.MustNewDuration(time.Minute), - OCR2CacheTTL: commoncfg.MustNewDuration(time.Hour), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - TxRetryTimeout: commoncfg.MustNewDuration(time.Minute), - TxConfirmTimeout: commoncfg.MustNewDuration(time.Second), - TxExpirationRebroadcast: ptr(false), - TxRetentionTimeout: commoncfg.MustNewDuration(0 * time.Second), - SkipPreflight: ptr(true), - Commitment: ptr("banana"), - MaxRetries: ptr[int64](7), - FeeEstimatorMode: ptr("fixed"), - ComputeUnitPriceMax: ptr[uint64](1000), - ComputeUnitPriceMin: ptr[uint64](10), - ComputeUnitPriceDefault: ptr[uint64](100), - FeeBumpPeriod: commoncfg.MustNewDuration(time.Minute), - BlockHistoryPollPeriod: commoncfg.MustNewDuration(time.Minute), - BlockHistorySize: ptr[uint64](1), - BlockHistoryBatchLoadSize: ptr[uint64](20), - ComputeUnitLimitDefault: ptr[uint32](100_000), - EstimateComputeUnitLimit: ptr(false), - LogPollerStartingLookback: commoncfg.MustNewDuration(24 * time.Hour), - LogPollerCPIEventsEnabled: ptr(true), - LogPollerSlotsBatchSize: ptr[int64](100), - }, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - Enabled: ptr(false), - PollFailureThreshold: ptr[uint32](5), - PollInterval: &second, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](5), - NodeIsSyncingEnabled: ptr(false), - LeaseDuration: &minute, - NewHeadsPollInterval: &second, - FinalizedBlockPollInterval: &second, - EnforceRepeatableRead: ptr(true), - DeathDeclarationDelay: &minute, - VerifyChainID: ptr(true), - NodeNoNewHeadsThreshold: &minute, - NoNewFinalizedHeadsThreshold: &minute, - FinalityDepth: ptr[uint32](0), - FinalityTagEnabled: ptr(true), - FinalizedBlockOffset: ptr[uint32](0), - }, - }, - Nodes: []*solcfg.Node{ - {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://solana.web"), Order: ptr(int32(1))}, - {Name: ptr("foo"), URL: commoncfg.MustParseURL("http://solana.foo"), SendOnly: true, Order: ptr(int32(2))}, - {Name: ptr("bar"), URL: commoncfg.MustParseURL("http://solana.bar"), SendOnly: true, Order: ptr(int32(3))}, + "ChainID": "mainnet", + "Enabled": false, + "BlockTime": "500ms", + "BalancePollPeriod": "1m0s", + "ConfirmPollPeriod": "1s", + "OCR2CachePollPeriod": "1m0s", + "OCR2CacheTTL": "1h0m0s", + "TxTimeout": "1h0m0s", + "TxRetryTimeout": "1m0s", + "TxConfirmTimeout": "1s", + "TxExpirationRebroadcast": false, + "TxRetentionTimeout": "0s", + "SkipPreflight": true, + "Commitment": "banana", + "MaxRetries": int64(7), + "FeeEstimatorMode": "fixed", + "ComputeUnitPriceMax": int64(1000), + "ComputeUnitPriceMin": int64(10), + "ComputeUnitPriceDefault": int64(100), + "FeeBumpPeriod": "1m0s", + "BlockHistoryPollPeriod": "1m0s", + "BlockHistorySize": int64(1), + "BlockHistoryBatchLoadSize": int64(20), + "ComputeUnitLimitDefault": int64(100_000), + "EstimateComputeUnitLimit": false, + "LogPollerStartingLookback": "24h0m0s", + "LogPollerCPIEventsEnabled": true, + "LogPollerSlotsBatchSize": int64(100), + "MultiNode": multiNodeRaw, + "Workflow": map[string]any{ + "AcceptanceTimeout": "45s", + "ForwarderAddress": "14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5", + "ForwarderState": "14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5", + "FromAddress": "4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e", + "GasLimitDefault": int64(0), + "Local": true, + "PollPeriod": "3s", + "TxAcceptanceState": int64(commontypes.Finalized), }, - Workflow: solcfg.WorkflowConfig{ - AcceptanceTimeout: commoncfg.MustNewDuration(time.Second * 45), - FromAddress: ptr(solana.MustPublicKeyFromBase58("4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e")), - ForwarderAddress: ptr(solana.MustPublicKeyFromBase58("14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5")), - ForwarderState: ptr(solana.MustPublicKeyFromBase58("14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5")), - TxAcceptanceState: ptr(commontypes.Finalized), - PollPeriod: commoncfg.MustNewDuration(time.Second * 3), - Local: ptr(true), - GasLimitDefault: ptr(uint64(0)), + "Nodes": []any{ + map[string]any{"Name": "primary", "URL": "http://solana.web", "SendOnly": false, "Order": int64(1)}, + map[string]any{"Name": "foo", "URL": "http://solana.foo", "SendOnly": true, "Order": int64(2)}, + map[string]any{"Name": "bar", "URL": "http://solana.bar", "SendOnly": true, "Order": int64(3)}, }, }, } @@ -1404,81 +1355,81 @@ HTTPURL = 'http://broadcast.mirror' SendOnly = true `}, {"Solana", Config{Solana: full.Solana}, `[[Solana]] -ChainID = 'mainnet' -Enabled = false -BlockTime = '500ms' BalancePollPeriod = '1m0s' -ConfirmPollPeriod = '1s' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '1m0s' -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'banana' -MaxRetries = 7 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 10 -ComputeUnitPriceDefault = 100 -FeeBumpPeriod = '1m0s' +BlockHistoryBatchLoadSize = 20 BlockHistoryPollPeriod = '1m0s' BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 +BlockTime = '500ms' +ChainID = 'mainnet' +Commitment = 'banana' ComputeUnitLimitDefault = 100000 +ComputeUnitPriceDefault = 100 +ComputeUnitPriceMax = 1000 +ComputeUnitPriceMin = 10 +ConfirmPollPeriod = '1s' +Enabled = false EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' +FeeBumpPeriod = '1m0s' +FeeEstimatorMode = 'fixed' LogPollerCPIEventsEnabled = true LogPollerSlotsBatchSize = 100 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 +LogPollerStartingLookback = '24h0m0s' +MaxRetries = 7 +OCR2CachePollPeriod = '1m0s' +OCR2CacheTTL = '1h0m0s' +SkipPreflight = true +TxConfirmTimeout = '1s' +TxExpirationRebroadcast = false +TxRetentionTimeout = '0s' +TxRetryTimeout = '1m0s' +TxTimeout = '1h0m0s' [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '1s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://solana.web' -SendOnly = false Order = 1 +SendOnly = false +URL = 'http://solana.web' [[Solana.Nodes]] Name = 'foo' -URL = 'http://solana.foo' -SendOnly = true Order = 2 +SendOnly = true +URL = 'http://solana.foo' [[Solana.Nodes]] Name = 'bar' -URL = 'http://solana.bar' -SendOnly = true Order = 3 +SendOnly = true +URL = 'http://solana.bar' + +[Solana.Workflow] +AcceptanceTimeout = '45s' +ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' +ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' +FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' +GasLimitDefault = 0 +Local = true +PollPeriod = '3s' +TxAcceptanceState = 3 `}, {"Mercury", Config{Core: toml.Core{Mercury: full.Mercury}}, `[Mercury] VerboseLogging = true @@ -1593,14 +1544,6 @@ func TestConfig_full(t *testing.T) { } } - for c := range got.Solana { - for n := range got.Solana[c].Nodes { - if got.Solana[c].Nodes[n].IsLoadBalancedRPC == nil { - got.Solana[c].Nodes[n].IsLoadBalancedRPC = ptr(false) - } - } - } - configtest.AssertFieldsNotNil(t, got) } @@ -1691,11 +1634,11 @@ func TestConfig_Validate(t *testing.T) { - Nodes: missing: expected at least one node - Solana: 4 errors: - 1.ChainID: invalid value (mainnet): duplicate - must be unique - - 0.Nodes: missing: must have at least one node - - 1.Nodes.0.URL: missing: required for all nodes + - 1.Nodes.1.Name: invalid value (bar): duplicate - must be unique + - 0.Nodes: missing: expected at least one node - 2: 2 errors: - - ChainID: empty: required for all chains - - Nodes: missing: must have at least one node + - ChainID: missing: required for all chains + - Nodes: missing: expected at least one node - Starknet: 3 errors: - 0.Nodes.1.Name: invalid value (primary): duplicate - must be unique - 0.ChainID: missing: required for all chains @@ -1943,7 +1886,7 @@ func TestConfig_setDefaults(t *testing.T) { var c Config c.EVM = evmcfg.EVMConfigs{{ChainID: sqlutil.NewI(99999133712345)}} c.Cosmos = RawConfigs{{"ChainID": ptr("unknown cosmos chain")}} - c.Solana = solcfg.TOMLConfigs{{ChainID: ptr("unknown solana chain")}} + c.Solana = RawConfigs{{"ChainID": ptr("unknown solana chain")}} c.Starknet = RawConfigs{{"ChainID": ptr("unknown starknet chain")}} c.setDefaults() diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 2d1ade7df49..df545cab676 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -108,6 +108,9 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedCosmosChainCnt int expectedCosmosNodeCnt int + + expectedSolanaChainCnt int + expectedSolanaNodeCnt int }{ {name: "2 evm chains with 3 nodes", @@ -151,6 +154,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { }), chainlink.InitStarknet(factory, keyStore.StarkNet(), keyStore.CSA(), cfg.StarknetConfigs()), chainlink.InitCosmos(factory, keyStore.Cosmos(), keyStore.CSA(), cfg.CosmosConfigs()), + chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), chainlink.SolanaFactoryConfig{ + TOMLConfigs: cfg.SolanaConfigs()}), }, expectedEVMChainCnt: 2, expectedEVMNodeCnt: 3, @@ -159,7 +164,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { {Network: relay.NetworkEVM, ChainID: evmChainID2.String()}, }, - expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}, relay.NetworkCosmos: {}, relay.NetworkStarkNet: {}}, + expectedRelayerNetworks: map[string]struct{}{relay.NetworkEVM: {}, relay.NetworkCosmos: {}, relay.NetworkSolana: {}, relay.NetworkStarkNet: {}}, }, } for _, tt := range tests { @@ -172,7 +177,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { cr, err = chainlink.NewCoreRelayerChainInteroperators(tt.initFuncs...) require.NoError(t, err) - expectedChainCnt := tt.expectedEVMChainCnt + tt.expectedCosmosChainCnt + tt.expectedStarknetChainCnt + expectedChainCnt := tt.expectedEVMChainCnt + tt.expectedCosmosChainCnt + tt.expectedSolanaChainCnt + tt.expectedStarknetChainCnt allChainsStats, cnt, err := cr.ChainStatuses(testctx, 0, 0) assert.NoError(t, err) assert.Len(t, allChainsStats, expectedChainCnt) @@ -183,7 +188,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { assert.Len(t, cr.Slice(), expectedChainCnt) assert.Len(t, cr.Services(), expectedChainCnt) - expectedNodeCnt := tt.expectedEVMNodeCnt + tt.expectedCosmosNodeCnt + tt.expectedStarknetNodeCnt + expectedNodeCnt := tt.expectedEVMNodeCnt + tt.expectedCosmosNodeCnt + tt.expectedSolanaNodeCnt + tt.expectedStarknetNodeCnt allNodeStats, cnt, err := cr.NodeStatuses(testctx, 0, 0) assert.NoError(t, err) assert.Len(t, allNodeStats, expectedNodeCnt) @@ -198,23 +203,20 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedEVMChainCnt, tt.expectedEVMNodeCnt case relay.NetworkCosmos: expectedChainCnt, expectedNodeCnt = tt.expectedCosmosChainCnt, tt.expectedCosmosNodeCnt - // LOOP-only relayers (solana, aptos, tron, ton, sui) can't be exercised at this level without booting - // the LOOPP subprocess, as ChainStatus/NodeStatus block on Wait until the plugin is started. Integration - // tests cover them end-to-end. Only networks with embedded (in-process) relayers are asserted here. case relay.NetworkSolana: - t.Skip("solana is LOOP-only; exercised via integration tests") + expectedChainCnt, expectedNodeCnt = tt.expectedSolanaChainCnt, tt.expectedSolanaNodeCnt case relay.NetworkStarkNet: expectedChainCnt, expectedNodeCnt = tt.expectedStarknetChainCnt, tt.expectedStarknetNodeCnt case relay.NetworkDummy: expectedChainCnt, expectedNodeCnt = tt.expectedDummyChainCnt, tt.expectedDummyNodeCnt case relay.NetworkAptos: - t.Skip("aptos is LOOP-only; exercised via integration tests") + t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") case relay.NetworkTron: - t.Skip("tron is LOOP-only; exercised via integration tests") + t.Skip("tron doesn't need a CoreRelayerChainInteroperator") case relay.NetworkTON: - t.Skip("ton is LOOP-only; exercised via integration tests") + t.Skip("ton doesn't need a CoreRelayerChainInteroperator") case relay.NetworkSui: - t.Skip("sui is LOOP-only; exercised via integration tests") + t.Skip("sui doesn't need a CoreRelayerChainInteroperator") default: require.Fail(t, "untested relay network", relayNetwork) diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index a784f98a591..e6e32f98cd8 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -619,78 +619,78 @@ HTTPURL = 'http://broadcast.mirror' SendOnly = true [[Solana]] -ChainID = 'mainnet' -Enabled = false -BlockTime = '500ms' BalancePollPeriod = '1m0s' -ConfirmPollPeriod = '1s' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '1m0s' -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'banana' -MaxRetries = 7 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 10 -ComputeUnitPriceDefault = 100 -FeeBumpPeriod = '1m0s' +BlockHistoryBatchLoadSize = 20 BlockHistoryPollPeriod = '1m0s' BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 +BlockTime = '500ms' +ChainID = 'mainnet' +Commitment = 'banana' ComputeUnitLimitDefault = 100000 +ComputeUnitPriceDefault = 100 +ComputeUnitPriceMax = 1000 +ComputeUnitPriceMin = 10 +ConfirmPollPeriod = '1s' +Enabled = false EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' +FeeBumpPeriod = '1m0s' +FeeEstimatorMode = 'fixed' LogPollerCPIEventsEnabled = true LogPollerSlotsBatchSize = 100 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 +LogPollerStartingLookback = '24h0m0s' +MaxRetries = 7 +OCR2CachePollPeriod = '1m0s' +OCR2CacheTTL = '1h0m0s' +SkipPreflight = true +TxConfirmTimeout = '1s' +TxExpirationRebroadcast = false +TxRetentionTimeout = '0s' +TxRetryTimeout = '1m0s' +TxTimeout = '1h0m0s' [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '1s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://solana.web' -SendOnly = false Order = 1 +SendOnly = false +URL = 'http://solana.web' [[Solana.Nodes]] Name = 'foo' -URL = 'http://solana.foo' -SendOnly = true Order = 2 +SendOnly = true +URL = 'http://solana.foo' [[Solana.Nodes]] Name = 'bar' -URL = 'http://solana.bar' -SendOnly = true Order = 3 +SendOnly = true +URL = 'http://solana.bar' + +[Solana.Workflow] +AcceptanceTimeout = '45s' +ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' +ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' +FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' +GasLimitDefault = 0 +Local = true +PollPeriod = '3s' +TxAcceptanceState = 3 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index ee3c20150eb..864ca6a7ea0 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -771,130 +771,58 @@ WSURL = 'wss://web.socket/test/bar' [[Solana]] ChainID = 'mainnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' MaxRetries = 12 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '1s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://mainnet.solana.com' -SendOnly = false Order = 1 +SendOnly = false +URL = 'http://mainnet.solana.com' [[Solana]] ChainID = 'testnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '1s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'secondary' -URL = 'http://testnet.solana.com' -SendOnly = false Order = 2 +SendOnly = false +URL = 'http://testnet.solana.com' diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index 7db000b7c85..0c6bbd6f539 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -82,55 +82,55 @@ ChainID = 'mainnet' MaxRetries = 12 [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '1s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://mainnet.solana.com' -SendOnly = false Order = 1 +SendOnly = false +URL = 'http://mainnet.solana.com' [[Solana]] ChainID = 'testnet' OCR2CachePollPeriod = '1m0s' [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '1s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'secondary' -URL = 'http://testnet.solana.com' -SendOnly = false Order = 2 +SendOnly = false +URL = 'http://testnet.solana.com' From b220ea479ed24072e537ca54c017c59726a662f1 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 15:06:48 -0500 Subject: [PATCH 14/25] refactor solana relay config to use raw unwrapped --- core/cmd/blocks_commands_integration_test.go | 10 +- core/cmd/chains_commands_integration_test.go | 10 +- core/cmd/node_commands_integration_test.go | 34 +++-- core/cmd/shell_test.go | 87 +++++-------- core/cmd/solana_transaction_commands_test.go | 19 ++- core/scripts/go.mod | 2 +- core/scripts/go.sum | 2 + core/services/chainlink/application.go | 6 +- core/services/chainlink/config.go | 12 +- core/services/chainlink/config_general.go | 3 +- .../chainlink/mocks/general_config.go | 13 +- .../chainlink/relayer_chain_interoperators.go | 4 +- .../relayer_chain_interoperators_test.go | 3 +- core/services/chainlink/relayer_factory.go | 57 +-------- core/services/chainlink/types.go | 4 +- .../web/chains_controller_integration_test.go | 46 +++---- core/web/resolver/testdata/config-full.toml | 90 ++++++------- .../config-multi-chain-effective.toml | 119 ++++-------------- .../resolver/testdata/config-multi-chain.toml | 46 +++---- deployment/go.mod | 2 +- deployment/go.sum | 2 + deployment/utils/nodetestutils/node.go | 47 +++---- go.mod | 2 +- go.sum | 2 + integration-tests/go.mod | 2 +- integration-tests/go.sum | 2 + integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 2 + plugins/plugins.public.yaml | 2 +- system-tests/lib/cre/don/config/config.go | 17 ++- .../lib/cre/features/solana/v2/solana.go | 12 +- system-tests/lib/go.mod | 2 +- system-tests/lib/go.sum | 2 + system-tests/tests/go.mod | 2 +- system-tests/tests/go.sum | 2 + 35 files changed, 232 insertions(+), 437 deletions(-) diff --git a/core/cmd/blocks_commands_integration_test.go b/core/cmd/blocks_commands_integration_test.go index 3bd0939a2c0..b29706d5b86 100644 --- a/core/cmd/blocks_commands_integration_test.go +++ b/core/cmd/blocks_commands_integration_test.go @@ -9,17 +9,17 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" ) func Test_ReplayFromBlock_Solana(t *testing.T) { t.Parallel() - cfg := solcfg.TOMLConfig{ - ChainID: ptr("devnet"), - Enabled: ptr(true), + chain := chainlink.RawConfig{ + "ChainID": "devnet", + "Enabled": true, } - app := solanaStartNewApplication(t, &cfg) + app := solanaStartNewApplication(t, chain) client, _ := app.NewShellAndRenderer() set := flag.NewFlagSet("test", 0) diff --git a/core/cmd/chains_commands_integration_test.go b/core/cmd/chains_commands_integration_test.go index 832d487f7a7..e78ea4a0ddb 100644 --- a/core/cmd/chains_commands_integration_test.go +++ b/core/cmd/chains_commands_integration_test.go @@ -8,8 +8,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/cosmostest" @@ -43,11 +41,11 @@ func TestShell_IndexSolanaChains(t *testing.T) { t.Parallel() id := solanatest.RandomChainID() - cfg := solcfg.TOMLConfig{ - ChainID: &id, - Enabled: ptr(true), + chain := chainlink.RawConfig{ + "ChainID": id, + "Enabled": true, } - app := solanaStartNewApplication(t, &cfg) + app := solanaStartNewApplication(t, chain) client, r := app.NewShellAndRenderer() require.NoError(t, cmd.NewChainClient(client, "solana").IndexChains(cltest.EmptyCLIContext())) diff --git a/core/cmd/node_commands_integration_test.go b/core/cmd/node_commands_integration_test.go index 17b980d9c43..4c16d12649c 100644 --- a/core/cmd/node_commands_integration_test.go +++ b/core/cmd/node_commands_integration_test.go @@ -12,7 +12,6 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -28,10 +27,7 @@ func cosmosStartNewApplication(t *testing.T, cfgs ...chainlink.RawConfig) *cltes }) } -func solanaStartNewApplication(t *testing.T, cfgs ...*solcfg.TOMLConfig) *cltest.TestApplication { - for i := range cfgs { - cfgs[i].SetDefaults() - } +func solanaStartNewApplication(t *testing.T, cfgs ...chainlink.RawConfig) *cltest.TestApplication { return startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Solana = cfgs c.EVM = nil @@ -150,19 +146,19 @@ func TestShell_IndexSolanaNodes(t *testing.T) { t.Parallel() id := solanatest.RandomChainID() - node1 := solcfg.Node{ - Name: ptr("first"), - URL: config.MustParseURL("https://solana1.example"), + node1 := map[string]any{ + "Name": ptr("first"), + "URL": config.MustParseURL("https://solana1.example"), } - node2 := solcfg.Node{ - Name: ptr("second"), - URL: config.MustParseURL("https://solana2.example"), + node2 := map[string]any{ + "Name": ptr("second"), + "URL": config.MustParseURL("https://solana2.example"), } - chain := solcfg.TOMLConfig{ - ChainID: &id, - Nodes: solcfg.Nodes{&node1, &node2}, + chain := chainlink.RawConfig{ + "ChainID": id, + "Nodes": []any{node1, node2}, } - app := solanaStartNewApplication(t, &chain) + app := solanaStartNewApplication(t, chain) client, r := app.NewShellAndRenderer() require.NoError(t, cmd.NewNodeClient(client, "solana").IndexNodes(cltest.EmptyCLIContext())) @@ -172,14 +168,14 @@ func TestShell_IndexSolanaNodes(t *testing.T) { n1 := nodes[0] n2 := nodes[1] assert.Equal(t, id, n1.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node1.Name), n1.ID) - assert.Equal(t, *node1.Name, n1.Name) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, "first"), n1.ID) + assert.Equal(t, "first", n1.Name) wantConfig, err := toml.Marshal(node1) require.NoError(t, err) assert.Equal(t, string(wantConfig), n1.Config) assert.Equal(t, id, n2.ChainID) - assert.Equal(t, cltest.FormatWithPrefixedChainID(id, *node2.Name), n2.ID) - assert.Equal(t, *node2.Name, n2.Name) + assert.Equal(t, cltest.FormatWithPrefixedChainID(id, "second"), n2.ID) + assert.Equal(t, "second", n2.Name) wantConfig2, err := toml.Marshal(node2) require.NoError(t, err) assert.Equal(t, string(wantConfig2), n2.Config) diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index f79d14d1a9c..905b57501b4 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -20,9 +20,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/beholder/beholdertest" commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil/sqltest" commonevents "github.com/smartcontractkit/chainlink-protos/workflows/go/common" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -358,45 +356,36 @@ func TestNewUserCache(t *testing.T) { func TestSetupSolanaRelayer(t *testing.T) { lggr := logger.TestLogger(t) reg := plugins.NewTestLoopRegistry(lggr) - ks := &keystore.StarknetLooppSigner{StarkNet: mocks.NewStarkNet(t)} + ks := &keystore.SolanaLooppSigner{Solana: mocks.NewSolana(t)} ksCSA := &keystore.CSASigner{CSA: mocks.NewCSA(t)} - ds := sqltest.NewNoOpDataSource() // config 3 chains but only enable 2 => should only be 2 relayer nEnabledChains := 2 tConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: ptr[string]("solana-id-1"), - Enabled: ptr(true), - Nodes: []*solcfg.Node{}, + c.Solana = chainlink.RawConfigs{ + { + "ChainID": "solana-id-1", + "Enabled": true, }, - &solcfg.TOMLConfig{ - ChainID: ptr[string]("solana-id-2"), - Enabled: ptr(true), - Nodes: []*solcfg.Node{}, + { + "ChainID": "solana-id-2", + "Enabled": true, }, - &solcfg.TOMLConfig{ - ChainID: ptr[string]("disabled-solana-id-1"), - Enabled: ptr(false), - Nodes: []*solcfg.Node{}, + { + "ChainID": "disabled-solana-id-1", + "Enabled": false, }, } - for i := range c.Solana { - c.Solana[i].SetDefaults() - } }) t2Config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: ptr[string]("solana-id-1"), - Enabled: ptr(true), - Nodes: []*solcfg.Node{}, + c.Solana = chainlink.RawConfigs{ + { + "ChainID": "solana-id-1", + "Enabled": true, }, } - c.Solana[0].SetDefaults() }) rf := chainlink.RelayerFactory{ @@ -404,14 +393,10 @@ func TestSetupSolanaRelayer(t *testing.T) { LoopRegistry: reg, } - cfg := chainlink.SolanaFactoryConfig{ - TOMLConfigs: tConfig.SolanaConfigs(), - DS: ds} - t.Run("plugin", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - relayers, err := rf.NewSolana(ks, ksCSA, cfg) + relayers, err := rf.NewSolana(ks, ksCSA, tConfig.SolanaConfigs()) require.NoError(t, err) require.NotNil(t, relayers) require.Len(t, relayers, nEnabledChains) @@ -421,34 +406,21 @@ func TestSetupSolanaRelayer(t *testing.T) { // test that duplicate enabled chains is an error when duplicateConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = solcfg.TOMLConfigs{ - &solcfg.TOMLConfig{ - ChainID: ptr[string]("dupe"), - Enabled: ptr(true), + c.Solana = chainlink.RawConfigs{ + { + "ChainID": "dupe", + "Enabled": true, }, - &solcfg.TOMLConfig{ - ChainID: ptr[string]("dupe"), - Enabled: ptr(true), + { + "ChainID": "dupe", + "Enabled": true, }, } - for i := range c.Solana { - c.Solana[i].SetDefaults() - } - }) - dupCfg := chainlink.SolanaFactoryConfig{ - TOMLConfigs: duplicateConfig.SolanaConfigs(), - DS: ds, - } - - // not parallel; shared state - t.Run("no plugin, duplicate chains", func(t *testing.T) { - _, err := rf.NewSolana(ks, ksCSA, dupCfg) - require.Error(t, err) }) t.Run("plugin, duplicate chains", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(ks, ksCSA, dupCfg) + _, err := rf.NewSolana(ks, ksCSA, duplicateConfig.SolanaConfigs()) require.Error(t, err) }) @@ -456,20 +428,17 @@ func TestSetupSolanaRelayer(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") t.Setenv("CL_SOLANA_ENV", "fake_path") - _, err := rf.NewSolana(ks, ksCSA, chainlink.SolanaFactoryConfig{ - TOMLConfigs: t2Config.SolanaConfigs(), - DS: ds, - }) + _, err := rf.NewSolana(ks, ksCSA, t2Config.SolanaConfigs()) require.Error(t, err) - require.Contains(t, err.Error(), "failed to parse Solana env file") + require.Contains(t, err.Error(), "failed to parse env file") }) t.Run("plugin already registered", func(t *testing.T) { t.Setenv("CL_SOLANA_CMD", "phony_solana_cmd") - _, err := rf.NewSolana(ks, ksCSA, cfg) + _, err := rf.NewSolana(ks, ksCSA, tConfig.SolanaConfigs()) require.Error(t, err) - require.Contains(t, err.Error(), "failed to create Solana LOOP command") + require.Contains(t, err.Error(), "failed to create LOOP command") }) } diff --git a/core/cmd/solana_transaction_commands_test.go b/core/cmd/solana_transaction_commands_test.go index b7623840095..7d4031d7d2a 100644 --- a/core/cmd/solana_transaction_commands_test.go +++ b/core/cmd/solana_transaction_commands_test.go @@ -15,10 +15,9 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" - "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" solanatesting "github.com/smartcontractkit/chainlink-solana/pkg/solana/testing" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/cmd" ) @@ -28,16 +27,14 @@ func TestShell_SolanaSendSol(t *testing.T) { ctx := testutils.Context(t) chainID := "localnet" url := solanatesting.SetupLocalSolNode(t) - node := solcfg.Node{ - Name: ptr(t.Name()), - URL: config.MustParseURL(url), + chain := chainlink.RawConfig{ + "ChainID": chainID, + "Enabled": true, + "Nodes": []any{ + map[string]any{"Name": t.Name(), "URL": url}, + }, } - cfg := solcfg.TOMLConfig{ - ChainID: &chainID, - Nodes: solcfg.Nodes{&node}, - Enabled: ptr(true), - } - app := solanaStartNewApplication(t, &cfg) + app := solanaStartNewApplication(t, chain) from, err := app.GetKeyStore().Solana().Create(ctx) require.NoError(t, err) to, err := solanago.NewRandomPrivateKey() diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 024dcdd64dc..53cb2df0c17 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -514,7 +514,7 @@ require ( github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 // indirect github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260409184948-5b16fae57fe0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 0359a597ff4..8bd31ad21b0 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1714,6 +1714,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index b9f70144d12..430d58defc8 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -327,11 +327,7 @@ func NewApplication(ctx context.Context, opts ApplicationOpts) (Application, err initOps = append(initOps, InitCosmos(relayerFactory, keyStore.Cosmos(), keyStore.CSA(), cfg.CosmosConfigs())) } if cfg.SolanaEnabled() { - solanaCfg := SolanaFactoryConfig{ - TOMLConfigs: cfg.SolanaConfigs(), - DS: opts.DS, - } - initOps = append(initOps, InitSolana(relayerFactory, keyStore.Solana(), keyStore.CSA(), solanaCfg)) + initOps = append(initOps, InitSolana(relayerFactory, keyStore.Solana(), keyStore.CSA(), cfg.SolanaConfigs())) } if cfg.StarkNetEnabled() { initOps = append(initOps, InitStarknet(relayerFactory, keyStore.StarkNet(), keyStore.CSA(), cfg.StarknetConfigs())) diff --git a/core/services/chainlink/config.go b/core/services/chainlink/config.go index 160beb95e30..e65da56a227 100644 --- a/core/services/chainlink/config.go +++ b/core/services/chainlink/config.go @@ -10,7 +10,6 @@ import ( gotoml "github.com/pelletier/go-toml/v2" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" configtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config/docs" @@ -37,7 +36,7 @@ type Config struct { Cosmos RawConfigs `toml:",omitempty"` - Solana solcfg.TOMLConfigs `toml:",omitempty"` + Solana RawConfigs `toml:",omitempty"` Starknet RawConfigs `toml:",omitempty"` @@ -334,12 +333,7 @@ func (c *Config) setDefaults() { c.Cosmos.SetDefaults() - for i := range c.Solana { - if c.Solana[i] == nil { - c.Solana[i] = new(solcfg.TOMLConfig) - } - c.Solana[i].SetDefaults() - } + c.Solana.SetDefaults() c.Starknet.SetDefaults() @@ -361,7 +355,7 @@ func (c *Config) SetFrom(f *Config) (err error) { appendErr(c.EVM.SetFrom(&f.EVM), "EVM") appendErr(c.Cosmos.SetFrom(f.Cosmos), "Cosmos") - appendErr(c.Solana.SetFrom(&f.Solana), "Solana") + appendErr(c.Solana.SetFrom(f.Solana), "Solana") appendErr(c.Starknet.SetFrom(f.Starknet), "Starknet") appendErr(c.Aptos.SetFrom(f.Aptos), "Aptos") appendErr(c.Tron.SetFrom(f.Tron), "Tron") diff --git a/core/services/chainlink/config_general.go b/core/services/chainlink/config_general.go index ed18c6ca7a0..66f9a27294a 100644 --- a/core/services/chainlink/config_general.go +++ b/core/services/chainlink/config_general.go @@ -15,7 +15,6 @@ import ( commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" evmcfg "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-common/keystore/corekeys" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/p2pkey" @@ -202,7 +201,7 @@ func (g *generalConfig) CosmosConfigs() RawConfigs { return g.c.Cosmos } -func (g *generalConfig) SolanaConfigs() solcfg.TOMLConfigs { +func (g *generalConfig) SolanaConfigs() RawConfigs { return g.c.Solana } diff --git a/core/services/chainlink/mocks/general_config.go b/core/services/chainlink/mocks/general_config.go index d6d602c9899..fb2df951ef5 100644 --- a/core/services/chainlink/mocks/general_config.go +++ b/core/services/chainlink/mocks/general_config.go @@ -7,7 +7,6 @@ import ( uuid "github.com/google/uuid" toml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" - solanaconfig "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" config "github.com/smartcontractkit/chainlink/v2/core/config" chainlink "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" mock "github.com/stretchr/testify/mock" @@ -2098,19 +2097,19 @@ func (_c *GeneralConfig_ShutdownGracePeriod_Call) RunAndReturn(run func() time.D } // SolanaConfigs provides a mock function with no fields -func (_m *GeneralConfig) SolanaConfigs() solanaconfig.TOMLConfigs { +func (_m *GeneralConfig) SolanaConfigs() chainlink.RawConfigs { ret := _m.Called() if len(ret) == 0 { panic("no return value specified for SolanaConfigs") } - var r0 solanaconfig.TOMLConfigs - if rf, ok := ret.Get(0).(func() solanaconfig.TOMLConfigs); ok { + var r0 chainlink.RawConfigs + if rf, ok := ret.Get(0).(func() chainlink.RawConfigs); ok { r0 = rf() } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(solanaconfig.TOMLConfigs) + r0 = ret.Get(0).(chainlink.RawConfigs) } } @@ -2134,12 +2133,12 @@ func (_c *GeneralConfig_SolanaConfigs_Call) Run(run func()) *GeneralConfig_Solan return _c } -func (_c *GeneralConfig_SolanaConfigs_Call) Return(_a0 solanaconfig.TOMLConfigs) *GeneralConfig_SolanaConfigs_Call { +func (_c *GeneralConfig_SolanaConfigs_Call) Return(_a0 chainlink.RawConfigs) *GeneralConfig_SolanaConfigs_Call { _c.Call.Return(_a0) return _c } -func (_c *GeneralConfig_SolanaConfigs_Call) RunAndReturn(run func() solanaconfig.TOMLConfigs) *GeneralConfig_SolanaConfigs_Call { +func (_c *GeneralConfig_SolanaConfigs_Call) RunAndReturn(run func() chainlink.RawConfigs) *GeneralConfig_SolanaConfigs_Call { _c.Call.Return(run) return _c } diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index b585b6e7ad6..ce4ea40e818 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -158,9 +158,9 @@ func InitCosmos(factory RelayerFactory, ks keystore.Cosmos, csaKS keystore.CSA, } // InitSolana is a option for instantiating Solana relayers -func InitSolana(factory RelayerFactory, ks keystore.Solana, csaKS keystore.CSA, config SolanaFactoryConfig) CoreRelayerChainInitFunc { +func InitSolana(factory RelayerFactory, ks keystore.Solana, csaKS keystore.CSA, chainCfgs RawConfigs) CoreRelayerChainInitFunc { return func(op *CoreRelayerChainInteroperators) error { - solRelayers, err := factory.NewSolana(&keystore.SolanaLooppSigner{Solana: ks}, &keystore.CSASigner{CSA: csaKS}, config) + solRelayers, err := factory.NewSolana(&keystore.SolanaLooppSigner{Solana: ks}, &keystore.CSASigner{CSA: csaKS}, chainCfgs) if err != nil { return fmt.Errorf("failed to setup Solana relayer: %w", err) } diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index df545cab676..6d52913f107 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -154,8 +154,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { }), chainlink.InitStarknet(factory, keyStore.StarkNet(), keyStore.CSA(), cfg.StarknetConfigs()), chainlink.InitCosmos(factory, keyStore.Cosmos(), keyStore.CSA(), cfg.CosmosConfigs()), - chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), chainlink.SolanaFactoryConfig{ - TOMLConfigs: cfg.SolanaConfigs()}), + chainlink.InitSolana(factory, keyStore.Solana(), keyStore.CSA(), cfg.SolanaConfigs()), }, expectedEVMChainCnt: 2, expectedEVMNodeCnt: 3, diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index 9a2b35f33f3..1ddb0867c56 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -12,14 +12,12 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/loop" - "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" coretypes "github.com/smartcontractkit/chainlink-common/pkg/types/core" "github.com/smartcontractkit/chainlink-data-streams/mercury/wsrpc" "github.com/smartcontractkit/chainlink-evm/pkg/chains/legacyevm" evmtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/keys" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" "github.com/smartcontractkit/chainlink/v2/core/config/env" @@ -136,59 +134,8 @@ func (r *RelayerFactory) NewEVM(config EVMFactoryConfig) (map[types.RelayID]evmr return relayers, nil } -type SolanaFactoryConfig struct { - solcfg.TOMLConfigs - DS sqlutil.DataSource -} - -func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, config SolanaFactoryConfig) (map[types.RelayID]loop.Relayer, error) { - chainCfgs := config.TOMLConfigs - solanaRelayers := make(map[types.RelayID]loop.Relayer) - var solLggr = logger.Named(r.Logger, "Solana") - - cmdName := cmp.Or(env.SolanaPlugin.Cmd.Get(), env.SolanaPlugin.CmdDefault) - if cmdName == "" { - return nil, fmt.Errorf("plugin command not defined: %s", env.SolanaPlugin.Cmd) - } - envVars, err := plugins.ParseEnvFile(env.SolanaPlugin.Env.Get()) - if err != nil { - return nil, fmt.Errorf("failed to parse Solana env file: %w", err) - } - - unique := make(map[string]struct{}) - // create one relayer per chain id - for _, chainCfg := range chainCfgs { - relayID := types.RelayID{Network: relay.NetworkSolana, ChainID: *chainCfg.ChainID} - if _, alreadyExists := unique[relayID.Name()]; alreadyExists { - return nil, fmt.Errorf("duplicate chain definitions for %s", relayID.Name()) - } - unique[relayID.Name()] = struct{}{} - - // skip disabled chains from further processing - if !chainCfg.IsEnabled() { - solLggr.Warnw("Skipping disabled chain", "id", chainCfg.ChainID) - continue - } - - lggr := logger.Named(solLggr, relayID.ChainID) - cfgTOML, err := toml.Marshal(struct { - Solana solcfg.TOMLConfig - }{Solana: *chainCfg}) - if err != nil { - return nil, fmt.Errorf("failed to marshal Solana configs: %w", err) - } - solCmdFn, err := plugins.NewCmdFactory(r.Register, plugins.CmdConfig{ - ID: relayID.Name(), - Cmd: cmdName, - Env: envVars, - }) - if err != nil { - return nil, fmt.Errorf("failed to create Solana LOOP command: %w", err) - } - - solanaRelayers[relayID] = loop.NewRelayerService(lggr, r.GRPCOpts, solCmdFn, string(cfgTOML), ks, ksCSA, r.CapabilitiesRegistry) - } - return solanaRelayers, nil +func (r *RelayerFactory) NewSolana(ks, ksCSA coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { + return r.NewLOOPRelayer("Solana", relay.NetworkSolana, env.SolanaPlugin, ks, ksCSA, chainCfgs) } func (r *RelayerFactory) NewStarkNet(ks, ksCSA coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { diff --git a/core/services/chainlink/types.go b/core/services/chainlink/types.go index 037ee88019f..ea7f196461c 100644 --- a/core/services/chainlink/types.go +++ b/core/services/chainlink/types.go @@ -1,8 +1,6 @@ package chainlink import ( - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" - "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink/v2/core/config" coreconfig "github.com/smartcontractkit/chainlink/v2/core/config" @@ -12,7 +10,7 @@ type GeneralConfig interface { config.AppConfig toml.HasEVMConfigs CosmosConfigs() RawConfigs - SolanaConfigs() solcfg.TOMLConfigs + SolanaConfigs() RawConfigs StarknetConfigs() RawConfigs AptosConfigs() RawConfigs TronConfigs() RawConfigs diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 5272d8c0c9b..38becf225d4 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -8,16 +8,13 @@ import ( "math/rand/v2" "net/http" "testing" - "time" "github.com/manyminds/api2go/jsonapi" "github.com/shopspring/decimal" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" commonTypes "github.com/smartcontractkit/chainlink-common/pkg/types" - "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -317,12 +314,10 @@ FinalizedBlockOffset = 50 t.Run(tc.name, func(t *testing.T) { t.Parallel() - controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, + controller := setupSolanaChainsControllerTestV2(t, chainlink.RawConfig{ + "ChainID": validID, + "SkipPreflight": false, + "TxTimeout": "1h0m0s", }) wantedResult := tc.want(t, controller.app) @@ -348,17 +343,13 @@ FinalizedBlockOffset = 50 func Test_SolanaChainsController_Index(t *testing.T) { t.Parallel() - chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int32N(999999))), - Chain: config.Chain{ - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, + chainA := chainlink.RawConfig{ + "ChainID": fmt.Sprintf("ChainlinktestA-%d", rand.Int32N(999999)), + "TxTimeout": "1h0m0s", } - chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int32N(999999))), - Chain: config.Chain{ - SkipPreflight: ptr(false), - }, + chainB := chainlink.RawConfig{ + "ChainID": fmt.Sprintf("ChainlinktestB-%d", rand.Int32N(999999)), + "SkipPreflight": false, } controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) @@ -385,10 +376,8 @@ func Test_SolanaChainsController_Index(t *testing.T) { assert.Empty(t, links["prev"].Href) assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) + assert.Equal(t, chainA.ChainID(), chains[0].ID) + assert.NotEmpty(t, chains[0].Config) resp, cleanup = controller.client.Get(links["next"].Href) t.Cleanup(cleanup) @@ -401,10 +390,8 @@ func Test_SolanaChainsController_Index(t *testing.T) { assert.NotEmpty(t, links["prev"].Href) assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) + assert.Equal(t, chainB.ChainID(), chains[0].ID) + assert.NotEmpty(t, chains[0].Config) } type TestSolanaChainsController struct { @@ -412,10 +399,7 @@ type TestSolanaChainsController struct { client cltest.HTTPClientCleaner } -func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } +func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...chainlink.RawConfig) *TestSolanaChainsController { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Solana = cfgs c.EVM = nil diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 5543f86326f..a353f1725d6 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -594,75 +594,75 @@ HTTPURL = 'http://broadcast.mirror' SendOnly = true [[Solana]] -ChainID = 'mainnet' -Enabled = true -BlockTime = '500ms' BalancePollPeriod = '1m0s' -ConfirmPollPeriod = '1s' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -TxTimeout = '1h0m0s' -TxRetryTimeout = '1m0s' -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'banana' -MaxRetries = 7 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' +BlockHistoryBatchLoadSize = 20 BlockHistoryPollPeriod = '5s' BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 +BlockTime = '500ms' +ChainID = 'mainnet' +Commitment = 'banana' ComputeUnitLimitDefault = 200000 +ComputeUnitPriceDefault = 0 +ComputeUnitPriceMax = 1000000 +ComputeUnitPriceMin = 0 +ConfirmPollPeriod = '1s' +Enabled = true EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' +FeeBumpPeriod = '3s' +FeeEstimatorMode = 'fixed' LogPollerCPIEventsEnabled = true LogPollerSlotsBatchSize = 100 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 +LogPollerStartingLookback = '24h0m0s' +MaxRetries = 7 +OCR2CachePollPeriod = '1m0s' +OCR2CacheTTL = '1h0m0s' +SkipPreflight = true +TxConfirmTimeout = '1s' +TxExpirationRebroadcast = false +TxRetentionTimeout = '0s' +TxRetryTimeout = '1m0s' +TxTimeout = '1h0m0s' [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NewHeadsPollInterval = '5s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://solana.web' SendOnly = false +URL = 'http://solana.web' [[Solana.Nodes]] Name = 'foo' -URL = 'http://solana.foo' SendOnly = false +URL = 'http://solana.foo' [[Solana.Nodes]] Name = 'bar' -URL = 'http://solana.bar' SendOnly = false +URL = 'http://solana.bar' + +[Solana.Workflow] +AcceptanceTimeout = '45s' +ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' +ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' +FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' +GasLimitDefault = 0 +Local = true +PollPeriod = '3s' +TxAcceptanceState = 3 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 6d4542a1092..9d25814a31f 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -771,128 +771,55 @@ WSURL = 'wss://web.socket/test/bar' [[Solana]] ChainID = 'mainnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' MaxRetries = 12 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 1000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://mainnet.solana.com' SendOnly = false +URL = 'http://mainnet.solana.com' [[Solana]] ChainID = 'testnet' -Enabled = true -BlockTime = '500ms' -BalancePollPeriod = '5s' -ConfirmPollPeriod = '500ms' -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1m0s' -TxTimeout = '1m0s' -TxRetryTimeout = '10s' -TxConfirmTimeout = '30s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -SkipPreflight = true -Commitment = 'confirmed' -MaxRetries = 0 -FeeEstimatorMode = 'fixed' -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 0 -ComputeUnitPriceDefault = 0 -FeeBumpPeriod = '3s' -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockHistoryBatchLoadSize = 20 -ComputeUnitLimitDefault = 200000 -EstimateComputeUnitLimit = false -LogPollerStartingLookback = '24h0m0s' -LogPollerCPIEventsEnabled = true LogPollerSlotsBatchSize = 2000 - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '11111111111111111111111111111111' -ForwarderState = '11111111111111111111111111111111' -FromAddress = '11111111111111111111111111111111' -GasLimitDefault = 300000 -Local = false -PollPeriod = '3s' -TxAcceptanceState = 3 +OCR2CachePollPeriod = '1m0s' [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'secondary' -URL = 'http://testnet.solana.com' SendOnly = false +URL = 'http://testnet.solana.com' diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 4bb46de4ccb..993ed298173 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -88,52 +88,52 @@ ChainID = 'mainnet' MaxRetries = 12 [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'primary' -URL = 'http://mainnet.solana.com' SendOnly = false +URL = 'http://mainnet.solana.com' [[Solana]] ChainID = 'testnet' -OCR2CachePollPeriod = '1m0s' LogPollerSlotsBatchSize = 2000 +OCR2CachePollPeriod = '1m0s' [Solana.MultiNode] +DeathDeclarationDelay = '1m0s' Enabled = false +EnforceRepeatableRead = true +FinalityDepth = 0 +FinalityTagEnabled = true +FinalizedBlockOffset = 0 +FinalizedBlockPollInterval = '1s' +LeaseDuration = '1m0s' +NoNewFinalizedHeadsThreshold = '1m0s' +NodeIsSyncingEnabled = false +NodeNoNewHeadsThreshold = '1m0s' PollFailureThreshold = 5 PollInterval = '1s' SelectionMode = 'HighestHead' SyncThreshold = 5 -NodeIsSyncingEnabled = false -LeaseDuration = '1m0s' -FinalizedBlockPollInterval = '1s' -EnforceRepeatableRead = true -DeathDeclarationDelay = '1m0s' VerifyChainID = true -NodeNoNewHeadsThreshold = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 [[Solana.Nodes]] Name = 'secondary' -URL = 'http://testnet.solana.com' SendOnly = false +URL = 'http://testnet.solana.com' diff --git a/deployment/go.mod b/deployment/go.mod index afe257dad5c..c4be3d5c4a1 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -52,7 +52,7 @@ require ( github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260420204255-a3f3bdd56877 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/orchestrator v0.10.0 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260409184948-5b16fae57fe0 diff --git a/deployment/go.sum b/deployment/go.sum index de265950030..f91bf0406ce 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1458,6 +1458,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= diff --git a/deployment/utils/nodetestutils/node.go b/deployment/utils/nodetestutils/node.go index f01a9daf0ba..586fcc5bd0e 100644 --- a/deployment/utils/nodetestutils/node.go +++ b/deployment/utils/nodetestutils/node.go @@ -38,11 +38,9 @@ import ( "github.com/smartcontractkit/chainlink-evm/pkg/keys" evmlptesting "github.com/smartcontractkit/chainlink-evm/pkg/logpoller/testing" "github.com/smartcontractkit/chainlink-evm/pkg/testutils" - mnCfg "github.com/smartcontractkit/chainlink-framework/multinode/config" nodev1 "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/node" "github.com/smartcontractkit/chainlink-protos/job-distributor/v1/shared/ptypes" pb "github.com/smartcontractkit/chainlink-protos/orchestrator/feedsmanager" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" sollptesting "github.com/smartcontractkit/chainlink-solana/pkg/solana/logpoller/testing" tonlptesting "github.com/smartcontractkit/chainlink-ton/pkg/logpoller/store/postgres/testing" "github.com/smartcontractkit/chainlink/deployment" @@ -437,7 +435,7 @@ func NewNode( } c.EVM = evmConfigs - var solConfigs solcfg.TOMLConfigs + var solConfigs chainlink.RawConfigs for chainID, chain := range nodecfg.BlockChains.SolanaChains() { solanaChainID, err := chainsel.GetChainIDFromSelector(chainID) if err != nil { @@ -822,39 +820,22 @@ func createConfigV2Chain(chainID uint64) *v2toml.EVMConfig { } } -func createSolanaChainConfig(chainID string, chain cldf_solana.Chain) *solcfg.TOMLConfig { - var chainConfig solcfg.Chain - - // CCIP requires a non-zero execution fee estimate - computeUnitPriceDefault := uint64(100) - txRetentionTimeout := config.MustNewDuration(10 * time.Minute) - chainConfig.ComputeUnitPriceDefault = &computeUnitPriceDefault - chainConfig.TxRetentionTimeout = txRetentionTimeout - skip := true - chainConfig.SkipPreflight = &skip - - url, err := config.ParseURL(chain.URL) - if err != nil { - panic(err) - } - - cfg := &solcfg.TOMLConfig{ - ChainID: &chainID, - Enabled: pointer.To(true), - Chain: chainConfig, - MultiNode: mnCfg.MultiNodeConfig{ - MultiNode: mnCfg.MultiNode{ - VerifyChainID: pointer.To(false), - }, +func createSolanaChainConfig(chainID string, chain cldf_solana.Chain) chainlink.RawConfig { + return chainlink.RawConfig{ + "ChainID": chainID, + "Enabled": true, + "ComputeUnitPriceDefault": uint64(100), + "TxRetentionTimeout": "10m0s", + "SkipPreflight": true, + "MultiNode": map[string]any{ + "VerifyChainID": false, }, - Nodes: []*solcfg.Node{{ - Name: pointer.To("primary"), - URL: url, - SendOnly: false, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": chain.URL, + "SendOnly": false, }}, } - cfg.SetDefaults() - return cfg } func setupJD(t *testing.T, app chainlink.Application) { diff --git a/go.mod b/go.mod index 8e6996fbccf..7832eb9b464 100644 --- a/go.mod +++ b/go.mod @@ -103,7 +103,7 @@ require ( github.com/smartcontractkit/chainlink-protos/ring/go v0.0.0-20260331131315-f08a616d8dcd github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc github.com/smartcontractkit/chainlink-ton v0.0.0-20260415120434-cecc380f8d87 github.com/smartcontractkit/cre-sdk-go v1.5.0 diff --git a/go.sum b/go.sum index cc48b7bd28e..ceda6780a1c 100644 --- a/go.sum +++ b/go.sum @@ -1300,6 +1300,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc/go.mod h1:wfcTy4b7gblAAuJ2HiBRc0OH/D9lztBmUZBVrqOIA1s= github.com/smartcontractkit/chainlink-ton v0.0.0-20260415120434-cecc380f8d87 h1:NgA2+Q0wfHicP/QeY1hgULQ1ZBk1sgBpOJi3GpxfjE8= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index b0262691278..e32b558ccad 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -428,7 +428,7 @@ require ( github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 // indirect github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.16 // indirect github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20260408092456-3c6369888d4a // indirect github.com/smartcontractkit/freeport v0.1.3-0.20250828155247-add56fa28aad // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index d7ea502e549..50c34aa9b18 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1443,6 +1443,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc/go.mod h1:wfcTy4b7gblAAuJ2HiBRc0OH/D9lztBmUZBVrqOIA1s= github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260420191233-429504ae18dc h1:4zH20ZvNJ4gUrQQBOKfV2/XPFlvEj4a0fiRRdADNzkA= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index b317f1a5688..baeaad6963c 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -507,7 +507,7 @@ require ( github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260420191233-429504ae18dc // indirect github.com/smartcontractkit/chainlink-testing-framework/lib v1.54.7 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 6f2865428ce..e708acf28c5 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1711,6 +1711,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc/go.mod h1:wfcTy4b7gblAAuJ2HiBRc0OH/D9lztBmUZBVrqOIA1s= github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260420191233-429504ae18dc h1:4zH20ZvNJ4gUrQQBOKfV2/XPFlvEj4a0fiRRdADNzkA= diff --git a/plugins/plugins.public.yaml b/plugins/plugins.public.yaml index 95b4fb2b3e6..2d0ba2d5c89 100644 --- a/plugins/plugins.public.yaml +++ b/plugins/plugins.public.yaml @@ -35,7 +35,7 @@ plugins: solana: - moduleURI: "github.com/smartcontractkit/chainlink-solana" - gitRef: "v1.1.2-0.20260421131224-c46cbfe7bc6c" + gitRef: "v1.1.2-0.20260425181804-74cb2d3ec1a1" installPath: "./pkg/solana/cmd/chainlink-solana" starknet: diff --git a/system-tests/lib/cre/don/config/config.go b/system-tests/lib/cre/don/config/config.go index a3c6dd33b7d..019872cc730 100644 --- a/system-tests/lib/cre/don/config/config.go +++ b/system-tests/lib/cre/don/config/config.go @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-evm/pkg/config/chaintype" evmconfigtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-testing-framework/framework" chipingressset "github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose/chip_ingress_set" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" @@ -854,20 +853,20 @@ func appendEVMChain(existingConfig *evmconfigtoml.EVMConfigs, evmChain *evmChain *existingConfig = append(*existingConfig, &cfg) } -func appendSolanaChain(existingConfig *solcfg.TOMLConfigs, solChain *solanaChain) { +func appendSolanaChain(existingConfig *corechainlink.RawConfigs, solChain *solanaChain) { for _, existingSol := range *existingConfig { - if existingSol.ChainID != nil && *existingSol.ChainID == solChain.ChainID { + if existingSol.ChainID() == solChain.ChainID { return } } - *existingConfig = append(*existingConfig, &solcfg.TOMLConfig{ - Enabled: ptr.Ptr(true), - ChainID: ptr.Ptr(solChain.ChainID), - Nodes: []*solcfg.Node{ + *existingConfig = append(*existingConfig, corechainlink.RawConfig{ + "Enabled": true, + "ChainID": solChain.ChainID, + "Nodes": []map[string]any{ { - Name: &solChain.Name, - URL: commonconfig.MustParseURL(solChain.NodeURL), + "Name": solChain.Name, + "URL": solChain.NodeURL, }, }, }) diff --git a/system-tests/lib/cre/features/solana/v2/solana.go b/system-tests/lib/cre/features/solana/v2/solana.go index 443d28ca61a..dcb2629d0c4 100644 --- a/system-tests/lib/cre/features/solana/v2/solana.go +++ b/system-tests/lib/cre/features/solana/v2/solana.go @@ -23,7 +23,6 @@ import ( "github.com/smartcontractkit/chainlink-deployments-framework/datastore" "github.com/smartcontractkit/chainlink-deployments-framework/operations" kcr "github.com/smartcontractkit/chainlink-evm/gethwrappers/keystone/generated/capabilities_registry_1_1_0" - solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-testing-framework/lib/utils/ptr" commonchangeset "github.com/smartcontractkit/chainlink/deployment/common/changeset" "github.com/smartcontractkit/chainlink/deployment/cre/forwarder" @@ -457,12 +456,10 @@ func updateNodeConfig(workerNode *cre.NodeMetadata, chainID string, data input, return nil, fmt.Errorf("only 1 Solana chain is supported, but found %d for node at index %d", len(typedConfig.Solana), workerNode.Index) } - if typedConfig.Solana[0].ChainID == nil { - return nil, fmt.Errorf("solana chainID is nil for node at index %d", workerNode.Index) + if typedConfig.Solana[0].ChainID() == "" { + return nil, fmt.Errorf("solana chainID is empty for node at index %d", workerNode.Index) } - var solCfg solcfg.WorkflowConfig - // Execute template with chain's workflow configuration tmpl, err := template.New("solanaWorkflowConfig").Parse(solWorkflowConfigTemplate) if err != nil { @@ -479,12 +476,13 @@ func updateNodeConfig(workerNode *cre.NodeMetadata, chainID string, data input, return nil, fmt.Errorf("%s template validation failed: %w\nRendered template: %s", flag, err, configStr) } - unmarshallErr = toml.Unmarshal([]byte(configStr), &solCfg) + var solWorkflow map[string]any + unmarshallErr = toml.Unmarshal([]byte(configStr), &solWorkflow) if unmarshallErr != nil { return nil, errors.Wrap(unmarshallErr, "failed to unmarshal Solana.Workflow config") } - typedConfig.Solana[0].Workflow = solCfg + typedConfig.Solana[0]["Workflow"] = solWorkflow stringifiedConfig, mErr := toml.Marshal(typedConfig) if mErr != nil { diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index ce013d03e53..2911d6b9c58 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -42,7 +42,7 @@ require ( github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.17 github.com/smartcontractkit/chainlink-testing-framework/framework/components/chiprouter v1.0.2 github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose v0.1.15 diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index ec1c7e40f4b..f37355ca962 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1679,6 +1679,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= diff --git a/system-tests/tests/go.mod b/system-tests/tests/go.mod index a4d40d8d283..d4c18101aa1 100644 --- a/system-tests/tests/go.mod +++ b/system-tests/tests/go.mod @@ -157,7 +157,7 @@ require ( github.com/smartcontractkit/chainlink-protos/chainlink-ccv/message-discovery v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260319180422-b5808c964785 // indirect - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 // indirect github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260409184948-5b16fae57fe0 // indirect github.com/stellar/go-stellar-sdk v0.1.0 // indirect diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index ca1d6d96b66..d6443739038 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1894,6 +1894,8 @@ github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644- github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= +github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c/go.mod h1:C5pZsbYX3qkhZTYWr1aYJi9QMfonFAun+Jl1npQ7UJA= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= From bbd0f3e72c29cc2424bdd4e921b8f48d24a1dab2 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 15:30:09 -0500 Subject: [PATCH 15/25] mod tidy --- core/scripts/go.sum | 2 -- deployment/go.mod | 2 +- deployment/go.sum | 2 -- go.sum | 2 -- integration-tests/go.sum | 2 -- integration-tests/load/go.sum | 2 -- system-tests/lib/go.mod | 2 +- system-tests/lib/go.sum | 2 -- system-tests/tests/go.sum | 2 -- 9 files changed, 2 insertions(+), 16 deletions(-) diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 8bd31ad21b0..0b02f7e8d57 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1712,8 +1712,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= diff --git a/deployment/go.mod b/deployment/go.mod index c4be3d5c4a1..7630f02defb 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -48,7 +48,6 @@ require ( github.com/smartcontractkit/chainlink-evm v0.3.4-0.20260416173445-80f6efde0a03 github.com/smartcontractkit/chainlink-evm/contracts/cre/gobindings v0.0.0-20260403151002-2c91155b5501 github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20260119171452-39c98c3b33cd - github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260410144512-ca02ad6ed16a github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20260420204255-a3f3bdd56877 github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/orchestrator v0.10.0 @@ -431,6 +430,7 @@ require ( github.com/smartcontractkit/chainlink-framework/capabilities v0.0.0-20250818175541-3389ac08a563 // indirect github.com/smartcontractkit/chainlink-framework/chains v0.0.0-20260326122810-b657beadfb57 // indirect github.com/smartcontractkit/chainlink-framework/metrics v0.0.0-20260410144512-ca02ad6ed16a // indirect + github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20260410144512-ca02ad6ed16a // indirect github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20251024234028-0988426d98f4 // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/committee-verifier v0.0.0-20251211142334-5c3421fe2c8d // indirect github.com/smartcontractkit/chainlink-protos/chainlink-ccv/heartbeat v0.0.0-20260115142640-f6b99095c12e // indirect diff --git a/deployment/go.sum b/deployment/go.sum index f91bf0406ce..b6f7553b90c 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -1456,8 +1456,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= diff --git a/go.sum b/go.sum index ceda6780a1c..105e7f6a6ee 100644 --- a/go.sum +++ b/go.sum @@ -1298,8 +1298,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 50c34aa9b18..44b32310e62 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1441,8 +1441,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index e708acf28c5..271527bdd32 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1709,8 +1709,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc h1:BfUgvQ9PzvCPfFyNOrFMN7F7ljpPA7p+RbGZPB2+kLw= diff --git a/system-tests/lib/go.mod b/system-tests/lib/go.mod index 2911d6b9c58..6649cfb458d 100644 --- a/system-tests/lib/go.mod +++ b/system-tests/lib/go.mod @@ -42,7 +42,6 @@ require ( github.com/smartcontractkit/chainlink-protos/job-distributor v0.18.0 github.com/smartcontractkit/chainlink-protos/linking-service/go v0.0.0-20251002192024-d2ad9222409b github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 - github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 github.com/smartcontractkit/chainlink-testing-framework/framework v0.15.17 github.com/smartcontractkit/chainlink-testing-framework/framework/components/chiprouter v1.0.2 github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose v0.1.15 @@ -479,6 +478,7 @@ require ( github.com/smartcontractkit/chainlink-protos/rmn/v1.6/go v0.0.0-20250131130834-15e0d4cde2a6 // indirect github.com/smartcontractkit/chainlink-protos/storage-service v0.3.0 // indirect github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3 // indirect + github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 // indirect github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c // indirect github.com/smartcontractkit/chainlink-sui v0.0.0-20260420191233-429504ae18dc // indirect github.com/smartcontractkit/chainlink-sui/deployment v0.0.0-20260409184948-5b16fae57fe0 // indirect diff --git a/system-tests/lib/go.sum b/system-tests/lib/go.sum index f37355ca962..007fdff3791 100644 --- a/system-tests/lib/go.sum +++ b/system-tests/lib/go.sum @@ -1677,8 +1677,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= diff --git a/system-tests/tests/go.sum b/system-tests/tests/go.sum index d6443739038..9e7aeaf618e 100644 --- a/system-tests/tests/go.sum +++ b/system-tests/tests/go.sum @@ -1892,8 +1892,6 @@ github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c github.com/smartcontractkit/chainlink-protos/svr v1.1.1-0.20260203131522-bb8bc5c423b3/go.mod h1:TcOliTQU6r59DwG4lo3U+mFM9WWyBHGuFkkxQpvSujo= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997 h1:W0HKHO8eE8BckTRnhSdqjHKbJcnk068nEWYnWRu6tJY= github.com/smartcontractkit/chainlink-protos/workflows/go v0.0.0-20260323124644-faea187e6997/go.mod h1:GTpDgyK0OObf7jpch6p8N281KxN92wbB8serZhU9yRc= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c h1:2ZdBZCZWKUMOWLtReaBBHkmDtXc0WtwcqIROHAcm3j4= -github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260421131224-c46cbfe7bc6c/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1 h1:oQOaU3dcT/oXykbq5twHlOqNy5NbCQvveWm71cqfHZE= github.com/smartcontractkit/chainlink-solana v1.1.2-0.20260425181804-74cb2d3ec1a1/go.mod h1:sUsEwLtVPBlz0wPcysaolS+HVj9cOAt4jYhwE6J8dXg= github.com/smartcontractkit/chainlink-solana/contracts v0.0.0-20260421131224-c46cbfe7bc6c h1:Hn/80PyYFrQhRlNSaq9HY4cjc/7AuP9zyWLle22t34A= From 7ae63eac9d0d3f50e3974b41f7d6dbd6d1a3a061 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 22:40:17 -0500 Subject: [PATCH 16/25] fix test --- core/web/resolver/testdata/config-full.toml | 1 - testdata/scripts/node/validate/invalid-duplicates.txtar | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index a353f1725d6..182ee39d329 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -606,7 +606,6 @@ ComputeUnitPriceDefault = 0 ComputeUnitPriceMax = 1000000 ComputeUnitPriceMin = 0 ConfirmPollPeriod = '1s' -Enabled = true EstimateComputeUnitLimit = false FeeBumpPeriod = '3s' FeeEstimatorMode = 'fixed' diff --git a/testdata/scripts/node/validate/invalid-duplicates.txtar b/testdata/scripts/node/validate/invalid-duplicates.txtar index 7cb1bbe6b6b..c45237d410d 100644 --- a/testdata/scripts/node/validate/invalid-duplicates.txtar +++ b/testdata/scripts/node/validate/invalid-duplicates.txtar @@ -96,10 +96,9 @@ Error running app: invalid configuration: 5 errors: - Cosmos: 2 errors: - 1.ChainID: invalid value (Malaga-420): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique - - Solana: 3 errors: + - Solana: 2 errors: - 1.ChainID: invalid value (mainnet): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique - - 1.Nodes.1.URL: invalid value (http://solana.web): duplicate - must be unique - Starknet: 2 errors: - 1.ChainID: invalid value (foobar): duplicate - must be unique - 1.Nodes.1.Name: invalid value (primary): duplicate - must be unique From d8987cc11f9330797319600d1dfe124c41953dcb Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 22:45:59 -0500 Subject: [PATCH 17/25] use default cmd --- .github/integration-in-memory-tests.yml | 40 ------------------------- 1 file changed, 40 deletions(-) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 16021df2bad..5cd8e8ab629 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -70,8 +70,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -89,8 +87,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Solana2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Revert_EVM2Solana_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -108,8 +104,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Revert_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_MultiExecReports_EVM2Solana path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -368,8 +362,6 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_token_transfer_test.go:*_LOOPP path: integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -387,8 +379,6 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_update_rmn_config_test.go:* path: integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go @@ -421,8 +411,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseUncurseAptos path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -457,8 +445,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -476,8 +462,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -494,8 +478,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -512,8 +494,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurse path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -531,8 +511,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseMCMS path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -550,8 +528,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -569,8 +545,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseConfigValidate path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -588,8 +562,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseConfigValidate$" -timeout 20m -count=1 -parallel=2 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseNoConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -606,8 +578,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseNoConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -624,8 +594,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesSolana path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -642,8 +610,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesSolana$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesGlobalOnly path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -660,8 +626,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesGlobalOnly$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesLaneOnlyOnSource path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -678,8 +642,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesLaneOnlyOnSource$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseForceOption path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -697,8 +659,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseForceOption$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_disable_lane_test.go:* path: integration-tests/smoke/ccip/ccip_disable_lane_test.go From 08fec605d142ccb9ecef65921a299a1d4e13c69b Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 23:36:20 -0500 Subject: [PATCH 18/25] fix --- core/cmd/blocks_commands_integration_test.go | 4 ++++ core/cmd/chains_commands_integration_test.go | 4 ++++ core/cmd/node_commands_integration_test.go | 10 ++++++---- core/web/chains_controller_integration_test.go | 12 ++++++++++++ testdata/scripts/nodes/solana/list/list.txtar | 4 ---- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/core/cmd/blocks_commands_integration_test.go b/core/cmd/blocks_commands_integration_test.go index b29706d5b86..ebe246d2d6b 100644 --- a/core/cmd/blocks_commands_integration_test.go +++ b/core/cmd/blocks_commands_integration_test.go @@ -18,6 +18,10 @@ func Test_ReplayFromBlock_Solana(t *testing.T) { chain := chainlink.RawConfig{ "ChainID": "devnet", "Enabled": true, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, } app := solanaStartNewApplication(t, chain) client, _ := app.NewShellAndRenderer() diff --git a/core/cmd/chains_commands_integration_test.go b/core/cmd/chains_commands_integration_test.go index e78ea4a0ddb..c173b28e9b6 100644 --- a/core/cmd/chains_commands_integration_test.go +++ b/core/cmd/chains_commands_integration_test.go @@ -44,6 +44,10 @@ func TestShell_IndexSolanaChains(t *testing.T) { chain := chainlink.RawConfig{ "ChainID": id, "Enabled": true, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, } app := solanaStartNewApplication(t, chain) client, r := app.NewShellAndRenderer() diff --git a/core/cmd/node_commands_integration_test.go b/core/cmd/node_commands_integration_test.go index 4c16d12649c..92c7ff68856 100644 --- a/core/cmd/node_commands_integration_test.go +++ b/core/cmd/node_commands_integration_test.go @@ -147,12 +147,14 @@ func TestShell_IndexSolanaNodes(t *testing.T) { id := solanatest.RandomChainID() node1 := map[string]any{ - "Name": ptr("first"), - "URL": config.MustParseURL("https://solana1.example"), + "Name": ptr("first"), + "URL": config.MustParseURL("https://solana1.example"), + "SendOnly": false, } node2 := map[string]any{ - "Name": ptr("second"), - "URL": config.MustParseURL("https://solana2.example"), + "Name": ptr("second"), + "URL": config.MustParseURL("https://solana2.example"), + "SendOnly": false, } chain := chainlink.RawConfig{ "ChainID": id, diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 38becf225d4..c4730e8093c 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -318,6 +318,10 @@ FinalizedBlockOffset = 50 "ChainID": validID, "SkipPreflight": false, "TxTimeout": "1h0m0s", + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, }) wantedResult := tc.want(t, controller.app) @@ -346,10 +350,18 @@ func Test_SolanaChainsController_Index(t *testing.T) { chainA := chainlink.RawConfig{ "ChainID": fmt.Sprintf("ChainlinktestA-%d", rand.Int32N(999999)), "TxTimeout": "1h0m0s", + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, } chainB := chainlink.RawConfig{ "ChainID": fmt.Sprintf("ChainlinktestB-%d", rand.Int32N(999999)), "SkipPreflight": false, + "Nodes": []map[string]any{{ + "Name": "primary", + "URL": "http://solana.example", + }}, } controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) diff --git a/testdata/scripts/nodes/solana/list/list.txtar b/testdata/scripts/nodes/solana/list/list.txtar index 81f5ec851f8..190f8a97614 100644 --- a/testdata/scripts/nodes/solana/list/list.txtar +++ b/testdata/scripts/nodes/solana/list/list.txtar @@ -46,8 +46,6 @@ State: Config: Name = 'Blue' URL = 'wss://primaryfoo.bar' SendOnly = false -Order = 100 -IsLoadBalancedRPC = false ----------------------------- Name: Yellow @@ -56,7 +54,5 @@ State: Config: Name = 'Yellow' URL = 'wss://sendonlyfoo.bar' SendOnly = false -Order = 100 -IsLoadBalancedRPC = false ----------------------------- From 6678156248eda669aac9d3b3c7b48e4c64eea014 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sat, 25 Apr 2026 23:58:41 -0500 Subject: [PATCH 19/25] fix test --- core/cmd/node_commands_integration_test.go | 8 ++------ core/web/chains_controller_integration_test.go | 6 +++++- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/core/cmd/node_commands_integration_test.go b/core/cmd/node_commands_integration_test.go index 92c7ff68856..6ac3c3e60c6 100644 --- a/core/cmd/node_commands_integration_test.go +++ b/core/cmd/node_commands_integration_test.go @@ -172,15 +172,11 @@ func TestShell_IndexSolanaNodes(t *testing.T) { assert.Equal(t, id, n1.ChainID) assert.Equal(t, cltest.FormatWithPrefixedChainID(id, "first"), n1.ID) assert.Equal(t, "first", n1.Name) - wantConfig, err := toml.Marshal(node1) - require.NoError(t, err) - assert.Equal(t, string(wantConfig), n1.Config) + assert.Equal(t, "Name = 'first'\nURL = 'https://solana1.example'\nSendOnly = false\n", n1.Config) assert.Equal(t, id, n2.ChainID) assert.Equal(t, cltest.FormatWithPrefixedChainID(id, "second"), n2.ID) assert.Equal(t, "second", n2.Name) - wantConfig2, err := toml.Marshal(node2) - require.NoError(t, err) - assert.Equal(t, string(wantConfig2), n2.Config) + assert.Equal(t, "Name = 'second'\nURL = 'https://solana2.example'\nSendOnly = false\n", n2.Config) assertTableRenders(t, r) // Render table and check the fields order diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index c4730e8093c..35be8af90f0 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -263,7 +263,6 @@ EstimateComputeUnitLimit = false LogPollerStartingLookback = '24h0m0s' LogPollerCPIEventsEnabled = true LogPollerSlotsBatchSize = 1000 -Nodes = [] [Workflow] AcceptanceTimeout = '45s' @@ -293,6 +292,11 @@ NoNewFinalizedHeadsThreshold = '20s' FinalityDepth = 0 FinalityTagEnabled = true FinalizedBlockOffset = 50 + +[[Nodes]] +Name = 'primary' +URL = 'http://solana.example' +SendOnly = false `, } }, From bc5f2115dada53d667c565b29aa6d3e9e553eb42 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sun, 26 Apr 2026 10:15:24 -0500 Subject: [PATCH 20/25] add test env var back --- .github/integration-in-memory-tests.yml | 40 +++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 5cd8e8ab629..16021df2bad 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -70,6 +70,8 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -87,6 +89,8 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Solana2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Revert_EVM2Solana_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -104,6 +108,8 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Revert_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_MultiExecReports_EVM2Solana path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -362,6 +368,8 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_token_transfer_test.go:*_LOOPP path: integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -379,6 +387,8 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_update_rmn_config_test.go:* path: integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go @@ -411,6 +421,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseUncurseAptos path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -445,6 +457,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -462,6 +476,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -478,6 +494,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -494,6 +512,8 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurse path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -511,6 +531,8 @@ runner-test-matrix: -- -v -run "^TestRMNUncurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseMCMS path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -528,6 +550,8 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -545,6 +569,8 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseConfigValidate path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -562,6 +588,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseConfigValidate$" -timeout 20m -count=1 -parallel=2 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseNoConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -578,6 +606,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseNoConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -594,6 +624,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesSolana path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -610,6 +642,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesSolana$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesGlobalOnly path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -626,6 +660,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesGlobalOnly$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesLaneOnlyOnSource path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -642,6 +678,8 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesLaneOnlyOnSource$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseForceOption path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -659,6 +697,8 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseForceOption$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true + test_env_vars: + CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_disable_lane_test.go:* path: integration-tests/smoke/ccip/ccip_disable_lane_test.go From df8c4a9d6b514dc84fe34ca9520d3b35d269fdb3 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Sun, 26 Apr 2026 11:08:52 -0500 Subject: [PATCH 21/25] update yml again with plugin fix --- .github/integration-in-memory-tests.yml | 40 ------------------- .../ccip/ccipsolana/pluginconfig.go | 4 +- 2 files changed, 1 insertion(+), 43 deletions(-) diff --git a/.github/integration-in-memory-tests.yml b/.github/integration-in-memory-tests.yml index 16021df2bad..5cd8e8ab629 100644 --- a/.github/integration-in-memory-tests.yml +++ b/.github/integration-in-memory-tests.yml @@ -70,8 +70,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Solana2EVM_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -89,8 +87,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Solana2EVM" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_Revert_EVM2Solana_LOOPP path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -108,8 +104,6 @@ runner-test-matrix: -- -v -run "Test_CCIPMessaging_Revert_EVM2Solana" -timeout 18m -count=1 -parallel=4 ./smoke/ccip test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_messaging_test.go:Test_CCIPMessaging_MultiExecReports_EVM2Solana path: integration-tests/smoke/ccip/ccip_messaging_test.go @@ -368,8 +362,6 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_token_transfer_test.go:*_LOOPP path: integration-tests/smoke/ccip/ccip_token_transfer_test.go @@ -387,8 +379,6 @@ runner-test-matrix: -- -v -run ".*" -timeout 16m -count=1 -parallel=2 smoke/ccip/ccip_token_transfer_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_update_rmn_config_test.go:* path: integration-tests/smoke/ccip/ccip_cs_update_rmn_config_test.go @@ -421,8 +411,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseUncurseAptos path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -457,8 +445,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -476,8 +462,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -494,8 +478,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseIdempotent path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -512,8 +494,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseIdempotent$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurse path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -531,8 +511,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurse$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseMCMS path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -550,8 +528,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseMCMS$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseBypass path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -569,8 +545,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseBypass$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseConfigValidate path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -588,8 +562,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseConfigValidate$" -timeout 20m -count=1 -parallel=2 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseNoConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -606,8 +578,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseNoConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanes path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -624,8 +594,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanes$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesSolana path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -642,8 +610,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesSolana$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesGlobalOnly path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -660,8 +626,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesGlobalOnly$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNCurseOneConnectedLanesLaneOnlyOnSource path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -678,8 +642,6 @@ runner-test-matrix: -- -v -run "^TestRMNCurseOneConnectedLanesLaneOnlyOnSource$" -timeout 20m -count=1 -parallel=1 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go:TestRMNUncurseForceOption path: integration-tests/smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go @@ -697,8 +659,6 @@ runner-test-matrix: -- -v -run "^TestRMNUncurseForceOption$" -timeout 20m -count=1 -parallel=4 smoke/ccip/ccip_cs_rmn_curse_uncurse_test.go test_go_project_path: integration-tests install_plugins_public: true - test_env_vars: - CL_SOLANA_CMD: chainlink-solana - id: smoke/ccip/ccip_disable_lane_test.go:* path: integration-tests/smoke/ccip/ccip_disable_lane_test.go diff --git a/core/capabilities/ccip/ccipsolana/pluginconfig.go b/core/capabilities/ccip/ccipsolana/pluginconfig.go index ca70b3774b9..919ffe9d6e3 100644 --- a/core/capabilities/ccip/ccipsolana/pluginconfig.go +++ b/core/capabilities/ccip/ccipsolana/pluginconfig.go @@ -6,8 +6,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/types/ccip/consts" "github.com/smartcontractkit/chainlink-common/pkg/types/ccipocr3" - "github.com/smartcontractkit/chainlink/v2/core/config/env" - ccipcommon "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/common" "github.com/smartcontractkit/chainlink/v2/core/capabilities/ccip/ocrimpls" ) @@ -26,7 +24,7 @@ func InitializePluginConfig(lggr logger.Logger, extraDataCodec ccipocr3.ExtraDat ChainRW: ChainRWProvider{}, ExtraDataCodec: ExtraDataDecoder{}, PriceOnlyCommitFn: consts.MethodCommitPriceOnly, - CCIPProviderSupported: env.SolanaPlugin.Cmd.Get() != "", + CCIPProviderSupported: true, } } From 215846f543951f0463c5ec338331f1a6a1732315 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 27 Apr 2026 16:23:39 -0500 Subject: [PATCH 22/25] delete solana config as raw config test is covered --- core/services/chainlink/config_test.go | 163 ------------------ .../chainlink/testdata/config-full.toml | 77 --------- .../config-multi-chain-effective.toml | 58 ------- .../testdata/config-multi-chain.toml | 58 ------- core/web/resolver/testdata/config-full.toml | 73 -------- .../config-multi-chain-effective.toml | 55 ------ .../resolver/testdata/config-multi-chain.toml | 55 ------ 7 files changed, 539 deletions(-) diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index ebbed878de9..b7fc74cedcb 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -49,26 +49,6 @@ var ( minute = *commoncfg.MustNewDuration(time.Minute) selectionMode = multinode.NodeSelectionModeHighestHead - multiNodeRaw = map[string]any{ - "Enabled": false, - "PollFailureThreshold": int64(5), - "PollInterval": "1s", - "SelectionMode": "HighestHead", - "SyncThreshold": int64(5), - "NodeIsSyncingEnabled": false, - "LeaseDuration": "1m0s", - "NewHeadsPollInterval": "1s", - "FinalizedBlockPollInterval": "1s", - "EnforceRepeatableRead": true, - "DeathDeclarationDelay": "1m0s", - "VerifyChainID": true, - "NodeNoNewHeadsThreshold": "1m0s", - "NoNewFinalizedHeadsThreshold": "1m0s", - "FinalityDepth": int64(0), - "FinalityTagEnabled": true, - "FinalizedBlockOffset": int64(0), - } - multiChain = Config{ Core: toml.Core{ RootDir: ptr("my/root/dir"), @@ -173,24 +153,6 @@ var ( }, }}, }, - Solana: RawConfigs{ - { - "ChainID": "mainnet", - "MaxRetries": int64(12), - "MultiNode": multiNodeRaw, - "Nodes": []any{ - map[string]any{"Name": "primary", "URL": "http://mainnet.solana.com", "SendOnly": false, "Order": int64(1)}, - }, - }, - { - "ChainID": "testnet", - "OCR2CachePollPeriod": "1m0s", - "MultiNode": multiNodeRaw, - "Nodes": []any{ - map[string]any{"Name": "secondary", "URL": "http://testnet.solana.com", "SendOnly": false, "Order": int64(2)}, - }, - }, - }, } ) @@ -851,54 +813,6 @@ func TestConfig_Marshal(t *testing.T) { }, }}, } - full.Solana = RawConfigs{ - { - "ChainID": "mainnet", - "Enabled": false, - "BlockTime": "500ms", - "BalancePollPeriod": "1m0s", - "ConfirmPollPeriod": "1s", - "OCR2CachePollPeriod": "1m0s", - "OCR2CacheTTL": "1h0m0s", - "TxTimeout": "1h0m0s", - "TxRetryTimeout": "1m0s", - "TxConfirmTimeout": "1s", - "TxExpirationRebroadcast": false, - "TxRetentionTimeout": "0s", - "SkipPreflight": true, - "Commitment": "banana", - "MaxRetries": int64(7), - "FeeEstimatorMode": "fixed", - "ComputeUnitPriceMax": int64(1000), - "ComputeUnitPriceMin": int64(10), - "ComputeUnitPriceDefault": int64(100), - "FeeBumpPeriod": "1m0s", - "BlockHistoryPollPeriod": "1m0s", - "BlockHistorySize": int64(1), - "BlockHistoryBatchLoadSize": int64(20), - "ComputeUnitLimitDefault": int64(100_000), - "EstimateComputeUnitLimit": false, - "LogPollerStartingLookback": "24h0m0s", - "LogPollerCPIEventsEnabled": true, - "LogPollerSlotsBatchSize": int64(100), - "MultiNode": multiNodeRaw, - "Workflow": map[string]any{ - "AcceptanceTimeout": "45s", - "ForwarderAddress": "14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5", - "ForwarderState": "14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5", - "FromAddress": "4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e", - "GasLimitDefault": int64(0), - "Local": true, - "PollPeriod": "3s", - "TxAcceptanceState": int64(commontypes.Finalized), - }, - "Nodes": []any{ - map[string]any{"Name": "primary", "URL": "http://solana.web", "SendOnly": false, "Order": int64(1)}, - map[string]any{"Name": "foo", "URL": "http://solana.foo", "SendOnly": true, "Order": int64(2)}, - map[string]any{"Name": "bar", "URL": "http://solana.bar", "SendOnly": true, "Order": int64(3)}, - }, - }, - } full.Mercury = toml.Mercury{ Cache: toml.MercuryCache{ LatestReportTTL: commoncfg.MustNewDuration(100 * time.Second), @@ -1353,83 +1267,6 @@ HTTPURL = 'https://bar.com' Name = 'broadcast' HTTPURL = 'http://broadcast.mirror' SendOnly = true -`}, - {"Solana", Config{Solana: full.Solana}, `[[Solana]] -BalancePollPeriod = '1m0s' -BlockHistoryBatchLoadSize = 20 -BlockHistoryPollPeriod = '1m0s' -BlockHistorySize = 1 -BlockTime = '500ms' -ChainID = 'mainnet' -Commitment = 'banana' -ComputeUnitLimitDefault = 100000 -ComputeUnitPriceDefault = 100 -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 10 -ConfirmPollPeriod = '1s' -Enabled = false -EstimateComputeUnitLimit = false -FeeBumpPeriod = '1m0s' -FeeEstimatorMode = 'fixed' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 100 -LogPollerStartingLookback = '24h0m0s' -MaxRetries = 7 -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -SkipPreflight = true -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -TxRetryTimeout = '1m0s' -TxTimeout = '1h0m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -Order = 1 -SendOnly = false -URL = 'http://solana.web' - -[[Solana.Nodes]] -Name = 'foo' -Order = 2 -SendOnly = true -URL = 'http://solana.foo' - -[[Solana.Nodes]] -Name = 'bar' -Order = 3 -SendOnly = true -URL = 'http://solana.bar' - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 `}, {"Mercury", Config{Core: toml.Core{Mercury: full.Mercury}}, `[Mercury] VerboseLogging = true diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index e6e32f98cd8..4fcd0391e1f 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -617,80 +617,3 @@ HTTPURL = 'https://bar.com' Name = 'broadcast' HTTPURL = 'http://broadcast.mirror' SendOnly = true - -[[Solana]] -BalancePollPeriod = '1m0s' -BlockHistoryBatchLoadSize = 20 -BlockHistoryPollPeriod = '1m0s' -BlockHistorySize = 1 -BlockTime = '500ms' -ChainID = 'mainnet' -Commitment = 'banana' -ComputeUnitLimitDefault = 100000 -ComputeUnitPriceDefault = 100 -ComputeUnitPriceMax = 1000 -ComputeUnitPriceMin = 10 -ConfirmPollPeriod = '1s' -Enabled = false -EstimateComputeUnitLimit = false -FeeBumpPeriod = '1m0s' -FeeEstimatorMode = 'fixed' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 100 -LogPollerStartingLookback = '24h0m0s' -MaxRetries = 7 -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -SkipPreflight = true -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -TxRetryTimeout = '1m0s' -TxTimeout = '1h0m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -Order = 1 -SendOnly = false -URL = 'http://solana.web' - -[[Solana.Nodes]] -Name = 'foo' -Order = 2 -SendOnly = true -URL = 'http://solana.foo' - -[[Solana.Nodes]] -Name = 'bar' -Order = 3 -SendOnly = true -URL = 'http://solana.bar' - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 864ca6a7ea0..417cc0aa4d7 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -768,61 +768,3 @@ AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -MaxRetries = 12 - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -Order = 1 -SendOnly = false -URL = 'http://mainnet.solana.com' - -[[Solana]] -ChainID = 'testnet' -OCR2CachePollPeriod = '1m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'secondary' -Order = 2 -SendOnly = false -URL = 'http://testnet.solana.com' diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index 0c6bbd6f539..88ff3ecd299 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -76,61 +76,3 @@ Mode = 'FixedPrice' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -MaxRetries = 12 - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -Order = 1 -SendOnly = false -URL = 'http://mainnet.solana.com' - -[[Solana]] -ChainID = 'testnet' -OCR2CachePollPeriod = '1m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '1s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'secondary' -Order = 2 -SendOnly = false -URL = 'http://testnet.solana.com' diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 182ee39d329..bbfd10f1feb 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -592,76 +592,3 @@ HTTPURL = 'https://bar.com' Name = 'broadcast' HTTPURL = 'http://broadcast.mirror' SendOnly = true - -[[Solana]] -BalancePollPeriod = '1m0s' -BlockHistoryBatchLoadSize = 20 -BlockHistoryPollPeriod = '5s' -BlockHistorySize = 1 -BlockTime = '500ms' -ChainID = 'mainnet' -Commitment = 'banana' -ComputeUnitLimitDefault = 200000 -ComputeUnitPriceDefault = 0 -ComputeUnitPriceMax = 1000000 -ComputeUnitPriceMin = 0 -ConfirmPollPeriod = '1s' -EstimateComputeUnitLimit = false -FeeBumpPeriod = '3s' -FeeEstimatorMode = 'fixed' -LogPollerCPIEventsEnabled = true -LogPollerSlotsBatchSize = 100 -LogPollerStartingLookback = '24h0m0s' -MaxRetries = 7 -OCR2CachePollPeriod = '1m0s' -OCR2CacheTTL = '1h0m0s' -SkipPreflight = true -TxConfirmTimeout = '1s' -TxExpirationRebroadcast = false -TxRetentionTimeout = '0s' -TxRetryTimeout = '1m0s' -TxTimeout = '1h0m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NewHeadsPollInterval = '5s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -SendOnly = false -URL = 'http://solana.web' - -[[Solana.Nodes]] -Name = 'foo' -SendOnly = false -URL = 'http://solana.foo' - -[[Solana.Nodes]] -Name = 'bar' -SendOnly = false -URL = 'http://solana.bar' - -[Solana.Workflow] -AcceptanceTimeout = '45s' -ForwarderAddress = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -ForwarderState = '14grJpemFaf88c8tiVb77W7TYg2W3ir6pfkKz3YjhhZ5' -FromAddress = '4BJXYkfvg37zEmBbsacZjeQDpTNx91KppxFJxRqrz48e' -GasLimitDefault = 0 -Local = true -PollPeriod = '3s' -TxAcceptanceState = 3 diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 9d25814a31f..b328fce13d7 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -768,58 +768,3 @@ AcceptanceTimeout = '30s' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -MaxRetries = 12 - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -SendOnly = false -URL = 'http://mainnet.solana.com' - -[[Solana]] -ChainID = 'testnet' -LogPollerSlotsBatchSize = 2000 -OCR2CachePollPeriod = '1m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'secondary' -SendOnly = false -URL = 'http://testnet.solana.com' diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 993ed298173..de243b708e8 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -82,58 +82,3 @@ Mode = 'FixedPrice' [[EVM.Nodes]] Name = 'bar' WSURL = 'wss://web.socket/test/bar' - -[[Solana]] -ChainID = 'mainnet' -MaxRetries = 12 - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'primary' -SendOnly = false -URL = 'http://mainnet.solana.com' - -[[Solana]] -ChainID = 'testnet' -LogPollerSlotsBatchSize = 2000 -OCR2CachePollPeriod = '1m0s' - -[Solana.MultiNode] -DeathDeclarationDelay = '1m0s' -Enabled = false -EnforceRepeatableRead = true -FinalityDepth = 0 -FinalityTagEnabled = true -FinalizedBlockOffset = 0 -FinalizedBlockPollInterval = '1s' -LeaseDuration = '1m0s' -NoNewFinalizedHeadsThreshold = '1m0s' -NodeIsSyncingEnabled = false -NodeNoNewHeadsThreshold = '1m0s' -PollFailureThreshold = 5 -PollInterval = '1s' -SelectionMode = 'HighestHead' -SyncThreshold = 5 -VerifyChainID = true - -[[Solana.Nodes]] -Name = 'secondary' -SendOnly = false -URL = 'http://testnet.solana.com' From fecf861223aa252a195584e1b67cdbca5519496a Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Mon, 27 Apr 2026 18:31:45 -0500 Subject: [PATCH 23/25] add missing fields back --- testdata/scripts/nodes/solana/list/list.txtar | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testdata/scripts/nodes/solana/list/list.txtar b/testdata/scripts/nodes/solana/list/list.txtar index 190f8a97614..81f5ec851f8 100644 --- a/testdata/scripts/nodes/solana/list/list.txtar +++ b/testdata/scripts/nodes/solana/list/list.txtar @@ -46,6 +46,8 @@ State: Config: Name = 'Blue' URL = 'wss://primaryfoo.bar' SendOnly = false +Order = 100 +IsLoadBalancedRPC = false ----------------------------- Name: Yellow @@ -54,5 +56,7 @@ State: Config: Name = 'Yellow' URL = 'wss://sendonlyfoo.bar' SendOnly = false +Order = 100 +IsLoadBalancedRPC = false ----------------------------- From 40d24efe9a44c873540acfb395362cf359263df6 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 28 Apr 2026 13:05:49 -0500 Subject: [PATCH 24/25] remove the old code added accidentally --- .../web/chains_controller_integration_test.go | 2 + core/web/chains_controller_test.go | 163 ------------------ 2 files changed, 2 insertions(+), 163 deletions(-) diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 35be8af90f0..262ca47f1f7 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -297,6 +297,8 @@ FinalizedBlockOffset = 50 Name = 'primary' URL = 'http://solana.example' SendOnly = false +Order = 100 +IsLoadBalancedRPC = false `, } }, diff --git a/core/web/chains_controller_test.go b/core/web/chains_controller_test.go index f89c142740c..84aa901b9e4 100644 --- a/core/web/chains_controller_test.go +++ b/core/web/chains_controller_test.go @@ -224,167 +224,4 @@ func setupEVMChainsControllerTest(t *testing.T, cfg chainlink.GeneralConfig) *Te } } -func Test_SolanaChainsController_Show(t *testing.T) { - t.Parallel() - - const validID = "Chainlink-12" - - testCases := []struct { - name string - inputID string - wantStatusCode int - want func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus - }{ - { - inputID: validID, - name: "success", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - wc := &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - wc.SetDefaults() - cfgStr, err := wc.TOMLString() - require.NoError(t, err) - return &commonTypes.ChainStatus{ - ID: validID, - Enabled: true, - Config: cfgStr, - } - }, - wantStatusCode: http.StatusOK, - }, - { - inputID: "234", - name: "not found", - want: func(t *testing.T, app *cltest.TestApplication) *commonTypes.ChainStatus { - return nil - }, - wantStatusCode: http.StatusBadRequest, - }, - } - - for _, testCase := range testCases { - tc := testCase - - t.Run(tc.name, func(t *testing.T) { - t.Parallel() - - controller := setupSolanaChainsControllerTestV2(t, &config.TOMLConfig{ - ChainID: ptr(validID), - Chain: config.Chain{ - SkipPreflight: ptr(false), - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - }) - - wantedResult := tc.want(t, controller.app) - resp, cleanup := controller.client.Get( - "/v2/chains/solana/" + tc.inputID, - ) - t.Cleanup(cleanup) - require.Equal(t, tc.wantStatusCode, resp.StatusCode) - - if wantedResult != nil { - resource1 := presenters.ChainResource{} - err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, resp), &resource1) - require.NoError(t, err) - - assert.Equal(t, wantedResult.ID, resource1.ID) - assert.Equal(t, wantedResult.Enabled, resource1.Enabled) - assert.Equal(t, wantedResult.Config, resource1.Config) - } - }) - } -} - -func Test_SolanaChainsController_Index(t *testing.T) { - t.Parallel() - - chainA := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestA-%d", rand.Int31n(999999))), - Chain: config.Chain{ - TxTimeout: commoncfg.MustNewDuration(time.Hour), - }, - } - chainB := &config.TOMLConfig{ - ChainID: ptr(fmt.Sprintf("ChainlinktestB-%d", rand.Int31n(999999))), - Chain: config.Chain{ - SkipPreflight: ptr(false), - }, - } - controller := setupSolanaChainsControllerTestV2(t, chainA, chainB) - - badResp, cleanup := controller.client.Get("/v2/chains/solana?size=asd") - t.Cleanup(cleanup) - require.Equal(t, http.StatusUnprocessableEntity, badResp.StatusCode) - - resp, cleanup := controller.client.Get("/v2/chains/solana?size=1") - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - body := cltest.ParseResponseBody(t, resp) - - metaCount, err := cltest.ParseJSONAPIResponseMetaCount(body) - require.NoError(t, err) - require.Equal(t, 2, metaCount) - - var links jsonapi.Links - - chains := []presenters.ChainResource{} - err = web.ParsePaginatedResponse(body, &chains, &links) - require.NoError(t, err) - assert.NotEmpty(t, links["next"].Href) - assert.Empty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainA.ChainID, chains[0].ID) - tomlA, err := chainA.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlA, chains[0].Config) - - resp, cleanup = controller.client.Get(links["next"].Href) - t.Cleanup(cleanup) - require.Equal(t, http.StatusOK, resp.StatusCode) - - chains = []presenters.ChainResource{} - err = web.ParsePaginatedResponse(cltest.ParseResponseBody(t, resp), &chains, &links) - require.NoError(t, err) - assert.Empty(t, links["next"].Href) - assert.NotEmpty(t, links["prev"].Href) - - assert.Len(t, links, 1) - assert.Equal(t, *chainB.ChainID, chains[0].ID) - tomlB, err := chainB.TOMLString() - require.NoError(t, err) - assert.Equal(t, tomlB, chains[0].Config) -} - -type TestSolanaChainsController struct { - app *cltest.TestApplication - client cltest.HTTPClientCleaner -} - -func setupSolanaChainsControllerTestV2(t *testing.T, cfgs ...*config.TOMLConfig) *TestSolanaChainsController { - for i := range cfgs { - cfgs[i].SetDefaults() - } - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.Solana = cfgs - c.EVM = nil - }) - app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) - - client := app.NewHTTPClient(nil) - - return &TestSolanaChainsController{ - app: app, - client: client, - } -} - func ptr[T any](t T) *T { return &t } From 8c8fca287e364e8e94cd804ee9741f5b7ff8fa85 Mon Sep 17 00:00:00 2001 From: Joe Huang Date: Tue, 28 Apr 2026 13:43:49 -0500 Subject: [PATCH 25/25] revert test modification --- core/web/chains_controller_integration_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/web/chains_controller_integration_test.go b/core/web/chains_controller_integration_test.go index 262ca47f1f7..35be8af90f0 100644 --- a/core/web/chains_controller_integration_test.go +++ b/core/web/chains_controller_integration_test.go @@ -297,8 +297,6 @@ FinalizedBlockOffset = 50 Name = 'primary' URL = 'http://solana.example' SendOnly = false -Order = 100 -IsLoadBalancedRPC = false `, } },