github.com/fibonacci-chain/fbc@v0.0.0-20231124064014-c7636198c1e9/libs/ibc-go/modules/apps/transfer/client/cli/tx.go (about) 1 package cli 2 3 import ( 4 "bufio" 5 "errors" 6 "fmt" 7 "math/big" 8 "strings" 9 "time" 10 11 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/context" 12 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/client/flags" 13 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec" 14 interfacetypes "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/codec/types" 15 sdk "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/types" 16 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/version" 17 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth" 18 "github.com/fibonacci-chain/fbc/libs/cosmos-sdk/x/auth/client/utils" 19 "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/apps/transfer/types" 20 clienttypes "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/02-client/types" 21 channelutils "github.com/fibonacci-chain/fbc/libs/ibc-go/modules/core/04-channel/client/utils" 22 "github.com/spf13/cobra" 23 ) 24 25 const ( 26 flagPacketTimeoutHeight = "packet-timeout-height" 27 flagPacketTimeoutTimestamp = "packet-timeout-timestamp" 28 flagAbsoluteTimeouts = "absolute-timeouts" 29 ) 30 31 // NewTransferTxCmd returns the command to create a NewMsgTransfer transaction 32 func NewTransferTxCmd(m *codec.CodecProxy, reg interfacetypes.InterfaceRegistry) *cobra.Command { 33 cmd := &cobra.Command{ 34 Use: "transfer [src-port] [src-channel] [receiver] [amount]", 35 Short: "Transfer a fungible token through IBC", 36 Long: strings.TrimSpace(`Transfer a fungible token through IBC. Timeouts can be specified 37 as absolute or relative using the "absolute-timeouts" flag. Timeout height can be set by passing in the height string 38 in the form {revision}-{height} using the "packet-timeout-height" flag. Relative timeout height is added to the block 39 height queried from the latest consensus state corresponding to the counterparty channel. Relative timeout timestamp 40 is added to the greater value of the local clock time and the block timestamp queried from the latest consensus state 41 corresponding to the counterparty channel. Any timeout set to 0 is disabled.`), 42 Example: fmt.Sprintf("%s tx ibc-transfer transfer [src-port] [src-channel] [receiver] [amount]", version.ServerName), 43 Args: cobra.ExactArgs(4), 44 RunE: func(cmd *cobra.Command, args []string) error { 45 inBuf := bufio.NewReader(cmd.InOrStdin()) 46 txBldr := auth.NewTxBuilderFromCLI(inBuf).WithTxEncoder(utils.GetTxEncoder(m.GetCdc())) 47 clientCtx := context.NewCLIContext().WithCodec(m.GetCdc()).WithInterfaceRegistry(reg) 48 49 sender := clientCtx.GetFromAddress() 50 srcPort := args[0] 51 srcChannel := args[1] 52 receiver := args[2] 53 54 coin, err := sdk.ParseDecCoin(args[3]) 55 if err != nil { 56 return err 57 } 58 //if denom wei div prec 59 if coin.Denom == sdk.DefaultIbcWei { 60 coin.Amount = sdk.Dec{ 61 coin.Amount.Div(coin.Amount.BigInt(), big.NewInt(sdk.DefaultDecInt)), 62 } 63 } 64 // 65 if !strings.HasPrefix(coin.Denom, "ibc/") { 66 denomTrace := types.ParseDenomTrace(coin.Denom) 67 coin.Denom = denomTrace.IBCDenom() 68 } 69 70 timeoutHeightStr, err := cmd.Flags().GetString(flagPacketTimeoutHeight) 71 if err != nil { 72 return err 73 } 74 timeoutHeight, err := clienttypes.ParseHeight(timeoutHeightStr) 75 if err != nil { 76 return err 77 } 78 79 timeoutTimestamp, err := cmd.Flags().GetUint64(flagPacketTimeoutTimestamp) 80 if err != nil { 81 return err 82 } 83 84 absoluteTimeouts, err := cmd.Flags().GetBool(flagAbsoluteTimeouts) 85 if err != nil { 86 return err 87 } 88 89 // if the timeouts are not absolute, retrieve latest block height and block timestamp 90 // for the consensus state connected to the destination port/channel 91 if !absoluteTimeouts { 92 consensusState, height, _, err := channelutils.QueryLatestConsensusState(clientCtx, srcPort, srcChannel) 93 if err != nil { 94 return err 95 } 96 97 if !timeoutHeight.IsZero() { 98 absoluteHeight := height 99 absoluteHeight.RevisionNumber += timeoutHeight.RevisionNumber 100 absoluteHeight.RevisionHeight += timeoutHeight.RevisionHeight 101 timeoutHeight = absoluteHeight 102 } 103 104 if timeoutTimestamp != 0 { 105 // use local clock time as reference time if it is later than the 106 // consensus state timestamp of the counter party chain, otherwise 107 // still use consensus state timestamp as reference 108 now := time.Now().UnixNano() 109 consensusStateTimestamp := consensusState.GetTimestamp() 110 if now > 0 { 111 now := uint64(now) 112 if now > consensusStateTimestamp { 113 timeoutTimestamp = now + timeoutTimestamp 114 } else { 115 timeoutTimestamp = consensusStateTimestamp + timeoutTimestamp 116 } 117 } else { 118 return errors.New("local clock time is not greater than Jan 1st, 1970 12:00 AM") 119 } 120 } 121 } 122 123 msg := types.NewMsgTransfer( 124 srcPort, srcChannel, coin, sender, receiver, timeoutHeight, timeoutTimestamp, 125 ) 126 return utils.GenerateOrBroadcastMsgs(clientCtx, txBldr, []sdk.Msg{msg}) 127 }, 128 } 129 130 cmd.Flags().String(flagPacketTimeoutHeight, types.DefaultRelativePacketTimeoutHeight, "Packet timeout block height. The timeout is disabled when set to 0-0.") 131 cmd.Flags().Uint64(flagPacketTimeoutTimestamp, types.DefaultRelativePacketTimeoutTimestamp, "Packet timeout timestamp in nanoseconds. Default is 10 minutes. The timeout is disabled when set to 0.") 132 cmd.Flags().Bool(flagAbsoluteTimeouts, false, "Timeout flags are used as absolute timeouts.") 133 flags.AddTxFlagsToCmd(cmd) 134 135 return cmd 136 }