Move /bank/balances/{address} REST endpoint into /x/bank (#4570)

Closes: #4560
This commit is contained in:
Alessio Treglia 2019-06-18 15:44:09 +02:00 committed by GitHub
parent a79749564e
commit 1e7c4dd58a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 250 additions and 140 deletions

View File

@ -0,0 +1 @@
#4570 Move /bank/balances/{address} REST handler to x/bank/client/rest. The exposed interface is unchanged.

View File

@ -42,7 +42,6 @@ var (
NewParams = types.NewParams
ParamKeyTable = types.ParamKeyTable
DefaultParams = types.DefaultParams
NewQueryAccountParams = types.NewQueryAccountParams
NewStdTx = types.NewStdTx
CountSubKeys = types.CountSubKeys
NewStdFee = types.NewStdFee
@ -75,7 +74,6 @@ type (
FeeCollectionKeeper = types.FeeCollectionKeeper
GenesisState = types.GenesisState
Params = types.Params
QueryAccountParams = types.QueryAccountParams
StdSignMsg = types.StdSignMsg
StdTx = types.StdTx
StdFee = types.StdFee

View File

@ -64,50 +64,6 @@ func QueryAccountRequestHandlerFn(
}
}
// query accountREST Handler
func QueryBalancesRequestHandlerFn(
storeName string, decoder types.AccountDecoder, cliCtx context.CLIContext,
) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
bech32addr := vars["address"]
addr, err := sdk.AccAddressFromBech32(bech32addr)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
res, _, err := cliCtx.QueryStore(types.AddressStoreKey(addr), storeName)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
// the query will return empty if there is no data for this account
if len(res) == 0 {
rest.PostProcessResponse(w, cliCtx, sdk.Coins{})
return
}
// decode the value
account, err := decoder(res)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
rest.PostProcessResponse(w, cliCtx, account.GetCoins())
}
}
// QueryTxsByTagsRequestHandlerFn implements a REST handler that searches for
// transactions by tags.
func QueryTxsByTagsRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {

View File

@ -12,12 +12,6 @@ func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router, storeName string)
"/auth/accounts/{address}",
QueryAccountRequestHandlerFn(storeName, context.GetAccountDecoder(cliCtx.Codec), cliCtx),
).Methods("GET")
// TODO: Change path or mount under x/bank if possible
r.HandleFunc(
"/bank/balances/{address}",
QueryBalancesRequestHandlerFn(storeName, context.GetAccountDecoder(cliCtx.Codec), cliCtx),
).Methods("GET")
}
// RegisterTxRoutes registers all transaction routes on the provided router.

View File

@ -4,9 +4,11 @@ import (
"fmt"
"testing"
"github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/x/auth/types"
)
func Test_queryAccount(t *testing.T) {
@ -20,13 +22,13 @@ func Test_queryAccount(t *testing.T) {
require.NotNil(t, err)
require.Nil(t, res)
req.Data = input.cdc.MustMarshalJSON(NewQueryAccountParams([]byte("")))
req.Data = input.cdc.MustMarshalJSON(types.NewQueryAccountParams([]byte("")))
res, err = queryAccount(input.ctx, req, input.ak)
require.NotNil(t, err)
require.Nil(t, res)
_, _, addr := types.KeyTestPubAddr()
req.Data = input.cdc.MustMarshalJSON(NewQueryAccountParams(addr))
req.Data = input.cdc.MustMarshalJSON(types.NewQueryAccountParams(addr))
res, err = queryAccount(input.ctx, req, input.ak)
require.NotNil(t, err)
require.Nil(t, res)

View File

@ -9,13 +9,12 @@ const (
QueryAccount = "account"
)
// defines the params for query: "custom/acc/account"
// QueryAccountParams defines the params for querying accounts.
type QueryAccountParams struct {
Address sdk.AccAddress
}
// NewQueryAccountParams creates a new instance of QueryAccountParams.
func NewQueryAccountParams(addr sdk.AccAddress) QueryAccountParams {
return QueryAccountParams{
Address: addr,
}
return QueryAccountParams{Address: addr}
}

View File

@ -15,6 +15,7 @@ const (
CodeInvalidInputsOutputs = types.CodeInvalidInputsOutputs
ModuleName = types.ModuleName
RouterKey = types.RouterKey
QuerierRoute = types.QuerierRoute
DefaultParamspace = types.DefaultParamspace
)

View File

@ -0,0 +1,54 @@
package rest
import (
"net/http"
"github.com/gorilla/mux"
"github.com/cosmos/cosmos-sdk/client/context"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
// query accountREST Handler
func QueryBalancesRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
vars := mux.Vars(r)
bech32addr := vars["address"]
addr, err := sdk.AccAddressFromBech32(bech32addr)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
cliCtx, ok := rest.ParseQueryHeightOrReturnBadRequest(w, cliCtx, r)
if !ok {
return
}
params := types.NewQueryBalanceParams(addr)
bz, err := cliCtx.Codec.MarshalJSON(params)
if err != nil {
rest.WriteErrorResponse(w, http.StatusBadRequest, err.Error())
return
}
res, _, err := cliCtx.QueryWithData("custom/bank/balances", bz)
if err != nil {
rest.WriteErrorResponse(w, http.StatusInternalServerError, err.Error())
return
}
// the query will return empty if there is no data for this account
if len(res) == 0 {
rest.PostProcessResponse(w, cliCtx, sdk.Coins{})
return
}
rest.PostProcessResponse(w, cliCtx, res)
}
}

View File

@ -6,7 +6,6 @@ import (
"github.com/gorilla/mux"
"github.com/cosmos/cosmos-sdk/client/context"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/types/rest"
"github.com/cosmos/cosmos-sdk/x/auth/client/utils"
@ -17,6 +16,7 @@ import (
// RegisterRoutes - Central function to define routes that get registered by the main application
func RegisterRoutes(cliCtx context.CLIContext, r *mux.Router) {
r.HandleFunc("/bank/accounts/{address}/transfers", SendRequestHandlerFn(cliCtx)).Methods("POST")
r.HandleFunc("/bank/balances/{address}", QueryBalancesRequestHandlerFn(cliCtx)).Methods("GET")
}
// SendReq defines the properties of a send request's body.
@ -25,12 +25,6 @@ type SendReq struct {
Amount sdk.Coins `json:"amount"`
}
var moduleCdc = codec.New()
func init() {
types.RegisterCodec(moduleCdc)
}
// SendRequestHandlerFn - http request handler to send coins to a address.
func SendRequestHandlerFn(cliCtx context.CLIContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {

View File

@ -21,6 +21,7 @@ import (
type testInput struct {
cdc *codec.Codec
ctx sdk.Context
k Keeper
ak auth.AccountKeeper
pk params.Keeper
}
@ -51,14 +52,15 @@ func setupTestInput() testInput {
ak.SetParams(ctx, auth.DefaultParams())
return testInput{cdc: cdc, ctx: ctx, ak: ak, pk: pk}
bankKeeper := NewBaseKeeper(ak, pk.Subspace(types.DefaultParamspace), types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
return testInput{cdc: cdc, ctx: ctx, k: bankKeeper, ak: ak, pk: pk}
}
func TestKeeper(t *testing.T) {
input := setupTestInput()
ctx := input.ctx
bankKeeper := NewBaseKeeper(input.ak, input.pk.Subspace(types.DefaultParamspace), types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
addr := sdk.AccAddress([]byte("addr1"))
addr2 := sdk.AccAddress([]byte("addr2"))
@ -67,57 +69,57 @@ func TestKeeper(t *testing.T) {
// Test GetCoins/SetCoins
input.ak.SetAccount(ctx, acc)
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
bankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
input.k.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
// Test HasCoins
require.True(t, bankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, bankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
require.False(t, bankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
require.False(t, bankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5))))
require.True(t, input.k.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, input.k.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
require.False(t, input.k.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
require.False(t, input.k.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5))))
// Test AddCoins
bankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 25))))
input.k.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 25))))
bankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 15)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 15), sdk.NewInt64Coin("foocoin", 25))))
input.k.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 15)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 15), sdk.NewInt64Coin("foocoin", 25))))
// Test SubtractCoins
bankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
bankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15))))
input.k.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
input.k.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15))))
bankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 11)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15))))
input.k.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 11)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 15))))
bankKeeper.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
require.False(t, bankKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 1))))
input.k.SubtractCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
require.False(t, input.k.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 1))))
// Test SendCoins
bankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
input.k.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, input.k.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
err2 := bankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
err2 := input.k.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 50)))
require.Implements(t, (*sdk.Error)(nil), err2)
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, input.k.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
bankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 30)))
bankKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)))
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5))))
require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10))))
input.k.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 30)))
input.k.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)))
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5))))
require.True(t, input.k.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10))))
// Test InputOutputCoins
input1 := types.NewInput(addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 2)))
output1 := types.NewOutput(addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 2)))
bankKeeper.InputOutputCoins(ctx, []types.Input{input1}, []types.Output{output1})
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 7))))
require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 8))))
input.k.InputOutputCoins(ctx, []types.Input{input1}, []types.Output{output1})
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 7))))
require.True(t, input.k.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 8))))
inputs := []types.Input{
types.NewInput(addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 3))),
@ -128,19 +130,18 @@ func TestKeeper(t *testing.T) {
types.NewOutput(addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 1))),
types.NewOutput(addr3, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5))),
}
bankKeeper.InputOutputCoins(ctx, inputs, outputs)
require.True(t, bankKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 21), sdk.NewInt64Coin("foocoin", 4))))
require.True(t, bankKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 7), sdk.NewInt64Coin("foocoin", 6))))
require.True(t, bankKeeper.GetCoins(ctx, addr3).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5))))
input.k.InputOutputCoins(ctx, inputs, outputs)
require.True(t, input.k.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 21), sdk.NewInt64Coin("foocoin", 4))))
require.True(t, input.k.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 7), sdk.NewInt64Coin("foocoin", 6))))
require.True(t, input.k.GetCoins(ctx, addr3).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 2), sdk.NewInt64Coin("foocoin", 5))))
}
func TestSendKeeper(t *testing.T) {
input := setupTestInput()
ctx := input.ctx
paramSpace := input.pk.Subspace(types.DefaultParamspace)
bankKeeper := NewBaseKeeper(input.ak, paramSpace, types.DefaultCodespace)
paramSpace := input.pk.Subspace("newspace")
sendKeeper := NewBaseSendKeeper(input.ak, paramSpace, types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
input.k.SetSendEnabled(ctx, true)
addr := sdk.AccAddress([]byte("addr1"))
addr2 := sdk.AccAddress([]byte("addr2"))
@ -150,7 +151,7 @@ func TestSendKeeper(t *testing.T) {
input.ak.SetAccount(ctx, acc)
require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
bankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
input.k.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
// Test HasCoins
@ -159,7 +160,7 @@ func TestSendKeeper(t *testing.T) {
require.False(t, sendKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15))))
require.False(t, sendKeeper.HasCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 5))))
bankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15)))
input.k.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 15)))
// Test SendCoins
sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5)))
@ -171,7 +172,7 @@ func TestSendKeeper(t *testing.T) {
require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 5))))
bankKeeper.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 30)))
input.k.AddCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 30)))
sendKeeper.SendCoins(ctx, addr, addr2, sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 5)))
require.True(t, sendKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 20), sdk.NewInt64Coin("foocoin", 5))))
require.True(t, sendKeeper.GetCoins(ctx, addr2).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("barcoin", 10), sdk.NewInt64Coin("foocoin", 10))))
@ -186,9 +187,7 @@ func TestSendKeeper(t *testing.T) {
func TestViewKeeper(t *testing.T) {
input := setupTestInput()
ctx := input.ctx
paramSpace := input.pk.Subspace(types.DefaultParamspace)
bankKeeper := NewBaseKeeper(input.ak, paramSpace, types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
//paramSpace := input.pk.Subspace(types.DefaultParamspace)
viewKeeper := NewBaseViewKeeper(input.ak, types.DefaultCodespace)
addr := sdk.AccAddress([]byte("addr1"))
@ -198,7 +197,7 @@ func TestViewKeeper(t *testing.T) {
input.ak.SetAccount(ctx, acc)
require.True(t, viewKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins()))
bankKeeper.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
input.k.SetCoins(ctx, addr, sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10)))
require.True(t, viewKeeper.GetCoins(ctx, addr).IsEqual(sdk.NewCoins(sdk.NewInt64Coin("foocoin", 10))))
// Test HasCoins
@ -216,8 +215,6 @@ func TestVestingAccountSend(t *testing.T) {
origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
bankKeeper := NewBaseKeeper(input.ak, input.pk.Subspace(types.DefaultParamspace), types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
addr1 := sdk.AccAddress([]byte("addr1"))
addr2 := sdk.AccAddress([]byte("addr2"))
@ -227,7 +224,7 @@ func TestVestingAccountSend(t *testing.T) {
input.ak.SetAccount(ctx, vacc)
// require that no coins be sendable at the beginning of the vesting schedule
err := bankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)
err := input.k.SendCoins(ctx, addr1, addr2, sendCoins)
require.Error(t, err)
// receive some coins
@ -236,7 +233,7 @@ func TestVestingAccountSend(t *testing.T) {
// require that all vested coins are spendable plus any received
ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
err = bankKeeper.SendCoins(ctx, addr1, addr2, sendCoins)
err = input.k.SendCoins(ctx, addr1, addr2, sendCoins)
vacc = input.ak.GetAccount(ctx, addr1).(*auth.ContinuousVestingAccount)
require.NoError(t, err)
require.Equal(t, origCoins, vacc.GetCoins())
@ -250,8 +247,6 @@ func TestVestingAccountReceive(t *testing.T) {
origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
sendCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
bankKeeper := NewBaseKeeper(input.ak, input.pk.Subspace(types.DefaultParamspace), types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
addr1 := sdk.AccAddress([]byte("addr1"))
addr2 := sdk.AccAddress([]byte("addr2"))
@ -262,10 +257,10 @@ func TestVestingAccountReceive(t *testing.T) {
acc := input.ak.NewAccountWithAddress(ctx, addr2)
input.ak.SetAccount(ctx, vacc)
input.ak.SetAccount(ctx, acc)
bankKeeper.SetCoins(ctx, addr2, origCoins)
input.k.SetCoins(ctx, addr2, origCoins)
// send some coins to the vesting account
bankKeeper.SendCoins(ctx, addr2, addr1, sendCoins)
input.k.SendCoins(ctx, addr2, addr1, sendCoins)
// require the coins are spendable
vacc = input.ak.GetAccount(ctx, addr1).(*auth.ContinuousVestingAccount)
@ -284,8 +279,6 @@ func TestDelegateCoins(t *testing.T) {
origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
bankKeeper := NewBaseKeeper(input.ak, input.pk.Subspace(types.DefaultParamspace), types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
addr1 := sdk.AccAddress([]byte("addr1"))
addr2 := sdk.AccAddress([]byte("addr2"))
@ -296,18 +289,18 @@ func TestDelegateCoins(t *testing.T) {
acc := input.ak.NewAccountWithAddress(ctx, addr2)
input.ak.SetAccount(ctx, vacc)
input.ak.SetAccount(ctx, acc)
bankKeeper.SetCoins(ctx, addr2, origCoins)
input.k.SetCoins(ctx, addr2, origCoins)
ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
// require the ability for a non-vesting account to delegate
_, err := bankKeeper.DelegateCoins(ctx, addr2, delCoins)
_, err := input.k.DelegateCoins(ctx, addr2, delCoins)
acc = input.ak.GetAccount(ctx, addr2)
require.NoError(t, err)
require.Equal(t, delCoins, acc.GetCoins())
// require the ability for a vesting account to delegate
_, err = bankKeeper.DelegateCoins(ctx, addr1, delCoins)
_, err = input.k.DelegateCoins(ctx, addr1, delCoins)
vacc = input.ak.GetAccount(ctx, addr1).(*auth.ContinuousVestingAccount)
require.NoError(t, err)
require.Equal(t, delCoins, vacc.GetCoins())
@ -321,8 +314,6 @@ func TestUndelegateCoins(t *testing.T) {
origCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 100))
delCoins := sdk.NewCoins(sdk.NewInt64Coin("stake", 50))
bankKeeper := NewBaseKeeper(input.ak, input.pk.Subspace(types.DefaultParamspace), types.DefaultCodespace)
bankKeeper.SetSendEnabled(ctx, true)
addr1 := sdk.AccAddress([]byte("addr1"))
addr2 := sdk.AccAddress([]byte("addr2"))
@ -333,27 +324,27 @@ func TestUndelegateCoins(t *testing.T) {
acc := input.ak.NewAccountWithAddress(ctx, addr2)
input.ak.SetAccount(ctx, vacc)
input.ak.SetAccount(ctx, acc)
bankKeeper.SetCoins(ctx, addr2, origCoins)
input.k.SetCoins(ctx, addr2, origCoins)
ctx = ctx.WithBlockTime(now.Add(12 * time.Hour))
// require the ability for a non-vesting account to delegate
_, err := bankKeeper.DelegateCoins(ctx, addr2, delCoins)
_, err := input.k.DelegateCoins(ctx, addr2, delCoins)
require.NoError(t, err)
// require the ability for a non-vesting account to undelegate
_, err = bankKeeper.UndelegateCoins(ctx, addr2, delCoins)
_, err = input.k.UndelegateCoins(ctx, addr2, delCoins)
require.NoError(t, err)
acc = input.ak.GetAccount(ctx, addr2)
require.Equal(t, origCoins, acc.GetCoins())
// require the ability for a vesting account to delegate
_, err = bankKeeper.DelegateCoins(ctx, addr1, delCoins)
_, err = input.k.DelegateCoins(ctx, addr1, delCoins)
require.NoError(t, err)
// require the ability for a vesting account to undelegate
_, err = bankKeeper.UndelegateCoins(ctx, addr1, delCoins)
_, err = input.k.UndelegateCoins(ctx, addr1, delCoins)
require.NoError(t, err)
vacc = input.ak.GetAccount(ctx, addr1).(*auth.ContinuousVestingAccount)

View File

@ -0,0 +1,45 @@
package keeper
import (
"fmt"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
const (
QueryBalance = "balances"
)
// NewQuerier returns a new sdk.Keeper instance.
func NewQuerier(k Keeper) sdk.Querier {
return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, sdk.Error) {
switch path[0] {
case QueryBalance:
return queryBalance(ctx, req, k)
default:
return nil, sdk.ErrUnknownRequest("unknown bank query endpoint")
}
}
}
// queryBalance fetch an account's balance for the supplied height.
// Height and account address are passed as first and second path components respectively.
func queryBalance(ctx sdk.Context, req abci.RequestQuery, k Keeper) ([]byte, sdk.Error) {
var params types.QueryBalanceParams
if err := types.ModuleCdc.UnmarshalJSON(req.Data, &params); err != nil {
return nil, sdk.ErrInternal(fmt.Sprintf("failed to parse params: %s", err))
}
bz, err := codec.MarshalJSONIndent(types.ModuleCdc, k.GetCoins(ctx, params.Address))
if err != nil {
return nil, sdk.ErrInternal(sdk.AppendMsgToErr("could not marshal result to JSON", err.Error()))
}
return bz, nil
}

View File

@ -0,0 +1,59 @@
package keeper
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
abci "github.com/tendermint/tendermint/abci/types"
sdk "github.com/cosmos/cosmos-sdk/types"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/x/bank/internal/types"
)
func TestBalances(t *testing.T) {
input := setupTestInput()
req := abci.RequestQuery{
Path: fmt.Sprintf("custom/bank/%s", QueryBalance),
Data: []byte{},
}
querier := NewQuerier(input.k)
res, err := querier(input.ctx, []string{"balances"}, req)
require.NotNil(t, err)
require.Nil(t, res)
_, _, addr := authtypes.KeyTestPubAddr()
req.Data = input.cdc.MustMarshalJSON(types.NewQueryBalanceParams(addr))
res, err = querier(input.ctx, []string{"balances"}, req)
require.Nil(t, err) // the account does not exist, no error returned anyway
require.NotNil(t, res)
var coins sdk.Coins
require.NoError(t, input.cdc.UnmarshalJSON(res, &coins))
require.True(t, coins.IsZero())
acc := input.ak.NewAccountWithAddress(input.ctx, addr)
acc.SetCoins(sdk.NewCoins(sdk.NewInt64Coin("foo", 10)))
input.ak.SetAccount(input.ctx, acc)
res, err = querier(input.ctx, []string{"balances"}, req)
require.Nil(t, err)
require.NotNil(t, res)
require.NoError(t, input.cdc.UnmarshalJSON(res, &coins))
require.True(t, coins.AmountOf("foo").Equal(sdk.NewInt(10)))
}
func TestQuerierRouteNotFound(t *testing.T) {
input := setupTestInput()
req := abci.RequestQuery{
Path: "custom/bank/notfound",
Data: []byte{},
}
querier := NewQuerier(input.k)
_, err := querier(input.ctx, []string{"notfound"}, req)
require.Error(t, err)
}

View File

@ -2,5 +2,6 @@ package types
const (
// module name
ModuleName = "bank"
ModuleName = "bank"
QuerierRoute = ModuleName
)

View File

@ -0,0 +1,15 @@
package types
import (
sdk "github.com/cosmos/cosmos-sdk/types"
)
// QueryBalanceParams defines the params for querying an account balance.
type QueryBalanceParams struct {
Address sdk.AccAddress
}
// NewQueryBalanceParams creates a new instance of QueryBalanceParams.
func NewQueryBalanceParams(addr sdk.AccAddress) QueryBalanceParams {
return QueryBalanceParams{Address: addr}
}

View File

@ -26,8 +26,6 @@ var (
// app module basics object
type AppModuleBasic struct{}
var _ module.AppModuleBasic = AppModuleBasic{}
// module name
func (AppModuleBasic) Name() string { return ModuleName }
@ -94,10 +92,12 @@ func (AppModule) Route() string { return RouterKey }
func (am AppModule) NewHandler() sdk.Handler { return NewHandler(am.keeper) }
// module querier route name
func (AppModule) QuerierRoute() string { return "" }
func (AppModule) QuerierRoute() string { return RouterKey }
// module querier
func (AppModule) NewQuerierHandler() sdk.Querier { return nil }
func (am AppModule) NewQuerierHandler() sdk.Querier {
return keeper.NewQuerier(am.keeper)
}
// module init-genesis
func (am AppModule) InitGenesis(ctx sdk.Context, data json.RawMessage) []abci.ValidatorUpdate {