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

Add GetFullCollectionById endpoint #754

8 changes: 8 additions & 0 deletions access/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,14 @@ func (c *Client) GetCollection(ctx context.Context, colID flow.Identifier) (*flo
return c.grpc.GetCollection(ctx, colID)
}

func (c *Client) GetCollectionByID(ctx context.Context, id flow.Identifier) (*flow.Collection, error) {
return c.grpc.GetLightCollectionByID(ctx, id)
}

func (c *Client) GetFullCollectionByID(ctx context.Context, id flow.Identifier) (*flow.FullCollection, error) {
return c.grpc.GetFullCollectionByID(ctx, id)
}

func (c *Client) SendTransaction(ctx context.Context, tx flow.Transaction) error {
return c.grpc.SendTransaction(ctx, tx)
}
Expand Down
30 changes: 30 additions & 0 deletions access/grpc/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,21 @@ func CollectionToMessage(c flow.Collection) *entities.Collection {
}
}

func FullCollectionToTransactionsMessage(tx flow.FullCollection) ([]*entities.Transaction, error) {
var convertedTxs []*entities.Transaction

for _, tx := range tx.Transactions {
convertedTx, err := TransactionToMessage(*tx)
if err != nil {
return nil, err
}

convertedTxs = append(convertedTxs, convertedTx)
}

return convertedTxs, nil
}

func MessageToCollection(m *entities.Collection) (flow.Collection, error) {
if m == nil {
return flow.Collection{}, ErrEmptyMessage
Expand All @@ -284,6 +299,21 @@ func MessageToCollection(m *entities.Collection) (flow.Collection, error) {
}, nil
}

func MessageToFullCollection(m []*entities.Transaction) (flow.FullCollection, error) {
var collection flow.FullCollection

for _, tx := range m {
convertedTx, err := MessageToTransaction(tx)
if err != nil {
return flow.FullCollection{}, err
}

collection.Transactions = append(collection.Transactions, &convertedTx)
}

return collection, nil
}

func CollectionGuaranteeToMessage(g flow.CollectionGuarantee) *entities.CollectionGuarantee {
return &entities.CollectionGuarantee{
CollectionId: g.CollectionID.Bytes(),
Expand Down
2 changes: 1 addition & 1 deletion access/grpc/convert/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func TestConvert_CadenceValue(t *testing.T) {
}

func TestConvert_Collection(t *testing.T) {
colA := test.CollectionGenerator().New()
colA := test.LightCollectionGenerator().New()

msg := CollectionToMessage(*colA)

Expand Down
44 changes: 44 additions & 0 deletions access/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,50 @@ func (c *BaseClient) GetCollection(
return &result, nil
}

func (c *BaseClient) GetLightCollectionByID(
ctx context.Context,
id flow.Identifier,
opts ...grpc.CallOption,
) (*flow.Collection, error) {
req := &access.GetCollectionByIDRequest{
Id: id.Bytes(),
}

res, err := c.rpcClient.GetCollectionByID(ctx, req, opts...)
if err != nil {
return nil, newRPCError(err)
}

result, err := convert.MessageToCollection(res.GetCollection())
if err != nil {
return nil, newMessageToEntityError(entityCollection, err)
}

return &result, nil
}

func (c *BaseClient) GetFullCollectionByID(
ctx context.Context,
id flow.Identifier,
opts ...grpc.CallOption,
) (*flow.FullCollection, error) {
req := &access.GetFullCollectionByIDRequest{
Id: id.Bytes(),
}

res, err := c.rpcClient.GetFullCollectionByID(ctx, req, opts...)
if err != nil {
return nil, newRPCError(err)
}

result, err := convert.MessageToFullCollection(res.GetTransactions())
if err != nil {
return nil, newMessageToEntityError(entityCollection, err)
}

return &result, nil
}

func (c *BaseClient) SendTransaction(
ctx context.Context,
tx flow.Transaction,
Expand Down
40 changes: 39 additions & 1 deletion access/grpc/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ func TestClient_GetBlockByHeight(t *testing.T) {
}

func TestClient_GetCollection(t *testing.T) {
cols := test.CollectionGenerator()
cols := test.LightCollectionGenerator()
ids := test.IdentifierGenerator()

t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
Expand Down Expand Up @@ -417,6 +417,44 @@ func TestClient_GetCollection(t *testing.T) {
}))
}

func TestClient_GetFullCollectionById(t *testing.T) {
collections := test.FullCollectionGenerator()
ids := test.IdentifierGenerator()

t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
expectedCollection := collections.New()
txs, err := convert.FullCollectionToTransactionsMessage(*expectedCollection)
require.NoError(t, err)

response := &access.FullCollectionResponse{
Transactions: txs,
}

rpc.
On("GetFullCollectionByID", ctx, mock.Anything).
Return(response, nil)

id := ids.New()
actualCollection, err := c.GetFullCollectionByID(ctx, id)
require.NoError(t, err)

require.Equal(t, expectedCollection, actualCollection)

}))

t.Run("Not found error", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
rpc.
On("GetFullCollectionByID", ctx, mock.Anything).
Return(nil, errNotFound)

id := ids.New()
col, err := c.GetFullCollectionByID(ctx, id)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Nil(t, col)
}))
}

func TestClient_SendTransaction(t *testing.T) {
transactions := test.TransactionGenerator()

Expand Down
2 changes: 1 addition & 1 deletion access/http/internal/unittest/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func BlockFlowFixture() models.Block {
}

func CollectionFlowFixture() models.Collection {
collection := test.CollectionGenerator().New()
collection := test.LightCollectionGenerator().New()

return models.Collection{
Id: collection.ID().String(),
Expand Down
17 changes: 17 additions & 0 deletions collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,20 @@ func (c Collection) Encode() []byte {
type CollectionGuarantee struct {
CollectionID Identifier
}

type FullCollection struct {
Transactions []*Transaction
}

// Light returns the light, reference-only version of the collection.
func (c FullCollection) Light() Collection {
lc := Collection{TransactionIDs: make([]Identifier, 0, len(c.Transactions))}
for _, tx := range c.Transactions {
lc.TransactionIDs = append(lc.TransactionIDs, tx.ID())
}
return lc
}

func (c FullCollection) ID() Identifier {
return c.Light().ID()
}
24 changes: 20 additions & 4 deletions test/entities.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,17 @@ func (g *BlockHeaders) New() flow.BlockHeader {
}
}

type Collections struct {
type LightCollection struct {
ids *Identifiers
}

func CollectionGenerator() *Collections {
return &Collections{
func LightCollectionGenerator() *LightCollection {
return &LightCollection{
ids: IdentifierGenerator(),
}
}

func (g *Collections) New() *flow.Collection {
func (g *LightCollection) New() *flow.Collection {
return &flow.Collection{
TransactionIDs: []flow.Identifier{
g.ids.New(),
Expand All @@ -207,6 +207,22 @@ func (g *Collections) New() *flow.Collection {
}
}

type FullCollection struct {
Transactions *Transactions
}

func FullCollectionGenerator() *FullCollection {
return &FullCollection{
Transactions: TransactionGenerator(),
}
}

func (c *FullCollection) New() *flow.FullCollection {
return &flow.FullCollection{
Transactions: []*flow.Transaction{c.Transactions.New(), c.Transactions.New()},
}
}

type CollectionGuarantees struct {
ids *Identifiers
}
Expand Down
Loading