feat: route-send-collectible
This commit is contained in:
parent
195214765b
commit
01babe3632
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue