From 08406a140dd1c6ad3fc4244e365d7a5df3df03e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 3 Aug 2023 08:07:59 +0200 Subject: [PATCH 01/11] Update staking endpoint with active flag --- nodeclient/apimodels/core.go | 4 +++- nodeclient/apimodels/core_test.go | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/nodeclient/apimodels/core.go b/nodeclient/apimodels/core.go index 59111db72..9d0d3e19f 100644 --- a/nodeclient/apimodels/core.go +++ b/nodeclient/apimodels/core.go @@ -315,8 +315,10 @@ type ( ValidatorStake iotago.BaseToken `serix:"3,mapKey=validatorStake"` // FixedCost is the fixed cost that the validator receives from the total pool reward. FixedCost iotago.Mana `serix:"4,mapKey=fixedCost"` + // Active indicates whether the validator was active recently, and would be considered during committee selection. + Active bool `serix:"5,mapKey=active"` // LatestSupportedProtocolVersion is the latest supported protocol version of the validator. - LatestSupportedProtocolVersion iotago.Version `serix:"5,mapKey=latestSupportedProtocolVersion"` + LatestSupportedProtocolVersion iotago.Version `serix:"6,mapKey=latestSupportedProtocolVersion"` } // AccountStakingListResponse defines the response for the staking REST API call. diff --git a/nodeclient/apimodels/core_test.go b/nodeclient/apimodels/core_test.go index e7629d779..25e7ff273 100644 --- a/nodeclient/apimodels/core_test.go +++ b/nodeclient/apimodels/core_test.go @@ -289,6 +289,7 @@ func Test_AccountStakingListResponse(t *testing.T) { PoolStake: 123, ValidatorStake: 456, FixedCost: 69, + Active: true, LatestSupportedProtocolVersion: 9, }, }, @@ -297,7 +298,7 @@ func Test_AccountStakingListResponse(t *testing.T) { jsonResponse, err := api.JSONEncode(response) require.NoError(t, err) - expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"latestSupportedProtocolVersion\":9}]}" + expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"active\":true,\"latestSupportedProtocolVersion\":9}]}" require.Equal(t, expected, string(jsonResponse)) decoded := new(apimodels.AccountStakingListResponse) From 1170e85bc1a11df7f57588dc739dee0c8b80741e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 3 Aug 2023 08:08:53 +0200 Subject: [PATCH 02/11] Update rewards response to contain actual epoch range --- nodeclient/apimodels/core.go | 8 +++++--- nodeclient/apimodels/core_test.go | 7 ++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/nodeclient/apimodels/core.go b/nodeclient/apimodels/core.go index 9d0d3e19f..207bcccc2 100644 --- a/nodeclient/apimodels/core.go +++ b/nodeclient/apimodels/core.go @@ -328,10 +328,12 @@ type ( // ManaRewardsResponse defines the response for the mana rewards REST API call. ManaRewardsResponse struct { - // EpochIndex is the epoch index for which the mana rewards are returned. - EpochIndex iotago.EpochIndex `serix:"0,mapKey=epochIndex"` + // EpochIndexStart is the starting epoch for range for which the mana rewards are returned. + EpochIndexStart iotago.EpochIndex `serix:"0,mapKey=epochIndexStart"` + // EpochIndexEnd is the ending epoch for range for which the mana rewards are returned. + EpochIndexEnd iotago.EpochIndex `serix:"1,mapKey=epochIndexEnd"` // The amount of totally available rewards the requested output may claim. - Rewards iotago.Mana `serix:"1,mapKey=rewards"` + Rewards iotago.Mana `serix:"2,mapKey=rewards"` } // CommitteeMemberResponse defines the response used in committee and staking response REST API calls. diff --git a/nodeclient/apimodels/core_test.go b/nodeclient/apimodels/core_test.go index 25e7ff273..dd36d13c3 100644 --- a/nodeclient/apimodels/core_test.go +++ b/nodeclient/apimodels/core_test.go @@ -310,14 +310,15 @@ func Test_ManaRewardsResponse(t *testing.T) { api := testAPI() response := &apimodels.ManaRewardsResponse{ - EpochIndex: 123, - Rewards: 456, + EpochIndexStart: 123, + EpochIndexEnd: 133, + Rewards: 456, } jsonResponse, err := api.JSONEncode(response) require.NoError(t, err) - expected := "{\"epochIndex\":\"123\",\"rewards\":\"456\"}" + expected := "{\"epochIndexStart\":\"123\",\"epochIndexEnd\":\"133\",\"rewards\":\"456\"}" require.Equal(t, expected, string(jsonResponse)) decoded := new(apimodels.ManaRewardsResponse) From 10edfa9567d77e4a016ee5253470096ccf542c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Thu, 3 Aug 2023 08:09:56 +0200 Subject: [PATCH 03/11] Add missing client lib functions and tests --- nodeclient/http_api_client.go | 88 ++++++++++++++++++++++ nodeclient/http_api_client_test.go | 117 +++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index 6e84cc787..d49d56b56 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -35,8 +35,40 @@ const ( // GET returns the node info. RouteInfo = "/api/core/v3/info" + // RouteCongestion is the route for getting congestion details for the account. + // GET returns the congestion details for the account. + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. + RouteCongestion = "/api/core/v3/accounts/%s/congestion" + + // RouteRewards is the route for getting the rewards for staking or delegation based on provieded output. + // GET returns the rewards for the output. + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. + RouteRewards = "/api/core/v3/rewards/%s" + + // RouteStaking is the route for getting the information about current validators. + // GET returns the information about current validators. + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. + RouteStaking = "/api/core/v3/staking" + + // RouteStakingAccount is the route for getting an account by its accountID. + // GET returns the account details. + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. + RouteStakingAccount = "/api/core/v3/staking/%s" + + // RouteCommittee is the route for getting the information about current committee. + // GET returns the information about current committee. + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. + RouteCommittee = "/api/core/v3/committee" + // RouteBlockIssuance is the route for getting all needed information for block creation. // GET returns the data needed toa attach block. + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. RouteBlockIssuance = "/api/core/v3/blocks/issuance" // RouteBlock is the route for getting a block by its ID. @@ -64,6 +96,8 @@ const ( // RouteTransactionsIncludedBlockMetadata is the route for getting the block metadata that was first confirmed in the ledger for a given transaction ID. // GET returns block metadata (including info about "promotion/reattachment needed"). + // MIMEApplicationJSON => json. + // MIMEVendorIOTASerializer => bytes. RouteTransactionsIncludedBlockMetadata = "/api/core/v3/transactions/%s/included-block/metadata" // RouteCommitmentByID is the route for getting a commitment by its ID. @@ -321,6 +355,60 @@ func (client *Client) BlockIssuance(ctx context.Context) (*apimodels.IssuanceBlo return res, nil } +func (client *Client) Congestion(ctx context.Context, accountID iotago.AccountID) (*apimodels.CongestionResponse, error) { + res := new(apimodels.CongestionResponse) + query := fmt.Sprintf(RouteCongestion, hexutil.EncodeHex(accountID[:])) + + if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { + return nil, err + } + + return res, nil +} + +func (client *Client) Rewards(ctx context.Context, outputID iotago.OutputID) (*apimodels.ManaRewardsResponse, error) { + res := &apimodels.ManaRewardsResponse{} + query := fmt.Sprintf(RouteRewards, hexutil.EncodeHex(outputID[:])) + if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { + return nil, err + } + + return res, nil +} + +func (client *Client) Staking(ctx context.Context) (*apimodels.AccountStakingListResponse, error) { + res := &apimodels.AccountStakingListResponse{} + if _, err := client.Do(ctx, http.MethodGet, RouteStaking, nil, res); err != nil { + return nil, err + } + + return res, nil +} + +func (client *Client) StakingAccount(ctx context.Context, accountID iotago.AccountID) (*apimodels.ValidatorResponse, error) { + res := &apimodels.ValidatorResponse{} + query := fmt.Sprintf(RouteStakingAccount, hexutil.EncodeHex(accountID[:])) + if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { + return nil, err + } + + return res, nil +} + +func (client *Client) Committee(ctx context.Context, optEpochIndex ...iotago.EpochIndex) (*apimodels.CommitteeResponse, error) { + query := RouteCommittee + if len(optEpochIndex) > 0 { + query += fmt.Sprintf("?epochIndex=%d", optEpochIndex[0]) + } + fmt.Printf("query: %s\n", query) + + res := &apimodels.CommitteeResponse{} + if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { + return nil, err + } + return res, nil +} + // NodeSupportsRoute gets the routes of the node and checks if the given route is enabled. func (client *Client) NodeSupportsRoute(ctx context.Context, route string) (bool, error) { routes, err := client.Routes(ctx) diff --git a/nodeclient/http_api_client_test.go b/nodeclient/http_api_client_test.go index c838db70b..b27ce3af5 100644 --- a/nodeclient/http_api_client_test.go +++ b/nodeclient/http_api_client_test.go @@ -197,6 +197,123 @@ func TestClient_BlockIssuance(t *testing.T) { require.EqualValues(t, originRes, res) } +func TestClient_Congestion(t *testing.T) { + defer gock.Off() + + accID := tpkg.RandAccountID() + + originRes := &apimodels.CongestionResponse{ + SlotIndex: iotago.SlotIndex(20), + Ready: true, + ReferenceManaCost: iotago.Mana(1000), + BlockIssuanceCredits: iotago.BlockIssuanceCredits(1000), + } + + mockGetJSON(fmt.Sprintf(nodeclient.RouteCongestion, accID.ToHex()), 200, originRes) + + nodeAPI := nodeClient(t) + res, err := nodeAPI.Congestion(context.Background(), accID) + require.NoError(t, err) + require.EqualValues(t, originRes, res) +} + +func TestClient_Rewards(t *testing.T) { + defer gock.Off() + + outID := tpkg.RandOutputID(1) + + originRes := &apimodels.ManaRewardsResponse{ + EpochIndexStart: iotago.EpochIndex(20), + EpochIndexEnd: iotago.EpochIndex(30), + Rewards: iotago.Mana(1000), + } + + mockGetJSON(fmt.Sprintf(nodeclient.RouteRewards, outID.ToHex()), 200, originRes) + + nodeAPI := nodeClient(t) + res, err := nodeAPI.Rewards(context.Background(), outID) + require.NoError(t, err) + require.EqualValues(t, originRes, res) +} + +func TestClient_Staking(t *testing.T) { + defer gock.Off() + + originRes := &apimodels.AccountStakingListResponse{Stakers: []*apimodels.ValidatorResponse{ + { + AccountID: tpkg.RandAccountID(), + StakingEpochEnd: iotago.EpochIndex(123), + PoolStake: iotago.BaseToken(100), + ValidatorStake: iotago.BaseToken(10), + FixedCost: iotago.Mana(10), + Active: true, + LatestSupportedProtocolVersion: 1, + }, + { + AccountID: tpkg.RandAccountID(), + StakingEpochEnd: iotago.EpochIndex(124), + PoolStake: iotago.BaseToken(1000), + ValidatorStake: iotago.BaseToken(100), + FixedCost: iotago.Mana(20), + Active: true, + LatestSupportedProtocolVersion: 1, + }, + }} + + mockGetJSON(nodeclient.RouteStaking, 200, originRes) + + nodeAPI := nodeClient(t) + res, err := nodeAPI.Staking(context.Background()) + require.NoError(t, err) + require.EqualValues(t, originRes, res) +} + +func TestClient_StakingByAccountID(t *testing.T) { + defer gock.Off() + + accID := tpkg.RandAccountID() + originRes := &apimodels.ValidatorResponse{ + AccountID: accID, + StakingEpochEnd: iotago.EpochIndex(123), + PoolStake: iotago.BaseToken(100), + ValidatorStake: iotago.BaseToken(10), + FixedCost: iotago.Mana(10), + Active: true, + LatestSupportedProtocolVersion: 1, + } + + mockGetJSON(fmt.Sprintf(nodeclient.RouteStakingAccount, accID.ToHex()), 200, originRes) + + nodeAPI := nodeClient(t) + res, err := nodeAPI.StakingAccount(context.Background(), accID) + require.NoError(t, err) + require.EqualValues(t, originRes, res) +} + +func TestClient_Committee(t *testing.T) { + defer gock.Off() + + originRes := &apimodels.CommitteeResponse{ + EpochIndex: iotago.EpochIndex(123), + TotalStake: 1000_1000, + TotalValidatorStake: 100_000, + Committee: []*apimodels.CommitteeMemberResponse{ + { + AccountID: tpkg.RandAccountID(), + PoolStake: 1000_000, + ValidatorStake: 100_000, + FixedCost: iotago.Mana(100), + }, + }, + } + + mockGetJSON(nodeclient.RouteCommittee, 200, originRes) + nodeAPI := nodeClient(t) + res, err := nodeAPI.Committee(context.Background()) + require.NoError(t, err) + require.EqualValues(t, originRes, res) +} + func TestClient_SubmitBlock(t *testing.T) { defer gock.Off() From be646ab925c68e308d7222584e60ce42b87e2130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 7 Aug 2023 07:52:51 +0200 Subject: [PATCH 04/11] Use pagination for stakers endpoint --- nodeclient/apimodels/core.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/nodeclient/apimodels/core.go b/nodeclient/apimodels/core.go index 207bcccc2..e03ddb8de 100644 --- a/nodeclient/apimodels/core.go +++ b/nodeclient/apimodels/core.go @@ -323,7 +323,10 @@ type ( // AccountStakingListResponse defines the response for the staking REST API call. AccountStakingListResponse struct { - Stakers []*ValidatorResponse `serix:"0,mapKey=stakers"` + Stakers []*ValidatorResponse `serix:"0,mapKey=stakers"` + PageSize uint32 `serix:"1,mapKey=pageSize"` + Coursor uint32 `serix:"2,mapKey=coursor"` + RequestedAt iotago.SlotIndex `serix:"3,mapKey=requestedAt"` } // ManaRewardsResponse defines the response for the mana rewards REST API call. From ef962bfabf811aad79ec8e5473572d569508b715 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 7 Aug 2023 09:19:37 +0200 Subject: [PATCH 05/11] Fix staking response in API encoding unit test --- nodeclient/apimodels/core_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/nodeclient/apimodels/core_test.go b/nodeclient/apimodels/core_test.go index dd36d13c3..95d56b32e 100644 --- a/nodeclient/apimodels/core_test.go +++ b/nodeclient/apimodels/core_test.go @@ -293,12 +293,14 @@ func Test_AccountStakingListResponse(t *testing.T) { LatestSupportedProtocolVersion: 9, }, }, + Coursor: 0, + PageSize: 50, + RequestedAt: 1, } jsonResponse, err := api.JSONEncode(response) require.NoError(t, err) - - expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"active\":true,\"latestSupportedProtocolVersion\":9}]}" + expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"active\":true,\"latestSupportedProtocolVersion\":9}],\"pageSize\":50,\"coursor\":0,\"requestedAt\":\"1\"}" require.Equal(t, expected, string(jsonResponse)) decoded := new(apimodels.AccountStakingListResponse) From 62be49e25b5ac27c5fe9b2eafea8325462f3337c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 7 Aug 2023 09:29:20 +0200 Subject: [PATCH 06/11] Silence the body close lint errors --- nodeclient/http_api_client.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index d49d56b56..4d3595ea0 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -358,7 +358,7 @@ func (client *Client) BlockIssuance(ctx context.Context) (*apimodels.IssuanceBlo func (client *Client) Congestion(ctx context.Context, accountID iotago.AccountID) (*apimodels.CongestionResponse, error) { res := new(apimodels.CongestionResponse) query := fmt.Sprintf(RouteCongestion, hexutil.EncodeHex(accountID[:])) - + //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { return nil, err } @@ -369,6 +369,7 @@ func (client *Client) Congestion(ctx context.Context, accountID iotago.AccountID func (client *Client) Rewards(ctx context.Context, outputID iotago.OutputID) (*apimodels.ManaRewardsResponse, error) { res := &apimodels.ManaRewardsResponse{} query := fmt.Sprintf(RouteRewards, hexutil.EncodeHex(outputID[:])) + //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { return nil, err } @@ -378,6 +379,7 @@ func (client *Client) Rewards(ctx context.Context, outputID iotago.OutputID) (*a func (client *Client) Staking(ctx context.Context) (*apimodels.AccountStakingListResponse, error) { res := &apimodels.AccountStakingListResponse{} + //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, RouteStaking, nil, res); err != nil { return nil, err } @@ -388,6 +390,7 @@ func (client *Client) Staking(ctx context.Context) (*apimodels.AccountStakingLis func (client *Client) StakingAccount(ctx context.Context, accountID iotago.AccountID) (*apimodels.ValidatorResponse, error) { res := &apimodels.ValidatorResponse{} query := fmt.Sprintf(RouteStakingAccount, hexutil.EncodeHex(accountID[:])) + //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { return nil, err } @@ -403,6 +406,7 @@ func (client *Client) Committee(ctx context.Context, optEpochIndex ...iotago.Epo fmt.Printf("query: %s\n", query) res := &apimodels.CommitteeResponse{} + //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { return nil, err } From 4a64c337200e2bab3f257a4a1f4c04c8a80e95f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 7 Aug 2023 09:31:28 +0200 Subject: [PATCH 07/11] Fix lint, no line before return --- nodeclient/http_api_client.go | 1 + 1 file changed, 1 insertion(+) diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index 4d3595ea0..5637ef832 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -410,6 +410,7 @@ func (client *Client) Committee(ctx context.Context, optEpochIndex ...iotago.Epo if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { return nil, err } + return res, nil } From 91d81af0389dad8f9b90c590135a8f714d5cc200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 7 Aug 2023 13:44:02 +0200 Subject: [PATCH 08/11] Apply review suggestions, make cursor string --- nodeclient/apimodels/core.go | 11 +++++------ nodeclient/http_api_client.go | 20 ++++++++++---------- nodeclient/http_api_client_test.go | 4 ++-- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/nodeclient/apimodels/core.go b/nodeclient/apimodels/core.go index e03ddb8de..3938f081a 100644 --- a/nodeclient/apimodels/core.go +++ b/nodeclient/apimodels/core.go @@ -323,17 +323,16 @@ type ( // AccountStakingListResponse defines the response for the staking REST API call. AccountStakingListResponse struct { - Stakers []*ValidatorResponse `serix:"0,mapKey=stakers"` - PageSize uint32 `serix:"1,mapKey=pageSize"` - Coursor uint32 `serix:"2,mapKey=coursor"` - RequestedAt iotago.SlotIndex `serix:"3,mapKey=requestedAt"` + Stakers []*ValidatorResponse `serix:"0,mapKey=stakers"` + PageSize uint32 `serix:"1,mapKey=pageSize"` + Cursor string `serix:"2,mapKey=cursor,omitempty"` } // ManaRewardsResponse defines the response for the mana rewards REST API call. ManaRewardsResponse struct { - // EpochIndexStart is the starting epoch for range for which the mana rewards are returned. + // EpochIndexStart is the starting epoch for the range for which the mana rewards are returned. EpochIndexStart iotago.EpochIndex `serix:"0,mapKey=epochIndexStart"` - // EpochIndexEnd is the ending epoch for range for which the mana rewards are returned. + // EpochIndexEnd is the ending epoch for the range for which the mana rewards are returned. EpochIndexEnd iotago.EpochIndex `serix:"1,mapKey=epochIndexEnd"` // The amount of totally available rewards the requested output may claim. Rewards iotago.Mana `serix:"2,mapKey=rewards"` diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index 5637ef832..54947ddc5 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -41,26 +41,26 @@ const ( // MIMEVendorIOTASerializer => bytes. RouteCongestion = "/api/core/v3/accounts/%s/congestion" - // RouteRewards is the route for getting the rewards for staking or delegation based on provieded output. + // RouteRewards is the route for getting the rewards for staking or delegation based on the provided output. // GET returns the rewards for the output. // MIMEApplicationJSON => json. // MIMEVendorIOTASerializer => bytes. RouteRewards = "/api/core/v3/rewards/%s" - // RouteStaking is the route for getting the information about current validators. - // GET returns the information about current validators. + // RouteValidators is the route for getting the information about current registered validators. + // GET returns the paginated information about about registered validators. // MIMEApplicationJSON => json. // MIMEVendorIOTASerializer => bytes. - RouteStaking = "/api/core/v3/staking" + RouteValidators = "/api/core/v3/validators" - // RouteStakingAccount is the route for getting an account by its accountID. + // RouteValidatorsAccount is the route for getting validator by its accountID. // GET returns the account details. // MIMEApplicationJSON => json. // MIMEVendorIOTASerializer => bytes. - RouteStakingAccount = "/api/core/v3/staking/%s" + RouteValidatorsAccount = "/api/core/v3/validators/%s" - // RouteCommittee is the route for getting the information about current committee. - // GET returns the information about current committee. + // RouteCommittee is the route for getting the information about the current committee. + // GET returns the information about the current committee. // MIMEApplicationJSON => json. // MIMEVendorIOTASerializer => bytes. RouteCommittee = "/api/core/v3/committee" @@ -380,7 +380,7 @@ func (client *Client) Rewards(ctx context.Context, outputID iotago.OutputID) (*a func (client *Client) Staking(ctx context.Context) (*apimodels.AccountStakingListResponse, error) { res := &apimodels.AccountStakingListResponse{} //nolint:bodyclose - if _, err := client.Do(ctx, http.MethodGet, RouteStaking, nil, res); err != nil { + if _, err := client.Do(ctx, http.MethodGet, RouteValidators, nil, res); err != nil { return nil, err } @@ -389,7 +389,7 @@ func (client *Client) Staking(ctx context.Context) (*apimodels.AccountStakingLis func (client *Client) StakingAccount(ctx context.Context, accountID iotago.AccountID) (*apimodels.ValidatorResponse, error) { res := &apimodels.ValidatorResponse{} - query := fmt.Sprintf(RouteStakingAccount, hexutil.EncodeHex(accountID[:])) + query := fmt.Sprintf(RouteValidatorsAccount, hexutil.EncodeHex(accountID[:])) //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, query, nil, res); err != nil { return nil, err diff --git a/nodeclient/http_api_client_test.go b/nodeclient/http_api_client_test.go index dcdac8db8..362013345 100644 --- a/nodeclient/http_api_client_test.go +++ b/nodeclient/http_api_client_test.go @@ -260,7 +260,7 @@ func TestClient_Staking(t *testing.T) { }, }} - mockGetJSON(nodeclient.RouteStaking, 200, originRes) + mockGetJSON(nodeclient.RouteValidators, 200, originRes) nodeAPI := nodeClient(t) res, err := nodeAPI.Staking(context.Background()) @@ -282,7 +282,7 @@ func TestClient_StakingByAccountID(t *testing.T) { LatestSupportedProtocolVersion: 1, } - mockGetJSON(fmt.Sprintf(nodeclient.RouteStakingAccount, accID.ToHex()), 200, originRes) + mockGetJSON(fmt.Sprintf(nodeclient.RouteValidatorsAccount, accID.ToHex()), 200, originRes) nodeAPI := nodeClient(t) res, err := nodeAPI.StakingAccount(context.Background(), accID) From d24681b1c9014de3d47e0c531e5f4eff270ddce8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Mon, 7 Aug 2023 13:53:23 +0200 Subject: [PATCH 09/11] Fix test after renaming --- nodeclient/apimodels/core_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/nodeclient/apimodels/core_test.go b/nodeclient/apimodels/core_test.go index 9e17b46a9..699a6b39e 100644 --- a/nodeclient/apimodels/core_test.go +++ b/nodeclient/apimodels/core_test.go @@ -293,14 +293,13 @@ func Test_AccountStakingListResponse(t *testing.T) { LatestSupportedProtocolVersion: 9, }, }, - Coursor: 0, - PageSize: 50, - RequestedAt: 1, + Cursor: "0,1", + PageSize: 50, } jsonResponse, err := api.JSONEncode(response) require.NoError(t, err) - expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"active\":true,\"latestSupportedProtocolVersion\":9}],\"pageSize\":50,\"coursor\":0,\"requestedAt\":\"1\"}" + expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"active\":true,\"latestSupportedProtocolVersion\":9}],\"pageSize\":50,\"cursor\":\"0,1\"}" require.Equal(t, expected, string(jsonResponse)) decoded := new(apimodels.AccountStakingListResponse) From 1e953b18af0b4e1b5c48fe29a2d9a7ec8618a3d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Tue, 8 Aug 2023 15:27:44 +0200 Subject: [PATCH 10/11] Start block type versioning from 0 --- block.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block.go b/block.go index 5cfd339fe..81863086d 100644 --- a/block.go +++ b/block.go @@ -31,8 +31,8 @@ const ( type BlockType byte const ( - BlockTypeBasic BlockType = 1 - BlockTypeValidation BlockType = 2 + BlockTypeBasic BlockType = 0 + BlockTypeValidation BlockType = 1 ) // EmptyBlockID returns an empty BlockID. From 7d5405cf09a211e48176b2ab242ec7c384554243 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daria=20Dziuba=C5=82towska?= Date: Wed, 9 Aug 2023 13:21:03 +0200 Subject: [PATCH 11/11] Align namings around validators endpoint --- nodeclient/apimodels/core.go | 20 ++++++++++---------- nodeclient/apimodels/core_test.go | 12 ++++++------ nodeclient/http_api_client.go | 5 +++-- nodeclient/http_api_client_test.go | 12 ++++++------ 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/nodeclient/apimodels/core.go b/nodeclient/apimodels/core.go index 3938f081a..5f49ec8b1 100644 --- a/nodeclient/apimodels/core.go +++ b/nodeclient/apimodels/core.go @@ -321,20 +321,20 @@ type ( LatestSupportedProtocolVersion iotago.Version `serix:"6,mapKey=latestSupportedProtocolVersion"` } - // AccountStakingListResponse defines the response for the staking REST API call. - AccountStakingListResponse struct { - Stakers []*ValidatorResponse `serix:"0,mapKey=stakers"` - PageSize uint32 `serix:"1,mapKey=pageSize"` - Cursor string `serix:"2,mapKey=cursor,omitempty"` + // ValidatorsResponse defines the response for the staking REST API call. + ValidatorsResponse struct { + Validators []*ValidatorResponse `serix:"0,mapKey=stakers"` + PageSize uint32 `serix:"1,mapKey=pageSize"` + Cursor string `serix:"2,mapKey=cursor,omitempty"` } // ManaRewardsResponse defines the response for the mana rewards REST API call. ManaRewardsResponse struct { - // EpochIndexStart is the starting epoch for the range for which the mana rewards are returned. - EpochIndexStart iotago.EpochIndex `serix:"0,mapKey=epochIndexStart"` - // EpochIndexEnd is the ending epoch for the range for which the mana rewards are returned. - EpochIndexEnd iotago.EpochIndex `serix:"1,mapKey=epochIndexEnd"` - // The amount of totally available rewards the requested output may claim. + // EpochStart is the starting epoch for the range for which the mana rewards are returned. + EpochStart iotago.EpochIndex `serix:"0,mapKey=epochIndexStart"` + // EpochEnd is the ending epoch for the range for which the mana rewards are returned, also the decay is only applied up to this point. + EpochEnd iotago.EpochIndex `serix:"1,mapKey=epochIndexEnd"` + // The amount of totally available rewards the requested output may claim, decayed up to EpochEnd (including). Rewards iotago.Mana `serix:"2,mapKey=rewards"` } diff --git a/nodeclient/apimodels/core_test.go b/nodeclient/apimodels/core_test.go index 699a6b39e..0dda1d569 100644 --- a/nodeclient/apimodels/core_test.go +++ b/nodeclient/apimodels/core_test.go @@ -281,8 +281,8 @@ func Test_CongestionResponse(t *testing.T) { func Test_AccountStakingListResponse(t *testing.T) { api := testAPI() - response := &apimodels.AccountStakingListResponse{ - Stakers: []*apimodels.ValidatorResponse{ + response := &apimodels.ValidatorsResponse{ + Validators: []*apimodels.ValidatorResponse{ { AccountID: iotago.AccountID{0xFF}, StakingEpochEnd: 0, @@ -302,7 +302,7 @@ func Test_AccountStakingListResponse(t *testing.T) { expected := "{\"stakers\":[{\"accountId\":\"0xff00000000000000000000000000000000000000000000000000000000000000\",\"stakingEpochEnd\":\"0\",\"poolStake\":\"123\",\"validatorStake\":\"456\",\"fixedCost\":\"69\",\"active\":true,\"latestSupportedProtocolVersion\":9}],\"pageSize\":50,\"cursor\":\"0,1\"}" require.Equal(t, expected, string(jsonResponse)) - decoded := new(apimodels.AccountStakingListResponse) + decoded := new(apimodels.ValidatorsResponse) require.NoError(t, api.JSONDecode(jsonResponse, decoded)) require.EqualValues(t, response, decoded) } @@ -311,9 +311,9 @@ func Test_ManaRewardsResponse(t *testing.T) { api := testAPI() response := &apimodels.ManaRewardsResponse{ - EpochIndexStart: 123, - EpochIndexEnd: 133, - Rewards: 456, + EpochStart: 123, + EpochEnd: 133, + Rewards: 456, } jsonResponse, err := api.JSONEncode(response) diff --git a/nodeclient/http_api_client.go b/nodeclient/http_api_client.go index 54947ddc5..f59751cf4 100644 --- a/nodeclient/http_api_client.go +++ b/nodeclient/http_api_client.go @@ -42,6 +42,7 @@ const ( RouteCongestion = "/api/core/v3/accounts/%s/congestion" // RouteRewards is the route for getting the rewards for staking or delegation based on the provided output. + // Rewards are decayed up to returned epochEnd index. // GET returns the rewards for the output. // MIMEApplicationJSON => json. // MIMEVendorIOTASerializer => bytes. @@ -377,8 +378,8 @@ func (client *Client) Rewards(ctx context.Context, outputID iotago.OutputID) (*a return res, nil } -func (client *Client) Staking(ctx context.Context) (*apimodels.AccountStakingListResponse, error) { - res := &apimodels.AccountStakingListResponse{} +func (client *Client) Validators(ctx context.Context) (*apimodels.ValidatorsResponse, error) { + res := &apimodels.ValidatorsResponse{} //nolint:bodyclose if _, err := client.Do(ctx, http.MethodGet, RouteValidators, nil, res); err != nil { return nil, err diff --git a/nodeclient/http_api_client_test.go b/nodeclient/http_api_client_test.go index 362013345..f751fb210 100644 --- a/nodeclient/http_api_client_test.go +++ b/nodeclient/http_api_client_test.go @@ -223,9 +223,9 @@ func TestClient_Rewards(t *testing.T) { outID := tpkg.RandOutputID(1) originRes := &apimodels.ManaRewardsResponse{ - EpochIndexStart: iotago.EpochIndex(20), - EpochIndexEnd: iotago.EpochIndex(30), - Rewards: iotago.Mana(1000), + EpochStart: iotago.EpochIndex(20), + EpochEnd: iotago.EpochIndex(30), + Rewards: iotago.Mana(1000), } mockGetJSON(fmt.Sprintf(nodeclient.RouteRewards, outID.ToHex()), 200, originRes) @@ -236,10 +236,10 @@ func TestClient_Rewards(t *testing.T) { require.EqualValues(t, originRes, res) } -func TestClient_Staking(t *testing.T) { +func TestClient_Validators(t *testing.T) { defer gock.Off() - originRes := &apimodels.AccountStakingListResponse{Stakers: []*apimodels.ValidatorResponse{ + originRes := &apimodels.ValidatorsResponse{Validators: []*apimodels.ValidatorResponse{ { AccountID: tpkg.RandAccountID(), StakingEpochEnd: iotago.EpochIndex(123), @@ -263,7 +263,7 @@ func TestClient_Staking(t *testing.T) { mockGetJSON(nodeclient.RouteValidators, 200, originRes) nodeAPI := nodeClient(t) - res, err := nodeAPI.Staking(context.Background()) + res, err := nodeAPI.Validators(context.Background()) require.NoError(t, err) require.EqualValues(t, originRes, res) }