From e00b8e5ca587afa46bc955b539db4790e3e8e788 Mon Sep 17 00:00:00 2001 From: bmurphy333 Date: Thu, 7 Sep 2023 11:12:47 +1200 Subject: [PATCH 1/4] chore: added pagination to the account channels method --- client/accounts.go | 48 +++++++++++++++++--- client/accounts_test.go | 76 +++++++++++++++++++++++++++++--- client/jsonrpc/jsonrpc_client.go | 43 ++++++++++++++++++ 3 files changed, 156 insertions(+), 11 deletions(-) diff --git a/client/accounts.go b/client/accounts.go index 438e8cc55..116d5f0a2 100644 --- a/client/accounts.go +++ b/client/accounts.go @@ -1,11 +1,13 @@ package client import ( + "fmt" + "github.com/xyield/xrpl-go/model/client/account" ) type Account interface { - GetAccountChannels(req *account.AccountChannelsRequest) (*account.AccountChannelsResponse, XRPLResponse, error) + GetAccountChannels(req *account.AccountChannelsRequest) ([]account.AccountChannelsResponse, XRPLResponse, error) GetAccountInfo(req *account.AccountInfoRequest) (*account.AccountInfoResponse, XRPLResponse, error) } @@ -13,17 +15,51 @@ type accountImpl struct { client Client } -func (a *accountImpl) GetAccountChannels(req *account.AccountChannelsRequest) (*account.AccountChannelsResponse, XRPLResponse, error) { - res, err := a.client.SendRequest(req) +func (a *accountImpl) GetAccountChannels(req *account.AccountChannelsRequest) ([]account.AccountChannelsResponse, XRPLResponse, error) { + + err := req.Validate() if err != nil { return nil, nil, err } - var acr account.AccountChannelsResponse - err = res.GetResult(&acr) + + pages := []account.AccountChannelsResponse{} + xrplResult, err := GetPages(a, req, &pages) if err != nil { return nil, nil, err } - return &acr, res, nil + + return pages, xrplResult, nil +} + +// TODO: have a way for user to choose if they re-try with marker? That would require the 10 min rule being followed - trigger go routine to run and watch timer +// Call this method instead of SendRequest when response is paginated +func GetPages(a *accountImpl, req *account.AccountChannelsRequest, pages *[]account.AccountChannelsResponse) (XRPLResponse, error) { + + // get first page of results + result, err := a.client.SendRequest(req) + if err != nil { + return nil, err + } + + fmt.Printf("Paginated response %v : ", result) + + // map results to struct + var acr account.AccountChannelsResponse + err = result.GetResult(&acr) + if err != nil { + return nil, err + } + + // add page to array + *pages = append(*pages, acr) + + // check if marker present and make new call if exists + if acr.Marker != nil { + req.Marker = acr.Marker + return GetPages(a, req, pages) + } + + return result, nil } func (a *accountImpl) GetAccountInfo(req *account.AccountInfoRequest) (*account.AccountInfoResponse, XRPLResponse, error) { diff --git a/client/accounts_test.go b/client/accounts_test.go index 9e18638b8..0a0246c58 100644 --- a/client/accounts_test.go +++ b/client/accounts_test.go @@ -42,7 +42,7 @@ func TestGetAccountChannels(t *testing.T) { description string input account.AccountChannelsRequest sendRequestResult mockClientXrplResponse - output account.AccountChannelsResponse + output []account.AccountChannelsResponse expectedErr error }{ { @@ -57,7 +57,7 @@ func TestGetAccountChannels(t *testing.T) { "destination_account": "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", }, }, - output: account.AccountChannelsResponse{}, + output: []account.AccountChannelsResponse{}, expectedErr: errors.New("1 error(s) decoding:\n\n* 'account' expected type 'types.Address', got unconvertible type 'int', value: '123'"), }, { @@ -87,7 +87,7 @@ func TestGetAccountChannels(t *testing.T) { "validated": true, }, }, - output: account.AccountChannelsResponse{ + output: []account.AccountChannelsResponse{{ Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", LedgerIndex: 71766314, LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", @@ -104,7 +104,7 @@ func TestGetAccountChannels(t *testing.T) { }, }, Validated: true, - }, + }}, expectedErr: nil, }, } @@ -123,9 +123,75 @@ func TestGetAccountChannels(t *testing.T) { if tc.expectedErr != nil { require.EqualError(t, err, tc.expectedErr.Error()) } else { - require.Equal(t, &tc.output, res) + require.Equal(t, tc.output, res) } }) } } + +func TestNew(t *testing.T) { + + t.Run("Pagination calls", func(t *testing.T) { + + req1 := account.AccountChannelsRequest{ + Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", + } + req2 := account.AccountChannelsRequest{ + Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", + Marker: "pageMarker1", + } + req3 := account.AccountChannelsRequest{ + Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", + Marker: "pageMarker2", + } + + res1 := mockClientXrplResponse{ + Result: map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": 71766343, + "marker": "pageMarker1", + }, + } + res2 := mockClientXrplResponse{ + Result: map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": 71766343, + "marker": "pageMarker2", + }, + } + res3 := mockClientXrplResponse{ + Result: map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": 71766343, + }, + } + + cl := new(mockClient) + a := &accountImpl{client: cl} + + cl.On("SendRequest", &req1).Return(&res1, nil).Once() + cl.On("SendRequest", &req2).Return(&res2, nil) + cl.On("SendRequest", &req3).Return(&res3, nil) // returns no marker as final call + + res, _, err := a.GetAccountChannels(&req1) + + expectedRes := []account.AccountChannelsResponse{{ + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766343, + Marker: "pageMarker1", + }, + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766343, + Marker: "pageMarker2", + }, + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766343, + }} + + require.Equal(t, expectedRes, res) + require.NoError(t, err) + }) +} diff --git a/client/jsonrpc/jsonrpc_client.go b/client/jsonrpc/jsonrpc_client.go index 1d2d8a294..6171431b8 100644 --- a/client/jsonrpc/jsonrpc_client.go +++ b/client/jsonrpc/jsonrpc_client.go @@ -194,3 +194,46 @@ func CheckForError(res *http.Response) (jsonrpcmodels.JsonRpcResponse, error) { return jr, nil } + +// CALL getPages if request is paginated, not sendRequest + +// to make generic pass in the json and check for "marker" in this, pass in the struct you wanna return +// func (c *JsonRpcClient) GetPages(reqParams client.XRPLRequest, responsePages *[]interface{}) (client.XRPLResponse, error) { + +// // get first page of results +// result, err := c.SendRequest(reqParams) +// if err != nil { +// return nil, err +// } + +// fmt.Printf("Paginated response %v : ", result) + +// // map results to struct +// var acr account.AccountChannelsResponse +// err = result.GetResult(&acr) +// if err != nil { +// return nil, err +// } + +// // add page to array +// *responsePages = append(*responsePages, acr) + +// // check if marker present and make new call if exists +// if acr.Marker != nil { + +// // create new value +// newParams := reflect.ValueOf(reqParams) + +// // Get the field of the slice element that we want to set. +// m := newParams.FieldByName("Marker") + +// // Set the value! +// m.Set(reflect.ValueOf(acr.Marker)) + +// // req.Marker = acr.Marker + +// return c.GetPages(reqParams, responsePages) +// } + +// return result, nil +// } From 3e38f8f74775628eaed4c17143266d2a583e6a30 Mon Sep 17 00:00:00 2001 From: bmurphy333 Date: Sat, 16 Sep 2023 15:07:46 +1200 Subject: [PATCH 2/4] chore: first start at generic pagination, more to do --- client/accounts.go | 48 +-- client/accounts_test.go | 326 +++++++++--------- client/client.go | 12 + client/jsonrpc/jsonrpc_client.go | 86 +++-- client/jsonrpc/jsonrpc_client_test.go | 163 ++++++++- client/jsonrpc/models/jsonrpc_response.go | 12 + client/websocket/websocket_client.go | 4 + client/websocket/websocket_client_response.go | 6 + .../jsonrpc-client/jsonrpc_client_example.go | 8 +- .../account/account_channels_request.go | 5 + .../account/account_channels_response.go | 9 + model/client/account/account_info_request.go | 4 + model/client/utility/ping_request.go | 3 + 13 files changed, 456 insertions(+), 230 deletions(-) diff --git a/client/accounts.go b/client/accounts.go index 116d5f0a2..33644b808 100644 --- a/client/accounts.go +++ b/client/accounts.go @@ -1,13 +1,11 @@ package client import ( - "fmt" - "github.com/xyield/xrpl-go/model/client/account" ) type Account interface { - GetAccountChannels(req *account.AccountChannelsRequest) ([]account.AccountChannelsResponse, XRPLResponse, error) + GetAccountChannels(req *account.AccountChannelsRequest, params XRPLPaginatedRequest) ([]account.AccountChannelsResponse, []XRPLResponse, error) GetAccountInfo(req *account.AccountInfoRequest) (*account.AccountInfoResponse, XRPLResponse, error) } @@ -15,51 +13,37 @@ type accountImpl struct { client Client } -func (a *accountImpl) GetAccountChannels(req *account.AccountChannelsRequest) ([]account.AccountChannelsResponse, XRPLResponse, error) { +func (a *accountImpl) GetAccountChannels(req *account.AccountChannelsRequest, params XRPLPaginatedRequest) ([]account.AccountChannelsResponse, []XRPLResponse, error) { + + // TODO; set timer to exit recurssion if continues too long? err := req.Validate() if err != nil { return nil, nil, err } - pages := []account.AccountChannelsResponse{} - xrplResult, err := GetPages(a, req, &pages) + XRPLResponsePages, err := a.client.SendRequestPaginated(req, params.Limit, params.Paginated) if err != nil { return nil, nil, err } - return pages, xrplResult, nil -} + acrPages := []account.AccountChannelsResponse{} -// TODO: have a way for user to choose if they re-try with marker? That would require the 10 min rule being followed - trigger go routine to run and watch timer -// Call this method instead of SendRequest when response is paginated -func GetPages(a *accountImpl, req *account.AccountChannelsRequest, pages *[]account.AccountChannelsResponse) (XRPLResponse, error) { + // loop through pages and get result + for _, page := range XRPLResponsePages { - // get first page of results - result, err := a.client.SendRequest(req) - if err != nil { - return nil, err - } - - fmt.Printf("Paginated response %v : ", result) - - // map results to struct - var acr account.AccountChannelsResponse - err = result.GetResult(&acr) - if err != nil { - return nil, err - } + var acr account.AccountChannelsResponse - // add page to array - *pages = append(*pages, acr) + err = page.GetResult(&acr) + if err != nil { + return nil, nil, err + } - // check if marker present and make new call if exists - if acr.Marker != nil { - req.Marker = acr.Marker - return GetPages(a, req, pages) + // append result to array + acrPages = append(acrPages, acr) } - return result, nil + return acrPages, XRPLResponsePages, nil } func (a *accountImpl) GetAccountInfo(req *account.AccountInfoRequest) (*account.AccountInfoResponse, XRPLResponse, error) { diff --git a/client/accounts_test.go b/client/accounts_test.go index 0a0246c58..57feef316 100644 --- a/client/accounts_test.go +++ b/client/accounts_test.go @@ -1,14 +1,8 @@ package client import ( - "errors" - "testing" - "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" - "github.com/xyield/xrpl-go/model/client/account" - "github.com/xyield/xrpl-go/model/client/common" ) type mockClient struct { @@ -31,167 +25,169 @@ func (m *mockClientXrplResponse) GetResult(v any) error { return nil } +// func (m *mockClientXrplResponse) GetMarker() any { +// return nil +// } + func (m *mockClient) SendRequest(req XRPLRequest) (XRPLResponse, error) { args := m.Called(req) return args.Get(0).(XRPLResponse), args.Error(1) } -func TestGetAccountChannels(t *testing.T) { - - tt := []struct { - description string - input account.AccountChannelsRequest - sendRequestResult mockClientXrplResponse - output []account.AccountChannelsResponse - expectedErr error - }{ - { - description: "GetResult returns an error", - input: account.AccountChannelsRequest{ - Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", - DestinationAccount: "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", - }, - sendRequestResult: mockClientXrplResponse{ - Result: map[string]any{ - "account": 123, - "destination_account": "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", - }, - }, - output: []account.AccountChannelsResponse{}, - expectedErr: errors.New("1 error(s) decoding:\n\n* 'account' expected type 'types.Address', got unconvertible type 'int', value: '123'"), - }, - { - description: "successful response", - input: account.AccountChannelsRequest{ - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", - LedgerIndex: common.VALIDATED, - }, - sendRequestResult: mockClientXrplResponse{ - Result: map[string]any{ - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "channels": []any{ - map[string]any{ - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "amount": "1000", - "balance": "0", - "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", - "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", - "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", - "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", - "settle_delay": 60, - }, - }, - "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", - "ledger_index": 71766314, - "validated": true, - }, - }, - output: []account.AccountChannelsResponse{{ - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - LedgerIndex: 71766314, - LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", - Channels: []account.ChannelResult{ - { - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - Amount: "1000", - Balance: "0", - ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", - DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", - PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", - PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", - SettleDelay: 60, - }, - }, - Validated: true, - }}, - expectedErr: nil, - }, - } - - for _, tc := range tt { - - t.Run(tc.description, func(t *testing.T) { - - cl := new(mockClient) - a := &accountImpl{client: cl} - - cl.On("SendRequest", &tc.input).Return(&tc.sendRequestResult, nil) - - res, _, err := a.GetAccountChannels(&tc.input) - - if tc.expectedErr != nil { - require.EqualError(t, err, tc.expectedErr.Error()) - } else { - require.Equal(t, tc.output, res) - } - - }) - } -} - -func TestNew(t *testing.T) { - - t.Run("Pagination calls", func(t *testing.T) { - - req1 := account.AccountChannelsRequest{ - Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", - } - req2 := account.AccountChannelsRequest{ - Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", - Marker: "pageMarker1", - } - req3 := account.AccountChannelsRequest{ - Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", - Marker: "pageMarker2", - } - - res1 := mockClientXrplResponse{ - Result: map[string]any{ - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "ledger_index": 71766343, - "marker": "pageMarker1", - }, - } - res2 := mockClientXrplResponse{ - Result: map[string]any{ - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "ledger_index": 71766343, - "marker": "pageMarker2", - }, - } - res3 := mockClientXrplResponse{ - Result: map[string]any{ - "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - "ledger_index": 71766343, - }, - } - - cl := new(mockClient) - a := &accountImpl{client: cl} - - cl.On("SendRequest", &req1).Return(&res1, nil).Once() - cl.On("SendRequest", &req2).Return(&res2, nil) - cl.On("SendRequest", &req3).Return(&res3, nil) // returns no marker as final call - - res, _, err := a.GetAccountChannels(&req1) - - expectedRes := []account.AccountChannelsResponse{{ - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - LedgerIndex: 71766343, - Marker: "pageMarker1", - }, - { - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - LedgerIndex: 71766343, - Marker: "pageMarker2", - }, - { - Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", - LedgerIndex: 71766343, - }} - - require.Equal(t, expectedRes, res) - require.NoError(t, err) - }) -} +// func (m *mockClient) SendRequestPaginated(reqParams XRPLRequest, limit int, pagination bool) ([]mockClientXrplResponse, error) { +// args := m.Called(reqParams, limit, pagination) +// return args.Get(0).([]mockClientXrplResponse), args.Error(1) +// } +// func (m *mockClient) SendRequestPaginated(reqParams XRPLRequest, limit int, pagination bool) ([]XRPLResponse, error) { +// args := m.Called(reqParams, limit, pagination) +// return args.Get(0).([]XRPLResponse), args.Error(1) +// } + +// func TestGetAccountChannels(t *testing.T) { + +// tt := []struct { +// description string +// input account.AccountChannelsRequest +// paginationParams XRPLPaginatedRequest +// sendRequestResult []mockClientXrplResponse +// output []account.AccountChannelsResponse +// expectedErr error +// }{ +// // { +// // description: "GetResult returns an error", +// // input: account.AccountChannelsRequest{ +// // Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", +// // DestinationAccount: "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", +// // }, +// // sendRequestResult: []mockClientXrplResponse{{ +// // Result: map[string]any{ +// // "account": 123, +// // "destination_account": "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", +// // }, +// // }}, +// // output: []account.AccountChannelsResponse{}, +// // expectedErr: errors.New("1 error(s) decoding:\n\n* 'account' expected type 'types.Address', got unconvertible type 'int', value: '123'"), +// // }, +// { +// description: "successful response", +// input: account.AccountChannelsRequest{ +// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", +// }, +// paginationParams: XRPLPaginatedRequest{ +// Limit: 0, +// Paginated: true, +// }, +// sendRequestResult: []mockClientXrplResponse{{ +// Result: map[string]any{ +// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// "channels": []any{ +// map[string]any{ +// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// "amount": "1000", +// "balance": "0", +// "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", +// "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", +// "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", +// "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", +// "settle_delay": 60, +// }, +// }, +// "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", +// "ledger_index": 71766314, +// "validated": true, +// "marker": "pageMarker1", +// }, +// }, +// { +// Result: map[string]any{ +// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// "channels": []any{ +// map[string]any{ +// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// "amount": "1000", +// "balance": "0", +// "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", +// "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", +// "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", +// "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", +// "settle_delay": 60, +// }, +// }, +// "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", +// "ledger_index": 71766314, +// "validated": true, +// }, +// }}, +// output: []account.AccountChannelsResponse{{ +// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// LedgerIndex: 71766314, +// LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", +// Channels: []account.ChannelResult{ +// { +// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// Amount: "1000", +// Balance: "0", +// ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", +// DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", +// PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", +// PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", +// SettleDelay: 60, +// }, +// }, +// Validated: true, +// Marker: "pageMarker1", +// }, +// { +// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// LedgerIndex: 71766314, +// LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", +// Channels: []account.ChannelResult{ +// { +// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// Amount: "1000", +// Balance: "0", +// ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", +// DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", +// PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", +// PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", +// SettleDelay: 60, +// }, +// }, +// Validated: true, +// }}, +// expectedErr: nil, +// }, +// } + +// for _, tc := range tt { + +// t.Run(tc.description, func(t *testing.T) { + +// // res1 := mockClientXrplResponse{ +// // Result: map[string]any{ +// // "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", +// // "ledger_index": 71766343, +// // "marker": "pageMarker1", +// // }, +// // } + +// cl := new(mockClient) +// a := &accountImpl{client: cl} + +// // TODO: this isn't working as slice of obj doesn't impl interface +// cl.On("SendRequestPaginated", &tc.input, tc.paginationParams.Limit, tc.paginationParams.Paginated).Return(tc.sendRequestResult, nil) + +// // cl.On("SendRequest", &tc.input).Return(&res1, nil) + +// res, _, err := a.GetAccountChannels(&tc.input, tc.paginationParams) + +// if tc.expectedErr != nil { +// require.EqualError(t, err, tc.expectedErr.Error()) +// } else { +// require.Equal(t, tc.output, res) +// } + +// }) +// } +// } diff --git a/client/client.go b/client/client.go index 4bb48522b..da44d6b40 100644 --- a/client/client.go +++ b/client/client.go @@ -2,6 +2,7 @@ package client type Client interface { SendRequest(req XRPLRequest) (XRPLResponse, error) + SendRequestPaginated(reqParams XRPLRequest, limit int, pagination bool) ([]XRPLResponse, error) } type XRPLClient struct { @@ -12,12 +13,23 @@ type XRPLClient struct { type XRPLRequest interface { Method() string Validate() error + SetMarker(m any) // TODO: take out of interface as only pag ones need it - make new ones for the req and response } type XRPLResponse interface { GetResult(v any) error + GetMarker() any } +type XRPLPaginatedRequest struct { + Limit int + Paginated bool +} + +// type XRPLPaginatedResponse interface { // structs in both clients will impl this +// GetMarker() any +// } + type XRPLResponseWarning struct { Id int `json:"id"` Message string `json:"message"` diff --git a/client/jsonrpc/jsonrpc_client.go b/client/jsonrpc/jsonrpc_client.go index 6171431b8..2cc76e1ff 100644 --- a/client/jsonrpc/jsonrpc_client.go +++ b/client/jsonrpc/jsonrpc_client.go @@ -195,45 +195,71 @@ func CheckForError(res *http.Response) (jsonrpcmodels.JsonRpcResponse, error) { return jr, nil } -// CALL getPages if request is paginated, not sendRequest +func (c *JsonRpcClient) SendRequestPaginated(reqParams client.XRPLRequest, limit int, pagination bool) ([]client.XRPLResponse, error) { -// to make generic pass in the json and check for "marker" in this, pass in the struct you wanna return -// func (c *JsonRpcClient) GetPages(reqParams client.XRPLRequest, responsePages *[]interface{}) (client.XRPLResponse, error) { + responsePages := []client.XRPLResponse{} -// // get first page of results -// result, err := c.SendRequest(reqParams) -// if err != nil { -// return nil, err -// } + if !pagination { -// fmt.Printf("Paginated response %v : ", result) + res, err := c.SendRequest(reqParams) + if err != nil { + return nil, err + } + + responsePages = append(responsePages, res) + + } else { + + // set default limit if nothing passed in + if limit == 0 { + limit = 10 + } + + err := GetPages(c, reqParams, &responsePages, limit, 0) + if err != nil { + return nil, err + } + } -// // map results to struct -// var acr account.AccountChannelsResponse -// err = result.GetResult(&acr) -// if err != nil { -// return nil, err -// } + return responsePages, nil +} -// // add page to array -// *responsePages = append(*responsePages, acr) +func GetPages(c *JsonRpcClient, reqParams client.XRPLRequest, responsePages *[]client.XRPLResponse, limit int, counter int) error { -// // check if marker present and make new call if exists -// if acr.Marker != nil { + if limit == counter { + return nil + } -// // create new value -// newParams := reflect.ValueOf(reqParams) + // get first page of results + result, err := c.SendRequest(reqParams) + if err != nil { + return err + } -// // Get the field of the slice element that we want to set. -// m := newParams.FieldByName("Marker") + fmt.Printf("Paginated response %v : ", result) -// // Set the value! -// m.Set(reflect.ValueOf(acr.Marker)) + // cast to JsonRpcResponse + jr, ok := result.(*jsonrpcmodels.JsonRpcResponse) + if !ok { + return errors.New("problem casting XRPLResponse to JsonRpcResponse") + } -// // req.Marker = acr.Marker + // add result to array + *responsePages = append(*responsePages, jr) -// return c.GetPages(reqParams, responsePages) -// } + // check for marker + marker := jr.GetMarker() + if marker != nil { -// return result, nil -// } + // set marker in request to get next page + reqParams.SetMarker(marker) + + // increase counter + counter++ + + // make next request + return GetPages(c, reqParams, responsePages, limit, counter) // TODO: check this!!! + } + + return nil +} diff --git a/client/jsonrpc/jsonrpc_client_test.go b/client/jsonrpc/jsonrpc_client_test.go index 0b0691800..574a8c945 100644 --- a/client/jsonrpc/jsonrpc_client_test.go +++ b/client/jsonrpc/jsonrpc_client_test.go @@ -334,7 +334,7 @@ func TestSendRequest(t *testing.T) { "ledger_hash": "27F530E5C93ED5C13994812787C1ED073C822BAEC7597964608F2C049C2ACD2D", "ledger_index": 71766343 } - }` + }` mc := &mockClient{} mc.DoFunc = func(req *http.Request) (*http.Response, error) { @@ -371,7 +371,6 @@ func TestSendRequest(t *testing.T) { assert.Equal(t, expected.LedgerIndex, channelsResponse.LedgerIndex) assert.Equal(t, expected.LedgerHash, channelsResponse.LedgerHash) }) - t.Run("SendRequest - timeout", func(t *testing.T) { req := &account.AccountChannelsRequest{ Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", @@ -396,3 +395,163 @@ func TestSendRequest(t *testing.T) { assert.Contains(t, err.Error(), "timeout") }) } + +func TestSendRequestPagination(t *testing.T) { + + req1 := account.AccountChannelsRequest{ + Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", + } + paginatedParams := client.XRPLPaginatedRequest{ + Limit: 3, + Paginated: true, + } + + markerResponse1 := `{ + "result": { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": 71766343, + "marker": "pageMarker1" + } + }` + markerResponse2 := `{ + "result": { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": 71766343, + "marker": "pageMarker2" + } + }` + noMarkerResponse := `{ + "result": { + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": 71766343 + } + }` + + t.Run("Pagination calls", func(t *testing.T) { + + expectedRes := []account.AccountChannelsResponse{ + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766343, + Marker: "pageMarker1", + }, + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766343, + Marker: "pageMarker2", + }, + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766343, + }, + } + + mc := &mockClient{} + mc.DoFunc = func(req *http.Request) (*http.Response, error) { + if mc.RequestCount < 1 { + // Return marker for first + mc.RequestCount++ + return mockResponse(markerResponse1, 200, mc)(req) + } + if mc.RequestCount < 2 { + // Return marker for second + mc.RequestCount++ + return mockResponse(markerResponse2, 200, mc)(req) + } + // Return no marker + return mockResponse(noMarkerResponse, 200, mc)(req) + } + cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) + assert.NoError(t, err) + jsonRpcClient := NewJsonRpcClient(cfg) + + pages, err := jsonRpcClient.SendRequestPaginated(&req1, paginatedParams.Limit, paginatedParams.Paginated) + assert.NoError(t, err) + + // TODO: is this ok to set equal? Is it useful to the user? + expectedFirstPage := jsonrpcmodels.JsonRpcResponse{ + Result: jsonrpcmodels.AnyJson{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "ledger_index": json.Number(strconv.FormatInt(71766343, 10)), + "marker": "pageMarker1", + }} + firstPage := pages[0] + assert.Equal(t, &expectedFirstPage, firstPage) + + // unmarshall into specified type + acrPages := []account.AccountChannelsResponse{} + + for _, page := range pages { + + var acr account.AccountChannelsResponse + + err = page.GetResult(&acr) + assert.NoError(t, err) + + acrPages = append(acrPages, acr) + } + + assert.Equal(t, expectedRes, acrPages) + }) + + t.Run("No Pagination", func(t *testing.T) { + + mc := &mockClient{} + mc.DoFunc = func(req *http.Request) (*http.Response, error) { + // Return no marker + return mockResponse(markerResponse1, 200, mc)(req) + } + + cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) + assert.NoError(t, err) + jsonRpcClient := NewJsonRpcClient(cfg) + + pages, err := jsonRpcClient.SendRequestPaginated(&req1, 10, false) + assert.NoError(t, err) + assert.Equal(t, 1, len(pages)) + }) + + t.Run("Limit set", func(t *testing.T) { + + mc := &mockClient{} + mc.DoFunc = func(req *http.Request) (*http.Response, error) { + if mc.RequestCount < 1 { + // Return marker for first + mc.RequestCount++ + return mockResponse(markerResponse1, 200, mc)(req) + } + if mc.RequestCount < 2 { + // Return marker for second + mc.RequestCount++ + return mockResponse(markerResponse2, 200, mc)(req) + } + // Return no marker + return mockResponse(noMarkerResponse, 200, mc)(req) + } + + cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) + assert.NoError(t, err) + jsonRpcClient := NewJsonRpcClient(cfg) + + pages, err := jsonRpcClient.SendRequestPaginated(&req1, 2, true) + assert.NoError(t, err) + assert.Equal(t, 2, len(pages)) + }) + + t.Run("Default limit", func(t *testing.T) { + mc := &mockClient{} + + mc.DoFunc = func(req *http.Request) (*http.Response, error) { + // Return no marker + return mockResponse(markerResponse1, 200, mc)(req) + } + + cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) + assert.NoError(t, err) + jsonRpcClient := NewJsonRpcClient(cfg) + + pages, err := jsonRpcClient.SendRequestPaginated(&req1, 0, true) + assert.NoError(t, err) + assert.Equal(t, 10, len(pages)) + }) +} diff --git a/client/jsonrpc/models/jsonrpc_response.go b/client/jsonrpc/models/jsonrpc_response.go index 1fb1ccff4..bb9b0b977 100644 --- a/client/jsonrpc/models/jsonrpc_response.go +++ b/client/jsonrpc/models/jsonrpc_response.go @@ -31,3 +31,15 @@ func (r JsonRpcResponse) GetResult(v any) error { } return nil } + +func (r JsonRpcResponse) GetMarker() any { + if _, ok := r.Result["marker"]; ok { + return r.Result["marker"] + } + return nil +} + +// // this will impl the XRPLPaginatedResponse +// type JsonRpcPaginatedResponse struct { +// results []JsonRpcResponse +// } diff --git a/client/websocket/websocket_client.go b/client/websocket/websocket_client.go index ae25e4484..038ecc9d7 100644 --- a/client/websocket/websocket_client.go +++ b/client/websocket/websocket_client.go @@ -23,6 +23,10 @@ type WebsocketClient struct { idCounter atomic.Uint32 } +func (c *WebsocketClient) SendRequestPaginated(reqParams client.XRPLRequest, limit int, pagination bool) ([]client.XRPLResponse, error) { + return nil, nil +} + func (c *WebsocketClient) SendRequest(req client.XRPLRequest) (client.XRPLResponse, error) { err := req.Validate() if err != nil { diff --git a/client/websocket/websocket_client_response.go b/client/websocket/websocket_client_response.go index 696bb45ab..04768b7fe 100644 --- a/client/websocket/websocket_client_response.go +++ b/client/websocket/websocket_client_response.go @@ -45,3 +45,9 @@ func (r *WebSocketClientXrplResponse) CheckError() error { } return nil } + +func (r WebSocketClientXrplResponse) GetMarker() any { + + // TODO: impl this method + return nil +} diff --git a/examples/jsonrpc-client/jsonrpc_client_example.go b/examples/jsonrpc-client/jsonrpc_client_example.go index ac52bb96f..436c4cfba 100644 --- a/examples/jsonrpc-client/jsonrpc_client_example.go +++ b/examples/jsonrpc-client/jsonrpc_client_example.go @@ -17,12 +17,18 @@ func main() { log.Panicln(err) } + paginatedParams := client.XRPLPaginatedRequest{ + Limit: 3, + Paginated: true, + } + // Initialise new json client with json config client := jsonrpcclient.NewClient(cfg) // call the desired method var req *account.AccountChannelsRequest - ac, xrplRes, err := client.Account.GetAccountChannels(req) + + ac, xrplRes, err := client.Account.GetAccountChannels(req, paginatedParams) if err != nil { fmt.Println(err.Error()) } diff --git a/model/client/account/account_channels_request.go b/model/client/account/account_channels_request.go index 8c5f46d58..e696b479a 100644 --- a/model/client/account/account_channels_request.go +++ b/model/client/account/account_channels_request.go @@ -21,6 +21,11 @@ func (*AccountChannelsRequest) Method() string { return "account_channels" } +// Below mean struct satisfies paginated response interface +func (a *AccountChannelsRequest) SetMarker(m any) { + a.Marker = m +} + // Validate method to be added to each request struct func (a *AccountChannelsRequest) Validate() error { if a.Account == "" { diff --git a/model/client/account/account_channels_response.go b/model/client/account/account_channels_response.go index 7b865938b..8c6c6d467 100644 --- a/model/client/account/account_channels_response.go +++ b/model/client/account/account_channels_response.go @@ -14,3 +14,12 @@ type AccountChannelsResponse struct { Limit int `json:"limit,omitempty"` Marker any `json:"marker,omitempty"` } + +// below to satisfy the paginated response struct +func (a *AccountChannelsResponse) GetMarker() any { + if a.Marker != nil { + return a.Marker + } else { + return nil + } +} diff --git a/model/client/account/account_info_request.go b/model/client/account/account_info_request.go index 9506ba7d6..eef465ef0 100644 --- a/model/client/account/account_info_request.go +++ b/model/client/account/account_info_request.go @@ -16,6 +16,10 @@ type AccountInfoRequest struct { Strict bool `json:"strict,omitempty"` } +func (a *AccountInfoRequest) SetMarker(m any) { + // empty as no marker to populate +} + func (*AccountInfoRequest) Method() string { return "account_info" } diff --git a/model/client/utility/ping_request.go b/model/client/utility/ping_request.go index d5cd0ce5b..48981ed87 100644 --- a/model/client/utility/ping_request.go +++ b/model/client/utility/ping_request.go @@ -9,3 +9,6 @@ func (*PingRequest) Method() string { func (*PingRequest) Validate() error { return nil } + +func (*PingRequest) SetMarker(m any) { +} From d9ecd8e0ab2fb31d3dc20009207d17e4d72006cc Mon Sep 17 00:00:00 2001 From: bmurphy333 Date: Sun, 17 Sep 2023 13:40:20 +1200 Subject: [PATCH 3/4] chore: sendRequestPagination finished for rpc client --- client/accounts.go | 10 +- client/accounts_test.go | 326 +++++++++--------- client/client.go | 17 +- client/jsonrpc/jsonrpc_client.go | 22 +- client/jsonrpc/jsonrpc_client_test.go | 18 +- client/jsonrpc/models/jsonrpc_response.go | 17 +- client/websocket/websocket_client.go | 3 +- client/websocket/websocket_client_response.go | 3 +- .../jsonrpc-client/jsonrpc_client_example.go | 2 +- model/client/account/account_info_request.go | 4 - model/client/utility/ping_request.go | 3 - 11 files changed, 224 insertions(+), 201 deletions(-) diff --git a/client/accounts.go b/client/accounts.go index 33644b808..330cc5237 100644 --- a/client/accounts.go +++ b/client/accounts.go @@ -5,7 +5,7 @@ import ( ) type Account interface { - GetAccountChannels(req *account.AccountChannelsRequest, params XRPLPaginatedRequest) ([]account.AccountChannelsResponse, []XRPLResponse, error) + GetAccountChannels(req *account.AccountChannelsRequest, params XRPLPaginatedParams) ([]account.AccountChannelsResponse, []XRPLResponse, error) GetAccountInfo(req *account.AccountInfoRequest) (*account.AccountInfoResponse, XRPLResponse, error) } @@ -13,20 +13,20 @@ type accountImpl struct { client Client } -func (a *accountImpl) GetAccountChannels(req *account.AccountChannelsRequest, params XRPLPaginatedRequest) ([]account.AccountChannelsResponse, []XRPLResponse, error) { - - // TODO; set timer to exit recurssion if continues too long? +func (a *accountImpl) GetAccountChannels(req *account.AccountChannelsRequest, params XRPLPaginatedParams) ([]account.AccountChannelsResponse, []XRPLResponse, error) { err := req.Validate() if err != nil { return nil, nil, err } - XRPLResponsePages, err := a.client.SendRequestPaginated(req, params.Limit, params.Paginated) + XRPLResponse, err := a.client.SendRequestPaginated(req, params.Limit, params.Paginated) if err != nil { return nil, nil, err } + XRPLResponsePages := XRPLResponse.GetXRPLPages() + acrPages := []account.AccountChannelsResponse{} // loop through pages and get result diff --git a/client/accounts_test.go b/client/accounts_test.go index 57feef316..b62609b99 100644 --- a/client/accounts_test.go +++ b/client/accounts_test.go @@ -1,19 +1,36 @@ package client import ( + "errors" + "testing" + "github.com/mitchellh/mapstructure" "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" + "github.com/xyield/xrpl-go/model/client/account" ) type mockClient struct { mock.Mock } +type mockPaginatedResponse struct { + Pages []mockClientXrplResponse +} + +func (r mockPaginatedResponse) GetXRPLPages() []XRPLResponse { + res := make([]XRPLResponse, len(r.Pages)) + for i, page := range r.Pages { + res[i] = page + } + return res +} + type mockClientXrplResponse struct { Result map[string]any } -func (m *mockClientXrplResponse) GetResult(v any) error { +func (m mockClientXrplResponse) GetResult(v any) error { dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{TagName: "json", Result: &v}) if err != nil { return err @@ -25,169 +42,156 @@ func (m *mockClientXrplResponse) GetResult(v any) error { return nil } -// func (m *mockClientXrplResponse) GetMarker() any { -// return nil -// } +func (m mockClientXrplResponse) GetMarker() any { + return nil +} func (m *mockClient) SendRequest(req XRPLRequest) (XRPLResponse, error) { args := m.Called(req) return args.Get(0).(XRPLResponse), args.Error(1) } -// func (m *mockClient) SendRequestPaginated(reqParams XRPLRequest, limit int, pagination bool) ([]mockClientXrplResponse, error) { -// args := m.Called(reqParams, limit, pagination) -// return args.Get(0).([]mockClientXrplResponse), args.Error(1) -// } -// func (m *mockClient) SendRequestPaginated(reqParams XRPLRequest, limit int, pagination bool) ([]XRPLResponse, error) { -// args := m.Called(reqParams, limit, pagination) -// return args.Get(0).([]XRPLResponse), args.Error(1) -// } - -// func TestGetAccountChannels(t *testing.T) { - -// tt := []struct { -// description string -// input account.AccountChannelsRequest -// paginationParams XRPLPaginatedRequest -// sendRequestResult []mockClientXrplResponse -// output []account.AccountChannelsResponse -// expectedErr error -// }{ -// // { -// // description: "GetResult returns an error", -// // input: account.AccountChannelsRequest{ -// // Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", -// // DestinationAccount: "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", -// // }, -// // sendRequestResult: []mockClientXrplResponse{{ -// // Result: map[string]any{ -// // "account": 123, -// // "destination_account": "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", -// // }, -// // }}, -// // output: []account.AccountChannelsResponse{}, -// // expectedErr: errors.New("1 error(s) decoding:\n\n* 'account' expected type 'types.Address', got unconvertible type 'int', value: '123'"), -// // }, -// { -// description: "successful response", -// input: account.AccountChannelsRequest{ -// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", -// }, -// paginationParams: XRPLPaginatedRequest{ -// Limit: 0, -// Paginated: true, -// }, -// sendRequestResult: []mockClientXrplResponse{{ -// Result: map[string]any{ -// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// "channels": []any{ -// map[string]any{ -// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// "amount": "1000", -// "balance": "0", -// "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", -// "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", -// "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", -// "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", -// "settle_delay": 60, -// }, -// }, -// "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", -// "ledger_index": 71766314, -// "validated": true, -// "marker": "pageMarker1", -// }, -// }, -// { -// Result: map[string]any{ -// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// "channels": []any{ -// map[string]any{ -// "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// "amount": "1000", -// "balance": "0", -// "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", -// "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", -// "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", -// "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", -// "settle_delay": 60, -// }, -// }, -// "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", -// "ledger_index": 71766314, -// "validated": true, -// }, -// }}, -// output: []account.AccountChannelsResponse{{ -// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// LedgerIndex: 71766314, -// LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", -// Channels: []account.ChannelResult{ -// { -// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// Amount: "1000", -// Balance: "0", -// ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", -// DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", -// PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", -// PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", -// SettleDelay: 60, -// }, -// }, -// Validated: true, -// Marker: "pageMarker1", -// }, -// { -// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// LedgerIndex: 71766314, -// LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", -// Channels: []account.ChannelResult{ -// { -// Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// Amount: "1000", -// Balance: "0", -// ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", -// DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", -// PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", -// PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", -// SettleDelay: 60, -// }, -// }, -// Validated: true, -// }}, -// expectedErr: nil, -// }, -// } - -// for _, tc := range tt { - -// t.Run(tc.description, func(t *testing.T) { - -// // res1 := mockClientXrplResponse{ -// // Result: map[string]any{ -// // "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", -// // "ledger_index": 71766343, -// // "marker": "pageMarker1", -// // }, -// // } - -// cl := new(mockClient) -// a := &accountImpl{client: cl} - -// // TODO: this isn't working as slice of obj doesn't impl interface -// cl.On("SendRequestPaginated", &tc.input, tc.paginationParams.Limit, tc.paginationParams.Paginated).Return(tc.sendRequestResult, nil) - -// // cl.On("SendRequest", &tc.input).Return(&res1, nil) - -// res, _, err := a.GetAccountChannels(&tc.input, tc.paginationParams) - -// if tc.expectedErr != nil { -// require.EqualError(t, err, tc.expectedErr.Error()) -// } else { -// require.Equal(t, tc.output, res) -// } - -// }) -// } -// } +func (m *mockClient) SendRequestPaginated(reqParams XRPLPaginatedRequest, limit int, pagination bool) (XRPLPaginatedResponse, error) { + args := m.Called(reqParams, limit, pagination) + return args.Get(0).(XRPLPaginatedResponse), args.Error(1) +} + +func TestGetAccountChannels(t *testing.T) { + + tt := []struct { + description string + input account.AccountChannelsRequest + paginationParams XRPLPaginatedParams + sendRequestResult mockPaginatedResponse + output []account.AccountChannelsResponse + expectedErr error + }{ + { + description: "GetResult returns an error", + input: account.AccountChannelsRequest{ + Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", + DestinationAccount: "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", + }, + sendRequestResult: mockPaginatedResponse{ + Pages: []mockClientXrplResponse{{ + Result: map[string]any{ + "account": 123, + "destination_account": "rnZvsWuLem5Ha46AZs61jLWR9R5esinkG3", + }, + }}, + }, + output: []account.AccountChannelsResponse{}, + expectedErr: errors.New("1 error(s) decoding:\n\n* 'account' expected type 'types.Address', got unconvertible type 'int', value: '123'"), + }, + { + description: "successful response", + input: account.AccountChannelsRequest{ + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + }, + paginationParams: XRPLPaginatedParams{ + Limit: 0, + Paginated: true, + }, + sendRequestResult: mockPaginatedResponse{ + Pages: []mockClientXrplResponse{{ + Result: map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "channels": []any{ + map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "amount": "1000", + "balance": "0", + "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", + "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", + "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", + "settle_delay": 60, + }, + }, + "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", + "ledger_index": 71766314, + "validated": true, + "marker": "pageMarker1", + }, + }, + { + Result: map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "channels": []any{ + map[string]any{ + "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + "amount": "1000", + "balance": "0", + "channel_id": "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", + "destination_account": "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + "public_key": "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", + "public_key_hex": "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", + "settle_delay": 60, + }, + }, + "ledger_hash": "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", + "ledger_index": 71766314, + "validated": true, + }, + }}, + }, + output: []account.AccountChannelsResponse{{ + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766314, + LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", + Channels: []account.ChannelResult{ + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Amount: "1000", + Balance: "0", + ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", + DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", + PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", + SettleDelay: 60, + }, + }, + Validated: true, + Marker: "pageMarker1", + }, + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + LedgerIndex: 71766314, + LedgerHash: "1EDBBA3C793863366DF5B31C2174B6B5E6DF6DB89A7212B86838489148E2A581", + Channels: []account.ChannelResult{ + { + Account: "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", + Amount: "1000", + Balance: "0", + ChannelID: "C7F634794B79DB40E87179A9D1BF05D05797AE7E92DF8E93FD6656E8C4BE3AE7", + DestinationAccount: "ra5nK24KXen9AHvsdFTKHSANinZseWnPcX", + PublicKey: "aBR7mdD75Ycs8DRhMgQ4EMUEmBArF8SEh1hfjrT2V9DQTLNbJVqw", + PublicKeyHex: "03CFD18E689434F032A4E84C63E2A3A6472D684EAF4FD52CA67742F3E24BAE81B2", + SettleDelay: 60, + }, + }, + Validated: true, + }}, + expectedErr: nil, + }, + } + + for _, tc := range tt { + + t.Run(tc.description, func(t *testing.T) { + + cl := new(mockClient) + a := &accountImpl{client: cl} + cl.On("SendRequestPaginated", &tc.input, tc.paginationParams.Limit, tc.paginationParams.Paginated).Return(tc.sendRequestResult, nil) + + res, _, err := a.GetAccountChannels(&tc.input, tc.paginationParams) + + if tc.expectedErr != nil { + require.EqualError(t, err, tc.expectedErr.Error()) + } else { + require.Equal(t, tc.output, res) + } + }) + } +} diff --git a/client/client.go b/client/client.go index da44d6b40..d58e0a528 100644 --- a/client/client.go +++ b/client/client.go @@ -2,7 +2,7 @@ package client type Client interface { SendRequest(req XRPLRequest) (XRPLResponse, error) - SendRequestPaginated(reqParams XRPLRequest, limit int, pagination bool) ([]XRPLResponse, error) + SendRequestPaginated(reqParams XRPLPaginatedRequest, limit int, pagination bool) (XRPLPaginatedResponse, error) } type XRPLClient struct { @@ -13,7 +13,6 @@ type XRPLClient struct { type XRPLRequest interface { Method() string Validate() error - SetMarker(m any) // TODO: take out of interface as only pag ones need it - make new ones for the req and response } type XRPLResponse interface { @@ -21,14 +20,20 @@ type XRPLResponse interface { GetMarker() any } -type XRPLPaginatedRequest struct { +type XRPLPaginatedParams struct { Limit int Paginated bool } -// type XRPLPaginatedResponse interface { // structs in both clients will impl this -// GetMarker() any -// } +type XRPLPaginatedRequest interface { + Method() string + Validate() error + SetMarker(m any) +} + +type XRPLPaginatedResponse interface { + GetXRPLPages() []XRPLResponse +} type XRPLResponseWarning struct { Id int `json:"id"` diff --git a/client/jsonrpc/jsonrpc_client.go b/client/jsonrpc/jsonrpc_client.go index 2cc76e1ff..ec8fdc93e 100644 --- a/client/jsonrpc/jsonrpc_client.go +++ b/client/jsonrpc/jsonrpc_client.go @@ -195,9 +195,9 @@ func CheckForError(res *http.Response) (jsonrpcmodels.JsonRpcResponse, error) { return jr, nil } -func (c *JsonRpcClient) SendRequestPaginated(reqParams client.XRPLRequest, limit int, pagination bool) ([]client.XRPLResponse, error) { +func (c *JsonRpcClient) SendRequestPaginated(reqParams client.XRPLPaginatedRequest, limit int, pagination bool) (client.XRPLPaginatedResponse, error) { - responsePages := []client.XRPLResponse{} + responsePages := []jsonrpcmodels.JsonRpcResponse{} if !pagination { @@ -205,8 +205,12 @@ func (c *JsonRpcClient) SendRequestPaginated(reqParams client.XRPLRequest, limit if err != nil { return nil, err } + jr, ok := res.(*jsonrpcmodels.JsonRpcResponse) + if !ok { + return nil, errors.New("problem casting XRPLResponse to JsonRpcResponse") + } - responsePages = append(responsePages, res) + responsePages = append(responsePages, *jr) } else { @@ -221,10 +225,14 @@ func (c *JsonRpcClient) SendRequestPaginated(reqParams client.XRPLRequest, limit } } - return responsePages, nil + res := jsonrpcmodels.JsonRpcPaginationResponse{ + Pages: responsePages, + } + + return res, nil } -func GetPages(c *JsonRpcClient, reqParams client.XRPLRequest, responsePages *[]client.XRPLResponse, limit int, counter int) error { +func GetPages(c *JsonRpcClient, reqParams client.XRPLPaginatedRequest, responsePages *[]jsonrpcmodels.JsonRpcResponse, limit int, counter int) error { if limit == counter { return nil @@ -245,7 +253,7 @@ func GetPages(c *JsonRpcClient, reqParams client.XRPLRequest, responsePages *[]c } // add result to array - *responsePages = append(*responsePages, jr) + *responsePages = append(*responsePages, *jr) // check for marker marker := jr.GetMarker() @@ -258,7 +266,7 @@ func GetPages(c *JsonRpcClient, reqParams client.XRPLRequest, responsePages *[]c counter++ // make next request - return GetPages(c, reqParams, responsePages, limit, counter) // TODO: check this!!! + return GetPages(c, reqParams, responsePages, limit, counter) } return nil diff --git a/client/jsonrpc/jsonrpc_client_test.go b/client/jsonrpc/jsonrpc_client_test.go index 574a8c945..df2aed999 100644 --- a/client/jsonrpc/jsonrpc_client_test.go +++ b/client/jsonrpc/jsonrpc_client_test.go @@ -401,7 +401,7 @@ func TestSendRequestPagination(t *testing.T) { req1 := account.AccountChannelsRequest{ Account: "rLHmBn4fT92w4F6ViyYbjoizLTo83tHTHu", } - paginatedParams := client.XRPLPaginatedRequest{ + paginatedParams := client.XRPLPaginatedParams{ Limit: 3, Paginated: true, } @@ -465,18 +465,19 @@ func TestSendRequestPagination(t *testing.T) { assert.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) - pages, err := jsonRpcClient.SendRequestPaginated(&req1, paginatedParams.Limit, paginatedParams.Paginated) + res, err := jsonRpcClient.SendRequestPaginated(&req1, paginatedParams.Limit, paginatedParams.Paginated) assert.NoError(t, err) - // TODO: is this ok to set equal? Is it useful to the user? expectedFirstPage := jsonrpcmodels.JsonRpcResponse{ Result: jsonrpcmodels.AnyJson{ "account": "rf1BiGeXwwQoi8Z2ueFYTEXSwuJYfV2Jpn", "ledger_index": json.Number(strconv.FormatInt(71766343, 10)), "marker": "pageMarker1", }} + + pages := res.GetXRPLPages() firstPage := pages[0] - assert.Equal(t, &expectedFirstPage, firstPage) + assert.Equal(t, expectedFirstPage, firstPage) // unmarshall into specified type acrPages := []account.AccountChannelsResponse{} @@ -506,7 +507,8 @@ func TestSendRequestPagination(t *testing.T) { assert.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) - pages, err := jsonRpcClient.SendRequestPaginated(&req1, 10, false) + res, err := jsonRpcClient.SendRequestPaginated(&req1, 10, false) + pages := res.GetXRPLPages() assert.NoError(t, err) assert.Equal(t, 1, len(pages)) }) @@ -533,7 +535,8 @@ func TestSendRequestPagination(t *testing.T) { assert.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) - pages, err := jsonRpcClient.SendRequestPaginated(&req1, 2, true) + res, err := jsonRpcClient.SendRequestPaginated(&req1, 2, true) + pages := res.GetXRPLPages() assert.NoError(t, err) assert.Equal(t, 2, len(pages)) }) @@ -550,7 +553,8 @@ func TestSendRequestPagination(t *testing.T) { assert.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) - pages, err := jsonRpcClient.SendRequestPaginated(&req1, 0, true) + res, err := jsonRpcClient.SendRequestPaginated(&req1, 0, true) + pages := res.GetXRPLPages() assert.NoError(t, err) assert.Equal(t, 10, len(pages)) }) diff --git a/client/jsonrpc/models/jsonrpc_response.go b/client/jsonrpc/models/jsonrpc_response.go index bb9b0b977..d7f27be0c 100644 --- a/client/jsonrpc/models/jsonrpc_response.go +++ b/client/jsonrpc/models/jsonrpc_response.go @@ -39,7 +39,16 @@ func (r JsonRpcResponse) GetMarker() any { return nil } -// // this will impl the XRPLPaginatedResponse -// type JsonRpcPaginatedResponse struct { -// results []JsonRpcResponse -// } +type JsonRpcPaginationResponse struct { + Pages []JsonRpcResponse +} + +func (r JsonRpcPaginationResponse) GetXRPLPages() []client.XRPLResponse { + + res := make([]client.XRPLResponse, len(r.Pages)) + for i, page := range r.Pages { + res[i] = page + } + + return res +} diff --git a/client/websocket/websocket_client.go b/client/websocket/websocket_client.go index 038ecc9d7..99b319fe3 100644 --- a/client/websocket/websocket_client.go +++ b/client/websocket/websocket_client.go @@ -23,7 +23,8 @@ type WebsocketClient struct { idCounter atomic.Uint32 } -func (c *WebsocketClient) SendRequestPaginated(reqParams client.XRPLRequest, limit int, pagination bool) ([]client.XRPLResponse, error) { +func (c *WebsocketClient) SendRequestPaginated(reqParams client.XRPLPaginatedRequest, limit int, pagination bool) (client.XRPLPaginatedResponse, error) { + // TODO: impl this method return nil, nil } diff --git a/client/websocket/websocket_client_response.go b/client/websocket/websocket_client_response.go index 04768b7fe..039979a90 100644 --- a/client/websocket/websocket_client_response.go +++ b/client/websocket/websocket_client_response.go @@ -47,7 +47,6 @@ func (r *WebSocketClientXrplResponse) CheckError() error { } func (r WebSocketClientXrplResponse) GetMarker() any { - - // TODO: impl this method + // TODO: impl this method for use in pagination method return nil } diff --git a/examples/jsonrpc-client/jsonrpc_client_example.go b/examples/jsonrpc-client/jsonrpc_client_example.go index 436c4cfba..54b3c701f 100644 --- a/examples/jsonrpc-client/jsonrpc_client_example.go +++ b/examples/jsonrpc-client/jsonrpc_client_example.go @@ -17,7 +17,7 @@ func main() { log.Panicln(err) } - paginatedParams := client.XRPLPaginatedRequest{ + paginatedParams := client.XRPLPaginatedParams{ Limit: 3, Paginated: true, } diff --git a/model/client/account/account_info_request.go b/model/client/account/account_info_request.go index eef465ef0..9506ba7d6 100644 --- a/model/client/account/account_info_request.go +++ b/model/client/account/account_info_request.go @@ -16,10 +16,6 @@ type AccountInfoRequest struct { Strict bool `json:"strict,omitempty"` } -func (a *AccountInfoRequest) SetMarker(m any) { - // empty as no marker to populate -} - func (*AccountInfoRequest) Method() string { return "account_info" } diff --git a/model/client/utility/ping_request.go b/model/client/utility/ping_request.go index 48981ed87..d5cd0ce5b 100644 --- a/model/client/utility/ping_request.go +++ b/model/client/utility/ping_request.go @@ -9,6 +9,3 @@ func (*PingRequest) Method() string { func (*PingRequest) Validate() error { return nil } - -func (*PingRequest) SetMarker(m any) { -} From d2e14ef771aa98ee0aa9231cf194819a0f74472a Mon Sep 17 00:00:00 2001 From: bmurphy333 Date: Sun, 17 Sep 2023 13:42:28 +1200 Subject: [PATCH 4/4] chore: updated all assert to require --- client/jsonrpc/jsonrpc_client_test.go | 126 +++++++++--------- .../jsonrpc/models/jsonrpc_response_test.go | 8 +- client/jsonrpc_config_test.go | 18 +-- model/client/account/account_channels_test.go | 4 +- 4 files changed, 78 insertions(+), 78 deletions(-) diff --git a/client/jsonrpc/jsonrpc_client_test.go b/client/jsonrpc/jsonrpc_client_test.go index df2aed999..5f0141941 100644 --- a/client/jsonrpc/jsonrpc_client_test.go +++ b/client/jsonrpc/jsonrpc_client_test.go @@ -11,7 +11,7 @@ import ( "time" jsoniter "github.com/json-iterator/go" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/xyield/xrpl-go/client" jsonrpcmodels "github.com/xyield/xrpl-go/client/jsonrpc/models" "github.com/xyield/xrpl-go/model/client/account" @@ -27,7 +27,7 @@ func TestJsonRpcClientCreation(t *testing.T) { jsonRpcClient := NewJsonRpcClient(cfg) - assert.Equal(t, &JsonRpcClient{Config: cfg}, jsonRpcClient) + require.Equal(t, &JsonRpcClient{Config: cfg}, jsonRpcClient) }) } @@ -55,9 +55,9 @@ func TestCheckForError(t *testing.T) { } bodyBytes, err := CheckForError(res) - assert.NotNil(t, bodyBytes) + require.NotNil(t, bodyBytes) expError := &JsonRpcClientError{ErrorString: "ledgerIndexMalformed"} - assert.Equal(t, expError, err) + require.Equal(t, expError, err) }) t.Run("Error Response with error code", func(t *testing.T) { @@ -71,9 +71,9 @@ func TestCheckForError(t *testing.T) { } bodyBytes, err := CheckForError(res) - assert.NotNil(t, bodyBytes) + require.NotNil(t, bodyBytes) expErrpr := &JsonRpcClientError{ErrorString: "Null Method"} - assert.Equal(t, expErrpr, err) + require.Equal(t, expErrpr, err) }) t.Run("No error Response", func(t *testing.T) { @@ -108,8 +108,8 @@ func TestCheckForError(t *testing.T) { bodyBytes, err := CheckForError(res) - assert.Nil(t, err) - assert.NotNil(t, bodyBytes) + require.Nil(t, err) + require.NotNil(t, bodyBytes) }) } @@ -130,11 +130,11 @@ func TestCreateRequest(t *testing.T) { byteRequest, err := CreateRequest(req) - assert.NoError(t, err) - // assert bytes equal - assert.Equal(t, expectedRequestBytes, byteRequest) - // assert json equal - assert.Equal(t, string(expectedRequestBytes), string(byteRequest)) + require.NoError(t, err) + // require bytes equal + require.Equal(t, expectedRequestBytes, byteRequest) + // require json equal + require.Equal(t, string(expectedRequestBytes), string(byteRequest)) }) t.Run("Create request - no parameters with using pointer declaration", func(t *testing.T) { @@ -147,11 +147,11 @@ func TestCreateRequest(t *testing.T) { byteRequest, err := CreateRequest(req) - assert.NoError(t, err) - // assert bytes equal - assert.Equal(t, expectedRequestBytes, byteRequest) - // assert json equal - assert.Equal(t, string(expectedRequestBytes), string(byteRequest)) + require.NoError(t, err) + // require bytes equal + require.Equal(t, expectedRequestBytes, byteRequest) + // require json equal + require.Equal(t, string(expectedRequestBytes), string(byteRequest)) }) t.Run("Create request - no parameters with struct initialisation", func(t *testing.T) { @@ -165,11 +165,11 @@ func TestCreateRequest(t *testing.T) { byteRequest, err := CreateRequest(req) - assert.NoError(t, err) - // assert bytes equal - assert.Equal(t, expectedRequestBytes, byteRequest) - // assert json equal - assert.Equal(t, string(expectedRequestBytes), string(byteRequest)) + require.NoError(t, err) + // require bytes equal + require.Equal(t, expectedRequestBytes, byteRequest) + // require json equal + require.Equal(t, string(expectedRequestBytes), string(byteRequest)) }) } @@ -189,17 +189,17 @@ func TestSendRequest(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) _, err = jsonRpcClient.SendRequest(req) - assert.NotNil(t, capturedRequest) - assert.NoError(t, err) - assert.Equal(t, "POST", capturedRequest.Method) - assert.Equal(t, "http://testnode/", capturedRequest.URL.String()) - assert.Equal(t, "application/json", capturedRequest.Header.Get("Content-Type")) + require.NotNil(t, capturedRequest) + require.NoError(t, err) + require.Equal(t, "POST", capturedRequest.Method) + require.Equal(t, "http://testnode/", capturedRequest.URL.String()) + require.Equal(t, "application/json", capturedRequest.Header.Get("Content-Type")) }) t.Run("SendRequest - sucessful response", func(t *testing.T) { @@ -228,7 +228,7 @@ func TestSendRequest(t *testing.T) { mc.DoFunc = mockResponse(response, 200, mc) cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) @@ -257,13 +257,13 @@ func TestSendRequest(t *testing.T) { LedgerHash: "27F530E5C93ED5C13994812787C1ED073C822BAEC7597964608F2C049C2ACD2D", } - assert.NoError(t, err) + require.NoError(t, err) - assert.Equal(t, expectedXrplResponse, xrplResponse) + require.Equal(t, expectedXrplResponse, xrplResponse) - assert.Equal(t, expected.Account, channelsResponse.Account) - assert.Equal(t, expected.LedgerIndex, channelsResponse.LedgerIndex) - assert.Equal(t, expected.LedgerHash, channelsResponse.LedgerHash) + require.Equal(t, expected.Account, channelsResponse.Account) + require.Equal(t, expected.LedgerIndex, channelsResponse.LedgerIndex) + require.Equal(t, expected.LedgerHash, channelsResponse.LedgerHash) }) t.Run("SendRequest - error response", func(t *testing.T) { @@ -288,13 +288,13 @@ func TestSendRequest(t *testing.T) { mc.DoFunc = mockResponse(response, 200, mc) cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) _, err = jsonRpcClient.SendRequest(req) - assert.EqualError(t, err, "ledgerIndexMalformed") + require.EqualError(t, err, "ledgerIndexMalformed") }) t.Run("SendRequest - 503 response", func(t *testing.T) { @@ -311,15 +311,15 @@ func TestSendRequest(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) _, err = jsonRpcClient.SendRequest(req) // Check that 3 extra requests were made - assert.Equal(t, 4, mc.RequestCount) - assert.EqualError(t, err, "Server is overloaded, rate limit exceeded") + require.Equal(t, 4, mc.RequestCount) + require.EqualError(t, err, "Server is overloaded, rate limit exceeded") }) @@ -348,7 +348,7 @@ func TestSendRequest(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) @@ -364,12 +364,12 @@ func TestSendRequest(t *testing.T) { } // Check that only 2 extra requests were made - assert.Equal(t, 3, mc.RequestCount) + require.Equal(t, 3, mc.RequestCount) - assert.NoError(t, err) - assert.Equal(t, expected.Account, channelsResponse.Account) - assert.Equal(t, expected.LedgerIndex, channelsResponse.LedgerIndex) - assert.Equal(t, expected.LedgerHash, channelsResponse.LedgerHash) + require.NoError(t, err) + require.Equal(t, expected.Account, channelsResponse.Account) + require.Equal(t, expected.LedgerIndex, channelsResponse.LedgerIndex) + require.Equal(t, expected.LedgerHash, channelsResponse.LedgerHash) }) t.Run("SendRequest - timeout", func(t *testing.T) { req := &account.AccountChannelsRequest{ @@ -384,15 +384,15 @@ func TestSendRequest(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) _, err = jsonRpcClient.SendRequest(req) // Check that the expected timeout error occurred - assert.Error(t, err) - assert.Contains(t, err.Error(), "timeout") + require.Error(t, err) + require.Contains(t, err.Error(), "timeout") }) } @@ -462,11 +462,11 @@ func TestSendRequestPagination(t *testing.T) { return mockResponse(noMarkerResponse, 200, mc)(req) } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) res, err := jsonRpcClient.SendRequestPaginated(&req1, paginatedParams.Limit, paginatedParams.Paginated) - assert.NoError(t, err) + require.NoError(t, err) expectedFirstPage := jsonrpcmodels.JsonRpcResponse{ Result: jsonrpcmodels.AnyJson{ @@ -477,7 +477,7 @@ func TestSendRequestPagination(t *testing.T) { pages := res.GetXRPLPages() firstPage := pages[0] - assert.Equal(t, expectedFirstPage, firstPage) + require.Equal(t, expectedFirstPage, firstPage) // unmarshall into specified type acrPages := []account.AccountChannelsResponse{} @@ -487,12 +487,12 @@ func TestSendRequestPagination(t *testing.T) { var acr account.AccountChannelsResponse err = page.GetResult(&acr) - assert.NoError(t, err) + require.NoError(t, err) acrPages = append(acrPages, acr) } - assert.Equal(t, expectedRes, acrPages) + require.Equal(t, expectedRes, acrPages) }) t.Run("No Pagination", func(t *testing.T) { @@ -504,13 +504,13 @@ func TestSendRequestPagination(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) res, err := jsonRpcClient.SendRequestPaginated(&req1, 10, false) pages := res.GetXRPLPages() - assert.NoError(t, err) - assert.Equal(t, 1, len(pages)) + require.NoError(t, err) + require.Equal(t, 1, len(pages)) }) t.Run("Limit set", func(t *testing.T) { @@ -532,13 +532,13 @@ func TestSendRequestPagination(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) res, err := jsonRpcClient.SendRequestPaginated(&req1, 2, true) pages := res.GetXRPLPages() - assert.NoError(t, err) - assert.Equal(t, 2, len(pages)) + require.NoError(t, err) + require.Equal(t, 2, len(pages)) }) t.Run("Default limit", func(t *testing.T) { @@ -550,12 +550,12 @@ func TestSendRequestPagination(t *testing.T) { } cfg, err := client.NewJsonRpcConfig("http://testnode/", client.WithHttpClient(mc)) - assert.NoError(t, err) + require.NoError(t, err) jsonRpcClient := NewJsonRpcClient(cfg) res, err := jsonRpcClient.SendRequestPaginated(&req1, 0, true) pages := res.GetXRPLPages() - assert.NoError(t, err) - assert.Equal(t, 10, len(pages)) + require.NoError(t, err) + require.Equal(t, 10, len(pages)) }) } diff --git a/client/jsonrpc/models/jsonrpc_response_test.go b/client/jsonrpc/models/jsonrpc_response_test.go index de9dbbd50..ce31ae9f4 100644 --- a/client/jsonrpc/models/jsonrpc_response_test.go +++ b/client/jsonrpc/models/jsonrpc_response_test.go @@ -5,7 +5,7 @@ import ( "strconv" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/xyield/xrpl-go/client" "github.com/xyield/xrpl-go/model/client/account" ) @@ -36,8 +36,8 @@ func TestGetResult(t *testing.T) { var acr account.AccountChannelsResponse err := jr.GetResult(&acr) - assert.NoError(t, err) - assert.Equal(t, expected, acr) + require.NoError(t, err) + require.Equal(t, expected, acr) }) t.Run("throws error for incorrect mapping", func(t *testing.T) { @@ -58,6 +58,6 @@ func TestGetResult(t *testing.T) { var acr account.AccountChannelsResponse err := jr.GetResult(&acr) - assert.Error(t, err) + require.Error(t, err) }) } diff --git a/client/jsonrpc_config_test.go b/client/jsonrpc_config_test.go index 2fe1e2c06..5aa55acb9 100644 --- a/client/jsonrpc_config_test.go +++ b/client/jsonrpc_config_test.go @@ -4,7 +4,7 @@ import ( "net/http" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) type customHttpClient struct{} @@ -21,14 +21,14 @@ func TestConfigCreation(t *testing.T) { req, err := http.NewRequest(http.MethodPost, "http://s1.ripple.com:51234/", nil) req.Header = cfg.Headers - assert.Equal(t, "http://s1.ripple.com:51234/", cfg.Url) - assert.NoError(t, err) + require.Equal(t, "http://s1.ripple.com:51234/", cfg.Url) + require.NoError(t, err) }) t.Run("No port + IP provided", func(t *testing.T) { cfg, err := NewJsonRpcConfig("") - assert.Nil(t, cfg) - assert.EqualError(t, err, "empty port and IP provided") + require.Nil(t, cfg) + require.EqualError(t, err, "empty port and IP provided") }) t.Run("Format root path - add /", func(t *testing.T) { cfg, _ := NewJsonRpcConfig("http://s1.ripple.com:51234") @@ -36,8 +36,8 @@ func TestConfigCreation(t *testing.T) { req, err := http.NewRequest(http.MethodPost, "http://s1.ripple.com:51234/", nil) req.Header = cfg.Headers - assert.Equal(t, "http://s1.ripple.com:51234/", cfg.Url) - assert.NoError(t, err) + require.Equal(t, "http://s1.ripple.com:51234/", cfg.Url) + require.NoError(t, err) }) t.Run("Pass in custom HTTP client", func(t *testing.T) { @@ -49,7 +49,7 @@ func TestConfigCreation(t *testing.T) { "Content-Type": {"application/json"}, } req.Header = cfg.Headers - assert.Equal(t, &JsonRpcConfig{HTTPClient: customHttpClient{}, Url: "http://s1.ripple.com:51234/", Headers: headers}, cfg) - assert.NoError(t, err) + require.Equal(t, &JsonRpcConfig{HTTPClient: customHttpClient{}, Url: "http://s1.ripple.com:51234/", Headers: headers}, cfg) + require.NoError(t, err) }) } diff --git a/model/client/account/account_channels_test.go b/model/client/account/account_channels_test.go index 7fd8b9d19..cdcf59804 100644 --- a/model/client/account/account_channels_test.go +++ b/model/client/account/account_channels_test.go @@ -3,7 +3,7 @@ package account import ( "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/xyield/xrpl-go/model/client/common" "github.com/xyield/xrpl-go/test" ) @@ -72,5 +72,5 @@ func TestValidate(t *testing.T) { err := s.Validate() - assert.EqualError(t, err, "no account ID specified") + require.EqualError(t, err, "no account ID specified") }