Support for binance chains
This commit is contained in:
parent
25e1c64ef5
commit
7ef2efaabd
|
@ -39,10 +39,16 @@ func (api *API) CheckRecentHistoryForChainIDs(ctx context.Context, chainIDs []ui
|
|||
|
||||
// GetTransfersByAddress returns transfers for a single address
|
||||
func (api *API) GetTransfersByAddress(ctx context.Context, address common.Address, toBlock, limit *hexutil.Big, fetchMore bool) ([]transfer.View, error) {
|
||||
log.Debug("[WalletAPI:: GetTransfersByAddress] get transfers for an address", "address")
|
||||
log.Debug("[WalletAPI:: GetTransfersByAddress] get transfers for an address", "address", address)
|
||||
return api.s.transferController.GetTransfersByAddress(ctx, api.s.rpcClient.UpstreamChainID, address, toBlock, limit, fetchMore)
|
||||
}
|
||||
|
||||
// LoadTransferByHash loads transfer to the database
|
||||
func (api *API) LoadTransferByHash(ctx context.Context, address common.Address, hash common.Hash) error {
|
||||
log.Debug("[WalletAPI:: LoadTransferByHash] get transfer by hash", "address", address, "hash", hash)
|
||||
return api.s.transferController.LoadTransferByHash(ctx, api.s.rpcClient, address, hash)
|
||||
}
|
||||
|
||||
func (api *API) GetTransfersByAddressAndChainID(ctx context.Context, chainID uint64, address common.Address, toBlock, limit *hexutil.Big, fetchMore bool) ([]transfer.View, error) {
|
||||
log.Debug("[WalletAPI:: GetTransfersByAddressAndChainID] get transfers for an address", "address", address)
|
||||
return api.s.transferController.GetTransfersByAddress(ctx, chainID, address, toBlock, limit, fetchMore)
|
||||
|
|
|
@ -14,7 +14,16 @@ import (
|
|||
"github.com/status-im/status-go/services/wallet/chain"
|
||||
)
|
||||
|
||||
var numberOfBlocksCheckedPerIteration = 40
|
||||
var (
|
||||
// This will work only for binance testnet as mainnet doesn't support
|
||||
// archival request.
|
||||
binanceChainMaxInitialRange = big.NewInt(500000)
|
||||
binanceChainErc20BatchSize = big.NewInt(5000)
|
||||
erc20BatchSize = big.NewInt(100000)
|
||||
binancChainID = uint64(56)
|
||||
binanceTestChainID = uint64(97)
|
||||
numberOfBlocksCheckedPerIteration = 40
|
||||
)
|
||||
|
||||
type ethHistoricalCommand struct {
|
||||
db *Database
|
||||
|
@ -87,12 +96,20 @@ func (c *erc20HistoricalCommand) Command() async.Command {
|
|||
}.Run
|
||||
}
|
||||
|
||||
func getErc20BatchSize(chainID uint64) *big.Int {
|
||||
if isBinanceChain(chainID) {
|
||||
return binanceChainErc20BatchSize
|
||||
}
|
||||
|
||||
return erc20BatchSize
|
||||
}
|
||||
|
||||
func (c *erc20HistoricalCommand) Run(ctx context.Context) (err error) {
|
||||
start := time.Now()
|
||||
if c.iterator == nil {
|
||||
c.iterator, err = SetupIterativeDownloader(
|
||||
c.db, c.chainClient, c.address,
|
||||
c.erc20, erc20BatchSize, c.to, c.from)
|
||||
c.erc20, getErc20BatchSize(c.chainClient.ChainID), c.to, c.from, !isBinanceChain(c.chainClient.ChainID))
|
||||
if err != nil {
|
||||
log.Error("failed to setup historical downloader for erc20")
|
||||
return err
|
||||
|
@ -585,8 +602,21 @@ func loadTransfers(ctx context.Context, accounts []common.Address, block *Block,
|
|||
}
|
||||
}
|
||||
|
||||
func findFirstRange(c context.Context, account common.Address, initialTo *big.Int, client *chain.Client) (*big.Int, error) {
|
||||
func isBinanceChain(chainID uint64) bool {
|
||||
return chainID == binancChainID || chainID == binanceTestChainID
|
||||
}
|
||||
|
||||
func getLowestFrom(chainID uint64, to *big.Int) *big.Int {
|
||||
from := big.NewInt(0)
|
||||
if isBinanceChain(chainID) && big.NewInt(0).Sub(to, from).Cmp(binanceChainMaxInitialRange) == 1 {
|
||||
from = big.NewInt(0).Sub(to, binanceChainMaxInitialRange)
|
||||
}
|
||||
|
||||
return from
|
||||
}
|
||||
|
||||
func findFirstRange(c context.Context, account common.Address, initialTo *big.Int, client *chain.Client) (*big.Int, error) {
|
||||
from := getLowestFrom(client.ChainID, initialTo)
|
||||
to := initialTo
|
||||
goal := uint64(20)
|
||||
|
||||
|
@ -602,7 +632,7 @@ func findFirstRange(c context.Context, account common.Address, initialTo *big.In
|
|||
}
|
||||
|
||||
if firstNonce <= goal {
|
||||
return zero, nil
|
||||
return from, nil
|
||||
}
|
||||
|
||||
nonceDiff := firstNonce
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/event"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"github.com/status-im/status-go/multiaccounts/accounts"
|
||||
|
@ -169,6 +170,35 @@ func mapToList(m map[common.Address]struct{}) []common.Address {
|
|||
return rst
|
||||
}
|
||||
|
||||
func (c *Controller) LoadTransferByHash(ctx context.Context, rpcClient *rpc.Client, address common.Address, hash common.Hash) error {
|
||||
chainClient, err := chain.NewClient(rpcClient, rpcClient.UpstreamChainID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
signer := types.NewLondonSigner(chainClient.ToBigInt())
|
||||
|
||||
transfer, err := getTransferByHash(ctx, chainClient, signer, address, hash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
transfers := []Transfer{*transfer}
|
||||
|
||||
err = c.db.InsertBlock(rpcClient.UpstreamChainID, address, transfer.BlockNumber, transfer.BlockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
blocks := []*big.Int{transfer.BlockNumber}
|
||||
err = c.db.SaveTranfers(rpcClient.UpstreamChainID, address, transfers, blocks)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Controller) GetTransfersByAddress(ctx context.Context, chainID uint64, address common.Address, toBlock, limit *hexutil.Big, fetchMore bool) ([]View, error) {
|
||||
log.Debug("[WalletAPI:: GetTransfersByAddress] get transfers for an address", "address", address)
|
||||
var toBlockBN *big.Int
|
||||
|
|
|
@ -351,6 +351,31 @@ func deleteHeaders(creator statementCreator, headers []*DBHeader) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (db *Database) InsertBlock(chainID uint64, account common.Address, blockNumber *big.Int, blockHash common.Hash) error {
|
||||
var (
|
||||
tx *sql.Tx
|
||||
)
|
||||
tx, err := db.client.Begin()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if err == nil {
|
||||
err = tx.Commit()
|
||||
return
|
||||
}
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
insert, err := tx.Prepare("INSERT OR IGNORE INTO blocks(network_id, address, blk_number, blk_hash, loaded) VALUES (?, ?, ?, ?, ?)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = insert.Exec(chainID, account, (*bigint.SQLBigInt)(blockNumber), blockHash, true)
|
||||
return err
|
||||
}
|
||||
|
||||
func insertBlocksWithTransactions(chainID uint64, creator statementCreator, account common.Address, headers []*DBHeader) error {
|
||||
insert, err := creator.Prepare("INSERT OR IGNORE INTO blocks(network_id, address, blk_number, blk_hash, loaded) VALUES (?, ?, ?, ?, ?)")
|
||||
if err != nil {
|
||||
|
|
|
@ -90,6 +90,44 @@ func (d *ETHDownloader) GetTransfersByNumber(ctx context.Context, number *big.In
|
|||
return rst, err
|
||||
}
|
||||
|
||||
func getTransferByHash(ctx context.Context, client *chain.Client, signer types.Signer, address common.Address, hash common.Hash) (*Transfer, error) {
|
||||
transaction, _, err := client.TransactionByHash(ctx, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
receipt, err := client.TransactionReceipt(ctx, hash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transactionLog := getTokenLog(receipt.Logs)
|
||||
|
||||
transferType := ethTransfer
|
||||
if transactionLog != nil {
|
||||
transferType = erc20Transfer
|
||||
}
|
||||
|
||||
from, err := types.Sender(signer, transaction)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
transfer := &Transfer{Type: transferType,
|
||||
ID: hash,
|
||||
Address: address,
|
||||
BlockNumber: receipt.BlockNumber,
|
||||
BlockHash: receipt.BlockHash,
|
||||
Timestamp: uint64(time.Now().Unix()),
|
||||
Transaction: transaction,
|
||||
From: from,
|
||||
Receipt: receipt,
|
||||
Log: transactionLog}
|
||||
|
||||
return transfer, nil
|
||||
}
|
||||
|
||||
func (d *ETHDownloader) getTransfersInBlock(ctx context.Context, blk *types.Block, accounts []common.Address) (rst []Transfer, err error) {
|
||||
for _, address := range accounts {
|
||||
preloadedTransfers, err := d.db.GetPreloadedTransactions(d.chainClient.ChainID, address, blk.Hash())
|
||||
|
|
|
@ -12,14 +12,14 @@ import (
|
|||
// SetupIterativeDownloader configures IterativeDownloader with last known synced block.
|
||||
func SetupIterativeDownloader(
|
||||
db *Database, client HeaderReader, address common.Address,
|
||||
downloader BatchDownloader, size *big.Int, to *big.Int, from *big.Int) (*IterativeDownloader, error) {
|
||||
downloader BatchDownloader, size *big.Int, to *big.Int, from *big.Int, isBatchSizeAdjustable bool) (*IterativeDownloader, error) {
|
||||
|
||||
if to == nil || from == nil {
|
||||
return nil, errors.New("to or from cannot be nil")
|
||||
}
|
||||
|
||||
adjustedSize := big.NewInt(0).Div(big.NewInt(0).Sub(to, from), big.NewInt(10))
|
||||
if adjustedSize.Cmp(size) == 1 {
|
||||
if isBatchSizeAdjustable && adjustedSize.Cmp(size) == 1 {
|
||||
size = adjustedSize
|
||||
}
|
||||
log.Info("iterative downloader", "address", address, "from", from, "to", to, "size", size)
|
||||
|
|
|
@ -13,10 +13,7 @@ import (
|
|||
"github.com/status-im/status-go/services/wallet/chain"
|
||||
)
|
||||
|
||||
var (
|
||||
erc20BatchSize = big.NewInt(100000)
|
||||
errAlreadyRunning = errors.New("already running")
|
||||
)
|
||||
var errAlreadyRunning = errors.New("already running")
|
||||
|
||||
// HeaderReader interface for reading headers using block number or hash.
|
||||
type HeaderReader interface {
|
||||
|
|
Loading…
Reference in New Issue