From ee9823cff0a7fed9499f768271e820de682bccc7 Mon Sep 17 00:00:00 2001 From: xiaoch05 Date: Thu, 25 Jul 2024 19:39:38 +0800 Subject: [PATCH] multi request withdraw status --- apollo/src/lnv3/lnv3.service.ts | 110 +++++++++++++++++++-- apollo/src/lnv3/source/ponder.service.ts | 7 ++ apollo/src/lnv3/source/source.service.ts | 6 ++ apollo/src/lnv3/source/thegraph.service.ts | 14 +++ 4 files changed, 129 insertions(+), 8 deletions(-) diff --git a/apollo/src/lnv3/lnv3.service.ts b/apollo/src/lnv3/lnv3.service.ts index a1f008e..f0c8bfa 100644 --- a/apollo/src/lnv3/lnv3.service.ts +++ b/apollo/src/lnv3/lnv3.service.ts @@ -23,6 +23,9 @@ export class Lnv3Service implements OnModuleInit { latestRelayerInfoNonce: -1, latestFillInfoTimestamp: -1, isSyncingHistory: false, + waitingWithdrawInterval: 0, + waitingWithdrawRecords: [], + fetchProviderInfoInterval: 0, })); protected fetchSendDataInterval = 5000; @@ -43,6 +46,8 @@ export class Lnv3Service implements OnModuleInit { async onModuleInit() { this.transferService.transfers.forEach((item, index) => { + this.fetchCache[index].waitingWithdrawInterval = index * 3; + this.fetchCache[index].fetchProviderInfoInterval = index; this.taskService.addInterval( `${item.chainConfig.code}-lnv3-fetch_history_data`, this.fetchSendDataInterval, @@ -55,6 +60,7 @@ export class Lnv3Service implements OnModuleInit { await this.fetchRecords(item, index); await this.batchFetchStatus(item, index); await this.fetchStatus(item, index); + await this.fetchWithdrawCacheStatus(item, index); this.fetchCache[index].isSyncingHistory = false; } ); @@ -108,7 +114,7 @@ export class Lnv3Service implements OnModuleInit { } } catch (err) { this.logger.warn( - `try to get records failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}` + `try to get records failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}, err ${err}` ); } } @@ -131,7 +137,7 @@ export class Lnv3Service implements OnModuleInit { } } catch (err) { this.logger.warn( - `try to get provider infos failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}` + `try to get provider infos failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}, err ${err}` ); } } @@ -153,12 +159,31 @@ export class Lnv3Service implements OnModuleInit { } } catch (err) { this.logger.warn( - `try to get relay status failed, id ${toChain.chainConfig.id}, type ${level0Indexer.indexerType}` + `try to get relay status failed, id ${toChain.chainConfig.id}, type ${level0Indexer.indexerType}, transferId ${transferId} err ${err}` ); } } } + async queryMultiRecordRelayStatus(toChain: PartnerT2, transferIds: string[]) { + for (const level0Indexer of toChain.level0Indexers) { + const url = level0Indexer.url; + const service = this.sourceServices.get(level0Indexer.indexerType); + try { + return await service.queryMultiRelayStatus( + level0Indexer.url, + toChain.chainConfig.id, + transferIds + ); + } catch (err) { + this.logger.warn( + `try to get multi relay status failed, id ${toChain.chainConfig.id}, type ${level0Indexer.indexerType}, transferIds ${transferIds} err ${err}` + ); + return []; + } + } + } + async queryRecordWithdrawStatus(transfer: PartnerT2, transferId: string) { for (const level0Indexer of transfer.level0Indexers) { const url = level0Indexer.url; @@ -174,7 +199,7 @@ export class Lnv3Service implements OnModuleInit { } } catch (err) { this.logger.warn( - `try to get withdraw status failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}` + `try to get withdraw status failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}, err ${err}` ); } } @@ -281,7 +306,7 @@ export class Lnv3Service implements OnModuleInit { } } catch (err) { this.logger.warn( - `try to batch get fill infos failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}` + `try to batch get fill infos failed, id ${transfer.chainConfig.id}, type ${level0Indexer.indexerType}, err ${err}` ); } } @@ -325,13 +350,15 @@ export class Lnv3Service implements OnModuleInit { }); // the record exist but not finished if (uncheckedRecord?.endTxHash === '') { + const endTxHash = uncheckedRecord.needWithdrawLiquidity + ? '' + : relayRecord.transactionHash; const updateData = { result: RecordStatus.success, responseTxHash: relayRecord.transactionHash, - endTxHash: relayRecord.transactionHash, + endTxHash: endTxHash, endTime: Number(relayRecord.timestamp), relayer: relayRecord.relayer.toLowerCase(), - needWithdrawLiquidity: false, lastRequestWithdraw: Number(relayRecord.requestWithdrawTimestamp), }; @@ -353,6 +380,55 @@ export class Lnv3Service implements OnModuleInit { } } + async fetchWithdrawCacheStatus(transfer: PartnerT2, index: number) { + let cache = this.fetchCache[index]; + cache.waitingWithdrawInterval += 1; + if (cache.waitingWithdrawInterval < 60) { + return; + } + cache.waitingWithdrawInterval = 0; + const records = cache.waitingWithdrawRecords; + const transferIdMap = new Map(); + for (let record of records) { + const recordSplitted = record.id.split('-'); + const transferId: string = last(recordSplitted); + const chainId = recordSplitted[2]; + const transferIds = transferIdMap.get(chainId); + if (!transferIds) { + transferIdMap.set(chainId, [transferId]); + } else { + transferIds.push(transferId); + } + } + for (let [chainId, transferIds] of transferIdMap) { + const toChain = this.getDestChain(chainId); + const relayRecords = await this.queryMultiRecordRelayStatus(toChain, transferIds); + for (const relayRecord of relayRecords) { + const requestWithdrawTimestamp = Number(relayRecord.requestWithdrawTimestamp); + if (requestWithdrawTimestamp > 0) { + const transferRecord = await this.queryRecordWithdrawStatus(transfer, relayRecord.id); + if (transferRecord) { + const id = this.genID( + transfer, + transfer.chainConfig.id.toString(), + transferRecord.remoteChainId, + transferRecord.id + ); + await this.aggregationService.updateHistoryRecord({ + where: { id: id }, + data: { + needWithdrawLiquidity: !transferRecord.hasWithdrawn, + endTxHash: transferRecord.hasWithdrawn ? relayRecord.transactionHash : '', + lastRequestWithdraw: requestWithdrawTimestamp, + }, + }); + } + } + } + } + cache.waitingWithdrawRecords = []; + } + async fetchStatus(transfer: PartnerT2, index: number) { try { const uncheckedRecords = await this.aggregationService @@ -380,6 +456,18 @@ export class Lnv3Service implements OnModuleInit { const dstChainId = recordSplitted[2]; if (record.endTxHash === '') { + // if record.result === RecordStatus.success, it must wait for withdraw liquidity + // then we need to reduce the frequency of requests + // push the request to the cache + if (record.result === RecordStatus.success && record.needWithdrawLiquidity) { + if ( + !this.fetchCache[index].waitingWithdrawRecords.some((item) => item.id === record.id) + ) { + this.fetchCache[index].waitingWithdrawRecords.push(record); + } + continue; + } + const toChain = this.getDestChain(dstChainId); const relayRecord = await this.queryRecordRelayStatus(toChain, transferId); @@ -455,7 +543,7 @@ export class Lnv3Service implements OnModuleInit { where: { id: record.id }, data: { needWithdrawLiquidity: !transferRecord.hasWithdrawn, - endTxHash: transferRecord.responseTxHash, + endTxHash: transferRecord.hasWithdrawn ? record.responseTxHash : '', lastRequestWithdraw: requestWithdrawTimestamp, }, }); @@ -509,6 +597,12 @@ export class Lnv3Service implements OnModuleInit { } async fetchProviderInfo(transfer: PartnerT2, index: number) { + let cache = this.fetchCache[index]; + cache.fetchProviderInfoInterval += 1; + if (cache.fetchProviderInfoInterval <= 5) { + return; + } + cache.fetchProviderInfoInterval = 0; let latestNonce = this.fetchCache[index].latestRelayerInfoNonce; try { if (latestNonce == -1) { diff --git a/apollo/src/lnv3/source/ponder.service.ts b/apollo/src/lnv3/source/ponder.service.ts index cf8ec1f..12ed3bc 100644 --- a/apollo/src/lnv3/source/ponder.service.ts +++ b/apollo/src/lnv3/source/ponder.service.ts @@ -46,6 +46,13 @@ export class Lnv3PonderService extends SourceService { }) .then((res) => res.data?.data?.lnv3RelayRecord); } + async queryMultiRelayStatus( + url: string, + chainId: number, + transferIds: string[] + ): Promise { + return []; + } async batchQueryRelayStatus( url: string, localId: number, diff --git a/apollo/src/lnv3/source/source.service.ts b/apollo/src/lnv3/source/source.service.ts index e16b1e0..3550d9e 100644 --- a/apollo/src/lnv3/source/source.service.ts +++ b/apollo/src/lnv3/source/source.service.ts @@ -65,6 +65,12 @@ export abstract class SourceService { chainId: number, transferId: string ): Promise; + abstract queryMultiRelayStatus( + url: string, + chainId: number, + transferIds: string[] + ): Promise; + abstract batchQueryRelayStatus( url: string, chainId: number, diff --git a/apollo/src/lnv3/source/thegraph.service.ts b/apollo/src/lnv3/source/thegraph.service.ts index ac90003..9a001b7 100644 --- a/apollo/src/lnv3/source/thegraph.service.ts +++ b/apollo/src/lnv3/source/thegraph.service.ts @@ -44,6 +44,20 @@ export class Lnv3ThegraphService extends SourceService { }) .then((res) => res.data?.data?.lnv3RelayRecord); } + async queryMultiRelayStatus( + url: string, + chainId: number, + transferIds: string[] + ): Promise { + const idArray = '["' + transferIds.join('","') + '"]'; + const query = `query { lnv3RelayRecords(first: 20, where: {id_in: ${idArray}}) { id, timestamp, requestWithdrawTimestamp, relayer, transactionHash, slashed, fee } }`; + return await axios + .post(url, { + query: query, + variables: null, + }) + .then((res) => res.data?.data?.lnv3RelayRecords); + } async batchQueryRelayStatus( url: string, chainId: number,