package rest import ( "io/ioutil" "net/http" "github.com/cosmos/cosmos-sdk/crypto/keys" "github.com/gorilla/mux" "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/bank" "github.com/cosmos/cosmos-sdk/x/bank/client" ) // RegisterRoutes - Central function to define routes that get registered by the main application func RegisterRoutes(ctx context.CoreContext, r *mux.Router, cdc *wire.Codec, kb keys.Keybase) { r.HandleFunc("/accounts/{address}/send", SendRequestHandlerFn(cdc, kb, ctx)).Methods("POST") } type sendBody struct { // fees is not used currently // Fees sdk.Coin `json="fees"` Amount sdk.Coins `json:"amount"` LocalAccountName string `json:"name"` Password string `json:"password"` ChainID string `json:"chain_id"` AccountNumber int64 `json:"account_number"` Sequence int64 `json:"sequence"` Gas int64 `json:"gas"` } var msgCdc = wire.NewCodec() func init() { bank.RegisterWire(msgCdc) } // SendRequestHandlerFn - http request handler to send coins to a address func SendRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, ctx context.CoreContext) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // collect data vars := mux.Vars(r) bech32addr := vars["address"] to, err := sdk.AccAddressFromBech32(bech32addr) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } var m sendBody body, err := ioutil.ReadAll(r.Body) if err != nil { w.WriteHeader(http.StatusBadRequest) w.Write([]byte(err.Error())) return } err = msgCdc.UnmarshalJSON(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 message msg := client.BuildMsg(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount) if err != nil { // XXX rechecking same error ? w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } // add gas to context ctx = ctx.WithGas(m.Gas) // add chain-id to context ctx = ctx.WithChainID(m.ChainID) // sign ctx = ctx.WithAccountNumber(m.AccountNumber) ctx = ctx.WithSequence(m.Sequence) txBytes, err := ctx.SignAndBuild(m.LocalAccountName, m.Password, []sdk.Msg{msg}, cdc) if err != nil { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(err.Error())) return } // send res, err := ctx.BroadcastTx(txBytes) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } output, err := wire.MarshalJSONIndent(cdc, res) if err != nil { w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(err.Error())) return } w.Write(output) } }