Skip to content

Commit

Permalink
added 2 extra method that allow to add/remove allowed tokens for ibc tx
Browse files Browse the repository at this point in the history
  • Loading branch information
RustNinja committed Mar 25, 2024
1 parent 6a2efe4 commit 2c06ec9
Show file tree
Hide file tree
Showing 6 changed files with 1,394 additions and 140 deletions.
54 changes: 54 additions & 0 deletions proto/composable/ibctransfermiddleware/v1beta1/tx.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ service Msg {
returns (MsgAddIBCFeeConfigResponse);
rpc RemoveIBCFeeConfig(MsgRemoveIBCFeeConfig)
returns (MsgRemoveIBCFeeConfigResponse);

rpc AddAllowedIbcToken(MsgAddAllowedIbcToken)
returns (MsgAddAllowedIbcTokenResponse);
rpc RemoveAllowedIbcToken(MsgRemoveAllowedIbcToken)
returns (MsgRemoveAllowedIbcTokenResponse);
}

// MsgUpdateParams is the Msg/UpdateParams request type.
Expand Down Expand Up @@ -82,3 +87,52 @@ message MsgRemoveIBCFeeConfig {
}

message MsgRemoveIBCFeeConfigResponse {}



// MsgAddParachainInfo represents a message to add new parachain info.
message MsgAddAllowedIbcToken {
option (cosmos.msg.v1.signer) = "authority";

// authority is the address that controls the module (defaults to x/gov unless
// overwritten).
string authority = 1 [ (gogoproto.moretags) = "yaml:\"authority\"" ];

string channel_id = 2 [
(gogoproto.moretags) = "yaml:\"channel_id\"",
(gogoproto.customname) = "ChannelID"
];

string denom = 3 [
(gogoproto.moretags) = "yaml:\"channel_id\"",
(gogoproto.customname) = "Denom"
];

int64 amount = 4;

int64 percentage = 5;
}

message MsgAddAllowedIbcTokenResponse {}


message MsgRemoveAllowedIbcToken {
option (cosmos.msg.v1.signer) = "authority";

// authority is the address that controls the module (defaults to x/gov unless
// overwritten).
string authority = 1 [ (gogoproto.moretags) = "yaml:\"authority\"" ];
;

string channel_id = 2 [
(gogoproto.moretags) = "yaml:\"channel_id\"",
(gogoproto.customname) = "ChannelID"
];

string denom = 3 [
(gogoproto.moretags) = "yaml:\"channel_id\"",
(gogoproto.customname) = "Denom"
];
}

message MsgRemoveAllowedIbcTokenResponse {}
91 changes: 88 additions & 3 deletions x/ibctransfermiddleware/client/cli/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,16 @@ func GetTxCmd() *cobra.Command {
txCmd.AddCommand(
AddIBCFeeConfig(),
RemoveIBCFeeConfig(),
AddAllowedIbcToken(),
RemoveAllowedIbcToken(),
)

return txCmd
}

func AddIBCFeeConfig() *cobra.Command {
cmd := &cobra.Command{
Use: "add-config [addr ]",
Use: "add-config [channel] [feeAddress] [minTimeoutTimestamp]",
Short: "add ibc fee config",
Args: cobra.MatchAll(cobra.ExactArgs(3), cobra.OnlyValidArgs),
Example: fmt.Sprintf("%s tx ibctransfermiddleware add-config [channel] [feeAddress] [minTimeoutTimestamp]", version.AppName),
Expand Down Expand Up @@ -73,10 +75,59 @@ func AddIBCFeeConfig() *cobra.Command {
return cmd
}

func AddAllowedIbcToken() *cobra.Command {
cmd := &cobra.Command{
Use: "add-allowed-ibc-token [channel] [denom] [amount] [percentage]",
Short: "add allowed ibc token",
Args: cobra.MatchAll(cobra.ExactArgs(4), cobra.OnlyValidArgs),
Example: fmt.Sprintf("%s tx ibctransfermiddleware add-allowed-ibc-token [channel] [denom] [amount] [percentage] (percentage '5' means 1/5 of amount will be taken as fee) ", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
channel := args[0]
denom := args[1]
amount := args[2]
percentage := args[3]

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

fromAddress := clientCtx.GetFromAddress().String()

amountInt, err := strconv.ParseInt(amount, 10, 64)
if err != nil {
return err
}

percentageInt, errPercentage := strconv.ParseInt(percentage, 10, 64)
if errPercentage != nil {
return errPercentage
}

msg := types.NewMsgAddAllowedIbcToken(
fromAddress,
channel,
denom,
amountInt,
percentageInt,
)

if err := msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
flags.AddTxFlagsToCmd(cmd)

return cmd
}

func RemoveIBCFeeConfig() *cobra.Command {
cmd := &cobra.Command{
Use: "remove-config [addr ]",
Short: "add ibc fee config",
Use: "remove-config [channel]",
Short: "remove ibc fee config",
Args: cobra.MatchAll(cobra.ExactArgs(1), cobra.OnlyValidArgs),
Example: fmt.Sprintf("%s tx ibctransfermiddleware remove-config [channel]", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
Expand Down Expand Up @@ -104,3 +155,37 @@ func RemoveIBCFeeConfig() *cobra.Command {

return cmd
}

func RemoveAllowedIbcToken() *cobra.Command {
cmd := &cobra.Command{
Use: "remove-allowed-ibc-token [channel] [denom]",
Short: "remove allowed ibc token",
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
Example: fmt.Sprintf("%s tx ibctransfermiddleware remove-allowed-ibc-token [channel] [denom]", version.AppName),
RunE: func(cmd *cobra.Command, args []string) error {
channel := args[0]
denom := args[1]

clientCtx, err := client.GetClientTxContext(cmd)
if err != nil {
return err
}

fromAddress := clientCtx.GetFromAddress().String()

msg := types.NewMsgRemoveAllowedIbcToken(
fromAddress,
channel,
denom,
)
if err := msg.ValidateBasic(); err != nil {
return err
}

return tx.GenerateOrBroadcastTxCLI(clientCtx, cmd.Flags(), msg)
},
}
flags.AddTxFlagsToCmd(cmd)

return cmd
}
80 changes: 80 additions & 0 deletions x/ibctransfermiddleware/keeper/msg_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,72 @@ func (ms msgServer) RemoveIBCFeeConfig(goCtx context.Context, req *types.MsgRemo
return &types.MsgRemoveIBCFeeConfigResponse{}, nil
}

func (ms msgServer) AddAllowedIbcToken(goCtx context.Context, req *types.MsgAddAllowedIbcToken) (*types.MsgAddAllowedIbcTokenResponse, error) {
if ms.authority != req.Authority {
// return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; Nikita expected %s, got %s", ms.authority, req.Authority)
}

ctx := sdk.UnwrapSDKContext(goCtx)
params := ms.Keeper.GetParams(ctx)
channelFee := findChannelParams(params.ChannelFees, req.ChannelID)
if channelFee != nil {
coin := findCoinByDenom(channelFee.AllowedTokens, req.Denom)
if coin != nil {
coin_c := sdk.Coin{
Denom: req.Denom,
Amount: sdk.NewInt(req.Amount),
}
coin.MinFee = coin_c
coin.Percentage = req.Percentage
} else {
coin_c := sdk.Coin{
Denom: req.Denom,
Amount: sdk.NewInt(req.Amount),
}
coin := &types.CoinItem{
MinFee: coin_c,
Percentage: req.Percentage,
}
channelFee.AllowedTokens = append(channelFee.AllowedTokens, coin)
}
} else {
return nil, errorsmod.Wrapf(types.ErrChannelFeeNotFound, "channel fee not found for channel %s", req.ChannelID)
}
errSetParams := ms.Keeper.SetParams(ctx, params)
if errSetParams != nil {
return nil, errSetParams
}

return &types.MsgAddAllowedIbcTokenResponse{}, nil
}

func (ms msgServer) RemoveAllowedIbcToken(goCtx context.Context, req *types.MsgRemoveAllowedIbcToken) (*types.MsgRemoveAllowedIbcTokenResponse, error) {
if ms.authority != req.Authority {
// return nil, errorsmod.Wrapf(govtypes.ErrInvalidSigner, "invalid authority; expected %s, got %s", ms.authority, req.Authority)
}

ctx := sdk.UnwrapSDKContext(goCtx)
params := ms.Keeper.GetParams(ctx)
channelFee := findChannelParams(params.ChannelFees, req.ChannelID)
if channelFee != nil {
for i, coin := range channelFee.AllowedTokens {
if coin.MinFee.Denom == req.Denom {
channelFee.AllowedTokens = append(channelFee.AllowedTokens[:i], channelFee.AllowedTokens[i+1:]...)
break
}
}
} else {
return nil, errorsmod.Wrapf(types.ErrChannelFeeNotFound, "channel fee not found for channel %s", req.ChannelID)
}

errSetParams := ms.Keeper.SetParams(ctx, params)
if errSetParams != nil {
return nil, errSetParams
}

return &types.MsgRemoveAllowedIbcTokenResponse{}, nil
}

func findChannelParams(channelFees []*types.ChannelFee, targetChannelID string) *types.ChannelFee {
for _, fee := range channelFees {
if fee.Channel == targetChannelID {
Expand All @@ -101,3 +167,17 @@ func findChannelParams(channelFees []*types.ChannelFee, targetChannelID string)
}
return nil // If the channel is not found
}

func findCoinByDenom(allowedTokens []*types.CoinItem, denom string) *types.CoinItem {
for _, coin := range allowedTokens {
if coin.MinFee.Denom == denom {
return coin
}
}
return nil // If the denom is not found
}

// rpc AddAllowedIbcToken(MsgAddAllowedIbcToken)
// returns (MsgAddAllowedIbcTokenResponse);
// rpc RemoveAllowedIbcToken(MsgRemoveAllowedIbcToken)
// returns (MsgRemoveAllowedIbcTokenResponse);
10 changes: 10 additions & 0 deletions x/ibctransfermiddleware/types/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package types

import (
errorsmod "cosmossdk.io/errors"
)

// x/ratelimit module sentinel errors
var (
ErrChannelFeeNotFound = errorsmod.Register(ModuleName, 1, "channel fee not found for channel")
)
88 changes: 88 additions & 0 deletions x/ibctransfermiddleware/types/msg.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ var _ sdk.Msg = &MsgAddIBCFeeConfig{}
const (
TypeMsgAddIBCFeeConfig = "add_config"
TypeMsgRemoveIBCFeeConfig = "remove_config"

TypeMsgAddAllowedIbcToken = "add_allowed_ibc_token"
TypeMsgRemoveAllowedIbcToken = "remove_allowed_ibc_token"
)

func NewMsgAddIBCFeeConfig(
Expand Down Expand Up @@ -101,3 +104,88 @@ func (msg *MsgRemoveIBCFeeConfig) ValidateBasic() error {

return nil
}

var _ sdk.Msg = &MsgAddAllowedIbcToken{}

func NewMsgAddAllowedIbcToken(
authority string,
channelID string,
denom string,
amount int64,
percentage int64,
) *MsgAddAllowedIbcToken {
return &MsgAddAllowedIbcToken{
Authority: authority,
ChannelID: channelID,
Denom: denom,
Amount: amount,
Percentage: percentage,
}
}

// Route Implements Msg.
func (msg MsgAddAllowedIbcToken) Route() string { return RouterKey }

// Type Implements Msg.
func (msg MsgAddAllowedIbcToken) Type() string { return TypeMsgAddAllowedIbcToken }

// GetSignBytes implements the LegacyMsg interface.
func (msg MsgAddAllowedIbcToken) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}

// GetSigners returns the expected signers for a MsgAddParachainIBCTokenInfo message.
func (msg *MsgAddAllowedIbcToken) GetSigners() []sdk.AccAddress {
addr, _ := sdk.AccAddressFromBech32(msg.Authority)
return []sdk.AccAddress{addr}
}

// ValidateBasic does a sanity check on the provided data.
func (msg *MsgAddAllowedIbcToken) ValidateBasic() error {
// validate authority
if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
return sdkerrors.Wrap(err, "invalid authority address")
}

return nil
}

var _ sdk.Msg = &MsgRemoveAllowedIbcToken{}

func NewMsgRemoveAllowedIbcToken(
authority string,
channelID string,
denom string,
) *MsgRemoveAllowedIbcToken {
return &MsgRemoveAllowedIbcToken{
Authority: authority,
ChannelID: channelID,
Denom: denom,
}
}

// Route Implements Msg.
func (msg MsgRemoveAllowedIbcToken) Route() string { return RouterKey }

// Type Implements Msg.
func (msg MsgRemoveAllowedIbcToken) Type() string { return TypeMsgRemoveAllowedIbcToken }

// GetSignBytes implements the LegacyMsg interface.
func (msg MsgRemoveAllowedIbcToken) GetSignBytes() []byte {
return sdk.MustSortJSON(ModuleCdc.MustMarshalJSON(&msg))
}

// GetSigners returns the expected signers for a MsgRemoveParachainIBCTokenInfo message.
func (msg *MsgRemoveAllowedIbcToken) GetSigners() []sdk.AccAddress {
addr, _ := sdk.AccAddressFromBech32(msg.Authority)
return []sdk.AccAddress{addr}
}

// ValidateBasic does a sanity check on the provided data.
func (msg *MsgRemoveAllowedIbcToken) ValidateBasic() error {
if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
return sdkerrors.Wrap(err, "invalid authority address")
}

return nil
}
Loading

0 comments on commit 2c06ec9

Please sign in to comment.