Skip to content

Commit

Permalink
Add get account keys endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
illia-malachyn committed Sep 11, 2024
1 parent ec08850 commit e7da346
Show file tree
Hide file tree
Showing 9 changed files with 496 additions and 6 deletions.
16 changes: 16 additions & 0 deletions access/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,22 @@ func (c *Client) GetAccountAtBlockHeight(ctx context.Context, address flow.Addre
return c.grpc.GetAccountAtBlockHeight(ctx, address, blockHeight)
}

func (c *Client) GetAccountKeyAtLatestBlock(ctx context.Context, address flow.Address, keyIndex uint32) (*flow.AccountKey, error) {
return c.grpc.GetAccountKeyAtLatestBlock(ctx, address, keyIndex)
}

func (c *Client) GetAccountKeyAtBlockHeight(ctx context.Context, address flow.Address, keyIndex uint32, height uint64) (*flow.AccountKey, error) {
return c.grpc.GetAccountKeyAtBlockHeight(ctx, address, keyIndex, height)
}

func (c *Client) GetAccountKeysAtLatestBlock(ctx context.Context, address flow.Address) ([]flow.AccountKey, error) {
return c.grpc.GetAccountKeysAtLatestBlock(ctx, address)
}

func (c *Client) GetAccountKeysAtBlockHeight(ctx context.Context, address flow.Address, height uint64) ([]flow.AccountKey, error) {
return c.grpc.GetAccountKeysAtBlockHeight(ctx, address, height)
}

func (c *Client) ExecuteScriptAtLatestBlock(ctx context.Context, script []byte, arguments []cadence.Value) (cadence.Value, error) {
return c.grpc.ExecuteScriptAtLatestBlock(ctx, script, arguments)
}
Expand Down
15 changes: 15 additions & 0 deletions access/grpc/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,21 @@ func MessageToAccountKey(m *entities.AccountKey) (*flow.AccountKey, error) {
}, nil
}

func MessageToAccountKeys(m []*entities.AccountKey) ([]flow.AccountKey, error) {
var accountKeys []flow.AccountKey

for _, entity := range m {
accountKey, err := MessageToAccountKey(entity)
if err != nil {
return nil, err
}

accountKeys = append(accountKeys, *accountKey)
}

return accountKeys, nil
}

func BlockToMessage(b flow.Block) (*entities.Block, error) {

t := timestamppb.New(b.BlockHeader.Timestamp)
Expand Down
92 changes: 92 additions & 0 deletions access/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -512,6 +512,98 @@ func (c *BaseClient) GetAccountAtBlockHeight(
return &account, nil
}

func (c *BaseClient) GetAccountKeyAtLatestBlock(
ctx context.Context,
address flow.Address,
keyIndex uint32,
) (*flow.AccountKey, error) {
request := &access.GetAccountKeyAtLatestBlockRequest{
Address: address.Bytes(),
Index: keyIndex,
}

response, err := c.rpcClient.GetAccountKeyAtLatestBlock(ctx, request)
if err != nil {
return nil, newRPCError(err)
}

accountKey, err := convert.MessageToAccountKey(response.GetAccountKey())
if err != nil {
return nil, newMessageToEntityError(entityAccount, err)
}

return accountKey, nil
}

func (c *BaseClient) GetAccountKeyAtBlockHeight(
ctx context.Context,
address flow.Address,
keyIndex uint32,
height uint64,
) (*flow.AccountKey, error) {
request := &access.GetAccountKeyAtBlockHeightRequest{
Address: address.Bytes(),
Index: keyIndex,
BlockHeight: height,
}

response, err := c.rpcClient.GetAccountKeyAtBlockHeight(ctx, request)
if err != nil {
return nil, newRPCError(err)
}

accountKey, err := convert.MessageToAccountKey(response.GetAccountKey())
if err != nil {
return nil, newMessageToEntityError(entityAccount, err)
}

return accountKey, nil
}

func (c *BaseClient) GetAccountKeysAtLatestBlock(
ctx context.Context,
address flow.Address,
) ([]flow.AccountKey, error) {
request := &access.GetAccountKeysAtLatestBlockRequest{
Address: address.Bytes(),
}

response, err := c.rpcClient.GetAccountKeysAtLatestBlock(ctx, request)
if err != nil {
return nil, newRPCError(err)
}

accountKeys, err := convert.MessageToAccountKeys(response.GetAccountKeys())
if err != nil {
return nil, newMessageToEntityError(entityAccount, err)
}

return accountKeys, nil
}

func (c *BaseClient) GetAccountKeysAtBlockHeight(
ctx context.Context,
address flow.Address,
height uint64,
) ([]flow.AccountKey, error) {
request := &access.GetAccountKeysAtBlockHeightRequest{
Address: address.Bytes(),
BlockHeight: height,
}

response, err := c.rpcClient.GetAccountKeysAtBlockHeight(ctx, request)
if err != nil {
return nil, newRPCError(err)
}

accountKeys, err := convert.MessageToAccountKeys(response.GetAccountKeys())
if err != nil {
return nil, newMessageToEntityError(entityAccount, err)
}

return accountKeys, nil
}

func (c *BaseClient) ExecuteScriptAtLatestBlock(
ctx context.Context,
script []byte,
Expand Down
142 changes: 142 additions & 0 deletions access/grpc/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,148 @@ func TestClient_ExecuteScriptAtLatestBlock(t *testing.T) {
}))
}

func TestClient_GetAccountKeyAtLatestBlock(t *testing.T) {
accounts := test.AccountGenerator()
addresses := test.AddressGenerator()
index := uint32(0)

t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
account := accounts.New()
response := &access.AccountKeyResponse{
AccountKey: convert.AccountKeyToMessage(account.Keys[index]),
}

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

key, err := c.GetAccountKeyAtLatestBlock(ctx, account.Address, index)
require.NoError(t, err)

assert.Equal(t, account.Keys[index], key)
}))

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

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

key, err := c.GetAccountKeyAtLatestBlock(ctx, address, index)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Nil(t, key)
}))
}

func TestClient_GetAccountKeyAtBlockHeight(t *testing.T) {
accounts := test.AccountGenerator()
addresses := test.AddressGenerator()
height := uint64(42)
index := uint32(0)

t.Run("Success", clientTest(func(t *testing.T, ctx context.Context, rpc *mocks.MockRPCClient, c *BaseClient) {
account := accounts.New()
response := &access.AccountKeyResponse{
AccountKey: convert.AccountKeyToMessage(account.Keys[index]),
}

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

key, err := c.GetAccountKeyAtBlockHeight(ctx, account.Address, index, height)
require.NoError(t, err)

assert.Equal(t, account.Keys[index], key)
}))

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

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

key, err := c.GetAccountKeyAtBlockHeight(ctx, address, index, height)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Nil(t, key)
}))
}

func TestClient_GetAccountKeysAtLatestBlock(t *testing.T) {
accounts := test.AccountGenerator()
addresses := test.AddressGenerator()
index := uint32(0)

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

response := &access.AccountKeysResponse{
AccountKeys: []*entities.AccountKey{convert.AccountKeyToMessage(account.Keys[index])},
}

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

keys, err := c.GetAccountKeysAtLatestBlock(ctx, account.Address)
require.NoError(t, err)
assert.Equal(t, *account.Keys[index], keys[index])
}))

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

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

keys, err := c.GetAccountKeysAtLatestBlock(ctx, address)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Empty(t, keys)
}))
}

func TestClient_GetAccountKeysAtBlockHeight(t *testing.T) {
accounts := test.AccountGenerator()
addresses := test.AddressGenerator()
height := uint64(42)
index := uint32(0)

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

response := &access.AccountKeysResponse{
AccountKeys: []*entities.AccountKey{convert.AccountKeyToMessage(account.Keys[index])},
}

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

keys, err := c.GetAccountKeysAtBlockHeight(ctx, account.Address, height)
require.NoError(t, err)
assert.Equal(t, *account.Keys[index], keys[index])
}))

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

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

keys, err := c.GetAccountKeysAtBlockHeight(ctx, address, height)
assert.Error(t, err)
assert.Equal(t, codes.NotFound, status.Code(err))
assert.Empty(t, keys)
}))
}

func TestClient_ExecuteScriptAtBlockID(t *testing.T) {
ids := test.IdentifierGenerator()

Expand Down
Loading

0 comments on commit e7da346

Please sign in to comment.