/
query_binding.go
128 lines (104 loc) · 3.66 KB
/
query_binding.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package types
import (
"encoding/json"
wasmvmtypes "github.com/CosmWasm/wasmvm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
)
// WasmQuerierInterface - query registration interface for other modules
type WasmQuerierInterface interface {
Query(ctx sdk.Context, request wasmvmtypes.QueryRequest) ([]byte, error)
QueryCustom(ctx sdk.Context, data json.RawMessage) ([]byte, error)
}
// StargateWasmQuerierInterface - query registration interface for stargate querier
type StargateWasmQuerierInterface interface {
Query(ctx sdk.Context, request wasmvmtypes.QueryRequest) ([]byte, error)
}
// Querier - wasm query handler
type Querier struct {
Ctx sdk.Context
ContractAddr sdk.AccAddress
Queriers map[string]WasmQuerierInterface
StargateQuerier StargateWasmQuerierInterface
}
// NewWasmQuerier return wasm querier
func NewWasmQuerier() Querier {
return Querier{
Queriers: make(map[string]WasmQuerierInterface),
}
}
// WasmCustomQuery - wasm custom query
type WasmCustomQuery struct {
Route string `json:"route"`
QueryData json.RawMessage `json:"query_data"`
}
var _ wasmvmtypes.Querier = Querier{}
// Routes of pre-determined wasm querier
const (
WasmQueryRouteBank = "bank"
WasmQueryRouteStaking = "staking"
WasmQueryRouteMarket = "market"
WasmQueryRouteOracle = "oracle"
WasmQueryRouteTreasury = "treasury"
WasmQueryRouteWasm = "wasm"
)
// WithCtx returns new querier with context
func (q Querier) WithCtx(ctx sdk.Context) Querier {
q.Ctx = ctx
return q
}
// WithContractAddr returns new querier with contractAddr
func (q Querier) WithContractAddr(contractAddr sdk.AccAddress) Querier {
q.ContractAddr = contractAddr
return q
}
// GasConsumed consume gas in the current context
func (q Querier) GasConsumed() uint64 {
return q.Ctx.GasMeter().GasConsumed()
}
// Query - interface for wasmvmtypes.Querier
func (q Querier) Query(request wasmvmtypes.QueryRequest, gasLimit uint64) ([]byte, error) {
// set a limit for a ctx
// gasLimit passed from the go-cosmwasm part, so need to divide it with gas multiplier
ctx := q.Ctx.WithGasMeter(sdk.NewGasMeter(gasLimit / GasMultiplier))
// make sure we charge the higher level context even on panic
defer func() {
q.Ctx.GasMeter().ConsumeGas(ctx.GasMeter().GasConsumed(), "contract sub-query")
}()
// do the query
switch {
case request.Bank != nil:
if querier, ok := q.Queriers[WasmQueryRouteBank]; ok {
return querier.Query(ctx, request)
}
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteBank)
case request.Custom != nil:
var customQuery WasmCustomQuery
err := json.Unmarshal(request.Custom, &customQuery)
if err != nil {
return nil, sdkerrors.Wrap(sdkerrors.ErrJSONUnmarshal, err.Error())
}
if querier, ok := q.Queriers[customQuery.Route]; ok {
return querier.QueryCustom(ctx, customQuery.QueryData)
}
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, customQuery.Route)
case request.Staking != nil:
if querier, ok := q.Queriers[WasmQueryRouteStaking]; ok {
return querier.Query(ctx, request)
}
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteStaking)
case request.Wasm != nil:
if querier, ok := q.Queriers[WasmQueryRouteWasm]; ok {
return querier.Query(ctx, request)
}
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, WasmQueryRouteWasm)
case request.Stargate != nil:
if q.StargateQuerier != nil {
return q.StargateQuerier.Query(ctx, request)
}
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, "stargate")
case request.IBC != nil:
return nil, sdkerrors.Wrap(ErrNoRegisteredQuerier, "IBC not supported")
}
return nil, wasmvmtypes.Unknown{}
}