215 lines
5.4 KiB
Go
215 lines
5.4 KiB
Go
package wallet
|
|
|
|
import (
|
|
context "context"
|
|
"fmt"
|
|
|
|
"github.com/phamminh0811/private-grpc/nockchain"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials"
|
|
)
|
|
|
|
type NockchainClient struct {
|
|
conn *grpc.ClientConn
|
|
client nockchain.NockchainServiceClient
|
|
appClient nockchain.NockAppServiceClient
|
|
}
|
|
|
|
// NewNockchainClient creates a new gRPC client connection
|
|
func NewNockchainClient(address string) (*NockchainClient, error) {
|
|
creds := credentials.NewClientTLSFromCert(nil, "")
|
|
|
|
conn, err := grpc.NewClient(
|
|
address,
|
|
grpc.WithTransportCredentials(creds),
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to connect: %w", err)
|
|
}
|
|
|
|
client := nockchain.NewNockchainServiceClient(conn)
|
|
appClient := nockchain.NewNockAppServiceClient(conn)
|
|
|
|
return &NockchainClient{
|
|
conn: conn,
|
|
client: client,
|
|
appClient: appClient,
|
|
}, nil
|
|
}
|
|
|
|
func (nc *NockchainClient) Close() error {
|
|
return nc.conn.Close()
|
|
}
|
|
|
|
func (nc *NockchainClient) WalletGetBalance(req *nockchain.GetBalanceRequest) (*nockchain.Balance, error) {
|
|
pageToken := ""
|
|
allNotes := []*nockchain.BalanceEntry{}
|
|
var height *nockchain.BlockHeight
|
|
var blockId *nockchain.Hash
|
|
page := &nockchain.PageRequest{
|
|
ClientPageItemsLimit: 0,
|
|
PageToken: pageToken,
|
|
MaxBytes: 0,
|
|
}
|
|
for {
|
|
var request *nockchain.WalletGetBalanceRequest
|
|
switch req.Selector.(type) {
|
|
case *nockchain.GetBalanceRequest_Address:
|
|
request = &nockchain.WalletGetBalanceRequest{
|
|
Selector: &nockchain.WalletGetBalanceRequest_Address{
|
|
Address: &nockchain.Base58Pubkey{
|
|
Key: req.GetAddress(),
|
|
},
|
|
},
|
|
Page: page,
|
|
}
|
|
case *nockchain.GetBalanceRequest_FirstName:
|
|
request = &nockchain.WalletGetBalanceRequest{
|
|
Selector: &nockchain.WalletGetBalanceRequest_FirstName{
|
|
FirstName: &nockchain.Base58Hash{
|
|
Hash: req.GetFirstName(),
|
|
},
|
|
},
|
|
Page: page,
|
|
}
|
|
}
|
|
resp, err := nc.client.WalletGetBalance(context.Background(), request)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
balance := nockchain.Balance{}
|
|
switch resp.Result.(type) {
|
|
case *nockchain.WalletGetBalanceResponse_Balance:
|
|
balance = *resp.GetBalance()
|
|
case *nockchain.WalletGetBalanceResponse_Error:
|
|
return nil, fmt.Errorf("error: %s", resp.GetError().Message)
|
|
default:
|
|
return nil, fmt.Errorf("invalid result type")
|
|
}
|
|
|
|
if height == nil {
|
|
height = balance.Height
|
|
blockId = balance.BlockId
|
|
}
|
|
|
|
if balance.Height != height || balance.BlockId != blockId {
|
|
return nil, fmt.Errorf("snapshot changed during pagination; retry")
|
|
}
|
|
|
|
allNotes = append(allNotes, balance.Notes...)
|
|
if balance.Page.NextPageToken == "" {
|
|
break
|
|
} else {
|
|
pageToken = balance.Page.NextPageToken
|
|
page.PageToken = pageToken
|
|
}
|
|
}
|
|
|
|
return &nockchain.Balance{
|
|
Notes: allNotes,
|
|
Height: height,
|
|
BlockId: blockId,
|
|
Page: &nockchain.PageResponse{
|
|
NextPageToken: "",
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (nc *NockchainClient) TxAccepted(txId string) (*nockchain.TransactionAcceptedResponse, error) {
|
|
req := nockchain.TransactionAcceptedRequest{
|
|
TxId: &nockchain.Base58Hash{
|
|
Hash: txId,
|
|
},
|
|
}
|
|
|
|
resp, err := nc.client.TransactionAccepted(context.Background(), &req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch resp.Result.(type) {
|
|
case *nockchain.TransactionAcceptedResponse_Accepted:
|
|
return resp, nil
|
|
case *nockchain.TransactionAcceptedResponse_Error:
|
|
return nil, fmt.Errorf("error: %s", resp.GetError().Message)
|
|
default:
|
|
return nil, fmt.Errorf("invalid result type")
|
|
}
|
|
}
|
|
|
|
func (nc *NockchainClient) WalletSendTransaction(tx *nockchain.RawTx) (*nockchain.WalletSendTransactionResponse, error) {
|
|
spends := []*nockchain.SpendEntry{}
|
|
for _, namedSpend := range tx.NamedSpends {
|
|
spendEntry, err := ConvertNamedSpend(namedSpend)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
spends = append(spends, spendEntry)
|
|
}
|
|
req := nockchain.WalletSendTransactionRequest{
|
|
TxId: ParseHash(tx.TxId),
|
|
RawTx: &nockchain.RawTransaction{
|
|
Id: ParseHash(tx.TxId),
|
|
Version: &nockchain.NoteVersion{
|
|
Value: uint32(tx.Version),
|
|
},
|
|
Spends: spends,
|
|
},
|
|
}
|
|
|
|
resp, err := nc.client.WalletSendTransaction(context.Background(), &req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch resp.Result.(type) {
|
|
case *nockchain.WalletSendTransactionResponse_Ack:
|
|
return resp, nil
|
|
case *nockchain.WalletSendTransactionResponse_Error:
|
|
return nil, fmt.Errorf("error: %s", resp.GetError().Message)
|
|
default:
|
|
return nil, fmt.Errorf("invalid result type")
|
|
}
|
|
}
|
|
|
|
func (nc *NockchainClient) Peek(pid int32, path []byte) ([]byte, error) {
|
|
req := nockchain.PeekRequest{
|
|
Pid: pid,
|
|
Path: path,
|
|
}
|
|
|
|
resp, err := nc.appClient.Peek(context.Background(), &req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
switch resp.Result.(type) {
|
|
case *nockchain.PeekResponse_Data:
|
|
return resp.GetData(), nil
|
|
case *nockchain.PeekResponse_Error:
|
|
return nil, fmt.Errorf("error: %s", resp.GetError().Message)
|
|
default:
|
|
return nil, fmt.Errorf("invalid result type")
|
|
}
|
|
}
|
|
|
|
func (nc *NockchainClient) Poke(pid int32, wire *nockchain.Wire, payload []byte) (bool, error) {
|
|
req := nockchain.PokeRequest{
|
|
Pid: pid,
|
|
Wire: wire,
|
|
Payload: payload,
|
|
}
|
|
|
|
resp, err := nc.appClient.Poke(context.Background(), &req)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
switch resp.Result.(type) {
|
|
case *nockchain.PokeResponse_Acknowledged:
|
|
return resp.GetAcknowledged(), nil
|
|
case *nockchain.PokeResponse_Error:
|
|
return false, fmt.Errorf("error: %s", resp.GetError().Message)
|
|
default:
|
|
return false, fmt.Errorf("invalid result type")
|
|
}
|
|
}
|