OSDN Git Service

add logs (#371)
[bytom/vapor.git] / toolbar / apinode / transaction.go
1 package apinode
2
3 import (
4         "encoding/json"
5
6         "github.com/vapor/blockchain/txbuilder"
7         "github.com/vapor/consensus"
8         "github.com/vapor/errors"
9         "github.com/vapor/protocol/bc"
10         "github.com/vapor/protocol/bc/types"
11 )
12
13 type SpendAccountAction struct {
14         AccountID string `json:"account_id"`
15         *bc.AssetAmount
16 }
17
18 func (s *SpendAccountAction) MarshalJSON() ([]byte, error) {
19         return json.Marshal(&struct {
20                 Type      string `json:"type"`
21                 AccountID string `json:"account_id"`
22                 *bc.AssetAmount
23         }{
24                 Type:        "spend_account",
25                 AccountID:   s.AccountID,
26                 AssetAmount: s.AssetAmount,
27         })
28 }
29
30 type ControlAddressAction struct {
31         Address string `json:"address"`
32         *bc.AssetAmount
33 }
34
35 func (c *ControlAddressAction) MarshalJSON() ([]byte, error) {
36         return json.Marshal(&struct {
37                 Type    string `json:"type"`
38                 Address string `json:"address"`
39                 *bc.AssetAmount
40         }{
41                 Type:        "control_address",
42                 Address:     c.Address,
43                 AssetAmount: c.AssetAmount,
44         })
45 }
46
47 func (n *Node) BatchSendBTM(accountID, password string, outputs map[string]uint64) (string, error) {
48         totalBTM := uint64(1000000)
49         actions := []interface{}{}
50         for address, amount := range outputs {
51                 actions = append(actions, &ControlAddressAction{
52                         Address:     address,
53                         AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: amount},
54                 })
55                 totalBTM += amount
56         }
57
58         actions = append(actions, &SpendAccountAction{
59                 AccountID:   accountID,
60                 AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: totalBTM},
61         })
62
63         tpl, err := n.buildTx(actions)
64         if err != nil {
65                 return "", err
66         }
67
68         tpl, err = n.signTx(tpl, password)
69         if err != nil {
70                 return "", err
71         }
72
73         return n.SubmitTx(tpl.Transaction)
74 }
75
76 type buildTxReq struct {
77         Actions []interface{} `json:"actions"`
78 }
79
80 func (n *Node) buildTx(actions []interface{}) (*txbuilder.Template, error) {
81         url := "/build-transaction"
82         payload, err := json.Marshal(&buildTxReq{Actions: actions})
83         if err != nil {
84                 return nil, errors.Wrap(err, "Marshal spend request")
85         }
86
87         result := &txbuilder.Template{}
88         return result, n.request(url, payload, result)
89 }
90
91 type signTxReq struct {
92         Tx       *txbuilder.Template `json:"transaction"`
93         Password string              `json:"password"`
94 }
95
96 type signTxResp struct {
97         Tx           *txbuilder.Template `json:"transaction"`
98         SignComplete bool                `json:"sign_complete"`
99 }
100
101 func (n *Node) signTx(tpl *txbuilder.Template, password string) (*txbuilder.Template, error) {
102         url := "/sign-transaction"
103         payload, err := json.Marshal(&signTxReq{Tx: tpl, Password: password})
104         if err != nil {
105                 return nil, errors.Wrap(err, "json marshal")
106         }
107
108         resp := &signTxResp{}
109         if err := n.request(url, payload, resp); err != nil {
110                 return nil, err
111         }
112
113         if !resp.SignComplete {
114                 return nil, errors.New("sign fail")
115         }
116
117         return resp.Tx, nil
118 }
119
120 type submitTxReq struct {
121         Tx *types.Tx `json:"raw_transaction"`
122 }
123
124 type submitTxResp struct {
125         TxID string `json:"tx_id"`
126 }
127
128 func (n *Node) SubmitTx(tx *types.Tx) (string, error) {
129         url := "/submit-transaction"
130         payload, err := json.Marshal(submitTxReq{Tx: tx})
131         if err != nil {
132                 return "", errors.Wrap(err, "json marshal")
133         }
134
135         res := &submitTxResp{}
136         return res.TxID, n.request(url, payload, res)
137 }