-
Notifications
You must be signed in to change notification settings - Fork 178
/
backend_accounts.go
95 lines (75 loc) · 2.33 KB
/
backend_accounts.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package backend
import (
"context"
execproto "github.com/onflow/flow/protobuf/go/flow/execution"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/onflow/flow-go/engine/common/rpc/convert"
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/state/protocol"
"github.com/onflow/flow-go/storage"
)
type backendAccounts struct {
state protocol.State
executionRPC execproto.ExecutionAPIClient
headers storage.Headers
}
func (b *backendAccounts) GetAccount(ctx context.Context, address flow.Address) (*flow.Account, error) {
return b.GetAccountAtLatestBlock(ctx, address)
}
func (b *backendAccounts) GetAccountAtLatestBlock(ctx context.Context, address flow.Address) (*flow.Account, error) {
// get the latest sealed header
latestHeader, err := b.state.Sealed().Head()
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get latest sealed header: %v", err)
}
// get the block id of the latest sealed header
latestBlockID := latestHeader.ID()
account, err := b.getAccountAtBlockID(ctx, address, latestBlockID)
if err != nil {
return nil, err
}
return account, nil
}
func (b *backendAccounts) GetAccountAtBlockHeight(
ctx context.Context,
address flow.Address,
height uint64,
) (*flow.Account, error) {
// get header at given height
header, err := b.headers.ByHeight(height)
if err != nil {
err = convertStorageError(err)
return nil, err
}
// get block ID of the header at the given height
blockID := header.ID()
account, err := b.getAccountAtBlockID(ctx, address, blockID)
if err != nil {
return nil, err
}
return account, nil
}
func (b *backendAccounts) getAccountAtBlockID(
ctx context.Context,
address flow.Address,
blockID flow.Identifier,
) (*flow.Account, error) {
exeReq := execproto.GetAccountAtBlockIDRequest{
Address: address.Bytes(),
BlockId: blockID[:],
}
exeRes, err := b.executionRPC.GetAccountAtBlockID(ctx, &exeReq)
if err != nil {
errStatus, _ := status.FromError(err)
if errStatus.Code() == codes.NotFound {
return nil, err
}
return nil, status.Errorf(codes.Internal, "failed to get account from the execution node: %v", err)
}
account, err := convert.MessageToAccount(exeRes.GetAccount())
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to convert account message: %v", err)
}
return account, nil
}