Skip to content

Commit

Permalink
ensure it's possible to fallback to the old chain struct
Browse files Browse the repository at this point in the history
  • Loading branch information
dhaidashenko committed Jan 10, 2025
1 parent a85a581 commit a27d397
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 52 deletions.
17 changes: 11 additions & 6 deletions pkg/solana/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,9 @@ type chain struct {
lggr logger.Logger

// if multiNode is enabled, the clientCache will not be used
multiNode *client.MultiNodeWrappedClient
txSender *mn.TransactionSender[*solanago.Transaction, *client.SendTxResult, mn.StringID, *client.MultiNodeClient]
multiNode *mn.MultiNode[mn.StringID, *client.MultiNodeClient]
txSender *mn.TransactionSender[*solanago.Transaction, *client.SendTxResult, mn.StringID, *client.MultiNodeClient]
multiClient *client.MultiClient

// tracking node chain id for verification
clientCache map[string]*verifiedCachedClient // map URL -> {client, chainId} [mainnet/testnet/devnet/localnet]
Expand Down Expand Up @@ -238,6 +239,7 @@ func newChain(id string, cfg *config.TOMLConfig, ks core.Keystore, lggr logger.L

var tc internal.Loader[client.ReaderWriter] = utils.NewLazyLoad(func() (client.ReaderWriter, error) { return ch.getClient() })
var bc internal.Loader[monitor.BalanceClient] = utils.NewLazyLoad(func() (monitor.BalanceClient, error) { return ch.getClient() })
ch.multiClient = client.NewMultiNodeWrappedClient(ch.getClient)

// txm will default to sending transactions using a single RPC client if sendTx is nil
var sendTx func(ctx context.Context, tx *solanago.Transaction) (solanago.Signature, error)
Expand Down Expand Up @@ -289,8 +291,11 @@ func newChain(id string, cfg *config.TOMLConfig, ks core.Keystore, lggr logger.L
0, // use the default value provided by the implementation
)

ch.multiNode = client.NewMultiNodeWrappedClient(multiNode)
ch.multiNode = multiNode
ch.txSender = txSender
ch.multiClient = client.NewMultiNodeWrappedClient(func() (client.ReaderWriter, error) {
return ch.multiNode.SelectRPC()
})

// clientCache will not be used if multinode is enabled
ch.clientCache = nil
Expand All @@ -304,8 +309,8 @@ func newChain(id string, cfg *config.TOMLConfig, ks core.Keystore, lggr logger.L
return result.Signature(), result.Error()
}

tc = internal.NewLoader[client.ReaderWriter](func() (client.ReaderWriter, error) { return ch.multiNode, nil })
bc = internal.NewLoader[monitor.BalanceClient](func() (monitor.BalanceClient, error) { return ch.multiNode, nil })
tc = internal.NewLoader[client.ReaderWriter](func() (client.ReaderWriter, error) { return ch.multiNode.SelectRPC() })
bc = internal.NewLoader[monitor.BalanceClient](func() (monitor.BalanceClient, error) { return ch.multiNode.SelectRPC() })
}

ch.txm = txm.NewTxm(ch.id, tc, sendTx, cfg, ks, lggr)
Expand Down Expand Up @@ -413,7 +418,7 @@ func (c *chain) ChainID() string {
// If multinode is enabled, it will return a client using the multinode selection instead.
func (c *chain) getClient() (client.ReaderWriter, error) {
if c.cfg.MultiNode.Enabled() {
return c.multiNode, nil
return c.multiNode.SelectRPC()
}

var node *config.Node
Expand Down
87 changes: 41 additions & 46 deletions pkg/solana/client/multinode_wrapped_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,165 +9,160 @@ import (
mn "github.com/smartcontractkit/chainlink-solana/pkg/solana/client/multinode"
)

var _ ReaderWriter = (*MultiNodeWrappedClient)(nil)
var _ ReaderWriter = (*MultiClient)(nil)

// MultiNodeWrappedClient - wrapper over MultiNode that reselect an RPC for each method call.
type MultiNodeWrappedClient struct {
multiNode *mn.MultiNode[mn.StringID, *MultiNodeClient]
// MultiClient - wrapper over multiple RPCs, underlying provider can be MultiNode or LazyLoader.
// Main purpose is to eliminate need for frequent error handling on selection of a client.
type MultiClient struct {
getClient func() (ReaderWriter, error)
}

func NewMultiNodeWrappedClient(multiNode *mn.MultiNode[mn.StringID, *MultiNodeClient]) *MultiNodeWrappedClient {
return &MultiNodeWrappedClient{multiNode}
}

func (m *MultiNodeWrappedClient) Start(ctx context.Context) error {
return m.multiNode.Start(ctx)
func NewMultiNodeWrappedClient(getClient func() (ReaderWriter, error)) *MultiClient {
return &MultiClient{
getClient: getClient,
}
}

func (m *MultiNodeWrappedClient) GetLatestBlockHeight(ctx context.Context) (uint64, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetLatestBlockHeight(ctx context.Context) (uint64, error) {
r, err := m.getClient()
if err != nil {
return 0, err
}

return r.GetLatestBlockHeight(ctx)
}

func (m *MultiNodeWrappedClient) SendTx(ctx context.Context, tx *solana.Transaction) (solana.Signature, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) SendTx(ctx context.Context, tx *solana.Transaction) (solana.Signature, error) {
r, err := m.getClient()
if err != nil {
return solana.Signature{}, err
}

return r.SendTx(ctx, tx)
}

func (m *MultiNodeWrappedClient) SimulateTx(ctx context.Context, tx *solana.Transaction, opts *rpc.SimulateTransactionOpts) (*rpc.SimulateTransactionResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) SimulateTx(ctx context.Context, tx *solana.Transaction, opts *rpc.SimulateTransactionOpts) (*rpc.SimulateTransactionResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.SimulateTx(ctx, tx, opts)
}

func (m *MultiNodeWrappedClient) SignatureStatuses(ctx context.Context, sigs []solana.Signature) ([]*rpc.SignatureStatusesResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) SignatureStatuses(ctx context.Context, sigs []solana.Signature) ([]*rpc.SignatureStatusesResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.SignatureStatuses(ctx, sigs)
}

func (m *MultiNodeWrappedClient) GetAccountInfoWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetAccountInfoOpts) (*rpc.GetAccountInfoResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetAccountInfoWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetAccountInfoOpts) (*rpc.GetAccountInfoResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetAccountInfoWithOpts(ctx, addr, opts)
}

func (m *MultiNodeWrappedClient) Balance(ctx context.Context, addr solana.PublicKey) (uint64, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) Balance(ctx context.Context, addr solana.PublicKey) (uint64, error) {
r, err := m.getClient()
if err != nil {
return 0, err
}

return r.Balance(ctx, addr)
}

func (m *MultiNodeWrappedClient) SlotHeight(ctx context.Context) (uint64, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) SlotHeight(ctx context.Context) (uint64, error) {
r, err := m.getClient()
if err != nil {
return 0, err
}

return r.SlotHeight(ctx)
}

func (m *MultiNodeWrappedClient) LatestBlockhash(ctx context.Context) (*rpc.GetLatestBlockhashResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) LatestBlockhash(ctx context.Context) (*rpc.GetLatestBlockhashResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.LatestBlockhash(ctx)
}

func (m *MultiNodeWrappedClient) ChainID(ctx context.Context) (mn.StringID, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) ChainID(ctx context.Context) (mn.StringID, error) {
r, err := m.getClient()
if err != nil {
return "", err
}

return r.ChainID(ctx)
}

func (m *MultiNodeWrappedClient) GetFeeForMessage(ctx context.Context, msg string) (uint64, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetFeeForMessage(ctx context.Context, msg string) (uint64, error) {
r, err := m.getClient()
if err != nil {
return 0, err
}

return r.GetFeeForMessage(ctx, msg)
}

func (m *MultiNodeWrappedClient) GetLatestBlock(ctx context.Context) (*rpc.GetBlockResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetLatestBlock(ctx context.Context) (*rpc.GetBlockResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetLatestBlock(ctx)
}

func (m *MultiNodeWrappedClient) GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetTransaction(ctx, txHash, opts)
}

func (m *MultiNodeWrappedClient) GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetBlocks(ctx, startSlot, endSlot)
}

func (m *MultiNodeWrappedClient) GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetBlocksWithLimit(ctx, startSlot, limit)
}

func (m *MultiNodeWrappedClient) GetBlock(ctx context.Context, slot uint64) (*rpc.GetBlockResult, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetBlock(ctx context.Context, slot uint64) (*rpc.GetBlockResult, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetBlock(ctx, slot)
}

func (m *MultiNodeWrappedClient) GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) {
r, err := m.multiNode.SelectRPC()
func (m *MultiClient) GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) {
r, err := m.getClient()
if err != nil {
return nil, err
}

return r.GetSignaturesForAddressWithOpts(ctx, addr, opts)
}

func (m *MultiNodeWrappedClient) Close() error {
return m.multiNode.Close()
}

0 comments on commit a27d397

Please sign in to comment.