feat: route-send-collectible

This commit is contained in:
Anthony Laibe 2023-08-24 10:45:14 +02:00
parent 195214765b
commit 01babe3632
10 changed files with 328 additions and 108 deletions

View File

@ -445,7 +445,7 @@ func (api *API) GetSuggestedRoutes(
sendType SendType,
account common.Address,
amountIn *hexutil.Big,
tokenSymbol string,
tokenID string,
disabledFromChainIDs,
disabledToChaindIDs,
preferedChainIDs []uint64,
@ -453,7 +453,7 @@ func (api *API) GetSuggestedRoutes(
fromLockedAmount map[uint64]*hexutil.Big,
) (*SuggestedRoutes, error) {
log.Debug("call to GetSuggestedRoutes")
return api.router.suggestedRoutes(ctx, sendType, account, amountIn.ToInt(), tokenSymbol, disabledFromChainIDs, disabledToChaindIDs, preferedChainIDs, gasFeeMode, fromLockedAmount)
return api.router.suggestedRoutes(ctx, sendType, account, amountIn.ToInt(), tokenID, disabledFromChainIDs, disabledToChaindIDs, preferedChainIDs, gasFeeMode, fromLockedAmount)
}
// Generates addresses for the provided paths, response doesn't include `HasActivity` value (if you need it check `GetAddressDetails` function)

View File

@ -24,54 +24,63 @@ func getSigner(chainID uint64, from types.Address, verifiedAccount *account.Sele
type TransactionBridge struct {
BridgeName string
ChainID uint64
SimpleTx *transactions.SendTxArgs
TransferTx *transactions.SendTxArgs
HopTx *HopTxArgs
CbridgeTx *CBridgeTxArgs
ERC721TransferTx *ERC721TransferTxArgs
}
func (t *TransactionBridge) Value() *big.Int {
if t.SimpleTx != nil && t.SimpleTx.To != nil {
return t.SimpleTx.Value.ToInt()
if t.TransferTx != nil && t.TransferTx.To != nil {
return t.TransferTx.Value.ToInt()
} else if t.HopTx != nil {
return t.HopTx.Amount.ToInt()
} else if t.CbridgeTx != nil {
return t.CbridgeTx.Amount.ToInt()
} else if t.ERC721TransferTx != nil {
return big.NewInt(1)
}
return big.NewInt(0)
}
func (t *TransactionBridge) From() types.Address {
if t.SimpleTx != nil && t.SimpleTx.To != nil {
return t.SimpleTx.From
if t.TransferTx != nil && t.TransferTx.To != nil {
return t.TransferTx.From
} else if t.HopTx != nil {
return t.HopTx.From
} else if t.CbridgeTx != nil {
return t.CbridgeTx.From
} else if t.ERC721TransferTx != nil {
return t.ERC721TransferTx.From
}
return types.HexToAddress("0x0")
}
func (t *TransactionBridge) To() types.Address {
if t.SimpleTx != nil && t.SimpleTx.To != nil {
return *t.SimpleTx.To
if t.TransferTx != nil && t.TransferTx.To != nil {
return *t.TransferTx.To
} else if t.HopTx != nil {
return types.Address(t.HopTx.Recipient)
} else if t.CbridgeTx != nil {
return types.Address(t.HopTx.Recipient)
} else if t.ERC721TransferTx != nil {
return types.Address(t.ERC721TransferTx.Recipient)
}
return types.HexToAddress("0x0")
}
func (t *TransactionBridge) Data() types.HexBytes {
if t.SimpleTx != nil && t.SimpleTx.To != nil {
return t.SimpleTx.Data
if t.TransferTx != nil && t.TransferTx.To != nil {
return t.TransferTx.Data
} else if t.HopTx != nil {
return types.HexBytes("")
} else if t.CbridgeTx != nil {
return types.HexBytes("")
} else if t.ERC721TransferTx != nil {
return types.HexBytes("")
}
return types.HexBytes("")
@ -81,7 +90,7 @@ type Bridge interface {
Name() string
Can(from *params.Network, to *params.Network, token *token.Token, balance *big.Int) (bool, error)
CalculateFees(from, to *params.Network, token *token.Token, amountIn *big.Int, nativeTokenPrice, tokenPrice float64, gasPrice *big.Float) (*big.Int, *big.Int, error)
EstimateGas(from *params.Network, to *params.Network, token *token.Token, amountIn *big.Int) (uint64, error)
EstimateGas(from *params.Network, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error)
CalculateAmountOut(from, to *params.Network, amountIn *big.Int, symbol string) (*big.Int, error)
Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error)
GetContractAddress(network *params.Network, token *token.Token) *common.Address

View File

@ -216,7 +216,7 @@ func (s *CBridge) CalculateFees(from, to *params.Network, token *token.Token, am
return big.NewInt(0), new(big.Int).Add(baseFee, percFee), nil
}
func (s *CBridge) EstimateGas(from, to *params.Network, token *token.Token, amountIn *big.Int) (uint64, error) {
func (s *CBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
// TODO: replace by estimate function
if token.IsNative() {
return 22000, nil // default gas limit for eth transaction

View File

@ -0,0 +1,109 @@
package bridge
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/contracts/community-tokens/collectibles"
"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 ERC721TransferTxArgs struct {
transactions.SendTxArgs
TokenID *hexutil.Big `json:"tokenId"`
Recipient common.Address `json:"recipient"`
}
type ERC721TransferBridge struct {
rpcClient *rpc.Client
transactor *transactions.Transactor
}
func NewERC721TransferBridge(rpcClient *rpc.Client, transactor *transactions.Transactor) *ERC721TransferBridge {
return &ERC721TransferBridge{rpcClient: rpcClient, transactor: transactor}
}
func (s *ERC721TransferBridge) Name() string {
return "ERC721Transfer"
}
func (s *ERC721TransferBridge) Can(from, to *params.Network, token *token.Token, balance *big.Int) (bool, error) {
return from.ChainID == to.ChainID, nil
}
func (s *ERC721TransferBridge) 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 *ERC721TransferBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
// ethClient, err := s.rpcClient.EthClient(from.ChainID)
// if err != nil {
// return 0, err
// }
// collectiblesABI, err := abi.JSON(strings.NewReader(collectibles.CollectiblesABI))
// if err != nil {
// return 0, err
// }
// toAddress := common.HexToAddress("0x0")
// tokenID, success := new(big.Int).SetString(token.Symbol, 10)
// if !success {
// return 0, err
// }
// data, err := collectiblesABI.Pack("safeTransferFrom", account, toAddress, tokenID)
// if err != nil {
// return 0, err
// }
// estimate, err := ethClient.EstimateGas(context.Background(), ethereum.CallMsg{
// From: account,
// To: &toAddress,
// Value: big.NewInt(0),
// Data: data,
// })
// if err != nil {
// return 0, err
// }
// return estimate + 1000, nil
return 80000, nil
}
func (s *ERC721TransferBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (hash types.Hash, err error) {
ethClient, err := s.rpcClient.EthClient(sendArgs.ChainID)
if err != nil {
return hash, err
}
contract, err := collectibles.NewCollectibles(common.Address(*sendArgs.ERC721TransferTx.To), ethClient)
if err != nil {
return hash, err
}
nonce, unlock, err := s.transactor.NextNonce(s.rpcClient, sendArgs.ChainID, sendArgs.ERC721TransferTx.From)
if err != nil {
return hash, err
}
defer func() {
unlock(err == nil, nonce)
}()
argNonce := hexutil.Uint64(nonce)
sendArgs.ERC721TransferTx.Nonce = &argNonce
txOpts := sendArgs.ERC721TransferTx.ToTransactOpts(getSigner(sendArgs.ChainID, sendArgs.ERC721TransferTx.From, verifiedAccount))
tx, err := contract.SafeTransferFrom(txOpts, common.Address(sendArgs.ERC721TransferTx.From), sendArgs.ERC721TransferTx.Recipient, sendArgs.ERC721TransferTx.TokenID.ToInt())
if err != nil {
return hash, err
}
return types.Hash(tx.Hash()), nil
}
func (s *ERC721TransferBridge) CalculateAmountOut(from, to *params.Network, amountIn *big.Int, symbol string) (*big.Int, error) {
return amountIn, nil
}
func (s *ERC721TransferBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
return &token.Address
}

View File

@ -125,7 +125,7 @@ func (h *HopBridge) Can(from, to *params.Network, token *token.Token, balance *b
return true, nil
}
func (h *HopBridge) EstimateGas(from, to *params.Network, token *token.Token, amountIn *big.Int) (uint64, error) {
func (h *HopBridge) EstimateGas(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
// TODO: find why this doesn't work
// ethClient, err := s.contractMaker.RPCClient.EthClient(from.ChainID)
// if err != nil {

View File

@ -1,53 +0,0 @@
package bridge
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/services/wallet/token"
"github.com/status-im/status-go/transactions"
)
type SimpleBridge struct {
transactor *transactions.Transactor
}
func NewSimpleBridge(transactor *transactions.Transactor) *SimpleBridge {
return &SimpleBridge{transactor: transactor}
}
func (s *SimpleBridge) Name() string {
return "Simple"
}
func (s *SimpleBridge) Can(from, to *params.Network, token *token.Token, balance *big.Int) (bool, error) {
return from.ChainID == to.ChainID, nil
}
func (s *SimpleBridge) 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 *SimpleBridge) EstimateGas(from, to *params.Network, token *token.Token, amountIn *big.Int) (uint64, error) {
// TODO: replace by estimate function
if token.IsNative() {
return 22000, nil // default gas limit for eth transaction
}
return 200000, nil //default gas limit for erc20 transaction
}
func (s *SimpleBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error) {
return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.SimpleTx, verifiedAccount)
}
func (s *SimpleBridge) CalculateAmountOut(from, to *params.Network, amountIn *big.Int, symbol string) (*big.Int, error) {
return amountIn, nil
}
func (s *SimpleBridge) GetContractAddress(network *params.Network, token *token.Token) *common.Address {
return nil
}

View File

@ -0,0 +1,53 @@
package bridge
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/status-im/status-go/account"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/services/wallet/token"
"github.com/status-im/status-go/transactions"
)
type TransferBridge struct {
transactor *transactions.Transactor
}
func NewTransferBridge(transactor *transactions.Transactor) *TransferBridge {
return &TransferBridge{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(from, to *params.Network, account common.Address, token *token.Token, amountIn *big.Int) (uint64, error) {
// TODO: replace by estimate function
if token.IsNative() {
return 22000, nil // default gas limit for eth transaction
}
return 200000, nil //default gas limit for erc20 transaction
}
func (s *TransferBridge) Send(sendArgs *TransactionBridge, verifiedAccount *account.SelectedExtKey) (types.Hash, error) {
return s.transactor.SendTransactionWithChainID(sendArgs.ChainID, *sendArgs.TransferTx, verifiedAccount)
}
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
}

View File

@ -134,3 +134,32 @@ func (o *OwnershipDB) GetOwnedCollectibles(chainIDs []w_common.ChainID, ownerAdd
return rowsToCollectibles(rows)
}
func (o *OwnershipDB) GetOwnedCollectible(chainID w_common.ChainID, ownerAddresses common.Address, contractAddress common.Address, tokenID *big.Int) (*thirdparty.CollectibleUniqueID, error) {
query := fmt.Sprintf(`SELECT %s
FROM collectibles_ownership_cache
WHERE chain_id = ? AND owner_address = ? AND contract_address = ? AND token_id = ?`, selectOwnershipColumns)
stmt, err := o.db.Prepare(query)
if err != nil {
return nil, err
}
defer stmt.Close()
rows, err := stmt.Query(chainID, ownerAddresses, contractAddress, (*bigint.SQLBigIntBytes)(tokenID))
if err != nil {
return nil, err
}
defer rows.Close()
ids, err := rowsToCollectibles(rows)
if err != nil {
return nil, err
}
if len(ids) == 0 {
return nil, nil
}
return &ids[0], nil
}

View File

@ -5,6 +5,7 @@ import (
"database/sql"
"encoding/json"
"errors"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
@ -265,3 +266,7 @@ func (s *Service) GetOwnedCollectibles(chainIDs []walletCommon.ChainID, owners [
return ids, hasMore, nil
}
func (s *Service) GetOwnedCollectible(chainID walletCommon.ChainID, owner common.Address, contractAddress common.Address, tokenID *big.Int) (*thirdparty.CollectibleUniqueID, error) {
return s.ownershipDB.GetOwnedCollectible(chainID, owner, contractAddress, tokenID)
}

View File

@ -23,10 +23,15 @@ import (
"github.com/status-im/status-go/services/wallet/async"
"github.com/status-im/status-go/services/wallet/bigint"
"github.com/status-im/status-go/services/wallet/bridge"
walletCommon "github.com/status-im/status-go/services/wallet/common"
"github.com/status-im/status-go/services/wallet/token"
"github.com/status-im/status-go/transactions"
)
const EstimateUsername = "RandomUsername"
const EstimatePubKey = "0x04bb2024ce5d72e45d4a4f8589ae657ef9745855006996115a23a1af88d536cf02c0524a585fce7bfa79d6a9669af735eda6205d6c7e5b3cdc2b8ff7b2fa1f0b56"
const ERC721TransferString = "ERC721Transfer"
type SendType int
const (
@ -36,20 +41,79 @@ const (
ENSSetPubKey
StickersBuy
Bridge
ERC721Transfer
)
const EstimateUsername = "RandomUsername"
const EstimatePubKey = "0x04bb2024ce5d72e45d4a4f8589ae657ef9745855006996115a23a1af88d536cf02c0524a585fce7bfa79d6a9669af735eda6205d6c7e5b3cdc2b8ff7b2fa1f0b56"
func (s SendType) FetchPrices(service *Service, tokenID string) (map[string]float64, error) {
symbols := []string{tokenID, "ETH"}
if s == ERC721Transfer {
symbols = []string{"ETH"}
}
pricesMap, err := service.marketManager.FetchPrices(symbols, []string{"USD"})
if err != nil {
return nil, err
}
prices := make(map[string]float64, 0)
for symbol, pricePerCurrency := range pricesMap {
prices[symbol] = pricePerCurrency["USD"]
}
if s == ERC721Transfer {
prices[tokenID] = 0
}
return prices, nil
}
func (s SendType) FindToken(service *Service, account common.Address, network *params.Network, tokenID string) *token.Token {
if s != ERC721Transfer {
return service.tokenManager.FindToken(network, tokenID)
}
parts := strings.Split(tokenID, ":")
contractAddress := common.HexToAddress(parts[0])
collectibleTokenID, success := new(big.Int).SetString(parts[1], 10)
if !success {
return nil
}
uniqueID, err := service.collectibles.GetOwnedCollectible(walletCommon.ChainID(network.ChainID), account, contractAddress, collectibleTokenID)
if err != nil || uniqueID == nil {
return nil
}
return &token.Token{
Address: contractAddress,
Symbol: collectibleTokenID.String(),
Decimals: 0,
ChainID: network.ChainID,
}
}
func (s SendType) isTransfer() bool {
return s == Transfer
return s == Transfer || s == ERC721Transfer
}
func (s SendType) isAvailableBetween(from, to *params.Network) bool {
if s != Bridge {
if s == ERC721Transfer {
return from.ChainID == to.ChainID
}
if s == Bridge {
return from.ChainID != to.ChainID
}
return true
}
return from.ChainID != to.ChainID
func (s SendType) canUseBridge(b bridge.Bridge) bool {
if s == ERC721Transfer && b.Name() != ERC721TransferString {
return false
}
if s != ERC721Transfer && b.Name() == ERC721TransferString {
return false
}
return true
}
func (s SendType) isAvailableFor(network *params.Network) bool {
@ -64,10 +128,9 @@ func (s SendType) isAvailableFor(network *params.Network) bool {
return false
}
func (s SendType) EstimateGas(service *Service, network *params.Network) uint64 {
from := types.Address(common.HexToAddress("0x5ffa75ce51c3a7ebe23bde37b5e3a0143dfbcee0"))
func (s SendType) EstimateGas(service *Service, network *params.Network, from common.Address, tokenID string) uint64 {
tx := transactions.SendTxArgs{
From: from,
From: (types.Address)(from),
Value: (*hexutil.Big)(zero),
}
if s == ENSRegister {
@ -96,7 +159,7 @@ func (s SendType) EstimateGas(service *Service, network *params.Network) uint64
if s == StickersBuy {
packID := &bigint.BigInt{Int: big.NewInt(2)}
estimate, err := service.stickers.API().BuyEstimate(context.Background(), network.ChainID, from, packID)
estimate, err := service.stickers.API().BuyEstimate(context.Background(), network.ChainID, (types.Address)(from), packID)
if err != nil {
return 400000
}
@ -343,10 +406,12 @@ func newSuggestedRoutes(
func NewRouter(s *Service) *Router {
bridges := make(map[string]bridge.Bridge)
simple := bridge.NewSimpleBridge(s.transactor)
transfer := bridge.NewTransferBridge(s.transactor)
erc721Transfer := bridge.NewERC721TransferBridge(s.rpcClient, s.transactor)
cbridge := bridge.NewCbridge(s.rpcClient, s.transactor, s.tokenManager)
hop := bridge.NewHopBridge(s.rpcClient, s.transactor, s.tokenManager)
bridges[simple.Name()] = simple
bridges[transfer.Name()] = transfer
bridges[erc721Transfer.Name()] = erc721Transfer
bridges[hop.Name()] = hop
bridges[cbridge.Name()] = cbridge
@ -369,7 +434,11 @@ type Router struct {
rpcClient *rpc.Client
}
func (r *Router) requireApproval(ctx context.Context, bridge bridge.Bridge, account common.Address, network *params.Network, token *token.Token, amountIn *big.Int) (bool, *big.Int, uint64, *common.Address, error) {
func (r *Router) requireApproval(ctx context.Context, sendType SendType, bridge bridge.Bridge, account common.Address, network *params.Network, token *token.Token, amountIn *big.Int) (bool, *big.Int, uint64, *common.Address, error) {
if sendType == ERC721Transfer {
return false, nil, 0, nil, nil
}
if token.IsNative() {
return false, nil, 0, nil, nil
}
@ -443,7 +512,7 @@ func (r *Router) suggestedRoutes(
sendType SendType,
account common.Address,
amountIn *big.Int,
tokenSymbol string,
tokenID string,
disabledFromChainIDs,
disabledToChaindIDs,
preferedChainIDs []uint64,
@ -460,14 +529,10 @@ func (r *Router) suggestedRoutes(
return nil, err
}
pricesMap, err := r.s.marketManager.FetchPrices([]string{"ETH", tokenSymbol}, []string{"USD"})
prices, err := sendType.FetchPrices(r.s, tokenID)
if err != nil {
return nil, err
}
prices := make(map[string]float64, 0)
for symbol, pricePerCurrency := range pricesMap {
prices[symbol] = pricePerCurrency["USD"]
}
var (
group = async.NewAtomicGroup(ctx)
@ -486,7 +551,8 @@ func (r *Router) suggestedRoutes(
if !sendType.isAvailableFor(network) {
continue
}
token := r.s.tokenManager.FindToken(network, tokenSymbol)
token := sendType.FindToken(r.s, account, network, tokenID)
if token == nil {
continue
}
@ -500,10 +566,14 @@ func (r *Router) suggestedRoutes(
return err
}
balance, err := r.getBalance(ctx, network, token, account)
// Default value is 1 as in case of erc721 as we built the token we are sure the account owns it
balance := big.NewInt(1)
if sendType != ERC721Transfer {
balance, err = r.getBalance(ctx, network, token, account)
if err != nil {
return err
}
}
maxAmountIn := (*hexutil.Big)(balance)
if amount, ok := fromLockedAmount[network.ChainID]; ok {
@ -522,6 +592,10 @@ func (r *Router) suggestedRoutes(
estimatedTime := r.s.feesManager.transactionEstimatedTime(ctx, network.ChainID, maxFees)
for _, bridge := range r.bridges {
if !sendType.canUseBridge(bridge) {
continue
}
for _, dest := range networks {
if dest.IsTest != areTestNetworksEnabled {
continue
@ -547,12 +621,10 @@ func (r *Router) suggestedRoutes(
if err != nil || !can {
continue
}
bonderFees, tokenFees, err := bridge.CalculateFees(network, dest, token, amountIn, prices["ETH"], prices[tokenSymbol], gasFees.GasPrice)
bonderFees, tokenFees, err := bridge.CalculateFees(network, dest, token, amountIn, prices["ETH"], prices[tokenID], gasFees.GasPrice)
if err != nil {
continue
}
if maxAmountIn.ToInt().Cmp(amountIn) >= 0 {
if bonderFees.Cmp(amountIn) >= 0 {
continue
@ -562,28 +634,24 @@ func (r *Router) suggestedRoutes(
continue
}
}
gasLimit := uint64(0)
if sendType.isTransfer() {
gasLimit, err = bridge.EstimateGas(network, dest, token, amountIn)
gasLimit, err = bridge.EstimateGas(network, dest, account, token, amountIn)
if err != nil {
continue
}
} else {
gasLimit = sendType.EstimateGas(r.s, network)
gasLimit = sendType.EstimateGas(r.s, network, account, tokenID)
}
requiredNativeBalance := new(big.Int).Mul(gweiToWei(maxFees), big.NewInt(int64(gasLimit)))
// Removed the required fees from maxAMount in case of native token tx
if token.IsNative() {
maxAmountIn = (*hexutil.Big)(new(big.Int).Sub(maxAmountIn.ToInt(), requiredNativeBalance))
}
if nativeBalance.Cmp(requiredNativeBalance) <= 0 {
continue
}
approvalRequired, approvalAmountRequired, approvalGasLimit, approvalContractAddress, err := r.requireApproval(ctx, bridge, account, network, token, amountIn)
approvalRequired, approvalAmountRequired, approvalGasLimit, approvalContractAddress, err := r.requireApproval(ctx, sendType, bridge, account, network, token, amountIn)
if err != nil {
continue
}
@ -606,12 +674,11 @@ func (r *Router) suggestedRoutes(
big.NewFloat(math.Pow(10, float64(token.Decimals))),
)
tokenCost := new(big.Float)
tokenCost.Mul(tokenFeesAsFloat, big.NewFloat(prices[tokenSymbol]))
tokenCost.Mul(tokenFeesAsFloat, big.NewFloat(prices[tokenID]))
cost := new(big.Float)
cost.Add(tokenCost, gasCost)
cost.Add(cost, approvalGasCost)
mu.Lock()
candidates = append(candidates, &Path{
BridgeName: bridge.Name(),
@ -641,14 +708,15 @@ func (r *Router) suggestedRoutes(
group.Wait()
suggestedRoutes := newSuggestedRoutes(amountIn, candidates, fromLockedAmount)
suggestedRoutes.TokenPrice = prices[tokenSymbol]
suggestedRoutes.TokenPrice = prices[tokenID]
suggestedRoutes.NativeChainTokenPrice = prices["ETH"]
for _, path := range suggestedRoutes.Best {
amountOut, err := r.bridges[path.BridgeName].CalculateAmountOut(path.From, path.To, (*big.Int)(path.AmountIn), tokenSymbol)
amountOut, err := r.bridges[path.BridgeName].CalculateAmountOut(path.From, path.To, (*big.Int)(path.AmountIn), tokenID)
if err != nil {
continue
}
path.AmountOut = (*hexutil.Big)(amountOut)
}
return suggestedRoutes, nil
}