github.com/status-im/status-go@v1.1.0/services/wallet/router/pathprocessor/processor_ens_register.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/accounts/abi/bind"
    11  	"github.com/ethereum/go-ethereum/common"
    12  	ethTypes "github.com/ethereum/go-ethereum/core/types"
    13  	"github.com/status-im/status-go/account"
    14  	"github.com/status-im/status-go/contracts"
    15  	"github.com/status-im/status-go/contracts/registrar"
    16  	"github.com/status-im/status-go/contracts/snt"
    17  	"github.com/status-im/status-go/eth-node/types"
    18  	"github.com/status-im/status-go/rpc"
    19  	"github.com/status-im/status-go/services/ens"
    20  	walletCommon "github.com/status-im/status-go/services/wallet/common"
    21  	"github.com/status-im/status-go/transactions"
    22  )
    23  
    24  type ENSRegisterProcessor struct {
    25  	contractMaker *contracts.ContractMaker
    26  	transactor    transactions.TransactorIface
    27  	ensService    *ens.Service
    28  }
    29  
    30  func NewENSRegisterProcessor(rpcClient *rpc.Client, transactor transactions.TransactorIface, ensService *ens.Service) *ENSRegisterProcessor {
    31  	return &ENSRegisterProcessor{
    32  		contractMaker: &contracts.ContractMaker{
    33  			RPCClient: rpcClient,
    34  		},
    35  		transactor: transactor,
    36  		ensService: ensService,
    37  	}
    38  }
    39  
    40  func createENSRegisterProcessorErrorResponse(err error) error {
    41  	return createErrorResponse(ProcessorENSRegisterName, err)
    42  }
    43  
    44  func (s *ENSRegisterProcessor) Name() string {
    45  	return ProcessorENSRegisterName
    46  }
    47  
    48  func (s *ENSRegisterProcessor) GetPriceForRegisteringEnsName(chainID uint64) (*big.Int, error) {
    49  	registryAddr, err := s.ensService.API().GetRegistrarAddress(context.Background(), chainID)
    50  	if err != nil {
    51  		return nil, createENSRegisterProcessorErrorResponse(err)
    52  	}
    53  	registrar, err := s.contractMaker.NewUsernameRegistrar(chainID, registryAddr)
    54  	if err != nil {
    55  		return nil, createENSRegisterProcessorErrorResponse(err)
    56  	}
    57  
    58  	callOpts := &bind.CallOpts{Context: context.Background(), Pending: false}
    59  	return registrar.GetPrice(callOpts)
    60  }
    61  
    62  func (s *ENSRegisterProcessor) AvailableFor(params ProcessorInputParams) (bool, error) {
    63  	return params.FromChain.ChainID == walletCommon.EthereumMainnet || params.FromChain.ChainID == walletCommon.EthereumSepolia, nil
    64  }
    65  
    66  func (s *ENSRegisterProcessor) CalculateFees(params ProcessorInputParams) (*big.Int, *big.Int, error) {
    67  	return ZeroBigIntValue, ZeroBigIntValue, nil
    68  }
    69  
    70  func (s *ENSRegisterProcessor) PackTxInputData(params ProcessorInputParams) ([]byte, error) {
    71  	price, err := s.GetPriceForRegisteringEnsName(params.FromChain.ChainID)
    72  	if err != nil {
    73  		return []byte{}, createENSRegisterProcessorErrorResponse(err)
    74  	}
    75  
    76  	registrarABI, err := abi.JSON(strings.NewReader(registrar.UsernameRegistrarABI))
    77  	if err != nil {
    78  		return []byte{}, createENSRegisterProcessorErrorResponse(err)
    79  	}
    80  
    81  	x, y := ens.ExtractCoordinates(params.PublicKey)
    82  	extraData, err := registrarABI.Pack("register", ens.UsernameToLabel(params.Username), params.FromAddr, x, y)
    83  	if err != nil {
    84  		return []byte{}, createENSRegisterProcessorErrorResponse(err)
    85  	}
    86  
    87  	sntABI, err := abi.JSON(strings.NewReader(snt.SNTABI))
    88  	if err != nil {
    89  		return []byte{}, createENSRegisterProcessorErrorResponse(err)
    90  	}
    91  
    92  	registryAddr, err := s.ensService.API().GetRegistrarAddress(context.Background(), params.FromChain.ChainID)
    93  	if err != nil {
    94  		return []byte{}, createENSRegisterProcessorErrorResponse(err)
    95  	}
    96  
    97  	return sntABI.Pack("approveAndCall", registryAddr, price, extraData)
    98  }
    99  
   100  func (s *ENSRegisterProcessor) EstimateGas(params ProcessorInputParams) (uint64, error) {
   101  	if params.TestsMode {
   102  		if params.TestEstimationMap != nil {
   103  			if val, ok := params.TestEstimationMap[s.Name()]; ok {
   104  				return val.Value, val.Err
   105  			}
   106  		}
   107  		return 0, ErrNoEstimationFound
   108  	}
   109  
   110  	contractAddress, err := s.GetContractAddress(params)
   111  	if err != nil {
   112  		return 0, createENSRegisterProcessorErrorResponse(err)
   113  	}
   114  
   115  	input, err := s.PackTxInputData(params)
   116  	if err != nil {
   117  		return 0, createENSRegisterProcessorErrorResponse(err)
   118  	}
   119  
   120  	ethClient, err := s.contractMaker.RPCClient.EthClient(params.FromChain.ChainID)
   121  	if err != nil {
   122  		return 0, createENSRegisterProcessorErrorResponse(err)
   123  	}
   124  
   125  	msg := ethereum.CallMsg{
   126  		From:  params.FromAddr,
   127  		To:    &contractAddress,
   128  		Value: ZeroBigIntValue,
   129  		Data:  input,
   130  	}
   131  
   132  	estimation, err := ethClient.EstimateGas(context.Background(), msg)
   133  	if err != nil {
   134  		return 0, createENSRegisterProcessorErrorResponse(err)
   135  	}
   136  
   137  	increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
   138  
   139  	return uint64(increasedEstimation), nil
   140  }
   141  
   142  func (s *ENSRegisterProcessor) Send(sendArgs *MultipathProcessorTxArgs, lastUsedNonce int64, verifiedAccount *account.SelectedExtKey) (hash types.Hash, usedNonce uint64, err error) {
   143  	return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.TransferTx, lastUsedNonce, verifiedAccount)
   144  }
   145  
   146  func (s *ENSRegisterProcessor) BuildTransaction(sendArgs *MultipathProcessorTxArgs, lastUsedNonce int64) (*ethTypes.Transaction, uint64, error) {
   147  	return s.transactor.ValidateAndBuildTransaction(sendArgs.ChainID, *sendArgs.TransferTx, lastUsedNonce)
   148  }
   149  
   150  func (s *ENSRegisterProcessor) CalculateAmountOut(params ProcessorInputParams) (*big.Int, error) {
   151  	return params.AmountIn, nil
   152  }
   153  
   154  func (s *ENSRegisterProcessor) GetContractAddress(params ProcessorInputParams) (common.Address, error) {
   155  	return snt.ContractAddress(params.FromChain.ChainID)
   156  }