Skip to content

Commit 9037b0c

Browse files
authored
Add WithID overloads for system transaction APIs (#917)
1 parent 99fbbb2 commit 9037b0c

8 files changed

Lines changed: 276 additions & 3 deletions

File tree

access/client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,17 @@ type Client interface {
9292
// GetSystemTransaction returns the system transaction for the given block ID.
9393
GetSystemTransaction(ctx context.Context, blockID flow.Identifier) (*flow.Transaction, error)
9494

95+
// GetSystemTransactionWithID returns the system transaction for the given block ID and optional system transaction ID.
96+
// If systemTxID is flow.EmptyID, the last system transaction for the block is returned.
97+
GetSystemTransactionWithID(ctx context.Context, blockID flow.Identifier, systemTxID flow.Identifier) (*flow.Transaction, error)
98+
9599
// GetSystemTransactionResult returns the transaction result of the system transaction for the given block ID.
96100
GetSystemTransactionResult(ctx context.Context, blockID flow.Identifier) (*flow.TransactionResult, error)
97101

102+
// GetSystemTransactionResultWithID returns the transaction result of the system transaction for the given block ID and optional system transaction ID.
103+
// If systemTxID is flow.EmptyID, the result of the last system transaction for the block is returned.
104+
GetSystemTransactionResultWithID(ctx context.Context, blockID flow.Identifier, systemTxID flow.Identifier) (*flow.TransactionResult, error)
105+
98106
// GetAccount is an alias for GetAccountAtLatestBlock.
99107
GetAccount(ctx context.Context, address flow.Address) (*flow.Account, error)
100108

access/grpc/client.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ func (c *Client) GetSystemTransaction(ctx context.Context, blockID flow.Identifi
185185
return c.grpc.GetSystemTransaction(ctx, blockID)
186186
}
187187

188+
// GetSystemTransactionWithID returns the system transaction for the given block ID and optional system transaction ID.
189+
// If systemTxID is flow.EmptyID, the last system transaction for the block is returned.
190+
func (c *Client) GetSystemTransactionWithID(ctx context.Context, blockID flow.Identifier, systemTxID flow.Identifier) (*flow.Transaction, error) {
191+
return c.grpc.GetSystemTransactionWithID(ctx, blockID, systemTxID)
192+
}
193+
188194
func (c *Client) GetTransactionsByBlockID(ctx context.Context, blockID flow.Identifier) ([]*flow.Transaction, error) {
189195
return c.grpc.GetTransactionsByBlockID(ctx, blockID)
190196
}
@@ -193,6 +199,12 @@ func (c *Client) GetSystemTransactionResult(ctx context.Context, blockID flow.Id
193199
return c.grpc.GetSystemTransactionResult(ctx, blockID)
194200
}
195201

202+
// GetSystemTransactionResultWithID returns the system transaction result for the given block and optional system transaction ID.
203+
// If systemTxID is flow.EmptyID, the result of the last system transaction for the block is returned.
204+
func (c *Client) GetSystemTransactionResultWithID(ctx context.Context, blockID flow.Identifier, systemTxID flow.Identifier) (*flow.TransactionResult, error) {
205+
return c.grpc.GetSystemTransactionResultWithID(ctx, blockID, systemTxID)
206+
}
207+
196208
func (c *Client) GetTransactionResult(ctx context.Context, txID flow.Identifier) (*flow.TransactionResult, error) {
197209
return c.grpc.GetTransactionResult(ctx, txID)
198210
}

access/grpc/grpc.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,34 @@ func (c *BaseClient) GetSystemTransaction(
416416
return &result, nil
417417
}
418418

419+
// GetSystemTransactionWithID returns the system transaction for the given block ID and optional system transaction ID.
420+
// If systemTxID is flow.EmptyID, the last system transaction for the block is returned (as defined by Access API).
421+
func (c *BaseClient) GetSystemTransactionWithID(
422+
ctx context.Context,
423+
blockID flow.Identifier,
424+
systemTxID flow.Identifier,
425+
opts ...grpc.CallOption,
426+
) (*flow.Transaction, error) {
427+
req := &access.GetSystemTransactionRequest{
428+
BlockId: blockID.Bytes(),
429+
}
430+
if systemTxID != (flow.Identifier{}) {
431+
req.Id = systemTxID.Bytes()
432+
}
433+
434+
res, err := c.rpcClient.GetSystemTransaction(ctx, req, opts...)
435+
if err != nil {
436+
return nil, newRPCError(err)
437+
}
438+
439+
result, err := convert.MessageToTransaction(res.GetTransaction())
440+
if err != nil {
441+
return nil, newMessageToEntityError(entityTransaction, err)
442+
}
443+
444+
return &result, nil
445+
}
446+
419447
func (c *BaseClient) GetTransactionsByBlockID(
420448
ctx context.Context,
421449
blockID flow.Identifier,
@@ -466,6 +494,35 @@ func (c *BaseClient) GetSystemTransactionResult(
466494
return &result, nil
467495
}
468496

497+
// GetSystemTransactionResultWithID returns the transaction result of the system transaction for the given block ID.
498+
// If systemTxID is flow.EmptyID, the result of the last system transaction for the block is returned (as defined by Access API).
499+
func (c *BaseClient) GetSystemTransactionResultWithID(
500+
ctx context.Context,
501+
blockID flow.Identifier,
502+
systemTxID flow.Identifier,
503+
opts ...grpc.CallOption,
504+
) (*flow.TransactionResult, error) {
505+
req := &access.GetSystemTransactionResultRequest{
506+
BlockId: blockID.Bytes(),
507+
EventEncodingVersion: c.eventEncoding,
508+
}
509+
if systemTxID != (flow.Identifier{}) {
510+
req.Id = systemTxID.Bytes()
511+
}
512+
513+
res, err := c.rpcClient.GetSystemTransactionResult(ctx, req, opts...)
514+
if err != nil {
515+
return nil, newRPCError(err)
516+
}
517+
518+
result, err := convert.MessageToTransactionResult(res, c.jsonOptions)
519+
if err != nil {
520+
return nil, newMessageToEntityError(entityTransactionResult, err)
521+
}
522+
523+
return &result, nil
524+
}
525+
469526
func (c *BaseClient) GetTransactionResult(
470527
ctx context.Context,
471528
txID flow.Identifier,

access/grpc/grpc_test.go

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,130 @@ func TestClient_GetSystemTransactionResult(t *testing.T) {
650650
}))
651651
}
652652

653+
func TestClient_GetSystemTransaction_WithID_SetsId(t *testing.T) {
654+
txs := test.TransactionGenerator()
655+
ids := test.IdentifierGenerator()
656+
657+
t.Run("WithID sets request Id", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
658+
blockID := ids.New()
659+
systemTxID := ids.New()
660+
expectedTx := txs.New()
661+
662+
txMsg, err := convert.TransactionToMessage(*expectedTx)
663+
require.NoError(t, err)
664+
665+
response := &access.TransactionResponse{Transaction: txMsg}
666+
667+
rpc.
668+
On("GetSystemTransaction", ctx, mock.Anything).
669+
Return(response, nil).
670+
Run(func(args mock.Arguments) {
671+
req, ok := args.Get(1).(*access.GetSystemTransactionRequest)
672+
require.True(t, ok)
673+
assert.Equal(t, blockID.Bytes(), req.GetBlockId())
674+
assert.Equal(t, systemTxID.Bytes(), req.GetId())
675+
})
676+
677+
tx, err := c.GetSystemTransactionWithID(ctx, blockID, systemTxID)
678+
require.NoError(t, err)
679+
assert.Equal(t, expectedTx, tx)
680+
}))
681+
}
682+
683+
func TestClient_GetSystemTransaction_WithEmptyID_OmitsId(t *testing.T) {
684+
txs := test.TransactionGenerator()
685+
ids := test.IdentifierGenerator()
686+
687+
t.Run("EmptyID omits request Id", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
688+
blockID := ids.New()
689+
expectedTx := txs.New()
690+
691+
txMsg, err := convert.TransactionToMessage(*expectedTx)
692+
require.NoError(t, err)
693+
694+
response := &access.TransactionResponse{Transaction: txMsg}
695+
696+
rpc.
697+
On("GetSystemTransaction", ctx, mock.Anything).
698+
Return(response, nil).
699+
Run(func(args mock.Arguments) {
700+
req, ok := args.Get(1).(*access.GetSystemTransactionRequest)
701+
require.True(t, ok)
702+
assert.Equal(t, blockID.Bytes(), req.GetBlockId())
703+
assert.Len(t, req.GetId(), 0)
704+
})
705+
706+
tx, err := c.GetSystemTransactionWithID(ctx, blockID, flow.EmptyID)
707+
require.NoError(t, err)
708+
assert.Equal(t, expectedTx, tx)
709+
}))
710+
}
711+
712+
func TestClient_GetSystemTransactionResult_WithID_SetsId(t *testing.T) {
713+
ids := test.IdentifierGenerator()
714+
715+
t.Run("WithID sets request Id", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
716+
blockID := ids.New()
717+
systemTxID := ids.New()
718+
719+
// Build a minimal result
720+
results := test.TransactionResultGenerator(flow.EventEncodingVersionCCF)
721+
expectedResult := results.New()
722+
response, _ := convert.TransactionResultToMessage(expectedResult, flow.EventEncodingVersionCCF)
723+
724+
rpc.
725+
On("GetSystemTransactionResult", ctx, mock.Anything).
726+
Return(response, nil).
727+
Run(func(args mock.Arguments) {
728+
req, ok := args.Get(1).(*access.GetSystemTransactionResultRequest)
729+
require.True(t, ok)
730+
assert.Equal(t, blockID.Bytes(), req.GetBlockId())
731+
assert.Equal(t, systemTxID.Bytes(), req.GetId())
732+
assert.Equal(t, entities.EventEncodingVersion_CCF_V0, req.GetEventEncodingVersion())
733+
})
734+
735+
result, err := c.GetSystemTransactionResultWithID(ctx, blockID, systemTxID)
736+
require.NoError(t, err)
737+
738+
// force type evaluation for equality
739+
for _, event := range result.Events {
740+
_ = event.Value.Type().ID()
741+
}
742+
assert.Equal(t, expectedResult, *result)
743+
}))
744+
}
745+
746+
func TestClient_GetSystemTransactionResult_WithEmptyID_OmitsId(t *testing.T) {
747+
ids := test.IdentifierGenerator()
748+
749+
t.Run("EmptyID omits request Id", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
750+
blockID := ids.New()
751+
752+
results := test.TransactionResultGenerator(flow.EventEncodingVersionCCF)
753+
expectedResult := results.New()
754+
response, _ := convert.TransactionResultToMessage(expectedResult, flow.EventEncodingVersionCCF)
755+
756+
rpc.
757+
On("GetSystemTransactionResult", ctx, mock.Anything).
758+
Return(response, nil).
759+
Run(func(args mock.Arguments) {
760+
req, ok := args.Get(1).(*access.GetSystemTransactionResultRequest)
761+
require.True(t, ok)
762+
assert.Equal(t, blockID.Bytes(), req.GetBlockId())
763+
assert.Len(t, req.GetId(), 0)
764+
assert.Equal(t, entities.EventEncodingVersion_CCF_V0, req.GetEventEncodingVersion())
765+
})
766+
767+
result, err := c.GetSystemTransactionResultWithID(ctx, blockID, flow.EmptyID)
768+
require.NoError(t, err)
769+
770+
for _, event := range result.Events {
771+
_ = event.Value.Type().ID()
772+
}
773+
assert.Equal(t, expectedResult, *result)
774+
}))
775+
}
776+
653777
func TestClient_GetTransactionResult(t *testing.T) {
654778
ids := test.IdentifierGenerator()
655779

access/http/client.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,18 @@ func (c *Client) GetSystemTransactionResult(ctx context.Context, blockID flow.Id
196196
return nil, fmt.Errorf("not implemented")
197197
}
198198

199+
// GetSystemTransactionWithID returns the system transaction for the given block and optional system transaction ID.
200+
// HTTP API does not currently support this endpoint.
201+
func (c *Client) GetSystemTransactionWithID(ctx context.Context, blockID flow.Identifier, systemTxID flow.Identifier) (*flow.Transaction, error) {
202+
return nil, fmt.Errorf("not implemented")
203+
}
204+
205+
// GetSystemTransactionResultWithID returns the system transaction result for the given block and optional system transaction ID.
206+
// HTTP API does not currently support this endpoint.
207+
func (c *Client) GetSystemTransactionResultWithID(ctx context.Context, blockID flow.Identifier, systemTxID flow.Identifier) (*flow.TransactionResult, error) {
208+
return nil, fmt.Errorf("not implemented")
209+
}
210+
199211
// GetAccount is an alias for GetAccountAtLatestBlock.
200212
func (c *Client) GetAccount(ctx context.Context, address flow.Address) (*flow.Account, error) {
201213
return c.GetAccountAtLatestBlock(ctx, address)

access/mocks/Client.go

Lines changed: 60 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/ethereum/go-ethereum v1.16.2
1111
github.com/onflow/cadence v1.7.0
1212
github.com/onflow/crypto v0.25.3
13-
github.com/onflow/flow/protobuf/go/flow v0.4.11
13+
github.com/onflow/flow/protobuf/go/flow v0.4.16
1414
github.com/onflow/sdks v0.6.0-preview.1
1515
github.com/pkg/errors v0.9.1
1616
github.com/stretchr/testify v1.11.1

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ github.com/onflow/crypto v0.25.3 h1:XQ3HtLsw8h1+pBN+NQ1JYM9mS2mVXTyg55OldaAIF7U=
102102
github.com/onflow/crypto v0.25.3/go.mod h1:+1igaXiK6Tjm9wQOBD1EGwW7bYWMUGKtwKJ/2QL/OWs=
103103
github.com/onflow/fixed-point v0.1.1 h1:j0jYZVO8VGyk1476alGudEg7XqCkeTVxb5ElRJRKS90=
104104
github.com/onflow/fixed-point v0.1.1/go.mod h1:gJdoHqKtToKdOZbvryJvDZfcpzC7d2fyWuo3ZmLtcGY=
105-
github.com/onflow/flow/protobuf/go/flow v0.4.11 h1:EYjaATmor1ONczbvJ6VejQAJK4elFRk5h9AapxQ7j4c=
106-
github.com/onflow/flow/protobuf/go/flow v0.4.11/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk=
105+
github.com/onflow/flow/protobuf/go/flow v0.4.16 h1:UADQeq/mpuqFk+EkwqDNoF70743raWQKmB/Dm/eKt2Q=
106+
github.com/onflow/flow/protobuf/go/flow v0.4.16/go.mod h1:NA2pX2nw8zuaxfKphhKsk00kWLwfd+tv8mS23YXO4Sk=
107107
github.com/onflow/sdks v0.6.0-preview.1 h1:mb/cUezuqWEP1gFZNAgUI4boBltudv4nlfxke1KBp9k=
108108
github.com/onflow/sdks v0.6.0-preview.1/go.mod h1:F0dj0EyHC55kknLkeD10js4mo14yTdMotnWMslPirrU=
109109
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=

0 commit comments

Comments
 (0)