fix(android): 分批查询交易记录以绕过 RPC 10000 区块限制

RPC 节点限制每次查询最多 10000 个区块,修改为分批查询:
- 每批查询 10000 个区块
- 总共扫描最近 100000 个区块(约 10 批)
- 添加批次日志输出

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-26 08:04:58 -08:00
parent 6e03c1c798
commit 78e105d46d
1 changed files with 74 additions and 61 deletions

View File

@ -3179,16 +3179,18 @@ data class ParticipantStatusInfo(
val currentBlockHex = getCurrentBlockNumber(client, rpcUrl)
val currentBlock = currentBlockHex?.removePrefix("0x")?.toLongOrNull(16) ?: 0L
// 查询最近 200000 个区块的历史Kava 出块快,确保覆盖足够长的时间)
val scanBlockCount = 200000L
val fromBlock = if (currentBlock > scanBlockCount) {
"0x${(currentBlock - scanBlockCount).toString(16)}"
// RPC 节点限制:每次最多查询 10000 个区块
// 分批查询最近 100000 个区块
val maxBlocksPerRequest = 10000L
val totalBlocksToScan = 100000L
val startBlock = if (currentBlock > totalBlocksToScan) {
currentBlock - totalBlocksToScan
} else {
"0x0"
0L
}
android.util.Log.d("TssRepository", "[SYNC-ERC20] Current block: $currentBlock ($currentBlockHex)")
android.util.Log.d("TssRepository", "[SYNC-ERC20] Scanning from block $fromBlock to latest (${scanBlockCount} blocks)")
android.util.Log.d("TssRepository", "[SYNC-ERC20] Current block: $currentBlock")
android.util.Log.d("TssRepository", "[SYNC-ERC20] Scanning blocks $startBlock to $currentBlock (total: ${currentBlock - startBlock})")
// Transfer event signature: keccak256("Transfer(address,address,uint256)")
val transferTopic = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
@ -3198,65 +3200,76 @@ data class ParticipantStatusInfo(
var totalSynced = 0
// 查询发送的交易 (from = address)
val sentRequest = """
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"address": "$contractAddress",
"topics": ["$transferTopic", "$paddedAddress", null],
"fromBlock": "$fromBlock",
"toBlock": "latest"
}],
"id": 1
// 分批查询,每批 10000 个区块
var fromBlock = startBlock
var batchCount = 0
while (fromBlock < currentBlock) {
val toBlock = minOf(fromBlock + maxBlocksPerRequest - 1, currentBlock)
batchCount++
val fromBlockHex = "0x${fromBlock.toString(16)}"
val toBlockHex = "0x${toBlock.toString(16)}"
android.util.Log.d("TssRepository", "[SYNC-ERC20] Batch #$batchCount: blocks $fromBlock-$toBlock")
// 查询发送的交易 (from = address)
val sentRequest = """
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"address": "$contractAddress",
"topics": ["$transferTopic", "$paddedAddress", null],
"fromBlock": "$fromBlockHex",
"toBlock": "$toBlockHex"
}],
"id": 1
}
""".trimIndent()
val sentResponse = client.newCall(
okhttp3.Request.Builder()
.url(rpcUrl)
.post(sentRequest.toRequestBody(jsonMediaType))
.build()
).execute()
val sentBody = sentResponse.body?.string()
if (sentBody != null) {
totalSynced += parseAndSaveTransferLogs(sentBody, shareId, address, tokenType, "SENT")
}
""".trimIndent()
val sentResponse = client.newCall(
okhttp3.Request.Builder()
.url(rpcUrl)
.post(sentRequest.toRequestBody(jsonMediaType))
.build()
).execute()
// 查询接收的交易 (to = address)
val receivedRequest = """
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"address": "$contractAddress",
"topics": ["$transferTopic", null, "$paddedAddress"],
"fromBlock": "$fromBlockHex",
"toBlock": "$toBlockHex"
}],
"id": 2
}
""".trimIndent()
val sentBody = sentResponse.body?.string()
android.util.Log.d("TssRepository", "[SYNC-ERC20] SENT response code: ${sentResponse.code}")
if (sentBody != null) {
android.util.Log.d("TssRepository", "[SYNC-ERC20] SENT response preview: ${sentBody.take(500)}")
totalSynced += parseAndSaveTransferLogs(sentBody, shareId, address, tokenType, "SENT")
val receivedResponse = client.newCall(
okhttp3.Request.Builder()
.url(rpcUrl)
.post(receivedRequest.toRequestBody(jsonMediaType))
.build()
).execute()
val receivedBody = receivedResponse.body?.string()
if (receivedBody != null) {
totalSynced += parseAndSaveTransferLogs(receivedBody, shareId, address, tokenType, "RECEIVED")
}
fromBlock = toBlock + 1
}
// 查询接收的交易 (to = address)
val receivedRequest = """
{
"jsonrpc": "2.0",
"method": "eth_getLogs",
"params": [{
"address": "$contractAddress",
"topics": ["$transferTopic", null, "$paddedAddress"],
"fromBlock": "$fromBlock",
"toBlock": "latest"
}],
"id": 2
}
""".trimIndent()
val receivedResponse = client.newCall(
okhttp3.Request.Builder()
.url(rpcUrl)
.post(receivedRequest.toRequestBody(jsonMediaType))
.build()
).execute()
val receivedBody = receivedResponse.body?.string()
android.util.Log.d("TssRepository", "[SYNC-ERC20] RECEIVED response code: ${receivedResponse.code}")
if (receivedBody != null) {
android.util.Log.d("TssRepository", "[SYNC-ERC20] RECEIVED response preview: ${receivedBody.take(500)}")
totalSynced += parseAndSaveTransferLogs(receivedBody, shareId, address, tokenType, "RECEIVED")
}
android.util.Log.d("TssRepository", "[SYNC-ERC20] Synced $totalSynced ${tokenType.name} transactions")
android.util.Log.d("TssRepository", "[SYNC-ERC20] Completed $batchCount batches, synced $totalSynced ${tokenType.name} transactions")
Result.success(totalSynced)
} catch (e: Exception) {
android.util.Log.e("TssRepository", "[SYNC-ERC20] Error: ${e.message}", e)