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 }