From eac5fdc92cabdc0db72ae7d3b74d479add5ca23a Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Tue, 18 Aug 2026 15:23:18 +0200 Subject: [PATCH] feat: add a method that reads Solana keys to clclient --- framework/.changeset/v0.16.7.md | 1 + framework/clclient/client.go | 40 +++++++++++++++++++++++++++++++++ framework/clclient/models.go | 21 +++++++++++++++++ 3 files changed, 62 insertions(+) create mode 100644 framework/.changeset/v0.16.7.md diff --git a/framework/.changeset/v0.16.7.md b/framework/.changeset/v0.16.7.md new file mode 100644 index 000000000..d31346c47 --- /dev/null +++ b/framework/.changeset/v0.16.7.md @@ -0,0 +1 @@ +- Add a method to read Solana keys to `clclient` diff --git a/framework/clclient/client.go b/framework/clclient/client.go index c4d629931..fec827da0 100644 --- a/framework/clclient/client.go +++ b/framework/clclient/client.go @@ -897,6 +897,46 @@ func (c *ChainlinkClient) MustReadAptosAccounts() ([]string, error) { return accounts, nil } +// ReadSolanaKeys reads all Solana keys from the Chainlink node +func (c *ChainlinkClient) ReadSolanaKeys() (*SolanaKeys, *resty.Response, error) { + solanaKeys := &SolanaKeys{} + framework.L.Info().Str(NodeURL, c.Config.URL).Msg("Reading Solana Keys") + resp, err := c.APIClient.R(). + SetResult(solanaKeys). + Get("/v2/keys/solana") + if err != nil { + return nil, nil, err + } + if len(solanaKeys.Data) == 0 { + framework.L.Warn().Str(NodeURL, c.Config.URL).Msg("Found no Solana Keys on the node") + } + return solanaKeys, resp, nil +} + +// MustReadSolanaKeys reads all Solana keys from the Chainlink node and returns an error if the request is unsuccessful. +func (c *ChainlinkClient) MustReadSolanaKeys() (*SolanaKeys, *resty.Response, error) { + solanaKeys, res, err := c.ReadSolanaKeys() + if err != nil { + return nil, res, err + } + return solanaKeys, res, VerifyStatusCodeWithResponse(res, http.StatusOK) +} + +// MustReadSolanaAccounts reads all Solana public keys (used as account addresses) from the Chainlink node. +func (c *ChainlinkClient) MustReadSolanaAccounts() ([]string, error) { + solanaKeys, _, err := c.MustReadSolanaKeys() + if err != nil { + return nil, err + } + + accounts := make([]string, 0, len(solanaKeys.Data)) + for _, key := range solanaKeys.Data { + accounts = append(accounts, key.Attributes.PublicKey) + } + + return accounts, nil +} + // DeleteTxKey deletes an tx key based on the provided ID func (c *ChainlinkClient) DeleteTxKey(chain string, id string) (*http.Response, error) { framework.L.Info().Str(NodeURL, c.Config.URL).Str("ID", id).Msg("Deleting Tx Key") diff --git a/framework/clclient/models.go b/framework/clclient/models.go index aace3343c..d6fb2f9a3 100644 --- a/framework/clclient/models.go +++ b/framework/clclient/models.go @@ -250,6 +250,27 @@ type AptosKeys struct { Data []AptosKeyData `json:"data"` } +// SolanaKeyAttributes is the model that represents the created Solana key attributes when read +type SolanaKeyAttributes struct { + PublicKey string `json:"publicKey"` +} + +// SolanaKeyData is the model that represents the created Solana keys when read +type SolanaKeyData struct { + ID string `json:"id"` + Attributes SolanaKeyAttributes `json:"attributes"` +} + +// SolanaKey is the model that represents the created Solana key when read +type SolanaKey struct { + Data SolanaKeyData `json:"data"` +} + +// SolanaKeys is the model that represents the created Solana keys when read +type SolanaKeys struct { + Data []SolanaKeyData `json:"data"` +} + // OCRKeys is the model that represents the created OCR keys when read type OCRKeys struct { Data []OCRKeyData `json:"data"`