From 75e06e64bcc7eef0932e92b04b593618f8b24020 Mon Sep 17 00:00:00 2001 From: Aaron Lu <50029043+aalu1418@users.noreply.github.com> Date: Thu, 5 Dec 2024 10:07:02 -0700 Subject: [PATCH 1/2] fix: add chainlink/deployment bump to updater workflow (#961) --- integration-tests/go.mod | 10 +++++----- integration-tests/go.sum | 16 ++++++++-------- scripts/update-e2e.sh | 4 +++- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 1c2332792..0c5efbd92 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -15,12 +15,12 @@ require ( github.com/pelletier/go-toml/v2 v2.2.3 github.com/rs/zerolog v1.33.0 github.com/smartcontractkit/chainlink-common v0.3.1-0.20241127162636-07aa781ee1f4 - github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241127210503-88cca3779525 - github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 + github.com/smartcontractkit/chainlink-solana v1.1.1-0.20241204153209-c3a71b0eef99 + github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 - github.com/smartcontractkit/chainlink/deployment v0.0.0-20241127192805-54ea74a13bfe - github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241204033247-732cc15aa87d - github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241204033247-732cc15aa87d + github.com/smartcontractkit/chainlink/deployment v0.0.0-20241205144849-138d4c51ad0d + github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241205144849-138d4c51ad0d + github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241205144849-138d4c51ad0d github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 github.com/stretchr/testify v1.9.0 github.com/testcontainers/testcontainers-go v0.34.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 59b3a9d3f..2dda62636 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1429,20 +1429,20 @@ github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2 h1:onBe3DqNrbtO github.com/smartcontractkit/chainlink-protos/orchestrator v0.3.2/go.mod h1:m/A3lqD7ms/RsQ9BT5P2uceYY0QX5mIt4KQxT2G6qEo= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8 h1:tNS7U9lrxkFvEuyxQv11HHOiV9LPDGC9wYEy+yM/Jv4= github.com/smartcontractkit/chainlink-starknet/relayer v0.1.1-0.20241202202529-2033490e77b8/go.mod h1:EBrEgcdIbwepqguClkv8Ohy7CbyWSJaE4EC9aBJlQK0= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17 h1:Fw2F8fKa5QdOUzLAj6Y/EB6XFC0QtK2pw5bqQSatL4A= -github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.17/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo= +github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg= github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9 h1:yB1x5UXvpZNka+5h57yo1/GrKfXKCqMzChCISpldZx4= github.com/smartcontractkit/chainlink-testing-framework/seth v1.50.9/go.mod h1:lJk0atEJ5Zyo3Tqrmf1Pl9jUEe79EgDb9bD3K5OTUBI= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2 h1:7bCdbTUWzyczQg+kwHCxlx6y07zE8HNB8+ntTne6qd8= github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.2/go.mod h1:MltlNu3jcXm/DyLN98I5TFNtu/o1NNAcaPAFKMXWk70= -github.com/smartcontractkit/chainlink/deployment v0.0.0-20241127192805-54ea74a13bfe h1:jUS49b8OODR6552wqvzNBMXHwgXV7iPZmz9lmESTsto= -github.com/smartcontractkit/chainlink/deployment v0.0.0-20241127192805-54ea74a13bfe/go.mod h1:ueUOL11tGBu1TTonZcIeD6/3av2iZE5AydxtclG8Dvo= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241204033247-732cc15aa87d h1:vV41ofCA5TGaHpoD2UHiN/VAR8xRqycWw4Fy75pXQj8= -github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241204033247-732cc15aa87d/go.mod h1:xCJuze3GgG6Ec/gLMAS/47FC/SzEa/Y+YiD5g4wvYTM= -github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241204033247-732cc15aa87d h1:W5f72PgRWg1ChYQBcwBZosrypWSwx7ShQNx3TKi7rwI= -github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241204033247-732cc15aa87d/go.mod h1:ofC2S3XuOMdqEew73eCNmV7jgWxayBayuEOLELR1CBM= +github.com/smartcontractkit/chainlink/deployment v0.0.0-20241205144849-138d4c51ad0d h1:nxjwsxk3qZOEFuoYJN9a61xBvwkFZLNMv24Z9QjYlnE= +github.com/smartcontractkit/chainlink/deployment v0.0.0-20241205144849-138d4c51ad0d/go.mod h1:jz4/Ko0lL7fhiuiBsVB53MNX2lEWK0VRfsxz232XRGA= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241205144849-138d4c51ad0d h1:Sl3/QHSA91H9nSaAVo9biKRpqIfWTKcGAKbCoWO6jr8= +github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20241205144849-138d4c51ad0d/go.mod h1:iRiKHT+MfvjrIuJuO/cGuWBxULctmlz2DFD3KDDU7oI= +github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241205144849-138d4c51ad0d h1:YSHlmOAuZvaBmjhENcLuyaDRy6+CcVqvsy6bF30Ovxw= +github.com/smartcontractkit/chainlink/v2 v2.14.0-mercury-20240807.0.20241205144849-138d4c51ad0d/go.mod h1:r2inuDnmNVZzUD/AsqgBs9exi9mIYwg8BgAnT+PyXU4= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7/go.mod h1:FX7/bVdoep147QQhsOPkYsPEXhGZjeYx6lBSaSXtZOA= github.com/smartcontractkit/libocr v0.0.0-20241007185508-adbe57025f12 h1:NzZGjaqez21I3DU7objl3xExTH4fxYvzTqar8DC6360= diff --git a/scripts/update-e2e.sh b/scripts/update-e2e.sh index 33198d5df..c1c4186fe 100755 --- a/scripts/update-e2e.sh +++ b/scripts/update-e2e.sh @@ -6,7 +6,9 @@ SHA=$(curl https://api.github.com/repos/smartcontractkit/chainlink/commits/devel echo "Chainlink Develop Commit: $SHA" # update dependencies +export GOPRIVATE=github.com/smartcontractkit/chainlink go get github.com/smartcontractkit/chainlink/integration-tests@$SHA -go mod tidy || echo -e "------\nInitial go mod tidy failed - will update chainlink dep and try tidy again\n------" +go mod tidy || echo -e "------\nInitial go mod tidy failed - will update chainlink + deployment dep and try tidy again\n------" go get github.com/smartcontractkit/chainlink/v2@$SHA +go get github.com/smartcontractkit/chainlink/deployment@$SHA go mod tidy From f7ecca855f8656712b779b37768950cc6b454db4 Mon Sep 17 00:00:00 2001 From: Dylan Tinianov Date: Thu, 5 Dec 2024 13:11:25 -0500 Subject: [PATCH 2/2] Update Solana Client for LogPoller (#933) * Add required methods * Add GetBlocks * Add GetBlocks method --- pkg/solana/client/client.go | 53 +++++++ pkg/solana/client/client_test.go | 46 ++++++ pkg/solana/client/mocks/reader_writer.go | 180 +++++++++++++++++++++++ 3 files changed, 279 insertions(+) diff --git a/pkg/solana/client/client.go b/pkg/solana/client/client.go index f9f6715b0..a015fdc1f 100644 --- a/pkg/solana/client/client.go +++ b/pkg/solana/client/client.go @@ -36,8 +36,11 @@ type Reader interface { ChainID(ctx context.Context) (mn.StringID, error) GetFeeForMessage(ctx context.Context, msg string) (uint64, error) GetLatestBlock(ctx context.Context) (*rpc.GetBlockResult, error) + GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) + GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error) GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error) GetBlock(ctx context.Context, slot uint64) (*rpc.GetBlockResult, error) + GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) } // AccountReader is an interface that allows users to pass either the solana rpc client or the relay client @@ -121,6 +124,43 @@ func (c *Client) SlotHeightWithCommitment(ctx context.Context, commitment rpc.Co return v.(uint64), err } +func (c *Client) GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) { + done := c.latency("signatures_for_address") + defer done() + + ctx, cancel := context.WithTimeout(ctx, c.contextDuration) + defer cancel() + if opts == nil { + opts = &rpc.GetSignaturesForAddressOpts{} + } + if opts.Commitment == "" { + opts.Commitment = c.commitment + } + return c.rpc.GetSignaturesForAddressWithOpts(ctx, addr, opts) +} + +func (c *Client) GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) { + done := c.latency("transaction") + defer done() + + ctx, cancel := context.WithTimeout(ctx, c.contextDuration) + defer cancel() + + if opts == nil { + opts = &rpc.GetTransactionOpts{ + Encoding: solana.EncodingBase64, + } + } + if opts.Commitment == "" { + opts.Commitment = c.commitment + } + + v, err, _ := c.requestGroup.Do("GetTransaction", func() (interface{}, error) { + return c.rpc.GetTransaction(ctx, txHash, opts) + }) + return v.(*rpc.GetTransactionResult), err +} + func (c *Client) GetAccountInfoWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetAccountInfoOpts) (*rpc.GetAccountInfoResult, error) { done := c.latency("account_info") defer done() @@ -131,6 +171,19 @@ func (c *Client) GetAccountInfoWithOpts(ctx context.Context, addr solana.PublicK return c.rpc.GetAccountInfoWithOpts(ctx, addr, opts) } +func (c *Client) GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (out rpc.BlocksResult, err error) { + done := c.latency("blocks") + defer done() + + ctx, cancel := context.WithTimeout(ctx, c.contextDuration) + defer cancel() + + v, err, _ := c.requestGroup.Do("GetBlocks", func() (interface{}, error) { + return c.rpc.GetBlocks(ctx, startSlot, endSlot, c.commitment) + }) + return v.(rpc.BlocksResult), err +} + func (c *Client) LatestBlockhash(ctx context.Context) (*rpc.GetLatestBlockhashResult, error) { done := c.latency("latest_blockhash") defer done() diff --git a/pkg/solana/client/client_test.go b/pkg/solana/client/client_test.go index ceb94035e..20b67ac8d 100644 --- a/pkg/solana/client/client_test.go +++ b/pkg/solana/client/client_test.go @@ -242,6 +242,52 @@ func TestClient_Writer_Integration(t *testing.T) { assert.Nil(t, statuses[0].Err) assert.NotNil(t, statuses[1].Err) + + getTxResult, err := c.GetTransaction(ctx, sigSuccess, nil) + assert.NoError(t, err) + assert.NotNil(t, getTxResult) + + sigs, err := c.GetSignaturesForAddressWithOpts(ctx, pubKey, nil) + assert.NoError(t, err) + requiredSigs := map[solana.Signature]bool{ + sigSuccess: false, + sigFail: false, + } + for _, sig := range sigs { + if _, required := requiredSigs[sig.Signature]; required { + requiredSigs[sig.Signature] = true + } + } + require.True(t, requiredSigs[sigSuccess] && requiredSigs[sigFail]) +} + +func TestClient_GetBlocks(t *testing.T) { + url := SetupLocalSolNode(t) + privKey, err := solana.NewRandomPrivateKey() + require.NoError(t, err) + pubKey := privKey.PublicKey() + FundTestAccounts(t, []solana.PublicKey{pubKey}, url) + + requestTimeout := 5 * time.Second + lggr := logger.Test(t) + cfg := config.NewDefault() + + ctx := tests.Context(t) + c, err := NewClient(url, cfg, requestTimeout, lggr) + require.NoError(t, err) + + // Verify we can retrieve blocks + startSlot := uint64(1) + endSlot := uint64(6) + require.Eventually(t, + func() bool { + blocks, err := c.GetBlocks(ctx, startSlot, &endSlot) + if err != nil { + return false + } + return len(blocks) == 5 + }, + requestTimeout, 500*time.Millisecond) } func TestClient_SendTxDuplicates_Integration(t *testing.T) { diff --git a/pkg/solana/client/mocks/reader_writer.go b/pkg/solana/client/mocks/reader_writer.go index 86285fdf5..c64a4a9ad 100644 --- a/pkg/solana/client/mocks/reader_writer.go +++ b/pkg/solana/client/mocks/reader_writer.go @@ -257,6 +257,66 @@ func (_c *ReaderWriter_GetBlock_Call) RunAndReturn(run func(context.Context, uin return _c } +// GetBlocks provides a mock function with given fields: ctx, startSlot, endSlot +func (_m *ReaderWriter) GetBlocks(ctx context.Context, startSlot uint64, endSlot *uint64) (rpc.BlocksResult, error) { + ret := _m.Called(ctx, startSlot, endSlot) + + if len(ret) == 0 { + panic("no return value specified for GetBlocks") + } + + var r0 rpc.BlocksResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) (rpc.BlocksResult, error)); ok { + return rf(ctx, startSlot, endSlot) + } + if rf, ok := ret.Get(0).(func(context.Context, uint64, *uint64) rpc.BlocksResult); ok { + r0 = rf(ctx, startSlot, endSlot) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(rpc.BlocksResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, uint64, *uint64) error); ok { + r1 = rf(ctx, startSlot, endSlot) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReaderWriter_GetBlocks_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetBlocks' +type ReaderWriter_GetBlocks_Call struct { + *mock.Call +} + +// GetBlocks is a helper method to define mock.On call +// - ctx context.Context +// - startSlot uint64 +// - endSlot *uint64 +func (_e *ReaderWriter_Expecter) GetBlocks(ctx interface{}, startSlot interface{}, endSlot interface{}) *ReaderWriter_GetBlocks_Call { + return &ReaderWriter_GetBlocks_Call{Call: _e.mock.On("GetBlocks", ctx, startSlot, endSlot)} +} + +func (_c *ReaderWriter_GetBlocks_Call) Run(run func(ctx context.Context, startSlot uint64, endSlot *uint64)) *ReaderWriter_GetBlocks_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(uint64), args[2].(*uint64)) + }) + return _c +} + +func (_c *ReaderWriter_GetBlocks_Call) Return(_a0 rpc.BlocksResult, _a1 error) *ReaderWriter_GetBlocks_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReaderWriter_GetBlocks_Call) RunAndReturn(run func(context.Context, uint64, *uint64) (rpc.BlocksResult, error)) *ReaderWriter_GetBlocks_Call { + _c.Call.Return(run) + return _c +} + // GetBlocksWithLimit provides a mock function with given fields: ctx, startSlot, limit func (_m *ReaderWriter) GetBlocksWithLimit(ctx context.Context, startSlot uint64, limit uint64) (*rpc.BlocksResult, error) { ret := _m.Called(ctx, startSlot, limit) @@ -432,6 +492,126 @@ func (_c *ReaderWriter_GetLatestBlock_Call) RunAndReturn(run func(context.Contex return _c } +// GetSignaturesForAddressWithOpts provides a mock function with given fields: ctx, addr, opts +func (_m *ReaderWriter) GetSignaturesForAddressWithOpts(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error) { + ret := _m.Called(ctx, addr, opts) + + if len(ret) == 0 { + panic("no return value specified for GetSignaturesForAddressWithOpts") + } + + var r0 []*rpc.TransactionSignature + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error)); ok { + return rf(ctx, addr, opts) + } + if rf, ok := ret.Get(0).(func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) []*rpc.TransactionSignature); ok { + r0 = rf(ctx, addr, opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]*rpc.TransactionSignature) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) error); ok { + r1 = rf(ctx, addr, opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReaderWriter_GetSignaturesForAddressWithOpts_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetSignaturesForAddressWithOpts' +type ReaderWriter_GetSignaturesForAddressWithOpts_Call struct { + *mock.Call +} + +// GetSignaturesForAddressWithOpts is a helper method to define mock.On call +// - ctx context.Context +// - addr solana.PublicKey +// - opts *rpc.GetSignaturesForAddressOpts +func (_e *ReaderWriter_Expecter) GetSignaturesForAddressWithOpts(ctx interface{}, addr interface{}, opts interface{}) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + return &ReaderWriter_GetSignaturesForAddressWithOpts_Call{Call: _e.mock.On("GetSignaturesForAddressWithOpts", ctx, addr, opts)} +} + +func (_c *ReaderWriter_GetSignaturesForAddressWithOpts_Call) Run(run func(ctx context.Context, addr solana.PublicKey, opts *rpc.GetSignaturesForAddressOpts)) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(solana.PublicKey), args[2].(*rpc.GetSignaturesForAddressOpts)) + }) + return _c +} + +func (_c *ReaderWriter_GetSignaturesForAddressWithOpts_Call) Return(_a0 []*rpc.TransactionSignature, _a1 error) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReaderWriter_GetSignaturesForAddressWithOpts_Call) RunAndReturn(run func(context.Context, solana.PublicKey, *rpc.GetSignaturesForAddressOpts) ([]*rpc.TransactionSignature, error)) *ReaderWriter_GetSignaturesForAddressWithOpts_Call { + _c.Call.Return(run) + return _c +} + +// GetTransaction provides a mock function with given fields: ctx, txHash, opts +func (_m *ReaderWriter) GetTransaction(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error) { + ret := _m.Called(ctx, txHash, opts) + + if len(ret) == 0 { + panic("no return value specified for GetTransaction") + } + + var r0 *rpc.GetTransactionResult + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, solana.Signature, *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error)); ok { + return rf(ctx, txHash, opts) + } + if rf, ok := ret.Get(0).(func(context.Context, solana.Signature, *rpc.GetTransactionOpts) *rpc.GetTransactionResult); ok { + r0 = rf(ctx, txHash, opts) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*rpc.GetTransactionResult) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, solana.Signature, *rpc.GetTransactionOpts) error); ok { + r1 = rf(ctx, txHash, opts) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ReaderWriter_GetTransaction_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTransaction' +type ReaderWriter_GetTransaction_Call struct { + *mock.Call +} + +// GetTransaction is a helper method to define mock.On call +// - ctx context.Context +// - txHash solana.Signature +// - opts *rpc.GetTransactionOpts +func (_e *ReaderWriter_Expecter) GetTransaction(ctx interface{}, txHash interface{}, opts interface{}) *ReaderWriter_GetTransaction_Call { + return &ReaderWriter_GetTransaction_Call{Call: _e.mock.On("GetTransaction", ctx, txHash, opts)} +} + +func (_c *ReaderWriter_GetTransaction_Call) Run(run func(ctx context.Context, txHash solana.Signature, opts *rpc.GetTransactionOpts)) *ReaderWriter_GetTransaction_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(context.Context), args[1].(solana.Signature), args[2].(*rpc.GetTransactionOpts)) + }) + return _c +} + +func (_c *ReaderWriter_GetTransaction_Call) Return(_a0 *rpc.GetTransactionResult, _a1 error) *ReaderWriter_GetTransaction_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *ReaderWriter_GetTransaction_Call) RunAndReturn(run func(context.Context, solana.Signature, *rpc.GetTransactionOpts) (*rpc.GetTransactionResult, error)) *ReaderWriter_GetTransaction_Call { + _c.Call.Return(run) + return _c +} + // LatestBlockhash provides a mock function with given fields: ctx func (_m *ReaderWriter) LatestBlockhash(ctx context.Context) (*rpc.GetLatestBlockhashResult, error) { ret := _m.Called(ctx)