Gaia Lite Generate Only Support (w/o Keybase) (#3396)
This commit is contained in:
parent
1a656e7023
commit
90797f5e09
|
@ -3,6 +3,8 @@
|
|||
BREAKING CHANGES
|
||||
|
||||
* Gaia REST API (`gaiacli advanced rest-server`)
|
||||
* [\#3284](https://github.com/cosmos/cosmos-sdk/issues/3284) Rename the `name`
|
||||
field to `from` in the `base_req` body.
|
||||
|
||||
* Gaia CLI (`gaiacli`)
|
||||
- [#3399](https://github.com/cosmos/cosmos-sdk/pull/3399) Add `gaiad validate-genesis` command to facilitate checking of genesis files
|
||||
|
@ -32,6 +34,11 @@ FEATURES
|
|||
IMPROVEMENTS
|
||||
|
||||
* Gaia REST API
|
||||
* [\#3284](https://github.com/cosmos/cosmos-sdk/issues/3284) Update Gaia Lite
|
||||
REST service to support the following:
|
||||
* Automatic account number and sequence population when fields are omitted
|
||||
* Generate only functionality no longer requires access to a local Keybase
|
||||
* `from` field in the `base_req` body can be a Keybase name or account address
|
||||
|
||||
* Gaia CLI (`gaiacli`)
|
||||
|
||||
|
|
|
@ -8,7 +8,9 @@ import (
|
|||
"path/filepath"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cryptokeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
|
@ -19,14 +21,10 @@ import (
|
|||
tmliteProxy "github.com/tendermint/tendermint/lite/proxy"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
cskeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
)
|
||||
|
||||
var (
|
||||
verifier tmlite.Verifier
|
||||
)
|
||||
var verifier tmlite.Verifier
|
||||
|
||||
// CLIContext implements a typical CLI context created in SDK modules for
|
||||
// transaction handling and queries.
|
||||
|
@ -47,8 +45,8 @@ type CLIContext struct {
|
|||
Verifier tmlite.Verifier
|
||||
Simulate bool
|
||||
GenerateOnly bool
|
||||
fromAddress types.AccAddress
|
||||
fromName string
|
||||
FromAddress sdk.AccAddress
|
||||
FromName string
|
||||
Indent bool
|
||||
}
|
||||
|
||||
|
@ -63,7 +61,11 @@ func NewCLIContext() CLIContext {
|
|||
}
|
||||
|
||||
from := viper.GetString(client.FlagFrom)
|
||||
fromAddress, fromName := fromFields(from)
|
||||
fromAddress, fromName, err := GetFromFields(from)
|
||||
if err != nil {
|
||||
fmt.Printf("failed to get from fields: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// We need to use a single verifier for all contexts
|
||||
if verifier == nil {
|
||||
|
@ -85,8 +87,8 @@ func NewCLIContext() CLIContext {
|
|||
Verifier: verifier,
|
||||
Simulate: viper.GetBool(client.FlagDryRun),
|
||||
GenerateOnly: viper.GetBool(client.FlagGenerateOnly),
|
||||
fromAddress: fromAddress,
|
||||
fromName: fromName,
|
||||
FromAddress: fromAddress,
|
||||
FromName: fromName,
|
||||
Indent: viper.GetBool(client.FlagIndentResponse),
|
||||
}
|
||||
}
|
||||
|
@ -137,37 +139,6 @@ func createVerifier() tmlite.Verifier {
|
|||
return verifier
|
||||
}
|
||||
|
||||
func fromFields(from string) (fromAddr types.AccAddress, fromName string) {
|
||||
if from == "" {
|
||||
return nil, ""
|
||||
}
|
||||
|
||||
keybase, err := keys.GetKeyBase()
|
||||
if err != nil {
|
||||
fmt.Println("no keybase found")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var info cskeys.Info
|
||||
if addr, err := types.AccAddressFromBech32(from); err == nil {
|
||||
info, err = keybase.GetByAddress(addr)
|
||||
if err != nil {
|
||||
fmt.Printf("could not find key %s\n", from)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
info, err = keybase.Get(from)
|
||||
if err != nil {
|
||||
fmt.Printf("could not find key %s\n", from)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
fromAddr = info.GetAddress()
|
||||
fromName = info.GetName()
|
||||
return
|
||||
}
|
||||
|
||||
// WithCodec returns a copy of the context with an updated codec.
|
||||
func (ctx CLIContext) WithCodec(cdc *codec.Codec) CLIContext {
|
||||
ctx.Codec = cdc
|
||||
|
@ -255,6 +226,19 @@ func (ctx CLIContext) WithSimulation(simulate bool) CLIContext {
|
|||
return ctx
|
||||
}
|
||||
|
||||
// WithFromName returns a copy of the context with an updated from account name.
|
||||
func (ctx CLIContext) WithFromName(name string) CLIContext {
|
||||
ctx.FromName = name
|
||||
return ctx
|
||||
}
|
||||
|
||||
// WithFromAddress returns a copy of the context with an updated from account
|
||||
// address.
|
||||
func (ctx CLIContext) WithFromAddress(addr sdk.AccAddress) CLIContext {
|
||||
ctx.FromAddress = addr
|
||||
return ctx
|
||||
}
|
||||
|
||||
// PrintOutput prints output while respecting output and indent flags
|
||||
// NOTE: pass in marshalled structs that have been unmarshaled
|
||||
// because this function will panic on marshaling errors
|
||||
|
@ -279,3 +263,31 @@ func (ctx CLIContext) PrintOutput(toPrint fmt.Stringer) (err error) {
|
|||
fmt.Println(string(out))
|
||||
return
|
||||
}
|
||||
|
||||
// GetFromFields returns a from account address and Keybase name given either
|
||||
// an address or key name.
|
||||
func GetFromFields(from string) (sdk.AccAddress, string, error) {
|
||||
if from == "" {
|
||||
return nil, "", nil
|
||||
}
|
||||
|
||||
keybase, err := keys.GetKeyBase()
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
var info cryptokeys.Info
|
||||
if addr, err := sdk.AccAddressFromBech32(from); err == nil {
|
||||
info, err = keybase.GetByAddress(addr)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
} else {
|
||||
info, err = keybase.Get(from)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
}
|
||||
|
||||
return info.GetAddress(), info.GetName(), nil
|
||||
}
|
||||
|
|
|
@ -82,13 +82,13 @@ func (ctx CLIContext) GetAccount(address []byte) (auth.Account, error) {
|
|||
}
|
||||
|
||||
// GetFromAddress returns the from address from the context's name.
|
||||
func (ctx CLIContext) GetFromAddress() (sdk.AccAddress, error) {
|
||||
return ctx.fromAddress, nil
|
||||
func (ctx CLIContext) GetFromAddress() sdk.AccAddress {
|
||||
return ctx.FromAddress
|
||||
}
|
||||
|
||||
// GetFromName returns the key name for the current context.
|
||||
func (ctx CLIContext) GetFromName() (string, error) {
|
||||
return ctx.fromName, nil
|
||||
func (ctx CLIContext) GetFromName() string {
|
||||
return ctx.FromName
|
||||
}
|
||||
|
||||
// GetAccountNumber returns the next account number for the given account
|
||||
|
@ -116,11 +116,7 @@ func (ctx CLIContext) GetAccountSequence(address []byte) (uint64, error) {
|
|||
// EnsureAccountExists ensures that an account exists for a given context. An
|
||||
// error is returned if it does not.
|
||||
func (ctx CLIContext) EnsureAccountExists() error {
|
||||
addr, err := ctx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addr := ctx.GetFromAddress()
|
||||
accountBytes, err := ctx.QueryStore(auth.AddressStoreKey(addr), ctx.AccountStore)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -2,7 +2,6 @@ package lcd
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
@ -26,6 +25,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/version"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
authrest "github.com/cosmos/cosmos-sdk/x/auth/client/rest"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/gov"
|
||||
"github.com/cosmos/cosmos-sdk/x/slashing"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
|
@ -211,16 +211,17 @@ func TestCoinSend(t *testing.T) {
|
|||
// run simulation and test success with estimated gas
|
||||
res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, "10000", 1.0, true, false, fees)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
var responseBody struct {
|
||||
GasEstimate int64 `json:"gas_estimate"`
|
||||
}
|
||||
require.Nil(t, json.Unmarshal([]byte(body), &responseBody))
|
||||
|
||||
var gasEstResp utils.GasEstimateResponse
|
||||
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &gasEstResp))
|
||||
require.NotZero(t, gasEstResp.GasEstimate)
|
||||
|
||||
acc = getAccount(t, port, addr)
|
||||
require.Equal(t, expectedBalance.Amount, acc.GetCoins().AmountOf(stakingTypes.DefaultBondDenom))
|
||||
|
||||
res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr,
|
||||
fmt.Sprintf("%d", responseBody.GasEstimate), 1.0, false, false, fees)
|
||||
// run successful tx
|
||||
gas := fmt.Sprintf("%d", gasEstResp.GasEstimate)
|
||||
res, body, _ = doTransferWithGas(t, port, seed, name1, memo, pw, addr, gas, 1.0, false, false, fees)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
err = cdc.UnmarshalJSON([]byte(body), &resultTx)
|
||||
|
@ -235,15 +236,67 @@ func TestCoinSend(t *testing.T) {
|
|||
require.Equal(t, expectedBalance.Amount.SubRaw(1), acc.GetCoins().AmountOf(stakingTypes.DefaultBondDenom))
|
||||
}
|
||||
|
||||
func TestCoinSendAccAuto(t *testing.T) {
|
||||
addr, seed := CreateAddr(t, name1, pw, GetKeyBase(t))
|
||||
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
acc := getAccount(t, port, addr)
|
||||
initialBalance := acc.GetCoins()
|
||||
|
||||
// send a transfer tx without specifying account number and sequence
|
||||
res, body, _ := doTransferWithGasAccAuto(t, port, seed, name1, memo, pw, "200000", 1.0, false, false, fees)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
// query sender
|
||||
acc = getAccount(t, port, addr)
|
||||
coins := acc.GetCoins()
|
||||
expectedBalance := initialBalance[0].Minus(fees[0])
|
||||
|
||||
require.Equal(t, stakingTypes.DefaultBondDenom, coins[0].Denom)
|
||||
require.Equal(t, expectedBalance.Amount.SubRaw(1), coins[0].Amount)
|
||||
}
|
||||
|
||||
func TestCoinSendGenerateOnly(t *testing.T) {
|
||||
addr, seed := CreateAddr(t, name1, pw, GetKeyBase(t))
|
||||
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
|
||||
// generate only
|
||||
res, body, _ := doTransferWithGas(t, port, seed, "", memo, "", addr, "200000", 1, false, true, fees)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var stdTx auth.StdTx
|
||||
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &stdTx))
|
||||
require.Equal(t, len(stdTx.Msgs), 1)
|
||||
require.Equal(t, stdTx.GetMsgs()[0].Route(), "bank")
|
||||
require.Equal(t, stdTx.GetMsgs()[0].GetSigners(), []sdk.AccAddress{addr})
|
||||
require.Equal(t, 0, len(stdTx.Signatures))
|
||||
require.Equal(t, memo, stdTx.Memo)
|
||||
require.NotZero(t, stdTx.Fee.Gas)
|
||||
require.IsType(t, stdTx.GetMsgs()[0], bank.MsgSend{})
|
||||
require.Equal(t, addr, stdTx.GetMsgs()[0].(bank.MsgSend).Inputs[0].Address)
|
||||
}
|
||||
|
||||
func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
|
||||
addr, seed := CreateAddr(t, name1, pw, GetKeyBase(t))
|
||||
cleanup, _, _, port := InitializeTestLCD(t, 1, []sdk.AccAddress{addr})
|
||||
defer cleanup()
|
||||
acc := getAccount(t, port, addr)
|
||||
|
||||
// generate TX
|
||||
res, body, _ := doTransferWithGas(t, port, seed, name1, memo, "", addr, client.GasFlagAuto, 1, false, true, fees)
|
||||
// simulate tx
|
||||
res, body, _ := doTransferWithGas(t, port, seed, name1, memo, "", addr, client.GasFlagAuto, 1, true, false, fees)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var gasEstResp utils.GasEstimateResponse
|
||||
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &gasEstResp))
|
||||
require.NotZero(t, gasEstResp.GasEstimate)
|
||||
|
||||
// generate tx
|
||||
gas := fmt.Sprintf("%d", gasEstResp.GasEstimate)
|
||||
res, body, _ = doTransferWithGas(t, port, seed, name1, memo, "", addr, gas, 1, false, true, fees)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
|
||||
var msg auth.StdTx
|
||||
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &msg))
|
||||
require.Equal(t, len(msg.Msgs), 1)
|
||||
|
@ -251,6 +304,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
|
|||
require.Equal(t, msg.Msgs[0].GetSigners(), []sdk.AccAddress{addr})
|
||||
require.Equal(t, 0, len(msg.Signatures))
|
||||
require.Equal(t, memo, msg.Memo)
|
||||
require.NotZero(t, msg.Fee.Gas)
|
||||
|
||||
gasEstimate := int64(msg.Fee.Gas)
|
||||
accnum := acc.GetAccountNumber()
|
||||
|
@ -268,6 +322,7 @@ func TestCoinSendGenerateSignAndBroadcast(t *testing.T) {
|
|||
}
|
||||
json, err := cdc.MarshalJSON(payload)
|
||||
require.Nil(t, err)
|
||||
|
||||
res, body = Request(t, port, "POST", "/tx/sign", json)
|
||||
require.Equal(t, http.StatusOK, res.StatusCode, body)
|
||||
require.Nil(t, cdc.UnmarshalJSON([]byte(body), &signedMsg))
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
swagger: '2.0'
|
||||
swagger: "2.0"
|
||||
info:
|
||||
version: "3.0"
|
||||
title: Gaia-Lite for Cosmos
|
||||
|
@ -411,7 +411,7 @@ paths:
|
|||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/KeyOutput'
|
||||
$ref: "#/definitions/KeyOutput"
|
||||
500:
|
||||
description: Server internal error
|
||||
post:
|
||||
|
@ -723,16 +723,6 @@ paths:
|
|||
post:
|
||||
summary: Submit an unbonding delegation
|
||||
parameters:
|
||||
- in: query
|
||||
name: simulate
|
||||
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
|
||||
required: false
|
||||
type: boolean
|
||||
- in: query
|
||||
name: generate_only
|
||||
description: if true, build an unsigned transaction and write it back
|
||||
required: false
|
||||
type: boolean
|
||||
- in: body
|
||||
name: delegation
|
||||
description: The password of the account to remove from the KMS
|
||||
|
@ -836,16 +826,6 @@ paths:
|
|||
post:
|
||||
summary: Submit a redelegation
|
||||
parameters:
|
||||
- in: query
|
||||
name: simulate
|
||||
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
|
||||
required: false
|
||||
type: boolean
|
||||
- in: query
|
||||
name: generate_only
|
||||
description: if true, build an unsigned transaction and write it back
|
||||
required: false
|
||||
type: boolean
|
||||
- in: body
|
||||
name: delegation
|
||||
description: The password of the account to remove from the KMS
|
||||
|
@ -1149,7 +1129,7 @@ paths:
|
|||
name: validatorAddr
|
||||
required: true
|
||||
in: path
|
||||
- description: ''
|
||||
- description: ""
|
||||
name: UnjailBody
|
||||
in: body
|
||||
required: true
|
||||
|
@ -1359,7 +1339,7 @@ paths:
|
|||
name: proposalId
|
||||
required: true
|
||||
in: path
|
||||
- description: ''
|
||||
- description: ""
|
||||
name: post_deposit_body
|
||||
in: body
|
||||
required: true
|
||||
|
@ -1645,16 +1625,6 @@ paths:
|
|||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: query
|
||||
name: simulate
|
||||
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
|
||||
required: false
|
||||
type: boolean
|
||||
- in: query
|
||||
name: generate_only
|
||||
description: if true, build an unsigned transaction and write it back
|
||||
required: false
|
||||
type: boolean
|
||||
- in: body
|
||||
name: Withdraw request body
|
||||
schema:
|
||||
|
@ -1712,16 +1682,6 @@ paths:
|
|||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: query
|
||||
name: simulate
|
||||
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
|
||||
required: false
|
||||
type: boolean
|
||||
- in: query
|
||||
name: generate_only
|
||||
description: if true, build an unsigned transaction and write it back
|
||||
required: false
|
||||
type: boolean
|
||||
- in: body
|
||||
name: Withdraw request body
|
||||
schema:
|
||||
|
@ -1772,16 +1732,6 @@ paths:
|
|||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: query
|
||||
name: simulate
|
||||
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
|
||||
required: false
|
||||
type: boolean
|
||||
- in: query
|
||||
name: generate_only
|
||||
description: if true, build an unsigned transaction and write it back
|
||||
required: false
|
||||
type: boolean
|
||||
- in: body
|
||||
name: Withdraw request body
|
||||
schema:
|
||||
|
@ -1859,16 +1809,6 @@ paths:
|
|||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: query
|
||||
name: simulate
|
||||
description: if true, ignore the gas field and perform a simulation of a transaction, but don't broadcast it
|
||||
required: false
|
||||
type: boolean
|
||||
- in: query
|
||||
name: generate_only
|
||||
description: if true, build an unsigned transaction and write it back
|
||||
required: false
|
||||
type: boolean
|
||||
- in: body
|
||||
name: Withdraw request body
|
||||
schema:
|
||||
|
@ -1948,8 +1888,8 @@ definitions:
|
|||
gas_wanted: 10000
|
||||
info: info
|
||||
tags:
|
||||
- ''
|
||||
- ''
|
||||
- ""
|
||||
- ""
|
||||
DeliverTxResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -1977,8 +1917,8 @@ definitions:
|
|||
gas_wanted: 10000
|
||||
info: info
|
||||
tags:
|
||||
- ''
|
||||
- ''
|
||||
- ""
|
||||
- ""
|
||||
BroadcastTxCommitResult:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2123,7 +2063,7 @@ definitions:
|
|||
example: 1
|
||||
time:
|
||||
type: string
|
||||
example: '2017-12-30T05:53:09.287+01:00'
|
||||
example: "2017-12-30T05:53:09.287+01:00"
|
||||
num_txs:
|
||||
type: number
|
||||
example: 0
|
||||
|
@ -2186,7 +2126,7 @@ definitions:
|
|||
example: "0"
|
||||
timestamp:
|
||||
type: string
|
||||
example: '2017-12-30T05:53:09.287+01:00'
|
||||
example: "2017-12-30T05:53:09.287+01:00"
|
||||
type:
|
||||
type: number
|
||||
example: 2
|
||||
|
@ -2194,7 +2134,7 @@ definitions:
|
|||
$ref: "#/definitions/BlockID"
|
||||
signature:
|
||||
type: string
|
||||
example: '7uTC74QlknqYWEwg7Vn6M8Om7FuZ0EO4bjvuj6rwH1mTUJrRuMMZvAAqT9VjNgP0RA/TDp6u/92AqrZfXJSpBQ=='
|
||||
example: "7uTC74QlknqYWEwg7Vn6M8Om7FuZ0EO4bjvuj6rwH1mTUJrRuMMZvAAqT9VjNgP0RA/TDp6u/92AqrZfXJSpBQ=="
|
||||
BlockQuery:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2210,9 +2150,10 @@ definitions:
|
|||
BaseReq:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
from:
|
||||
type: string
|
||||
example: "my_name"
|
||||
example: "cosmos1g9ahr6xhht5rmqven628nklxluzyv8z9jqjcmc"
|
||||
description: Sender address or Keybase name to generate a transaction
|
||||
password:
|
||||
type: string
|
||||
example: "12345678"
|
||||
|
@ -2238,21 +2179,19 @@ definitions:
|
|||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/Coin"
|
||||
gas_prices:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/definitions/DecCoin"
|
||||
generate_only:
|
||||
type: boolean
|
||||
example: false
|
||||
description: Create a JSON transaction that can be signed client side instead of actually signing and broadcasting
|
||||
simulate:
|
||||
type: boolean
|
||||
example: true
|
||||
example: false
|
||||
description: Estimate gas for a transaction (cannot be used in conjunction with generate_only)
|
||||
TendermintValidator:
|
||||
type: object
|
||||
properties:
|
||||
address:
|
||||
$ref: '#/definitions/ValidatorAddress'
|
||||
$ref: "#/definitions/ValidatorAddress"
|
||||
pub_key:
|
||||
type: string
|
||||
example: cosmosvalconspub1zcjduepq7sjfglw7ra4mjxpw4ph7dtdhdheh7nz8dfgl6t8u2n5szuuql9mqsrwquu
|
||||
|
@ -2331,7 +2270,7 @@ definitions:
|
|||
type: object
|
||||
properties:
|
||||
operator_address:
|
||||
$ref: '#/definitions/ValidatorAddress'
|
||||
$ref: "#/definitions/ValidatorAddress"
|
||||
consensus_pubkey:
|
||||
type: string
|
||||
example: cosmosvalconspub1zcjduepq7sjfglw7ra4mjxpw4ph7dtdhdheh7nz8dfgl6t8u2n5szuuql9mqsrwquu
|
||||
|
@ -2356,31 +2295,31 @@ definitions:
|
|||
type: string
|
||||
bond_height:
|
||||
type: string
|
||||
example: '0'
|
||||
example: "0"
|
||||
bond_intra_tx_counter:
|
||||
type: integer
|
||||
example: 0
|
||||
unbonding_height:
|
||||
type: string
|
||||
example: '0'
|
||||
example: "0"
|
||||
unbonding_time:
|
||||
type: string
|
||||
example: '1970-01-01T00:00:00Z'
|
||||
example: "1970-01-01T00:00:00Z"
|
||||
commission:
|
||||
type: object
|
||||
properties:
|
||||
rate:
|
||||
type: string
|
||||
example: '0'
|
||||
example: "0"
|
||||
max_rate:
|
||||
type: string
|
||||
example: '0'
|
||||
example: "0"
|
||||
max_change_rate:
|
||||
type: string
|
||||
example: '0'
|
||||
example: "0"
|
||||
update_time:
|
||||
type: string
|
||||
example: '1970-01-01T00:00:00Z'
|
||||
example: "1970-01-01T00:00:00Z"
|
||||
Delegation:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2434,13 +2373,13 @@ definitions:
|
|||
community_pool:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Coin'
|
||||
$ref: "#/definitions/Coin"
|
||||
val_accum:
|
||||
$ref: '#/definitions/TotalAccum'
|
||||
$ref: "#/definitions/TotalAccum"
|
||||
val_pool:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Coin'
|
||||
$ref: "#/definitions/Coin"
|
||||
TotalAccum:
|
||||
type: object
|
||||
properties:
|
||||
|
@ -2452,16 +2391,16 @@ definitions:
|
|||
type: object
|
||||
properties:
|
||||
operator_addr:
|
||||
$ref: '#/definitions/ValidatorAddress'
|
||||
$ref: "#/definitions/ValidatorAddress"
|
||||
fee_pool_withdrawal_height:
|
||||
type: integer
|
||||
del_accum:
|
||||
$ref: '#/definitions/TotalAccum'
|
||||
$ref: "#/definitions/TotalAccum"
|
||||
del_pool:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Coin'
|
||||
$ref: "#/definitions/Coin"
|
||||
val_commission:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/definitions/Coin'
|
||||
$ref: "#/definitions/Coin"
|
||||
|
|
|
@ -688,23 +688,32 @@ func doTransfer(t *testing.T, port, seed, name, memo, password string, addr sdk.
|
|||
return receiveAddr, resultTx
|
||||
}
|
||||
|
||||
func doTransferWithGas(t *testing.T, port, seed, name, memo, password string, addr sdk.AccAddress, gas string,
|
||||
gasAdjustment float64, simulate, generateOnly bool, fees sdk.Coins) (
|
||||
res *http.Response, body string, receiveAddr sdk.AccAddress) {
|
||||
func doTransferWithGas(
|
||||
t *testing.T, port, seed, from, memo, password string, addr sdk.AccAddress,
|
||||
gas string, gasAdjustment float64, simulate, generateOnly bool, fees sdk.Coins,
|
||||
) (res *http.Response, body string, receiveAddr sdk.AccAddress) {
|
||||
|
||||
// create receive address
|
||||
kb := client.MockKeyBase()
|
||||
receiveInfo, _, err := kb.CreateMnemonic("receive_address", cryptoKeys.English, gapp.DefaultKeyPass, cryptoKeys.SigningAlgo("secp256k1"))
|
||||
require.Nil(t, err)
|
||||
receiveAddr = sdk.AccAddress(receiveInfo.GetPubKey().Address())
|
||||
|
||||
receiveInfo, _, err := kb.CreateMnemonic(
|
||||
"receive_address", cryptoKeys.English, gapp.DefaultKeyPass, cryptoKeys.SigningAlgo("secp256k1"),
|
||||
)
|
||||
require.Nil(t, err)
|
||||
|
||||
receiveAddr = sdk.AccAddress(receiveInfo.GetPubKey().Address())
|
||||
acc := getAccount(t, port, addr)
|
||||
accnum := acc.GetAccountNumber()
|
||||
sequence := acc.GetSequence()
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
|
||||
if generateOnly {
|
||||
// generate only txs do not use a Keybase so the address must be used
|
||||
from = addr.String()
|
||||
}
|
||||
|
||||
baseReq := utils.NewBaseReq(
|
||||
name, password, memo, chainID, gas,
|
||||
from, password, memo, chainID, gas,
|
||||
fmt.Sprintf("%f", gasAdjustment), accnum, sequence, fees, nil,
|
||||
generateOnly, simulate,
|
||||
)
|
||||
|
@ -721,6 +730,39 @@ func doTransferWithGas(t *testing.T, port, seed, name, memo, password string, ad
|
|||
return
|
||||
}
|
||||
|
||||
func doTransferWithGasAccAuto(
|
||||
t *testing.T, port, seed, from, memo, password string, gas string,
|
||||
gasAdjustment float64, simulate, generateOnly bool, fees sdk.Coins,
|
||||
) (res *http.Response, body string, receiveAddr sdk.AccAddress) {
|
||||
|
||||
// create receive address
|
||||
kb := client.MockKeyBase()
|
||||
|
||||
receiveInfo, _, err := kb.CreateMnemonic(
|
||||
"receive_address", cryptoKeys.English, gapp.DefaultKeyPass, cryptoKeys.SigningAlgo("secp256k1"),
|
||||
)
|
||||
require.Nil(t, err)
|
||||
|
||||
receiveAddr = sdk.AccAddress(receiveInfo.GetPubKey().Address())
|
||||
chainID := viper.GetString(client.FlagChainID)
|
||||
|
||||
baseReq := utils.NewBaseReq(
|
||||
from, password, memo, chainID, gas,
|
||||
fmt.Sprintf("%f", gasAdjustment), 0, 0, fees, nil, generateOnly, simulate,
|
||||
)
|
||||
|
||||
sr := sendReq{
|
||||
Amount: sdk.Coins{sdk.NewInt64Coin(stakingTypes.DefaultBondDenom, 1)},
|
||||
BaseReq: baseReq,
|
||||
}
|
||||
|
||||
req, err := cdc.MarshalJSON(sr)
|
||||
require.NoError(t, err)
|
||||
|
||||
res, body = Request(t, port, "POST", fmt.Sprintf("/bank/accounts/%s/transfers", receiveAddr), req)
|
||||
return
|
||||
}
|
||||
|
||||
type sendReq struct {
|
||||
Amount sdk.Coins `json:"amount"`
|
||||
BaseReq utils.BaseReq `json:"base_req"`
|
||||
|
|
|
@ -16,7 +16,12 @@ import (
|
|||
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||
)
|
||||
|
||||
//----------------------------------------
|
||||
// GasEstimateResponse defines a response definition for tx gas estimation.
|
||||
type GasEstimateResponse struct {
|
||||
GasEstimate uint64 `json:"gas_estimate"`
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Basic HTTP utilities
|
||||
|
||||
// WriteErrorResponse prepares and writes a HTTP error
|
||||
|
@ -28,9 +33,17 @@ func WriteErrorResponse(w http.ResponseWriter, status int, err string) {
|
|||
|
||||
// WriteSimulationResponse prepares and writes an HTTP
|
||||
// response for transactions simulations.
|
||||
func WriteSimulationResponse(w http.ResponseWriter, gas uint64) {
|
||||
func WriteSimulationResponse(w http.ResponseWriter, cdc *codec.Codec, gas uint64) {
|
||||
gasEst := GasEstimateResponse{GasEstimate: gas}
|
||||
resp, err := cdc.MarshalJSON(gasEst)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(fmt.Sprintf(`{"gas_estimate":%v}`, gas)))
|
||||
w.Write(resp)
|
||||
}
|
||||
|
||||
// ParseInt64OrReturnBadRequest converts s to a int64 value.
|
||||
|
@ -77,31 +90,13 @@ func ParseFloat64OrReturnBadRequest(w http.ResponseWriter, s string, defaultIfEm
|
|||
return n, true
|
||||
}
|
||||
|
||||
// WriteGenerateStdTxResponse writes response for the generate_only mode.
|
||||
func WriteGenerateStdTxResponse(w http.ResponseWriter, cdc *codec.Codec, txBldr authtxb.TxBuilder, msgs []sdk.Msg) {
|
||||
stdMsg, err := txBldr.Build(msgs)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
output, err := cdc.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo))
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(output)
|
||||
return
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
// Building / Sending utilities
|
||||
|
||||
// BaseReq defines a structure that can be embedded in other request structures
|
||||
// that all share common "base" fields.
|
||||
type BaseReq struct {
|
||||
Name string `json:"name"`
|
||||
From string `json:"from"`
|
||||
Password string `json:"password"`
|
||||
Memo string `json:"memo"`
|
||||
ChainID string `json:"chain_id"`
|
||||
|
@ -117,12 +112,12 @@ type BaseReq struct {
|
|||
|
||||
// NewBaseReq creates a new basic request instance and sanitizes its values
|
||||
func NewBaseReq(
|
||||
name, password, memo, chainID string, gas, gasAdjustment string,
|
||||
from, password, memo, chainID string, gas, gasAdjustment string,
|
||||
accNumber, seq uint64, fees sdk.Coins, gasPrices sdk.DecCoins, genOnly, simulate bool,
|
||||
) BaseReq {
|
||||
|
||||
return BaseReq{
|
||||
Name: strings.TrimSpace(name),
|
||||
From: strings.TrimSpace(from),
|
||||
Password: password,
|
||||
Memo: strings.TrimSpace(memo),
|
||||
ChainID: strings.TrimSpace(chainID),
|
||||
|
@ -140,7 +135,7 @@ func NewBaseReq(
|
|||
// Sanitize performs basic sanitization on a BaseReq object.
|
||||
func (br BaseReq) Sanitize() BaseReq {
|
||||
return NewBaseReq(
|
||||
br.Name, br.Password, br.Memo, br.ChainID, br.Gas, br.GasAdjustment,
|
||||
br.From, br.Password, br.Memo, br.ChainID, br.Gas, br.GasAdjustment,
|
||||
br.AccountNumber, br.Sequence, br.Fees, br.GasPrices, br.GenerateOnly, br.Simulate,
|
||||
)
|
||||
}
|
||||
|
@ -171,8 +166,8 @@ func (br BaseReq) ValidateBasic(w http.ResponseWriter) bool {
|
|||
}
|
||||
}
|
||||
|
||||
if len(br.Name) == 0 {
|
||||
WriteErrorResponse(w, http.StatusUnauthorized, "name required but not specified")
|
||||
if len(br.From) == 0 {
|
||||
WriteErrorResponse(w, http.StatusUnauthorized, "name or address required but not specified")
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -209,59 +204,65 @@ func ReadRESTReq(w http.ResponseWriter, r *http.Request, cdc *codec.Codec, req i
|
|||
}
|
||||
|
||||
// CompleteAndBroadcastTxREST implements a utility function that facilitates
|
||||
// sending a series of messages in a signed transaction given a TxBuilder and a
|
||||
// QueryContext. It ensures that the account exists, has a proper number and
|
||||
// sequence set. In addition, it builds and signs a transaction with the
|
||||
// supplied messages. Finally, it broadcasts the signed transaction to a node.
|
||||
// sending a series of messages in a signed tx. In addition, it will handle
|
||||
// tx gas simulation and estimation.
|
||||
//
|
||||
// NOTE: Also see CompleteAndBroadcastTxCli.
|
||||
// NOTE: Also see x/stake/client/rest/tx.go delegationsRequestHandlerFn.
|
||||
// NOTE: Also see CompleteAndBroadcastTxCLI.
|
||||
func CompleteAndBroadcastTxREST(
|
||||
w http.ResponseWriter, r *http.Request, cliCtx context.CLIContext,
|
||||
baseReq BaseReq, msgs []sdk.Msg, cdc *codec.Codec,
|
||||
) {
|
||||
|
||||
gasAdjustment, ok := ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment)
|
||||
gasAdj, ok := ParseFloat64OrReturnBadRequest(w, baseReq.GasAdjustment, client.DefaultGasAdjustment)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
simulateAndExecute, gas, err := client.ParseGas(baseReq.Gas)
|
||||
simAndExec, gas, err := client.ParseGas(baseReq.Gas)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(baseReq.From)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
txBldr := authtxb.NewTxBuilder(
|
||||
GetTxEncoder(cdc), baseReq.AccountNumber,
|
||||
baseReq.Sequence, gas, gasAdjustment, baseReq.Simulate,
|
||||
baseReq.Sequence, gas, gasAdj, baseReq.Simulate,
|
||||
baseReq.ChainID, baseReq.Memo, baseReq.Fees, baseReq.GasPrices,
|
||||
)
|
||||
|
||||
if baseReq.Simulate || simulateAndExecute {
|
||||
if gasAdjustment < 0 {
|
||||
txBldr, err = prepareTxBuilder(txBldr, cliCtx)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if baseReq.Simulate || simAndExec {
|
||||
if gasAdj < 0 {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, "gas adjustment must be a positive float")
|
||||
return
|
||||
}
|
||||
|
||||
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, baseReq.Name, msgs)
|
||||
txBldr, err = EnrichWithGas(txBldr, cliCtx, cliCtx.GetFromName(), msgs)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if baseReq.Simulate {
|
||||
WriteSimulationResponse(w, txBldr.GetGas())
|
||||
WriteSimulationResponse(w, cdc, txBldr.GetGas())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if baseReq.GenerateOnly {
|
||||
WriteGenerateStdTxResponse(w, cdc, txBldr, msgs)
|
||||
return
|
||||
}
|
||||
|
||||
txBytes, err := txBldr.BuildAndSign(baseReq.Name, baseReq.Password, msgs)
|
||||
txBytes, err := txBldr.BuildAndSign(cliCtx.GetFromName(), baseReq.Password, msgs)
|
||||
if keyerror.IsErrKeyNotFound(err) {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
|
@ -282,9 +283,10 @@ func CompleteAndBroadcastTxREST(
|
|||
PostProcessResponse(w, cdc, res, cliCtx.Indent)
|
||||
}
|
||||
|
||||
// PostProcessResponse performs post process for rest response
|
||||
// PostProcessResponse performs post processing for a REST response.
|
||||
func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response interface{}, indent bool) {
|
||||
var output []byte
|
||||
|
||||
switch response.(type) {
|
||||
default:
|
||||
var err error
|
||||
|
@ -300,6 +302,41 @@ func PostProcessResponse(w http.ResponseWriter, cdc *codec.Codec, response inter
|
|||
case []byte:
|
||||
output = response.([]byte)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.Write(output)
|
||||
}
|
||||
|
||||
// WriteGenerateStdTxResponse writes response for the generate only mode.
|
||||
func WriteGenerateStdTxResponse(w http.ResponseWriter, cdc *codec.Codec, br BaseReq, msgs []sdk.Msg) {
|
||||
gasAdj, ok := ParseFloat64OrReturnBadRequest(w, br.GasAdjustment, client.DefaultGasAdjustment)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
_, gas, err := client.ParseGas(br.Gas)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
txBldr := authtxb.NewTxBuilder(
|
||||
GetTxEncoder(cdc), br.AccountNumber, br.Sequence, gas, gasAdj,
|
||||
br.Simulate, br.ChainID, br.Memo, br.Fees, br.GasPrices,
|
||||
)
|
||||
|
||||
stdMsg, err := txBldr.Build(msgs)
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
output, err := cdc.MarshalJSON(auth.NewStdTx(stdMsg.Msgs, stdMsg.Fee, nil, stdMsg.Memo))
|
||||
if err != nil {
|
||||
WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
w.Write(output)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -18,26 +18,23 @@ import (
|
|||
authtxb "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||
)
|
||||
|
||||
// CompleteAndBroadcastTxCli implements a utility function that facilitates
|
||||
// CompleteAndBroadcastTxCLI implements a utility function that facilitates
|
||||
// sending a series of messages in a signed transaction given a TxBuilder and a
|
||||
// QueryContext. It ensures that the account exists, has a proper number and
|
||||
// sequence set. In addition, it builds and signs a transaction with the
|
||||
// supplied messages. Finally, it broadcasts the signed transaction to a node.
|
||||
//
|
||||
// NOTE: Also see CompleteAndBroadcastTxREST.
|
||||
func CompleteAndBroadcastTxCli(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error {
|
||||
func CompleteAndBroadcastTxCLI(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) error {
|
||||
txBldr, err := prepareTxBuilder(txBldr, cliCtx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
name, err := cliCtx.GetFromName()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
name := cliCtx.GetFromName()
|
||||
|
||||
if txBldr.GetSimulateAndExecute() || cliCtx.Simulate {
|
||||
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, name, msgs)
|
||||
txBldr, err = EnrichWithGas(txBldr, cliCtx, name, msgs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -63,9 +60,9 @@ func CompleteAndBroadcastTxCli(txBldr authtxb.TxBuilder, cliCtx context.CLIConte
|
|||
return err
|
||||
}
|
||||
|
||||
// EnrichCtxWithGas calculates the gas estimate that would be consumed by the
|
||||
// EnrichWithGas calculates the gas estimate that would be consumed by the
|
||||
// transaction and set the transaction's respective value accordingly.
|
||||
func EnrichCtxWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) {
|
||||
func EnrichWithGas(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, name string, msgs []sdk.Msg) (authtxb.TxBuilder, error) {
|
||||
_, adjusted, err := simulateMsgs(txBldr, cliCtx, name, msgs)
|
||||
if err != nil {
|
||||
return txBldr, err
|
||||
|
@ -236,10 +233,7 @@ func prepareTxBuilder(txBldr authtxb.TxBuilder, cliCtx context.CLIContext) (auth
|
|||
return txBldr, err
|
||||
}
|
||||
|
||||
from, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return txBldr, err
|
||||
}
|
||||
from := cliCtx.GetFromAddress()
|
||||
|
||||
// TODO: (ref #1903) Allow for user supplied account number without
|
||||
// automatically doing a manual lookup.
|
||||
|
@ -275,22 +269,21 @@ func buildUnsignedStdTx(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msg
|
|||
|
||||
func buildUnsignedStdTxOffline(txBldr authtxb.TxBuilder, cliCtx context.CLIContext, msgs []sdk.Msg) (stdTx auth.StdTx, err error) {
|
||||
if txBldr.GetSimulateAndExecute() {
|
||||
var name string
|
||||
name, err = cliCtx.GetFromName()
|
||||
name := cliCtx.GetFromName()
|
||||
|
||||
txBldr, err = EnrichWithGas(txBldr, cliCtx, name, msgs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
txBldr, err = EnrichCtxWithGas(txBldr, cliCtx, name, msgs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "estimated gas = %v\n", txBldr.GetGas())
|
||||
}
|
||||
|
||||
stdSignMsg, err := txBldr.Build(msgs)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return auth.NewStdTx(stdSignMsg.Msgs, stdSignMsg.Fee, nil, stdSignMsg.Memo), nil
|
||||
}
|
||||
|
||||
|
@ -300,5 +293,6 @@ func isTxSigner(user sdk.AccAddress, signers []sdk.AccAddress) bool {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -105,10 +105,19 @@ The recommended way to listen for incoming transaction is to periodically query
|
|||
|
||||
## Rest API
|
||||
|
||||
The Rest API documents all the available endpoints that you can use to interract with your full node. It can be found [here](https://cosmos.network/rpc/).
|
||||
The Rest API documents all the available endpoints that you can use to interact
|
||||
with your full node. It can be found [here](https://cosmos.network/rpc/).
|
||||
|
||||
The API is divided into ICS standards for each category of endpoints. For example, the [ICS20](https://cosmos.network/rpc/#/ICS20/) describes the API to interact with tokens.
|
||||
The API is divided into ICS standards for each category of endpoints. For
|
||||
example, the [ICS20](https://cosmos.network/rpc/#/ICS20/) describes the API to
|
||||
interact with tokens.
|
||||
|
||||
To give more flexibility to implementers, we have included the ability to generate unsigned transactions, [sign](https://cosmos.network/rpc/#/ICS20/post_tx_sign) and [broadcast](https://cosmos.network/rpc/#/ICS20/post_tx_broadcast) them with different API endpoints. This allows service providers to use their own signing mechanism for instance.
|
||||
To give more flexibility to implementers, we have included the ability to
|
||||
generate unsigned transactions, [sign](https://cosmos.network/rpc/#/ICS20/post_tx_sign)
|
||||
and [broadcast](https://cosmos.network/rpc/#/ICS20/post_tx_broadcast) them with
|
||||
different API endpoints. This allows service providers to use their own signing
|
||||
mechanism for instance.
|
||||
|
||||
In order to generate an unsigned transaction (example with [coin transfer](https://cosmos.network/rpc/#/ICS20/post_bank_accounts__address__transfers)), you need to use the flag `?generate_only`.
|
||||
In order to generate an unsigned transaction (example with
|
||||
[coin transfer](https://cosmos.network/rpc/#/ICS20/post_bank_accounts__address__transfers)),
|
||||
you need to use the field `generate_only` in the body of `base_req`.
|
||||
|
|
|
@ -209,7 +209,8 @@ You can also check your balance at a given block by using the `--block` flag:
|
|||
gaiacli query account <account_cosmos> --block=<block_height>
|
||||
```
|
||||
|
||||
You can simulate a transaction without actually broadcasting it by appending the `--dry-run` flag to the command line:
|
||||
You can simulate a transaction without actually broadcasting it by appending the
|
||||
`--dry-run` flag to the command line:
|
||||
|
||||
```bash
|
||||
gaiacli tx send \
|
||||
|
@ -220,7 +221,8 @@ gaiacli tx send \
|
|||
--dry-run
|
||||
```
|
||||
|
||||
Furthermore, you can build a transaction and print its JSON format to STDOUT by appending `--generate-only` to the list of the command line arguments:
|
||||
Furthermore, you can build a transaction and print its JSON format to STDOUT by
|
||||
appending `--generate-only` to the list of the command line arguments:
|
||||
|
||||
```bash
|
||||
gaiacli tx send \
|
||||
|
@ -231,7 +233,14 @@ gaiacli tx send \
|
|||
--generate-only > unsignedSendTx.json
|
||||
```
|
||||
|
||||
You can now sign the transaction file generated through the `--generate-only` flag by providing your key to the following command:
|
||||
::: tip Note
|
||||
Simulation cannot be used in conjunction with tx generation only functionality
|
||||
due to the fact that simulation requires a public key and generation only does
|
||||
not utilize a Keybase.
|
||||
|
||||
You can now sign the transaction file generated through the `--generate-only`
|
||||
flag by providing your key to the following command:
|
||||
:::
|
||||
|
||||
```bash
|
||||
gaiacli tx sign \
|
||||
|
|
|
@ -41,6 +41,15 @@ func SignTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
|||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(m.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
|
||||
txBldr := authtxb.NewTxBuilder(
|
||||
utils.GetTxEncoder(cdc),
|
||||
m.BaseReq.AccountNumber,
|
||||
|
@ -54,7 +63,7 @@ func SignTxRequestHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Ha
|
|||
nil,
|
||||
)
|
||||
|
||||
signedTx, err := txBldr.SignStdTx(m.BaseReq.Name, m.BaseReq.Password, m.Tx, m.AppendSig)
|
||||
signedTx, err := txBldr.SignStdTx(cliCtx.GetFromName(), m.BaseReq.Password, m.Tx, m.AppendSig)
|
||||
if keyerror.IsErrKeyNotFound(err) {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
|
|
|
@ -50,11 +50,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
from, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
from := cliCtx.GetFromAddress()
|
||||
account, err := cliCtx.GetAccount(from)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -71,7 +67,7 @@ func SendTxCmd(cdc *codec.Codec) *cobra.Command {
|
|||
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank/client"
|
||||
bankclient "github.com/cosmos/cosmos-sdk/x/bank/client"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
@ -37,7 +37,7 @@ func SendRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIC
|
|||
vars := mux.Vars(r)
|
||||
bech32Addr := vars["address"]
|
||||
|
||||
to, err := sdk.AccAddressFromBech32(bech32Addr)
|
||||
toAddr, err := sdk.AccAddressFromBech32(bech32Addr)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
|
@ -54,13 +54,30 @@ func SendRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CLIC
|
|||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(req.BaseReq.Name)
|
||||
if req.BaseReq.GenerateOnly {
|
||||
// When generate only is supplied, the from field must be a valid Bech32
|
||||
// address.
|
||||
fromAddr, err := sdk.AccAddressFromBech32(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
msg := client.CreateMsg(sdk.AccAddress(info.GetPubKey().Address()), to, req.Amount)
|
||||
msg := bankclient.CreateMsg(fromAddr, toAddr, req.Amount)
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
msg := bankclient.CreateMsg(cliCtx.GetFromAddress(), toAddr, req.Amount)
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,18 +63,11 @@ func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command {
|
|||
var msg sdk.Msg
|
||||
switch {
|
||||
case isVal:
|
||||
addr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
addr := cliCtx.GetFromAddress()
|
||||
valAddr := sdk.ValAddress(addr.Bytes())
|
||||
msg = types.NewMsgWithdrawValidatorCommission(valAddr)
|
||||
default:
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delAddr := cliCtx.GetFromAddress()
|
||||
valAddr, err := sdk.ValAddressFromBech32(onlyFromVal)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -88,7 +81,7 @@ func GetCmdWithdrawRewards(cdc *codec.Codec) *cobra.Command {
|
|||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(flagOnlyFromValidator, "", "only withdraw from this validator address (in bech)")
|
||||
|
@ -109,11 +102,7 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command {
|
|||
WithCodec(cdc).
|
||||
WithAccountDecoder(cdc)
|
||||
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delAddr := cliCtx.GetFromAddress()
|
||||
withdrawAddr, err := sdk.AccAddressFromBech32(args[0])
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -122,7 +111,7 @@ func GetCmdSetWithdrawAddr(cdc *codec.Codec) *cobra.Command {
|
|||
msg := types.NewMsgSetWithdrawAddress(delAddr, withdrawAddr)
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
|
|
|
@ -86,10 +86,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome
|
|||
WithAccountDecoder(cdc)
|
||||
|
||||
// Get from address
|
||||
from, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from := cliCtx.GetFromAddress()
|
||||
|
||||
// Pull associated account
|
||||
account, err := cliCtx.GetAccount(from)
|
||||
|
@ -126,7 +123,7 @@ $ gaiacli gov submit-proposal --title="Test Proposal" --description="My awesome
|
|||
// Build and sign the transaction, then broadcast to Tendermint
|
||||
// proposalID must be returned, and it is a part of response.
|
||||
cliCtx.PrintResponse = true
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -199,11 +196,7 @@ $ gaiacli tx gov deposit 1 10stake --from mykey
|
|||
return fmt.Errorf("Failed to fetch proposal-id %d: %s", proposalID, err)
|
||||
}
|
||||
|
||||
// Get from address
|
||||
from, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from := cliCtx.GetFromAddress()
|
||||
|
||||
// Fetch associated account
|
||||
account, err := cliCtx.GetAccount(from)
|
||||
|
@ -233,7 +226,7 @@ $ gaiacli tx gov deposit 1 10stake --from mykey
|
|||
}
|
||||
|
||||
// Build and sign the transaction, then broadcast to a Tendermint node.
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -258,10 +251,7 @@ $ gaiacli tx gov vote 1 yes --from mykey
|
|||
WithAccountDecoder(cdc)
|
||||
|
||||
// Get voting address
|
||||
from, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
from := cliCtx.GetFromAddress()
|
||||
|
||||
// validate that the proposal id is a uint
|
||||
proposalID, err := strconv.ParseUint(args[0], 10, 64)
|
||||
|
@ -294,7 +284,7 @@ $ gaiacli tx gov vote 1 yes --from mykey
|
|||
}
|
||||
|
||||
// Build and sign the transaction, then broadcast to a Tendermint node.
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -101,6 +101,11 @@ func postProposalHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.Han
|
|||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +145,11 @@ func depositHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerF
|
|||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
@ -185,6 +195,11 @@ func voteHandlerFn(cdc *codec.Codec, cliCtx context.CLIContext) http.HandlerFunc
|
|||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,11 +32,7 @@ func IBCTransferCmd(cdc *codec.Codec) *cobra.Command {
|
|||
WithCodec(cdc).
|
||||
WithAccountDecoder(cdc)
|
||||
|
||||
from, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
from := cliCtx.GetFromAddress()
|
||||
msg, err := buildMsg(from)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -45,7 +41,7 @@ func IBCTransferCmd(cdc *codec.Codec) *cobra.Command {
|
|||
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -82,11 +82,7 @@ func (c relayCommander) runIBCRelay(cmd *cobra.Command, args []string) {
|
|||
toChainID := viper.GetString(FlagToChainID)
|
||||
toChainNode := viper.GetString(FlagToChainNode)
|
||||
|
||||
address, err := context.NewCLIContext().GetFromAddress()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
address := context.NewCLIContext().GetFromAddress()
|
||||
c.address = address
|
||||
|
||||
c.loop(fromChainID, fromChainNode, toChainID, toChainNode)
|
||||
|
@ -96,10 +92,7 @@ func (c relayCommander) runIBCRelay(cmd *cobra.Command, args []string) {
|
|||
func (c relayCommander) loop(fromChainID, fromChainNode, toChainID, toChainNode string) {
|
||||
cliCtx := context.NewCLIContext()
|
||||
|
||||
name, err := cliCtx.GetFromName()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
name := cliCtx.GetFromName()
|
||||
passphrase, err := keys.ReadPassphraseFromStdin(name)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -207,11 +200,7 @@ func (c relayCommander) refine(bz []byte, ibcSeq, accSeq uint64, passphrase stri
|
|||
txBldr := authtxb.NewTxBuilderFromCLI().WithSequence(accSeq).WithTxEncoder(utils.GetTxEncoder(c.cdc))
|
||||
cliCtx := context.NewCLIContext()
|
||||
|
||||
name, err := cliCtx.GetFromName()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
name := cliCtx.GetFromName()
|
||||
res, err := txBldr.BuildAndSign(name, passphrase, []sdk.Msg{msg})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -48,18 +48,28 @@ func TransferRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.
|
|||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(req.BaseReq.Name)
|
||||
var fromAddr sdk.AccAddress
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
// When generate only is supplied, the from field must be a valid Bech32
|
||||
// address.
|
||||
addr, err := sdk.AccAddressFromBech32(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
packet := ibc.NewIBCPacket(
|
||||
sdk.AccAddress(info.GetPubKey().Address()), to,
|
||||
req.Amount, req.BaseReq.ChainID, destChainID,
|
||||
)
|
||||
fromAddr = addr
|
||||
}
|
||||
|
||||
packet := ibc.NewIBCPacket(fromAddr, to, req.Amount, req.BaseReq.ChainID, destChainID)
|
||||
msg := ibc.IBCTransferMsg{IBCPacket: packet}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,16 +25,13 @@ func GetCmdUnjail(cdc *codec.Codec) *cobra.Command {
|
|||
WithCodec(cdc).
|
||||
WithAccountDecoder(cdc)
|
||||
|
||||
valAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
valAddr := cliCtx.GetFromAddress()
|
||||
|
||||
msg := slashing.NewMsgUnjail(sdk.ValAddress(valAddr))
|
||||
if cliCtx.GenerateOnly {
|
||||
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -43,24 +43,38 @@ func unjailRequestHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.CL
|
|||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(req.BaseReq.Name)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
valAddr, err := sdk.ValAddressFromBech32(bech32validator)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(info.GetPubKey().Address(), valAddr) {
|
||||
msg := slashing.NewMsgUnjail(valAddr)
|
||||
err = msg.ValidateBasic()
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
|
||||
if !bytes.Equal(cliCtx.GetFromAddress(), valAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "must use own validator address")
|
||||
return
|
||||
}
|
||||
|
||||
msg := slashing.NewMsgUnjail(valAddr)
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func GetCmdCreateValidator(cdc *codec.Codec) *cobra.Command {
|
|||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -71,11 +71,7 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command {
|
|||
WithCodec(cdc).
|
||||
WithAccountDecoder(cdc)
|
||||
|
||||
valAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
valAddr := cliCtx.GetFromAddress()
|
||||
description := staking.Description{
|
||||
Moniker: viper.GetString(FlagMoniker),
|
||||
Identity: viper.GetString(FlagIdentity),
|
||||
|
@ -102,7 +98,7 @@ func GetCmdEditValidator(cdc *codec.Codec) *cobra.Command {
|
|||
}
|
||||
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -128,11 +124,7 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
|
|||
return err
|
||||
}
|
||||
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delAddr := cliCtx.GetFromAddress()
|
||||
valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -144,7 +136,7 @@ func GetCmdDelegate(cdc *codec.Codec) *cobra.Command {
|
|||
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -167,11 +159,7 @@ func GetCmdRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
|
||||
var err error
|
||||
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delAddr := cliCtx.GetFromAddress()
|
||||
valSrcAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidatorSrc))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -199,7 +187,7 @@ func GetCmdRedelegate(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -220,11 +208,7 @@ func GetCmdUnbond(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
WithCodec(cdc).
|
||||
WithAccountDecoder(cdc)
|
||||
|
||||
delAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
delAddr := cliCtx.GetFromAddress()
|
||||
valAddr, err := sdk.ValAddressFromBech32(viper.GetString(FlagAddressValidator))
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -247,7 +231,7 @@ func GetCmdUnbond(storeName string, cdc *codec.Codec) *cobra.Command {
|
|||
return utils.PrintUnsignedStdTx(os.Stdout, txBldr, cliCtx, []sdk.Msg{msg}, false)
|
||||
}
|
||||
// build and sign the transaction, then broadcast to Tendermint
|
||||
return utils.CompleteAndBroadcastTxCli(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
return utils.CompleteAndBroadcastTxCLI(txBldr, cliCtx, []sdk.Msg{msg})
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -265,12 +249,9 @@ func BuildCreateValidatorMsg(cliCtx context.CLIContext, txBldr authtxb.TxBuilder
|
|||
return txBldr, nil, err
|
||||
}
|
||||
|
||||
valAddr, err := cliCtx.GetFromAddress()
|
||||
if err != nil {
|
||||
return txBldr, nil, err
|
||||
}
|
||||
|
||||
valAddr := cliCtx.GetFromAddress()
|
||||
pkStr := viper.GetString(FlagPubKey)
|
||||
|
||||
pk, err := sdk.GetConsPubKeyBech32(pkStr)
|
||||
if err != nil {
|
||||
return txBldr, nil, err
|
||||
|
|
|
@ -68,17 +68,6 @@ func postDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.
|
|||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(req.BaseReq.Name)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(info.GetPubKey().Address(), req.DelegatorAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
|
||||
return
|
||||
}
|
||||
|
||||
msg := staking.NewMsgDelegate(req.DelegatorAddr, req.ValidatorAddr, req.Delegation)
|
||||
err = msg.ValidateBasic()
|
||||
if err != nil {
|
||||
|
@ -86,6 +75,25 @@ func postDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx context.
|
|||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
|
||||
if !bytes.Equal(cliCtx.GetFromAddress(), req.DelegatorAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "must use own delegator address")
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
@ -105,17 +113,6 @@ func postRedelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx contex
|
|||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(req.BaseReq.Name)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(info.GetPubKey().Address(), req.DelegatorAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
|
||||
return
|
||||
}
|
||||
|
||||
msg := staking.NewMsgBeginRedelegate(req.DelegatorAddr, req.ValidatorSrcAddr, req.ValidatorDstAddr, req.SharesAmount)
|
||||
err = msg.ValidateBasic()
|
||||
if err != nil {
|
||||
|
@ -123,6 +120,25 @@ func postRedelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx contex
|
|||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
|
||||
if !bytes.Equal(cliCtx.GetFromAddress(), req.DelegatorAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "must use own delegator address")
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
@ -142,17 +158,6 @@ func postUnbondingDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx
|
|||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(req.BaseReq.Name)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !bytes.Equal(info.GetPubKey().Address(), req.DelegatorAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "Must use own delegator address")
|
||||
return
|
||||
}
|
||||
|
||||
msg := staking.NewMsgUndelegate(req.DelegatorAddr, req.ValidatorAddr, req.SharesAmount)
|
||||
err = msg.ValidateBasic()
|
||||
if err != nil {
|
||||
|
@ -160,6 +165,25 @@ func postUnbondingDelegationsHandlerFn(cdc *codec.Codec, kb keys.Keybase, cliCtx
|
|||
return
|
||||
}
|
||||
|
||||
if req.BaseReq.GenerateOnly {
|
||||
utils.WriteGenerateStdTxResponse(w, cdc, req.BaseReq, []sdk.Msg{msg})
|
||||
return
|
||||
}
|
||||
|
||||
// derive the from account address and name from the Keybase
|
||||
fromAddress, fromName, err := context.GetFromFields(req.BaseReq.From)
|
||||
if err != nil {
|
||||
utils.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
cliCtx = cliCtx.WithFromName(fromName).WithFromAddress(fromAddress)
|
||||
|
||||
if !bytes.Equal(cliCtx.GetFromAddress(), req.DelegatorAddr) {
|
||||
utils.WriteErrorResponse(w, http.StatusUnauthorized, "must use own delegator address")
|
||||
return
|
||||
}
|
||||
|
||||
utils.CompleteAndBroadcastTxREST(w, r, cliCtx, req.BaseReq, []sdk.Msg{msg}, cdc)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue