Skip to content

Commit

Permalink
Merge pull request #753 from The-K-R-O-K/illia-malachyn/744-account-k…
Browse files Browse the repository at this point in the history
…eys-endpoint

Add get account keys endpoints
  • Loading branch information
peterargue authored Sep 24, 2024
2 parents 9b49f3e + 8884ba7 commit 423dc3a
Show file tree
Hide file tree
Showing 4 changed files with 265 additions and 0 deletions.
16 changes: 16 additions & 0 deletions access/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,22 @@ func (c *Client) GetAccountBalanceAtBlockHeight(ctx context.Context, address flo
return c.grpc.GetAccountBalanceAtBlockHeight(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 @@ -597,6 +597,98 @@ func (c *BaseClient) GetAccountBalanceAtBlockHeight(
return response.GetBalance(), 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 @@ -939,6 +939,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

0 comments on commit 423dc3a

Please sign in to comment.