github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/x/wasm/keeper/handler_plugin_encoders.go (about)

     1  package keeper
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  
     7  	ibcadapter "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/ibc-adapter"
     8  	bank "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/bank"
     9  
    10  	wasmvmtypes "github.com/CosmWasm/wasmvm/types"
    11  	codectypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types"
    12  	sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types"
    13  	sdkerrors "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types/errors"
    14  	ibctransfertypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types"
    15  	ibcclienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types"
    16  	channeltypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/types"
    17  
    18  	"github.com/fibonacci-chain/fbc/x/wasm/types"
    19  )
    20  
    21  type BankEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.BankMsg) ([]ibcadapter.Msg, error)
    22  type CustomEncoder func(sender sdk.AccAddress, msg json.RawMessage) ([]ibcadapter.Msg, error)
    23  type DistributionEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.DistributionMsg) ([]ibcadapter.Msg, error)
    24  type StakingEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.StakingMsg) ([]ibcadapter.Msg, error)
    25  type StargateEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.StargateMsg) ([]ibcadapter.Msg, error)
    26  type WasmEncoder func(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]ibcadapter.Msg, error)
    27  type IBCEncoder func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]ibcadapter.Msg, error)
    28  
    29  type MessageEncoders struct {
    30  	Bank   func(sender sdk.AccAddress, msg *wasmvmtypes.BankMsg) ([]ibcadapter.Msg, error)
    31  	Custom func(sender sdk.AccAddress, msg json.RawMessage) ([]ibcadapter.Msg, error)
    32  	//Distribution func(sender sdk.AccAddress, msg *wasmvmtypes.DistributionMsg) ([]sdk.Msg, error)
    33  	//IBC          func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]sdk.Msg, error)
    34  	//Staking      func(sender sdk.AccAddress, msg *wasmvmtypes.StakingMsg) ([]sdk.Msg, error)
    35  	Stargate func(sender sdk.AccAddress, msg *wasmvmtypes.StargateMsg) ([]ibcadapter.Msg, error)
    36  	Wasm     func(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]ibcadapter.Msg, error)
    37  	//Gov          func(sender sdk.AccAddress, msg *wasmvmtypes.GovMsg) ([]sdk.Msg, error)
    38  }
    39  
    40  func DefaultEncoders(unpacker codectypes.AnyUnpacker, portSource types.ICS20TransferPortSource) MessageEncoders {
    41  	return MessageEncoders{
    42  		Bank:   EncodeBankMsg,
    43  		Custom: NoCustomMsg,
    44  		//Distribution: EncodeDistributionMsg,
    45  		//IBC:          EncodeIBCMsg(portSource),
    46  		//Staking:      EncodeStakingMsg,
    47  		Stargate: EncodeStargateMsg(unpacker),
    48  		Wasm:     EncodeWasmMsg,
    49  		//Gov:          EncodeGovMsg,
    50  	}
    51  }
    52  
    53  func (e MessageEncoders) Merge(o *MessageEncoders) MessageEncoders {
    54  	if o == nil {
    55  		return e
    56  	}
    57  	if o.Bank != nil {
    58  		e.Bank = o.Bank
    59  	}
    60  	if o.Custom != nil {
    61  		e.Custom = o.Custom
    62  	}
    63  	//if o.Distribution != nil {
    64  	//	e.Distribution = o.Distribution
    65  	//}
    66  	//if o.IBC != nil {
    67  	//	e.IBC = o.IBC
    68  	//}
    69  	//if o.Staking != nil {
    70  	//	e.Staking = o.Staking
    71  	//}
    72  	if o.Stargate != nil {
    73  		e.Stargate = o.Stargate
    74  	}
    75  	if o.Wasm != nil {
    76  		e.Wasm = o.Wasm
    77  	}
    78  	//if o.Gov != nil {
    79  	//	e.Gov = o.Gov
    80  	//}
    81  	return e
    82  }
    83  
    84  func (e MessageEncoders) Encode(ctx sdk.Context, contractAddr sdk.AccAddress, contractIBCPortID string, msg wasmvmtypes.CosmosMsg) ([]ibcadapter.Msg, error) {
    85  	switch {
    86  	case msg.Bank != nil:
    87  		return e.Bank(contractAddr, msg.Bank)
    88  	case msg.Custom != nil:
    89  		return e.Custom(contractAddr, msg.Custom)
    90  	//case msg.Distribution != nil:
    91  	//	return e.Distribution(contractAddr, msg.Distribution)
    92  	//case msg.IBC != nil:
    93  	//	return e.IBC(ctx, contractAddr, contractIBCPortID, msg.IBC)
    94  	//case msg.Staking != nil:
    95  	//	return e.Staking(contractAddr, msg.Staking)
    96  	case msg.Stargate != nil:
    97  		return e.Stargate(contractAddr, msg.Stargate)
    98  	case msg.Wasm != nil:
    99  		return e.Wasm(contractAddr, msg.Wasm)
   100  		//case msg.Gov != nil:
   101  		//	return EncodeGovMsg(contractAddr, msg.Gov)
   102  	}
   103  	return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "unknown variant of Wasm")
   104  }
   105  
   106  func EncodeBankMsg(sender sdk.AccAddress, msg *wasmvmtypes.BankMsg) ([]ibcadapter.Msg, error) {
   107  	if msg.Send == nil {
   108  		return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "unknown variant of Bank")
   109  	}
   110  	if len(msg.Send.Amount) == 0 {
   111  		return nil, nil
   112  	}
   113  	toSend, err := ConvertWasmCoinsToSdkCoins(msg.Send.Amount)
   114  	if err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	sdkMsg := bank.MsgSendAdapter{
   119  		FromAddress: sender.String(),
   120  		ToAddress:   msg.Send.ToAddress,
   121  		Amount:      toSend,
   122  	}
   123  	return []ibcadapter.Msg{&sdkMsg}, nil
   124  }
   125  
   126  func NoCustomMsg(sender sdk.AccAddress, msg json.RawMessage) ([]ibcadapter.Msg, error) {
   127  	return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "custom variant not supported")
   128  }
   129  
   130  //func EncodeDistributionMsg(sender sdk.AccAddress, msg *wasmvmtypes.DistributionMsg) ([]ibcadapter.Msg, error) {
   131  //	switch {
   132  //	case msg.SetWithdrawAddress != nil:
   133  //		withDrawAddress, err := sdk.AccAddressFromBech32(msg.SetWithdrawAddress.Address)
   134  //		if err != nil {
   135  //			return nil, err
   136  //		}
   137  //		setMsg := distributiontypes.MsgSetWithdrawAddress{
   138  //			DelegatorAddress: sender,
   139  //			WithdrawAddress:  withDrawAddress,
   140  //		}
   141  //		return []ibcadapter.Msg{&setMsg}, nil
   142  //	case msg.WithdrawDelegatorReward != nil:
   143  //		validatorAddress, err := sdk.AccAddressFromBech32(msg.WithdrawDelegatorReward.Validator)
   144  //		if err != nil {
   145  //			return nil, err
   146  //		}
   147  //		withdrawMsg := distributiontypes.MsgWithdrawDelegatorReward{
   148  //			DelegatorAddress: sender,
   149  //			ValidatorAddress: sdk.ValAddress(validatorAddress),
   150  //		}
   151  //		return []ibcadapter.Msg{&withdrawMsg}, nil
   152  //	default:
   153  //		return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "unknown variant of Distribution")
   154  //	}
   155  //}
   156  
   157  //func EncodeStakingMsg(sender sdk.AccAddress, msg *wasmvmtypes.StakingMsg) ([]ibcadapter.Msg, error) {
   158  //	switch {
   159  //	case msg.Delegate != nil:
   160  //		coin, err := ConvertWasmCoinToSdkCoin(msg.Delegate.Amount)
   161  //		if err != nil {
   162  //			return nil, err
   163  //		}
   164  //		validatorAddress, err := sdk.AccAddressFromBech32(msg.Delegate.Validator)
   165  //		if err != nil {
   166  //			return nil, err
   167  //		}
   168  //		sdkMsg := stakingtypes.MsgDelegate{
   169  //			DelegatorAddress: sender,
   170  //			ValidatorAddress: sdk.ValAddress(validatorAddress),
   171  //			Amount:           coin,
   172  //		}
   173  //		return []ibcadapter.Msg{&sdkMsg}, nil
   174  //
   175  //	case msg.Redelegate != nil:
   176  //		coin, err := ConvertWasmCoinToSdkCoin(msg.Redelegate.Amount)
   177  //		if err != nil {
   178  //			return nil, err
   179  //		}
   180  //		srcValidatorAddress, err := sdk.AccAddressFromBech32(msg.Redelegate.SrcValidator)
   181  //		if err != nil {
   182  //			return nil, err
   183  //		}
   184  //		dstValidatorAddress, err := sdk.AccAddressFromBech32(msg.Redelegate.DstValidator)
   185  //		if err != nil {
   186  //			return nil, err
   187  //		}
   188  //		sdkMsg := stakingtypes.MsgBeginRedelegate{
   189  //			DelegatorAddress:    sender,
   190  //			ValidatorSrcAddress: sdk.ValAddress(srcValidatorAddress),
   191  //			ValidatorDstAddress: sdk.ValAddress(dstValidatorAddress),
   192  //			Amount:              coin,
   193  //		}
   194  //		return []sdk.Msg{&sdkMsg}, nil
   195  //	case msg.Undelegate != nil:
   196  //		coin, err := ConvertWasmCoinToSdkCoin(msg.Undelegate.Amount)
   197  //		if err != nil {
   198  //			return nil, err
   199  //		}
   200  //		dstValidatorAddress, err := sdk.AccAddressFromBech32(msg.Undelegate.Validator)
   201  //		if err != nil {
   202  //			return nil, err
   203  //		}
   204  //		sdkMsg := stakingtypes.MsgUndelegate{
   205  //			DelegatorAddress: sender,
   206  //			ValidatorAddress: sdk.ValAddress(dstValidatorAddress),
   207  //			Amount:           coin,
   208  //		}
   209  //		return []sdk.Msg{&sdkMsg}, nil
   210  //	default:
   211  //		return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "unknown variant of Staking")
   212  //	}
   213  //}
   214  
   215  func EncodeStargateMsg(unpacker codectypes.AnyUnpacker) StargateEncoder {
   216  	return func(sender sdk.AccAddress, msg *wasmvmtypes.StargateMsg) ([]ibcadapter.Msg, error) {
   217  		any := codectypes.Any{
   218  			TypeUrl: msg.TypeURL,
   219  			Value:   msg.Value,
   220  		}
   221  		var sdkMsg ibcadapter.Msg
   222  		if err := unpacker.UnpackAny(&any, &sdkMsg); err != nil {
   223  			return nil, sdkerrors.Wrap(types.ErrInvalidMsg, fmt.Sprintf("Cannot unpack proto message with type URL: %s", msg.TypeURL))
   224  		}
   225  		if err := codectypes.UnpackInterfaces(sdkMsg, unpacker); err != nil {
   226  			return nil, sdkerrors.Wrap(types.ErrInvalidMsg, fmt.Sprintf("UnpackInterfaces inside msg: %s", err))
   227  		}
   228  		return []ibcadapter.Msg{sdkMsg}, nil
   229  	}
   230  }
   231  
   232  func EncodeWasmMsg(sender sdk.AccAddress, msg *wasmvmtypes.WasmMsg) ([]ibcadapter.Msg, error) {
   233  	switch {
   234  	case msg.Execute != nil:
   235  		coins, err := ConvertWasmCoinsToSdkCoins(msg.Execute.Funds)
   236  		if err != nil {
   237  			return nil, err
   238  		}
   239  
   240  		sdkMsg := types.MsgExecuteContract{
   241  			Sender:   sender.String(),
   242  			Contract: msg.Execute.ContractAddr,
   243  			Msg:      msg.Execute.Msg,
   244  			Funds:    coins,
   245  		}
   246  		return []ibcadapter.Msg{&sdkMsg}, nil
   247  	case msg.Instantiate != nil:
   248  		coins, err := ConvertWasmCoinsToSdkCoins(msg.Instantiate.Funds)
   249  		if err != nil {
   250  			return nil, err
   251  		}
   252  
   253  		sdkMsg := types.MsgInstantiateContract{
   254  			Sender: sender.String(),
   255  			CodeID: msg.Instantiate.CodeID,
   256  			Label:  msg.Instantiate.Label,
   257  			Msg:    msg.Instantiate.Msg,
   258  			Admin:  msg.Instantiate.Admin,
   259  			Funds:  coins,
   260  		}
   261  		return []ibcadapter.Msg{&sdkMsg}, nil
   262  	case msg.Migrate != nil:
   263  		sdkMsg := types.MsgMigrateContract{
   264  			Sender:   sender.String(),
   265  			Contract: msg.Migrate.ContractAddr,
   266  			CodeID:   msg.Migrate.NewCodeID,
   267  			Msg:      msg.Migrate.Msg,
   268  		}
   269  		return []ibcadapter.Msg{&sdkMsg}, nil
   270  	case msg.ClearAdmin != nil:
   271  		sdkMsg := types.MsgClearAdmin{
   272  			Sender:   sender.String(),
   273  			Contract: msg.ClearAdmin.ContractAddr,
   274  		}
   275  		return []ibcadapter.Msg{&sdkMsg}, nil
   276  	case msg.UpdateAdmin != nil:
   277  		sdkMsg := types.MsgUpdateAdmin{
   278  			Sender:   sender.String(),
   279  			Contract: msg.UpdateAdmin.ContractAddr,
   280  			NewAdmin: msg.UpdateAdmin.Admin,
   281  		}
   282  		return []ibcadapter.Msg{&sdkMsg}, nil
   283  	default:
   284  		return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "unknown variant of Wasm")
   285  	}
   286  }
   287  
   288  func EncodeIBCMsg(portSource types.ICS20TransferPortSource) func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]ibcadapter.Msg, error) {
   289  	return func(ctx sdk.Context, sender sdk.AccAddress, contractIBCPortID string, msg *wasmvmtypes.IBCMsg) ([]ibcadapter.Msg, error) {
   290  		switch {
   291  		case msg.CloseChannel != nil:
   292  			return []ibcadapter.Msg{&channeltypes.MsgChannelCloseInit{
   293  				PortId:    PortIDForContract(sender),
   294  				ChannelId: msg.CloseChannel.ChannelID,
   295  				Signer:    sender.String(),
   296  			}}, nil
   297  		case msg.Transfer != nil:
   298  			amount, err := ConvertWasmCoinToSdkCoin(msg.Transfer.Amount)
   299  			if err != nil {
   300  				return nil, sdkerrors.Wrap(err, "amount")
   301  			}
   302  			msg := &ibctransfertypes.MsgTransfer{
   303  				SourcePort:       portSource.GetPort(ctx),
   304  				SourceChannel:    msg.Transfer.ChannelID,
   305  				Token:            amount,
   306  				Sender:           sender.String(),
   307  				Receiver:         msg.Transfer.ToAddress,
   308  				TimeoutHeight:    ConvertWasmIBCTimeoutHeightToCosmosHeight(msg.Transfer.Timeout.Block),
   309  				TimeoutTimestamp: msg.Transfer.Timeout.Timestamp,
   310  			}
   311  			return []ibcadapter.Msg{msg}, nil
   312  		default:
   313  			return nil, sdkerrors.Wrap(types.ErrUnknownMsg, "Unknown variant of IBC")
   314  		}
   315  	}
   316  }
   317  
   318  //func EncodeGovMsg(sender sdk.AccAddress, msg *wasmvmtypes.GovMsg) ([]ibcadapter.Msg, error) {
   319  //	var option govtypes.VoteOption
   320  //	switch msg.Vote.Vote {
   321  //	case wasmvmtypes.Yes:
   322  //		option = govtypes.OptionYes
   323  //	case wasmvmtypes.No:
   324  //		option = govtypes.OptionNo
   325  //	case wasmvmtypes.NoWithVeto:
   326  //		option = govtypes.OptionNoWithVeto
   327  //	case wasmvmtypes.Abstain:
   328  //		option = govtypes.OptionAbstain
   329  //	}
   330  //	vote := &govtypes.MsgVote{
   331  //		ProposalID: msg.Vote.ProposalId,
   332  //		Voter:      sender,
   333  //		Option:     option,
   334  //	}
   335  //	return []ibcadapter.Msg{vote}, nil
   336  //}
   337  
   338  // ConvertWasmIBCTimeoutHeightToCosmosHeight converts a wasmvm type ibc timeout height to ibc module type height
   339  func ConvertWasmIBCTimeoutHeightToCosmosHeight(ibcTimeoutBlock *wasmvmtypes.IBCTimeoutBlock) ibcclienttypes.Height {
   340  	if ibcTimeoutBlock == nil {
   341  		return ibcclienttypes.NewHeight(0, 0)
   342  	}
   343  	return ibcclienttypes.NewHeight(ibcTimeoutBlock.Revision, ibcTimeoutBlock.Height)
   344  }
   345  
   346  // ConvertWasmCoinsToSdkCoins converts the wasm vm type coins to sdk type coins
   347  func ConvertWasmCoinsToSdkCoins(coins []wasmvmtypes.Coin) (sdk.CoinAdapters, error) {
   348  	var toSend sdk.CoinAdapters
   349  	for _, coin := range coins {
   350  		c, err := ConvertWasmCoinToSdkCoin(coin)
   351  		if err != nil {
   352  			return nil, err
   353  		}
   354  		toSend = append(toSend, c)
   355  	}
   356  	return toSend, nil
   357  }
   358  
   359  // ConvertWasmCoinToSdkCoin converts a wasm vm type coin to sdk type coin
   360  func ConvertWasmCoinToSdkCoin(coin wasmvmtypes.Coin) (sdk.CoinAdapter, error) {
   361  	amount, ok := sdk.NewIntFromString(coin.Amount)
   362  	if !ok {
   363  		return sdk.CoinAdapter{}, sdkerrors.Wrap(sdkerrors.ErrInvalidCoins, coin.Amount+coin.Denom)
   364  	}
   365  	r := sdk.CoinAdapter{
   366  		Denom:  coin.Denom,
   367  		Amount: amount,
   368  	}
   369  	if err := sdk.ValidateDenom(coin.Denom); err != nil {
   370  		return sdk.CoinAdapter{}, err
   371  	}
   372  	if r.IsNegative() {
   373  		return sdk.CoinAdapter{}, sdkerrors.Wrapf(sdkerrors.ErrInvalidCoins, coin.Amount+coin.Denom)
   374  	}
   375  	return r, nil
   376  }