Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement missing endpoints #6

Merged
merged 12 commits into from
Jan 30, 2024
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "concordium-grpc-api"]
path = concordium-grpc-api
url = [email protected]:Concordium/concordium-grpc-api.git
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Changelog

## Unreleased changes
- Added support for GRPC V2 `GetWinningBakersEpoch` for getting a list of bakers that won the lottery in a particular historical epoch. Only available when querying a node with version at least 6.1.
- Added support for GRPC V2 `GetFirstBlockEpoch` for getting the block hash of the first finalized block in a specified epoch. Only available when querying a node with version at least 6.1.
- Added support for GRPC V2 `GetBakerEarliestWinTime` for getting the projected earliest time at which a particular baker will be required to bake a block. Only available when querying a node with version at least 6.1.
- Added support for GRPC V2 `GetBakerRewardPeriodInfo` for getting all the bakers in the reward period of a block. Only available when querying a node with version at least 6.1.
- Added support for GRPC V2 `GetBlockCertificates` for retrieving certificates for a block supporting ConcordiumBF, i.e. a node with at least version 6.1.
1 change: 1 addition & 0 deletions concordium-grpc-api
Submodule concordium-grpc-api added at ffd3be
28 changes: 28 additions & 0 deletions v2/examples/getbakerearliestwintime/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

import (
"context"
"fmt"
"log"

v2 "github.com/Concordium/concordium-go-sdk/v2"
"github.com/Concordium/concordium-go-sdk/v2/pb"
)

// This example retrieves and prints projected earliest wintime of a baker.
func main() {
client, err := v2.NewClient(v2.Config{NodeAddress: "node.testnet.concordium.com:20000"})
if err != nil {
log.Fatalf("Failed to instantiate client, err: %v", err)
}

// sending empty context, can also use any other context instead.
resp, err := client.GetBakerEarliestWinTime(context.TODO(), &pb.BakerId{
Value: 1,
})
if err != nil {
log.Fatalf("failed to get wintime, err: %v", err)
}

fmt.Println("wintime: ", resp)
}
36 changes: 36 additions & 0 deletions v2/examples/getbakersrewardperiod/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
"context"
"fmt"
"io"
"log"

v2 "github.com/Concordium/concordium-go-sdk/v2"
)

// This example retrieves and prints the info of the bakers in the reward period of a block.
func main() {
client, err := v2.NewClient(v2.Config{NodeAddress: "node.testnet.concordium.com:20000"})
if err != nil {
log.Fatalf("Failed to instantiate client, err: %v", err)
}

// sending empty context, can also use any other context instead.
stream, err := client.GetBakersRewardPeriod(context.TODO(), v2.BlockHashInputBest{})
if err != nil {
log.Fatalf("failed to get BakerRewardPeriodInfos, err: %v", err)
}

for err == nil {
bakerRewardPeriodInfo, err := stream.Recv()
if err != nil {
if err == io.EOF {
// All BakerRewardPeriodInfo recieved.
break
}
log.Fatalf("Could not receive BakerRewardPeriodInfo, err: %v", err)
}
fmt.Println("BakerRewardPeriodInfo: ", bakerRewardPeriodInfo)
}
}
25 changes: 25 additions & 0 deletions v2/examples/getblockcertificates/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package main

import (
"context"
"fmt"
"log"

v2 "github.com/Concordium/concordium-go-sdk/v2"
)

// This example retrieves and prints the blockcertificates of a non-genesis block.
func main() {
client, err := v2.NewClient(v2.Config{NodeAddress: "node.testnet.concordium.com:20000"})
if err != nil {
log.Fatalf("Failed to instantiate client, err: %v", err)
}

// sending empty context, can also use any other context instead.
resp, err := client.GetBlockCertificates(context.TODO(), v2.BlockHashInputBest{})
if err != nil {
log.Fatalf("failed to get certificates, err: %v", err)
}

fmt.Println("certificates: ", resp)
}
2 changes: 1 addition & 1 deletion v2/examples/getconsensusinfo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"fmt"
"log"

"github.com/Concordium/concordium-go-sdk/v2"
v2 "github.com/Concordium/concordium-go-sdk/v2"
)

// in this example we receive and print consensus info.
Expand Down
27 changes: 27 additions & 0 deletions v2/examples/getfirstblockepoch/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

import (
"context"
"fmt"
"log"

v2 "github.com/Concordium/concordium-go-sdk/v2"
)

// This example retrieves and prints the block hash of the first finalized block in a specific epoch.
func main() {
client, err := v2.NewClient(v2.Config{NodeAddress: "node.testnet.concordium.com:20000"})
if err != nil {
log.Fatalf("Failed to instantiate client, err: %v", err)
}

// sending empty context, can also use any other context instead.
resp, err := client.GetFirstBlockEpoch(context.TODO(), v2.EpochRequestBlockHash{
BlockHash: v2.BlockHashInputLastFinal{},
})
if err != nil {
log.Fatalf("failed to get first block, err: %v", err)
}

fmt.Println("hash: ", resp)
}
39 changes: 39 additions & 0 deletions v2/examples/getwinningbakersepoch/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"context"
"fmt"
"io"
"log"

v2 "github.com/Concordium/concordium-go-sdk/v2"
)

// This example retrieves and prints the bakers that won the lottery in a particular historical epoch.
func main() {
client, err := v2.NewClient(v2.Config{NodeAddress: "node.testnet.concordium.com:20000"})
if err != nil {
log.Fatalf("Failed to instantiate client, err: %v", err)
}

// sending empty context, can also use any other context instead.
stream, err := client.GetWinningBakersEpoch(context.TODO(), v2.EpochRequestRelativeEpoch{
GenesisIndex: v2.GenesisIndex{Value: 3},
Epoch: v2.Epoch{Value: 5},
})
if err != nil {
log.Fatalf("failed to get winning bakers, err: %v", err)
}

for err == nil {
winningBaker, err := stream.Recv()
if err != nil {
if err == io.EOF {
// All WinningBakers recieved.
break
}
log.Fatalf("Could not receive winning baker, err: %v", err)
}
fmt.Println("Winning baker: ", winningBaker)
}
}
30 changes: 30 additions & 0 deletions v2/getbakerearliestwintime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package v2

import (
"context"

"github.com/Concordium/concordium-go-sdk/v2/pb"
)

// GetBakerEarliestWinTime retrieves the projected earliest time at which a particular baker will be required to bake a block.
//
// - If the baker is not a baker for the current reward period, this returns a timestamp at the start of the next reward period.
// - If the baker is a baker for the current reward period, the earliest win time is projected from the current round forwward,
// assuming that each round after the last finalixed round will take the minimum block time. (If blocks take longer, or timeouts occur,
// the actual time may be later, and the reported time in subsequent queries may reflect this.)
// - At the end of an epoch (or if the baker is not projected to bake before the end of the epoch)
// the earliest win time for a (current) baker will be projected as the start of the next epoch.
// This is because the seed for the leader election is updated at the epoch boundary,
// and so the winners cannot be predicted beyond that.
//
// Note that in some circumstances the returned timestamp can be in the past, especially at the end of an epoch.
//
// This endpoint is only supported for protocol version 6 and onwards.
func (c *Client) GetBakerEarliestWinTime(ctx context.Context, req *pb.BakerId) (_ Timestamp, err error) {
timestamp, err := c.GrpcClient.GetBakerEarliestWinTime(ctx, req)
if err != nil {
return Timestamp{}, err
}

return parseTimestamp(timestamp), nil
}
17 changes: 17 additions & 0 deletions v2/getbakersrewardperiod.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package v2

import (
"context"
)

// GetBakersRewardPeriod retrieves all bakers in the reward period of a block.
//
// This endpoint is only supported for protocol version 6 and onwards.
func (c *Client) GetBakersRewardPeriod(ctx context.Context, req isBlockHashInput) (_ BakerRewardPeriodInfoStream, err error) {
stream, err := c.GrpcClient.GetBakersRewardPeriod(ctx, convertBlockHashInput(req))
if err != nil {
return BakerRewardPeriodInfoStream{}, err
}

return BakerRewardPeriodInfoStream{stream: stream}, nil
}
20 changes: 20 additions & 0 deletions v2/getblockcertificates.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package v2

import (
"context"

"github.com/Concordium/concordium-go-sdk/v2/pb"
)

// GetBlockCertificates returns the quorum certificate, a timeout certificate (if present) and epoch finalization certificate (if present)
// for a non-genesis block.
//
// This endpoint is only supported for protocol version 6 and onwards.
func (c *Client) GetBlockCertificates(ctx context.Context, req isBlockHashInput) (_ *pb.BlockCertificates, err error) {
certificates, err := c.GrpcClient.GetBlockCertificates(ctx, convertBlockHashInput(req))
if err != nil {
return &pb.BlockCertificates{}, err
}

return certificates, nil
}
29 changes: 29 additions & 0 deletions v2/getfirstblockepoch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package v2

import (
"context"
)

// GetFirstBlockEpoch retrieves the block hash of the first finalized block in a specified epoch.
//
// The following errors are possible:
// - `NOT_FOUND` if the query specifies an unknown block.
// - `UNAVAILABLE` if the query is for an epoch that is not finalized in the current genesis index, or is for a future genesis index.
// - `INVALID_ARGUMENT` if the query is for an epoch with no finalized blocks for a past genesis index.
// - `INVALID_ARGUMENT` if the input `EpochRequest` is malformed.
// - `UNIMPLEMENTED` if the endpoint is disabled on the node.
//
// This endpoint is only supported for protocol version 6 and onwards.
func (c *Client) GetFirstBlockEpoch(ctx context.Context, req isEpochRequest) (_ BlockHash, err error) {
resp, err := c.GrpcClient.GetFirstBlockEpoch(ctx, convertEpochRequest(req))
if err != nil {
return BlockHash{}, err
}

res, err := parseBlockHash(resp)
if err != nil {
return BlockHash{}, err
}

return res, nil
}
29 changes: 29 additions & 0 deletions v2/getwinningbakersepoch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package v2

import (
"context"
)

// GetWinningBakersEpoch retrieves the list of bakers that won the lottery in a particular historical epoch
// (i.e. the last finalized block is in a later epoch). This lists the winners for each round in the
// epoch, starting from the round after the last block in the previous epoch, running to
// the round before the first block in the next epoch. It also indicates if a block in each
// round was included in the finalized chain.
//
// The following error cases are possible:
// - `NOT_FOUND` if the query specifies an unknown block.
// - `UNAVAILABLE` if the query is for an epoch that is not finalized in the current genesis index, or is for a future genesis index.
// - `INVALID_ARGUMENT` if the query is for an epoch that is not finalized for a past genesis index.
// - `INVALID_ARGUMENT` if the query is for a genesis index at consensus version 0.
// - `INVALID_ARGUMENT` if the input `EpochRequest` is malformed.
// - `UNIMPLEMENTED` if the endpoint is disabled on the node.
//
// This endpoint is only supported for protocol version 6 and onwards.
func (c *Client) GetWinningBakersEpoch(ctx context.Context, req isEpochRequest) (_ WinningBakerStream, err error) {
stream, err := c.GrpcClient.GetWinningBakersEpoch(ctx, convertEpochRequest(req))
if err != nil {
return WinningBakerStream{}, err
}

return WinningBakerStream{stream: stream}, nil
}
Loading