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: ¶ms.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 }