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  }