cosmos-sdk/x/stake/client/rest/tx.go

121 lines
3.1 KiB
Go
Raw Normal View History

2018-05-14 16:43:51 -07:00
package rest
import (
2018-05-24 08:41:17 -07:00
"bytes"
2018-05-14 16:43:51 -07:00
"encoding/json"
"io/ioutil"
"net/http"
"github.com/gorilla/mux"
"github.com/tendermint/go-crypto/keys"
ctypes "github.com/tendermint/tendermint/rpc/core/types"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
"github.com/cosmos/cosmos-sdk/x/stake"
)
func registerTxRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, kb keys.Keybase) {
2018-05-24 08:41:17 -07:00
r.HandleFunc(
"/stake/delegations",
editDelegationsRequestHandlerFn(cdc, kb, ctx),
).Methods("POST")
2018-05-14 16:43:51 -07:00
}
2018-05-24 08:41:17 -07:00
type editDelegationsBody struct {
LocalAccountName string `json:"name"`
Password string `json:"password"`
ChainID string `json:"chain_id"`
Sequence int64 `json:"sequence"`
Delegate []stake.MsgDelegate `json:"delegate"`
Unbond []stake.MsgUnbond `json:"unbond"`
2018-05-14 16:43:51 -07:00
}
2018-05-24 08:41:17 -07:00
func editDelegationsRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc {
2018-05-14 16:43:51 -07:00
return func(w http.ResponseWriter, r *http.Request) {
2018-05-24 08:41:17 -07:00
var m editDelegationsBody
2018-05-14 16:43:51 -07:00
body, err := ioutil.ReadAll(r.Body)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
err = json.Unmarshal(body, &m)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte(err.Error()))
return
}
info, err := kb.Get(m.LocalAccountName)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error()))
return
}
// build messages
messages := make([]sdk.Msg, len(m.Delegate)+len(m.Unbond))
i := 0
2018-05-24 08:41:17 -07:00
for _, msg := range m.Delegate {
if !bytes.Equal(info.Address(), msg.DelegatorAddr) {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Must use own delegator address"))
return
}
messages[i] = msg
i++
2018-05-14 16:43:51 -07:00
}
2018-05-24 08:41:17 -07:00
for _, msg := range m.Unbond {
if !bytes.Equal(info.Address(), msg.DelegatorAddr) {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte("Must use own delegator address"))
return
}
messages[i] = msg
i++
2018-05-14 16:43:51 -07:00
}
// sign messages
signedTxs := make([][]byte, len(messages[:]))
for i, msg := range messages {
2018-05-14 16:43:51 -07:00
// increment sequence for each message
ctx = ctx.WithSequence(m.Sequence)
m.Sequence++
txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, msg, cdc)
if err != nil {
w.WriteHeader(http.StatusUnauthorized)
w.Write([]byte(err.Error()))
return
}
signedTxs[i] = txBytes
2018-05-14 16:43:51 -07:00
}
// send
// XXX the operation might not be atomic if a tx fails
// should we have a sdk.MultiMsg type to make sending atomic?
results := make([]*ctypes.ResultBroadcastTxCommit, len(signedTxs[:]))
for i, txBytes := range signedTxs {
2018-05-14 16:43:51 -07:00
res, err := ctx.BroadcastTx(txBytes)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
results[i] = res
2018-05-14 16:43:51 -07:00
}
output, err := json.MarshalIndent(results[:], "", " ")
2018-05-14 16:43:51 -07:00
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(err.Error()))
return
}
w.Write(output)
}
}