Skip to content

Commit aa34153

Browse files
committed
feat: add ignore address type for token transfer monitoring
- Add Ignore type to AddressClassification enum - Add IgnoreAddresses configuration option - Update monitoring service to skip metrics for ignore addresses individually - Only skip the specific address metrics, not the entire transaction - Add detailed logging for ignored addresses
1 parent 39d9630 commit aa34153

4 files changed

Lines changed: 126 additions & 41 deletions

File tree

src/AElfScanServer.Worker.Core/Dtos/TransferEventDto.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public enum AddressClassification
3131
Normal,
3232
Blacklist,
3333
ToOnlyMonitored,
34-
LargeAmountOnly
34+
LargeAmountOnly,
35+
Ignore
3536
}
3637

3738
/// <summary>

src/AElfScanServer.Worker.Core/Options/TokenTransferMonitoringOptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ public class TokenTransferMonitoringOptions
2929
/// </summary>
3030
public List<string> LargeAmountOnlyAddresses { get; set; } = new();
3131

32+
/// <summary>
33+
/// Addresses to ignore completely - no metrics will be recorded for these addresses
34+
/// </summary>
35+
public List<string> IgnoreAddresses { get; set; } = new();
36+
3237
/// <summary>
3338
/// Minimum USD value threshold for histogram recording, default is 0
3439
/// </summary>

src/AElfScanServer.Worker.Core/Service/TokenTransferMonitoringService.cs

Lines changed: 73 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public class TokenTransferMonitoringService : ITokenTransferMonitoringService, I
3838
private readonly HashSet<string> _blacklistAddresses;
3939
private readonly HashSet<string> _toOnlyMonitoredAddresses;
4040
private readonly HashSet<string> _largeAmountOnlyAddresses;
41+
private readonly HashSet<string> _ignoreAddresses;
4142
private readonly IOptionsMonitor<TokenTransferMonitoringOptions> _optionsMonitor;
4243

4344
public TokenTransferMonitoringService(
@@ -62,6 +63,7 @@ public TokenTransferMonitoringService(
6263
_blacklistAddresses = new HashSet<string>(_options.BlacklistAddresses, StringComparer.OrdinalIgnoreCase);
6364
_toOnlyMonitoredAddresses = new HashSet<string>(_options.ToOnlyMonitoredAddresses, StringComparer.OrdinalIgnoreCase);
6465
_largeAmountOnlyAddresses = new HashSet<string>(_options.LargeAmountOnlyAddresses, StringComparer.OrdinalIgnoreCase);
66+
_ignoreAddresses = new HashSet<string>(_options.IgnoreAddresses, StringComparer.OrdinalIgnoreCase);
6567
// Initialize histogram with configured buckets
6668
_transferUSDEventsHistogram = instrumentationProvider.Meter.CreateHistogram<double>(
6769
"aelf_transfer_usd_value",
@@ -310,58 +312,88 @@ public void SendTransferMetrics(TransferEventDto transfer)
310312
// Determine if this is a high-value transfer once
311313
var isHighValue = transfer.UsdValue >= currentOptions.MinUsdValueThreshold;
312314

313-
// Record outbound transaction (from perspective)
314-
var outboundTags = new KeyValuePair<string, object?>[]
315+
// Record outbound transaction (from perspective) - skip if fromAddress is ignore type
316+
if (transfer.FromAddressType != AddressClassification.Ignore && !transfer.FromAddress.IsNullOrEmpty())
315317
{
316-
new("chain_id", transfer.ChainId),
317-
new("symbol", transfer.Symbol),
318-
new("transfer_type", transfer.Type.ToString()),
319-
new("address", transfer.FromAddress),
320-
new("direction", "outbound"),
321-
new("address_type", transfer.FromAddressType.ToString()),
322-
};
323-
324-
// Record inbound transaction (to perspective)
325-
var inboundTags = new KeyValuePair<string, object?>[]
326-
{
327-
new("chain_id", transfer.ChainId),
328-
new("symbol", transfer.Symbol),
329-
new("transfer_type", transfer.Type.ToString()),
330-
new("address", transfer.ToAddress),
331-
new("direction", "inbound"),
332-
new("address_type", transfer.ToAddressType.ToString()),
333-
};
334-
335-
// Always record counter (for all transfers)
318+
var outboundTags = new KeyValuePair<string, object?>[]
319+
{
320+
new("chain_id", transfer.ChainId),
321+
new("symbol", transfer.Symbol),
322+
new("transfer_type", transfer.Type.ToString()),
323+
new("address", transfer.FromAddress),
324+
new("direction", "outbound"),
325+
new("address_type", transfer.FromAddressType.ToString()),
326+
};
327+
328+
// Always record counter
329+
_transferCountsCounter.Add(1, outboundTags);
336330

337-
if (!transfer.FromAddress.IsNullOrEmpty())
331+
// Only record histogram for high-value transfers
332+
if (isHighValue)
333+
{
334+
_transferUSDEventsHistogram.Record((double)transfer.UsdValue, outboundTags);
335+
}
336+
}
337+
else if (transfer.FromAddressType == AddressClassification.Ignore)
338338
{
339-
_transferCountsCounter.Add(1, outboundTags);
339+
_logger.LogInformation("Skipping outbound metrics for transaction {TransactionId} from ignore address {FromAddress}",
340+
transfer.TransactionId, transfer.FromAddress);
340341
}
341342

342-
if (!transfer.ToAddress.IsNullOrEmpty() || !IsSystemContractTransfer(transfer.ToAddress))
343+
// Record inbound transaction (to perspective) - skip if toAddress is ignore type
344+
if (transfer.ToAddressType != AddressClassification.Ignore &&
345+
!transfer.ToAddress.IsNullOrEmpty() &&
346+
!IsSystemContractTransfer(transfer.ToAddress))
343347
{
348+
var inboundTags = new KeyValuePair<string, object?>[]
349+
{
350+
new("chain_id", transfer.ChainId),
351+
new("symbol", transfer.Symbol),
352+
new("transfer_type", transfer.Type.ToString()),
353+
new("address", transfer.ToAddress),
354+
new("direction", "inbound"),
355+
new("address_type", transfer.ToAddressType.ToString()),
356+
};
357+
358+
// Always record counter
344359
_transferCountsCounter.Add(1, inboundTags);
360+
361+
// Only record histogram for high-value transfers
362+
if (isHighValue)
363+
{
364+
_transferUSDEventsHistogram.Record((double)transfer.UsdValue, inboundTags);
365+
}
345366
}
346-
// Only record histogram for high-value transfers
347-
if (isHighValue)
367+
else if (transfer.ToAddressType == AddressClassification.Ignore)
348368
{
349-
if (!transfer.FromAddress.IsNullOrEmpty())
369+
_logger.LogInformation("Skipping inbound metrics for transaction {TransactionId} to ignore address {ToAddress}",
370+
transfer.TransactionId, transfer.ToAddress);
371+
}
372+
373+
// Log transaction processing summary
374+
var recordedMetrics = new List<string>();
375+
if (transfer.FromAddressType != AddressClassification.Ignore && !transfer.FromAddress.IsNullOrEmpty())
376+
recordedMetrics.Add("outbound");
377+
if (transfer.ToAddressType != AddressClassification.Ignore && !transfer.ToAddress.IsNullOrEmpty() && !IsSystemContractTransfer(transfer.ToAddress))
378+
recordedMetrics.Add("inbound");
379+
380+
if (recordedMetrics.Any())
381+
{
382+
if (isHighValue)
350383
{
351-
_transferUSDEventsHistogram.Record((double)transfer.UsdValue, outboundTags);
384+
_logger.LogInformation("Sent transfer metrics ({Directions}) for transaction {TransactionId}, amount {Amount} {Symbol}, USD value {UsdValue}",
385+
string.Join(", ", recordedMetrics), transfer.TransactionId, transfer.Amount, transfer.Symbol, transfer.UsdValue);
352386
}
353-
354-
if (!transfer.ToAddress.IsNullOrEmpty() || !IsSystemContractTransfer(transfer.ToAddress))
387+
else
355388
{
356-
_transferUSDEventsHistogram.Record((double)transfer.UsdValue, inboundTags);
389+
_logger.LogInformation("Sent counter metrics only ({Directions}) for transaction {TransactionId}, amount {Amount} {Symbol}, USD value {UsdValue} below histogram threshold",
390+
string.Join(", ", recordedMetrics), transfer.TransactionId, transfer.Amount, transfer.Symbol, transfer.UsdValue);
357391
}
358-
_logger.LogInformation("Sent transfer metrics for transaction {TransactionId}, amount {Amount} {Symbol}, USD value {UsdValue}",
359-
transfer.TransactionId, transfer.Amount, transfer.Symbol, transfer.UsdValue);
360392
}
361393
else
362394
{
363-
_logger.LogInformation("Sent counter metrics only for transaction {TransactionId}, amount {Amount} {Symbol}, USD value {UsdValue} below histogram threshold",
364-
transfer.TransactionId, transfer.Amount, transfer.Symbol, transfer.UsdValue);
395+
_logger.LogInformation("No metrics recorded for transaction {TransactionId} - both addresses are ignore type or system contracts",
396+
transfer.TransactionId);
365397
}
366398
}
367399
catch (Exception ex)
@@ -394,7 +426,11 @@ private AddressClassification ClassifyAddress(string address)
394426
if (string.IsNullOrEmpty(address))
395427
return AddressClassification.Normal;
396428

397-
// Check blacklist first (highest priority)
429+
// Check ignore addresses first (highest priority)
430+
if (_ignoreAddresses.Contains(address))
431+
return AddressClassification.Ignore;
432+
433+
// Check blacklist (second highest priority)
398434
if (_blacklistAddresses.Contains(address))
399435
return AddressClassification.Blacklist;
400436

src/AElfScanServer.Worker/appsettings.json

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,55 @@
264264
},
265265
"TokenTransferMonitoring": {
266266
"EnableMonitoring": true,
267-
"EnableSystemContractFilter":false,
267+
"EnableSystemContractFilter":true,
268268
"BlacklistAddresses": [
269-
"2Ue8S2qAb8dGMrRgcNtjWgBx48Bx3XmNT6UBBKwNLYm5ZpbA"],
269+
"2Ue8S2qAb8dGMrRgcNtjWgBx48Bx3XmNT6UBBKwNLYm5ZpbA",
270+
"kh8TeQiTzr3FWAmNN3fd97fjsNtPVeNr9cxtkdkFf2gyuxXDn",
271+
"B6dvH6p93zMD3rE3zESRVt3gRQg2e8rHw34h1ZJNXxoWNBYjB",
272+
"k9qVGtY5usEhViiacGvXGgNb8wpCEEwFU14w4rxoXAxgZwREF",
273+
"q6w7NcsfLeGSMnNTmXKMnaRUPKSk7yczS4YCd6ZJC4XNTDcb8",
274+
"hUkyUrCNoSuTuduYTbSKCCoHn17fvtX8NYVRNgnhFhpxAyoTt",
275+
"2vJMKR3DqeLffJcjCEquvaR1hTQ2MS7mfpcK3bD8QEiRorDVdG"
276+
],
277+
"ToOnlyMonitoredAddresses": [
278+
"2cbyVVSin9aHZzwdjHHGP3HLZxHgo7dKB5S7HdNGaXkwkpvHfT",
279+
"2vGq6qQi9qJSdn5yjhQ7tpez16qQnEKuRCZHoQiUkGBMC34MdT",
280+
"2PPYHTa582wijxchyrniTTWG1SG2QHhV8eLutP4MXRrnUc52uw",
281+
"2imJ6W4ada5wNq735WVEisDfkVgGWDbSxHSyhmwXBBsgKWmMSr",
282+
"2LB3MevN2QSW36ahkFJ6PxEPWFwunpCPQYAWCEXFaNzVwMDrdr",
283+
"nxREyjyKXqzA7aQaK4Nc7EVNL2BWaiFSrDturUQfWwJ4uwW6b",
284+
"eGw4LRJpXWZKcRRuxUi1uhqjJafEpzow4ZzQgnPmRJv7ReGrK",
285+
"2RWf7Aj7Cn2UpZcXVrXLL7iWfhdHz69otYY1YDJ4X158cVNWG2",
286+
"2VeAzekM7bEMisNMyJpRCAARgPcnuFoJVw9uXfWnGa8RX2tnuZ",
287+
"KPFwtmxK48mDjKYTWeYFDfkSmnPNPFrEXAxyJf84jX5ytaGg8",
288+
"29tJaX3k16ZibaXYz2yq9ZbeN4G7cLWJyAucGcSoCsLwhnkAoy",
289+
"2eZtVJvL26DqmKgzQzULK764ihMCoXKTqgK7NzbPBCRRmuBZgz",
290+
"bUxH4xMXHi2yisGd1GCjb81oWVavfXbEeXZ96vNdv4hpBhdeM",
291+
"2PxkDj9tzyNBnAvuGhLVgUPr8bPN4r1DALYVPhYcsjQficvrUV",
292+
"2cvQi5yLSvyni6xdUHXRynesz2nDQCDMBAyFG2QqA6iVSBDvtH",
293+
"5CazTqiizhhDgn9QmPFqHEmJ7EspCRqVoencfCe3r7Qkog3c3",
294+
"2NCCXHS48wyGyjxczJ19qUA4nmPz1HxfUAi359XWvTo4tzdNzM",
295+
"g6LeMdzLcUPccrK97TWYSxri1NxK6ZXJwQjv1VUNf1F8BzfF3",
296+
"2sVo6v1ysTefrFT1bStsoztnCGQHkZEjFK9mSUWjEP6nGnoma1",
297+
"AERrwTnr9LE8Tu682FP1jpUSeJhwAuB8cSgR86SgMGqmeS6ii",
298+
"zaVUYRhCkrurJfMs2EfTUnruJ9qeAbJ4jmsVM7wcaAPcDuKnt",
299+
"FiXvL7pdz9uFYajitRVQw64EVNcu6vXqss3phMkVLTcCCFQ7d"
300+
],
301+
"LargeAmountOnlyAddresses": [
302+
"2b7Gf7YqVmjhZXir7uehmZoRwsYo1KNFTo9JDZiiByxPBQS1d8",
303+
"2AJXAXSwyHbKTHQhKFiaYozakUUQDeh3xrHW9FGi3vYDMBjtiS",
304+
"25CkLPA8qwDRGQci2kFg77i6pZXVivvX4DHW78i1B7rPHdBkoK",
305+
"2PwfVguYDmYcpJVPmoH9doEpBgd8L28NCcUDiuq77CzvEWzuKZ",
306+
"2eJ4MnRWFo7YJXB92qj2AF3NWoB3umBggzNLhbGeahkwDYYLAD"
307+
],
308+
"IgnoreAddresses": [
309+
"ExampleIgnoreAddress1234567890ABCDEFGHIJKLMNOPQRST",
310+
"TestIgnoreAddress2345678901BCDEFGHIJKLMNOPQRSTUV"
311+
],
312+
"MinUsdValueThreshold": 0.1,
270313
"MonitoredTokens": ["ELF", "USDT", "BTC", "ETH"],
271314
"ScanConfig": {
272-
"ChainIds": ["AELF", "tDVW"],
315+
"ChainIds": ["AELF", "tDVV"],
273316
"IntervalSeconds": 30,
274317
"BatchSize": 1000
275318
}

0 commit comments

Comments
 (0)