Skip to content

Commit

Permalink
Merge pull request #332 from onflow/rbtz/newBatchAPIs
Browse files Browse the repository at this point in the history
Add GetTransactionsByBlockID and GetTransactionResultsByBlockID
  • Loading branch information
SaveTheRbtz authored Dec 19, 2022
2 parents ca0cd69 + 4e4c4cd commit 2f3cf15
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 16 deletions.
6 changes: 6 additions & 0 deletions access/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,15 @@ type Client interface {
// GetTransaction gets a transaction by ID.
GetTransaction(ctx context.Context, txID flow.Identifier) (*flow.Transaction, error)

// GetTransactionsByBlockID gets all the transactions for a specified block.
GetTransactionsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.Transaction, error)

// GetTransactionResult gets the result of a transaction.
GetTransactionResult(ctx context.Context, txID flow.Identifier) (*flow.TransactionResult, error)

// GetTransactionResultsByBlockID gets all the transaction results for a specified block.
GetTransactionResultsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.TransactionResult, error)

// GetAccount is an alias for GetAccountAtLatestBlock.
GetAccount(ctx context.Context, address flow.Address) (*flow.Account, error)

Expand Down
8 changes: 8 additions & 0 deletions access/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,18 @@ func (c *Client) GetTransaction(ctx context.Context, txID flow.Identifier) (*flo
return c.grpc.GetTransaction(ctx, txID)
}

func (c *Client) GetTransactionsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.Transaction, error) {
return c.grpc.GetTransactionsByBlockID(ctx, blockID)
}

func (c *Client) GetTransactionResult(ctx context.Context, txID flow.Identifier) (*flow.TransactionResult, error) {
return c.grpc.GetTransactionResult(ctx, txID)
}

func (c *Client) GetTransactionResultsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.TransactionResult, error) {
return c.grpc.GetTransactionResultsByBlockID(ctx, blockID)
}

func (c *Client) GetAccount(ctx context.Context, address flow.Address) (*flow.Account, error) {
return c.grpc.GetAccount(ctx, address)
}
Expand Down
24 changes: 13 additions & 11 deletions access/grpc/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,12 +495,13 @@ func transactionResultToMessage(result flow.TransactionResult) (*access.Transact
}

return &access.TransactionResultResponse{
Status: entities.TransactionStatus(result.Status),
StatusCode: uint32(statusCode),
ErrorMessage: errorMsg,
Events: eventMessages,
BlockId: identifierToMessage(result.BlockID),
BlockHeight: result.BlockHeight,
Status: entities.TransactionStatus(result.Status),
StatusCode: uint32(statusCode),
ErrorMessage: errorMsg,
Events: eventMessages,
BlockId: identifierToMessage(result.BlockID),
BlockHeight: result.BlockHeight,
TransactionId: identifierToMessage(result.TransactionID),
}, nil
}

Expand Down Expand Up @@ -530,10 +531,11 @@ func messageToTransactionResult(m *access.TransactionResultResponse, options []j
}

return flow.TransactionResult{
Status: flow.TransactionStatus(m.GetStatus()),
Error: err,
Events: events,
BlockID: flow.BytesToID(m.GetBlockId()),
BlockHeight: m.BlockHeight,
Status: flow.TransactionStatus(m.GetStatus()),
Error: err,
Events: events,
BlockID: flow.BytesToID(m.GetBlockId()),
BlockHeight: m.GetBlockHeight(),
TransactionID: flow.BytesToID(m.GetTransactionId()),
}, nil
}
55 changes: 55 additions & 0 deletions access/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,33 @@ func (c *BaseClient) GetTransaction(
return &result, nil
}

func (c *BaseClient) GetTransactionsByBlockID(
ctx context.Context,
blockID flow.Identifier,
opts ...grpc.CallOption,
) ([]*flow.Transaction, error) {
req := &access.GetTransactionsByBlockIDRequest{
BlockId: blockID.Bytes(),
}

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

unparsedResults := res.GetTransactions()
results := make([]*flow.Transaction, 0, len(unparsedResults))
for _, result := range unparsedResults {
parsed, err := messageToTransaction(result)
if err != nil {
return nil, newMessageToEntityError(entityTransaction, err)
}
results = append(results, &parsed)
}

return results, nil
}

func (c *BaseClient) GetTransactionResult(
ctx context.Context,
txID flow.Identifier,
Expand All @@ -293,6 +320,34 @@ func (c *BaseClient) GetTransactionResult(
return &result, nil
}

func (c *BaseClient) GetTransactionResultsByBlockID(
ctx context.Context,
blockID flow.Identifier,
opts ...grpc.CallOption,
) ([]*flow.TransactionResult, error) {

req := &access.GetTransactionsByBlockIDRequest{
BlockId: blockID.Bytes(),
}

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

unparsedResults := res.GetTransactionResults()
results := make([]*flow.TransactionResult, 0, len(unparsedResults))
for _, result := range unparsedResults {
parsed, err := messageToTransactionResult(result, c.jsonOptions)
if err != nil {
return nil, newMessageToEntityError(entityTransactionResult, err)
}
results = append(results, &parsed)
}

return results, nil
}

func (c *BaseClient) GetAccount(ctx context.Context, address flow.Address, opts ...grpc.CallOption) (*flow.Account, error) {
return c.GetAccountAtLatestBlock(ctx, address, opts...)
}
Expand Down
71 changes: 71 additions & 0 deletions access/grpc/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,41 @@ func TestClient_GetTransaction(t *testing.T) {
}))
}

func TestClient_GetTransactionsByBlockID(t *testing.T) {
txs := test.TransactionGenerator()
ids := test.IdentifierGenerator()
blockID := ids.New()

t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *MockRPCClient, c *BaseClient) {
expectedTx := txs.New()

txMsg, err := transactionToMessage(*expectedTx)
require.NoError(t, err)

responses := &access.TransactionsResponse{
Transactions: []*entities.Transaction{txMsg},
}

rpc.On("GetTransactionsByBlockID", ctx, mock.Anything).Return(responses, nil)

txs, err := c.GetTransactionsByBlockID(ctx, blockID)
require.NoError(t, err)

assert.Equal(t, len(txs), 1)
assert.Equal(t, expectedTx, txs[0])
}))

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

tx, err := c.GetTransactionsByBlockID(ctx, blockID)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Nil(t, tx)
}))
}

func TestClient_GetTransactionResult(t *testing.T) {
results := test.TransactionResultGenerator()
ids := test.IdentifierGenerator()
Expand Down Expand Up @@ -402,6 +437,42 @@ func TestClient_GetTransactionResult(t *testing.T) {
}))
}

func TestClient_GetTransactionResultsByBlockID(t *testing.T) {
resultGenerator := test.TransactionResultGenerator()
ids := test.IdentifierGenerator()

t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *MockRPCClient, c *BaseClient) {
blockID := ids.New()
expectedResult := resultGenerator.New()
response, err := transactionResultToMessage(expectedResult)
require.NoError(t, err)

responses := &access.TransactionResultsResponse{
TransactionResults: []*access.TransactionResultResponse{response},
}

rpc.On("GetTransactionResultsByBlockID", ctx, mock.Anything).Return(responses, nil)

results, err := c.GetTransactionResultsByBlockID(ctx, blockID)
require.NoError(t, err)

assert.Equal(t, len(results), 1)
assert.Equal(t, expectedResult, *results[0])
}))

t.Run("Not found error", clientTest(func(t *testing.T, ctx context.Context, rpc *MockRPCClient, c *BaseClient) {
blockID := ids.New()

rpc.On("GetTransactionResultsByBlockID", ctx, mock.Anything).
Return(nil, errNotFound)

result, err := c.GetTransactionResultsByBlockID(ctx, blockID)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Nil(t, result)
}))
}

func TestClient_GetAccountAtLatestBlock(t *testing.T) {
accounts := test.AccountGenerator()
addresses := test.AddressGenerator()
Expand Down
9 changes: 9 additions & 0 deletions access/http/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package http

import (
"context"
"fmt"

"github.com/onflow/cadence"

Expand Down Expand Up @@ -121,10 +122,18 @@ func (c *Client) GetTransaction(ctx context.Context, ID flow.Identifier) (*flow.
return c.httpClient.GetTransaction(ctx, ID)
}

func (c *Client) GetTransactionsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.Transaction, error) {
return nil, fmt.Errorf("not implemented")
}

func (c *Client) GetTransactionResult(ctx context.Context, ID flow.Identifier) (*flow.TransactionResult, error) {
return c.httpClient.GetTransactionResult(ctx, ID)
}

func (c *Client) GetTransactionResultsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.TransactionResult, error) {
return nil, fmt.Errorf("not implemented")
}

// GetAccount is an alias for GetAccountAtLatestBlock.
func (c *Client) GetAccount(ctx context.Context, address flow.Address) (*flow.Account, error) {
return c.GetAccountAtLatestBlock(ctx, address)
Expand Down
11 changes: 6 additions & 5 deletions transaction.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,11 +609,12 @@ func (s signaturesList) canonicalForm() []transactionSignatureCanonicalForm {
}

type TransactionResult struct {
Status TransactionStatus
Error error
Events []Event
BlockID Identifier
BlockHeight uint64
Status TransactionStatus
Error error
Events []Event
BlockID Identifier
BlockHeight uint64
TransactionID Identifier
}

// TransactionStatus represents the status of a transaction.
Expand Down

0 comments on commit 2f3cf15

Please sign in to comment.