OSDN Git Service

zhen xiang
[bytom/vapor.git] / federation / service / node.go
1 package service
2
3 import (
4         "encoding/json"
5
6         btmTypes "github.com/bytom/protocol/bc/types"
7
8         "github.com/vapor/errors"
9         "github.com/vapor/federation/util"
10         "github.com/vapor/protocol/bc"
11         vaporTypes "github.com/vapor/protocol/bc/types"
12 )
13
14 // Node can invoke the api which provide by the full node server
15 type Node struct {
16         ip string
17 }
18
19 // Node create a api client with target server
20 func NewNode(ip string) *Node {
21         return &Node{ip: ip}
22 }
23
24 func (n *Node) GetBlockByHash(hash string) (string, *bc.TransactionStatus, error) {
25         return n.getRawBlock(&getRawBlockReq{BlockHash: hash})
26 }
27
28 func (n *Node) GetBlockByHeight(height uint64) (string, *bc.TransactionStatus, error) {
29         return n.getRawBlock(&getRawBlockReq{BlockHeight: height})
30 }
31
32 type getBlockCountResp struct {
33         BlockCount uint64 `json:"block_count"`
34 }
35
36 func (n *Node) GetBlockCount() (uint64, error) {
37         url := "/get-block-count"
38         res := &getBlockCountResp{}
39         return res.BlockCount, n.request(url, nil, res)
40 }
41
42 type getRawBlockReq struct {
43         BlockHeight uint64 `json:"block_height"`
44         BlockHash   string `json:"block_hash"`
45 }
46
47 type getRawBlockResp struct {
48         RawBlock string `json:"raw_block"`
49         // TransactionStatus has same marshalling rule for both bytom and vapor
50         TransactionStatus *bc.TransactionStatus `json:"transaction_status"`
51 }
52
53 func (n *Node) getRawBlock(req *getRawBlockReq) (string, *bc.TransactionStatus, error) {
54         url := "/get-raw-block"
55         payload, err := json.Marshal(req)
56         if err != nil {
57                 return "", nil, errors.Wrap(err, "json marshal")
58         }
59
60         res := &getRawBlockResp{}
61         return res.RawBlock, res.TransactionStatus, n.request(url, payload, res)
62 }
63
64 type submitMainchainTxReq struct {
65         Tx *btmTypes.Tx `json:"raw_transaction"`
66 }
67
68 type submitSidechainTxReq struct {
69         Tx *vaporTypes.Tx `json:"raw_transaction"`
70 }
71
72 type submitTxResp struct {
73         TxID string `json:"tx_id"`
74 }
75
76 func (n *Node) SubmitTx(tx interface{} /*, isMainchain bool*/) (string, error) {
77         url := "/submit-transaction"
78         var payload []byte
79         var err error
80
81         switch tx := tx.(type) {
82         case *btmTypes.Tx:
83                 payload, err = json.Marshal(submitMainchainTxReq{Tx: tx})
84                 if err != nil {
85                         return "", errors.Wrap(err, "json marshal")
86                 }
87
88         case *vaporTypes.Tx:
89                 payload, err = json.Marshal(submitSidechainTxReq{Tx: tx})
90                 if err != nil {
91                         return "", errors.Wrap(err, "json marshal")
92                 }
93
94         default:
95                 return "", errors.New("unknown tx type")
96         }
97
98         res := &submitTxResp{}
99         return res.TxID, n.request(url, payload, res)
100 }
101
102 type response struct {
103         Status    string          `json:"status"`
104         Data      json.RawMessage `json:"data"`
105         ErrDetail string          `json:"error_detail"`
106 }
107
108 func (n *Node) request(url string, payload []byte, respData interface{}) error {
109         resp := &response{}
110         if err := util.Post(n.ip+url, payload, resp); err != nil {
111                 return err
112         }
113
114         if resp.Status != "success" {
115                 return errors.New(resp.ErrDetail)
116         }
117
118         return json.Unmarshal(resp.Data, respData)
119 }