cosmos-sdk/x/ibc/client/rest/transfer.go

122 lines
3.5 KiB
Go
Raw Normal View History

2018-03-19 10:13:28 -07:00
package rest
import (
"io/ioutil"
"net/http"
"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/client/utils"
2018-08-06 11:11:30 -07:00
"github.com/cosmos/cosmos-sdk/crypto/keys"
2018-03-19 10:13:28 -07:00
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/wire"
2018-08-06 11:11:30 -07:00
authctx "github.com/cosmos/cosmos-sdk/x/auth/client/context"
2018-03-19 10:13:28 -07:00
"github.com/cosmos/cosmos-sdk/x/ibc"
2018-08-06 11:11:30 -07:00
"github.com/gorilla/mux"
2018-03-19 10:13:28 -07:00
)
2018-04-18 21:49:24 -07:00
// RegisterRoutes - Central function to define routes that get registered by the main application
2018-08-06 11:11:30 -07:00
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, cdc *wire.Codec, kb keys.Keybase) {
r.HandleFunc("/ibc/{destchain}/{address}/send", TransferRequestHandlerFn(cdc, kb, cliCtx)).Methods("POST")
2018-04-18 21:49:24 -07:00
}
2018-03-19 10:13:28 -07:00
type transferBody struct {
// Fees sdk.Coin `json="fees"`
Amount sdk.Coins `json:"amount"`
LocalAccountName string `json:"name"`
Password string `json:"password"`
SrcChainID string `json:"src_chain_id"`
AccountNumber int64 `json:"account_number"`
2018-03-19 10:13:28 -07:00
Sequence int64 `json:"sequence"`
Gas int64 `json:"gas"`
GasAdjustment string `json:"gas_adjustment"`
2018-03-19 10:13:28 -07:00
}
// TransferRequestHandler - http request handler to transfer coins to a address
// on a different chain via IBC
// nolint: gocyclo
2018-08-06 11:11:30 -07:00
func TransferRequestHandlerFn(cdc *wire.Codec, kb keys.Keybase, cliCtx context.CLIContext) http.HandlerFunc {
2018-03-19 10:13:28 -07:00
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
destChainID := vars["destchain"]
bech32addr := vars["address"]
2018-07-09 16:06:05 -07:00
to, err := sdk.AccAddressFromBech32(bech32addr)
if err != nil {
utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error())
return
}
2018-03-19 10:13:28 -07:00
var m transferBody
body, err := ioutil.ReadAll(r.Body)
if err != nil {
utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error())
2018-03-19 10:13:28 -07:00
return
}
2018-08-06 11:11:30 -07:00
2018-04-07 10:56:49 -07:00
err = cdc.UnmarshalJSON(body, &m)
2018-03-19 10:13:28 -07:00
if err != nil {
utils.WriteErrorResponse(&w, http.StatusBadRequest, err.Error())
2018-03-19 10:13:28 -07:00
return
}
info, err := kb.Get(m.LocalAccountName)
if err != nil {
utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error())
2018-03-19 10:13:28 -07:00
return
}
// build message
2018-07-06 00:06:53 -07:00
packet := ibc.NewIBCPacket(sdk.AccAddress(info.GetPubKey().Address()), to, m.Amount, m.SrcChainID, destChainID)
2018-03-19 10:13:28 -07:00
msg := ibc.IBCTransferMsg{packet}
2018-08-06 11:11:30 -07:00
txCtx := authctx.TxContext{
Codec: cdc,
ChainID: m.SrcChainID,
AccountNumber: m.AccountNumber,
Sequence: m.Sequence,
Gas: m.Gas,
}
adjustment, ok := utils.ParseFloat64OrReturnBadRequest(&w, m.GasAdjustment, client.DefaultGasAdjustment)
if !ok {
return
}
cliCtx = cliCtx.WithGasAdjustment(adjustment)
if utils.HasDryRunArg(r) || m.Gas == 0 {
newCtx, err := utils.EnrichCtxWithGas(txCtx, cliCtx, m.LocalAccountName, []sdk.Msg{msg})
if err != nil {
2018-08-24 06:57:45 -07:00
utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error())
return
}
if utils.HasDryRunArg(r) {
utils.WriteSimulationResponse(&w, txCtx.Gas)
return
}
2018-08-24 01:48:02 -07:00
txCtx = newCtx
}
2018-08-06 11:11:30 -07:00
txBytes, err := txCtx.BuildAndSign(m.LocalAccountName, m.Password, []sdk.Msg{msg})
2018-03-19 10:13:28 -07:00
if err != nil {
utils.WriteErrorResponse(&w, http.StatusUnauthorized, err.Error())
2018-03-19 10:13:28 -07:00
return
}
2018-08-06 11:11:30 -07:00
res, err := cliCtx.BroadcastTx(txBytes)
2018-03-19 10:13:28 -07:00
if err != nil {
utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error())
2018-03-19 10:13:28 -07:00
return
}
2018-04-07 10:56:49 -07:00
output, err := cdc.MarshalJSON(res)
2018-03-19 10:13:28 -07:00
if err != nil {
utils.WriteErrorResponse(&w, http.StatusInternalServerError, err.Error())
2018-03-19 10:13:28 -07:00
return
}
w.Write(output)
}
}