diff --git a/cmd/broadcaster-cli/helper/functions.go b/cmd/broadcaster-cli/helper/functions.go index 15636bf55..06aa29495 100644 --- a/cmd/broadcaster-cli/helper/functions.go +++ b/cmd/broadcaster-cli/helper/functions.go @@ -1,11 +1,9 @@ package helper import ( - "errors" "fmt" "github.com/lmittmann/tint" "log/slog" - "net/url" "os" "strconv" "strings" @@ -16,11 +14,7 @@ import ( ) func CreateClient(auth *broadcaster.Auth, arcServer string) (broadcaster.ArcClient, error) { - arcServerUrl, err := url.Parse(arcServer) - if err != nil { - return nil, errors.New("arcUrl is not a valid url") - } - return broadcaster.NewHTTPBroadcaster(arcServerUrl.String(), auth), nil + return broadcaster.NewHTTPBroadcaster(arcServer, auth) } func GetKeySetsKeyFile(keyFile string) (fundingKeySet *keyset.KeySet, receivingKeySet *keyset.KeySet, err error) { diff --git a/internal/broadcaster/api.go b/internal/broadcaster/api.go index 554262d2d..6c63139e5 100644 --- a/internal/broadcaster/api.go +++ b/internal/broadcaster/api.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "net/http" + "net/url" "github.com/bitcoin-sv/arc/pkg/api" "github.com/bitcoin-sv/arc/pkg/metamorph/metamorph_api" @@ -15,8 +16,7 @@ import ( ) type APIBroadcaster struct { - arcServer string - auth *Auth + arcClient api.ClientInterface } type Auth struct { @@ -32,19 +32,16 @@ type Response struct { BlockHash string `json:"blockHash"` } -func NewHTTPBroadcaster(arcServer string, auth *Auth) *APIBroadcaster { - return &APIBroadcaster{ - arcServer: arcServer, - auth: auth, - } -} - -func (a *APIBroadcaster) BroadcastTransactions(ctx context.Context, txs []*bt.Tx, waitForStatus metamorph_api.Status, callbackURL string, callbackToken string, fullStatusUpdates bool, skipFeeValidation bool) ([]*metamorph_api.TransactionStatus, error) { - arcClient, err := a.getArcClient() +func NewHTTPBroadcaster(arcServer string, auth *Auth) (*APIBroadcaster, error) { + arcClient, err := getArcClient(arcServer, auth) if err != nil { return nil, err } + return &APIBroadcaster{arcClient: arcClient}, nil +} + +func (a *APIBroadcaster) BroadcastTransactions(ctx context.Context, txs []*bt.Tx, waitForStatus metamorph_api.Status, callbackURL string, callbackToken string, fullStatusUpdates bool, skipFeeValidation bool) ([]*metamorph_api.TransactionStatus, error) { waitFor := api.WaitForStatus(waitForStatus) params := &api.POSTTransactionsParams{ XWaitForStatus: &waitFor, @@ -70,7 +67,7 @@ func (a *APIBroadcaster) BroadcastTransactions(ctx context.Context, txs []*bt.Tx } var response *http.Response - response, err = arcClient.POSTTransactions(ctx, params, body) + response, err := a.arcClient.POSTTransactions(ctx, params, body) if err != nil { return nil, err } @@ -118,11 +115,6 @@ func (a *APIBroadcaster) BroadcastTransactions(ctx context.Context, txs []*bt.Tx } func (a *APIBroadcaster) BroadcastTransaction(ctx context.Context, tx *bt.Tx, waitFor metamorph_api.Status, callbackURL string) (*metamorph_api.TransactionStatus, error) { - arcClient, err := a.getArcClient() - if err != nil { - return nil, err - } - waitForStatus := api.WaitForStatus(waitFor) params := &api.POSTTransactionParams{ XWaitForStatus: &waitForStatus, @@ -136,60 +128,67 @@ func (a *APIBroadcaster) BroadcastTransaction(ctx context.Context, tx *bt.Tx, wa RawTx: hex.EncodeToString(tx.ExtendedBytes()), } - var response *api.POSTTransactionResponse - response, err = arcClient.POSTTransactionWithResponse(ctx, params, arcBody) + response, err := a.arcClient.POSTTransaction(ctx, params, arcBody) + if err != nil { + return nil, err + } + + var bodyBytes []byte + bodyBytes, err = io.ReadAll(response.Body) if err != nil { return nil, err } - if response.StatusCode() != http.StatusOK && response.StatusCode() != http.StatusCreated { - if response != nil && response.HTTPResponse != nil { + if response.StatusCode != http.StatusOK && response.StatusCode != http.StatusCreated { + if response.Body != nil { // read body into json map var body map[string]interface{} - err = json.Unmarshal(response.Body, &body) + err = json.Unmarshal(bodyBytes, &body) if err == nil { responseBody, ok := body["detail"].(string) if ok { return nil, errors.New(responseBody) } - return nil, fmt.Errorf("error: %s", string(response.Body)) + return nil, fmt.Errorf("error: %s", string(bodyBytes)) } } - return nil, errors.New("error: " + response.Status()) + return nil, errors.New("error: " + response.Status) } - bodyResponse := response.JSON200 - - blockHeight := *bodyResponse.BlockHeight - txStatus := bodyResponse.TxStatus - - res := &metamorph_api.TransactionStatus{ - Txid: bodyResponse.Txid, - Status: metamorph_api.Status(metamorph_api.Status_value[txStatus]), - BlockHeight: blockHeight, - BlockHash: *bodyResponse.BlockHash, + var bodyResponse Response + err = json.Unmarshal(bodyBytes, &bodyResponse) + if err != nil { + return nil, err } - if bodyResponse.ExtraInfo != nil { - res.RejectReason = *bodyResponse.ExtraInfo + res := &metamorph_api.TransactionStatus{ + Txid: bodyResponse.Txid, + Status: metamorph_api.Status(metamorph_api.Status_value[bodyResponse.TxStatus]), + BlockHeight: bodyResponse.BlockHeight, + BlockHash: bodyResponse.BlockHash, + RejectReason: bodyResponse.ExtraInfo, } return res, nil } -func (a *APIBroadcaster) getArcClient() (*api.ClientWithResponses, error) { +func getArcClient(arcServer string, auth *Auth) (*api.Client, error) { + _, err := url.Parse(arcServer) + if arcServer == "" || err != nil { + return nil, errors.New("arcUrl is not a valid url") + } opts := make([]api.ClientOption, 0) - if a.auth.Authorization != "" { + if auth != nil && auth.Authorization != "" { // custom provider opts = append(opts, api.WithRequestEditorFn(func(ctx context.Context, req *http.Request) error { - req.Header.Add("Authorization", a.auth.Authorization) + req.Header.Add("Authorization", auth.Authorization) return nil })) } - arcClient, err := api.NewClientWithResponses(a.arcServer, opts...) + arcClient, err := api.NewClient(arcServer, opts...) if err != nil { return nil, err } diff --git a/internal/broadcaster/api_test.go b/internal/broadcaster/api_test.go new file mode 100644 index 000000000..f21d0c18b --- /dev/null +++ b/internal/broadcaster/api_test.go @@ -0,0 +1,228 @@ +package broadcaster + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "io" + "net/http" + "testing" + + "github.com/bitcoin-sv/arc/pkg/api" + "github.com/bitcoin-sv/arc/pkg/api/mocks" + "github.com/bitcoin-sv/arc/pkg/metamorph/metamorph_api" + "github.com/libsv/go-bt/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestNewHTTPBroadcaster(t *testing.T) { + broadcaster, err := NewHTTPBroadcaster("arc:9090", nil) + require.NoError(t, err) + require.NotNil(t, broadcaster) +} + +func TestBroadcastTransactions(t *testing.T) { + testCases := []struct { + name string + httpStatusCode int + postTxResponses []*api.TransactionResponse + postTxError *api.ErrorFields + expectedTxStatuses []*metamorph_api.TransactionStatus + expectedError error + }{ + { + name: "error marlformed", + httpStatusCode: int(api.ErrStatusMalformed), + postTxResponses: nil, + postTxError: &api.ErrorFields{ + Detail: "Transaction is malformed and cannot be processed", + }, + expectedTxStatuses: nil, + expectedError: errors.New("failed to broadcast transactions: {\"detail\":\"Transaction is malformed and cannot be processed\",\"extraInfo\":null,\"instance\":null,\"status\":0,\"title\":\"\",\"txid\":null,\"type\":\"\"}"), + }, + { + name: "valid tx", + httpStatusCode: int(api.StatusOK), + postTxResponses: []*api.TransactionResponse{ + { + BlockHash: ptrTo("0000000000000aac89fbed163ed60061ba33bc0ab9de8e7fd8b34ad94c2414cd"), + BlockHeight: ptrTo(uint64(736228)), + TxStatus: "SEEN_ON_NETWORK", + Txid: "b68b064b336b9a4abdb173f3e32f27b38a222cb2102f51b8c92563e816b12b4a", + }, + }, + postTxError: nil, + expectedTxStatuses: []*metamorph_api.TransactionStatus{ + { + Txid: "b68b064b336b9a4abdb173f3e32f27b38a222cb2102f51b8c92563e816b12b4a", + Status: metamorph_api.Status_SEEN_ON_NETWORK, + BlockHeight: 736228, + BlockHash: "0000000000000aac89fbed163ed60061ba33bc0ab9de8e7fd8b34ad94c2414cd", + RejectReason: "", + }, + }, + expectedError: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var body interface{} + + if tc.postTxError == nil { + body = tc.postTxResponses + } else { + body = tc.postTxError + } + + bodyBytes, err := json.Marshal(body) + require.NoError(t, err) + + response := &http.Response{ + StatusCode: tc.httpStatusCode, + Body: io.NopCloser(bytes.NewReader(bodyBytes)), + } + + arcClientMock := &mocks.ClientInterfaceMock{ + POSTTransactionsFunc: func(ctx context.Context, params *api.POSTTransactionsParams, body []api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + return response, nil + }, + } + + broadcaster := &APIBroadcaster{ + arcClient: arcClientMock, + } + + // random valid transaction + tx, err := bt.NewTxFromString("020000000000000000ef010f117b3f9ea4955d5c592c61838bea10096fc88ac1ad08561a9bcabd715a088200000000494830450221008fd0e0330470ac730b9f6b9baf1791b76859cbc327e2e241f3ebeb96561a719602201e73532eb1312a00833af276d636254b8aa3ecbb445324fb4c481f2a493821fb41feffffff00f2052a01000000232103b12bda06e5a3e439690bf3996f1d4b81289f4747068a5cbb12786df83ae14c18ac02a0860100000000001976a914b7b88045cc16f442a0c3dcb3dc31ecce8d156e7388ac605c042a010000001976a9147a904b8ae0c2f9d74448993029ad3c040ebdd69a88ac66000000") + require.NoError(t, err) + + status, err := broadcaster.BroadcastTransactions(context.Background(), []*bt.Tx{tx}, metamorph_api.Status_SEEN_ON_NETWORK, "", "", false, false) + + assert.Equal(t, tc.expectedTxStatuses, status) + assert.Equal(t, tc.expectedError, err) + }) + } +} + +func TestBroadcastTransaction(t *testing.T) { + testCases := []struct { + name string + httpStatusCode int + postTxResponse *api.TransactionResponse + postTxError *api.ErrorFields + expectedTxStatus *metamorph_api.TransactionStatus + expectedError error + }{ + { + name: "error marlformed", + httpStatusCode: int(api.ErrStatusMalformed), + postTxResponse: nil, + postTxError: &api.ErrorFields{ + Detail: "Transaction is malformed and cannot be processed", + }, + expectedTxStatus: nil, + expectedError: errors.New("Transaction is malformed and cannot be processed"), + }, + { + name: "valid tx", + httpStatusCode: int(api.StatusOK), + postTxResponse: &api.TransactionResponse{ + BlockHash: ptrTo("0000000000000aac89fbed163ed60061ba33bc0ab9de8e7fd8b34ad94c2414cd"), + BlockHeight: ptrTo(uint64(736228)), + TxStatus: "SEEN_ON_NETWORK", + Txid: "b68b064b336b9a4abdb173f3e32f27b38a222cb2102f51b8c92563e816b12b4a", + }, + postTxError: nil, + expectedTxStatus: &metamorph_api.TransactionStatus{ + Txid: "b68b064b336b9a4abdb173f3e32f27b38a222cb2102f51b8c92563e816b12b4a", + Status: metamorph_api.Status_SEEN_ON_NETWORK, + BlockHeight: 736228, + BlockHash: "0000000000000aac89fbed163ed60061ba33bc0ab9de8e7fd8b34ad94c2414cd", + RejectReason: "", + }, + expectedError: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + var body interface{} + + if tc.postTxError == nil { + body = tc.postTxResponse + } else { + body = tc.postTxError + } + + bodyBytes, err := json.Marshal(body) + require.NoError(t, err) + + response := &http.Response{ + StatusCode: tc.httpStatusCode, + Body: io.NopCloser(bytes.NewReader(bodyBytes)), + } + + arcClientMock := &mocks.ClientInterfaceMock{ + POSTTransactionFunc: func(ctx context.Context, params *api.POSTTransactionParams, body api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + return response, nil + }, + } + + broadcaster := &APIBroadcaster{ + arcClient: arcClientMock, + } + + // random valid transaction + tx, err := bt.NewTxFromString("020000000000000000ef010f117b3f9ea4955d5c592c61838bea10096fc88ac1ad08561a9bcabd715a088200000000494830450221008fd0e0330470ac730b9f6b9baf1791b76859cbc327e2e241f3ebeb96561a719602201e73532eb1312a00833af276d636254b8aa3ecbb445324fb4c481f2a493821fb41feffffff00f2052a01000000232103b12bda06e5a3e439690bf3996f1d4b81289f4747068a5cbb12786df83ae14c18ac02a0860100000000001976a914b7b88045cc16f442a0c3dcb3dc31ecce8d156e7388ac605c042a010000001976a9147a904b8ae0c2f9d74448993029ad3c040ebdd69a88ac66000000") + require.NoError(t, err) + + status, err := broadcaster.BroadcastTransaction(context.Background(), tx, metamorph_api.Status_SEEN_ON_NETWORK, "") + + assert.Equal(t, tc.expectedTxStatus, status) + assert.Equal(t, tc.expectedError, err) + }) + } +} + +func TestGetArcClient(t *testing.T) { + testCases := []struct { + name string + url string + expectedError error + }{ + { + name: "empty url", + url: "", + expectedError: errors.New("arcUrl is not a valid url"), + }, + { + name: "invalid url", + url: ":/invalid_url", + expectedError: errors.New("arcUrl is not a valid url"), + }, + { + name: "valid url", + url: "http://localhost:9090", + expectedError: nil, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + arcClient, err := getArcClient(tc.url, nil) + + assert.Equal(t, tc.expectedError, err) + if tc.expectedError == nil { + assert.NotNil(t, arcClient) + } + }) + } +} + +// PtrTo returns a pointer to the given value. +func ptrTo[T any](v T) *T { + return &v +} diff --git a/internal/metamorph/peer_handler_test.go b/internal/metamorph/peer_handler_test.go new file mode 100644 index 000000000..e4b93e0d3 --- /dev/null +++ b/internal/metamorph/peer_handler_test.go @@ -0,0 +1,151 @@ +package metamorph_test + +import ( + "context" + "errors" + "testing" + "time" + + "github.com/bitcoin-sv/arc/internal/metamorph" + "github.com/bitcoin-sv/arc/internal/metamorph/mocks" + "github.com/bitcoin-sv/arc/internal/metamorph/store" + "github.com/bitcoin-sv/arc/pkg/metamorph/metamorph_api" + "github.com/libsv/go-p2p" + "github.com/libsv/go-p2p/chaincfg/chainhash" + "github.com/libsv/go-p2p/wire" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestPeerHandler(t *testing.T) { + messageCh := make(chan *metamorph.PeerTxMessage) + mtmStore := &mocks.MetamorphStoreMock{ + GetFunc: func(ctx context.Context, key []byte) (*store.StoreData, error) { + return &store.StoreData{ + RawTx: []byte("1234"), + }, nil + }, + } + + peerHandler := metamorph.NewPeerHandler(mtmStore, messageCh) + require.NotNil(t, peerHandler) + + peer, err := p2p.NewPeerMock("mock_peer", nil, wire.MainNet) + require.NoError(t, err) + + t.Run("HandleTransactionSent", func(t *testing.T) { + msgTx := wire.NewMsgTx(70001) + hash := msgTx.TxHash() + + expectedMsg := &metamorph.PeerTxMessage{ + Hash: &hash, + Status: metamorph_api.Status_SENT_TO_NETWORK, + Peer: "mock_peer", + } + + go func() { + _ = peerHandler.HandleTransactionSent(msgTx, peer) + }() + + select { + case msg := <-messageCh: + assert.Equal(t, expectedMsg, msg) + case <-time.After(time.Second): + t.Fatal("test timed out or error while executing goroutine") + } + }) + + t.Run("HandleTransactionAnnouncement", func(t *testing.T) { + hash, err := chainhash.NewHashFromStr("1234") + require.NoError(t, err) + + msgInv := wire.NewInvVect(wire.InvTypeBlock, hash) + require.NoError(t, err) + + expectedMsg := &metamorph.PeerTxMessage{ + Hash: &msgInv.Hash, + Status: metamorph_api.Status_SEEN_ON_NETWORK, + Peer: "mock_peer", + } + + go func() { + _ = peerHandler.HandleTransactionAnnouncement(msgInv, peer) + }() + + select { + case msg := <-messageCh: + assert.Equal(t, expectedMsg, msg) + case <-time.After(time.Second): + t.Fatal("test timed out or error while executing goroutine") + } + }) + + t.Run("HandleTransactionRejection", func(t *testing.T) { + msgReject := wire.NewMsgReject("command", wire.RejectMalformed, "malformed") + + expectedMsg := &metamorph.PeerTxMessage{ + Hash: &msgReject.Hash, + Status: metamorph_api.Status_REJECTED, + Peer: "mock_peer", + Err: errors.New("transaction rejected by peer mock_peer: malformed"), + } + + go func() { + _ = peerHandler.HandleTransactionRejection(msgReject, peer) + }() + + select { + case msg := <-messageCh: + assert.Equal(t, expectedMsg, msg) + case <-time.After(time.Second): + t.Fatal("test timed out or error while executing goroutine") + } + }) + + t.Run("HandleTransactionGet", func(t *testing.T) { + hash, err := chainhash.NewHashFromStr("1234") + require.NoError(t, err) + + msgInv := wire.NewInvVect(wire.InvTypeBlock, hash) + require.NoError(t, err) + + expectedMsg := &metamorph.PeerTxMessage{ + Hash: &msgInv.Hash, + Status: metamorph_api.Status_REQUESTED_BY_NETWORK, + Peer: "mock_peer", + } + + go func() { + _, _ = peerHandler.HandleTransactionGet(msgInv, peer) + }() + + select { + case msg := <-messageCh: + assert.Equal(t, expectedMsg, msg) + case <-time.After(time.Second): + t.Fatal("test timed out or error while executing goroutine") + } + }) + + t.Run("HandleTransaction", func(t *testing.T) { + msgTx := wire.NewMsgTx(70001) + hash := msgTx.TxHash() + + expectedMsg := &metamorph.PeerTxMessage{ + Hash: &hash, + Status: metamorph_api.Status_SEEN_ON_NETWORK, + Peer: "mock_peer", + } + + go func() { + _ = peerHandler.HandleTransaction(msgTx, peer) + }() + + select { + case msg := <-messageCh: + assert.Equal(t, expectedMsg, msg) + case <-time.After(time.Second): + t.Fatal("test timed out or error while executing goroutine") + } + }) +} diff --git a/pkg/api/arc_test.go b/pkg/api/arc_test.go new file mode 100644 index 000000000..67c4041c5 --- /dev/null +++ b/pkg/api/arc_test.go @@ -0,0 +1,3 @@ +package api + +//go:generate moq -pkg mocks -out ./mocks/client_interface_mock.go . ClientInterface diff --git a/pkg/api/handler/helpers_test.go b/pkg/api/handler/helpers_test.go index c2181dbc5..20fe606f8 100644 --- a/pkg/api/handler/helpers_test.go +++ b/pkg/api/handler/helpers_test.go @@ -6,7 +6,10 @@ import ( "strings" "testing" + "github.com/bitcoin-sv/arc/internal/beef" + "github.com/bitcoin-sv/arc/pkg/blocktx" "github.com/labstack/echo/v4" + "github.com/stretchr/testify/assert" ) func TestCheckSwagger(t *testing.T) { @@ -26,7 +29,47 @@ func TestCheckSwagger(t *testing.T) { req := httptest.NewRequest(http.MethodPost, tc.path, strings.NewReader("")) req.Header.Set(echo.HeaderContentType, echo.MIMEApplicationJSON) - CheckSwagger(e) + swagger := CheckSwagger(e) + assert.NotNil(t, swagger) + }) + } +} + +func TestConvertMerkleRootsRequest(t *testing.T) { + testCases := []struct { + name string + request []beef.MerkleRootVerificationRequest + expectedRequest []blocktx.MerkleRootVerificationRequest + }{ + { + name: "", + request: []beef.MerkleRootVerificationRequest{ + { + MerkleRoot: "1234", + BlockHeight: 818000, + }, + { + MerkleRoot: "5678", + BlockHeight: 818001, + }, + }, + expectedRequest: []blocktx.MerkleRootVerificationRequest{ + { + MerkleRoot: "1234", + BlockHeight: 818000, + }, + { + MerkleRoot: "5678", + BlockHeight: 818001, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + request := convertMerkleRootsRequest(tc.request) + assert.Equal(t, tc.expectedRequest, request) }) } } diff --git a/pkg/api/mocks/client_interface_mock.go b/pkg/api/mocks/client_interface_mock.go new file mode 100644 index 000000000..eae273579 --- /dev/null +++ b/pkg/api/mocks/client_interface_mock.go @@ -0,0 +1,574 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package mocks + +import ( + "context" + "github.com/bitcoin-sv/arc/pkg/api" + "io" + "net/http" + "sync" +) + +// Ensure, that ClientInterfaceMock does implement api.ClientInterface. +// If this is not the case, regenerate this file with moq. +var _ api.ClientInterface = &ClientInterfaceMock{} + +// ClientInterfaceMock is a mock implementation of api.ClientInterface. +// +// func TestSomethingThatUsesClientInterface(t *testing.T) { +// +// // make and configure a mocked api.ClientInterface +// mockedClientInterface := &ClientInterfaceMock{ +// GETHealthFunc: func(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the GETHealth method") +// }, +// GETPolicyFunc: func(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the GETPolicy method") +// }, +// GETTransactionStatusFunc: func(ctx context.Context, txid string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the GETTransactionStatus method") +// }, +// POSTTransactionFunc: func(ctx context.Context, params *api.POSTTransactionParams, body api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the POSTTransaction method") +// }, +// POSTTransactionWithBodyFunc: func(ctx context.Context, params *api.POSTTransactionParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the POSTTransactionWithBody method") +// }, +// POSTTransactionWithTextBodyFunc: func(ctx context.Context, params *api.POSTTransactionParams, body string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the POSTTransactionWithTextBody method") +// }, +// POSTTransactionsFunc: func(ctx context.Context, params *api.POSTTransactionsParams, body []api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the POSTTransactions method") +// }, +// POSTTransactionsWithBodyFunc: func(ctx context.Context, params *api.POSTTransactionsParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the POSTTransactionsWithBody method") +// }, +// POSTTransactionsWithTextBodyFunc: func(ctx context.Context, params *api.POSTTransactionsParams, body string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { +// panic("mock out the POSTTransactionsWithTextBody method") +// }, +// } +// +// // use mockedClientInterface in code that requires api.ClientInterface +// // and then make assertions. +// +// } +type ClientInterfaceMock struct { + // GETHealthFunc mocks the GETHealth method. + GETHealthFunc func(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // GETPolicyFunc mocks the GETPolicy method. + GETPolicyFunc func(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // GETTransactionStatusFunc mocks the GETTransactionStatus method. + GETTransactionStatusFunc func(ctx context.Context, txid string, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // POSTTransactionFunc mocks the POSTTransaction method. + POSTTransactionFunc func(ctx context.Context, params *api.POSTTransactionParams, body api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // POSTTransactionWithBodyFunc mocks the POSTTransactionWithBody method. + POSTTransactionWithBodyFunc func(ctx context.Context, params *api.POSTTransactionParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // POSTTransactionWithTextBodyFunc mocks the POSTTransactionWithTextBody method. + POSTTransactionWithTextBodyFunc func(ctx context.Context, params *api.POSTTransactionParams, body string, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // POSTTransactionsFunc mocks the POSTTransactions method. + POSTTransactionsFunc func(ctx context.Context, params *api.POSTTransactionsParams, body []api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // POSTTransactionsWithBodyFunc mocks the POSTTransactionsWithBody method. + POSTTransactionsWithBodyFunc func(ctx context.Context, params *api.POSTTransactionsParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // POSTTransactionsWithTextBodyFunc mocks the POSTTransactionsWithTextBody method. + POSTTransactionsWithTextBodyFunc func(ctx context.Context, params *api.POSTTransactionsParams, body string, reqEditors ...api.RequestEditorFn) (*http.Response, error) + + // calls tracks calls to the methods. + calls struct { + // GETHealth holds details about calls to the GETHealth method. + GETHealth []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // GETPolicy holds details about calls to the GETPolicy method. + GETPolicy []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // GETTransactionStatus holds details about calls to the GETTransactionStatus method. + GETTransactionStatus []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Txid is the txid argument value. + Txid string + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // POSTTransaction holds details about calls to the POSTTransaction method. + POSTTransaction []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *api.POSTTransactionParams + // Body is the body argument value. + Body api.TransactionRequest + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // POSTTransactionWithBody holds details about calls to the POSTTransactionWithBody method. + POSTTransactionWithBody []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *api.POSTTransactionParams + // ContentType is the contentType argument value. + ContentType string + // Body is the body argument value. + Body io.Reader + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // POSTTransactionWithTextBody holds details about calls to the POSTTransactionWithTextBody method. + POSTTransactionWithTextBody []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *api.POSTTransactionParams + // Body is the body argument value. + Body string + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // POSTTransactions holds details about calls to the POSTTransactions method. + POSTTransactions []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *api.POSTTransactionsParams + // Body is the body argument value. + Body []api.TransactionRequest + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // POSTTransactionsWithBody holds details about calls to the POSTTransactionsWithBody method. + POSTTransactionsWithBody []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *api.POSTTransactionsParams + // ContentType is the contentType argument value. + ContentType string + // Body is the body argument value. + Body io.Reader + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + // POSTTransactionsWithTextBody holds details about calls to the POSTTransactionsWithTextBody method. + POSTTransactionsWithTextBody []struct { + // Ctx is the ctx argument value. + Ctx context.Context + // Params is the params argument value. + Params *api.POSTTransactionsParams + // Body is the body argument value. + Body string + // ReqEditors is the reqEditors argument value. + ReqEditors []api.RequestEditorFn + } + } + lockGETHealth sync.RWMutex + lockGETPolicy sync.RWMutex + lockGETTransactionStatus sync.RWMutex + lockPOSTTransaction sync.RWMutex + lockPOSTTransactionWithBody sync.RWMutex + lockPOSTTransactionWithTextBody sync.RWMutex + lockPOSTTransactions sync.RWMutex + lockPOSTTransactionsWithBody sync.RWMutex + lockPOSTTransactionsWithTextBody sync.RWMutex +} + +// GETHealth calls GETHealthFunc. +func (mock *ClientInterfaceMock) GETHealth(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.GETHealthFunc == nil { + panic("ClientInterfaceMock.GETHealthFunc: method is nil but ClientInterface.GETHealth was just called") + } + callInfo := struct { + Ctx context.Context + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + ReqEditors: reqEditors, + } + mock.lockGETHealth.Lock() + mock.calls.GETHealth = append(mock.calls.GETHealth, callInfo) + mock.lockGETHealth.Unlock() + return mock.GETHealthFunc(ctx, reqEditors...) +} + +// GETHealthCalls gets all the calls that were made to GETHealth. +// Check the length with: +// +// len(mockedClientInterface.GETHealthCalls()) +func (mock *ClientInterfaceMock) GETHealthCalls() []struct { + Ctx context.Context + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + ReqEditors []api.RequestEditorFn + } + mock.lockGETHealth.RLock() + calls = mock.calls.GETHealth + mock.lockGETHealth.RUnlock() + return calls +} + +// GETPolicy calls GETPolicyFunc. +func (mock *ClientInterfaceMock) GETPolicy(ctx context.Context, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.GETPolicyFunc == nil { + panic("ClientInterfaceMock.GETPolicyFunc: method is nil but ClientInterface.GETPolicy was just called") + } + callInfo := struct { + Ctx context.Context + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + ReqEditors: reqEditors, + } + mock.lockGETPolicy.Lock() + mock.calls.GETPolicy = append(mock.calls.GETPolicy, callInfo) + mock.lockGETPolicy.Unlock() + return mock.GETPolicyFunc(ctx, reqEditors...) +} + +// GETPolicyCalls gets all the calls that were made to GETPolicy. +// Check the length with: +// +// len(mockedClientInterface.GETPolicyCalls()) +func (mock *ClientInterfaceMock) GETPolicyCalls() []struct { + Ctx context.Context + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + ReqEditors []api.RequestEditorFn + } + mock.lockGETPolicy.RLock() + calls = mock.calls.GETPolicy + mock.lockGETPolicy.RUnlock() + return calls +} + +// GETTransactionStatus calls GETTransactionStatusFunc. +func (mock *ClientInterfaceMock) GETTransactionStatus(ctx context.Context, txid string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.GETTransactionStatusFunc == nil { + panic("ClientInterfaceMock.GETTransactionStatusFunc: method is nil but ClientInterface.GETTransactionStatus was just called") + } + callInfo := struct { + Ctx context.Context + Txid string + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Txid: txid, + ReqEditors: reqEditors, + } + mock.lockGETTransactionStatus.Lock() + mock.calls.GETTransactionStatus = append(mock.calls.GETTransactionStatus, callInfo) + mock.lockGETTransactionStatus.Unlock() + return mock.GETTransactionStatusFunc(ctx, txid, reqEditors...) +} + +// GETTransactionStatusCalls gets all the calls that were made to GETTransactionStatus. +// Check the length with: +// +// len(mockedClientInterface.GETTransactionStatusCalls()) +func (mock *ClientInterfaceMock) GETTransactionStatusCalls() []struct { + Ctx context.Context + Txid string + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Txid string + ReqEditors []api.RequestEditorFn + } + mock.lockGETTransactionStatus.RLock() + calls = mock.calls.GETTransactionStatus + mock.lockGETTransactionStatus.RUnlock() + return calls +} + +// POSTTransaction calls POSTTransactionFunc. +func (mock *ClientInterfaceMock) POSTTransaction(ctx context.Context, params *api.POSTTransactionParams, body api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.POSTTransactionFunc == nil { + panic("ClientInterfaceMock.POSTTransactionFunc: method is nil but ClientInterface.POSTTransaction was just called") + } + callInfo := struct { + Ctx context.Context + Params *api.POSTTransactionParams + Body api.TransactionRequest + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Params: params, + Body: body, + ReqEditors: reqEditors, + } + mock.lockPOSTTransaction.Lock() + mock.calls.POSTTransaction = append(mock.calls.POSTTransaction, callInfo) + mock.lockPOSTTransaction.Unlock() + return mock.POSTTransactionFunc(ctx, params, body, reqEditors...) +} + +// POSTTransactionCalls gets all the calls that were made to POSTTransaction. +// Check the length with: +// +// len(mockedClientInterface.POSTTransactionCalls()) +func (mock *ClientInterfaceMock) POSTTransactionCalls() []struct { + Ctx context.Context + Params *api.POSTTransactionParams + Body api.TransactionRequest + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Params *api.POSTTransactionParams + Body api.TransactionRequest + ReqEditors []api.RequestEditorFn + } + mock.lockPOSTTransaction.RLock() + calls = mock.calls.POSTTransaction + mock.lockPOSTTransaction.RUnlock() + return calls +} + +// POSTTransactionWithBody calls POSTTransactionWithBodyFunc. +func (mock *ClientInterfaceMock) POSTTransactionWithBody(ctx context.Context, params *api.POSTTransactionParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.POSTTransactionWithBodyFunc == nil { + panic("ClientInterfaceMock.POSTTransactionWithBodyFunc: method is nil but ClientInterface.POSTTransactionWithBody was just called") + } + callInfo := struct { + Ctx context.Context + Params *api.POSTTransactionParams + ContentType string + Body io.Reader + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Params: params, + ContentType: contentType, + Body: body, + ReqEditors: reqEditors, + } + mock.lockPOSTTransactionWithBody.Lock() + mock.calls.POSTTransactionWithBody = append(mock.calls.POSTTransactionWithBody, callInfo) + mock.lockPOSTTransactionWithBody.Unlock() + return mock.POSTTransactionWithBodyFunc(ctx, params, contentType, body, reqEditors...) +} + +// POSTTransactionWithBodyCalls gets all the calls that were made to POSTTransactionWithBody. +// Check the length with: +// +// len(mockedClientInterface.POSTTransactionWithBodyCalls()) +func (mock *ClientInterfaceMock) POSTTransactionWithBodyCalls() []struct { + Ctx context.Context + Params *api.POSTTransactionParams + ContentType string + Body io.Reader + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Params *api.POSTTransactionParams + ContentType string + Body io.Reader + ReqEditors []api.RequestEditorFn + } + mock.lockPOSTTransactionWithBody.RLock() + calls = mock.calls.POSTTransactionWithBody + mock.lockPOSTTransactionWithBody.RUnlock() + return calls +} + +// POSTTransactionWithTextBody calls POSTTransactionWithTextBodyFunc. +func (mock *ClientInterfaceMock) POSTTransactionWithTextBody(ctx context.Context, params *api.POSTTransactionParams, body string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.POSTTransactionWithTextBodyFunc == nil { + panic("ClientInterfaceMock.POSTTransactionWithTextBodyFunc: method is nil but ClientInterface.POSTTransactionWithTextBody was just called") + } + callInfo := struct { + Ctx context.Context + Params *api.POSTTransactionParams + Body string + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Params: params, + Body: body, + ReqEditors: reqEditors, + } + mock.lockPOSTTransactionWithTextBody.Lock() + mock.calls.POSTTransactionWithTextBody = append(mock.calls.POSTTransactionWithTextBody, callInfo) + mock.lockPOSTTransactionWithTextBody.Unlock() + return mock.POSTTransactionWithTextBodyFunc(ctx, params, body, reqEditors...) +} + +// POSTTransactionWithTextBodyCalls gets all the calls that were made to POSTTransactionWithTextBody. +// Check the length with: +// +// len(mockedClientInterface.POSTTransactionWithTextBodyCalls()) +func (mock *ClientInterfaceMock) POSTTransactionWithTextBodyCalls() []struct { + Ctx context.Context + Params *api.POSTTransactionParams + Body string + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Params *api.POSTTransactionParams + Body string + ReqEditors []api.RequestEditorFn + } + mock.lockPOSTTransactionWithTextBody.RLock() + calls = mock.calls.POSTTransactionWithTextBody + mock.lockPOSTTransactionWithTextBody.RUnlock() + return calls +} + +// POSTTransactions calls POSTTransactionsFunc. +func (mock *ClientInterfaceMock) POSTTransactions(ctx context.Context, params *api.POSTTransactionsParams, body []api.TransactionRequest, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.POSTTransactionsFunc == nil { + panic("ClientInterfaceMock.POSTTransactionsFunc: method is nil but ClientInterface.POSTTransactions was just called") + } + callInfo := struct { + Ctx context.Context + Params *api.POSTTransactionsParams + Body []api.TransactionRequest + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Params: params, + Body: body, + ReqEditors: reqEditors, + } + mock.lockPOSTTransactions.Lock() + mock.calls.POSTTransactions = append(mock.calls.POSTTransactions, callInfo) + mock.lockPOSTTransactions.Unlock() + return mock.POSTTransactionsFunc(ctx, params, body, reqEditors...) +} + +// POSTTransactionsCalls gets all the calls that were made to POSTTransactions. +// Check the length with: +// +// len(mockedClientInterface.POSTTransactionsCalls()) +func (mock *ClientInterfaceMock) POSTTransactionsCalls() []struct { + Ctx context.Context + Params *api.POSTTransactionsParams + Body []api.TransactionRequest + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Params *api.POSTTransactionsParams + Body []api.TransactionRequest + ReqEditors []api.RequestEditorFn + } + mock.lockPOSTTransactions.RLock() + calls = mock.calls.POSTTransactions + mock.lockPOSTTransactions.RUnlock() + return calls +} + +// POSTTransactionsWithBody calls POSTTransactionsWithBodyFunc. +func (mock *ClientInterfaceMock) POSTTransactionsWithBody(ctx context.Context, params *api.POSTTransactionsParams, contentType string, body io.Reader, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.POSTTransactionsWithBodyFunc == nil { + panic("ClientInterfaceMock.POSTTransactionsWithBodyFunc: method is nil but ClientInterface.POSTTransactionsWithBody was just called") + } + callInfo := struct { + Ctx context.Context + Params *api.POSTTransactionsParams + ContentType string + Body io.Reader + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Params: params, + ContentType: contentType, + Body: body, + ReqEditors: reqEditors, + } + mock.lockPOSTTransactionsWithBody.Lock() + mock.calls.POSTTransactionsWithBody = append(mock.calls.POSTTransactionsWithBody, callInfo) + mock.lockPOSTTransactionsWithBody.Unlock() + return mock.POSTTransactionsWithBodyFunc(ctx, params, contentType, body, reqEditors...) +} + +// POSTTransactionsWithBodyCalls gets all the calls that were made to POSTTransactionsWithBody. +// Check the length with: +// +// len(mockedClientInterface.POSTTransactionsWithBodyCalls()) +func (mock *ClientInterfaceMock) POSTTransactionsWithBodyCalls() []struct { + Ctx context.Context + Params *api.POSTTransactionsParams + ContentType string + Body io.Reader + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Params *api.POSTTransactionsParams + ContentType string + Body io.Reader + ReqEditors []api.RequestEditorFn + } + mock.lockPOSTTransactionsWithBody.RLock() + calls = mock.calls.POSTTransactionsWithBody + mock.lockPOSTTransactionsWithBody.RUnlock() + return calls +} + +// POSTTransactionsWithTextBody calls POSTTransactionsWithTextBodyFunc. +func (mock *ClientInterfaceMock) POSTTransactionsWithTextBody(ctx context.Context, params *api.POSTTransactionsParams, body string, reqEditors ...api.RequestEditorFn) (*http.Response, error) { + if mock.POSTTransactionsWithTextBodyFunc == nil { + panic("ClientInterfaceMock.POSTTransactionsWithTextBodyFunc: method is nil but ClientInterface.POSTTransactionsWithTextBody was just called") + } + callInfo := struct { + Ctx context.Context + Params *api.POSTTransactionsParams + Body string + ReqEditors []api.RequestEditorFn + }{ + Ctx: ctx, + Params: params, + Body: body, + ReqEditors: reqEditors, + } + mock.lockPOSTTransactionsWithTextBody.Lock() + mock.calls.POSTTransactionsWithTextBody = append(mock.calls.POSTTransactionsWithTextBody, callInfo) + mock.lockPOSTTransactionsWithTextBody.Unlock() + return mock.POSTTransactionsWithTextBodyFunc(ctx, params, body, reqEditors...) +} + +// POSTTransactionsWithTextBodyCalls gets all the calls that were made to POSTTransactionsWithTextBody. +// Check the length with: +// +// len(mockedClientInterface.POSTTransactionsWithTextBodyCalls()) +func (mock *ClientInterfaceMock) POSTTransactionsWithTextBodyCalls() []struct { + Ctx context.Context + Params *api.POSTTransactionsParams + Body string + ReqEditors []api.RequestEditorFn +} { + var calls []struct { + Ctx context.Context + Params *api.POSTTransactionsParams + Body string + ReqEditors []api.RequestEditorFn + } + mock.lockPOSTTransactionsWithTextBody.RLock() + calls = mock.calls.POSTTransactionsWithTextBody + mock.lockPOSTTransactionsWithTextBody.RUnlock() + return calls +}