github.com/status-im/status-go@v1.1.0/services/wallet/router/pathprocessor/processor_transfer.go (about)

     1  package pathprocessor
     2  
     3  import (
     4  	"context"
     5  	"math/big"
     6  	"strings"
     7  
     8  	"github.com/ethereum/go-ethereum"
     9  	"github.com/ethereum/go-ethereum/accounts/abi"
    10  	"github.com/ethereum/go-ethereum/common"
    11  	ethTypes "github.com/ethereum/go-ethereum/core/types"
    12  	"github.com/status-im/status-go/account"
    13  	"github.com/status-im/status-go/contracts/ierc20"
    14  	"github.com/status-im/status-go/eth-node/types"
    15  	"github.com/status-im/status-go/rpc"
    16  	"github.com/status-im/status-go/transactions"
    17  )
    18  
    19  type TransferProcessor struct {
    20  	rpcClient  *rpc.Client
    21  	transactor transactions.TransactorIface
    22  }
    23  
    24  func NewTransferProcessor(rpcClient *rpc.Client, transactor transactions.TransactorIface) *TransferProcessor {
    25  	return &TransferProcessor{rpcClient: rpcClient, transactor: transactor}
    26  }
    27  
    28  func createTransferErrorResponse(err error) error {
    29  	return createErrorResponse(ProcessorTransferName, err)
    30  }
    31  
    32  func (s *TransferProcessor) Name() string {
    33  	return ProcessorTransferName
    34  }
    35  
    36  func (s *TransferProcessor) AvailableFor(params ProcessorInputParams) (bool, error) {
    37  	if params.FromChain == nil || params.ToChain == nil {
    38  		return false, ErrNoChainSet
    39  	}
    40  	if params.FromToken == nil {
    41  		return false, ErrNoTokenSet
    42  	}
    43  	if params.ToToken != nil {
    44  		return false, ErrToTokenShouldNotBeSet
    45  	}
    46  	return params.FromChain.ChainID == params.ToChain.ChainID, nil
    47  }
    48  
    49  func (s *TransferProcessor) CalculateFees(params ProcessorInputParams) (*big.Int, *big.Int, error) {
    50  	return ZeroBigIntValue, ZeroBigIntValue, nil
    51  }
    52  
    53  func (s *TransferProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) {
    54  	if params.FromToken.IsNative() {
    55  		return []byte("eth_sendRawTransaction"), nil
    56  	} else {
    57  		abi, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI))
    58  		if err != nil {
    59  			return []byte{}, createTransferErrorResponse(err)
    60  		}
    61  		return abi.Pack("transfer",
    62  			params.ToAddr,
    63  			params.AmountIn,
    64  		)
    65  	}
    66  }
    67  
    68  func (s *TransferProcessor) EstimateGas(params ProcessorInputParams) (uint64, error) {
    69  	if params.TestsMode {
    70  		if params.TestEstimationMap != nil {
    71  			if val, ok := params.TestEstimationMap[s.Name()]; ok {
    72  				return val.Value, val.Err
    73  			}
    74  		}
    75  		return 0, ErrNoEstimationFound
    76  	}
    77  
    78  	estimation := uint64(0)
    79  	var err error
    80  
    81  	input, err := s.PackTxInputData(params)
    82  	if err != nil {
    83  		return 0, createTransferErrorResponse(err)
    84  	}
    85  
    86  	if params.FromToken.IsNative() {
    87  		estimation, err = s.transactor.EstimateGas(params.FromChain, params.FromAddr, params.ToAddr, params.AmountIn, input)
    88  		if err != nil {
    89  			return 0, createTransferErrorResponse(err)
    90  		}
    91  	} else {
    92  		ethClient, err := s.rpcClient.EthClient(params.FromChain.ChainID)
    93  		if err != nil {
    94  			return 0, createTransferErrorResponse(err)
    95  		}
    96  
    97  		ctx := context.Background()
    98  
    99  		msg := ethereum.CallMsg{
   100  			From: params.FromAddr,
   101  			To:   &params.FromToken.Address,
   102  			Data: input,
   103  		}
   104  
   105  		estimation, err = ethClient.EstimateGas(ctx, msg)
   106  		if err != nil {
   107  			return 0, createTransferErrorResponse(err)
   108  		}
   109  
   110  	}
   111  
   112  	increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
   113  	return uint64(increasedEstimation), nil
   114  }
   115  
   116  func (s *TransferProcessor) Send(sendArgs *MultipathProcessorTxArgs, lastUsedNonce int64, verifiedAccount *account.SelectedExtKey) (types.Hash, uint64, error) {
   117  	return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.TransferTx, lastUsedNonce, verifiedAccount)
   118  }
   119  
   120  func (s *TransferProcessor) BuildTransaction(sendArgs *MultipathProcessorTxArgs, lastUsedNonce int64) (*ethTypes.Transaction, uint64, error) {
   121  	return s.transactor.ValidateAndBuildTransaction(sendArgs.ChainID, *sendArgs.TransferTx, lastUsedNonce)
   122  }
   123  
   124  func (s *TransferProcessor) CalculateAmountOut(params ProcessorInputParams) (*big.Int, error) {
   125  	return params.AmountIn, nil
   126  }
   127  
   128  func (s *TransferProcessor) GetContractAddress(params ProcessorInputParams) (common.Address, error) {
   129  	return common.Address{}, nil
   130  }