diff --git a/x/tokenfactory/bindings/message_plugin.go b/x/tokenfactory/bindings/message_plugin.go index 0e5e58f..a09a48f 100644 --- a/x/tokenfactory/bindings/message_plugin.go +++ b/x/tokenfactory/bindings/message_plugin.go @@ -64,10 +64,49 @@ func (m *CustomMessenger) DispatchMsg(ctx sdk.Context, contractAddr sdk.AccAddre if contractMsg.ForceTransfer != nil { return m.forceTransfer(ctx, contractAddr, contractMsg.ForceTransfer) } + if contractMsg.CreateStakedrop != nil { + return m.createStakedrop(ctx, contractAddr, contractMsg.CreateStakedrop) + } } return m.wrapped.DispatchMsg(ctx, contractAddr, contractIBCPortID, msg) } +// createDenom creates a new token denom +func (m *CustomMessenger) createStakedrop(ctx sdk.Context, contractAddr sdk.AccAddress, createStakedrop *bindingstypes.CreateStakedrop) ([]sdk.Event, [][]byte, [][]*types.Any, error) { + bz, err := PerformCreateStakedrop(m.tokenFactory, m.bank, ctx, contractAddr, createStakedrop) + if err != nil { + return nil, nil, nil, errorsmod.Wrap(err, "perform create stakedrop") + } + // TODO: double check how this is all encoded to the contract + return nil, [][]byte{bz}, nil, nil +} + +// PerformCreateStakedrop is used with createStakedrop to create a stakedrop; validates the msgCreateStakedrop. +func PerformCreateStakedrop(f *tokenfactorykeeper.Keeper, b bankkeeper.Keeper, ctx sdk.Context, contractAddr sdk.AccAddress, createStakedrop *bindingstypes.CreateStakedrop) ([]byte, error) { + if createStakedrop == nil { + return nil, wasmvmtypes.InvalidRequest{Err: "create stakedrop null create stakedrop"} + } + + msgServer := tokenfactorykeeper.NewMsgServerImpl(*f) + + msgCreateStakedrop := tokenfactorytypes.NewMsgCreateStakeDrop(contractAddr.String(), sdk.NewCoin(createStakedrop.Denom, createStakedrop.Amount), createStakedrop.StartBlock, createStakedrop.EndBlock) + + if err := msgCreateStakedrop.ValidateBasic(); err != nil { + return nil, errorsmod.Wrap(err, "failed validating MsgCreateStakedrop") + } + + // Create denom + resp, err := msgServer.CreateStakeDrop( + ctx, + msgCreateStakedrop, + ) + if err != nil { + return nil, errorsmod.Wrap(err, "creating stakedrop") + } + + return resp.Marshal() +} + // createDenom creates a new token denom func (m *CustomMessenger) createDenom(ctx sdk.Context, contractAddr sdk.AccAddress, createDenom *bindingstypes.CreateDenom) ([]sdk.Event, [][]byte, [][]*types.Any, error) { bz, err := PerformCreateDenom(m.tokenFactory, m.bank, ctx, contractAddr, createDenom) diff --git a/x/tokenfactory/bindings/queries.go b/x/tokenfactory/bindings/queries.go index 100468c..4f8de7b 100644 --- a/x/tokenfactory/bindings/queries.go +++ b/x/tokenfactory/bindings/queries.go @@ -8,6 +8,7 @@ import ( bindingstypes "github.com/ChihuahuaChain/chihuahua/x/tokenfactory/bindings/types" tokenfactorykeeper "github.com/ChihuahuaChain/chihuahua/x/tokenfactory/keeper" + tftypes "github.com/ChihuahuaChain/chihuahua/x/tokenfactory/types" ) type QueryPlugin struct { @@ -32,6 +33,27 @@ func (qp QueryPlugin) GetDenomAdmin(ctx sdk.Context, denom string) (*bindingstyp return &bindingstypes.AdminResponse{Admin: metadata.Admin}, nil } +// GetDenomAdmin is a query to get denom admin. +func (qp QueryPlugin) GetStakedropByDenom(ctx sdk.Context, denom string) (*bindingstypes.StakedropByDenomResponse, error) { + stakedropsByDenom := []tftypes.Stakedrop{} + iter, err := qp.tokenFactoryKeeper.ActiveStakedrop.Indexes.StakedropByDenom.MatchExact(ctx, denom) + if err != nil { + return nil, err + } + for ; iter.Valid(); iter.Next() { + key, err := iter.PrimaryKey() + if err != nil { + return nil, err + } + stakedrop, err := qp.tokenFactoryKeeper.ActiveStakedrop.Get(ctx, key) + if err != nil { + return nil, err + } + stakedropsByDenom = append(stakedropsByDenom, stakedrop) + } + return &bindingstypes.StakedropByDenomResponse{Stakedrops: stakedropsByDenom}, nil +} + func (qp QueryPlugin) GetDenomsByCreator(ctx sdk.Context, creator string) (*bindingstypes.DenomsByCreatorResponse, error) { // TODO: validate creator address denoms := qp.tokenFactoryKeeper.GetDenomsFromCreator(ctx, creator) diff --git a/x/tokenfactory/bindings/query_plugin.go b/x/tokenfactory/bindings/query_plugin.go index 28b4441..27c0759 100644 --- a/x/tokenfactory/bindings/query_plugin.go +++ b/x/tokenfactory/bindings/query_plugin.go @@ -8,9 +8,9 @@ import ( errorsmod "cosmossdk.io/errors" - sdk "github.com/cosmos/cosmos-sdk/types" - bindingstypes "github.com/ChihuahuaChain/chihuahua/x/tokenfactory/bindings/types" + tftypes "github.com/ChihuahuaChain/chihuahua/x/tokenfactory/types" + sdk "github.com/cosmos/cosmos-sdk/types" ) // CustomQuerier dispatches custom CosmWasm bindings queries. @@ -92,6 +92,33 @@ func CustomQuerier(qp *QueryPlugin) func(ctx sdk.Context, request json.RawMessag return nil, fmt.Errorf("failed to JSON marshal ParamsResponse: %w", err) } + return bz, nil + case contractQuery.Stakedrop != nil: + stakedropsByDenom := []tftypes.Stakedrop{} + iter, err := qp.tokenFactoryKeeper.ActiveStakedrop.Indexes.StakedropByDenom.MatchExact(ctx, contractQuery.Stakedrop.Denom) + if err != nil { + return nil, err + } + for ; iter.Valid(); iter.Next() { + key, err := iter.PrimaryKey() + if err != nil { + return nil, err + } + stakedrop, err := qp.tokenFactoryKeeper.ActiveStakedrop.Get(ctx, key) + if err != nil { + return nil, err + } + stakedropsByDenom = append(stakedropsByDenom, stakedrop) + } + if err != nil { + return nil, err + } + + bz, err := json.Marshal(stakedropsByDenom) + if err != nil { + return nil, fmt.Errorf("failed to JSON marshal ParamsResponse: %w", err) + } + return bz, nil default: diff --git a/x/tokenfactory/bindings/types/msg.go b/x/tokenfactory/bindings/types/msg.go index 81d9a68..d219306 100644 --- a/x/tokenfactory/bindings/types/msg.go +++ b/x/tokenfactory/bindings/types/msg.go @@ -19,6 +19,15 @@ type TokenFactoryMsg struct { SetMetadata *SetMetadata `json:"set_metadata,omitempty"` /// Forces a transfer of tokens from one address to another. ForceTransfer *ForceTransfer `json:"force_transfer,omitempty"` + + CreateStakedrop *CreateStakedrop `json:"create_stakedrop,omitempty"` +} + +type CreateStakedrop struct { + Denom string `json:"denom"` + Amount math.Int `json:"amount"` + StartBlock int64 `json:"start_block"` + EndBlock int64 `json:"end_block"` } // CreateDenom creates a new factory denom, of denomination: diff --git a/x/tokenfactory/bindings/types/query.go b/x/tokenfactory/bindings/types/query.go index 60f0ac3..c3718a0 100644 --- a/x/tokenfactory/bindings/types/query.go +++ b/x/tokenfactory/bindings/types/query.go @@ -1,14 +1,17 @@ package types +import "github.com/ChihuahuaChain/chihuahua/x/tokenfactory/types" + // See https://github.com/CosmWasm/token-bindings/blob/main/packages/bindings/src/query.rs type TokenFactoryQuery struct { /// Given a subdenom minted by a contract via `OsmosisMsg::MintTokens`, /// returns the full denom as used by `BankMsg::Send`. - FullDenom *FullDenom `json:"full_denom,omitempty"` - Admin *DenomAdmin `json:"admin,omitempty"` - Metadata *GetMetadata `json:"metadata,omitempty"` - DenomsByCreator *DenomsByCreator `json:"denoms_by_creator,omitempty"` - Params *GetParams `json:"params,omitempty"` + FullDenom *FullDenom `json:"full_denom,omitempty"` + Admin *DenomAdmin `json:"admin,omitempty"` + Metadata *GetMetadata `json:"metadata,omitempty"` + DenomsByCreator *DenomsByCreator `json:"denoms_by_creator,omitempty"` + Params *GetParams `json:"params,omitempty"` + Stakedrop *StakedropByDenom `json:"stakedrop,omitempty"` } // query types @@ -22,6 +25,10 @@ type GetMetadata struct { Denom string `json:"denom"` } +type StakedropByDenom struct { + Denom string `json:"denom"` +} + type DenomAdmin struct { Denom string `json:"denom"` } @@ -38,6 +45,10 @@ type FullDenomResponse struct { Denom string `json:"denom"` } +type StakedropByDenomResponse struct { + Stakedrops []types.Stakedrop `json:"stakedrops"` +} + type AdminResponse struct { Admin string `json:"admin"` }