public async Task ScanAsync( bool skipUsed = false, CancellationToken cancellationToken = default) { var currency = Currency; var scanParams = new[] { // new {Chain = HdKeyStorage.NonHdKeysChain, LookAhead = 0}, new { Chain = Bip44.Internal, LookAhead = InternalLookAhead }, new { Chain = Bip44.External, LookAhead = ExternalLookAhead }, }; var txs = new List <EthereumTransaction>(); var api = new EtherScanApi(currency); var lastBlockNumberResult = await api .GetBlockNumber() .ConfigureAwait(false); if (lastBlockNumberResult.HasError) { Log.Error( "Error while getting last block number with code {@code} and description {@description}", lastBlockNumberResult.Error.Code, lastBlockNumberResult.Error.Description); return; } var lastBlockNumber = lastBlockNumberResult.Value; if (lastBlockNumber <= 0) { Log.Error("Error in block number {@lastBlockNumber}", lastBlockNumber); return; } foreach (var param in scanParams) { var freeKeysCount = 0; var index = 0u; while (true) { cancellationToken.ThrowIfCancellationRequested(); var walletAddress = await Account .DivideAddressAsync( account : Bip44.DefaultAccount, chain : param.Chain, index : index, keyType : CurrencyConfig.StandardKey) .ConfigureAwait(false); if (walletAddress == null) { break; } Log.Debug( "Scan transactions for {@name} address {@chain}:{@index}:{@address}", currency.Name, param.Chain, index, walletAddress.Address); var events = await GetERC20EventsAsync(walletAddress.Address, cancellationToken); if (events == null || !events.Any()) { var ethereumAddress = await EthereumAccount .GetAddressAsync(walletAddress.Address, cancellationToken) .ConfigureAwait(false); if (ethereumAddress != null && ethereumAddress.HasActivity) { freeKeysCount = 0; index++; continue; } freeKeysCount++; if (freeKeysCount >= param.LookAhead) { Log.Debug("{@lookAhead} free keys found. Chain scan completed", param.LookAhead); break; } } else // address has activity { freeKeysCount = 0; foreach (var ev in events) { var tx = new EthereumTransaction(); if (ev.IsERC20ApprovalEvent()) { tx = ev.TransformApprovalEvent(currency, lastBlockNumber); } else if (ev.IsERC20TransferEvent()) { tx = ev.TransformTransferEvent(walletAddress.Address, currency, lastBlockNumber); } if (tx != null) { txs.Add(tx); } } } index++; } } if (txs.Any()) { await UpsertTransactionsAsync(txs) .ConfigureAwait(false); } await Account .UpdateBalanceAsync(cancellationToken : cancellationToken) .ConfigureAwait(false); }
public async Task ScanAsync( string address, CancellationToken cancellationToken = default) { var currency = Currency; Log.Debug("Scan transactions for {@currency} address {@address}", Currency.Name, address); var txs = new List <EthereumTransaction>(); var api = new EtherScanApi(currency); var lastBlockNumberResult = await api .GetBlockNumber() .ConfigureAwait(false); if (lastBlockNumberResult == null) { Log.Error("Connection error while get block number"); return; } if (lastBlockNumberResult.HasError) { Log.Error( "Error while getting last block number with code {@code} and description {@description}", lastBlockNumberResult.Error.Code, lastBlockNumberResult.Error.Description); return; } var lastBlockNumber = lastBlockNumberResult.Value; if (lastBlockNumber <= 0) { Log.Error( "Error in block number {@lastBlockNumber}", lastBlockNumber); return; } var events = await GetERC20EventsAsync(address, cancellationToken) .ConfigureAwait(false); if (events == null || !events.Any()) // address without activity { return; } foreach (var ev in events) { var tx = new EthereumTransaction(); if (ev.IsERC20ApprovalEvent()) { tx = ev.TransformApprovalEvent(currency, lastBlockNumber); } else if (ev.IsERC20TransferEvent()) { tx = ev.TransformTransferEvent(address, currency, lastBlockNumber); } if (tx != null) { txs.Add(tx); } } if (txs.Any()) { await UpsertTransactionsAsync(txs) .ConfigureAwait(false); } await Account .UpdateBalanceAsync(address : address, cancellationToken : cancellationToken) .ConfigureAwait(false); }