diff --git a/client.go b/client.go index 81ed25d..7359825 100644 --- a/client.go +++ b/client.go @@ -60,6 +60,39 @@ func (c Client) GetAccountState(accountAddr string) (AccountState, error) { return FromAccountStateBlob(accStateBlob) } +// GetTransactionList +func (c Client) GetTransactionList(limit int) (TransactionList, error) { + // 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_GetTransactionsRequest{ + GetTransactionsRequest: &types.GetTransactionsRequest{ + StartVersion: 1, + Limit: uint64(limit), + FetchEvents: true, + }, + }, + }, + } + 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 TransactionList{}, err + } + + txList := updateLedgerResponse.GetResponseItems()[0].GetGetTransactionsResponse().GetTxnListWithProof().GetTransactions() + + return FromTransactionList(txList) +} + // SendTx sends a transaction to the connected validator node. func (c Client) SendTx(tx Transaction) error { txRequest := admission_control.SubmitTransactionRequest{ diff --git a/examples/main.go b/examples/main.go index 03c2e2c..b7ed248 100644 --- a/examples/main.go +++ b/examples/main.go @@ -14,7 +14,7 @@ func main() { } defer c.Close() - acc := "8cd377191fe0ef113455c8e8d769f0c0147d5bb618bf195c0af31a05fbfd0969" + acc := "82258967750773ea090d125f9aeb9b9e42f6c7ff6df0742336992bfc52b4096a" accState, err := c.GetAccountState(acc) if err != nil { panic(err) @@ -23,4 +23,11 @@ func main() { fmt.Printf("Raw account state: 0x%x\n", accState.Blob) fmt.Println() fmt.Printf("Account resource: %v\n", accState.AccountResource) + + txlist, err := c.GetTransactionList(1) + if err != nil { + panic(err) + } + fmt.Println() + fmt.Printf("Transaction list resource: %v\n", txlist.Transactions) } diff --git a/tx.go b/tx.go index f903502..7563b43 100644 --- a/tx.go +++ b/tx.go @@ -1,8 +1,68 @@ package libra +import ( + "bytes" + "encoding/binary" + "fmt" + + "github.com/philippgille/libra-sdk-go/rpc/types" +) + // Transaction is a transaction of Libra Coins. type Transaction struct { RawBytes []byte SenderPubKey []byte SenderSig []byte } + +// TransactionList +type TransactionList struct { + Transactions []Transaction +} + +// FromTransactionListResourceBlob +func FromTransactionListResourceBlob(transactionListResourceBlob []byte) (TransactionListResource, error) { + result := TransactionListResource{} + + r := bytes.NewReader(transactionListResourceBlob) + + var balance uint64 + err := binary.Read(r, binary.LittleEndian, &balance) + if err != nil { + return result, err + } + result.Balance = balance + + return result, nil +} + +// TransactionListResource +type TransactionListResource struct { + AuthKey []byte + Balance uint64 + ReceivedEvents uint64 + SentEvents uint64 + SequenceNo uint64 +} + +// String formats the account state similarly to the Libra CLI. +// Numbers are formatted as string because the numbers are uint64, +// whose max value exceeds JSON's "save integer", +// which can lead to parsing errors. +func (tx Transaction) String() string { + return fmt.Sprintf("{\"raw_bytes\": \"0x%x\", \"sender_pub_key\": \"0x%x\", \"sender_sig\": \"0x%x\"}", + tx.RawBytes, tx.SenderPubKey, tx.SenderSig) +} + +// FromAccountStateBlob converts an account state blob into an object of the AccountState struct. +func FromTransactionList(transactionList []*types.SignedTransaction) (TransactionList, error) { + results := TransactionList{} + for _, x := range transactionList { + result := Transaction{} + result.RawBytes = x.GetRawTxnBytes() + result.SenderPubKey = x.GetSenderPublicKey() + result.SenderSig = x.GetSenderSignature() + results.Transactions = append(results.Transactions, result) + } + return results, nil +}