-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathclient.go
99 lines (89 loc) · 3.34 KB
/
client.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
96
97
98
99
package libra
import (
"context"
"encoding/hex"
"time"
"google.golang.org/grpc"
"github.com/philippgille/libra-sdk-go/rpc/admission_control"
"github.com/philippgille/libra-sdk-go/rpc/types"
)
// Client is a libra client that's connected to a validator node via gRPC.
// It allows you to query the account state, send transactions etc.
type Client struct {
// Only for printing. It was only used to create the gRPC client connection.
address string
// Shouldn't need to be used. It was only used to create the AdmissionControlClient.
conn *grpc.ClientConn
// Actual client
acc admission_control.AdmissionControlClient
}
// GetAccountState requests the state of the given account.
func (c Client) GetAccountState(accountAddr string) (AccountState, error) {
accountAddrBytes, err := hex.DecodeString(accountAddr)
if err != nil {
return AccountState{}, err
}
// From the generated Go code:
//
// Types that are valid to be assigned to RequestedItems:
// *RequestItem_GetAccountStateRequest
// *RequestItem_GetAccountTransactionBySequenceNumberRequest
// *RequestItem_GetEventsByEventAccessPathRequest
// *RequestItem_GetTransactionsRequest
requestedItems := []*types.RequestItem{
&types.RequestItem{
RequestedItems: &types.RequestItem_GetAccountStateRequest{
GetAccountStateRequest: &types.GetAccountStateRequest{
Address: accountAddrBytes,
},
},
},
}
knownVersion := uint64(0) // TODO: Does this make a difference for accounts? Or only for events? Might need to be a method parameter.
updateLedgerRequest := types.UpdateToLatestLedgerRequest{
ClientKnownVersion: knownVersion,
RequestedItems: requestedItems,
}
updateLedgerResponse, err := c.acc.UpdateToLatestLedger(context.Background(), &updateLedgerRequest)
if err != nil {
return AccountState{}, err
}
// We only put one request item in the request, so there should only be one response.
accStateBlob := updateLedgerResponse.GetResponseItems()[0].GetGetAccountStateResponse().GetAccountStateWithProof().GetBlob().GetBlob()
return FromAccountStateBlob(accStateBlob)
}
// SendTx sends a transaction to the connected validator node.
func (c Client) SendTx(tx Transaction) error {
txRequest := admission_control.SubmitTransactionRequest{
SignedTxn: &types.SignedTransaction{
RawTxnBytes: tx.RawBytes,
SenderPublicKey: tx.SenderPubKey,
SenderSignature: tx.SenderSig,
},
}
_, err := c.acc.SubmitTransaction(context.Background(), &txRequest)
return err
}
// Close closes the underlying gRPC connection.
func (c Client) Close() {
c.conn.Close()
}
// NewClient creates a new Libra client.
// It connects to the given validator node via gRPC.
// The connection is kept open until Close() is called on the client.
func NewClient(address string, dialTimeout time.Duration) (Client, error) {
ctxWithTimeout, cancelFunc := context.WithTimeout(context.Background(), dialTimeout)
defer cancelFunc()
// We need the grpc.WithBlock() dial option so that the timeout is used for establishing the connection
// and calling the cancel function via defer doesn't lead to cancelling the connection before the timeout.
conn, err := grpc.DialContext(ctxWithTimeout, address, grpc.WithBlock(), grpc.WithInsecure())
if err != nil {
return Client{}, err
}
acc := admission_control.NewAdmissionControlClient(conn)
return Client{
address: address,
conn: conn,
acc: acc,
}, nil
}