package apinode import ( "encoding/json" "github.com/vapor/blockchain/txbuilder" "github.com/vapor/consensus" "github.com/vapor/errors" "github.com/vapor/protocol/bc" "github.com/vapor/protocol/bc/types" ) type SpendAccountAction struct { AccountID string `json:"account_id"` *bc.AssetAmount } func (s *SpendAccountAction) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string `json:"type"` AccountID string `json:"account_id"` *bc.AssetAmount }{ Type: "spend_account", AccountID: s.AccountID, AssetAmount: s.AssetAmount, }) } type ControlAddressAction struct { Address string `json:"address"` *bc.AssetAmount } func (c *ControlAddressAction) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string `json:"type"` Address string `json:"address"` *bc.AssetAmount }{ Type: "control_address", Address: c.Address, AssetAmount: c.AssetAmount, }) } func (n *Node) BatchSendBTM(accountID, password string, outputs map[string]uint64) error { totalBTM := uint64(10000000) actions := []interface{}{} for address, amount := range outputs { actions = append(actions, &ControlAddressAction{ Address: address, AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: amount}, }) totalBTM += amount } actions = append(actions, &SpendAccountAction{ AccountID: accountID, AssetAmount: &bc.AssetAmount{AssetId: consensus.BTMAssetID, Amount: totalBTM}, }) tpl, err := n.buildTx(actions) if err != nil { return err } tpl, err = n.signTx(tpl, password) if err != nil { return err } _, err = n.SubmitTx(tpl.Transaction) return err } type buildTxReq struct { Actions []interface{} `json:"actions"` } func (n *Node) buildTx(actions []interface{}) (*txbuilder.Template, error) { url := "/build-transaction" payload, err := json.Marshal(&buildTxReq{Actions: actions}) if err != nil { return nil, errors.Wrap(err, "Marshal spend request") } result := &txbuilder.Template{} return result, n.request(url, payload, result) } type signTxReq struct { Tx *txbuilder.Template `json:"transaction"` Password string `json:"password"` } type signTxResp struct { Tx *txbuilder.Template `json:"transaction"` SignComplete bool `json:"sign_complete"` } func (n *Node) signTx(tpl *txbuilder.Template, password string) (*txbuilder.Template, error) { url := "/sign-transaction" payload, err := json.Marshal(&signTxReq{Tx: tpl, Password: password}) if err != nil { return nil, errors.Wrap(err, "json marshal") } resp := &signTxResp{} if err := n.request(url, payload, resp); err != nil { return nil, err } if !resp.SignComplete { return nil, errors.New("sign fail") } return resp.Tx, nil } type submitTxReq struct { Tx *types.Tx `json:"raw_transaction"` } type submitTxResp struct { TxID string `json:"tx_id"` } func (n *Node) SubmitTx(tx *types.Tx) (string, error) { url := "/submit-transaction" payload, err := json.Marshal(submitTxReq{Tx: tx}) if err != nil { return "", errors.Wrap(err, "json marshal") } res := &submitTxResp{} return res.TxID, n.request(url, payload, res) }