From b51308adb919dfc1f6747a64814157ae098319ad Mon Sep 17 00:00:00 2001 From: ilija42 Date: Thu, 18 Jun 2026 12:36:06 +0200 Subject: [PATCH 01/20] Add stellar to relayer factory --- .../chainlink/relayer_chain_interoperators.go | 18 ++++++++++++++++++ core/services/chainlink/relayer_factory.go | 4 ++++ core/services/relay/relay.go | 2 ++ 3 files changed, 24 insertions(+) diff --git a/core/services/chainlink/relayer_chain_interoperators.go b/core/services/chainlink/relayer_chain_interoperators.go index ce4ea40e818..56251c39355 100644 --- a/core/services/chainlink/relayer_chain_interoperators.go +++ b/core/services/chainlink/relayer_chain_interoperators.go @@ -264,6 +264,24 @@ func InitSui(factory RelayerFactory, ks keystore.Sui, csaKS keystore.CSA, chainC } } +// InitStellar is an option for instantiating Stellar relayers. +func InitStellar(factory RelayerFactory, ks keystore.Stellar, csaKS keystore.CSA, chainCfgs RawConfigs) CoreRelayerChainInitFunc { + return func(op *CoreRelayerChainInteroperators) (err error) { + loopKs := &keystore.StellarLooppSigner{Stellar: ks} + relayers, err := factory.NewStellar(loopKs, &keystore.CSASigner{CSA: csaKS}, chainCfgs) + if err != nil { + return fmt.Errorf("failed to setup Stellar relayer: %w", err) + } + + for id, relayer := range relayers { + op.srvs = append(op.srvs, relayer) + op.loopRelayers[id] = relayer + } + + return nil + } +} + // Get a [loop.Relayer] by id func (rs *CoreRelayerChainInteroperators) Get(id types.RelayID) (loop.Relayer, error) { rs.mu.Lock() diff --git a/core/services/chainlink/relayer_factory.go b/core/services/chainlink/relayer_factory.go index c8d59553ec9..7a87e0a275c 100644 --- a/core/services/chainlink/relayer_factory.go +++ b/core/services/chainlink/relayer_factory.go @@ -179,6 +179,10 @@ func (r *RelayerFactory) NewSui(ks coretypes.Keystore, ksCSA coretypes.Keystore, return r.NewLOOPRelayer("Sui", relay.NetworkSui, env.SuiPlugin, ks, ksCSA, chainCfgs) } +func (r *RelayerFactory) NewStellar(ks coretypes.Keystore, ksCSA coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { + return r.NewLOOPRelayer("Stellar", relay.NetworkStellar, env.StellarPlugin, ks, ksCSA, chainCfgs) +} + func (r *RelayerFactory) NewLOOPRelayer(name string, network string, plugin env.Plugin, ks, ksCSA coretypes.Keystore, chainCfgs RawConfigs) (map[types.RelayID]loop.Relayer, error) { relayers := make(map[types.RelayID]loop.Relayer) lggr := logger.Named(r.Logger, name) diff --git a/core/services/relay/relay.go b/core/services/relay/relay.go index 2811fc050df..94babbdd426 100644 --- a/core/services/relay/relay.go +++ b/core/services/relay/relay.go @@ -17,6 +17,7 @@ const ( NetworkTron = "tron" NetworkTON = "ton" NetworkSui = "sui" + NetworkStellar = "stellar" NetworkDummy = "dummy" ) @@ -30,6 +31,7 @@ var SupportedNetworks = map[string]struct{}{ NetworkTron: {}, NetworkTON: {}, NetworkSui: {}, + NetworkStellar: {}, NetworkDummy: {}, } From 20f647f53c12066d9e739dcae413c3538253c643 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 12:34:37 +0200 Subject: [PATCH 02/20] Add stellar keystore to orm --- core/services/chainlink/node_platform.go | 2 ++ core/services/job/job_orm_test.go | 13 ++++++++++++- core/services/job/orm.go | 5 +++++ core/services/keystore/keystoretest.go | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/core/services/chainlink/node_platform.go b/core/services/chainlink/node_platform.go index a9efb861496..bad4227735d 100644 --- a/core/services/chainlink/node_platform.go +++ b/core/services/chainlink/node_platform.go @@ -249,6 +249,8 @@ func (r nodePlatformSubmitterKeyReader) submitterKeysForRelay(ctx context.Contex return nodePlatformKeyIDs(r.keyStore.TON()) case relay.NetworkSui: return nodePlatformKeyIDs(r.keyStore.Sui()) + case relay.NetworkStellar: + return nodePlatformKeyIDs(r.keyStore.Stellar()) default: return nil, nil } diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 84e918b78f8..7405eda852b 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -250,7 +250,6 @@ func TestORM(t *testing.T) { assert.Equal(t, ocrSpecError2, dbSpecErr2.Description) }) - t.Run("rejects webhook job creation with external initiators", func(t *testing.T) { eiFoo := cltest.MustInsertExternalInitiator(t, borm) eiBar := cltest.MustInsertExternalInitiator(t, borm) @@ -1062,6 +1061,18 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { require.NoError(t, err) }) + t.Run("test Stellar key validation", func(t *testing.T) { + ctx := testing.TB.Context(t) + jb.OCR2OracleSpec.Relay = relay.NetworkStellar + err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") + require.EqualError(t, err, "no Stellar key matching: \"bad key\"") + + stellarKey, err := keyStore.Stellar().Create(ctx) + require.NoError(t, err) + err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, stellarKey.ID()) + require.NoError(t, err) + }) + t.Run("test Mercury ETH key validation", func(t *testing.T) { ctx := testutils.Context(t) jb.OCR2OracleSpec.PluginType = types.Mercury diff --git a/core/services/job/orm.go b/core/services/job/orm.go index f3abbd0ee8a..0f12bc18385 100644 --- a/core/services/job/orm.go +++ b/core/services/job/orm.go @@ -669,6 +669,11 @@ func validateKeyStoreMatchForRelay(ctx context.Context, network string, keyStore if err != nil { return errors.Errorf("no Sui key matching: %q", key) } + case relay.NetworkStellar: + _, err := keyStore.Stellar().Get(key) + if err != nil { + return errors.Errorf("no Stellar key matching: %q", key) + } } return nil } diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go index a77824aa5bc..2b9b64d12e4 100644 --- a/core/services/keystore/keystoretest.go +++ b/core/services/keystore/keystoretest.go @@ -75,6 +75,7 @@ func NewInMemory(ds sqlutil.DataSource, scryptParams keystore.ScryptParams, logf starknet: newStarkNetKeyStore(km), sui: newSuiKeyStore(km), aptos: newAptosKeyStore(km), + stellar: newStellarKeyStore(km), tron: newTronKeyStore(km), ton: newTONKeyStore(km), vrf: newVRFKeyStore(km), From c68cf433ade6cf82bd156f2d0abd77b3d23792be Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 12:35:08 +0200 Subject: [PATCH 03/20] Register Stellar as a LOOP --- core/config/env/env.go | 1 + core/services/chainlink/application.go | 3 +++ deployment/utils/nodetestutils/node.go | 4 +++- plugins/plugins.public.yaml | 5 +++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/core/config/env/env.go b/core/config/env/env.go index 6edaeefb29a..dc5b4951fbc 100644 --- a/core/config/env/env.go +++ b/core/config/env/env.go @@ -38,6 +38,7 @@ var ( TronPlugin = NewPlugin("tron") TONPlugin = NewPlugin("ton") SuiPlugin = NewPlugin("sui") + StellarPlugin = NewPlugin("stellar") CapabilitiesPlugin = NewPlugin("capabilities") // PrometheusDiscoveryHostName is the externally accessible hostname // published by the node in the `/discovery` endpoint. Generally, it is expected to match diff --git a/core/services/chainlink/application.go b/core/services/chainlink/application.go index 54458798f4d..3afe18bf10b 100644 --- a/core/services/chainlink/application.go +++ b/core/services/chainlink/application.go @@ -337,6 +337,9 @@ func NewApplication(ctx context.Context, opts ApplicationOpts) (Application, err if cfg.SuiEnabled() { initOps = append(initOps, InitSui(relayerFactory, keyStore.Sui(), keyStore.CSA(), cfg.SuiConfigs())) } + if cfg.StellarEnabled() { + initOps = append(initOps, InitStellar(relayerFactory, keyStore.Stellar(), keyStore.CSA(), cfg.StellarConfigs())) + } relayChainInterops, err := NewCoreRelayerChainInteroperators(initOps...) if err != nil { diff --git a/deployment/utils/nodetestutils/node.go b/deployment/utils/nodetestutils/node.go index b4526932ff9..52923e68aba 100644 --- a/deployment/utils/nodetestutils/node.go +++ b/deployment/utils/nodetestutils/node.go @@ -273,6 +273,8 @@ func (n Node) JDChainConfigs() ([]*nodev1.ChainConfig, error) { ocrtype = corekeys.Sui case chainsel.FamilyTron: ocrtype = corekeys.Tron + case chainsel.FamilyStellar: + ocrtype = corekeys.Stellar default: return nil, fmt.Errorf("unsupported chain family %v", family) } @@ -491,7 +493,7 @@ func NewNode( require.NoError(t, master.Unlock(ctx, "password")) require.NoError(t, master.CSA().EnsureKey(ctx)) require.NoError(t, master.Workflow().EnsureKey(ctx)) - require.NoError(t, master.OCR2().EnsureKeys(ctx, corekeys.EVM, corekeys.Solana, corekeys.Aptos)) + require.NoError(t, master.OCR2().EnsureKeys(ctx, corekeys.EVM, corekeys.Solana, corekeys.Aptos, corekeys.Stellar)) app, err := chainlink.NewApplication(ctx, chainlink.ApplicationOpts{ Opts: cre.Opts{ diff --git a/plugins/plugins.public.yaml b/plugins/plugins.public.yaml index cbe7fe86e43..d272bb92c64 100644 --- a/plugins/plugins.public.yaml +++ b/plugins/plugins.public.yaml @@ -43,6 +43,11 @@ plugins: gitRef: "5d83a289da752e966692a9f390970dbc86c95c7a" # chainlink-starknet develop (#695 merged) installPath: "./pkg/chainlink/cmd/chainlink-starknet" + stellar: + - moduleURI: "github.com/smartcontractkit/chainlink-stellar" + gitRef: "0e9836f8575b711d87335fbadb1ed28b8f678377" # chainlink-stellar #128 (add-multinode merged) + installPath: "./cmd/chainlink-stellar" + streams: - moduleURI: "github.com/smartcontractkit/chainlink-data-streams" gitRef: "v0.1.15-0.20260522094612-5f9f748bd87a" From 7403d99a8104c9766d49c07b180853b11b15a916 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 12:35:19 +0200 Subject: [PATCH 04/20] run generate --- testdata/scripts/chains/help.txtar | 1 + .../scripts/health/multi-chain-loopp.txtar | 87 +++++++++++++++++++ testdata/scripts/nodes/help.txtar | 1 + 3 files changed, 89 insertions(+) diff --git a/testdata/scripts/chains/help.txtar b/testdata/scripts/chains/help.txtar index 5aedccd4281..fa36a19a67c 100644 --- a/testdata/scripts/chains/help.txtar +++ b/testdata/scripts/chains/help.txtar @@ -14,6 +14,7 @@ COMMANDS: evm Commands for handling evm chains solana Commands for handling solana chains starknet Commands for handling starknet chains + stellar Commands for handling stellar chains sui Commands for handling sui chains ton Commands for handling ton chains tron Commands for handling tron chains diff --git a/testdata/scripts/health/multi-chain-loopp.txtar b/testdata/scripts/health/multi-chain-loopp.txtar index c265928b150..c80bde92c6f 100644 --- a/testdata/scripts/health/multi-chain-loopp.txtar +++ b/testdata/scripts/health/multi-chain-loopp.txtar @@ -102,6 +102,13 @@ Name = 'example' URL = 'http://tron.org' SolidityURL = 'https://solidity.evm' +[[Stellar]] +ChainID = 'cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472' + +[[Stellar.Nodes]] +Name = 'primary' +URL = 'http://stellar.rpc' + -- out.txt -- ok Aptos.4.RelayerService ok Aptos.4.RelayerService.PluginRelayerClient @@ -164,6 +171,14 @@ ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Chain ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Chain.Txm ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.PluginRelayerConfigEmitter ok StarkNet.Baz.RelayerService.PluginRelayerClient.PluginStarknet.Relayer +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.PluginRelayerConfigEmitter +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain.MultiNode +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain.StellarTxm +ok Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarRelayer ok Sui.67.RelayerService ok Sui.67.RelayerService.PluginRelayerClient ok Sui.67.RelayerService.PluginRelayerClient.PluginSui @@ -735,6 +750,78 @@ ok WorkflowStore "output": "" } }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.PluginRelayerConfigEmitter", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.PluginRelayerConfigEmitter", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain.MultiNode", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain.MultiNode", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain.StellarTxm", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarChain.StellarTxm", + "status": "passing", + "output": "" + } + }, + { + "type": "checks", + "id": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarRelayer", + "attributes": { + "name": "Stellar.cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472.RelayerService.PluginRelayerClient.PluginStellar.StellarRelayer", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "Sui.67.RelayerService", diff --git a/testdata/scripts/nodes/help.txtar b/testdata/scripts/nodes/help.txtar index 67511bd4f75..c6ffcbdd7c9 100644 --- a/testdata/scripts/nodes/help.txtar +++ b/testdata/scripts/nodes/help.txtar @@ -14,6 +14,7 @@ COMMANDS: evm Commands for handling evm node configuration solana Commands for handling solana node configuration starknet Commands for handling starknet node configuration + stellar Commands for handling stellar node configuration sui Commands for handling sui node configuration ton Commands for handling ton node configuration tron Commands for handling tron node configuration From 2daa7feda10dde8869ae99814240e2a816d5f3f0 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 14:09:23 +0200 Subject: [PATCH 05/20] Cleanup stellar core node cmds --- core/cmd/app.go | 1 + core/cmd/stellar_keys_commands.go | 57 ++++++ core/cmd/stellar_keys_commands_test.go | 174 ++++++++++++++++++ core/internal/cltest/cltest.go | 4 + core/web/auth/auth_test.go | 8 + core/web/presenters/stellar_key.go | 34 ++++ core/web/router.go | 1 + core/web/stellar_keys_controller.go | 13 ++ core/web/stellar_keys_controller_test.go | 108 +++++++++++ stellar_smoke.toml | 9 + testdata/scripts/chains/stellar/help.txtar | 16 ++ .../scripts/chains/stellar/list/help.txtar | 9 + testdata/scripts/help-all/help-all.txtar | 10 + testdata/scripts/keys/help.txtar | 1 + testdata/scripts/keys/stellar/help.txtar | 20 ++ testdata/scripts/nodes/stellar/help.txtar | 16 ++ .../scripts/nodes/stellar/list/help.txtar | 9 + 17 files changed, 490 insertions(+) create mode 100644 core/cmd/stellar_keys_commands.go create mode 100644 core/cmd/stellar_keys_commands_test.go create mode 100644 core/web/presenters/stellar_key.go create mode 100644 core/web/stellar_keys_controller.go create mode 100644 core/web/stellar_keys_controller_test.go create mode 100644 stellar_smoke.toml create mode 100644 testdata/scripts/chains/stellar/help.txtar create mode 100644 testdata/scripts/chains/stellar/list/help.txtar create mode 100644 testdata/scripts/keys/stellar/help.txtar create mode 100644 testdata/scripts/nodes/stellar/help.txtar create mode 100644 testdata/scripts/nodes/stellar/list/help.txtar diff --git a/core/cmd/app.go b/core/cmd/app.go index b8d8776fbe9..d160a1a1e3b 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -206,6 +206,7 @@ func NewApp(s *Shell) *cli.App { keysCommand("Solana", NewSolanaKeysClient(s)), keysCommand("StarkNet", NewStarkNetKeysClient(s)), keysCommand("Aptos", NewAptosKeysClient(s)), + keysCommand("Stellar", NewStellarKeysClient(s)), keysCommand("Tron", NewTronKeysClient(s)), keysCommand("TON", NewTONKeysClient(s)), keysCommand("Sui", NewSuiKeysClient(s)), diff --git a/core/cmd/stellar_keys_commands.go b/core/cmd/stellar_keys_commands.go new file mode 100644 index 00000000000..fa109af50fd --- /dev/null +++ b/core/cmd/stellar_keys_commands.go @@ -0,0 +1,57 @@ +package cmd + +import ( + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +type StellarKeyPresenter struct { + JAID + presenters.StellarKeyResource +} + +// RenderTable implements TableRenderer +func (p StellarKeyPresenter) RenderTable(rt RendererTable) error { + headers := []string{"ID", "Stellar Public Key"} + rows := [][]string{p.ToRow()} + + if _, err := rt.Write([]byte("🔑 Stellar Keys\n")); err != nil { + return err + } + renderList(headers, rows, rt.Writer) + + return utils.JustError(rt.Write([]byte("\n"))) +} + +func (p *StellarKeyPresenter) ToRow() []string { + row := []string{ + p.ID, + p.PubKey, + } + + return row +} + +type StellarKeyPresenters []StellarKeyPresenter + +// RenderTable implements TableRenderer +func (ps StellarKeyPresenters) RenderTable(rt RendererTable) error { + headers := []string{"ID", "Stellar Public Key"} + rows := [][]string{} + + for _, p := range ps { + rows = append(rows, p.ToRow()) + } + + if _, err := rt.Write([]byte("🔑 Stellar Keys\n")); err != nil { + return err + } + renderList(headers, rows, rt.Writer) + + return utils.JustError(rt.Write([]byte("\n"))) +} + +func NewStellarKeysClient(s *Shell) KeysClient { + return newKeysClient[stellarkey.Key, StellarKeyPresenter, StellarKeyPresenters]("Stellar", s) +} diff --git a/core/cmd/stellar_keys_commands_test.go b/core/cmd/stellar_keys_commands_test.go new file mode 100644 index 00000000000..1e044dcec64 --- /dev/null +++ b/core/cmd/stellar_keys_commands_test.go @@ -0,0 +1,174 @@ +package cmd_test + +import ( + "bytes" + "context" + "flag" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/urfave/cli" + + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + "github.com/smartcontractkit/chainlink/v2/core/cmd" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func TestStellarKeyPresenter_RenderTable(t *testing.T) { + t.Parallel() + + var ( + id = "GDTERXGZ7J6NQCSTG7ZNDR7RYV6QD2K4U4XG7K6Y4GD5EQLNMXS6K4C5" + pubKey = "somepubkey" + buffer = bytes.NewBufferString("") + r = cmd.RendererTable{Writer: buffer} + ) + + p := cmd.StellarKeyPresenter{ + JAID: cmd.JAID{ID: id}, + StellarKeyResource: presenters.StellarKeyResource{ + JAID: presenters.NewJAID(id), + PubKey: pubKey, + }, + } + + // Render a single resource + require.NoError(t, p.RenderTable(r)) + + output := buffer.String() + assert.Contains(t, output, id) + assert.Contains(t, output, pubKey) + + // Render many resources + buffer.Reset() + ps := cmd.StellarKeyPresenters{p} + require.NoError(t, ps.RenderTable(r)) + + output = buffer.String() + assert.Contains(t, output, id) + assert.Contains(t, output, pubKey) +} + +func TestShell_StellarKeys(t *testing.T) { + app := startNewApplicationV2(t, nil) + ks := app.GetKeyStore().Stellar() + cleanup := func() { + ctx := context.Background() + keys, err := ks.GetAll() + require.NoError(t, err) + for _, key := range keys { + require.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) + } + requireStellarKeyCount(t, app, 0) + } + + t.Run("ListStellarKeys", func(tt *testing.T) { + defer cleanup() + ctx := testing.TB.Context(t) + client, r := app.NewShellAndRenderer() + key, err := app.GetKeyStore().Stellar().Create(ctx) + require.NoError(t, err) + requireStellarKeyCount(t, app, 1) + assert.NoError(t, cmd.NewStellarKeysClient(client).ListKeys(cltest.EmptyCLIContext())) + require.Len(t, r.Renders, 1) + keys := *r.Renders[0].(*cmd.StellarKeyPresenters) + assert.Equal(t, key.PublicKeyStr(), keys[0].PubKey) + }) + + t.Run("CreateStellarKey", func(tt *testing.T) { + defer cleanup() + client, _ := app.NewShellAndRenderer() + require.NoError(t, cmd.NewStellarKeysClient(client).CreateKey(nilContext)) + keys, err := app.GetKeyStore().Stellar().GetAll() + require.NoError(t, err) + require.Len(t, keys, 1) + }) + + t.Run("DeleteStellarKey", func(tt *testing.T) { + defer cleanup() + ctx := testing.TB.Context(t) + client, _ := app.NewShellAndRenderer() + key, err := app.GetKeyStore().Stellar().Create(ctx) + require.NoError(t, err) + requireStellarKeyCount(t, app, 1) + set := flag.NewFlagSet("test", 0) + flagSetApplyFromAction(cmd.NewStellarKeysClient(client).DeleteKey, set, "stellar") + + require.NoError(tt, set.Set("yes", "true")) + + strID := key.ID() + err = set.Parse([]string{strID}) + require.NoError(t, err) + c := cli.NewContext(nil, set, nil) + err = cmd.NewStellarKeysClient(client).DeleteKey(c) + require.NoError(t, err) + requireStellarKeyCount(t, app, 0) + }) + + t.Run("ImportExportStellarKey", func(tt *testing.T) { + defer cleanup() + defer deleteKeyExportFile(t) + ctx := testing.TB.Context(t) + client, _ := app.NewShellAndRenderer() + + _, err := app.GetKeyStore().Stellar().Create(ctx) + require.NoError(t, err) + + keys := requireStellarKeyCount(t, app, 1) + key := keys[0] + keyName := keyNameForTest(t) + + // Export test invalid id + set := flag.NewFlagSet("test Stellar export", 0) + flagSetApplyFromAction(cmd.NewStellarKeysClient(client).ExportKey, set, "stellar") + + require.NoError(tt, set.Parse([]string{"0"})) + require.NoError(tt, set.Set("new-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(tt, set.Set("output", keyName)) + + c := cli.NewContext(nil, set, nil) + err = cmd.NewStellarKeysClient(client).ExportKey(c) + require.Error(t, err, "Error exporting") + require.Error(t, utils.JustError(os.Stat(keyName))) + + // Export test + set = flag.NewFlagSet("test Stellar export", 0) + flagSetApplyFromAction(cmd.NewStellarKeysClient(client).ExportKey, set, "stellar") + + require.NoError(tt, set.Parse([]string{key.ID()})) + require.NoError(tt, set.Set("new-password", "../internal/fixtures/incorrect_password.txt")) + require.NoError(tt, set.Set("output", keyName)) + + c = cli.NewContext(nil, set, nil) + + require.NoError(t, cmd.NewStellarKeysClient(client).ExportKey(c)) + require.NoError(t, utils.JustError(os.Stat(keyName))) + + require.NoError(t, utils.JustError(app.GetKeyStore().Stellar().Delete(ctx, key.ID()))) + requireStellarKeyCount(t, app, 0) + + set = flag.NewFlagSet("test Stellar import", 0) + flagSetApplyFromAction(cmd.NewStellarKeysClient(client).ImportKey, set, "stellar") + + require.NoError(tt, set.Parse([]string{keyName})) + require.NoError(tt, set.Set("old-password", "../internal/fixtures/incorrect_password.txt")) + c = cli.NewContext(nil, set, nil) + require.NoError(t, cmd.NewStellarKeysClient(client).ImportKey(c)) + + requireStellarKeyCount(t, app, 1) + }) +} + +func requireStellarKeyCount(t *testing.T, app chainlink.Application, length int) []stellarkey.Key { + t.Helper() + keys, err := app.GetKeyStore().Stellar().GetAll() + require.NoError(t, err) + require.Len(t, keys, length) + return keys +} diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index 4042714be6f..bec968480cc 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -43,11 +43,13 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/workflows/metering" commonkeystore "github.com/smartcontractkit/chainlink-common/keystore" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/workflows/dontime" "github.com/smartcontractkit/chainlink-data-streams/llo/retirement" "github.com/smartcontractkit/chainlink-framework/multinode" + "github.com/smartcontractkit/chainlink/v2/core/capabilities/compute" "github.com/smartcontractkit/chainlink-evm/pkg/assets" @@ -72,6 +74,7 @@ import ( "github.com/smartcontractkit/chainlink-common/keystore/corekeys/vrfkey" "github.com/smartcontractkit/chainlink-data-streams/mercury/wsrpc" "github.com/smartcontractkit/chainlink-data-streams/mercury/wsrpc/cache" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/capabilities" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" @@ -138,6 +141,7 @@ var ( DefaultTronKey = tronkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultTONKey = tonkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultSuiKey = suikey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) + DefaultStellarKey = stellarkey.MustNewInsecure(keystest.NewRandReaderFromSeed(KeyBigIntSeed)) DefaultVRFKey = vrfkey.MustNewV2XXXTestingOnly(big.NewInt(KeyBigIntSeed)) ) diff --git a/core/web/auth/auth_test.go b/core/web/auth/auth_test.go index e5d973efa95..0585ab1d57c 100644 --- a/core/web/auth/auth_test.go +++ b/core/web/auth/auth_test.go @@ -276,30 +276,35 @@ var routesRolesMap = [...]routeRules{ {"GET", "/v2/keys/cosmos", true, true, true}, {"GET", "/v2/keys/starknet", true, true, true}, {"GET", "/v2/keys/aptos", true, true, true}, + {"GET", "/v2/keys/stellar", true, true, true}, {"GET", "/v2/keys/tron", true, true, true}, {"GET", "/v2/keys/ton", true, true, true}, {"POST", "/v2/keys/solana", false, false, true}, {"POST", "/v2/keys/cosmos", false, false, true}, {"POST", "/v2/keys/starknet", false, false, true}, {"POST", "/v2/keys/aptos", false, false, true}, + {"POST", "/v2/keys/stellar", false, false, true}, {"POST", "/v2/keys/tron", false, false, true}, {"POST", "/v2/keys/ton", false, false, true}, {"DELETE", "/v2/keys/solana/MOCK", false, false, false}, {"DELETE", "/v2/keys/cosmos/MOCK", false, false, false}, {"DELETE", "/v2/keys/starknet/MOCK", false, false, false}, {"DELETE", "/v2/keys/aptos/MOCK", false, false, false}, + {"DELETE", "/v2/keys/stellar/MOCK", false, false, false}, {"DELETE", "/v2/keys/tron/MOCK", false, false, false}, {"DELETE", "/v2/keys/ton/MOCK", false, false, false}, {"POST", "/v2/keys/solana/import", false, false, false}, {"POST", "/v2/keys/cosmos/import", false, false, false}, {"POST", "/v2/keys/starknet/import", false, false, false}, {"POST", "/v2/keys/aptos/import", false, false, false}, + {"POST", "/v2/keys/stellar/import", false, false, false}, {"POST", "/v2/keys/tron/import", false, false, false}, {"POST", "/v2/keys/ton/import", false, false, false}, {"POST", "/v2/keys/solana/export/MOCK", false, false, false}, {"POST", "/v2/keys/cosmos/export/MOCK", false, false, false}, {"POST", "/v2/keys/starknet/export/MOCK", false, false, false}, {"POST", "/v2/keys/aptos/export/MOCK", false, false, false}, + {"POST", "/v2/keys/stellar/export/MOCK", false, false, false}, {"POST", "/v2/keys/tron/export/MOCK", false, false, false}, {"POST", "/v2/keys/ton/export/MOCK", false, false, false}, {"GET", "/v2/keys/vrf", true, true, true}, @@ -320,15 +325,18 @@ var routesRolesMap = [...]routeRules{ {"PATCH", "/v2/log", false, false, false}, {"GET", "/v2/chains/evm", true, true, true}, {"GET", "/v2/chains/solana", true, true, true}, + {"GET", "/v2/chains/stellar", true, true, true}, {"GET", "/v2/chains/cosmos", true, true, true}, {"GET", "/v2/chains/evm/MOCK", true, true, true}, {"GET", "/v2/chains/cosmos/MOCK", true, true, true}, {"GET", "/v2/nodes/", true, true, true}, {"GET", "/v2/nodes/evm", true, true, true}, {"GET", "/v2/nodes/solana", true, true, true}, + {"GET", "/v2/nodes/stellar", true, true, true}, {"GET", "/v2/nodes/cosmos", true, true, true}, {"GET", "/v2/chains/evm/MOCK/nodes", true, true, true}, {"GET", "/v2/chains/solana/MOCK/nodes", true, true, true}, + {"GET", "/v2/chains/stellar/MOCK/nodes", true, true, true}, {"GET", "/v2/chains/cosmos/MOCK/nodes", true, true, true}, {"GET", "/v2/nodes/evm/forwarders", true, true, true}, {"POST", "/v2/nodes/evm/forwarders/track", false, false, true}, diff --git a/core/web/presenters/stellar_key.go b/core/web/presenters/stellar_key.go new file mode 100644 index 00000000000..e2675d73913 --- /dev/null +++ b/core/web/presenters/stellar_key.go @@ -0,0 +1,34 @@ +package presenters + +import ( + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" +) + +// StellarKeyResource represents a Stellar key JSONAPI resource. +type StellarKeyResource struct { + JAID + PubKey string `json:"publicKey"` +} + +// GetName implements the api2go EntityNamer interface +func (StellarKeyResource) GetName() string { + return "encryptedStellarKeys" +} + +func NewStellarKeyResource(key stellarkey.Key) *StellarKeyResource { + r := &StellarKeyResource{ + JAID: JAID{ID: key.ID()}, + PubKey: key.PublicKeyStr(), + } + + return r +} + +func NewStellarKeyResources(keys []stellarkey.Key) []StellarKeyResource { + rs := []StellarKeyResource{} + for _, key := range keys { + rs = append(rs, *NewStellarKeyResource(key)) + } + + return rs +} diff --git a/core/web/router.go b/core/web/router.go index ce1160b63f7..3a93812f40c 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -360,6 +360,7 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { {"cosmos", NewCosmosKeysController(app)}, {"starknet", NewStarkNetKeysController(app)}, {"aptos", NewAptosKeysController(app)}, + {"stellar", NewStellarKeysController(app)}, {"tron", NewTronKeysController(app)}, {"sui", NewSuiKeysController(app)}, {"ton", NewTONKeysController(app)}, diff --git a/core/web/stellar_keys_controller.go b/core/web/stellar_keys_controller.go new file mode 100644 index 00000000000..164fd732acd --- /dev/null +++ b/core/web/stellar_keys_controller.go @@ -0,0 +1,13 @@ +package web + +import ( + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" + + "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func NewStellarKeysController(app chainlink.Application) KeysController { + return NewKeysController[stellarkey.Key, presenters.StellarKeyResource](app.GetKeyStore().Stellar(), app.GetLogger(), app.GetAuditLogger(), + "stellarKey", presenters.NewStellarKeyResource, presenters.NewStellarKeyResources) +} diff --git a/core/web/stellar_keys_controller_test.go b/core/web/stellar_keys_controller_test.go new file mode 100644 index 00000000000..0da37e416bd --- /dev/null +++ b/core/web/stellar_keys_controller_test.go @@ -0,0 +1,108 @@ +package web_test + +import ( + "net/http" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/services/keystore" + "github.com/smartcontractkit/chainlink/v2/core/web" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" +) + +func TestStellarKeysController_Index_HappyPath(t *testing.T) { + t.Parallel() + + client, keyStore := setupStellarKeysControllerTests(t) + keys, _ := keyStore.Stellar().GetAll() + + response, cleanup := client.Get("/v2/keys/stellar") + t.Cleanup(cleanup) + cltest.AssertServerResponse(t, response, http.StatusOK) + + var resources []presenters.StellarKeyResource + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, response), &resources) + require.NoError(t, err) + + require.Len(t, resources, len(keys)) + + assert.Equal(t, keys[0].ID(), resources[0].ID) + assert.Equal(t, keys[0].PublicKeyStr(), resources[0].PubKey) +} + +func TestStellarKeysController_Create_HappyPath(t *testing.T) { + t.Parallel() + + app := cltest.NewApplicationEVMDisabled(t) + require.NoError(t, app.Start(testing.TB.Context(t))) + client := app.NewHTTPClient(nil) + keyStore := app.GetKeyStore() + + response, cleanup := client.Post("/v2/keys/stellar", nil) + t.Cleanup(cleanup) + cltest.AssertServerResponse(t, response, http.StatusOK) + + keys, _ := keyStore.Stellar().GetAll() + require.Len(t, keys, 1) + + resource := presenters.StellarKeyResource{} + err := web.ParseJSONAPIResponse(cltest.ParseResponseBody(t, response), &resource) + require.NoError(t, err) + + assert.Equal(t, keys[0].ID(), resource.ID) + assert.Equal(t, keys[0].PublicKeyStr(), resource.PubKey) + + _, err = keyStore.Stellar().Get(resource.ID) + require.NoError(t, err) +} + +func TestStellarKeysController_Delete_NonExistentStellarKeyID(t *testing.T) { + t.Parallel() + + client, _ := setupStellarKeysControllerTests(t) + + nonExistentStellarKeyID := "foobar" + response, cleanup := client.Delete("/v2/keys/stellar/" + nonExistentStellarKeyID) + t.Cleanup(cleanup) + assert.Equal(t, http.StatusNotFound, response.StatusCode) +} + +func TestStellarKeysController_Delete_HappyPath(t *testing.T) { + t.Parallel() + ctx := testing.TB.Context(t) + + client, keyStore := setupStellarKeysControllerTests(t) + + keys, _ := keyStore.Stellar().GetAll() + initialLength := len(keys) + key, _ := keyStore.Stellar().Create(ctx) + + response, cleanup := client.Delete("/v2/keys/stellar/" + key.ID()) + t.Cleanup(cleanup) + assert.Equal(t, http.StatusOK, response.StatusCode) + require.Error(t, utils.JustError(keyStore.Stellar().Get(key.ID()))) + + keys, _ = keyStore.Stellar().GetAll() + assert.Len(t, keys, initialLength) +} + +func setupStellarKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { + t.Helper() + ctx := testing.TB.Context(t) + + app := cltest.NewApplication(t) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + stellarKeyStore := app.GetKeyStore().Stellar() + require.NotNil(t, stellarKeyStore) + require.NoError(t, stellarKeyStore.Add(ctx, cltest.DefaultStellarKey)) + + client := app.NewHTTPClient(nil) + + return client, app.GetKeyStore() +} diff --git a/stellar_smoke.toml b/stellar_smoke.toml new file mode 100644 index 00000000000..bd08ab195d0 --- /dev/null +++ b/stellar_smoke.toml @@ -0,0 +1,9 @@ +[Webserver] +HTTPPort = 6688 + +[[Stellar]] +ChainID = 'cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472' + +[[Stellar.Nodes]] +Name = 'primary' +URL = 'https://soroban-testnet.stellar.org' \ No newline at end of file diff --git a/testdata/scripts/chains/stellar/help.txtar b/testdata/scripts/chains/stellar/help.txtar new file mode 100644 index 00000000000..686fe4435a9 --- /dev/null +++ b/testdata/scripts/chains/stellar/help.txtar @@ -0,0 +1,16 @@ +exec chainlink chains stellar --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink chains stellar - Commands for handling stellar chains + +USAGE: + chainlink chains stellar command [command options] [arguments...] + +COMMANDS: + list List all existing stellar chains + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/chains/stellar/list/help.txtar b/testdata/scripts/chains/stellar/list/help.txtar new file mode 100644 index 00000000000..c64736f9f2d --- /dev/null +++ b/testdata/scripts/chains/stellar/list/help.txtar @@ -0,0 +1,9 @@ +exec chainlink chains stellar list --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink chains stellar list - List all existing stellar chains + +USAGE: + chainlink chains stellar list [arguments...] diff --git a/testdata/scripts/help-all/help-all.txtar b/testdata/scripts/help-all/help-all.txtar index 6e356c6db2d..99b03516abc 100644 --- a/testdata/scripts/help-all/help-all.txtar +++ b/testdata/scripts/help-all/help-all.txtar @@ -34,6 +34,8 @@ chains solana # Commands for handling solana chains chains solana list # List all existing solana chains chains starknet # Commands for handling starknet chains chains starknet list # List all existing starknet chains +chains stellar # Commands for handling stellar chains +chains stellar list # List all existing stellar chains chains sui # Commands for handling sui chains chains sui list # List all existing sui chains chains ton # Commands for handling ton chains @@ -117,6 +119,12 @@ keys starknet delete # Delete StarkNet key if present keys starknet export # Export StarkNet key to keyfile keys starknet import # Import StarkNet key from keyfile keys starknet list # List the StarkNet keys +keys stellar # Remote commands for administering the node's Stellar keys +keys stellar create # Create a Stellar key +keys stellar delete # Delete Stellar key if present +keys stellar export # Export Stellar key to keyfile +keys stellar import # Import Stellar key from keyfile +keys stellar list # List the Stellar keys keys sui # Remote commands for administering the node's Sui keys keys sui create # Create a Sui key keys sui delete # Delete Sui key if present @@ -174,6 +182,8 @@ nodes solana # Commands for handling solana node configuration nodes solana list # List all existing solana nodes nodes starknet # Commands for handling starknet node configuration nodes starknet list # List all existing starknet nodes +nodes stellar # Commands for handling stellar node configuration +nodes stellar list # List all existing stellar nodes nodes sui # Commands for handling sui node configuration nodes sui list # List all existing sui nodes nodes ton # Commands for handling ton node configuration diff --git a/testdata/scripts/keys/help.txtar b/testdata/scripts/keys/help.txtar index f6df3bc6090..38e3dfa4d3a 100644 --- a/testdata/scripts/keys/help.txtar +++ b/testdata/scripts/keys/help.txtar @@ -18,6 +18,7 @@ COMMANDS: solana Remote commands for administering the node's Solana keys starknet Remote commands for administering the node's StarkNet keys aptos Remote commands for administering the node's Aptos keys + stellar Remote commands for administering the node's Stellar keys tron Remote commands for administering the node's Tron keys ton Remote commands for administering the node's TON keys sui Remote commands for administering the node's Sui keys diff --git a/testdata/scripts/keys/stellar/help.txtar b/testdata/scripts/keys/stellar/help.txtar new file mode 100644 index 00000000000..93af2b9d612 --- /dev/null +++ b/testdata/scripts/keys/stellar/help.txtar @@ -0,0 +1,20 @@ +exec chainlink keys stellar --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink keys stellar - Remote commands for administering the node's Stellar keys + +USAGE: + chainlink keys stellar command [command options] [arguments...] + +COMMANDS: + create Create a Stellar key + import Import Stellar key from keyfile + export Export Stellar key to keyfile + delete Delete Stellar key if present + list List the Stellar keys + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/nodes/stellar/help.txtar b/testdata/scripts/nodes/stellar/help.txtar new file mode 100644 index 00000000000..9f6a3c6f4c7 --- /dev/null +++ b/testdata/scripts/nodes/stellar/help.txtar @@ -0,0 +1,16 @@ +exec chainlink nodes stellar --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink nodes stellar - Commands for handling stellar node configuration + +USAGE: + chainlink nodes stellar command [command options] [arguments...] + +COMMANDS: + list List all existing stellar nodes + +OPTIONS: + --help, -h show help + diff --git a/testdata/scripts/nodes/stellar/list/help.txtar b/testdata/scripts/nodes/stellar/list/help.txtar new file mode 100644 index 00000000000..9349cf46a22 --- /dev/null +++ b/testdata/scripts/nodes/stellar/list/help.txtar @@ -0,0 +1,9 @@ +exec chainlink nodes stellar list --help +cmp stdout out.txt + +-- out.txt -- +NAME: + chainlink nodes stellar list - List all existing stellar nodes + +USAGE: + chainlink nodes stellar list [arguments...] From 6ef7878ae43db40099ff508e343fc328c5a57d41 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 14:18:01 +0200 Subject: [PATCH 06/20] lint --- core/cmd/stellar_keys_commands.go | 3 ++- core/cmd/stellar_keys_commands_test.go | 5 +++++ core/services/job/job_orm_test.go | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/core/cmd/stellar_keys_commands.go b/core/cmd/stellar_keys_commands.go index fa109af50fd..4148817b9be 100644 --- a/core/cmd/stellar_keys_commands.go +++ b/core/cmd/stellar_keys_commands.go @@ -3,6 +3,7 @@ package cmd import ( "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/web/presenters" ) @@ -38,7 +39,7 @@ type StellarKeyPresenters []StellarKeyPresenter // RenderTable implements TableRenderer func (ps StellarKeyPresenters) RenderTable(rt RendererTable) error { headers := []string{"ID", "Stellar Public Key"} - rows := [][]string{} + var rows [][]string for _, p := range ps { rows = append(rows, p.ToRow()) diff --git a/core/cmd/stellar_keys_commands_test.go b/core/cmd/stellar_keys_commands_test.go index 1e044dcec64..d2044f0b452 100644 --- a/core/cmd/stellar_keys_commands_test.go +++ b/core/cmd/stellar_keys_commands_test.go @@ -56,6 +56,7 @@ func TestStellarKeyPresenter_RenderTable(t *testing.T) { } func TestShell_StellarKeys(t *testing.T) { + t.Parallel() app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().Stellar() cleanup := func() { @@ -69,6 +70,7 @@ func TestShell_StellarKeys(t *testing.T) { } t.Run("ListStellarKeys", func(tt *testing.T) { + t.Parallel() defer cleanup() ctx := testing.TB.Context(t) client, r := app.NewShellAndRenderer() @@ -82,6 +84,7 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("CreateStellarKey", func(tt *testing.T) { + t.Parallel() defer cleanup() client, _ := app.NewShellAndRenderer() require.NoError(t, cmd.NewStellarKeysClient(client).CreateKey(nilContext)) @@ -91,6 +94,7 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("DeleteStellarKey", func(tt *testing.T) { + t.Parallel() defer cleanup() ctx := testing.TB.Context(t) client, _ := app.NewShellAndRenderer() @@ -112,6 +116,7 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("ImportExportStellarKey", func(tt *testing.T) { + t.Parallel() defer cleanup() defer deleteKeyExportFile(t) ctx := testing.TB.Context(t) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 7405eda852b..6c37f35a752 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" + "github.com/smartcontractkit/chainlink/v2/core/services/ccv/ccvcommitteeverifier" "github.com/smartcontractkit/chainlink/v2/core/services/ccv/ccvexecutor" "github.com/smartcontractkit/chainlink/v2/core/services/cresettings" @@ -30,6 +31,7 @@ import ( evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ethkey" + "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -1062,6 +1064,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { }) t.Run("test Stellar key validation", func(t *testing.T) { + t.Parallel() ctx := testing.TB.Context(t) jb.OCR2OracleSpec.Relay = relay.NetworkStellar err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") From 175c27a2e6afc685128581e949495d415c3635f2 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 14:24:39 +0200 Subject: [PATCH 07/20] update TestCoreRelayerChainInteroperators with stellar --- core/services/chainlink/relayer_chain_interoperators_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 6d52913f107..2281b3fb90f 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -208,7 +208,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedStarknetChainCnt, tt.expectedStarknetNodeCnt case relay.NetworkDummy: expectedChainCnt, expectedNodeCnt = tt.expectedDummyChainCnt, tt.expectedDummyNodeCnt - case relay.NetworkAptos: + case relay.Net: t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") case relay.NetworkTron: t.Skip("tron doesn't need a CoreRelayerChainInteroperator") @@ -216,7 +216,8 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { t.Skip("ton doesn't need a CoreRelayerChainInteroperator") case relay.NetworkSui: t.Skip("sui doesn't need a CoreRelayerChainInteroperator") - + case relay.NetworkStellar: + t.Skip("stellar doesn't need a CoreRelayerChainInteroperator") default: require.Fail(t, "untested relay network", relayNetwork) } From 4c367d05885c3b14a62a0ab8692ed9b67beccbb0 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 14:25:32 +0200 Subject: [PATCH 08/20] rm stray test file --- stellar_smoke.toml | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 stellar_smoke.toml diff --git a/stellar_smoke.toml b/stellar_smoke.toml deleted file mode 100644 index bd08ab195d0..00000000000 --- a/stellar_smoke.toml +++ /dev/null @@ -1,9 +0,0 @@ -[Webserver] -HTTPPort = 6688 - -[[Stellar]] -ChainID = 'cee0302d59844d32bdca915c8203dd44b33fbb7edc19051ea37abedf28ecd472' - -[[Stellar.Nodes]] -Name = 'primary' -URL = 'https://soroban-testnet.stellar.org' \ No newline at end of file From 1addc88ad438b8128488e7196038cd6661f0f1d8 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 14:37:39 +0200 Subject: [PATCH 09/20] lint --- core/cmd/stellar_keys_commands_test.go | 14 +++++++------- .../chainlink/relayer_chain_interoperators_test.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/cmd/stellar_keys_commands_test.go b/core/cmd/stellar_keys_commands_test.go index d2044f0b452..2f1f7550003 100644 --- a/core/cmd/stellar_keys_commands_test.go +++ b/core/cmd/stellar_keys_commands_test.go @@ -70,9 +70,9 @@ func TestShell_StellarKeys(t *testing.T) { } t.Run("ListStellarKeys", func(tt *testing.T) { - t.Parallel() + tt.Parallel() defer cleanup() - ctx := testing.TB.Context(t) + ctx := tt.Context() client, r := app.NewShellAndRenderer() key, err := app.GetKeyStore().Stellar().Create(ctx) require.NoError(t, err) @@ -84,7 +84,7 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("CreateStellarKey", func(tt *testing.T) { - t.Parallel() + tt.Parallel() defer cleanup() client, _ := app.NewShellAndRenderer() require.NoError(t, cmd.NewStellarKeysClient(client).CreateKey(nilContext)) @@ -94,9 +94,9 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("DeleteStellarKey", func(tt *testing.T) { - t.Parallel() + tt.Parallel() defer cleanup() - ctx := testing.TB.Context(t) + ctx := tt.Context() client, _ := app.NewShellAndRenderer() key, err := app.GetKeyStore().Stellar().Create(ctx) require.NoError(t, err) @@ -116,10 +116,10 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("ImportExportStellarKey", func(tt *testing.T) { - t.Parallel() + tt.Parallel() defer cleanup() defer deleteKeyExportFile(t) - ctx := testing.TB.Context(t) + ctx := tt.Context() client, _ := app.NewShellAndRenderer() _, err := app.GetKeyStore().Stellar().Create(ctx) diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 2281b3fb90f..e45b9338fa6 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -208,7 +208,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { expectedChainCnt, expectedNodeCnt = tt.expectedStarknetChainCnt, tt.expectedStarknetNodeCnt case relay.NetworkDummy: expectedChainCnt, expectedNodeCnt = tt.expectedDummyChainCnt, tt.expectedDummyNodeCnt - case relay.Net: + case relay.NetworkAptos: t.Skip("aptos doesn't need a CoreRelayerChainInteroperator") case relay.NetworkTron: t.Skip("tron doesn't need a CoreRelayerChainInteroperator") From f4796a4231acfeab27f87490287d131980cd5f40 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 15:01:27 +0200 Subject: [PATCH 10/20] lint --- core/cmd/app.go | 2 +- core/cmd/stellar_keys_commands_test.go | 5 ----- core/web/router.go | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/core/cmd/app.go b/core/cmd/app.go index d160a1a1e3b..5073c301c74 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -206,10 +206,10 @@ func NewApp(s *Shell) *cli.App { keysCommand("Solana", NewSolanaKeysClient(s)), keysCommand("StarkNet", NewStarkNetKeysClient(s)), keysCommand("Aptos", NewAptosKeysClient(s)), - keysCommand("Stellar", NewStellarKeysClient(s)), keysCommand("Tron", NewTronKeysClient(s)), keysCommand("TON", NewTONKeysClient(s)), keysCommand("Sui", NewSuiKeysClient(s)), + keysCommand("Stellar", NewStellarKeysClient(s)), initVRFKeysSubCmd(s), }, diff --git a/core/cmd/stellar_keys_commands_test.go b/core/cmd/stellar_keys_commands_test.go index 2f1f7550003..857d533f0a0 100644 --- a/core/cmd/stellar_keys_commands_test.go +++ b/core/cmd/stellar_keys_commands_test.go @@ -56,7 +56,6 @@ func TestStellarKeyPresenter_RenderTable(t *testing.T) { } func TestShell_StellarKeys(t *testing.T) { - t.Parallel() app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().Stellar() cleanup := func() { @@ -70,7 +69,6 @@ func TestShell_StellarKeys(t *testing.T) { } t.Run("ListStellarKeys", func(tt *testing.T) { - tt.Parallel() defer cleanup() ctx := tt.Context() client, r := app.NewShellAndRenderer() @@ -84,7 +82,6 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("CreateStellarKey", func(tt *testing.T) { - tt.Parallel() defer cleanup() client, _ := app.NewShellAndRenderer() require.NoError(t, cmd.NewStellarKeysClient(client).CreateKey(nilContext)) @@ -94,7 +91,6 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("DeleteStellarKey", func(tt *testing.T) { - tt.Parallel() defer cleanup() ctx := tt.Context() client, _ := app.NewShellAndRenderer() @@ -116,7 +112,6 @@ func TestShell_StellarKeys(t *testing.T) { }) t.Run("ImportExportStellarKey", func(tt *testing.T) { - tt.Parallel() defer cleanup() defer deleteKeyExportFile(t) ctx := tt.Context() diff --git a/core/web/router.go b/core/web/router.go index 3a93812f40c..4f06158421e 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -360,10 +360,10 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { {"cosmos", NewCosmosKeysController(app)}, {"starknet", NewStarkNetKeysController(app)}, {"aptos", NewAptosKeysController(app)}, - {"stellar", NewStellarKeysController(app)}, {"tron", NewTronKeysController(app)}, {"sui", NewSuiKeysController(app)}, {"ton", NewTONKeysController(app)}, + {"stellar", NewStellarKeysController(app)}, } { authv2.GET("/keys/"+keys.path, keys.kc.Index) authv2.POST("/keys/"+keys.path, auth.RequiresEditRole(keys.kc.Create)) From 2a99bff5792caca2a380cad8a325ff210ea3629c Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 15:20:16 +0200 Subject: [PATCH 11/20] lint --- core/cmd/app.go | 2 +- core/web/router.go | 2 +- deployment/utils/nodetestutils/node.go | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/core/cmd/app.go b/core/cmd/app.go index 5073c301c74..d160a1a1e3b 100644 --- a/core/cmd/app.go +++ b/core/cmd/app.go @@ -206,10 +206,10 @@ func NewApp(s *Shell) *cli.App { keysCommand("Solana", NewSolanaKeysClient(s)), keysCommand("StarkNet", NewStarkNetKeysClient(s)), keysCommand("Aptos", NewAptosKeysClient(s)), + keysCommand("Stellar", NewStellarKeysClient(s)), keysCommand("Tron", NewTronKeysClient(s)), keysCommand("TON", NewTONKeysClient(s)), keysCommand("Sui", NewSuiKeysClient(s)), - keysCommand("Stellar", NewStellarKeysClient(s)), initVRFKeysSubCmd(s), }, diff --git a/core/web/router.go b/core/web/router.go index 4f06158421e..3a93812f40c 100644 --- a/core/web/router.go +++ b/core/web/router.go @@ -360,10 +360,10 @@ func v2Routes(app chainlink.Application, r *gin.RouterGroup) { {"cosmos", NewCosmosKeysController(app)}, {"starknet", NewStarkNetKeysController(app)}, {"aptos", NewAptosKeysController(app)}, + {"stellar", NewStellarKeysController(app)}, {"tron", NewTronKeysController(app)}, {"sui", NewSuiKeysController(app)}, {"ton", NewTONKeysController(app)}, - {"stellar", NewStellarKeysController(app)}, } { authv2.GET("/keys/"+keys.path, keys.kc.Index) authv2.POST("/keys/"+keys.path, auth.RequiresEditRole(keys.kc.Create)) diff --git a/deployment/utils/nodetestutils/node.go b/deployment/utils/nodetestutils/node.go index 52923e68aba..f9ce5e5633f 100644 --- a/deployment/utils/nodetestutils/node.go +++ b/deployment/utils/nodetestutils/node.go @@ -273,8 +273,6 @@ func (n Node) JDChainConfigs() ([]*nodev1.ChainConfig, error) { ocrtype = corekeys.Sui case chainsel.FamilyTron: ocrtype = corekeys.Tron - case chainsel.FamilyStellar: - ocrtype = corekeys.Stellar default: return nil, fmt.Errorf("unsupported chain family %v", family) } From 9c3fdb7a016e7ac3ee3ceabeb2c8436b343dfa6f Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 15:29:38 +0200 Subject: [PATCH 12/20] tm bad test parallel execution --- core/services/job/job_orm_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 6c37f35a752..483d44b1c1b 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -1064,7 +1064,6 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { }) t.Run("test Stellar key validation", func(t *testing.T) { - t.Parallel() ctx := testing.TB.Context(t) jb.OCR2OracleSpec.Relay = relay.NetworkStellar err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") From 352327f53394208b2532af4d7ec1aaa2e1d2fe6f Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 15:30:46 +0200 Subject: [PATCH 13/20] supress lint on parallel test --- core/cmd/shell_local_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 1682c8dbe16..a0051114369 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -741,6 +741,12 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) + + pwd, err := utils.PasswordFromFile("../internal/fixtures/correct_password.txt") + require.NoError(t, err) + + require.NoError(t, keyStore.Unlock(testutils.Context(t), pwd)) + authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), audit.NoopLogger) testRelayers := genTestEVMRelayers(t, cfg, db, keyStore.Eth(), &keystore.CSASigner{CSA: keyStore.CSA()}) @@ -785,7 +791,7 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { // First initialize components (this includes authentication) cliApp := cmd.NewApp(&shell) - err := cliApp.Before(c) + err = cliApp.Before(c) require.NoError(t, err) err = shell.BeforeNode(c) From 776cecadfd75d4d2be9debf82d8c37698a9bc26e Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 15:59:56 +0200 Subject: [PATCH 14/20] lint --- core/cmd/stellar_keys_commands_test.go | 7 ++++++- core/web/presenters/stellar_key.go | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/cmd/stellar_keys_commands_test.go b/core/cmd/stellar_keys_commands_test.go index 857d533f0a0..52ce8f1c110 100644 --- a/core/cmd/stellar_keys_commands_test.go +++ b/core/cmd/stellar_keys_commands_test.go @@ -55,6 +55,7 @@ func TestStellarKeyPresenter_RenderTable(t *testing.T) { assert.Contains(t, output, pubKey) } +//nolint:paralleltest // subtests share a single keystore/application instance func TestShell_StellarKeys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().Stellar() @@ -68,6 +69,7 @@ func TestShell_StellarKeys(t *testing.T) { requireStellarKeyCount(t, app, 0) } + //nolint:paralleltest // subtests share a single keystore/application instance t.Run("ListStellarKeys", func(tt *testing.T) { defer cleanup() ctx := tt.Context() @@ -75,12 +77,13 @@ func TestShell_StellarKeys(t *testing.T) { key, err := app.GetKeyStore().Stellar().Create(ctx) require.NoError(t, err) requireStellarKeyCount(t, app, 1) - assert.NoError(t, cmd.NewStellarKeysClient(client).ListKeys(cltest.EmptyCLIContext())) + require.NoError(t, cmd.NewStellarKeysClient(client).ListKeys(cltest.EmptyCLIContext())) require.Len(t, r.Renders, 1) keys := *r.Renders[0].(*cmd.StellarKeyPresenters) assert.Equal(t, key.PublicKeyStr(), keys[0].PubKey) }) + //nolint:paralleltest // subtests share a single keystore/application instance t.Run("CreateStellarKey", func(tt *testing.T) { defer cleanup() client, _ := app.NewShellAndRenderer() @@ -90,6 +93,7 @@ func TestShell_StellarKeys(t *testing.T) { require.Len(t, keys, 1) }) + //nolint:paralleltest // subtests share a single keystore/application instance t.Run("DeleteStellarKey", func(tt *testing.T) { defer cleanup() ctx := tt.Context() @@ -111,6 +115,7 @@ func TestShell_StellarKeys(t *testing.T) { requireStellarKeyCount(t, app, 0) }) + //nolint:paralleltest // subtests share a single keystore/application instance t.Run("ImportExportStellarKey", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(t) diff --git a/core/web/presenters/stellar_key.go b/core/web/presenters/stellar_key.go index e2675d73913..d2014cc1801 100644 --- a/core/web/presenters/stellar_key.go +++ b/core/web/presenters/stellar_key.go @@ -25,7 +25,7 @@ func NewStellarKeyResource(key stellarkey.Key) *StellarKeyResource { } func NewStellarKeyResources(keys []stellarkey.Key) []StellarKeyResource { - rs := []StellarKeyResource{} + var rs = make([]StellarKeyResource, len(keys)) for _, key := range keys { rs = append(rs, *NewStellarKeyResource(key)) } From 8739f734399f47f397ed7ba7c7425098c3ecaa64 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 16:09:01 +0200 Subject: [PATCH 15/20] lint --- core/cmd/shell_local_test.go | 2 +- core/cmd/stellar_keys_commands.go | 2 +- core/services/job/job_orm_test.go | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index a0051114369..f9b55846fed 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -745,7 +745,7 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { pwd, err := utils.PasswordFromFile("../internal/fixtures/correct_password.txt") require.NoError(t, err) - require.NoError(t, keyStore.Unlock(testutils.Context(t), pwd)) + require.NoError(t, keyStore.Unlock(testing.TB.Context(t), pwd)) authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), audit.NoopLogger) diff --git a/core/cmd/stellar_keys_commands.go b/core/cmd/stellar_keys_commands.go index 4148817b9be..44eae670441 100644 --- a/core/cmd/stellar_keys_commands.go +++ b/core/cmd/stellar_keys_commands.go @@ -39,7 +39,7 @@ type StellarKeyPresenters []StellarKeyPresenter // RenderTable implements TableRenderer func (ps StellarKeyPresenters) RenderTable(rt RendererTable) error { headers := []string{"ID", "Stellar Public Key"} - var rows [][]string + rows := make([][]string, 0, len(ps)) for _, p := range ps { rows = append(rows, p.ToRow()) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index 483d44b1c1b..b2e7d145e80 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -1063,6 +1063,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { require.NoError(t, err) }) + //nolint:paralleltest same instance t.Run("test Stellar key validation", func(t *testing.T) { ctx := testing.TB.Context(t) jb.OCR2OracleSpec.Relay = relay.NetworkStellar From 98204bc2f3b0eb1e2cef523f2586ff039901df81 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 16:33:56 +0200 Subject: [PATCH 16/20] Fix NewStellarKeyResources key slice init --- core/web/presenters/stellar_key.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/web/presenters/stellar_key.go b/core/web/presenters/stellar_key.go index d2014cc1801..2d2983e9820 100644 --- a/core/web/presenters/stellar_key.go +++ b/core/web/presenters/stellar_key.go @@ -25,7 +25,7 @@ func NewStellarKeyResource(key stellarkey.Key) *StellarKeyResource { } func NewStellarKeyResources(keys []stellarkey.Key) []StellarKeyResource { - var rs = make([]StellarKeyResource, len(keys)) + var rs = make([]StellarKeyResource, 0, len(keys)) for _, key := range keys { rs = append(rs, *NewStellarKeyResource(key)) } From 0687730548347a0bd4f5f5c1474b7cbfba72ede7 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 16:40:41 +0200 Subject: [PATCH 17/20] lint --- core/services/job/job_orm_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index b2e7d145e80..d740c3f5d97 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -966,7 +966,7 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing } func TestORM_ValidateKeyStoreMatch(t *testing.T) { - ctx := testutils.Context(t) + ctx := testing.TB.Context(t) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) keyStore := cltest.NewKeyStore(t, pgtest.NewSqlxDB(t)) @@ -1063,8 +1063,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { require.NoError(t, err) }) - //nolint:paralleltest same instance - t.Run("test Stellar key validation", func(t *testing.T) { + t.Run("test Stellar key validation", func(t *testing.T) { //nolint:paralleltest // same instance ctx := testing.TB.Context(t) jb.OCR2OracleSpec.Relay = relay.NetworkStellar err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") From 1436359fcc122cb6044cd6eafb495621667fb83a Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 16:51:10 +0200 Subject: [PATCH 18/20] goimports --- core/cmd/shell_local_test.go | 2 +- core/internal/cltest/cltest.go | 2 +- core/services/job/job_orm_test.go | 13 +++++-------- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index f9b55846fed..b16d440b665 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -742,7 +742,7 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) - pwd, err := utils.PasswordFromFile("../internal/fixtures/correct_password.txt") + pwd, err := utils.PasswordFromFile(test.pwdfile) require.NoError(t, err) require.NoError(t, keyStore.Unlock(testing.TB.Context(t), pwd)) diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index bec968480cc..bb5e0b292aa 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -43,7 +43,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/workflows/metering" commonkeystore "github.com/smartcontractkit/chainlink-common/keystore" - "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" "github.com/smartcontractkit/chainlink-common/pkg/workflows/dontime" @@ -68,6 +67,7 @@ import ( "github.com/smartcontractkit/chainlink-common/keystore/corekeys/p2pkey" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/solkey" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/starkkey" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/stellarkey" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/suikey" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/tonkey" "github.com/smartcontractkit/chainlink-common/keystore/corekeys/tronkey" diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index d740c3f5d97..236d3850e33 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -15,23 +15,16 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/guregu/null.v4" + "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ethkey" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink-common/pkg/utils/jsonserializable" pkgworkflows "github.com/smartcontractkit/chainlink-common/pkg/workflows" - - "github.com/smartcontractkit/chainlink/v2/core/services/ccv/ccvcommitteeverifier" - "github.com/smartcontractkit/chainlink/v2/core/services/ccv/ccvexecutor" - "github.com/smartcontractkit/chainlink/v2/core/services/cresettings" - "github.com/smartcontractkit/chainlink/v2/core/services/workflows/artifacts" - "github.com/smartcontractkit/chainlink-evm/pkg/assets" configtoml "github.com/smartcontractkit/chainlink-evm/pkg/config/toml" "github.com/smartcontractkit/chainlink-evm/pkg/keys" evmtypes "github.com/smartcontractkit/chainlink-evm/pkg/types" - "github.com/smartcontractkit/chainlink-common/keystore/corekeys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" @@ -41,7 +34,10 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" "github.com/smartcontractkit/chainlink/v2/core/services/blockheaderfeeder" + "github.com/smartcontractkit/chainlink/v2/core/services/ccv/ccvcommitteeverifier" + "github.com/smartcontractkit/chainlink/v2/core/services/ccv/ccvexecutor" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" + "github.com/smartcontractkit/chainlink/v2/core/services/cresettings" "github.com/smartcontractkit/chainlink/v2/core/services/cron" "github.com/smartcontractkit/chainlink/v2/core/services/gateway" "github.com/smartcontractkit/chainlink/v2/core/services/job" @@ -53,6 +49,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/standardcapabilities" "github.com/smartcontractkit/chainlink/v2/core/services/streams" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/vrfcommon" + "github.com/smartcontractkit/chainlink/v2/core/services/workflows/artifacts" "github.com/smartcontractkit/chainlink/v2/core/testdata/testspecs" "github.com/smartcontractkit/chainlink/v2/core/utils/testutils/heavyweight" ) From 58c9318d29f70bb46cdd20cc013d892da6188122 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 17:15:13 +0200 Subject: [PATCH 19/20] lint --- core/cmd/shell_local_test.go | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index b16d440b665..acb9d98e678 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -742,11 +742,6 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) - pwd, err := utils.PasswordFromFile(test.pwdfile) - require.NoError(t, err) - - require.NoError(t, keyStore.Unlock(testing.TB.Context(t), pwd)) - authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), audit.NoopLogger) testRelayers := genTestEVMRelayers(t, cfg, db, keyStore.Eth(), &keystore.CSASigner{CSA: keyStore.CSA()}) @@ -791,7 +786,7 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { // First initialize components (this includes authentication) cliApp := cmd.NewApp(&shell) - err = cliApp.Before(c) + err := cliApp.Before(c) require.NoError(t, err) err = shell.BeforeNode(c) From 35278dcd9a9c4c510752c21baedcccef0a10f0e0 Mon Sep 17 00:00:00 2001 From: ilija42 Date: Fri, 19 Jun 2026 17:16:34 +0200 Subject: [PATCH 20/20] lint --- core/cmd/shell_local_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index acb9d98e678..1682c8dbe16 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -741,7 +741,6 @@ func TestShell_RunNode_WithBeforeNode(t *testing.T) { db := pgtest.NewSqlxDB(t) keyStore := cltest.NewKeyStore(t, db) - authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), audit.NoopLogger) testRelayers := genTestEVMRelayers(t, cfg, db, keyStore.Eth(), &keystore.CSASigner{CSA: keyStore.CSA()})