Sale Djenic 6bfc1bed08 chore: read and use nonce from network instead from the local cache when sending tx
Reading the Nonce from the local cache may be incorrect if the tx is made out of the Status app or
if Status app sends a tx prepared by the dapp (via WalletConnect). A submitted tx with a wrong Nonce
results in a failing tx, that's why we need to read the Nonce from the network.
2023-12-29 08:43:03 +01:00

102 lines
3.0 KiB
Go

package bridge
import (
"context"
"math/big"
"strings"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
ethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/contracts/ierc20"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/rpc"
"github.com/status-im/status-go/services/wallet/token"
"github.com/status-im/status-go/transactions"
)
type TransferBridge struct {
rpcClient *rpc.Client
transactor *transactions.Transactor
}
func NewTransferBridge(rpcClient *rpc.Client, transactor *transactions.Transactor) *TransferBridge {
return &TransferBridge{rpcClient: rpcClient, transactor: transactor}
}
func (s *TransferBridge) Name() string {
return "Transfer"
}
func (s *TransferBridge) Can(from, to *params.Network, token *token.Token, balance *big.Int) (bool, error) {
return from.ChainID == to.ChainID, nil
}
func (s *TransferBridge) CalculateFees(from, to *params.Network, token *token.Token, amountIn *big.Int, nativeTokenPrice, tokenPrice float64, gasPrice *big.Float) (*big.Int, *big.Int, error) {
return big.NewInt(0), big.NewInt(0), nil
}
func (s *TransferBridge) EstimateGas(fromNetwork *params.Network, toNetwork *params.Network, from common.Address, to common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
estimation := uint64(0)
var err error
if token.Symbol == "ETH" {
estimation, err = s.transactor.EstimateGas(fromNetwork, from, to, amountIn, []byte("eth_sendRawTransaction"))
if err != nil {
return 0, err
}
} else {
ethClient, err := s.rpcClient.EthClient(fromNetwork.ChainID)
if err != nil {
return 0, err
}
abi, err := abi.JSON(strings.NewReader(ierc20.IERC20ABI))
if err != nil {
return 0, err
}
input, err := abi.Pack("transfer",
to,
amountIn,
)
if err != nil {
return 0, err
}
ctx := context.Background()
msg := ethereum.CallMsg{
From: from,
To: &token.Address,
Data: input,
}
estimation, err = ethClient.EstimateGas(ctx, msg)
if err != nil {
return 0, err
}
}
increasedEstimation := float64(estimation) * IncreaseEstimatedGasFactor
return uint64(increasedEstimation), nil
}
func (s *TransferBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error) {
return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.TransferTx, verifiedAccount)
}
func (s *TransferBridge) BuildTransaction(sendArgs *TransactionBridge) (*ethTypes.Transaction, error) {
return s.transactor.ValidateAndBuildTransaction(sendArgs.ChainID, *sendArgs.TransferTx)
}
func (s *TransferBridge) CalculateAmountOut(from, to *params.Network, amountIn *big.Int, symbol string) (*big.Int, error) {
return amountIn, nil
}
func (s *TransferBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
return nil
}